abcl-src-1.9.0/0040755 0000000 0000000 00000000000 14242630071 011740 5ustar000000000 0000000 abcl-src-1.9.0/ci/0040755 0000000 0000000 00000000000 14242630070 012332 5ustar000000000 0000000 abcl-src-1.9.0/contrib/0040755 0000000 0000000 00000000000 14242630070 013377 5ustar000000000 0000000 abcl-src-1.9.0/contrib/abcl-asdf/0040755 0000000 0000000 00000000000 14242630070 015213 5ustar000000000 0000000 abcl-src-1.9.0/contrib/abcl-asdf/t/0040755 0000000 0000000 00000000000 14242630070 015456 5ustar000000000 0000000 abcl-src-1.9.0/contrib/abcl-asdf/t/eg/0040755 0000000 0000000 00000000000 14242630070 016051 5ustar000000000 0000000 abcl-src-1.9.0/contrib/abcl-build/0040755 0000000 0000000 00000000000 14242630070 015375 5ustar000000000 0000000 abcl-src-1.9.0/contrib/abcl-build/build/0040755 0000000 0000000 00000000000 14242630070 016474 5ustar000000000 0000000 abcl-src-1.9.0/contrib/abcl-build/build/t/0040755 0000000 0000000 00000000000 14242630070 016737 5ustar000000000 0000000 abcl-src-1.9.0/contrib/abcl-introspect/0040755 0000000 0000000 00000000000 14242630070 016470 5ustar000000000 0000000 abcl-src-1.9.0/contrib/abcl-introspect/t/0040755 0000000 0000000 00000000000 14242630070 016733 5ustar000000000 0000000 abcl-src-1.9.0/contrib/asdf-jar/0040755 0000000 0000000 00000000000 14242630070 015066 5ustar000000000 0000000 abcl-src-1.9.0/contrib/jfli/0040755 0000000 0000000 00000000000 14242630070 014323 5ustar000000000 0000000 abcl-src-1.9.0/contrib/jfli/examples/0040755 0000000 0000000 00000000000 14242630070 016141 5ustar000000000 0000000 abcl-src-1.9.0/contrib/jfli/examples/swing/0040755 0000000 0000000 00000000000 14242630070 017270 5ustar000000000 0000000 abcl-src-1.9.0/contrib/jfli/examples/swt/0040755 0000000 0000000 00000000000 14242630070 016756 5ustar000000000 0000000 abcl-src-1.9.0/contrib/jfli/test/0040755 0000000 0000000 00000000000 14242630070 015302 5ustar000000000 0000000 abcl-src-1.9.0/contrib/jss/0040755 0000000 0000000 00000000000 14242630070 014176 5ustar000000000 0000000 abcl-src-1.9.0/contrib/jss/t/0040755 0000000 0000000 00000000000 14242630070 014441 5ustar000000000 0000000 abcl-src-1.9.0/contrib/mvn/0040755 0000000 0000000 00000000000 14242630070 014177 5ustar000000000 0000000 abcl-src-1.9.0/contrib/named-readtables/0040755 0000000 0000000 00000000000 14242630070 016567 5ustar000000000 0000000 abcl-src-1.9.0/contrib/named-readtables/doc/0040755 0000000 0000000 00000000000 14242630070 017334 5ustar000000000 0000000 abcl-src-1.9.0/contrib/named-readtables/src/0040755 0000000 0000000 00000000000 14242630070 017356 5ustar000000000 0000000 abcl-src-1.9.0/contrib/named-readtables/test/0040755 0000000 0000000 00000000000 14242630070 017546 5ustar000000000 0000000 abcl-src-1.9.0/contrib/named-readtables/test/doc/0040755 0000000 0000000 00000000000 14242630070 020313 5ustar000000000 0000000 abcl-src-1.9.0/contrib/named-readtables/test/src/0040755 0000000 0000000 00000000000 14242630070 020335 5ustar000000000 0000000 abcl-src-1.9.0/contrib/quicklisp/0040755 0000000 0000000 00000000000 14242630070 015403 5ustar000000000 0000000 abcl-src-1.9.0/doc/0040755 0000000 0000000 00000000000 14242630070 012504 5ustar000000000 0000000 abcl-src-1.9.0/doc/asdf/0040755 0000000 0000000 00000000000 14242630070 013421 5ustar000000000 0000000 abcl-src-1.9.0/doc/design/0040755 0000000 0000000 00000000000 14242630070 013755 5ustar000000000 0000000 abcl-src-1.9.0/doc/design/amop/0040755 0000000 0000000 00000000000 14242630070 014711 5ustar000000000 0000000 abcl-src-1.9.0/doc/design/pathnames/0040755 0000000 0000000 00000000000 14242630070 015735 5ustar000000000 0000000 abcl-src-1.9.0/doc/design/streams/0040755 0000000 0000000 00000000000 14242630070 015433 5ustar000000000 0000000 abcl-src-1.9.0/doc/manual/0040755 0000000 0000000 00000000000 14242630070 013761 5ustar000000000 0000000 abcl-src-1.9.0/etc/0040755 0000000 0000000 00000000000 14242630070 012512 5ustar000000000 0000000 abcl-src-1.9.0/etc/ant/0040755 0000000 0000000 00000000000 14242630070 013274 5ustar000000000 0000000 abcl-src-1.9.0/examples/0040755 0000000 0000000 00000000000 14242630070 013555 5ustar000000000 0000000 abcl-src-1.9.0/examples/google-app-engine/0040755 0000000 0000000 00000000000 14242630070 017052 5ustar000000000 0000000 abcl-src-1.9.0/examples/google-app-engine/src/0040755 0000000 0000000 00000000000 14242630070 017641 5ustar000000000 0000000 abcl-src-1.9.0/examples/google-app-engine/src/abcl_ae/0040755 0000000 0000000 00000000000 14242630070 021207 5ustar000000000 0000000 abcl-src-1.9.0/examples/google-app-engine/war/0040755 0000000 0000000 00000000000 14242630070 017643 5ustar000000000 0000000 abcl-src-1.9.0/examples/google-app-engine/war/WEB-INF/0040755 0000000 0000000 00000000000 14242630070 020672 5ustar000000000 0000000 abcl-src-1.9.0/examples/gui/0040755 0000000 0000000 00000000000 14242630070 014341 5ustar000000000 0000000 abcl-src-1.9.0/examples/gui/abcl/0040755 0000000 0000000 00000000000 14242630070 015242 5ustar000000000 0000000 abcl-src-1.9.0/examples/gui/awt/0040755 0000000 0000000 00000000000 14242630070 015134 5ustar000000000 0000000 abcl-src-1.9.0/examples/gui/swing/0040755 0000000 0000000 00000000000 14242630070 015470 5ustar000000000 0000000 abcl-src-1.9.0/examples/java-exception/0040755 0000000 0000000 00000000000 14242630070 016472 5ustar000000000 0000000 abcl-src-1.9.0/examples/java-interface/0040755 0000000 0000000 00000000000 14242630070 016434 5ustar000000000 0000000 abcl-src-1.9.0/examples/java-to-lisp-1/0040755 0000000 0000000 00000000000 14242630070 016221 5ustar000000000 0000000 abcl-src-1.9.0/examples/java-to-lisp-2/0040755 0000000 0000000 00000000000 14242630070 016222 5ustar000000000 0000000 abcl-src-1.9.0/examples/jsr-223/0040755 0000000 0000000 00000000000 14242630070 014657 5ustar000000000 0000000 abcl-src-1.9.0/examples/lisp-to-java/0040755 0000000 0000000 00000000000 14242630070 016063 5ustar000000000 0000000 abcl-src-1.9.0/examples/misc/0040755 0000000 0000000 00000000000 14242630070 014510 5ustar000000000 0000000 abcl-src-1.9.0/examples/pure-lisp-to-java/0040755 0000000 0000000 00000000000 14242630071 017035 5ustar000000000 0000000 abcl-src-1.9.0/nbproject/0040755 0000000 0000000 00000000000 14242630070 013725 5ustar000000000 0000000 abcl-src-1.9.0/nbproject/configs/0040755 0000000 0000000 00000000000 14242630071 015356 5ustar000000000 0000000 abcl-src-1.9.0/nbproject/netbeans-older/0040755 0000000 0000000 00000000000 14242630070 016627 5ustar000000000 0000000 abcl-src-1.9.0/nbproject/private/0040755 0000000 0000000 00000000000 14242630070 015377 5ustar000000000 0000000 abcl-src-1.9.0/nbproject/private/configs/0040755 0000000 0000000 00000000000 14242630070 017027 5ustar000000000 0000000 abcl-src-1.9.0/src/0040755 0000000 0000000 00000000000 14242630070 012526 5ustar000000000 0000000 abcl-src-1.9.0/src/META-INF/0040755 0000000 0000000 00000000000 14242630070 013666 5ustar000000000 0000000 abcl-src-1.9.0/src/META-INF/services/0040755 0000000 0000000 00000000000 14242630071 015512 5ustar000000000 0000000 abcl-src-1.9.0/src/org/0040755 0000000 0000000 00000000000 14242630070 013315 5ustar000000000 0000000 abcl-src-1.9.0/src/org/armedbear/0040755 0000000 0000000 00000000000 14242630070 015237 5ustar000000000 0000000 abcl-src-1.9.0/src/org/armedbear/lisp/0040755 0000000 0000000 00000000000 14242630071 016207 5ustar000000000 0000000 abcl-src-1.9.0/src/org/armedbear/lisp/java/0040755 0000000 0000000 00000000000 14242630070 017127 5ustar000000000 0000000 abcl-src-1.9.0/src/org/armedbear/lisp/java/swing/0040755 0000000 0000000 00000000000 14242630070 020256 5ustar000000000 0000000 abcl-src-1.9.0/src/org/armedbear/lisp/protocol/0040755 0000000 0000000 00000000000 14242630071 020050 5ustar000000000 0000000 abcl-src-1.9.0/src/org/armedbear/lisp/scripting/0040755 0000000 0000000 00000000000 14242630070 020210 5ustar000000000 0000000 abcl-src-1.9.0/src/org/armedbear/lisp/scripting/lisp/0040755 0000000 0000000 00000000000 14242630071 021160 5ustar000000000 0000000 abcl-src-1.9.0/src/org/armedbear/lisp/util/0040755 0000000 0000000 00000000000 14242630071 017164 5ustar000000000 0000000 abcl-src-1.9.0/test/0040755 0000000 0000000 00000000000 14242630070 012716 5ustar000000000 0000000 abcl-src-1.9.0/test/lisp/0040755 0000000 0000000 00000000000 14242630070 013665 5ustar000000000 0000000 abcl-src-1.9.0/test/lisp/abcl/0040755 0000000 0000000 00000000000 14242630071 014567 5ustar000000000 0000000 abcl-src-1.9.0/test/lisp/ansi/0040755 0000000 0000000 00000000000 14242630070 014617 5ustar000000000 0000000 abcl-src-1.9.0/test/lisp/cl-bench/0040755 0000000 0000000 00000000000 14242630070 015340 5ustar000000000 0000000 abcl-src-1.9.0/test/src/0040755 0000000 0000000 00000000000 14242630070 013505 5ustar000000000 0000000 abcl-src-1.9.0/test/src/org/0040755 0000000 0000000 00000000000 14242630070 014274 5ustar000000000 0000000 abcl-src-1.9.0/test/src/org/abcl/0040755 0000000 0000000 00000000000 14242630070 015175 5ustar000000000 0000000 abcl-src-1.9.0/test/src/org/abcl/util/0040755 0000000 0000000 00000000000 14242630070 016152 5ustar000000000 0000000 abcl-src-1.9.0/test/src/org/armedbear/0040755 0000000 0000000 00000000000 14242630070 016216 5ustar000000000 0000000 abcl-src-1.9.0/test/src/org/armedbear/lisp/0040755 0000000 0000000 00000000000 14242630071 017166 5ustar000000000 0000000 abcl-src-1.9.0/test/src/org/armedbear/lisp/serialization/0040755 0000000 0000000 00000000000 14242630070 022042 5ustar000000000 0000000 abcl-src-1.9.0/test/src/org/armedbear/lisp/util/0040755 0000000 0000000 00000000000 14242630070 020142 5ustar000000000 0000000 abcl-src-1.9.0/CHANGES0100644 0000000 0000000 00000226336 14242627550 012754 0ustar000000000 0000000 Version 1.9.0 ============= May 2022 * [r15588] ABCL-BUILD can now be use Maven to execute a non-canonical build. * [r15587] (alan) Fix CL:DIRECTORY's handling #p"." or #p".." fragments in certain cases. * [r15586] (alan) ABCL-ASDF introspection of Maven now falls back to using the value supplied in the manifest. * [r15585] (alan) Tweak CLOS finalization protocol to favor continuing execution as opposed to in erroring in finalization situations to be more like SBCL. * [r15584] (alan) Overhaul the implementation's thread interrupt infrastructure to handle at finer granularity making things more responsive. * [r15582] Replace SYS:DIAG compiler diagnostic macro with a function to fix the internal compiler diagnostic macro to actually work. * [r15580] (alejandrozf) Compiler falls back to interpreted forms greater than 65535 bytes. * [r15578][r15579] Fix CL:DISSASSEMBLE in some places by falling back to funcall. Document the implementation specific machinery around its use a bit better. * [r15572] (Jonathan Cunningham) Update reference to a freely available version of Rhode's Extensible Sequence paper. * [r15571] (Alan Ruttenberg) JSS update to javaparser-3.24.2 Fix tests, fix typo, lazily initialize via LOAD-JAVAPARSER on the first use of the number argument version of the macro. * [r15570] (Uthar) Prevent JCLASS-SUPERCLASS from failing on names (keywords) of classes generated by JNEW-RUNTIME-CLASS * [r15562] (Alan Ruttenberg) Add a restart for undefined functions * [r15561] Clarify call and lambda arguments limits somewhat * [r15560] (Alan Ruttenberg) Support for catch tags in SLIME * [r15559] (Alan Ruttenberg) Record source location for slot readers * [r15558] ABCL-INTROSPECT explictly home exported symbols in ABCL-INTROSPECT/SYSTEM to identify machinery added to the SYSTEM package after initial ANSI boot. * [r15549] (alejandrozf) Fix (coerce 'documentation 'function) * [r15548] (alejandrozf) Fill slots operation and operands with DivisionByZero condition when it is raised * [r15545] (alejandrozf) Update fill pointer when arrays are shrunk if necessary. * [r15544] [r15543] (phoe) Use PUSHNEW for CL:*FEATURES*; place :EXTENSIBLE-SEQUENCES in CL:*FEATURES* where appropiate * [r15542] (alejandrozf) Accessible symbols are always printed with package prefix * [r15541] (alejandrozf) Improve DRIBBLE to save almost everything, lexically closing over new REPLs, now cleanly closing/restarting * [r15494] When reading ZIP archives from streams, use modified date of byte source. * [r15493] The implmentation now uses :NEWEST for the version of references to EXT:JAR-PATHNAME objects which have been cached. * [r15492] Address inconsistency between populating entries in EXT:JAR-PATHNAME. A DIRECTORY should always be :ABSOLUTE in a EXT:JAR-PATHNAME unless there is no name or type component. * [r15491] Fix ZipCache to use the file system modification date * [r15490] EXT:AS-JAR-PATHNAME-ARCHIVE returns reference to a CL:PATHNAME as a EXT:JAR-PATHNAME * [r15489] DISABLE-ZIP-CACHE isn't currently working * [r15486] (Eric Timmons) Fix SYS:PROCESS-PID with SYS:RUN-PROGRAM * [r15483] Explictly scope all symbols in fasl loader * [r15481] Fix (or (unsigned-byte 8) (unsigned-byte 32)) vector reset * [r15480][r15484] (Robert Munyer) New algorithim for COMPILE-FILE-PATHNAME * [r15479] ABCL-BUILD now tests with ant-1.10.9 * [r15478] ZS3 fix allocation for non-simple (unsigned-byte 8) vectors * [r15538] (contrapunctus) needled to correct outdated HTML links * [r15537] [r15536] [r15535] [r15534] [r15533] [r15532] ABCL-BUILD Correct deprecated JAVA-COMPILE-FILE, add file unit for top-level targets, implement COPY-DIRECTORIES-RECURSIVELY utility, docstring for exported ENSURE-MAVEN, clean compile errors, updateant URIs to available versions * [r15527] JNA update to jna-5.9.0 * [r15525] JSS fix introspecting abcl.jar under openjdk1[67] * [r15524] [r15520] Test released LTS Java editions for openjdk{8,11,17} with Adoptium. * [r15523] (Scott Burson) Corrections to ENCODE-UNIVERSAL-TIME for dates after 2037. * [r15521] Use java.lang.Integer.valueOf() rather than constructor * [r15519] (Samuel Hunter) Fix and standardize all error reader functions. * [r15518] (Uthar) Remove confusing comment in example * [r15515] ASDF Fix JAR-PATHNAME loading systems under Windows * [r15513] (alejandrozf) Fix generic lambda lists congruency with keywords * [r15511] (Phil Eaton) Support variadic arguments with more required parameters * [r15504] Allow JAVA:JCLASS to work with non-primtive arrays suffixed with "[]" * [r15503] ABCL-AIO Fix finding ABCL-CONTRIB * [r15502] build: deprecate use of abcl.implementation.version * [r15501] (daewok) Uppercase arch before pushing it to *FEATURES* * [r15500] (Ferada) Fix printing of RANDOM-STATE * [r15496] Support use of Project Loom virtual threads. When the underlying JVM supports virtual threads, :VIRTUAL-THREADS will be present in CL:*FEATURES* * [r15495] This release targets openjdk8, openjdk11, and openjdk17 Version 1.8.0 ============= October 29, 2020 Features -------- * [r15390-r15406][r15408-r15413][r15422-r15425][r15434-r15458][r15460-15463] Overhauled JAR-PATHNAME and URL-PATHNAME subtypes of PATHNAME to fully support recursive addressing of zip within both local and remote zip archives. Incompatibilities ----------------- * [r15414] Change algorithm for determining pathname type from parsing namestrings to be more like SBCL and CCL | Expression | NAME | TYPE | |------------+--------+------| | #p"..." | ".." | "" | | #p".foo" | ".foo" | NIL | Enhancements ------------ * [r15378][r15421] Support openjdk15 * [r15360-r15365] (Alessio) Serialization of top-level, named functions. * [r15353] JAVA:JCLASS now works on all arrays of primitive type. * [r15356] ABCL-INTROSPECT adds EXT:READ-CLASS to conveniently read java class bytes from the source referenced by a PATHNAME. * [r15366] The compiler now properly emits make-array for top-level specialized vector forms. * [r15367] Loading ABCL-INTROSPECT now adds the function EXT:STREAM-UNIX-FD which returns the integer of the underlying file descriptor from a socket stream reference. * [r15368] Less cryptic warnings for ignored socket write timeout. * [r15381] JNEW-ARRAY-FROM-ARRAY now capable of constructing all possible arrays of primitive type. Fixes ----- * [r15359] Fix running openjdk11 compilation on openjdk8. * [r15358] Fix SYS:RUN-PROGRAM issues with openjdk11. * [r15357] Re-work strategy for the denotation of the hosting runtime platform in CL:*FEATURES* to include a "JAVA-" where "" is an integer denoting the major version of the platform according to JEP-223. * [r15351][r15352] For CL:MAKE-ARRAY, ensure :NIO-BUFFER argument works in all cases, fix :NIO-DIRECT for (unsigned-byte 16) specialized arrays. * [r15369][r15376] Fix wildcard matching to work on pathnames consisting of only #\* characters. * [r15377] (Daniel Kochmański) Fix loop destructuring problems. * [r15379] Fix VECTOR-PUSH-EXTEND for (UNSIGNED-BYTE 8). * [r15427] Define CALL-NEXT-METHOD and NEXT-METHOD-P as local functions. * [r15386] Make the pre-compiler be more careful in optimizing lambdas. * [r15388] Ensure that SYS:CHECK-REDEFINITION does not signal error conditions. * [r15387] Fix FILE-POSITION by resetting file charset decoder before conversion. * [r15383] Fix capacity allocation for arrays specialized on (or (unsigned-byte 16) (unsigned-byte 32)) created via an CL:MAKE-ARRAY :NIO-BUFFER argument. Contrib ------- * [r15420] Use jna-5.6.0. * [r15384] quicklisp-abcl attempts to remove all Quicklisp fasls on failure to load. * ASDF-JAR loading compiled fasls stored in JAR archives now works again. Build ----- * [r15426] Ensure that we construct the manual with a proper version. * [r15407] Building and running a local ABCL hopefully does more of what you mean. Tests ----- * [r15416] The default reporting via abcl/test/lisp/parse-ansi-tests is for compiled tests. * [r15385] Travis CI now uses versions of STATIC-VECTORS, CL+SSL, and CFFI from Quicklisp. Overhaul ABCL-PROVE system definition explicitly enumerating tests for more deterministic behavior. * [r15382] Test usage of :NIO-BUFFER keyword in CL:MAKE-ARRAY. * [r15380] Tests for creating primitive java arrays. Version 1.7.1 ============= July 18, 2020 Fixes ----- * [r15337] Fix ELT on vectors specialized on (unsigned-byte 32) * [r15327] Restore svref optimizations for SIMPLE-VECTOR sorts * [r15326] Fix sorting vectors of length 0 Version 1.7.0 ============= June 3, 2020 The implementation now runs on the openjdk6, openjdk7, openjdk8, openjdk11, openjdk13, and openjdk14 JVM runtimes. Enhancements ------------ * [r15305][r15306][r15307] The :NIO symbol is now present in CL:*FEATURES*, denoting the use of java.nio.ByteBuffer et. al. in the implementation of arrays specialized on commonly used unsigned byte-types. CL:MAKE-ARRAY now has the :NIO-BUFFER and :NIO-DIRECT keyword arguments useful in the construction of such arrays. * [r15280][r15283] The default implementation for CL:DISASSEMBLE has been switched from jad to javap. The SYS:CHOOSE-ASSEMBLER interface is now able to switch between the jad, javap, fernflower, Procyon, and CFR backends provided as loaded ASDF definitions contained in the ABCL-INTROSPECT contrib. * [r15268] ABCL-BUILD:DIRECTORY-HASHES outputs the SHA256 hashes of files in a directory. * [r15282] The ABCL-INTROSPECT contrib now adds the EXT:WRITE-CLASS method to write the bytecode representation of a Java class to disk. * [r15293] The Dockerfile has been updated to use openjdk11 Fixes ----- * [r15292] Fixed all known outstanding problems with DECODE-FLOAT for values less than normalized floats. * [r15287] Attempts to fill specialized 32-bit arrays with elements greater than 2^32-1 now properly signals a type error. * [r15267] ABCL-BUILD:ANT/CALL no longer signals an error on failure instead reporting associated error messages. * [r15281] Autoconfiguration for builds on supported platforms extended. * [r15290] The invocation of CL-BENCH now utilizes its ASDF definition. * [r15294][r15298] The contents of the directory are now included in the source release, and have had all mention of TRAVIS_BUILD_DIR removed decoupling their use from the presence of Travis. Tests ----- * [r15277] (pdietz) Additional tests for compiler failures. * [r15278][r15279] (phoe) Added tests for unbound slots DIVISION-BY-ZERO has ARITHMETIC-ERROR-OPERANDS. * [r15284][r15285][r15288] The CI now tests the ability to use OpenSSL via CL+SSL. * [r15289] The CI now tests the version CFFI with CFFI-SYS:MAKE-SHAREABLE-BYTE-VECTOR implemented. * [r15291] The CI now tests IRONCLAD. Version 1.6.1 ============= April 24, 2020 Enhancements ------------ * [r15223] Fix compiler for java.lang.VerifyError with PROGN (somewhat-functional-programmer) * [r15250] ABCL now builds and runs across openjdk{6,7,8,11,13,14} * [r15256] Build autoconfiguration via ci/create-build-properties.bash * [r15252] Provide accessor in URL-STREAM for underlying java.io.InputStream * [r15226] [INCOMPLETE] Address problems with DECODE-FLOAT (Robert Dodier) Fixes ----- * [r15229] Maven central repository now requires TLS * [r15242] jstatic: check narrowing for explicit method reference * [r15232] [r15233] [r15241] Reworking DWIM on java call sites The FFI will now find Java call sites whose types are Short or Byte with integers if they can be narrowed without losing information. This work should be considered provisional, subject to possible revision. * [r15234] Fix calling Java methods with varargs parameters * [r15233] Fix calling Java methods with short and byte parameters * [r15231] abcl-build: test the install of maven-3.6.3 * [r15238] build: ensure javac compiles with UTF-8 encoding * [r15243] abcl-asdf: rework Maven usage strategy * [r15245] abcl-asdf: use WITH-AETHER macro to ensure Maven Aether is loaded * [r15251] abcl-asdf: assume that either 'which' or 'where' works Updates ------- * [r15240] Use ASDF-3.3.4 Tests ----- * [r15239] ci: now use latest CFFI distributed with Quicklisp * [r15247] t/format-dollar: correction for CL:FORMAT dollar usage * [r15248] t/jcoerce-numerics: JCOERCE across numerics without losing information * [r15249] t/decode-float: tests for currently broken handling of CL:DECODE-FLOAT Version 1.6.0 ============= November 22, 2019 Compatiblity ------------ ABCL 1.6.0 supports building and running on openjdk6, openjdk7, openjdk8, and openjdk11. Enhancements ----------- * [r15085] Add a restart for generics defined over functions or macros when arguments don't match (Alan). * [r15086] jss: Disambiguate java class lookup in dynamic scope (Alan). * [r15087] jss: Optimizations for jss field accessors (Alan). * [r15089] [r15090] jss: JSS:TO-HASHSET converts java.util.List references to java.util.Hashset (Alan). * [r15091] jss: Improve JSS:J2LIST, add JSS:JMAP (Olof). * [r15092] Make JVM class names more intelligible (Olof). * [r15093] abcl-asdf: Support multiple Maven repositories (Olof). * [r15101] [r15102] [r15103] abcl-asdf: add test cases for multiple repositories (Olof). * [r15095] Define undefined conditions and handler functions following error-fun='error pattern (Alan). * [r15105] jss: make use of warning muffling (Olof). * [r15133] [r15134] Support building and running in openjdk11. * [r15142] Signal better error for out-of-bounds CL:REPLACE (Olof). * [r15148] docker: use the now standardized openjdk8 container, install ant and maven dependencies. Fixes ----- * [r15096] Fix and check array types for JSS:JMAP/J2LIST (Olof). * [r15097] abcl-asdf: compatiblity with maven-3.5.0. * [r15099] Export the JVM:*RESIGNAL-COMPILER-WARNINGS* interface. * [r15100] Fix ASDF usage of MVN module (Olof). * [r15107] Fix translate-directory-components-aux: throw takes 2 arguments (metawilm). * [r15114] Intern SYSTEM:AVAILABLE-ENCODINGS symbols (Robert Dodier). * [r15115] abcl-asdf: fix ABCL-ASDF:MVN-MODULE collect request (Alan). * [r15116] Fix CL:PRINT-OBJECT of null pointer (Alan). * [r15117] The compiled version of JSS:INVOKE-RESTARGS was evaluating the first argument twice (Alan). * [r15118] abcl-asdf: stop complaining about not loading a file named the module name (Alan). * [r15120] Don't evaluate format control string in ReaderError (Javier Olaechea). * [r15124] Fix monetary floating-point formatted output (Scott Burson). * [r15125] Stackframe head edge case fix (Alan). * [r15137] Fix ANSI-TESTS GENSYM.ERROR.10 and GENSYM.ERROR.11 (Douglas Miles). * [r15138] Fix ANSI-TEST MAKE-CONCATENATED-STREAM.30 failure (Douglas Miles). * [r15139] Fix ANSI-TESTS FILE-POSITION.10 (Douglas Miles). * [r15141] compiler: fix stack inconsistency errors (somewhat-functional-programmer). * [r15143] Check for element type before filling vectors (Olof). * [r15144] Fix high start index for CL:SUBSEQ (Olof). * [r15146] JSS read sharp expression bugfixes (Alan). * [r15149] jss: explicitly scope JSS:TO-HASHSET. Updates ------- * ASDF 3.3.3 * JNA 5.5.0 Version 1.5.0 ============= June 11, 2017 Enhancements ------------ * [r14934] ABCL-INTROSPECT a contrib for accessing ABCL compiler information (Alan). * [r14907] ABCL-AIO all-in-one jar target creates dist/abcl-aio.jar (Alan). * [r15009] Rework ABCL-BUILD as a contrib which uses UIOP machinery to invoke Ant on , unifying all build mechanisms to a single prescriptive source artifact external to Common-Lisp. * [r14911] [r14955] [r14914] Source recording on SYS:SOURCE plist PRECOMPILER possibly beta reduce form with function position lambda, record arglist during Build * [r14912] [r14922] Re-write the ASDF descriptions using secondary systems * [r14917] build: 'abcl.clean.application.fasls' now cleans only ABCL fasls * [r14923] Added Dockerfile to package ABCL in Docker * [r14927] Build add ability to download Maven from Ant * [r14931] Bless EXT:GET-PID as the offical way to get process id * [r14947] JSS syntax for access Java fields (Alan) * [r14962] JSS:J2LIST as a convenience method for turning "anything" in Java to an appropriate Lisp list. * [r14967] (Provisional) ABCL-ASDF JDK-JAR ASDF class to describe JDK path locations (Alan). * [r14969] Add QUICKLISP-ABCL:*QUICKLISP-PARENT-DIR* special (Alan). * [r14978] Implement MAKE-LOAD-FORM for Java fields (Alan). * [r15013] Restore the ability SYSTEM:CHOOSE-ASSEMBLER to use Objectweb * [r15018] Enable use of MVN-MODULE in ASDF definitions (Alan). * [r15019] Add NAMED-READTABLES from <​https://github.com/melisgl/named-readtables> * [r15062] ABCL-INTROSPECT 'javaparser.asd' definition adds a SHARPSIGN-ONE-QUOTATION_MARK macro to evaluate arbitrary Java expressions Fixes ----- * [r14902] Fix CL:OPEN for :DIRECTION :INPUT (pipping) * [r14903] JNEW-RUNTIME-CLASS Make static functions and :int parameters work. Fix return conversion for null. Ensure that the same classloader is used (olof). * [r14905] ABCL-ASDF uses the value of the reported Maven home to look for libraries, fixing loading CFFI under FreeBSD 11-RELEASE. * [r14906] JSS:LOOKUP-CLASSNAME would return allcaps class name if not found (alan). * [r14909] QUICKLISP-ABCL simplify load/compile logic. * [r14918] JAVA Remove generic Throwable handler from JAVA:JFIELD innards * [r14919] ABCL-ASDF fix finding Maven on Fedora * [r14926] ABCL-ASDF fix problems with test suite's reliance on PROVE * [r14921] CL:DIRECTORY no longer errors on files containing asterisk characters * [r14950] Fix restart calculation for compiled closures (Alan) * [r14952] Guard printing of large Java objects (Alan) * [r14953] Fix debugging frames which don't have a pathname (Alan) * [r14956] Show function documentation in describe (Alan) * [r14966] JAVA:CHAIN returns last value of computation (Alan) * [r14973] ABCL-ASDF probes for "mvn" and "mvn.cmd" under Windows * [r14974] Standardize the use of CL:*LOAD-VERBOSE* to control loading verbosity. * [r14976] Fix CL:GET-OUTPUT-STREAM-STRING to reset underlying buffer * [r14979] Fix JavaObject.getParts() for Java arrays (Alan). * [r14980] Fix SETF for EXT:URL-PATHNAME-FRAGMENT * [r14987] Fix CL:MAKE-PATHNAME for explicitly nil HOST * [r14996] Correctly implement 'time-of-the-time' daylight savings semantics (Scott). * [r15001] Fix signalling simple error with #\~ in CL:FORMAT string (Alan). * [r15002] Fix problems with SHARED-INITIALIZE (Olof). * [r15003] Fix ENSURE-GENERIC-FUNCTION when removing definition (Olof). * [r15004] Fix DESTRUCTURING-BIND with &rest arguments (Olof) * [r15024] Optimise LOGCOUNT (Olof). * [r15026] Support bignum argument for FILE-POSITION (Olof). * [r15032] Better directory validation; handle :UNSPECIFIC (Olof). * [r15033] Fix LOOP code size estimation (Olof). * [r15034] Fix NTH inlining type mismatch (Olof). * [r15035] Fix byte code verification error in edge case (Olof). * [r15036] Fix PACKAGE-ERROR-PACKAGE behaviour (Olof). * [r15037] Fix MAX type derivation (Olof). * [r15038] Fix NPE if directory can't be accessed (Olof). * [r15044] Documentation renders less/greater-than characters correctly (Olof). Updates ------- * ASDF 3.2.1 Version 1.4.0 ============= 08-OCT-2016 Enhancements ============ * Consolidated RUN-PROGRAM fixes (ferada, pipping) In support of getting a more universal UIOP:RUN-PROGAM across all contemporary Lisp implementations. * Upstream consolidated patchset (ferada) ** [r14857] Support `FILE-POSITION` on string streams. ** [r14859] Add multiple disassembler selector. ** [r14860] Add EXTERNAL-ONLY option to APROPOS. ** [r14861] Fix nested classes from JARs not visible with JSS. * [r14840-2] (Scott L. Burson) Introduced "time of time" semantics for {encode,decode}-universal time. * EXTENSIONS:MAKE-TEMP-FILE now takes keyword arguments to specify values of the prefix and suffix strings to the underlying JVM implementation of java.io.File.createTempFile(). * [r14849] EXT:OS-{UNIX,WINDOWS}-P now provide a pre-ASDF runtime check on hosting platform Fixes ----- * [r14863] RandomCharacterFile (vibhu) * [r14839] (JSS) Ensure the interpolation of Java symbol names as strings (alan ruttenberg) * [r14889] Fix ANSI-TEST SXHASH.8 (dmiles) Updates ------ * [r14883] asdf-3.1.7.27 * [r14849] jna-4.2.2 Removed ------- * [r14885] ASDF-INSTALL was removed Version 1.3.3 ============= 18-SEP-2015 Enhancements ------------ * [r14802,r14813] Add character name for non-breaking space Use a human readable name for character 160, #\No-break_space, following sbcl, ccl and clisp. This permits the Quicklisp system spinneret to load. The #\No-break_space name is a valid CHAR-NAME/NAME-CHAR pair, but is not emitted as a glyph under the current output encoding under the CL:FORMAT "~:c" directive as these implementations do by default. Thanks to Javier Olaechea. Fixes ----- * [r14808] CL:FILE-WRITE-DATE fixed for logical pathnames * ANSI-TEST ** Update references to new git repository at ** ABCL now runs the git master consolidated ANSI-TEST suite which features subdirectories and distinquished value for *DEFAULT-PATHNAME-DEFAULTS*. ** ABCL.TEST.ANSI:CLEAN-TESTS now acts recursively via appropiate Pathname wildcards to match new directory structure. * ASDF Fix COMPILE-SYSTEM to offer full ANSI environment for ASDF and ABCL-CONTRIB. * ABCL-ASDF ** Use of Maven has been robustified. *** [r14803] Fix usage with all known versions through maven-3.3.3 Addresses . *** [r14806] Fix usage with specifying local Maven repository ** More complete attempt at re-initialization via (ABCL-ASDF:INIT :force t) Version 1.3.2 ============= 19-APR-2015 Enhancements ------------ * Make result of DEFINE-MODIFY-MACRO available at compilation time [r14727] Fixes ----- * Fix failed AVER [#289] [r14763] * Fix incorrect dead code elimination Additionally, don't recurse into flet/labels upon elimination of a single labels function; simply continue by changing the applicable set. Reported by Vibhu Mohindra. [r14754][r14756] * Numeric tower repairs on promoting floats across representation boundaries [r14749-50] (Massimiliano Ghilardi). * Return SIMPLE-ERROR for invalid external-format arguments.[r14735] * Lisp stack frame representation now formatted as unreadable. [r14738-9] Contrib ------- * JSS ** Fix GET-JAVA-FIELD and SET-JAVA-FIELD [r14718] ** no longer error on NO-SUCH-JAVA-FIELD, by setting fields as accessible where necessary [r14715] [r14725] * ABCL-ASDF ** Update to current Maven support (keep up with changing APIs through the Maven 3.2.3-3.2.5 hysteresis) [r14742-7] (Cyrus Hamon). ** Special-case JNA artifacts with alternate network location [r14733] ** Further work on ABCL-ASDF:RESOLVE [r14732] (Cyrus Hamon) ** Find Maven under FreeBSD ports [r14723], under OS X Homebrew [r14776] * ABCL-JAR ** Fix ASDF-JAR:PACKAGE [#376] [r14717][r14720][r14736] (Eduardo Bellani) * ASDF ** Updated to version 3.1.4. Version 1.3.1 ============= 30-APR-2014 ## Fixed * The underlying Java Function Interface (JFI) now converts CL:T and CL:NIL to JAVA:+TRUE+ and JAVA:+FALSE+. Users who wish to reference a JAVA:+NULL+ should do so explicitly. * Make JCALL work in more places. Thanks to Olof-Joachim Frahm. * Interpolate CL:SLEEP and THREADS:OBJECT-WAIT for timeouts below the Planck timer ("1ns") to a nanosecond. * Update to ASDF 3.1.0.103. Fixes loading of Ironclad and other Quicklisp systems. * Fix Uniform Naming Convention (aka "UNC" or "network") paths under Windows. DIRECTORY now works again on UNC paths. UNC paths may be either specified with either back slash (#\\) or forward slash (#\/) doubled as the first character in a Pathname namestring. The patterns in ////[directories-and-files] are parsed as is stored as HOST. is stored as DEVICE. [directories-and-files] gets parsed as per the normal rules under Windows. Mixing namestrings with both backslash and slash characters can lead to unpredictable results. It is recommended not to use backslash characters in namestrings if it can be avoided. The pathname printed representation is always normalized to using forward slash delimiters. * Find contrib based on system jar name. From Olof-Joachim Frahm. Version 1.3.0 ============= 15-MAR-2014 ## Features * Make LispStackFrame.UNAVAILABLE_ARG a singleton object, and lazily create the little used portions of the Lisp stack. Aggressively cache and control the use of memory by the underlying Lisp stack frame representation by introducing the private LispThread.StackFrame and LispThread.StackSegments classes. Contributed by Dmitry Nadezhin. LispStackFrame object are allocated on every LispThread.execute(...) . However, they are seldom [accessed] ([... verify via] inspect[tion of the] stack trace). This patch delays allocation of LispStackFrame? objects until they are requested. Raw information about stack frames is stored in stack. Stack is an Object[] array (more precisely a list of [...]4 [Mib] Object[] arrays). ME: We are going to need a way to try to less agressively grab 4Mib chunks in low memory situations. Memory profiling of ABCL shows that the classes with largest allocation count are org.armedbear.lisp.LispStackFrame and org.armedbear.lisp.LispStackFrame.UnavailableArgument. Contributed by Dmitry Nadezhin. [r14572]: http://abcl.org/trac/changeset/14572 [r14579]: http://abcl.org/trac/changeset/14579 * ASDF 3.0.1.94 shipped with the implementation * per function call stack and memory exception handler in CL:COMPILE Inline calls to jrun-exception-protected (used by handler-bind to catch out of memory conditions). This commit saves generation roughly 50 cls files. [r14552]: http://abcl.org/trac/changeset/14552 * SYS:SHA256 audited The functionality if the SYS:SHA256 algorithim has been audited for use on inputs of single for files with recently shipping ORCL Java 7 implementations (through jdk-1.7.0_51). [r14582]: http://abcl.org/trac/changeset/14582 * Connect to NetBeans controlled JDWP via SLIME The Netbeans IDE configuration now includes a way to connect to the running-under-jdb ABCL via SLIME. One needs a version of SLIME able to be loaded from its 'swank.asd' definition. * Install 'abcl.jar' and 'abcl-contrib.jar' locally as Maven artifacts The Ant `abcl.mvn.install` target now installs build artifacts into the local Maven repository (Olof-Joachim Frahm) [r14579]: http://abcl.org/trac/changeset/14606 ## Compatibility * CL:DIRECTORY The implementation specific :RESOLVE-SYMLINKS argument to the ANSI DIRECTORY function has been changed to nil. This implements behavior closer to SBCL and guarantees that a DIRECTORY operation will not signal a file error. [r14619]: http://abcl.org/trac/changeset/14619 [ticket-340]: http://abcl.org/trac/ticket/340 ## Fixes * Fix CL:SLEEP for intervals less than a millisecond. For intervals less than or equal to a nanosecond, including an interval of zero, the current thread merely yields execution to other threads. [r14632]: http://abcl.org/trac/changeset/14632 ## Tested ### "Java_HotSpot(TM)_64-Bit_Server_VM-Oracle_Corporation-1.7.0_51-b13" "x86_64-Mac_OS_X-10.9.1" ### "Java_HotSpot(TM)_64-Bit_Server_VM-Oracle_Corporation-1.8.0-b129" "x86_64-Mac_OS_X-10.9.2" ## Contrib #### abcl-asdf * Now working with both Maven 3.0.x and 3.1.x. Thanks to Anton for the help! [ticket-328]: http://abcl.org/trac/ticket/328 * cache Maven dependency resolution to avoid repeated lookups. Instead of calling ABCL-ASDF:RESOLVE in both the ASDF COMPILE-OP and LOAD-OP, we now cache the result of invocation in COMPILE-OP and add this value in the LOAD-OP phase. Contributed by Cyrus Harmon. [r14631]: http://abcl.org/trac/changeset/14631 #### jna Now references jna-4.0.0. Some incompatibility with CFFI ([in progress with fixing upstream][cffi-easye]). [cffi-easye]: http://github.com/easye/cffi/ Version 1.2.1 ============= 27-JUN-2013 * Tested: orcl-jdk-1.7.0_25 orcl-jdk-1.6.0_43 ** ansi tests rc-2 failing 11-13 of 21708 total. Some regressions since 1.1.1 * Stablility fixes; additional Quicklisp compatibility ** Fix (make-instance 'standard-generic-function) Version 1.2.0 ============= 01-JUN-2013 Released at ECLM 2013 Madrid, ES // 01 June 2013 * Package local nicknames to behave like SBCL * ASDF 3.0.1 is now shipped with the implementation * a more robust MOP implementation * Common cases of creating purely synthetic JAVA:JNEW-RUNTIME-CLASS now (mostly) work. Please report corner cases for fixing. * the system autoloader has been extended to cover functions bound to symbol properties Version 1.1.1 ============= 14-FEB-2013 * All reported errors with the MOP implementation have been addressed. * An autoloader for SETF expansion functions has been implemented, eliminating the errors associated with not being able to use (SETF SYMBOL) without first invoking SYMBOL as a function. [#266 * All outstanding regressions in the ANSI test suite with respect to abcl-1.0.1 have been fixed. * The ability to resolve Maven components in ASDF system definitions has been restored. Issues Resolved --------------- [#266] PSETF.47 ANSI regression [#284] checks in ensure-generic-function-using-class should occur later [#296] SLIME fails to initialize with (SETF DOCUMENTATION) undefined [#198] Hunchentoot run failure [#228] Need to implement autoloader facility for SETF functions [#288] Control character names [#290] Compiling (defvar *foo* '(quote . x)) throws an error [#293] Loop and default value for of-type problem [#294] Reader doesn't recognize terminating characters in some cases [#299] ABCL-ASDF:MVN components not loading Version 1.1.0 ============= 07-DEC-2012 Features -------- * A functioning (A)MOP implementation through the hard work of Rudi Schlatte (@rudi) * The implementation can be used across many more Quicklisp systems through a process of extensive testing. Thanks @xach! Nota bene: all of the following systems need patches to work as of the 2012-10-13 Quicklisp. All patches have been accepted in at least an initial form by the upstream maintainers. ** CLOSER-MOP Quite possible with local patches ** CFFI Needs patches to 2012-10-13 Quicklisp. [!!?] *** Dynamic interfaces idempotent across process -- no more reloading ** HUNCHENTOOT *** some bugs with underlying streams to be fixed in abcl-1.2-dev ** CXML Basic XML parsing works. XPath still borked. [???] * Java 5 bytecode Compiler The internal Lisp-to-Java bytecode compiler has been hardened by regression testing across Quicklisp libraries. ** Extensive interpreter/compiler bug fixes due to access to cl-test-suite [???] @antov ** large objects (?!?) * The facility to construct runtime classes via JNEW-RUNTIME-CLASS (@astalla) Pretty close to full coverage of primtives for creating synthethic java classes at runtime. Easy to extend with your needs; sensible defaults. ** Fields *** getter/setters ** Annotations * ASDF ** Stock ASDF-2.26.6 which includes #+abcl conditional patches for the URL-PATHAME and JAR-PATHNAME implementation extensions to ANSI. * ABCL-CONTRIB ** ABCL-ASDF Network installation of binary artifacts named by Maven POM uris. *** checks at runtime if a given class is present in the accessible classloaders *** If the check for the presence of a class fails, find a maven-3.0.4 binary locally, execute its Aether connector to retrieve its transitive dependencies from the network. ** JSS Java Syntax Sucks. q.v [lsw2] Extensive bugfixing wrt. method resolution [#229] ** JFLI A "captured from the wild" version of what @rich.hickey did before Clojure. Changes ------- * [#249] PATHNAME merge semantics DWIMs on an inferred type Extends ANSI PATHNAME in a non-conforming manner, which was probably already the case. * [r13695] Reimplementation of global symbol macros to avoid using the symbol's value slot. * [r13696] DEFMACRO now supports documentation strings as per the ANSI specification. * [r13700] ABCL loads under the Weblogic 10.3 application server. * [r13768] [#193] Allow zero-length symbols * [r13785] JNEW-RUNTIME-CLASS gets fields and annotations * [r13790] JNEW-RUNTIME-CLASS getters/setters for fields * [r13796] [r13797] N3 DOAP description for ABCL * [r13803] Build target 'abcl-contrib.jar' packages ABCL-CONTRIB Fixes ----- * ANSI [#241] ** &AUX parameters fixes RESTAS * [#221] Stack exhaustsion on funcall in non-existing package * [#113] DEFSTRUCT concurrency * [#216][#211] Compiler ** stack inconsistency * [#187] Better SORT and STABLE-SORT via Jorge Tavares [???] Issues Resolved --------------- * [#234] ABCL-ASDF mvn errors with VERSION slot unbound * [#237] JNA fails to load blocking CFFI * [#249] Problems under Ubuntu * [#250] SYS:SHA256 does not compile * [#265] COMPILE-FILE.2 COMPILE-FILE.2A ANSI regression * [#268] ABCL-ASDF working with maven-3.0.3 * [#269] SLIME cannot browse systems with November Quicklisp * [#270] Is BUGS.DEFEGENERIC.1 a valid test? * [#271] ASDF-2.26 changes synced upstream * [#272] DESCRIBE.[14] ANSI regression rschlatte * [#275] ABCL-CONTRIB still provided if abcl-contrib.jar cannot be located * [#276] defmethod doesn't call add-method * [#277] reinitialize-instance on class metaobjects incorrect * [#113] DEFSTRUCT redefinition can crash ABCL on MAKE-STRUCT * [#199] CL:DEFMETHOD fails for &AUX arguments that reference other arguments * [#213] ABCL-ASDF breakage on trunk * [#215] ABCL-ASDF:RESOLVE should work in more (some?) cases * [#229] JSS method resolution failure * [#246] CFFI: dynamically generated classes referred from .fasl can not be found after ABCL restart * [#168] Compilation fails for quicklisp let-plus * [#187] Stack Overflow for Worst-case Vector Sort * [#202] ENSURE-GENERIC-FUNCTION assumes LAMBDA-LIST is NIL * [#204] abcl-asdf maybe-parse-mvn ignores version information * [#205] JSS logic for resolving methods a little wonky (could use better diagnostics on why resolution has failed) * [#207] DECLARE should signal conditions when type declarations are violated * [#210] Add JFLI to contrib * [#217] ANSI tests wont run on Revision 14011: /trunk/abcl * [#219] Keyword argument checking for lambda lists is too lenient for ANSI * [#220] Lambda list checking too lenient * [#224] Autoloader fails when *read-XXXX* variables bound to non-standard values * [#225] One of the paths in STD-COMPUTE-DISCRIMINATING function not working * [#235] Compiled cl+ssl sources not reloadable * [#241] &rest and &aux can't coexist anymore in lambda lists * [#243] ClassCastException in MAKE-PATHNAME * [#245] Slots of a class with a custom meta-class are reported as unbound. * [#247] CFFI: $Proxy3 is not assignable to com.sun.jna.Pointer * [#252] MOP rework broke profiler? * [#254] Cannot load ASDF systems in jar archives with ASDF-BINARY-LOCATIONS-COMPATIBILTY enabled * [#255] ASDF file encoding specification doesn't work * [#263] loading systems from abcl-contrib fails if CLASSPATH has a component with wildcard * [#264] abcl-asdf.asd broken since revision 14233 * [#60 ]Implement USE-FAST-CALLS properly * [#130] "SLIME under Windows has ""extra"" CRLF" * [#172] DOCUMENTATION does not work for generic functions * [#174] Conformance bug in time implementation when using SLIME * [#175] abcl.release target fails occasionally unassigned * [#189] Compiler fails for 'unsigned-byte type declaration * [#201] &WHOLE broken in DEFINE-METHOD-COMBINATION * [#206] COMPILER-UNSUPPORTED-FEATURE-ERROR is derived from CONDITION, rather than from ERROR * [#208] "Files loaded via ""--load "" on the command line have no pathname defaults" * [#211] closure-common fails to load correctly after compilation * [#214] Stack overflow when compiler macro with fallback is triggered * [#232] Allow wrapper script to reference install directory instead of build directory * [#192] ASDF::IMPLEMENTATION-IDENTIFIER contains ABCL build environment identifier * [#195] prompt is displayed twice when evaluating NIL at the REPL Version 1.0.1 ============== 09-JAN-2012 Changes ------- * Updated ASDF to 2.019 * User Manual now contains more polished formating from docstring groveling, an index of symbols, and additional enhancements. * 'abcl.properties.in' now contains examples of optimizing the ABCL wrapper script for 64bit instances for Java7 and for Java6. * [r13720] Randomize string hash computation to guard against exploits. * [r13723] New internal API in Package.java for looking up internal vs. external symbols. Fixes ----- * [#181][r13718] The implementation now correctly loads ASDF definitions from jar archives. This had prevented the ABCL-CONTRIB loading mechanism from working. * [#177] Made the mechanism for locating the abcl-contrib archive more robust * [#177] LIST-DIRECTORY no longer ignores :RESOLVE-SYMLINKS * [r13706] Fix Streadm.readToken() bug reported by Blake McBride. * [#183][r13703] Move threads-jss.lisp out of system source to restore conditional recompilation logic. Version 1.0.0 ============== 22-OCT-2011 Released at the European Common Lisp Meeting Amsterdam 2011 Features -------- * (Draft) manual * Much better Quicklisp system capabilities (trivial-garbage, bordeaux-threads, parenscript, cxml, et. al.) Changes ------- * Updated ASDF to 2.017.22 Fixes ----- * CLOSURE-HTML now compiles * DEFINE-METHOD-COMBINATION long form implemented Version 0.27.0 ============== Features -------- * ABCL works as an SBCL build host * Huge (> 64k) literal object support (fixes CL-UNICODE support) * The ABCL-ASDF contrib allows the specification of JAR-FILE or JAR-DIRECTORY components that can be resolved via a PATHNAME. The MVN component bootstraps a Maven3 Aether connector to locally replicate a versioned jar artifact for dynamic inclusion in the CLASSPATH. Changes ------- * Renamed LispObject.writeToString() method to (more Lispy) printObject() * New LispObject.princToString() for user readable output * Changed behaviour of LispObject.unreadableString() to signal errors when *PRINT-READABLY* is non-NIL * Static initializers moved to () (java: static { }) to prevent repeated execution when invoking the constructor multiple times * Compiler clean-ups * Changed implementation of LABELS to eliminate the need to *always* create a closure * File compiler (COMPILE-FILE) clean-ups * When calling a function with the wrong number of arguments, report the expected (range) of arguments * Upgraded ASDF to 2.017 * JSS:JLIST-TO-LIST now converts any java.list.List to a Lisp list. * The ASDF extensions from JSS for the "jar-directory", "jar-file", and "class-file-directory" types have been refactored into the ABCL-ASDF contrib as well as the *ADDED-TO-CLASSPATH* variable which records dynamically added dependencies. Use the JSS:ENSURE-COMPATIBILITY function to have JSS include these dependencies. * As long as ABCL-ASDF:ENSURE-MVN-VERSION can dynamically introspect and then load Maven 3 libraries at runtime, ASDF components of type MVN can now be used to specify versioned JVM artifacts. * Threads spawned by THREADS:MAKE-THREAD can terminate the Lisp image via the EXT:QUIT and EXT:EXIT functions. Fixes ----- * MULTIPLE-VALUE-PROG1.10 (ansi test) fixed * [ticket #148] READTABLE-CASE :INVERT doesn't work for uninterned symbols * [ticket #161] READTABLE-CASE of current readtable affects FASL content * [ticket #162] Non-symbol in variable position of SETQ form causes class verification failure * [ticket #163] Local functions shadow global macro and function bindings (fixes PARENSCRIPT support) * [ticket 158] Readable printing of the string "#" does not signal a PRINT-NOT-READABLE error anymore * Fixed SYNTAX.SHARP-BACKSLASH.6 and SYNTAX.SHARP-BACKSLASH.7 * Fixed many PPRINT.* test suite failures * [ticket #151] LOAD fails for whitespace in JAR-PATHNAME Version 0.26.2 ============== 14-AUG-2011 Features -------- * Enable compilation with Java 7 Fixes ----- * Fix loading from fasls under Windows with whitespace in pathname. * Fix #131: Don't include ':' in the version string. * Fix #141: SETF of APPLY not working with arbitrary function. * Include filename in the error string being reported. * Include the test source in the release. * Include ASDF definition in source release. Version 0.26.1 ============== 27-JUL-2011 Features -------- * Upgrade ASDF to 2.017. Fixes ----- * Fix compilation problems by including the org.armedbear.lisp.protocol source in the build process * Printing of conditions defined with DEFINE-CONDITION * Regression with failing SYNTAX.SHARP-BACKSLASH.6 and SYNTAX.SHARP-BACKSLASH.7 ANSI test suite failures * Multiple failures in PPRINT.* ANSI test suite failures * String interop with Java for strings with fill pointer * Made #\Uxxxx a synonym for character codes with values greater than 255 on input, but never output as the character name by the implementation. Version 0.26.0 ============== 10-JUL-2011 Features -------- * Add support for weak reference objects * Add support for finalizers on LispObject derived classes * Upgrade ASDF to 2.0.16.1 * #\ reader macro now understands #\uNNNN as unicode codepoints * JAVA:JRESOLVE-METHOD returns same method as would have been called by JAVA:JCALL with the same arguments * Ant 'update' target to upload application to Google App Engine * Simple RUN-PROGRAM implementation * Support for custom slot definitions according to AMOP * New JAVA:*JAVA-OBJECT-TO-STRING-LENGTH* variable to control pretty printing of Java objects * JSS - more dynamic Lisp/Java FFI - (http://lsw2.googlecode.com/svn/trunk) imported * (REQUIRE :ABCL-CONTRIB) adds 'abcl-contrib.jar' to the ASDF search path * Support for weak references in hash tables through a :WEAKNESS keyword argument to MAKE-HASH-TABLE; with SYS:HASH-TABLE-WEAKNESS for inspection * Support for loading ASDF systems from JAR archives * Fast SHA1, SHA256 and SHA512 cryptographic hashes for files * Beginnings of a manual * ABCL/ASDF integration with Maven provided systems * ASDF-JAR:PACKAGE function to package ASDF systems into JARs Changes ======= * Reduced code size in the compiler by changing COMPILE-TEST-FORM * Enhanced SLIME inspector for JAVA:JAVA-OBJECT * Reimplemented MERGE-PATHNAMES * TRANSLATE-PATHNAME aligned with SBCL's behaviour if version is wild * Removed PRINT-OBJECT methods duplicating Java side code * Refactored code in SYSTEM:ZIP function * Allow JCOERCE to convert any number to java.lang.Byte (using its two's complement) * Replace MAKE-IMMEDIATE-OBJECT with +NULL+, +TRUE+ and +FALSE+ constants (the only supported ones) * Better separation between java-collections package and Java FFI * JAVA:ADD-TO-CLASSPATH is now a generic function Fixes ===== * Google App Engine example fixed * MAKE-PATHNAME erroneously merges directories as in MERGE-PATHNAME * Pretty printer routines using SYS:OUTPUT-OBJECT with GRAY-STREAM * Value of *PRINT-CASE* affects file (to FASL) compilation * MAKE-PATHNAME ignores version in :DEFAULTS * URI decoding algorithm in Pathname.java * JNEW-ARRAY-FROM-ARRAY should create byte[] arrays Version 0.25.0 ============== 10-MAR-2011 Features -------- * Add :resolve-symlinks keyword argument for DIRECTORY. * Support -- as a command line parameter for the REPL. * Preliminary support for Maven deployment. * Add an initargs cache for speedups in check-initargs. This should make the initarg checking in CLOS quite a bit faster. * Incorporate output of 'svnversion' into LISP-IMPLEMENTATION-VERSION. * Ant target for generating Javadoc. Fixes ----- * [svn r13229] Remove non-existing THREAD-LOCK and THREAD-UNLOCK from autoloads. * [svn 13228] Fix incorrect elimination of named local functions declared inline when they're actually reified in the flet/labels body. * [svn r13217] Forward-referenced classes work properly now. * [svn r13209] Add initarg checking to REINITIALIZE-INSTANCE. * [svn r13204] FINALIZE-INHERITANCE is (more) AMOP compatible. * [svn r13203] Create ATOMIC-DEFGENERIC macro, in order to eliminate FMAKUNBOUND calls and the resulting windows where no function is bound to symbols which are the most essential building blocks in CLOS/AMOP. * [svn r13200] Atomically swap generic functions into place of temporary DEFUNs for all standard-class slot accessors. Note: This addresses the recursive requirement to be able to allocate objects and classes while changing the functions used to create them. * [svn r13196] Provide more context regarding the reason of autoloading. Note: This change *hugely* helps debugging. * [svn r13189] Fix MACROEXPAND-ALL autoloader which should be loaded from 'format.lisp'. * [svn r13188] Fix DEFSTRUCT trying to generate accessors named NIL * [svn r13187] Fix #125: FASL reader should not convert symbol case [Qi FASL loading issues]. * [svn r13185] Fix #119: Incorrect dynamic environment for evaluation of :CLASS allocation slot initforms. * [svn r13182-r13184] Fix error printing issues. * [svn r13181] Increase autoload verbosity: include FASLs too (not only Java classes). Changes ------- * Merge 'unsafe-p-removal' branch. Version 0.24.0 ============== 22-JAN-2011 Features -------- * [svn r130103-r13107] Implemented JNULL_REF_P to distinguish a JAVA-OBJECT which contains a Java "null" from the Lisp NIL. * [svn r13102] More type-conversion helpers in JAVA package: LIST-FROM-JARRAY, VECTOR-FROM-JARRAY, and LIST-FROM-JENUMERATION. * [svn r13078] JVM::MAKE-CLASS-INTERFACE-FILE provides an interface for the creation of Java interfaces as serialized by the new classwriter code. An example of use can be found in "examples/misc/dynamic-interfaces.lisp". * [svn r13087] Upgraded to ASDF-2.012 Fixes ----- * [svn r13135] Fix the problem that FASLs can contain a limited number of functions. * [svn r13117][ticket #117] Fix stack inconsistency error. * [svn r13018][ticket #114] Fix strange backtrace growth. * [svn r13105] Fix Pathname.java failing to find boot.lisp in an "unpacked JAR" situation found by running ABCL in the Glassfish v3 servlet container. * [svn r13096] For arrays, add initialization with the default value of the element type if neither INITIAL-ELEMENT nor INITIAL-CONTENT have been specified. Found by: dmalves_ (freenode irc nick). * [svn r13094] Eliminate flushes after every character in javax.scripting support. * [svn r13090] Make --batch exit, use Lisp.exit() in places where applicable so that the streams are flushed, hence allowing --eval output to be flushed. * [svn r13088] Fix algorithim error in writing byte sequences via RandomAccessCharacterFile. Found and fixed by David Kirkman. Changes ------- * [svn r13141-13146,13156] Make ABCL a well behaving library to better support embedding: NEVER call System.exit() again. Instead, ABCL now throws org.armedbear.lisp.ProcessingTerminated and org.armedbear.lisp.IntegrityError. * [svn r13111] Added a "tools" directory available in SVN repository to contain tools for developing ABCL in various states. The first inhabitant is 'code-grapher.lisp' that provides a prototype to diagram a JVM instruction sequence via graphviz. * [svn r13101] Reduced verbosity of the AbclScriptEngine. * [svn r13097-13100] Slight refactoring of PATHNAME code, further specifying URI escaping rules. * [svn r13091-2] Better error reporting for UnhandledCondition thrown from the Interpreter, storing the originating Java error in the "cause" field if the cause is a subclass of JAVA_EXCEPTION. Version 0.23.1 ============== 01-DEC-2010 Fixes ----- * [svn r13509-10] Allow JSR-223 clients to query ABCL metadata without incurring the entire interpreter startup time. * [svn r13506] Fix probles with loading FASLs in directories containing whitespace characters. We now require all PATHNAME objects constructed via a namestring containing the "file" scheme to be URI encoded according to RFC3986. Version 0.23 ============ 25-NOV-2010 Features -------- * [svn r12986] Update to ASDF 2.010.1 * [svn r12982] Experimental support for the long form of DEFINE-METHOD-COMBINATION * [svn r12994] New java-interop macros: CHAIN and JMETHOD-LET * [svn r13030-31,r13034] ASDF-INSTALL improvements: Ensure that the ASDF registry contains the ASDF-INSTALL locations. Better resolution mechanism for 'gpg' binary. Fixes ----- * [svn r13039] Restore the Lisp-based build * [ticket #108][svn r13027] Fix download problems with ASDF-INSTALL * [svn r12995-12997] Changes to generated byte code to prevent JRockit JVM from crashing when optimizing it * Various fixes in order to complete the Maxima test suite without failures * [ticket #98] THREAD type specifier not exported from the THREADS package * [svn r12946] Fix CLOS thread-safety * [svn r12930] Fix non-constantness of constant symbols when using SET * [svn r12929] Don't throw conditions on floating point underflow (fixes Maxima failures) * [svn r12928] Fix for Java-collections-as-lisp-sequences support * [svn r12927] Fix for regression to moved threads related symbols * [ticket #104] SET changes value of symbols defined with DEFCONSTANT * [ticket #88] Need a predicate to indicate source of compiled version ie Java vs Lisp * [ticket #106] DEFSTRUCT :include with :conc-name creating overwriting inherited slot accessors * [ticket #97] Symbol imported in multiple packages reported multiple times by APROPOS * [ticket #107] Incorrect compilation of (SETF STRUCTURE-REF) expansion * [ticket #105] DIRECTORY ignores :WILD-INFERIORS Other ----- * [svn r12918] Compiler byte code generator cleanup: introduction of generic class file writer, elimination of special purpose code in the compiler. * Number of hashtable implementations reduced to 1 (from 5) * Reduced use of 'synchronized' global hash table access by using the java.util.concurrent package Version 0.22 ============ 24-SEP-2010 Fixes ----- * [svn r12902] Fix reading data with scandinavian latin1 characters * [svn r12906] Respect the CLASSPATH environment variable in the abcl wrapper scripts * [ticket #103] DOCUMENTATION not autoloaded Other ----- * [svn r12819] Until-0.22-compatibility hacks (in threads support) removed Version 0.21 ============ 24-JUL-2010 Features -------- * [svn r12818] Update to ASDF 2.004 * [svn r12738-805] Support for custom CLOS slot definitions and custom class options. * [svn r12756] slot-* functions work on structures too. * [svn r12774] Improved Java integration: jmake-proxy can implement more than one interface. * [svn r12773] Improved Java integration: functions to dynamically manipulate the classpath. * [svn r12755] Improved Java integration: CL:STRING can convert Java strings to Lisp strings. Fixes ----- * [svn 12809-10-20] Various printing fixes. * [svn 12804] Fixed elimination of unused local functions shadowed by macrolet. * [svn r12798-803] Fixed pathname serialization across OSes. On Windows pathnames are always printed with forward slashes, but can still be read with backslashes. * [svn r12740] Make JSR-223 classes compilable with Java 1.5 Other ----- * [svn r12754] Changed class file generation and FASL loading to minimize reflection. * [svn r12734] A minimal Swing GUI Console with a REPL is now included with ABCL. Version 0.20 ============ 24-MAY-2010 Features -------- * [svn r12576] Support for CLOS METACLASS feature. * [svn r12591-602] Consolidation of copy/paste code in the readers. * [svn r12619] Update to ASDF2 (specifically to ASDF 1.719). * [svn r12620] Use interpreted function in FASL when compilation fails. * [ticket #95] PATHNAME-JAR and PATHNAME-URL subtypes now handle jar and URL references working for OPEN, LOAD, PROBE-FILE, FILE-WRITE-DATE, DIRECTORY, et. al. * Many small speed improvements (by marking functions 'final'). * [ticket #91] Threads started through MAKE-THREAD now have a thread-termination restart available in their debugger. * [svn r12663] JCLASS supports an optional class-loader argument. * [svn r12634] THREADS:THREAD-JOIN implemented. * [svn r12671] Site specific initialization code can be included in builds via the 'abcl.startup.file' Ant property. Fixes ----- * [ticket #89] Inlining of READ-LINE broken when the return value is unused. * [svn r12636] Java class verification error when compiling PROGV in a context wanting an unboxed return value (typically a logical expression). * [svn r12635] ABCL loads stale fasls instead of updated source even when LOAD is called with a file name without extension. * [ticket #92] Codepoints between #xD800 and #xDFFF are incorrectly returned as characters from CODE-CHAR. * [ticket #93] Reader doesn't handle zero returned values from macro functions correctly. * [ticket #79] Different, yet similarly named, uninterned symbols are incorrectly coalesced into the same object in a fasl. * [ticket #86] No restarts available to kill a thread, if none bound by user code. * [svn r12586] Increased function dispatch speed by eliminating FIND-CLASS calls (replacing them by constant references). * [svn r12656] PATHNAME-JAR now properly uses HTTP/1.1 HEAD requests to detect if remote resource has been changed. * [svn r12643] PATHNAME-JAR now properly references Windows drive letters on DEVICE other than the default. * [svn r12621] Missing 'build-from-lisp.sh' referenced in README now included in source release. Other ----- * [svn r12581] LispCharacter() constructors made private, in favor of getInstance() for better re-use of pre-constructed characters. * [svn r12583] JAVA-CLASS reimplemented in Lisp. * [svn r12673] Load 'system.lisp' moved later in boot sequence so unhandled conditions drop to debugger. * [svn r12675] '--nosystem' commandline option inhibits loading of 'system.lisp'. * [svn r12642] Under Windows, pathname TYPE components can now contain embedded periods iff they end in '.lnk' to support shortcuts. Version 0.19 ============ 14-MAR-2010 Features -------- * [svn r12518] *DISASSEMBLER* may now contain a hook which returns the command to disassemble compiled functions. * [svn r12516] An implementation of user-extensible sequences as proposed in Christopher Rhodes, "User-extensible sequences in Common Lisp", Proc. of the 2007 International Lisp Conference. * [svn r12513] Implement SYS:SRC and SYS:JAVA logical pathname translations for system Lisp source and the root of the Java package structure, respectively. * [svn r12505] All calls to anonymous functions and local functions that have been declared inline are now converted to LET* forms, reducing stack usage and the number of generated classes. * [svn r12487] An initial port ASDF-INSTALL now forms the first ABCL contrib. Such contribs are optionally built by the Ant target 'abcl.contrib'. ASDF-INSTALL is not expected to work very well under Windows in its present state. * [svn r12447] [ticket:80] REQUIRE now searches for ASDF systems. * [svn r12422] Jar pathname support extensively re-worked and tested so that LOAD, PROBE-FILE, TRUENAME, DIRECTORY, and WRITE-FILE-DATE all work both for local and remote jar pathnames of the form "jar:URL!/JAR-ENTRY". The loading ASDF systems from jar files is now possible. SYS:PATHNAME-JAR-P predicate signals whether a pathname references a jar. NB: jar pathnames do *not* currently work as an argument to OPEN. SYS:UNZIP implemented to unpack ZIP files. SYS:ZIP now has a three argument version for creating zip files with hierarchical entries. * [svn r12450] Collect unprocessed command-line arguments in EXT:*COMMAND-LINE-ARGUMENT-LIST* (Dennis Lambe Jr.) * [svn r12414] SYS::%GET-OUTPUT-STREAM-ARRAY returns a Lisp byte array from a Java byte array stream. * [svn 12402] ABCL.TEST.LISP:RUN-MATCHING will now execute that subset of tests which match a string. Fixes/Optimizations ------------------- * [svn r12526] Unbinding of PROGV bound variables on local transfer of control (within-java-function jump targets) * [svn r12510] The new ansi-test WITH-STANDARD-IO-SYNTAX.23 passes. Our with-standard-io-syntax implementation now correctly resets all necessary pprint variables. Patch by Douglas R. Miles, thanks for the contribution! * [svn r12485] Pathnames starting with "." can now have TYPE. * [svn r12484] FASLs containing "." characters not used to indicate type (i.e. ".foo.bar.baz.abcl") can now be loaded. * [svn r12422] Pathname.java URL contructor under Windows now properly interprets the drive letter. * [svn r12449] The 'abcl.jar' produced by Netbeans now contains a valid manifest (found by Paul Griffionen). * [svn r12441] ZipCache now caches all references to ZipFiles based on the last-modified time for local files. Remote files are always retrieved due to problems in the underlying JVM code. SYS:REMOVE-ZIP-CACHE implements a way to invalidate an entry given a pathname. * [svn r12439] Remove duplication of java options in Windows 'abcl.bat' script. * [svn r12437] CHAR-CODE-LIMIT is the upper execlusive limit (found by Paul Griffionen). * [svn r12436] Describe formatting was missing a newline (reported by Blake McBride). * [svn 12469] Ensure that FILE-ERROR always has a value (possibly NIL) for its PATHNAME member. * [svn r14222] MERGE-PATHNAMES no longer potentially shares structure between its result and *DEFAULT-PATHNAME-DEFAULTS*. * [svn r12416] Fixed ANSI LAMBDA.nn test failures caused by errors in lambda inlining. * [svn r12417] [ticket:83] Fix TRANSLATE-LOGICAL-PATHNAME regression. (Alan Ruttenberg). * [svn r12412] Optimize memory efficiency of FORMAT by use of a hashtable rather than a CHAR-CODE-LIMIT array. * [svn r12408] FIND-SYMBOL requires a string argument. * [svn r12400] Make NIL (as symbol) available to the compiler. * [svn r12398] Move lambda list analysis to compile time where possible. * [svn r12397] BROADCAST-STREAM obeys default external format fixing ANSI MAKE-BROADCAST-STREAM.8. * [svn r12395] Improve arglist display for SLIME (Matthias Hölzl). * [svn r12394] Optimize array utilization in closures. * [svn r12393] Optimize array functions in compiler which don't require clearing the VALUES array. * [svn r12392] Optimize/normalize aspects of boot.lisp * [svn r12391] Prevent duplicated subclasses form occuring. Other ----- * [svn r12447] SYS::*MODULE-PROVIDER-FUNCTION* now provides a mechanism to extend the REQUIRE resolver mechanism at runtime. * [svn r12430] Ant based build no longer writes temporary files to contain the Lisp build instructions. * [svn r12481] STANDARD-CLASS now has slots to be inherited by deriving metaclasses in support of the (in progress) work on metaclass. * [svn r12425] No longer ignore the METACLASS defclass option in support of the (in progress) work on metaclass * [svn r12422] SYS::*LOAD-TRUENAME-FASL* now contains the TRUENAME of the Java "*.cls" component when loading a packed FASL. * [svn r12461] Human readable Java representations for class cast exceptions for NULL and UNBOUND values. * [svn r12453 et. ff.] Large numbers of the implementation of Java primitives have been declared in a way so that a stack trace provides a much more readable indication of what has been invoked. Primitives which extend Primitive are prefixed with "pf_"; those which extend SpecialOperator are prefixed with "sf_". * [svn r12422] The internal structure of a jar pathname has changed. Previously a pathname with a DEVICE that was itself a pathname referenced a jar. This convention was not able to simultaneously represent both jar entries that were themselves jar files (as occurs with packed FASLs within JARs) and devices which refer to drive letters under Windows. Now, a pathname which refers to a jar has a DEVICE which is a proper list of at most two entries. The first entry always references the "outer jar", and the second entry (if it exists) references the "inner jar". * [svn r12419] Ant 'abcl.release' target centralizes the build steps necessary for creating releases. * [svn r12409] Compiler now rewrites function calls with (LAMBDA …) as the operator to LET* forms. * [svn r12415] CLASS-FILE renamed to ABCL-CLASS-FILE to prepare for (in progress) reworking of Stream inheritance. * [svn r123406] 'test/lisp/abcl/bugs.lisp' forms a default location to add unit tests for current bug testing. The intention is to move these tests into the proper location elsewhere in the test suite once they have been fixed. * [svn r124040] Java tests upgraded to use junit-4.8.1. Netbeans project runtime classpath now uses compilation results before source directory, allowing the invocation of ABCL in interpreted mode if the Ant 'abcl.compile.lisp.skip' property is set. Java unit tests for some aspects of jar pathname work added. * New toplevel 'doc' directory now contains: + [svn r12410] Design for the (in progress) reworking of the Stream inheritance. + [svn r12433] Design and current status for the re-implementation of jar pathnames. * [svn r12402] Change ABCL unit tests to use the ABCL-TEST-LISP definition contained in 'abcl.asd'. Fixed and renabled math-tests. Added new tests for work related to handling jar pathnames. * [svn r12401] The REFERENCES-NEEDED-P field of the LOCAL-FUNCTION structure now tracks whether local functions need the capture of an actual function object. Version 0.18.1 ============== 17-JAN-2010 Features: * Support for printing java objects with print-object * Support for disassembling proxied functions Bugs fixed: * maxima works again Version 0.18.0 ============== 12-JAN-2010 Features: * Programmable handling of out-of-memory and stack-overflow conditions * Faster initial startup (to support Google App Engine) * Faster special variable lookup * New interface for binding/unwinding special variables * Implement (SETF (STREAM-EXTERNAL-FORMAT ) ) * Implement (SETF (JAVA:JFIELD ) ) * Constant FORMAT strings get compiled for performance Bugs fixed: * FASLs are system default encoding dependent (ticket 77) * I/O of charset-unsupported characters causes infinite loop (ticket 76) * Memory leak where on unused functions with documentation * ANSI PRINT-LEVEL.* tests * Continued execution after failing to handle Throwable exceptions * Line numbers in generated java classes incorrect * JCALL, JNEW doesn't select best match when multiple applicable methods * STREAM-EXTERNAL-FORMAT always returns :DEFAULT, instead of actual format * REPL no longer hangs in Netbeans 6.[578] output window * Lambda-list variables replaced by surrounding SYMBOL-MACROLET Other changes * LispObject does not inherit from Lisp anymore * Many functions declared 'final' for performance improvement * SYSTEM:*SOURCE* FASLs for system files no longer refer to intermediate build location Version 0.17.0 ============== 07-NOV-2009 Features: * Google App Engine example project "Hello world" * Support for loading FASLs from JAR files * Checking of init-arguments for MAKE-INSTANCE (CLOS) * Support for *INVOKE-DEBUGGER-HOOK* (to support SLIME) * Reduced abcl.jar size (bytes and number of objects) * Faster access to locally bound specials (compiler efficiency) * Java property to print autoloading information: abcl.autoload.verbose * Experimental: binary fasls * Default Ant build target now "abcl.clean abcl.wrapper" (from abcl.help) * ConditionThrowable class renamed to ControlTransfer, parent class changed to RuntimeException (to make it unchecked) * API no longer throws ConditionThrowable/ControlTransfer Bugs fixed: * Better fix for #63: Prevent exceptions from happening (GO and RETURN-FROM) * Restore ability for ABCL to be build host for SBCL * CLOS performance improvements through looser COMPILE dependency * Compilation fix for highest SPEED setting (triggered by CL-BENCH) * COMPILE's use of temp files eliminated * OpenJDK on Darwin now correctly identified * Incorrect block names for SETF functions defined by LABELS * Fixed MULTIPLE-VALUE-CALL with more than 8 arguments * Incorrect identification of lexical scope on recursive TAGBODY/GO and BLOCK/RETURN-FROM blocks (compiler and interpreter) * Correctly return 65k in char-code-limit (was 256, incorrectly) * Fixes to be able to run the BEYOND-ANSI tests (part of ANSI test suite) * Compiler typo fix * Implementation of mutex functionality moved to lisp from Java * Functions handling #n= and #n# are now compiled * Autoload cleanups * System package creation cleaned up * CHAR-CODE-LIMIT correctly reflects CHAR-CODE maximum return value * Precompiler macroexpansion failure for macros expanding into special operators Version 0.16.1 ============== 17-OCT-2009 Bugs fixed: * More careful checking for null args in LispStackFrame * Honor appearance of &allow-other-keys in CLOS MAKE-INSTANCE * Fix #63: GO forms to non-existent TAGBODY labels would exit ABCL * Don't leak temp files during compilation Version 0.16.0 ============== 06-SEP-2009 Summary of changes: ------------------ * Fixed generated wrapper for path names with spaces (Windows) * Fixed ticket #58: Inspection of Java objects in Lisp code * Restored functionality of the built-in profiler * Profiler extended with hot-spot counting (as opposed to call counting) * Stack sampling in the profiler moved to scheduler thread to reduce impact on the program execution thread * THE type-checking for the interpreter (for simple-enough type specifications) * Added structure argument type checking in structure slot accessor functions * Make GENSYM thread-safe * Various performance fixes found by running the raytracer from http://www.ffconsultancy.com/languages/ray_tracer/benchmark.html * Better initarg checking for make-instance and change-class Fixes ansi-test errors CHANGE-CLASS.1.11, MAKE-INSTANCE.ERROR.3, MAKE-INSTANCE.ERROR.4, CHANGE-CLASS.ERROR.4 and SHARED-INITIALIZE.ERROR.4 * Improve performance of StackFrames (Erik Huelsmann, Ville Voutilainen, with input from Peter Graves and Douglas Miles) * Improve performance of CLOS eql-specializers via cache (Anton Vodonosov) * 'build-from-lisp.sh' shell script (Tobias Rittweiler) * New threading primitives aligned with Java/JVM constructs (Erik Huelsmann) SYNCHRONIZED-ON OBJECT-NOTIFY OBJECT-NOTIFY-ALL * THREADS package created to hold threads related primitives: THREADP THREAD-UNLOCK THREAD-LOCK THREAD-NAME THREAD-ALIVE-P CURRENT-THREAD DESTROY-THREAD INTERRUPT-THREAD WITH-THREAD-LOCK MAKE-THREAD-LOCK MAKE-THREAD INTERRUPT-THREAD MAPCAR-THREADS GET-MUTEX MAKE-MUTEX WITH-MUTEX RELEASE-MUTEX These primitives are still part of the EXTENSIONS package but are now to be considered as deprecated, marked to be removed with 0.22 * Stacktraces now contain calls through Java code relevant to debugging (Tobias Rittweiler) Backtrace functionality been moved from EXT:BACKTRACE-AS-LIST to SYS:BACKTRACE to mark this changes. The methods SYS:FRAME-TO-STRING and SYS:FRAME-TO-LIST can be used to inspect the new LISP_STACK_FRAME and JAVA_STACK_FRAME objects * Various stream input performance optimizations * Fixed breakage when combining Gray streams and the pretty printer * Performance improvements for resolution of non-recursive #=n and #n# Version 0.15.0 ============== 07-Jun-2009 Summary of changes: ------------------- * 2 more MOP exported symbols to support Cells port * Updated FASL version * Support (pre)compilation of functions with a non-null lexical environment * Compiler and precompiler cleanups * 'rt.lisp' copy from ANSI test suite removed * Many documentation additions for the (pre)compiler * JSR-233 support improvements * Refactoring of classes: - deleted: CompiledFunction, ClosureTemplateFunction, CompiledClosure, Primitive0R, Primitive1R, Primitive2R - renamed: CompiledClosure [from ClosureTemplateFunction] * Compiler support for non-constant &key and &optional initforms * Fixed ticket #21: JVM stack inconsistency [due to use of RET/JSR] * Numerous special bindings handling fixes, especially with respect to (local) transfer of control with GO/RETURN-FROM * Paths retrieved using URL.getPath() require decoding (r11815) * Build doesn't work inside paths with spaces (r11813) * Compilation of export of a symbol not in *package* (r11808) * Moved compiler-related rewriting of forms from precompiler to compiler * Removed chained closures ('XEPs') in case of &optional arguments only * Loading of SLIME fails under specific conditions (r11791) * Binding of *FASL-ANONYMOUS-PACKAGE* breaks specials handling (r11783) * Fixed ANSI tests: DO-ALL-SYMBOLS.{6,9,12}, DEFINE-SETF-EXPANDER.{1,6,?}, MULTIPLE-VALUE-SETQ.{5,8}, SYMBOL-MACROLET.8, COMPILE-FILE.{17,18} * COMPILE and COMPILE-FILE second and third values after a failed invocation inside the same compilation-unit (r11769) * JCLASS on non-existing classes should signal an error (r11762) * Dotted lambda lists break interpretation (r11760) * Implementation of MACROEXPAND-ALL and COMPILER-LET (r11755) * Switch from casting to 'instanceof' for performance (r11754) * Google App Engine support: don't die if 'os.arch' isn't set (r11750) * Excessive stack use while resolving #n= and #n# (r11474) Version 0.14.1 ============== 05-Apr-2009 Summary of changes: ------------------- * Include this CHANGES file and scripting files in the tar and zip files Version 0.14.0 ============== 05-APR-2009 Summary of changes: ------------------- * Increased clarity on licensing (Classpath exception mentioned in COPYING, removed LICENSE) * Resolved infinite recursion on TRACEing the compiler * Changes on the lisp based build system for parity with Ant * Fixed interpreter creation in Java Scripting * libabcl.so no longer created; it was solely about installing a SIGINT handler. Libraries should not do that. * boxing of LispObject descendants in JCALL/JCALL-RAW fixed * OpenBSD and NetBSD platform detection * fixed special bindings restores in compiled code for MULTIPLE-VALUE-BIND/LET/LET*/PROGV and function bodies * introduced variadic list() function to replace list1() ... list9() * fix return value type of ACOS with complex argument * fixed precision of multiplication of complex values * fixed use of COMPILE inside file compilation (i.e. COMPILE-FILE) * fix expansion of macros inside RESTART-CASE (fixes RESTART-CASE ANSI failures) * fix macroexpansion in the precompiler * Fixnum and Bignum now use a static factory method; constructors are now private -> increases chances of numbers being EQ * Code cleanup in EXPT to fix (EXPT ) Version 0.13.0 ============== 28-FEB-2009 Summary of changes: ------------------- * Separated J and ABCL into two trees * Many many compiler code cleanups * NetBeans project files * Support for CDR6 (See http://cdr.eurolisp.org/document/6/) * More efficient code emission in the compiler * Ant build targets for testing (abcl.test) * Use ConcurrentHashMap to store the lisp threads for increased performance * Fix adjustability of expressly adjustable arrays (ticket #28) * Fix calculation of upperbound on ASH in the compiler (don't calculate numbers too big, instead, return '*') * Introduce LispInteger as the super type of Bignum and Fixnum * Boxing/unboxing for SingleFloat and DoubleFloat values, inclusive of unboxed calculations * Fixed URL decoding bug in loadCompiledFunction (use java.net.URLDecoder) * Fixed line number counting * Inlining of simple calculations (+/-/*) * All static fields declared 'final' * Add support for java.lang.Long based on Bignum to our FFI abcl-src-1.9.0/COPYING0100644 0000000 0000000 00000044735 14202767264 013020 0ustar000000000 0000000 The software in this package is distributed under the GNU General Public License (with a special exception described below as 13th term). GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 13. Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License cover the whole combination. The following paragraph details the "classpath exception" which ABCL allows as an exception to the statement about linking libraries. As a special exception, the copyright holders of this software give you permission to link this software with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this software. If you modify this software, you may extend this exception to your version of the software, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice abcl-src-1.9.0/README0100644 0000000 0000000 00000022111 14242627550 012622 0ustar000000000 0000000 Armed Bear Common Lisp (ABCL) README ==================================== Armed Bear Common Lisp is a conforming implementation of ANSI X3J13 Common Lisp that runs in a Java virtual machine. It compiles Lisp code directly to Java byte code for execution. LICENSE ------- Armed Bear Common Lisp is distributed under the GNU General Public License with a classpath exception (see "Classpath Exception" below). A copy of GNU General Public License (GPLv2) is included in this distribution, in . We have modified our GPLv2 license section 13 to read: 13. Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License cover the whole combination. The following paragraph details the "classpath exception" which ABCL allows as an exception to the statement about linking libraries. As a special exception, the copyright holders of this software give you permission to link this software with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this software. If you modify this software, you may extend this exception to your version of the software, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. CONTAINERIZATION ---------------- We recommend using podman over docker for political reasons, but the surface syntax is identical so if you must, just subsitute `docker` for `podman` in the following examples. With [podman][] installed, one may execute: podman build -t YOURID/abcl . podman run -it YOURID/abcl to get something like illin:~/work/abcl$ podman run -it YOURID/abcl VM settings: Max. Heap Size (Estimated): 498.00M Using VM: OpenJDK 64-Bit Server VM Armed Bear Common Lisp 1.9.0 Java 17.0.2 Oracle Corporation OpenJDK 64-Bit Server VM Low-level initialization completed in 0.952 seconds. Startup completed in 4.248 seconds. Type ":help" for a list of available commands. CL-USER(1): To install Quicklisp for ABCL in the Docker container run: podman run -t YOURID/abcl abcl \ --batch --load /home/abcl/work/abcl/ci/install-quicklisp.lisp See for the build instructions. [podman]: https://podman.io/releases/2022/02/22/podman-release-v4.0.0.html [Docker Engine]: https://www.docker.com/products/docker-engine RUNNING FROM BINARY RELEASE --------------------------- After you have downloaded a binary release from either [the distributed Maven POM graph][maven-abcl] or from [abcl.org][abcl.org-release] archive unpack it into its own directory. To run ABCL directly from this directory, make sure the Java executable (`java`) (Java 6, 7, 8, 11, 13, 14, 15, 16, 17, and 18 are supported by ABCL 1.9.0) is in your shell's path. [maven-abcl]: [maven-abcl-contrib]: [abcl.org-release]: To start ABCL, simply issue the following command: cmd$ java -jar abcl.jar which should result in output like the following Armed Bear Common Lisp 1.9.0 Java 17.0.2 OpenJDK Porters Group OpenJDK 64-Bit Server VM Low-level initialization completed in 0.107 seconds. Startup completed in 0.493 seconds. CL-USER(1): Yer now at the interactive ABCL "Read Eval Print Loop" (REPL): hacks 'n glory await. See the section headed "SLIME" for instructions to connect to this repl from Emacs. BUILDING FROM SOURCE RELEASE ---------------------------- ABCL may be built from its source code by executing the build instructions expressed by the venerable Apache Ant tool. To build, one must have a Java 6, 7, 8, 11, 13, 14, 15, 16 or 17 Java Development Kit (openjdk) installed locally. Just the Java Runtime Environment (JRE) isn't enough, as you need the Java compiler ('javac') to compile the Java source of the ABCL implementation. Download a binary distribution [Ant version 1.7.1 or greater][ant]. Unpack the files somewhere convenient, ensuring that the 'ant' (or 'ant.bat' under Windows) executable is in your path and executable. [ant]: http://ant.apache.org/bindownload.cgi Then simply executing cmd$ ant from the directory containing the instructions will create an executable wrapper ('abcl' under UNIX, 'abcl.bat' under Windows). Use this wrapper to start ABCL. The build may be customized by copying to , which will cause Ant to attempt to build incrementally as well as optimizing the runtime for a contemporary 64bit desktop/server machine running Java 8, 11, and/or 17. The file contains incomplete documentation on how it may be edited for subsequent customization. As an alternative to copying the prototype, if one has a version of bash locally, one may issue via Ant ant abcl.properties.autoconfigure.openjdk.17 or from the shell as bash ci/create-abcl-properties.bash openjdk17 Currently supported platforms are 'openjdk6', 'openjdk7', 'openjdk8', 'openjdk11', 'openjdk13', 'openjdk14', 'openjdk15', 'openjd16', and 'openjdk17'. USING APACHE NETBEANS --------------------- Alternatively, one may install the [Netbeans visual integrated development environment][netbeans], which contains both the Java Development Kit as well as the Ant build tool. The source distribution contains Netbeans-specific project artifacts under for loading ABCL as a Netbeans project. With Netbeans, one should be able to open the ABCL directory as a project whereupon the usual build, run, and debug targets as invoked in the GUI are available. Use the 'slime' config with a suitably linked SLIME `swank.asd` ASDF configuration to connect a REPL to the NetBeans debug process. [netbeans]: http://netbeans.org/downloads/ SLIME ----- For usage of ABCL with the [Superior Lisp Interaction Mode for Emacs][slime], one may easily start a Swank listener via: (require :asdf) (require :abcl-contrib) (asdf:load-system :quicklisp-abcl) (or (asdf:make :swank) (ql:quickload :swank)) (swank:create-server :dont-close t) [slime]: https://common-lisp.net/project/slime/ BUGS ---- Armed Bear Common Lisp strives to be a conforming ANSI X3J13 Common Lisp implementation. Any other behavior should be reported as a bug. ABCL has a [User Manual][manual] stating its conformance to the ANSI standard, providing a compliant and practical Common Lisp implementation. [manual]: https://abcl.org/releases/1.9.0/abcl-1.9.0.pdf TESTS ----- | Version | Failures | Total | |---------+----------+-------| | 1.9.0 | 61-2 | 21870 | | 1.8.0 | 49 | 21848 | | 1.5.0 | 48 | 21708 | ABCL 1.9.0 currently fails ~61-62 out of 21870 the current ANSI test suite derived from the tests originally written for GCL. Note that under the various cloud CIs that build the testing of [ansi-test][] is done via a git clone of current master branch at the time that the tests are executed, so these results may vary somewhat. We maintain by hand a [historical database of failing symbols][ansi-failures-abcl] that could frankly use a bit more love to be useful. In addition, there is a problem with the testing of RANDOM-STATE under the implementation that results in a test failing at random under each run, hence the "61-2" failures for this release. [ansi-test]: git+ [ansi-failures-abcl]: Maxima's test suite runs without failures. ABCL comes with a test suite. Consult the output of `ant help.test` for more information. SUPPORT ------- ABCL has many deficiencies, both known and unknown. Descriptions, tests, and even patches to address them will be gladly accepted. Please report problems to the [development mailing list][mailing-list] or via opening an issue on either the [ABCL trac instance][trac] or [github][]. [mailing-list]: https://mailman.common-lisp.net/pipermail/armedbear-devel/ [github]: https://github.com/armedbear/abcl/issues [trac]: https://abcl.org/trac/ AUTHORS ------- On behalf of all ABCL development team and contributors, Mark Evenson Erik Hülsmann Rudolf Schlatte Alessio Stalla Ville Voutilainen alan dmiles Dmitry Nadezhin olof ferada pipping slyrus vibhu Jonathan Cunningham Uthar alejandrozf phoe jackdaniel Robert Munyer Eric Timmons (daewok) contrapunctus Scott Burson Samuel Hunter Phil Eaton András Simon Peter Graves Have fun! May 2022 abcl-src-1.9.0/abcl.asd0100644 0000000 0000000 00000015707 14242627550 013351 0ustar000000000 0000000 ;;; -*- Mode: LISP; Syntax: COMMON-LISP -*- (defsystem abcl :version "1.9.0" :in-order-to ((test-op (test-op "abcl/test/lisp")))) (defsystem abcl/test/lisp :version "1.9.0" :description "Test ABCL with the its own collection of unit tests." :perform (test-op (o s) (uiop:symbol-call :abcl.test.lisp '#:run)) :components ((:module abcl-rt :pathname "test/lisp/abcl/" :serial t :components ((:file "rt-package") (:file "rt") (:file "test-utilities"))) (:module package :depends-on (abcl-rt) :pathname "test/lisp/abcl/" :components ((:file "package"))) (:module test :depends-on (package) :pathname "test/lisp/abcl/" :components ((:file "utilities") (:file "compiler-tests") (:file "condition-tests") #+abcl (:file "class-file") #+abcl (:file "metaclass") #+abcl (:file "mop-tests-setup") #+abcl (:file "mop-tests" :depends-on ("mop-tests-setup")) (:file "clos-tests") (:file "file-system-tests") #+abcl (:file "jar-pathname" :depends-on ("utilities" "pathname-tests" "file-system-tests")) #+abcl (:file "url-pathname") (:file "math-tests" :depends-on ("compiler-tests")) (:file "misc-tests") (:file "latin1-tests") (:file "bugs" :depends-on ("file-system-tests")) #+abcl (:file "wild-pathnames" :depends-on ("file-system-tests")) #+abcl (:file "weak-hash-tables") #+abcl (:file "zip") #+abcl (:file "java") (:file "pathname-tests" :depends-on ("utilities")) #+abcl (:file "runtime-class") #+abcl (:file "package-local-nicknames-tests") #+abcl (:file "closure-serialization"))))) ;;; ;;; ASDF definitions and the ANSI-TEST suite ;;; ;;; Below refer to the ANSI-TEST source tree, which isn't included as ;;; part of ABCL, but may be obtained at ;;; ;;; For the 'abcl/test/ansi/*' definitions to work, we require that ;;; the ANSI-TEST to be in a sibling directory named "ansi-tests" ;;; which should be manually synced with the contents of the SVN ;;; repository listed above. ;;; The ABCL.TEST.ANSI defines a function VERIFY-ANSI-TESTS to check ;;; whether the test suite is present, which provides a more useful ;;; diagnostic, but I can't seem to find a way to hook this into the ;;; ASDF:LOAD-OP phase. (defsystem abcl/ansi-rt :description "Enapsulation of the REGRESSION-TEST framework used by ~ the ANSI test suite, so that we may build on its 'API'. Requires that the contents of ~ be in a directory named '../ansi-test/'." :pathname "../ansi-test/" ;;; NB works when loaded from ASDF but not with a naked EVAL :default-component-class cl-source-file.lsp :components ((:file "rt-package") (:file "rt" :depends-on (rt-package)))) (defsystem abcl/test/ansi :depends-on (abcl/ansi-rt) :components ((:module ansi-tests :pathname "test/lisp/ansi/" :components ((:file "packages") (:file "abcl-ansi" :depends-on ("packages")) (:file "parse-ansi-errors" :depends-on ("abcl-ansi")))))) (defsystem abcl/test/ansi/interpreted :version "1.2" :description "Test ABCL with the interpreted ANSI tests." :depends-on (abcl/test/ansi) :perform (test-op (o s) (uiop:symbol-call :abcl.test.ansi 'run :compile-tests nil))) (defsystem abcl/test/ansi/compiled :version "1.2" :description "Test ABCL with the compiled ANSI tests." :depends-on (abcl/test/ansi) :perform (test-op (o s) (uiop:symbol-call :abcl.test.ansi 'run :compile-tests t)) :components ((:module ansi-tests :pathname "test/lisp/ansi/" :components ((:file "packages") (:file "abcl-ansi" :depends-on ("packages")) (:file "parse-ansi-errors" :depends-on ("abcl-ansi")))))) (defsystem abcl/test/cl-bench :description "Test ABCL with CL-BENCH." :perform (test-op (o s) (uiop:symbol-call :abcl.test.cl-bench 'run)) :components ((:module wrapper :pathname "test/lisp/cl-bench/" :components ((:file "wrapper"))))) (defsystem abcl/documentation :description "Tools to generate LaTeX source from docstrings." :depends-on (swank jss) ;; provided by abcl-contrib :components ((:module package :pathname "doc/manual/" :components ((:file "package"))) (:module grovel :depends-on (package) :pathname "doc/manual/" :components ((:file "index" :depends-on (grovel)) (:file "grovel"))))) (defsystem abcl/tools :version "0.2.0" :components (#+(or) ;; TODO Untangle source unit compile time execution (:module grapher :pathname "tools/" :components ((:file "code-grapher"))) (:module digest :pathname "tools/" :components ((:file "digest"))))) #+(or) ;; TODO Untangle source unit compile time execution (defsystem abcl/tools/bisect :version "0.1.0" :depends-on (abcl/test/ansi/compiled) :components ((:module bisect :pathname "tools/" :components ((:file "check"))))) (defsystem abcl/tools/resource :version "0.1.0" :depends-on (dexador alexandria) :components ((:module http :pathname "tools/" :components ((:file "resource"))))) (defsystem abcl/model/changes :version "0.1.0" :depends-on (jeannie) ;;; :components ((:module n3 :pathname "etc/" :components ((:static-file "changes.n3") (:file "changes"))))) abcl-src-1.9.0/abcl.bat.in0100644 0000000 0000000 00000000170 14202767264 013744 0ustar000000000 0000000 @"@JAVA@" -cp "@ABCL_CLASSPATH@";"%CLASSPATH%" @ABCL_JAVA_OPTIONS@ org.armedbear.lisp.Main %1 %2 %3 %4 %5 %6 %7 %8 %9 abcl-src-1.9.0/abcl.in0100644 0000000 0000000 00000000173 14202767264 013202 0ustar000000000 0000000 #!/bin/sh exec @JAVA@ \ -cp @ABCL_CLASSPATH@:"$CLASSPATH" \ @ABCL_JAVA_OPTIONS@ \ org.armedbear.lisp.Main \ "$@" abcl-src-1.9.0/abcl.properties.in0100644 0000000 0000000 00000006702 14202767264 015401 0ustar000000000 0000000 ## Ant based build process and runtime settings ## A file named 'abcl.properties' controls settings for the ABCL ## build. This is the prototype for its contents. # Attempt to perform incremental compilation? abcl.build.incremental=true ## javac compiler options for ABCL build # generate class files for this target JVM #ant.build.javac.target=1.8 # specify Java source compatiblity level #ant.build.javac.source=1.6 ## Additional site specific startup code to be merged in 'system.lisp' at build time #abcl.startup.file=${basedir}/startup.lisp ## java.options sets the invoking JVM options in the abcl wrapper script # Base JVM settings that work on all supported platforms # <> java.options java.options=-XshowSettings:vm -Dfile.encoding=UTF-8 ## N.b. Ant properties can only be set once, so lines like ## java.options=${java.options} further options ## will NOT work. Instead one has to "manually" create lines #<> # ( openjdk11, openjdk13, openjdk14 ) ; # #java.options=-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx -Xlog:gc #<> # openjdk11 ; # rdfs:seeAlso ; #java.options=-XX:CompileThreshold=10 #<> # openjdk8 ; #java.options=-XX:+UseG1GC -XX:+AggressiveOpts -XX:CompileThreshold=10 #<> # rdfs:comment "openjdk7 with 64bit optimizations" ; # openjdk7 ; #java.options=-d64 -XX:+UseG1GC #<> # rdfs:comment "openjdk6 is the minimum supported runtime" # openjdk6 ; #java.options=-d64 -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=1g -XX:+UseConcMarkSweepGC # Comprehensive documentation for JVM options does not really exist: # per the usual entropy of long projects, the only true source of # truth is the source of the specific openjdk. # # As of 2020, decent online compendiums are # and # # ORCL's documentation ## Various historical option settings # Java7 on 64bit optimizations #java.options=-d64 -Xmx16g -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=2g # Set the JVM to use a maximum of 1GB of RAM (only works for 64bit JVMs) #java.options=-d64 -Xmx1g # Use the G1 garbage collector stablized with jdk1.7.0_04, printing GC details #java.options=-d64 -Xmx4g -XX:+UseG1GC # Use a separate concurrent GC thread (java-1.6_14 or later) #java.options=-d64 -Xmx8g -XX:+UseConcMarkSweepGC # Verbose garbage collection #java.options=-verbos:gc -XX:+PrintGCDetails # Java 5 era (???) flag to GC class definitions #java.options=-XX:+CMSPermGenSweepingEnabled # The unloading of class definitions is a per jvm policy. For # implementations which run out of permgen space, the following should # help things out. #java.options=-d64 -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=1g # Enable assertions specified via the JVM contract # TODO move all use of org.armedbear.lisp.Debug assertions to this interface. #java.options=-ea ## ABCL Development # skips the compilation of Lisp sources in Netbeans # (for debugging compiler-pass1.lisp and subsequent passes) #abcl.compile.lisp.skip=true # JVM option to execute when debugging the Lisp compilation via 'abcl.compile.lisp.debug' # Debug the compilation by connecting a JVM debugger to localhost:6789 via JDWP. #abcl.compile.lisp.debug.jvmarg=-agentlib:jdwp=transport=dt_socket,server=y,address=6789,suspend=y abcl-src-1.9.0/abcl.rdf0100644 0000000 0000000 00000017722 14242627550 013354 0ustar000000000 0000000 # -*- Mode: n3 -*- @prefix abcl: . <> abcl:is "W3C Turtle RDF serializations format" . @prefix doap: . @prefix rdf: . @prefix rdfs: . <> a doap:Project . <> rdfs:seeAlso . <> rdfs:seeAlso . @prefix dc: . <> abcl:branch ; dc:identifier ; # deprecated? dc:identifier ; doap:language "Common Lisp" ; dc:created "01-JAN-2004" ; dc:modified "25-MAY-2022" ; dc:version "abcl-1.9.0" ; # dc:release "dev" ; # uncomment when release is finished dc:release "rc-3" ; abcl:git ; abcl:git ; abcl:svn . <> rdfs:seeAlso ; rdfs:seeAlso ; rdfs:seeAlso ; rdfs:seeAlso . @prefix dc: . a doap:Project ; doap:label "Armed Bear Common Lisp" ; doap:download ; dc:abstract "An implementation of ANSI Common Lisp that runs on the JVM." ; doap:shortname "ABCL" ; abcl:contributors """ehu easye v-ille astalla rudi peter""" . doap:language "Common Lisp" . <> [ a rdf:Bag; rdf:_0 "Common Lisp"; rdf:_1 "Java"; rdf:_2 "Ant"; rdf:_3 "Bourne Shell Script"; rdf:_4 "Windows Batch Script" ] . dc:contributor [ a rdf:Bag; rdf:_1024 _:peter ; rdf:_2048 _:piso ; rdf:_1 _:ehu ; rdf:_2 _:easye ; rdf:_3 _:ville ; rdf:_4 _:astalla ; rdf:_5 _:rudi ; rdf:_11 _:ferada ; rdf:_11 _:olof ; rdf:_11 "Olof-Joachim Frahm" ; rdf:_7 _:cyrus ; rdf:_8 _:dmiles ; rdf:_9 _:alanr ; rdf:_9 "Alan Ruttenberg" ; rdf:_10 _:pipping ; rdf:_10 "Elias Pipping" ; rdf:_12 _:vibhu ; rdf:_12 "Vibhu Mohindra" ; rdf:_13 "somewhat-functional-programmer" ; rdf:_14 "Jonathan Cunningham"; rdf:_15 "Uthar"; rdf:_16 "alejandrozf"; rdf:_17 "phoe"; rdf:_18 "jackdaniel"; rdf:_19 "Robert Munyer"; rdf:_20 "contrapunctus"; rdf:_21 "Scott Burson"; rdf:_22 "Samuel Hunter"; rdf:_23 "Eric Timmons (daewok)"; rdf:_24 "Phil Eaton"; ] . doap:language "Common Lisp", "Java", "Ant", "Bourne Shell Script", "Windows Batch Script" . _:user dc:identifier ; rdf:label "V-ille" . rdfs:seeAlso . <> doap:license [ dc:license ; dc:license ; dc:licenseDocument ; ] . doap:Project rdfs:seeAlso [ a rdf:Bag; rdf:_0 ; rdf:_1 ; rdf:_2 ; rdf:_4 ; rdf:_5 ; dc:source abcl:tag ; dc:Software [ a rdf:Bag; rdf:_1 ; rdf:_2 ; rdf:_3 ; rdf:_4 ; rdf:_5 ; rdf:_6 ; rdf:_14 ; rdf:_7 ; rdf:_8 ; rdf:_9 ; rdf:_10 ; rdf:_11 ; rdf:_13 ; rdf:_17 ; rdf:_19 ; rdf:_23 ; rdf:_29 ; ] ; ] . <> abcl:provides ; rdfs:seeAlso . <> dc:Standard ; rdfs:seeAlso [ a rdf:Bag ; rdf:_1 ; rdf:_2 "ANSI+INCITS+226-1994+(R2004).pdf" ] ; dc:abstract "ANSI INCITS 226-1994 (R2004) American National Standard for Programming Language Common LISP (X3J13)" . <> rdfs:seeAlso . doap:Project rdfs:seeAlso , , , , , . <> doap:packages [ a rdf:Alt; rdf:_1 abcl:abcl ; rdf:_2 abcl:abcl-contrib ; rdf:_4 abcl:jss ; rdf:_5 abcl:jfli ; rdf:_6 abcl:abcl-asdf ; rdf:_7 abcl:jna ; rdf:_8 abcl:asdf-jar ; rdf:_9 abcl:quicklisp-abcl ; rdf:_10 abcl:abcl-introspect ; ] . abcl:jna dc:version "5.9.0" . abcl:asdf dc:version "3.3.5.7" . abcl:abcl-introspect rdfs:seeAlso . abcl:abcl-contrib rdfs:seeAlso . abcl:abcl-asdf rdfs:seeAlso . abcl:asdf-jar rdfs:seeAlso . abcl:jfli rdfs:seeAlso . abcl:jss rdfs:seeAlso . # FIXME: figure out the right way to specify these values ontologically @prefix java: . @prefix openjdk: . @prefix not.org: . [abcl:run _:supported] a rdf:Bag ; rdf:_6 openjdk:6 ; rdf:_7 openjdk:7 ; rdf:_8 openjdk:8 ; rdf:_11 openjdk:11 ; rdf:_13 openjdk:13 ; rdf:_14 openjdk:14 ; rdf:_15 openjdk:15 ; rdf:_16 openjdk:16 ; rdf:_17 openjdk:17 ; rdfs:comment "Compatible Java runtimes" . [abcl:run _:options] not.org:base "-XShowSettings:vm -DFile.encoding=UTF-8" ; openjdk:6 "-XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=1g -XX:+UseConcMarkSweepGC" ; openjdk:8 "-XX:+AggressiveOpts" ; openjdk:11 "-XX:CompileThreshold=10" ; openjdk:13 "-XX:CompileThreshold=10" ; openjdk:14 "-XX:CompileThreshold=10" ; openjdk:15 "-XX:CompileThreshold=10" ; openjdk:16 "-XX:CompileThreshold=10" ; openjdk:17 "-XX:CompileThreshold=10" ; rdfs:comment "Java platform runtime options" . [abcl:build _:options] not.org:target "1.8" ; # not.org:source "1.6" ; not.org:encoding "UTF-8" ; not.org:debug "true" ; rdfs:comment "Java build options" . [abcl:build _:supported] a rdf:Bag ; rdf:_6 openjdk:6 ; rdf:_6 not.org:deprecated ; rdf:_7 openjdk:7 ; rdf:_7 not.org:deprecated ; rdf:_8 openjdk:8 ; rdf:_8 not.org:deprecated ; rdf:_11 openjdk:11 ; rdf:_13 openjdk:13 ; rdf:_14 openjdk:14 ; rdf:_15 openjdk:15 ; rdf:_16 openjdk:16 ; rdf:_17 openjdk:17 ; rdfs:comment "Supported build platforms" . abcl-src-1.9.0/build.xml0100644 0000000 0000000 00000136675 14202767264 013613 0ustar000000000 0000000 Compiling, testing, and packaging Armed Bear Common Lisp Main Ant targets: abcl.wrapper -- [default] create executable wrapper for ABCL. abcl.compile -- compile ABCL to ${build.classes.dir}. abcl.jar -- create packaged ${abcl.jar.path}. abcl.source.zip abcl.source.tar -- create source distributions in ${dist.dir}. abcl.clean -- remove ABCL intermediate files For help on the automatic tests available, use the Ant target 'help.test'. Compiled ABCL with Java version: ${java.version} Cleaning all intermediate compilation artifacts. Setting 'abcl.build.incremental' enables incremental compilation. java.version: ${java.version} WARNING: Use of Java version ${java.version} not recommended. Notice: JSR-223 support won't be built since it is not supported, neither natively by your JVM nor by libraries in the CLASSPATH. Compiling Lisp system from ${abcl.home.dir} to ${abcl.lisp.output} Debugging with jvmarg ${abcl.compile.lisp.debug.jvmarg} abcl.version.svn: ${abcl.version.svn} ABCL implementation version: ${abcl.implementation.version} ${abcl.implementation.version} abcl.hostname: ${abcl.hostname}
Creates in-place executable shell wrapper in '${abcl.wrapper.file}' Created executable ABCL wrapper in '${abcl.wrapper.file}' N.B. This wrapper requires '${abcl.jar.path}' not be moved. Packaged contribs in ${abcl-contrib.jar}. To use contribs, ensure that this file is in the same directory as 'abcl.jar', and then CL-USER> (require 'abcl-contrib) will place all the contribs in the ASDF registry. To load a contrib, something like CL-USER> (require 'jss) will compile (if necessary) and load JSS. Invoke ABCL with JPDA listener on port 6789 JPDA listening on localhost:6789 Invoke ABCL with JPDA listener on port 6789 JPDA listening on localhost:6789 Deleting ABCL SLIME fasls under ${slime.fasls} Deleting ABCL Quicklisp fasls under ${quicklisp.common-lisp.fasls} The following Ant targets run various test suites: abcl.test -- Run all available tests. abcl.test.java -- Run the ABCL junit Java tests under ${basedir}/test/src/ abcl.test.lisp -- Run the 'test.ansi.compiled', 'test.abcl', 'test.cl-bench' targets test.ansi.compiled -- Run the compiled version of the ANSI test suite test.abcl -- Run the Lisp RT tests collected in ${basedir}/test/lisp/abcl/ test.cl-bench -- Run the cl-bench test suite. The ANSI tests require that the [ANSI tests][1] be manually installed in ${basedir}/../ansi-test/. [1]: git+https://gitlab.common-lisp.net/ansi-test/ansi-test.git The CL-BENCH tests require that [cl-bench][2] be manually installed in ${basedir}/../cl-bench [2]: http://www.chez.com/emarsden/downloads/cl-bench.tar.gz Installing Maven for ABCL from ${maven.dist.uri}. Recording test output in ${abcl.test.log.file}. Finished recording test output in ${abcl.test.log.file}. Recording test output in ${abcl.test.log.file}. Finished recording test output in ${abcl.test.log.file}. Recording test output in ${abcl.test.log.file}. Finished recording test output in ${abcl.test.log.file}. Recording test output in ${abcl.test.log.file}. Finished recording test output in ${abcl.test.log.file}. JVM System Properties ===================== :java.version ${java.version} :java.vendor ${java.vendor} :java.vm.vendor ${java.vm.vendor} :java.vm.name ${java.vm.name} :os.name ${os.name} :os.arch ${os.arch} :os.version ${os.version} :java.specification.version ${java.specification.version} :java.vm.specification.version ${java.vm.specification.version} This target requires 'make' and a LaTeX installation to be on the PATH. This target requires 'texi2pdf' to be on the PATH.
abcl-src-1.9.0/ci/asdf-finds-abcl.bash0100644 0000000 0000000 00000000312 14202767264 016113 0ustar000000000 0000000 #!/usr/bin/env bash DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" dest=$HOME/.config/common-lisp/source-registry.conf.d mkdir -p $dest echo "(:tree \""${ABCL_ROOT}"\")" > ${dest}/abcl.conf abcl-src-1.9.0/ci/create-abcl-properties.awk0100644 0000000 0000000 00000000310 14202767264 017375 0ustar000000000 0000000 /^java.options/ {print $0 " " options; next} /ant.build.javac.target/ {print "ant.build.javac.target=" target; next} /ant.build.javac.source/ {print "ant.build.javac.source=" source; next} {print $0} abcl-src-1.9.0/ci/create-abcl-properties.bash0100644 0000000 0000000 00000004041 14202767264 017535 0ustar000000000 0000000 #!/usr/bin/env bash DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" jdk=$1 if [[ -z $jdk ]]; then jdk=openjdk8 fi root="${DIR}/.." prop_in="${root}/abcl.properties.in" prop_out="${root}/abcl.properties" echo "Configuring for $jdk from <${prop_in}>." # Unused # zgc="-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx -Xlog:gc" abcl_javac_source=1.8 case $jdk in 6|openjdk6) options="-d64 -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=1g -XX:+UseConcMarkSweepGC" ant_build_javac_target=1.6 ant_build_javac_source=1.6 ;; 7|openjdk7) options="-d64 -XX:+UseG1GC" ant_build_javac_target=1.7 ant_build_javac_source=1.7 ;; 8|openjdk8) options="-XX:+UseG1GC -XX:+AggressiveOpts -XX:CompileThreshold=10" ant_build_javac_target=1.8 ant_build_javac_source=1.8 ;; 11|openjdk11) options="-XX:CompileThreshold=10" ant_build_javac_target=11 ant_build_javac_source=1.8 ;; # untested: weakly unsupported 12|openjdk12) options="-XX:CompileThreshold=10" ant_build_javac_target=12 ant_build_javac_source=1.8 ;; 13|openjdk13) options="-XX:CompileThreshold=10" ant_build_javac_target=13 ant_build_javac_source=1.8 ;; 14|openjdk14) options="-XX:CompileThreshold=10 ${zgc}" ant_build_javac_target=14 ant_build_javac_source=1.8 ;; 15|openjdk15) options="-XX:CompileThreshold=10 ${zgc}" ant_build_javac_target=15 ant_build_javac_source=1.8 ;; 16|openjdk16) options="-XX:CompileThreshold=10 ${zgc}" ant_build_javac_target=16 ant_build_javac_source=1.8 ;; 17|openjdk17) options="-XX:CompileThreshold=10 ${zgc}" ant_build_javac_target=17 ant_build_javac_source=1.8 ;; esac cat ${root}/abcl.properties.in \ | awk -F = \ -v options="$options" \ -v target="$ant_build_javac_target" \ -v source="$ant_build_javac_source" \ -f ${DIR}/create-abcl-properties.awk \ > ${root}/abcl.properties echo "Finished configuring for $jdk into <${prop_out}>." abcl-src-1.9.0/ci/ensure-jenv-is-present.bash0100644 0000000 0000000 00000000353 14202767264 017533 0ustar000000000 0000000 export JENV_ROOT=$HOME/.jenv if [[ $(echo $PATH | grep -c .jenv) -eq 0 ]]; then export PATH="$JENV_ROOT/bin:$PATH" fi eval "$(jenv init -)" eval "$(jenv enable-plugin export)" abcl-src-1.9.0/ci/install-ansi-test.bash0100644 0000000 0000000 00000000466 14202767264 016563 0ustar000000000 0000000 #!/usr/bin/env bash pushd ${ABCL_ROOT}/.. if [[ ! -r ansi-test ]]; then git clone https://gitlab.common-lisp.net/ansi-test/ansi-test else pushd ansi-test if [[ -r .hg ]]; then hg pull -u else git fetch fi popd fi pushd ansi-test git show-ref git rev-parse popd popd abcl-src-1.9.0/ci/install-cffi.bash0100644 0000000 0000000 00000000611 14202767264 015553 0ustar000000000 0000000 #!/usr/bin/env bash dir="cffi" uri="https://github.com/armedbear/${dir}" root="${HOME}/common-lisp" tag="abcl/easye-20200602a" mkdir -p ${root} pushd ${root} if [[ ! -d ${dir} ]]; then git clone ${uri} ${dir} fi pushd ${dir} if [[ -d .hg ]]; then hg pull hg update -r $tag hg sum -v else git pull git checkout $tag git show-ref git rev-parse fi popd popd abcl-src-1.9.0/ci/install-cl+ssl.bash0100644 0000000 0000000 00000000574 14202767264 016047 0ustar000000000 0000000 #!/usr/bin/env bash dir="cl-plus-ssl" uri="https://github.com/armedbear/${dir}" root="${HOME}/common-lisp" tag="easye/stream-fd-20200603a" mkdir -p ${root} pushd ${root} if [[ ! -d ${dir} ]]; then git clone ${uri} ${dir} fi pushd ${dir} if [[ -d .hg ]]; then hg update -r $tag hg sum -v else git checkout $tag git show-ref git rev-parse fi popd popd abcl-src-1.9.0/ci/install-jeannie.bash0100644 0000000 0000000 00000000572 14202767264 016263 0ustar000000000 0000000 #!/usr/bin/env bash dir="jeannie" uri="https://github.com/easye/${dir}" root="${HOME}/common-lisp" tag="master" mkdir -p ${root} pushd ${root} if [[ ! -d ${dir} ]]; then git clone ${uri} ${dir} fi pushd ${dir} if [[ -d .hg ]]; then hg pull hg update -r $tag hg sum -v else git pull git checkout $tag git show-ref git rev-parse fi popd popd abcl-src-1.9.0/ci/install-jenv.bash0100644 0000000 0000000 00000000474 14202767264 015615 0ustar000000000 0000000 #!/usr/bin/env bash DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" target=~/.jenv if [[ ! -r "${target}" ]]; then git clone https://github.com/jenv/jenv.git "${target}" fi . ${DIR}/ensure-jenv-is-present.bash jenv enable-plugin ant jenv enable-plugin maven jenv enable-plugin export jenv doctor abcl-src-1.9.0/ci/install-openjdk.bash0100644 0000000 0000000 00000007724 14202767264 016312 0ustar000000000 0000000 #!/usr/bin/env bash DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" . ${DIR}/install-jenv.bash jdk=$1 if [[ -z $jdk ]]; then jdk=openjdk8 fi # empty variables are not necessary, but a hint that these are not # lexically scoped in their modification. topdir= dist= function determine_openjdk() { case $(uname) in Darwin) case $jdk in openjdk8) topdir=jdk8u302-b08 dist="https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u302-b08/OpenJDK8U-jdk_x64_mac_hotspot_8u302b08.tar.gz" ;; openjdk11) topdir=jdk-11.0.12+7 dist="https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.12%2B7/OpenJDK11U-jdk_x64_mac_hotspot_11.0.12_7.tar.gz" ;; openjdk14) # Need version from adoptium topdir=jdk-14.0.2+12 dist="https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.2%2B12/OpenJDK14U-jdk_x64_mac_hotspot_14.0.2_12.tar.gz" ;; openjdk15) # Need version from adoptium topdir=jdk-15+36 dist="https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15%2B36/OpenJDK15U-jdk_x64_mac_hotspot_15_36.tar.gz" ;; openjdk16) topdir=jdk-16.0.2+7 dist="https://github.com/adoptium/temurin16-binaries/releases/download/jdk-16.0.2%2B7/OpenJDK16U-jdk_x64_mac_hotspot_16.0.2_7.tar.gz" ;; openjdk17) topdir="jdk-17+35" dist="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17%2B35/OpenJDK17-jdk_x64_mac_hotspot_17_35.tar.gz" ;; esac ;; Linux) case $jdk in openjdk8) topdir=jdk8u302-b08 dist="https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u302-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u302b08.tar.gz" ;; openjdk11) topdir=jdk-11.0.8+10 dist="https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.8%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.8_10.tar.gz" ;; openjdk14) # Need version from adoptium topdir=jdk-14.0.2+12 dist="https://github.com/AdoptOpenJDK/openjdk14-binaries/releases/download/jdk-14.0.2%2B12/OpenJDK14U-jdk_x64_linux_hotspot_14.0.2_12.tar.gz" ;; openjdk15) # Need version from adoptium topdir=jdk-15+36 dist="https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15%2B36/OpenJDK15U-jdk_x64_linux_hotspot_15_36.tar.gz" ;; openjdk16) topdir=jdk-16.0.2+7 dist="https://github.com/adoptium/temurin16-binaries/releases/download/jdk-16.0.2%2B7/OpenJDK16U-jdk_x64_linux_hotspot_16.0.2_7.tar.gz" ;; openjdk17) topdir="jdk-17+35" dist="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17%2B35/OpenJDK17-jdk_x64_linux_hotspot_17_35.tar.gz" ;; esac ;; *) echo No known dist for $(uname) esac } tmpdir=/var/tmp function download_and_extract() { pushd ${tmpdir} && wget --continue ${dist} tar xvz -f $(basename ${dist}) popd } function add_jdk() { echo $dist echo $tmpdir case $(uname) in Darwin) jenv add ${tmpdir}/${topdir}/Contents/Home ;; Linux) jenv add ${tmpdir}/${topdir} ;; esac } determine_openjdk download_and_extract add_jdk . ${DIR}/set-jdk.bash jenv doctor abcl-src-1.9.0/ci/install-quicklisp.lisp0100644 0000000 0000000 00000000312 14202767264 016700 0ustar000000000 0000000 ;;; Install Quicklisp under ABCL via the QUICKLISP-ABCL contrib (require :asdf) (require :abcl-contrib) (asdf:load-system :quicklisp-abcl) (let ((ql-util::*do-not-prompt* t)) (ql:add-to-init-file)) abcl-src-1.9.0/ci/install-static-vectors.bash0100644 0000000 0000000 00000000635 14202767264 017624 0ustar000000000 0000000 #!/usr/bin/env bash dir="static-vectors" uri="https://github.com/armedbear/${dir}" root="${HOME}/quicklisp/common-lisp" tag="abcl/easye-20200603a" mkdir -p ${root} pushd ${root} if [[ ! -d ${dir} ]]; then git clone ${uri} ${dir} fi pushd ${dir} if [[ -d .hg ]]; then hg pull hg update -r $tag hg sum -v else git pull git checkout $tag git show-ref git rev-parse fi popd popd abcl-src-1.9.0/ci/release.lisp0100644 0000000 0000000 00000001443 14202767264 014656 0ustar000000000 0000000 (require :asdf) (require :abcl-contrib) (if (not (asdf:find-system :abcl-build)) (warn "Failed to find in ASDF to hash release.") (asdf:make :abcl-build)) (let ((root (uiop:getenv "ABCL_ROOT")) ant) (format *standard-output* "ABCL_ROOT='~a'~%" root) #+(or) ;;; needs TeXlive to render User Manual (abcl-build:with-ensured-ant (ant) (abcl-build:ant/call "build.xml" '("abcl.release" "abcl.wrapper"))) (let ((dist (concatenate 'string root "/dist/"))) (format *standard-output* "dist='~a'~%" dist) (multiple-value-bind (hashes report) (abcl-build:directory-hashes dist) (format *standard-output* report)))) abcl-src-1.9.0/ci/set-jdk.bash0100644 0000000 0000000 00000001550 14202767264 014544 0ustar000000000 0000000 function set_jdk() { abcl_jdk=$1 if [[ -z ${abcl_jdk} ]]; then abcl_jdk=openjdk8 fi dir=$2 if [[ -z ${dir} ]]; then dir=${ABCL_ROOT} fi . ${DIR}/ensure-jenv-is-present.bash jenv versions case ${abcl_jdk} in openjdk8) version=$(jenv versions | grep openjdk | grep 1.8 | tail -1 | sed s/*//) ;; openjdk11) version=$(jenv versions | grep openjdk | grep 11.0 | tail -1 | sed s/*//) ;; esac if [[ -z ${version} ]]; then version=$(jenv versions | tail -1 | sed s/*//) fi if [[ -z ${version} ]]; then version=1.8 fi pushd ${dir} jenv local ${version} # but practically we guard every invocation of jenv this way jenv global ${version} jenv version popd } set_jdk ${ABCL_JDK} ${ABCL_ROOT} abcl-src-1.9.0/ci/test-abcl-introspect.lisp0100644 0000000 0000000 00000000124 14202767264 017277 0ustar000000000 0000000 (ql:quickload :abcl-introspect-test) (time (asdf:test-system :abcl-introspect)) abcl-src-1.9.0/ci/test-abcl-prove.lisp0100644 0000000 0000000 00000000105 14202767264 016237 0ustar000000000 0000000 (ql:quickload :abcl-prove) (time (asdf:test-system :abcl-prove)) abcl-src-1.9.0/ci/test-abcl.lisp0100644 0000000 0000000 00000000076 14202767264 015115 0ustar000000000 0000000 (require :asdf) (time (asdf:test-system :abcl/test/lisp)) abcl-src-1.9.0/ci/test-ansi.lisp0100644 0000000 0000000 00000000107 14202767264 015141 0ustar000000000 0000000 (require :asdf) (time (asdf:test-system :abcl/test/ansi/compiled)) abcl-src-1.9.0/ci/test-cffi.lisp0100644 0000000 0000000 00000000164 14202767264 015121 0ustar000000000 0000000 (require :asdf) (require :abcl-contrib) (ql:quickload '(:cffi :cffi-tests)) (time (asdf:test-system :cffi)) abcl-src-1.9.0/ci/test-cl+ssl.lisp0100644 0000000 0000000 00000000206 14202767264 015402 0ustar000000000 0000000 #+abcl (progn (require :asdf) (require :abcl-contrib)) (ql:quickload '(:cl+ssl :cl+ssl.test)) (time (fiveam:run-all-tests)) abcl-src-1.9.0/ci/test-ironclad.lisp0100644 0000000 0000000 00000000125 14202767264 016002 0ustar000000000 0000000 (ql:quickload '(:ironclad :ironclad/tests)) (time (asdf:test-system :ironclad)) abcl-src-1.9.0/ci/test-jeannie.lisp0100644 0000000 0000000 00000000302 14202767264 015615 0ustar000000000 0000000 ;;; Jeannie is not in Quicklisp: see ;;; But we possibly need to install dependencies from Quicklisp (ql:quickload :jeannie) (time (asdf:test-system :jeannie)) abcl-src-1.9.0/ci/test-static-vectors.lisp0100644 0000000 0000000 00000000217 14202767264 017163 0ustar000000000 0000000 (require :asdf) (require :abcl-contrib) (ql:quickload '(:static-vectors :static-vectors/test)) (time (asdf:test-system :static-vectors)) abcl-src-1.9.0/contrib/README.markdown0100644 0000000 0000000 00000006155 14202767264 016120 0ustar000000000 0000000 ABCL-CONTRIB ============ The contributions to Armed Bear constitute Common Lisp only code that is potentially useful for system construction and distribution. As such, these contributions have varying license terms which the end user needs to accept on her own terms. Please see the licensing metadata as expressed in the ASDF definitions for the status of your usage. quicklisp-abcl Loads and installs the Quicklisp library manager from the network if not locally present. abcl-asdf ABCL specific extensions to ASDF, including resolution of binary JVM artifacts cached from the network according to Maven metadata with the derived transitive relationships. asdf-jar Package ASDF system definitions into JVM artifacts for distribution jss A higher-order, more Lisp oriented interface for constructing Lisp interfaces to existing binary code libraries available for the JVM built on the primitives provided by the JAVA package. Used in the [lsw2][] Semantic Web package for dealing with OWL2 ontologies in RDF(S) and other notations. [lsw2]: https://github.com/alanruttenberg/lsw2/ jfli The "original" higher-order JVM interface descended from Rich Hickey's work on the JVM before Clojure. This implementation currently uses a fork of the public [JFLI][] API that uses the java interop of the ABCL JAVA package instead of the JNI interface. [jfli]: http://sourceforge.net/projects/jfli/ mvn A collection of various useful JVM artifacts downloaded and cached by the Aether Maven connector. Requires the maven-3.0.3 executable "mvn" (or "mvn.bat" under MSFT Windows) to be in the current processes's path. These artifacts load the binary artifacts necessary in the current JVM process, mvn currently includes: jna JNA provides an the ability to dynamically link to shared executables on the host platform, needed by CFFI. log4j An example of a dependency without an explicit version. abcl-introspect Advanced introspection of Java and Lisp runtime classes representation. abcl-build The ABCL build system plus associated utilities for manipulating external tools via UIOP. named-readtables (BSD Licensed) From : NAMED-READTABLES is a library that provides a namespace for readtables akin to the already-existing namespace of packages. In particular: - you can associate readtables with names, and retrieve readtables by names; - you can associate source files with readtable names, and be sure that the right readtable is active when compiling/loading the file; - similiarly, your development environment now has a chance to automatically determine what readtable should be active while processing source forms on interactive commands. (E.g. think of `C-c C-c` in Slime (yet to be done)) # Colophon Mark Created: 2011-09-11 Revised: 2017-06-11 <> abcl:documents . abcl-src-1.9.0/contrib/abcl-asdf/README.markdown0100644 0000000 0000000 00000014161 14202767264 017730 0ustar000000000 0000000 ABCL-ASDF ========= To use: CL-USER> (require :abcl-contrib) CL-USER> (require :abcl-asdf) ABCL specific contributions to ASDF system definition mainly concerned with finding JVM artifacts such as jar archives to be dynamically loaded. Example 1 --------- For the following ASDF definition stored in a file named "log4j.asd" that can be loaded: ;;;; -*- Mode: LISP -*- (in-package :asdf) (defsystem log4j :components ((:mvn "log4j/log4j/1.2.13"))) After issuing CL-USER> (asdf:make :log4j) all the Log4j libraries would be dynamically added to the classpath so that the following code would (let ((logger (#"getLogger" 'log4j.Logger (symbol-name (gensym))))) (#"trace" logger "Kilroy wuz here.")) output the message "Kilroy wuz here" to the Log4j logging system. API --- We define an API within the ASDF package consisting of the following ASDF classes derived from ASDF:COMPONENT: JAR-DIRECTORY, JAR-FILE, and CLASS-FILE-DIRECTORY for JVM artifacts that have a currently valid pathname representation (i.e. they exist on the local filesystem). The MVN and IRI classes descend from ASDF-COMPONENT, but do not directly have a filesystem location. The IRI component is currently unused, but serves as a point to base the inheritance of the MVN component while allowing other forms of uri-like resources to be encapsulated in the future. The MVN component should specify a [Maven URI][mvn-uri] as its PATH. A Maven URI has a namestring of the form "GROUP-ID/ARTIFACT-ID/VERSION" which specifies the dependency to be satisfied for this component by resolution through the Maven distributed dependency graph. The scheme (the initial "mvn://" in a Maven URI) is implied, and usually omitted for brevity. If a VERSION is not specified (i.e. by a namestring like "GROUP-ID/ARTIFACT-ID" for the MVN component), then the latest available version of the artifact will be retrieved from the network. [mvn-uri]: http://team.ops4j.org/wiki/display/paxurl/Mvn+Protocol The MVN component may specify a CLASSNAME which if present in the current jvm, inhibits further loading from the network. This may be used to bypass the invocation of Maven. Since classnames are not unique to jar archives, this mechanism may not have the desired result in all cases, but it is surpisingly, like the rest of Java, "good enough" for everyday use. The MVN component may specify an ALTERNATE-URI which will be added to the jvm classpath if Maven cannot be located. Since a Maven URI may refer to more than one binary artifact, this may not work in all cases. For use outside of ASDF, we currently define the generic function ABCL-ASDF:RESOLVE which locates, downloads, caches, and then loads into the currently executing JVM process all recursive dependencies annotated in the ditributed Maven pom.xml graph. One can muffle the verbosity of the Maven Aether resolver by setting CL:*load-VERBOSE* to NIL. Example 2 --------- Bypassing ASDF, one can directly issue requests for the Maven artifacts to be downloaded CL-USER> (abcl-asdf:resolve "com.google.gwt:gwt-user") WARNING: Using LATEST for unspecified version. "/Users/evenson/.m2/repository/com/google/gwt/gwt-user/2.4.0-rc1/gwt-user-2.4.0-rc1.jar:/Users/evenson/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar:/Users/evenson/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA-sources.jar" Notice that all recursive dependencies have been located and installed as well. ABCL-ASDF:RESOLVE does not added the resolved dependencies to the current JVM classpath. Use JAVA:ADD-TO-CLASSPATH as follows to do that: CL-USER> (java:add-to-classpath (abcl-asdf:as-classpath (abcl-asdf:resolve "com.google.gwt:gwt-user"))) Example 3 --------- For a filesystem of jar archives: ./lib/ext/flora2-reasoner/XSBFlora.jar ./lib/ext/iris-reasoner/iris/iris-0.58.jar ./lib/ext/iris-reasoner/jgrapht/jgrapht-jdk1.5-0.7.1.jar ./lib/ext/log4j/log4j-1.2.14.jar ./lib/ext/mandrax-reasoner/commons-collections-2.1.jar ./lib/ext/mandrax-reasoner/jdom-b10.jar ./lib/ext/mandrax-reasoner/log4j-1.2.8.jar ./lib/ext/mandrax-reasoner/mandarax-3.4.jar ./lib/ext/mins-reasoner/mins-v0_3.jar ./lib/ext/pellet-reasoner/aterm/1.6/aterm-java-1.6.jar ./lib/ext/pellet-reasoner/commons-logging/1.1/commons-logging-1.1.jar ./lib/ext/pellet-reasoner/kaon/1.2.9/rdfapi.jar ./lib/ext/pellet-reasoner/owl-api/1.4.3/abstractparser.jar ./lib/ext/pellet-reasoner/owl-api/1.4.3/io.jar ./lib/ext/pellet-reasoner/owl-api/1.4.3/rdfparser.jar ./lib/ext/pellet-reasoner/owl-api/1.4.3/validation.jar ./lib/ext/pellet-reasoner/owl-api/owl-api-econn/2006-04-27/api.jar ./lib/ext/pellet-reasoner/owl-api/owl-api-econn/2006-04-27/impl.jar ./lib/ext/pellet-reasoner/pellet/pellet.jar ./lib/ext/pellet-reasoner/relaxng/1.0/relaxngDatatype.jar ./lib/ext/pellet-reasoner/xsdlib/xsdlib.jar ./lib/ext/wsmo/WSML-grammar-20081202.jar ./lib/ext/wsmo/wsmo-api-0.6.2.jar ./lib/ext/wsmo/wsmo4j-0.6.2.jar ./lib/ext/xsb-system/interprolog.jar The following ASDF defintion loads enough JVM artifacts to use the [IRIS reasoner][iris-reasoner]: (defsystem :wsml2reasoner-jars :version "0.6.4" ;; last sync with SVN :defsystem-depends-on (abcl-contrib abcl-asdf) :components ((:module wsml2reasoner :pathname "lib/" :components ((:jar-file "wsml2reasoner"))) (:module iris-libs :pathname "lib/ext/iris-reasoner/iris/" :components ((:jar-file "iris-0.58"))) (:module jgrapht-libs :pathname "lib/ext/iris-reasoner/jgrapht/" :components ((:jar-file "jgrapht-jdk1.5-0.7.1"))) (:module wsmo-libs :pathname "lib/ext/wsmo/" :components ((:jar-file "WSML-grammar-20081202") (:jar-file "wsmo-api-0.6.2") (:jar-file "wsmo4j-0.6.2"))) (:module log4j-libs :pathname "lib/ext/log4j/" :components ((:jar-file "log4j-1.2.14"))))) [iris-reasoner]: http://www.iris-reasoner.org/ #### Colophon Mark Created: 2011-01-01 Revised: 2017-06-13 abcl-src-1.9.0/contrib/abcl-asdf/abcl-asdf-tests.asd0100644 0000000 0000000 00000001216 14242627550 020666 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem abcl-asdf-tests :author "Mark Evenson" :long-description "" :version "2.1.0" :defsystem-depends-on (prove-asdf) :depends-on (abcl-asdf prove) :components ((:module tests :pathname "t/" :components ((:test-file "log4j") (:test-file "resolve") (:test-file "resolve-multiple-maven-dependencies") (:test-file "maven")))) :perform (asdf:test-op (op c) (uiop:symbol-call :prove-asdf 'run-test-system c))) abcl-src-1.9.0/contrib/abcl-asdf/abcl-asdf.asd0100644 0000000 0000000 00000001427 14242627550 017532 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem abcl-asdf :author "Mark Evenson" :description "Extensions to ASDF for handling Java binary artifacts." :long-description "" :version "2.1.0" :depends-on (jss abcl-build) :components ((:module package :pathname "" :components ((:file "package"))) (:module base :pathname "" :components ((:file "abcl-asdf") (:file "asdf-jar" :depends-on ("abcl-asdf"))) :depends-on (package maven)) (:module maven :pathname "" :components ((:file "maven") (:file "mvn-module")) :depends-on (package))) :in-order-to ((test-op (test-op abcl-asdf-tests)))) abcl-src-1.9.0/contrib/abcl-asdf/abcl-asdf.lisp0100644 0000000 0000000 00000015414 14202767264 017736 0ustar000000000 0000000 ;;;; The ABCL specific overrides in ASDF. ;;;; ;;;; Extensions to ASDF for use by ABCL (require :asdf) (in-package :asdf) (defclass iri (component) ((schema :initform nil) (authority :initform nil) (path :initform nil) (query :initform nil) (fragment :initform nil))) (defclass mvn (iri) ((group-id :initarg :group-id :initform nil) (artifact-id :initarg :artifact-id :initform nil) (repositories :initarg :repositories :initform (list abcl-asdf::*default-repository*)) (resolved-classpath :initform nil :accessor resolved-classpath) (classname :initarg :classname :initform nil) (alternate-uri :initarg :alternate-uri :initform nil) ;; inherited from ASDF:COMPONENT ??? what are the CL semantics on overriding -- ME 2012-04-01 #+nil (version :initform nil))) (defmethod shared-initialize ((mvn mvn) slot-names &rest initargs &key (repository NIL repository-p) repositories &allow-other-keys) (if repository-p (let ((initargs (list* :repositories (cons repository repositories) (remove-plist-keys '(:repository :repositories) initargs)))) (apply #'call-next-method mvn slot-names initargs)) (call-next-method))) ;;; We intercept compilation to ensure that load-op will succeed (defmethod perform ((op compile-op) (c mvn)) (unless (resolved-classpath c) (setf (resolved-classpath c) (abcl-asdf:resolve (ensure-parsed-mvn c))))) (defmethod perform ((operation load-op) (c mvn)) (let ((resolved-classpath (resolved-classpath c))) (when (stringp resolved-classpath) (java:add-to-classpath (abcl-asdf:as-classpath resolved-classpath))))) ;;; A Maven URI has the form "mvn:group-id/artifact-id/version" ;;; ;;; Sometimes people write "group-id:artifact-id:version" to refer to ;;; Maven artifacts. One can use ABCL-ASDF:RESOLVE directly for ;;; serialized references to artifacts of this form. ;;; ;;; Currently we "stuff" the group-id/artifact-id into the 'name' and ;;; use the component 'version' for the version. Parts of ASDF ;;; *reallY* want ASDF:VERSION to be a triple of intergers, and never ;;; anything more, so that is part of the motivation behind this effort. (defparameter *mvn-repositories* nil "A list of all Maven repositories encountered in the lifetime of this instance of the implementation.") #+nil (defmethod slot-missing ((class mvn) object slot-name operation &optional new-value) (setf (slot-value object slot-name) (if new-value new-value nil))) (defun ensure-parsed-mvn (component) (with-slots (name group-id artifact-id version schema path repositories) component (when (null asdf::artifact-id) (let ((parsed (abcl-asdf::split-string name "/")) (asdf-version-p (slot-boundp component 'version)) (default-version "LATEST")) (cond ((= (length parsed) 3) (setf group-id (first parsed) artifact-id (second parsed) version (third parsed))) ((= (length parsed) 2) (setf group-id (first parsed) artifact-id (second parsed) version (if asdf-version-p version default-version))) (t (error "Failed to construct a mvn reference from name '~A' and version '~A'" name version))) (setf schema "mvn") (when repositories (setf *mvn-repositories* (union repositories *mvn-repositories* :test #'string=))) ;;; Always set path to normalized path "on the way out" to ;;; contain group-id/artifact-id/version ;;; TODO? record repository as well in path of component (setf path (format nil "~A/~A/~A" group-id artifact-id version)))) component)) (eval-when (:compile-toplevel :load-toplevel :execute) (export `(mvn iri ensure-parsed-mvn group-id artifact-id version) 'asdf)) (defmethod source-file-type ((component iri) (system system)) nil) (defmethod component-relative-pathname ((component iri)) nil) (in-package #:abcl-asdf) (defgeneric resolve (something) (:documentation "Returns a string in JVM CLASSPATH format as entries delimited by classpath separator string.")) (defmethod resolve ((mvn-component asdf::mvn)) "Resolve all runtime dependencies of MVN-COMPONENT. Returns either a string in jvm classpath format as entries delimited by classpath separator string or T. If the value T is returned, it denotes that current JVM already has already loaded a given class. Can possibly be a single entry denoting a remote binary artifact." (asdf::ensure-parsed-mvn mvn-component) (let ((name (slot-value mvn-component 'asdf::name)) (group-id (slot-value mvn-component 'asdf::group-id)) (artifact-id (slot-value mvn-component 'asdf::artifact-id)) (classname (slot-value mvn-component 'asdf::classname)) (alternate-uri (slot-value mvn-component 'asdf::alternate-uri)) (repositories (slot-value mvn-component 'asdf::repositories)) (version (if (slot-value mvn-component 'asdf::version) (slot-value mvn-component 'asdf::version) "LATEST"))) (handler-case (when (and classname (let ((jss:*muffle-warnings* T)) (jss:find-java-class classname))) (warn "Not loading ~A from the network because ~A is present in classpath." name classname) (return-from resolve t)) (java:java-exception (e) (unless (java:jinstance-of-p (java:java-exception-cause e) "java.lang.ClassNotFoundException") (error "Unexpected Java exception~&~A.~&" e)))) (let ((result (ignore-errors (with-aether () (resolve-dependencies group-id artifact-id :version version :repository NIL :repositories repositories))))) (if result result ;; The alternate-uri facility doesn't currently work. ;; It would only work if there is a single jar that ;; corresponds to a dependency, which is often not the case. ;; probably should just remove… (if alternate-uri (values (pathname alternate-uri) alternate-uri) (error "Failed to resolve MVN component name ~A." name)))))) (defmethod resolve ((uri pathname)) (warn "Unimplemented.")) (defun as-classpath (classpath) "Break apart the JVM CLASSPATH string into a list of its consituents." (split-string classpath (java:jfield "java.io.File" "pathSeparator"))) abcl-src-1.9.0/contrib/abcl-asdf/asdf-jar.lisp0100644 0000000 0000000 00000010267 14202767264 017612 0ustar000000000 0000000 (in-package :abcl-asdf) (defvar *added-to-classpath* nil) (defvar *inhibit-add-to-classpath* nil) (defun add-directory-jars-to-class-path (directory recursive-p) (loop :for jar :in (if recursive-p (all-jars-below directory) (directory (merge-pathnames "*.jar" directory))) :do (java:add-to-classpath jar))) (defun all-jars-below (directory) (loop :with q = (system:list-directory directory) :while q :for top = (pop q) :if (null (pathname-name top)) :do (setq q (append q (all-jars-below top))) :if (equal (pathname-type top) "jar") :collect top)) (defun need-to-add-directory-jar? (directory recursive-p) (loop :for jar :in (if recursive-p (all-jars-below directory) (directory (merge-pathnames "*.jar" directory))) :doing (if (not (member (namestring (truename jar)) *added-to-classpath* :test 'equal)) (return-from need-to-add-directory-jar? t))) nil) (defmethod java:add-to-classpath :around ((uri-or-uris t) &optional classloader) (declare (ignore classloader)) (call-next-method) (if (listp uri-or-uris) (dolist (uri uri-or-uris) (pushnew uri *added-to-classpath*)) (pushnew uri-or-uris *added-to-classpath*))) (in-package :asdf) (defclass jar-directory (static-file) ()) (defmethod perform ((operation compile-op) (c jar-directory)) (unless abcl-asdf:*inhibit-add-to-classpath* (abcl-asdf:add-directory-jars-to-class-path (truename (component-pathname c)) t))) (defmethod perform ((operation load-op) (c jar-directory)) (unless abcl-asdf:*inhibit-add-to-classpath* (abcl-asdf:add-directory-jars-to-class-path (truename (component-pathname c)) t))) (defmethod operation-done-p ((operation load-op) (c jar-directory)) (or abcl-asdf:*inhibit-add-to-classpath* (not (abcl-asdf:need-to-add-directory-jar? (component-pathname c) t)))) (defmethod operation-done-p ((operation compile-op) (c jar-directory)) t) (defclass jar-file (static-file) ((type :initform "jar"))) (defmethod perform ((operation compile-op) (c jar-file)) (java:add-to-classpath (component-pathname c))) (defmethod perform ((operation load-op) (c jar-file)) (or abcl-asdf:*inhibit-add-to-classpath* (java:add-to-classpath (component-pathname c)))) ;;; The original JSS specified jar pathnames as having a NAME ending ;;; in ".jar" without a TYPE. If we encounter such a definition, we ;;; clean it up. (defmethod normalize-jar-name ((component jar-file)) (when (#"endsWith" (slot-value component 'name) ".jar") (with-slots (name absolute-pathname) component (let* ((new-name (subseq name 0 (- (length name) 4))) (new-absolute-pathname (make-pathname :defaults absolute-pathname :name new-name))) (setf name new-name absolute-pathname new-absolute-pathname))))) (defmethod perform :before ((operation compile-op) (c jar-file)) (normalize-jar-name c)) (defmethod perform :before ((operation load-op) (c jar-file)) (normalize-jar-name c)) (defmethod operation-done-p :before ((operation load-op) (c jar-file)) (normalize-jar-name c)) (defmethod operation-done-p ((operation load-op) (c jar-file)) (or abcl-asdf:*inhibit-add-to-classpath* (member (namestring (truename (component-pathname c))) abcl-asdf:*added-to-classpath* :test 'equal))) (defmethod operation-done-p ((operation compile-op) (c jar-file)) t) (defclass class-file-directory (static-file) ()) (defmethod perform ((operation compile-op) (c class-file-directory)) (java:add-to-classpath (component-pathname c))) (defmethod perform ((operation load-op) (c class-file-directory)) (java:add-to-classpath (component-pathname c))) ;; a jar file where the pathname and name are relative to JAVA_HOME (defclass jdk-jar (jar-file) ()) (defmethod normalize-jar-name :after ((c jdk-jar)) (setf (slot-value c 'absolute-pathname) (merge-pathnames (merge-pathnames (slot-value c 'name) (make-pathname :directory `(:relative ,(slot-value (component-parent c) 'relative-pathname)))) (java::jstatic "getProperty" "java.lang.System" "java.home")))) abcl-src-1.9.0/contrib/abcl-asdf/asdf-mvn-module-tests.asd0100644 0000000 0000000 00000000536 14202767264 022057 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem asdf-mvn-module-tests :defsystem-depends-on (prove-asdf) :depends-on (prove asdf-mvn-module) :components ((:module tests :pathname "t/" :components ((:file "mvn-module")))) :perform (asdf:test-op (op c) (uiop:symbol-call :prove-asdf 'run-test-system c))) abcl-src-1.9.0/contrib/abcl-asdf/asdf-mvn-module.asd0100644 0000000 0000000 00000001022 14242627550 020703 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem asdf-mvn-module :author "Alan Ruttenberg" :version "1.0.0" :depends-on (jss abcl-asdf) :description "Handles Maven artifact exclusions via the ADSF:MVN-MODULE component." :long-description "" :version "1.0.0" :in-order-to ((test-op (test-op asdf-mvn-module-tests))) :components ((:module source :pathname "" :components ((:file "asdf-mvn-module"))))) abcl-src-1.9.0/contrib/abcl-asdf/asdf-mvn-module.lisp0100644 0000000 0000000 00000002654 14202767264 021122 0ustar000000000 0000000 (in-package :asdf) ;; dependencies: a list of maven artifacts. color or slash separated ;; components groupid:artifactid:versionid ;; managed-dependencies: a list of maven artifacts. If an dependency ;; with same groupid and artifactid are encountered, the version ;; specified here overrides. ;; exclusions: a list of partial maven artifacts ;; groupid:artifactid. Dependencies with same groupid and artifactid are ;; exluded (defclass mvn-module (component) ((depends :initarg :dependencies :initform nil :accessor mvn-module-depends) (excludes :initarg :exclusions :initform nil :accessor mvn-module-excludes) (managed :initarg :managed-dependencies :initform nil :accessor mvn-module-managed))) (defmethod component-children ((c mvn-module)) nil) ;;; ASDF problems: method is deprecated. How do we define MVN-MODULE, ;;; a subclass of ASDF:COMPONENT, which has no corresponding pathname? (defmethod source-file-type ((c mvn-module) (system parent-component)) :directory) (defmethod perform ((op compile-op) (c mvn-module))) (defmethod perform ((op prepare-op) (c mvn-module))) (defmethod perform ((operation load-op) (c mvn-module)) (loop for path in (abcl-asdf:resolve-multiple-maven-dependencies (mvn-module-depends c) (mvn-module-managed c) (mvn-module-excludes c)) do (unless (member path abcl-asdf::*added-to-classpath* :test 'equalp) (jss::add-to-classpath path)))) abcl-src-1.9.0/contrib/abcl-asdf/maven.lisp0100644 0000000 0000000 00000070031 14242624277 017224 0ustar000000000 0000000 ;;;; Use the Aether system packaged as jar files in a locally ;;;; installed Maven3 distribution to download and install JVM ;;;; artifact dependencies. #| # Implementation Not necessarily multi-threaded safe, and unclear how much work that would be, as it is unknown how the Maven implementation behaves. ## Installing Maven http://maven.apache.org/download.html ## Current Javadoc for Maven Aether connector http://sonatype.github.com/sonatype-aether/apidocs/overview-summary.html ## Incomplete, seemingly often wrong https://docs.sonatype.org/display/AETHER/Home Note that this is not an implementation of Maven per se, but the use of the Maven Aether connector infrastructure. Among other things, this means that the Maven specific "~/.m2/settings.xml" file is NOT parsed for settings. |# #| We aim to be compatible with the "current" version of Maven back to maven-3.0.4. The necessary internals of Maven are messy, and not very well abstracted, especially in the earlier releases. In maintaining this code over the past decade, it has been the case that entire APIs will disappear during what are advertised as "patchlevel" upgrades of Maven. |# ;;; N.b. evaluated *after* we load the ABCL specific modifications of ;;; ASDF in abcl-asdf.lisp (in-package :abcl-asdf) (require :abcl-contrib) (require :jss) #| Test: (abcl-asdf:resolve "org.slf4j:slf4j-api:1.6.1") (abcl-asdf:resolve "org.apache.maven:maven-aether-provider:3.0.4") (abcl-asdf:resolve "com.google.gwt:gwt-user") |# (defparameter *mavens* (if (find :windows *features*) '("mvn" "mvn.bat" "mvn.cmd" "mvn3.bat") '("mvn" "mvn3" ;; MacPorts "/opt/local/bin/mvn" "/opt/local/bin/mvn3")) "Locations to search for the Maven executable.") (defun find-mvn () "Attempt to find a suitable Maven ('mvn') executable on the hosting operating system. Returns the path of the Maven executable or nil if none are found. Returns the version of Maven found as the second value. Emits warnings if not able to find a suitable executable." (let ((m2-home (ext:getenv "M2_HOME")) (m2 (ext:getenv "M2")) (mvn-executable (if (find :unix *features*) "mvn" "mvn.bat"))) (when (and m2-home (probe-file m2-home)) (let* ((m2-home (truename m2-home)) (mvn-path (merge-pathnames (format nil "bin/~A" mvn-executable) m2-home)) (mvn (truename mvn-path))) (if mvn (values (return-from find-mvn mvn) (ensure-mvn-version)) (warn "M2_HOME was set to '~A' in the process environment but '~A' doesn't exist." m2-home mvn-path)))) (when (and m2 (probe-file m2)) (let* ((m2 (truename m2)) (mvn-path (merge-pathnames mvn-executable m2)) (mvn (truename mvn-path))) (if mvn (values (return-from find-mvn mvn) (ensure-mvn-version)) (warn "M2 was set to '~A' in the process environment but '~A' doesn't exist." m2 mvn-path)))) (let ((which-cmd (if (find :unix *features*) "which" ;; Starting with Windows Server 2003 "where.exe"))) (dolist (mvn-path *mavens*) (let ((mvn (handler-case (truename (string-trim '(#\space #\newline #\return #\tab) (uiop:run-program (format nil "~a ~a" which-cmd mvn-path) :output :string))) (t (e) (format cl:*load-verbose* "~&; abcl-asdf; Failed to find Maven executable '~a' in PATH because~%~a" mvn-path e))))) (when mvn (return-from find-mvn mvn))))) (warn "Unable to locate Maven executable to find Maven Aether adaptors."))) (defun find-mvn-libs () (unless (find-mvn) (warn "Failed to find Maven executable to determine Aether library location. Continuing anyways.")) (some (lambda (d) (when (and (pathnamep d) (directory (merge-pathnames "maven-core*.jar" d))) (truename d))) (list (ignore-errors (make-pathname :defaults (merge-pathnames "../lib/" (find-mvn)) :name nil :type nil)) (ignore-errors (make-pathname :defaults (merge-pathnames "lib/" (mvn-home)) :name nil :type nil)) ;; library location for homebrew maven package on OS X (ignore-errors (make-pathname :defaults (merge-pathnames "../libexec/lib/" (find-mvn)) :name nil :type nil)) #p"/usr/local/share/java/maven3/lib/" ;; FreeBSD ports #p"/usr/local/maven/lib/"))) ;; OpenBSD location suggested by Timo Myyrä (defparameter *mvn-libs-directory* nil "Location of 'maven-core-3..

.jar', 'maven-embedder-3..

.jar' etc.") (defun normalize-mvn-libs () "Ensure that any *mvn-libs-directory* is a both directory and a pathname" (unless *mvn-libs-directory* (return-from normalize-mvn-libs nil)) (when (not (pathnamep *mvn-libs-directory*)) (setf *mvn-libs-directory* (pathname *mvn-libs-directory*))) (when (not (#"endsWith" (namestring *mvn-libs-directory*) "/")) (setf *mvn-libs-directory* (pathname (concatenate 'string *mvn-libs-directory* "/")))) *mvn-libs-directory*) (defun mvn-version () "Return the version of Maven libaries in use" (unless (normalize-mvn-libs) (error "Need to specify a value of *mvn-libs-directory*")) (let* ((pattern "maven-core*.jar") (maven-core-jars (directory (merge-pathnames pattern *mvn-libs-directory*))) (maven-core-jar (cond ((= (length maven-core-jars) 0) (error "No file matching '~a' found in '~a'." pattern *mvn-libs-directory*)) ((> (length maven-core-jars) 1) (warn "More than one file matching '~a' found in '~a'." pattern *mvn-libs-directory*) (first maven-core-jars)) (t (first maven-core-jars))))) (let* ((manifest (#"getManifest" (jss:new 'java.util.jar.JarFile (namestring maven-core-jar)))) (attributes (#"getMainAttributes" manifest)) (version (#"getValue" attributes "Implementation-Version"))) (if version (parse-mvn-version version) (mvn-version-from-mvn-executable))))) ;;; deprecated, unused: we now get the version directly from the JAR manifest (defun mvn-version-from-mvn-executable () "Return the Maven version used by the Aether connector located by FIND-MVN as a list of (MAJOR MINOR PATHLEVEL) integers. Signals a simple-error with additional information if this attempt fails." (handler-case (let* ((mvn (truename (find-mvn))) (pattern (#"compile" 'regex.Pattern "^Apache Maven ([0-9]+\\.[0-9]+\\.[0-9]+)"))) (multiple-value-bind (output error) (uiop:run-program (format nil "~a --version" mvn) :output :string :error :string) (let ((matcher (#"matcher" pattern output))) (when (#"find" matcher) (return-from mvn-version-from-mvn-executable (parse-mvn-version (#"group" matcher 1))))) (when output (signal "No parseable Maven version found in ~a" output)) (signal "Invocation of Maven returned the error ~{~& ~A~}" error))) (t (e) (error "Failed to determine Maven version: ~A." e)))) (defun parse-mvn-version (version-string) (let* ((pattern (#"compile" 'regex.Pattern "([0-9]+)\\.([0-9]+)\\.([0-9]+)")) (matcher (#"matcher" pattern version-string))) (if (#"find" matcher) (mapcar #'parse-integer `(,(#"group" matcher 1) ,(#"group" matcher 2) ,(#"group" matcher 3))) (error "Failed to parse a MAJOR.MINOR.PATCHLEVEL version from '~a'" version-string)))) (defun mvn-home () "If the Maven executable can be invoked, introspect the value reported as Maven home." (handler-case (multiple-value-bind (output error-output status) (uiop:run-program (format nil "~a --version" (truename (find-mvn))) :output :string :error-output :string) (unless (zerop status) (error "Failed to invoke Maven executable to introspect library locations: ~a." error-output)) (let ((pattern (#"compile" 'regex.Pattern "Maven home: (.+)$"))) (with-input-from-string (s output) (do ((line (read-line s nil :eof) (read-line s nil :eof))) ((or (not line) (eq line :eof)) nil) (let ((matcher (#"matcher" pattern line))) (when (#"find" matcher) (return-from mvn-home (uiop/pathname:ensure-directory-pathname (#"group" matcher 1))))))))) (subprocess-error (e) (error "Failed to invoke Maven executable to introspect library locations: ~a." e)))) (defun ensure-mvn-version () "Return t if Maven version is 3.0.3 or greater." (let* ((version (mvn-version)) (major (first version)) (minor (second version)) (patch (third version))) (values (or (and (>= major 3) (>= minor 1)) (and (>= major 3) (>= minor 0) (>= patch 3))) (list major minor patch)))) (define-condition no-aether-maven-libs (error) ((locations :initarg :locations :initform nil :reader locations)) (:report (lambda (condition stream) (format stream "No Maven Aether libraries found locally in '~a'." (locations condition))))) (defparameter *init-p* nil "Whether we have successfully located the necessary Maven libraries") (defun init (&optional &key (force nil)) "Run the initialization strategy to bootstrap a Maven dependency node Set *MVN-LIBS-DIRECTORY* to an explicit value before running this function in order to bypass the dynamic introspection of the location of the mvn executable with an explicit value." (when force (setf *session* nil *repository-system* nil)) (unless (or force *mvn-libs-directory*) (setf *mvn-libs-directory* (find-mvn-libs))) (unless (and *mvn-libs-directory* (probe-file *mvn-libs-directory*)) ;; FIXME Remove warning; put message in restart (warn "Please obtain and install maven-3.0.3 or later locally from , then set ABCL-ASDF:*MVN-LIBS-DIRECTORY* to the directory containing maven-core-3.*.jar et. al.") (error (make-condition 'abcl-asdf::no-aether-maven-libs :locations (list *mvn-libs-directory*)))) (unless (ensure-mvn-version) (error "We need maven-3.0.3 or later.")) (add-directory-jars-to-class-path *mvn-libs-directory* nil) (setf *init-p* t)) ;;; The AETHER-DIRECTORY parameter is conceptually a little broken: ;;; because we can't "unload" jar files, we can't easily switch ;;; between Maven implementation at runtime. Maybe this would be ;;; possible with some sort of classloader chaining, but such effort ;;; is not currently deemed as worthwhile. Instead, to change Aether ;;; libraries, you'll have to restart ABCL. (defmacro with-aether ((&optional aether-directory) &body body) "Ensure that the code in BODY is executed with the Maven Aether libraries on the classpath" (if aether-directory `(let ((*mvn-libs-directory* ,aether-directory)) (init :force t) ,@body) `(progn (unless *init-p* (init)) ,@body))) (defun find-http-wagon () "Find an implementation of the object that provides access to http and https resources. Supposedly configurable with the java.net.protocols (c.f. reference maso2000 in the Manual.)" (handler-case ;; maven-3.0.4 (java:jnew "org.apache.maven.wagon.providers.http.HttpWagon") (error () ;; maven-3.0.3 reported as not working with all needed functionality (java:jnew "org.apache.maven.wagon.providers.http.LightweightHttpWagon")))) (defun make-wagon-provider () "Returns an implementation of the org.sonatype.aether.connector.wagon.WagonProvider contract The implementation is specified as Lisp closures. Currently, it only specializes the lookup() method if passed an 'http' or an 'https' role hint." (unless *init-p* (init)) (java:jinterface-implementation (#"getName" (or (ignore-errors ;; Maven 3.2.5+ (jss:find-java-class 'aether.transport.wagon.WagonProvider)) (ignore-errors ;; Maven 3.1.0+ (jss:find-java-class 'aether.connector.wagon.WagonProvider)) (ignore-errors ;; Maven 3.0.x (jss:find-java-class 'org.sonatype.aether.connector.wagon.WagonProvider)))) "lookup" (lambda (role-hint) (cond ((find role-hint '("http" "https") :test #'string-equal) (find-http-wagon)) (t (progn (format cl:*load-verbose* "~&; abcl-asdf; WagonProvider stub passed '~A' as a hint it couldn't satisfy.~%" role-hint) java:+null+)))) "release" (lambda (wagon) (declare (ignore wagon))))) (defun find-service-locator () (or (ignore-errors ;; maven-3.0.4 (jss:new "org.apache.maven.repository.internal.MavenServiceLocator")) (ignore-errors ;; maven-3.1.0 using org.eclipse.aether... (jss:new "aether.impl.DefaultServiceLocator")) (ignore-errors (jss:new "org.apache.maven.repository.internal.DefaultServiceLocator")) (ignore-errors ;; maven-3.1.0 (#"newServiceLocator" 'org.apache.maven.repository.internal.MavenRepositorySystemUtils)))) (defun make-repository-system () (unless *init-p* (init)) (let ((locator (find-service-locator)) (wagon-provider-class (or (ignore-errors (java:jclass "org.sonatype.aether.connector.wagon.WagonProvider")) (ignore-errors ;; Maven-3.3.x (jss:find-java-class 'connector.transport.TransporterFactory)) (ignore-errors ;; Maven-3.2.5 (jss:find-java-class 'org.eclipse.aether.transport.wagon.WagonProvider)) (ignore-errors ;; Maven-3.1.x (jss:find-java-class 'aether.connector.wagon.WagonProvider)))) (wagon-repository-connector-factory-class (or (ignore-errors (jss:find-java-class 'org.sonatype.aether.connector.wagon.WagonRepositoryConnectorFactory)) (ignore-errors (jss:find-java-class 'org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory)) (ignore-errors (java:jclass "org.sonatype.aether.connector.wagon.WagonRepositoryConnectorFactory")))) (repository-connector-factory-class (or (ignore-errors (jss:find-java-class 'aether.spi.connector.RepositoryConnectorFactory)) (ignore-errors (jss:find-java-class 'org.eclipse.aether.spi.connector.RepositoryConnectorFactory)) (ignore-errors (java:jclass "org.sonatype.aether.spi.connector.RepositoryConnectorFactory")))) (repository-system-class (or (ignore-errors (java:jclass "org.sonatype.aether.RepositorySystem")) (ignore-errors (jss:find-java-class 'org.eclipse.aether.RepositorySystem)) (ignore-errors (jss:find-java-class 'aether.RepositorySystem))))) (if (equal wagon-provider-class (ignore-errors (jss:find-java-class 'TransporterFactory))) ;;; Maven-3.3.3 (let ((wagon-transporter-factory (jss:new 'WagonTransporterFactory))) (#"setWagonProvider" wagon-transporter-factory (make-wagon-provider)) (#"setServices" locator wagon-provider-class (java:jarray-from-list (list wagon-transporter-factory)))) (#"setServices" locator wagon-provider-class (java:jarray-from-list (list (make-wagon-provider))))) (#"addService" locator repository-connector-factory-class wagon-repository-connector-factory-class) (values (#"getService" locator repository-system-class) locator))) (defun make-session (repository-system) "Construct a new aether.RepositorySystemSession from the specified REPOSITORY-SYSTEM." (with-aether () (let ((session (or (ignore-errors (java:jnew (jss:find-java-class "MavenRepositorySystemSession"))) (ignore-errors (#"newSession" 'org.apache.maven.repository.internal.MavenRepositorySystemUtils)))) (local-repository (make-local-repository))) (#"setLocalRepositoryManager" session (make-local-repository-manager repository-system local-repository session))))) (defun make-local-repository-manager (repository-system local-repository session) (or (ignore-errors (#"newLocalRepositoryManager" repository-system local-repository)) (ignore-errors ;; maven-3.1.0 (#"newLocalRepositoryManager" repository-system session local-repository)))) (defun make-local-repository () (java:jnew (or (ignore-errors (jss:find-java-class "org.sonatype.aether.repository.LocalRepository")) (ignore-errors (jss:find-java-class "org.eclipse.aether.repository.LocalRepository"))) (namestring (merge-pathnames ".m2/repository/" (user-homedir-pathname))))) (defparameter *maven-http-proxy* nil "A string containing the URI of an http proxy for Maven to use.") (defun make-proxy () "Return an aether.repository.Proxy instance initialized from *MAVEN-HTTP-PROXY*." (unless *maven-http-proxy* (warn "No proxy specified in *MAVEN-HTTP-PROXY*") (return-from make-proxy nil)) (let* ((p (pathname *maven-http-proxy*)) (scheme (ext:url-pathname-scheme p)) (authority (ext:url-pathname-authority p)) (host (if (search ":" authority) (subseq authority 0 (search ":" authority)) authority)) (port (when (search ":" authority) (parse-integer (subseq authority (1+ (search ":" authority)))))) ;; TODO allow specification of authentication (authentication java:+null+)) (or (ignore-errors (jss:new 'org.eclipse.aether.repository.Proxy scheme host port authentication)) (ignore-errors (jss:new 'org.sonatype.aether.repository.Proxy scheme host port authentication))))) (defparameter *repository-system* nil "The aether.RepositorySystem used by the Maeven Aether connector.") (defun ensure-repository-system (&key (force nil)) (when (or force (not *repository-system*)) (setf *repository-system* (make-repository-system))) *repository-system*) (defparameter *session* nil "Reference to the Maven RepositorySystemSession") (defun ensure-session (&key (force nil)) "Ensure that the RepositorySystemSession has been created. If *MAVEN-HTTP-PROXY* is non-nil, parse its value as the http proxy." (when (or force (not *session*)) (ensure-repository-system :force force) (setf *session* (make-session *repository-system*)) (#"setRepositoryListener" *session* (make-repository-listener)) (when *maven-http-proxy* (let ((proxy (make-proxy))) (#"add" (#"getProxySelector" *session*) proxy ;; A string specifying non proxy hosts, or null java:+null+)))) *session*) (defun make-artifact (artifact-string) "Return an instance of aether.artifact.DefaultArtifact initialized from ARTIFACT-STRING" (or (ignore-errors (jss:new "org.sonatype.aether.util.artifact.DefaultArtifact" artifact-string)) (ignore-errors (jss:new 'aether.artifact.DefaultArtifact artifact-string)))) (defun make-artifact-request () "Construct a new aether.resolution.ArtifactRequest." (or (ignore-errors (java:jnew (jss:find-java-class 'aether.resolution.ArtifactRequest))) (ignore-errors (java:jnew "org.sonatype.aether.resolution.ArtifactRequest")))) ;;; TODO change this to work on artifact strings like log4j:log4j:jar:1.2.16 (defun resolve-artifact (group-id artifact-id &key (version "LATEST" versionp)) "Resolve artifact to location on the local filesystem. Declared dependencies are not attempted to be located. If unspecified, the string \"LATEST\" will be used for the VERSION. Returns the Maven specific string for the artifact " (unless versionp (warn "Using LATEST for unspecified version.")) (unless *init-p* (init)) (let* ((artifact-string (format nil "~A:~A:~A" group-id artifact-id version)) (artifact (make-artifact artifact-string)) (artifact-request (make-artifact-request))) (#"setArtifact" artifact-request artifact) (#"addRepository" artifact-request (ensure-remote-repository)) (#"toString" (#"getFile" (#"getArtifact" (#"resolveArtifact" (ensure-repository-system) (ensure-session) artifact-request)))))) (defun make-remote-repository (id type url) (or (ignore-errors (jss:new 'org.sonatype.aether.repository.RemoteRepository id type url)) (ignore-errors (#"build" (jss:new "org.eclipse.aether.repository.RemoteRepository$Builder" id type url))))) (defvar *default-repository* "https://repo1.maven.org/maven2/" "URI of default remote Maven repository") (defun add-repository (repository) (ensure-remote-repository :repository repository)) (defparameter *maven-remote-repository* nil "Reference to remote repository used by the Maven Aether embedder.") (defun ensure-remote-repository (&key (force nil) (repository *default-repository* repository-p)) (unless *init-p* (init)) (when (or force repository-p (not *maven-remote-repository*)) (let ((r (make-remote-repository "central" "default" repository))) (when *maven-http-proxy* (#"setProxy" r (make-proxy))) (setf *maven-remote-repository* r))) *maven-remote-repository*) (defun resolve-dependencies (group-id artifact-id &key (version "LATEST" versionp) (repository *maven-remote-repository* repository-p) (repositories NIL repositories-p)) "Dynamically resolve Maven dependencies for item with GROUP-ID and ARTIFACT-ID optionally with a VERSION and a REPOSITORY. All recursive dependencies will be visited before resolution is successful. If unspecified, the string \"LATEST\" will be used for the VERSION. Returns a string containing the necessary jvm classpath entries packed in Java CLASSPATH representation." (unless *init-p* (init)) (unless versionp (warn "Using LATEST for unspecified version.")) (let* ((coords (format nil "~A:~A:~A" group-id artifact-id (if versionp version "LATEST"))) (artifact (make-artifact coords)) (dependency (make-dependency artifact)) (collect-request (or (ignore-errors (java:jnew (jss:find-java-class "org.sonatype.aether.collection.CollectRequest"))) (ignore-errors (java:jnew (jss:find-java-class "org.eclipse.aether.collection.CollectRequest")))))) (#"setRoot" collect-request dependency) (setf repositories-p (or repository-p repositories-p)) ;; Don't call addRepository if we explicitly specify a NIL repository (cond ((not repositories-p) (#"addRepository" collect-request (ensure-remote-repository))) (repository (if (stringp repository) (push repository repositories) (#"addRepository" collect-request repository)))) (dolist (repository repositories) (#"addRepository" collect-request (let ((r (make-remote-repository "central" "default" repository))) (when *maven-http-proxy* (#"setProxy" r (make-proxy))) r))) (let* ((collect-result (#"collectDependencies" (ensure-repository-system) (ensure-session) collect-request)) (node (#"getRoot" collect-result)) (dependency-request (or (ignore-errors ;;; pre Maven-3.3.x (java:jnew (jss:find-java-class "DependencyRequest") node java:+null+)) (ignore-errors (jss:new 'DependencyRequest)))) (nlg (java:jnew (jss:find-java-class "PreorderNodeListGenerator")))) (#"setRoot" dependency-request node) (#"resolveDependencies" (ensure-repository-system) (ensure-session) dependency-request) (#"accept" node nlg) (#"getClassPath" nlg)))) (defun make-dependency (artifact) (or (ignore-errors (java:jnew (jss:find-java-class 'org.sonatype.aether.graph.Dependency) artifact (java:jfield (jss:find-java-class "org.sonatype.aether.util.artifact.JavaScopes") "COMPILE"))) (ignore-errors (java:jnew (jss:find-java-class 'org.eclipse.aether.graph.Dependency) artifact (java:jfield (jss:find-java-class "org.eclipse.aether.util.artifact.JavaScopes") "COMPILE"))))) (defun make-repository-listener () (flet ((log (e) (format cl:*load-verbose* "~&; abcl-asdf; ~A~%" (#"toString" e)))) (java:jinterface-implementation (#"getName" (jss:find-java-class 'aether.RepositoryListener)) "artifactDeployed" #'log "artifactDeploying" #'log "artifactDescriptorInvalid" #'log "artifactDescriptorMissing" #'log "artifactDownloaded" #'log "artifactDownloading" #'log "artifactInstalled" #'log "artifactInstalling" #'log "artifactResolved" #'log "artifactResolving" #'log "metadataDeployed" #'log "metadataDeploying" #'log "metadataDownloaded" #'log "metadataDownloading" #'log "metadataInstalled" #'log "metadataInstalling" #'log "metadataInvalid" #'log "metadataResolved" #'log "metadataResolving" #'log))) (defmethod resolve ((string string)) "Resolve a colon separated GROUP-ID:ARTIFACT-ID[:VERSION] reference to a Maven artifact. Examples of artifact references: \"log4j:log4j:1.2.14\" for 'log4j-1.2.14.jar'. Resolving \"log4j:log4j\" would return the latest version of the artifact known to the distributed Maven pom.xml graph. Returns a string containing the necessary classpath entries for this artifact and all of its transitive dependencies." (let ((result (split-string string ":"))) (cond ((= (length result) 3) (resolve-dependencies (first result) (second result) :version (third result))) ((string= string "com.sun.jna:jna") (warn "Replacing request for no longer available com.sun.jna:jna with net.java.dev.jna:jna") (resolve-dependencies "net.java.dev.jna" "jna" :version "LATEST")) ((= (length result) 2) (resolve-dependencies (first result) (second result))) (t (destructuring-bind (group-id artifact-id &optional version repository) (abcl-build:split-string string "/") (setf result (apply #'resolve-dependencies group-id artifact-id (append (when version `(:version ,version)) (when repository `(:repository ,repository)))))))))) ;;; Currently the last file listed in ASDF (provide 'abcl-asdf) abcl-src-1.9.0/contrib/abcl-asdf/mvn-module.lisp0100644 0000000 0000000 00000006567 14202767264 020216 0ustar000000000 0000000 (in-package :abcl-asdf) ;;; ;;; If a artifact is root then its optional dependencies are ;; collected. If the same artifact is not root, then the optional ;;; dependencies are not collected. We don't need optionals since from ;;; our point of view we are the top pom and everything specified are ;;; dependencies ;;; Used by asdf-mvn-module. (defun resolve-multiple-maven-dependencies (dependencies &optional managed-dependencies exclusions (first-is-root nil)) "Return a list of jar file paths that satisfy dependencies dependencies: a list of maven artifacts. color or slash separated components groupid:artifactid:versionid managed-dependencies: a list of maven artifacts. If an dependency with same groupid and artifactid are encountered, the version specified here overrides. exclusions: a list of partial maven artifacts groupid:artifactid. Dependencies with same groupid and artifactid are exluded first-is-root: If the first dependency should include optional dependencies, set this to t. Usually not. " (with-aether (nil) (let ((collect-request (java:jnew (jss:find-java-class "CollectRequest"))) (exclusions-collection (jss:new 'java.util.HashSet)) (compile-scope (java:jfield (jss:find-java-class "JavaScopes") "COMPILE"))) (#"addRepository" collect-request (ensure-remote-repository)) (loop for e in exclusions for (groupid artifactid) = (abcl-build:split-string e #\:) ;; If i have scope be compile-scope it doesn't get excluded!! for exclusion = (jss:new 'aether.graph.Exclusion groupid artifactid "" "jar") do (#"add" exclusions-collection exclusion)) (loop for a in dependencies for artifact = (make-artifact (#"replaceAll" a "/" ":")) for dependency = (jss:new 'aether.graph.Dependency artifact compile-scope) do ;; setExclusions returns a new dependency. We have to use ;; that. That passed dependency i not modified! ;; http://grepcode.com/file/repo1.maven.org/maven2/org.eclipse.aether/aether-api/1.0.2.v0150114/org/eclipse/aether/graph/Dependency.java#Dependency.getOptional%28%29 ;; Nice of them to clearly document that :-/ (setq dependency (#"setExclusions" dependency exclusions-collection)) (if first-is-root (#"setRoot" collect-request dependency) (#"addDependency" collect-request dependency)) (setq first-is-root nil)) (loop for a in managed-dependencies for artifact = (make-artifact (#"replaceAll" a "/" ":")) for dependency = (jss:new 'aether.graph.Dependency artifact compile-scope) do (setq dependency (#"setExclusions" dependency exclusions-collection)) (#"addManagedDependency" collect-request dependency)) (let ((dependencies (#"collectDependencies" (ensure-repository-system) (ensure-session) collect-request)) (nodelist-generator (jss:new 'PreorderNodeListGenerator)) (dependency-request (jss:new 'DependencyRequest))) (#"setRoot" dependency-request (#"getRoot" dependencies)) (#"resolveDependencies" (ensure-repository-system) (ensure-session) dependency-request) (#"accept" (#"getRoot" dependencies) nodelist-generator) (abcl-build:split-string (#"getClassPath" nodelist-generator) #\:))))) abcl-src-1.9.0/contrib/abcl-asdf/package.lisp0100644 0000000 0000000 00000001310 14202767264 017503 0ustar000000000 0000000 (in-package :cl-user) (defpackage abcl-asdf (:use cl) (:import-from :abcl/build #:split-string) (:export ;;; Public API #:resolve ;; Configuring Maven #:with-aether #:ensure-mvn-version #:find-mvn #:mvn-version #:*mvn-directory* #:init ;;; "Internal" API #:resolve-dependencies #:resolve-artifact ;;;; Maven #:*mvn-libs-directory* #:*maven-http-proxy* #:*default-repository* #:make-remote-repository #:*maven-remote-repository* #:resolve-multiple-maven-dependencies #:as-classpath #:add-directory-jars-to-class-path #:need-to-add-directory-jar? #:*added-to-classpath* #:*inhibit-add-to-classpath*)) abcl-src-1.9.0/contrib/abcl-asdf/t/eg/soot-mixed-repositories.asd0100644 0000000 0000000 00000000554 14202767264 023374 0ustar000000000 0000000 (defsystem #:soot-mixed-repositories :defsystem-depends-on (#:jss #:abcl-asdf) :components ((:mvn "ca.mcgill.sable/soot/3.0.0-20170622.230711-112" :repository "http://repo1.maven.org/maven2/" :repositories ("https://soot-build.cs.uni-paderborn.de/nexus/repository/soot-snapshot/") :classname "soot.SootClass"))) abcl-src-1.9.0/contrib/abcl-asdf/t/eg/soot-only-repositories.asd0100644 0000000 0000000 00000000556 14202767264 023251 0ustar000000000 0000000 (defsystem #:soot-only-repositories :defsystem-depends-on (#:jss #:abcl-asdf) :components ((:mvn "ca.mcgill.sable/soot/3.0.0-20170622.230711-112" :repositories ("https://soot-build.cs.uni-paderborn.de/nexus/repository/soot-snapshot/" "http://repo1.maven.org/maven2/") :classname "soot.SootClass"))) abcl-src-1.9.0/contrib/abcl-asdf/t/eg/test-mvn-module.asd0100644 0000000 0000000 00000002433 14202767264 021615 0ustar000000000 0000000 ;;; From https://github.com/alanruttenberg/lsw2/blob/owlapiv4/owl2/owl2libs-mvn2.asd (defsystem test-mvn-module :description "Non-Lisp dependencies necessary for OWL to function." :defsystem-depends-on (asdf-mvn-module) :components ((:mvn-module maven :dependencies ("net.sourceforge.owlapi/pellet-cli-ignazio1977/2.4.0-ignazio1977" "org.semanticweb.elk/elk-owlapi/0.4.3" "net.sourceforge.owlapi/org.semanticweb.hermit/1.3.8.413" "net.sourceforge.owlapi/owlapi-distribution/4.2.6" "net.sourceforge.owlapi/owlexplanation/2.0.0" "de.sciss/prefuse-core/1.0.1" "de.sciss/prefuse-demos/1.0.1") :managed-dependencies ("org.slf4j/slf4j-api/1.7.21" "net.sourceforge.owlapi:owlapi-distribution:4.2.6") :exclusions ("net.sourceforge.owlapi:owlapi-osgidistribution" "edu.stanford.protege:org.protege.editor.owl")) #+(or) (:module rest :pathname "lib" :components ((:bundle "uk.ac.manchester.cs.owl.factplusplus-1.6.5") (:jar-file "LSWTreeview-1.0.0") (:jar-file "QuotedStringAnnotationVisitor-1.0.0"))) (:module lib :pathname "lib" :depends-on (maven #+(or) rest))) :perform (load-op :after (o c) (progn (#"configure" 'org.apache.log4j.BasicConfigurator (jss::new 'NullAppender)) (print "configured log4j")))) abcl-src-1.9.0/contrib/abcl-asdf/t/log4j.lisp0100644 0000000 0000000 00000001222 14202767264 017374 0ustar000000000 0000000 (in-package :cl-user) (prove:diag "Output a message to the Console. Note: for users of SLIME, this will appear in the associated *inferior-lisp* buffer.") (prove:plan 2) (progn (when (find "log4j" (asdf:already-loaded-systems) :test 'equal) (prove:diag "Log4j was already loaded. Explicitly clearing it from ASDF.") (asdf:clear-system :log4j)) (prove:ok (asdf:load-system :log4j) "Testing loading the log4j system…") (#"configure" 'log4j.BasicConfigurator) (#"info" (#"getRootLogger" 'log4j.Logger) "Kilroy wuz here.") (prove:pass "No error occured while testing logging to *standard-output*")) (prove:finalize) abcl-src-1.9.0/contrib/abcl-asdf/t/maven.lisp0100644 0000000 0000000 00000000626 14202767264 017472 0ustar000000000 0000000 (in-package :cl-user) (prove:plan 5) (prove:diag "Testing local bootable Maven version.") (multiple-value-bind (good version) (abcl-asdf:ensure-mvn-version) (prove:ok good) (prove:is-type version 'list) (prove:ok (every #'fixnump version))) (prove:is-type (abcl-asdf:resolve-dependencies "log4j" "log4j") 'string) (prove:is-type (abcl-asdf:resolve "org.abcl/abcl") 'string) (prove:finalize) abcl-src-1.9.0/contrib/abcl-asdf/t/mvn-module.lisp0100644 0000000 0000000 00000001370 14202767264 020444 0ustar000000000 0000000 (in-package :cl-user) ;;; TODO: restore original ASDF configuration after running test (defun asdf-add-test-mvn-module () (asdf:initialize-source-registry `(:source-registry (:directory ,(asdf:system-relative-pathname :asdf-mvn-module "t/eg/")) :inherit-configuration))) (unless (ignore-errors (asdf:find-system :test-mvn-module)) (asdf-add-test-mvn-module)) (prove:plan 3) (prove:ok (asdf:load-system :test-mvn-module) "Testing loading of ASDF:MVN-MODULE definition…") (prove:ok (asdf:load-system :soot-only-repositories) "Testing loading with only repositories list…") (prove:ok (asdf:load-system :soot-mixed-repositories) "Testing loading with both single and list of repositories…") (prove:finalize) abcl-src-1.9.0/contrib/abcl-asdf/t/resolve-multiple-maven-dependencies.lisp0100644 0000000 0000000 00000001447 14202767264 025426 0ustar000000000 0000000 (in-package :cl-user) (prove:plan 3) (let ((deps (abcl-asdf:resolve-multiple-maven-dependencies '("net.sourceforge.owlapi:org.semanticweb.hermit:1.3.8.413" "net.sourceforge.owlapi:owlapi-distribution:4.2.6" "net.sourceforge.owlapi/pellet-cli-ignazio1977/2.4.0-ignazio1977" "org.semanticweb.elk/elk-reasoner/0.4.3" "net.sourceforge.owlapi/owlexplanation/2.0.0") '("net.sourceforge.owlapi:owlapi-distribution:4.2.6") '("net.sourceforge.owlapi:owlapi-osgidistribution" "edu.stanford.protege:org.protege.editor.owl")))) (prove:is (length deps) 87) (prove:ok (not (find "owlapi-osgidistribution" deps :test 'search))) (prove:ok (not (find "protege" deps :test 'search)))) (prove:finalize) abcl-src-1.9.0/contrib/abcl-asdf/t/resolve.lisp0100644 0000000 0000000 00000000304 14202767264 020034 0ustar000000000 0000000 (in-package :cl-user) (prove:plan 1) (prove:is-type (abcl-asdf:resolve-dependencies "org.armedbear.lisp" "abcl") 'string "Resolving ABCL from distributed Maven POM graph.") (prove:finalize) abcl-src-1.9.0/contrib/abcl-build/README.markdown0100644 0000000 0000000 00000000233 14202767264 020105 0ustar000000000 0000000 ABCL-BUILD ========== Installing and executing the necessary toolchain to build ABCL. Utility functions to download needed artifacts from the network. abcl-src-1.9.0/contrib/abcl-build/abcl-build-tests.asd0100644 0000000 0000000 00000001250 14202767264 021233 0ustar000000000 0000000 (defsystem abcl-build-tests :version "2.0.1" :description "Test ABCL build system." :defsystem-depends-on (prove-asdf) :depends-on (abcl-build prove) :perform (test-op (op c) (symbol-call :prove-asdf 'run-test-system c)) :components ((:module build :pathname "build/t/" :components ((:test-file "util") (:test-file "install") (:test-file "ant") (:test-file "maven") (:test-file "abcl-build"))))) abcl-src-1.9.0/contrib/abcl-build/abcl-build.asd0100644 0000000 0000000 00000002672 14202767264 020104 0ustar000000000 0000000 ;;; aka the "Lisp-hosted build system" which doesn't share build ;;; instructions with the canonical build system in ;;; Works for: abcl, sbcl, clisp, cmu, lispworks, allegro, openmcl (defsystem abcl-build :version "2.1.0" :description "Build ABCL from a Lisp. Downloads necessary build-time tools to local cache if not available on system." :in-order-to ((test-op (test-op abcl-build-tests))) :components ((:module package :pathname "build/" :components ((:file "package"))) (:module util :pathname "build/" :depends-on (package) :components ((:file "util") (:file "report"))) (:module build :pathname "build/" :depends-on (util) :serial t :components (;;; TODO optionally parse a local configuration for customization (:file "customizations-default") (:file "install") (:file "maven") (:file "ant") (:file "abcl-build") ;; TODO: support API (:file "build") (:file "deprecated"))))) abcl-src-1.9.0/contrib/abcl-build/build/abcl-build.lisp0100644 0000000 0000000 00000001425 14202767264 021376 0ustar000000000 0000000 (in-package :abcl/build) (defun make-dist (version-string) (warn "Unimplemented")) (defun build-abcl (&key force ;; DEPRECATED: not sure of meaning in new underlying API (batch t) ;; DEPRECATED: lack of meaning compile-system ;; DEPRECATED: COMPILE-SYSTEM is always invoked jar ;; DEPRECATED: a jar archive is always built clean full) ;; DEPRECATED: a full build is always performed (unless (ignore-errors (asdf:find-system :abcl)) (return-from build-abcl nil)) (let ((targets '("abcl"))) (when clean (push "abcl.clean" targets)) (ant/call (asdf:system-relative-pathname :abcl "build.xml") (nreverse targets)))) abcl-src-1.9.0/contrib/abcl-build/build/ant.lisp0100644 0000000 0000000 00000006023 14202767264 020161 0ustar000000000 0000000 (in-package :abcl/build) ;; TODO function to deal with looking up a locally preferred mirrors (defun ant-zip-uri () #p"https://archive.apache.org/dist/ant/binaries/apache-ant-1.9.16-bin.zip" #+(or) ;; need apache-ant-1.9 for JVM version 49.0 #p"https://www-eu.apache.org/dist/ant/binaries/apache-ant-1.10.12-bin.zip") (defun xdg/ant-executable () (xdg/executable (ant-zip-uri) "bin/ant")) #+(or) (defun xdg/ant-executable () (let* ((uri (ant-zip-uri)) (directory (xdg/abcl-install-root uri)) (ant-root-name (let ((name (pathname-name uri))) (subseq name 0 (- (length name) (length "-bin"))))) (ant-home (merge-pathnames (make-pathname :directory `(:relative ,ant-root-name)) directory)) (ant (merge-pathnames #p"bin/ant" ant-home)) result) (dolist (p (possible-executable-names ant)) (when (probe-file p) (return-from xdg/ant-executable (values (probe-file p) ant)))) ;; failure (values nil ant))) (defun ant/install () (unless (xdg/ant-executable) (xdg/install (ant-zip-uri) :type :unzip)) (values (xdg/ant-executable) (directory (merge-pathnames "**/*" (xdg/abcl-install-root (ant-zip-uri)))))) (defparameter *ant-home* nil) (define-condition no-installed-ant (error) ((searched)) (:report (lambda (condition stream) (declare (ignore condition)) (format stream "Unable to introspect Apache Ant installation.")))) ;; TODO after this routines executes *ANT-EXECUTABLE-DIRECTORY* and XDG/ANT-EXECUTABLE will work (defun ensure-ant (&key (ant-home nil ant-home-p)) "Ensure that Apache Ant may be invoked, installing one if necessary" (cond ((and (null ant-home) ant-home-p) (warn "Unimplemented explicit auto-configuration run.")) ((and ant-home ant-home-p) (warn "Unimplemented explicit configuration with specified directory directory.")) (t (if *ant-home* *ant-home* (restart-case (let ((ant-home (some-directory-containing "ant"))) (unless ant-home (signal 'no-installed-ant)) (setf *ant-home ant-home)) (install-ant () (ant/install))))))) (defmacro with-ensured-ant ((ant) &body body) `(progn (unless ,ant (setf ,ant (ensure-ant))) ,@body)) (defun ant/call (ant-file target-or-targets) "Synchronously invoke external Apache Ant on ANT-FILE with TARGET-OR-TARGETS" (let ((ant-file-pathname (if (typep ant-file 'pathname) ant-file (merge-pathnames ant-file))) ant) (with-ensured-ant (ant) (warn "About to invoke synchronous call to run external proccess…") (uiop:run-program `(,ant "-buildfile" ,(stringify ant-file-pathname) ,@(listify target-or-targets)) :ignore-error-status t :error-output :string :output :string)))) abcl-src-1.9.0/contrib/abcl-build/build/build.lisp0100644 0000000 0000000 00000000637 14202767264 020503 0ustar000000000 0000000 (in-package :abcl/build) (defun abcl/build () (abcl-build:ant/call (asdf:system-relative-pathname :abcl "build.xml") "abcl")) (defun abcl/dist () (abcl-build:ant/call (asdf:system-relative-pathname :abcl "build.xml") "abcl.release")) (defun abcl/test () (abcl-build:ant/call (asdf:system-relative-pathname :abcl "build.xml") "abcl.test")) abcl-src-1.9.0/contrib/abcl-build/build/customizations-default.lisp0100644 0000000 0000000 00000001764 14202767264 024123 0ustar000000000 0000000 ;;; Copy this file to "customizations.lisp" ;;; User customizations for the build. ;;; This file is LOADed by INITIALIZE-BUILD (in build-abcl.lisp). ;;; The variable *PLATFORM-IS-WINDOWS* should be true on Windows platforms. You ;;; can, of course, substitute your own test for this in the code below, or add ;;; a section for OS X, or Solaris, or whatever... ;;; You MUST set *JDK* to the location of the JDK you want to use. Remove or ;;; comment out settings that don't apply to your situation. ;;; You don't really need to specify anything but *JDK*. *JAVA-COMPILER* and ;;; *JAR* default to javac and jar, respectively, from the configured JDK. ;;; Directories should be specified with a trailing slash (or, on Windows, a ;;; trailing backslash). (in-package :abcl/build) ;; Standard compiler options. (defparameter *javac-options* "-g") (defparameter *jikes-options* "+D -g") (defparameter *jdk* (cond ((uiop:os-macosx-p) "/usr/") (t (introspect-path-for "javac")))) abcl-src-1.9.0/contrib/abcl-build/build/deprecated.lisp0100644 0000000 0000000 00000045627 14202767264 021514 0ustar000000000 0000000 ;;;; Historic cross platform build infrastructure ;;;; N.b. currently unused in favor of canonicalizing build.xml (in-package :abcl/build) (defun chop-end-from-char (string char) "Chops off the character at the end of `string' if it matches char" (let ((len (length string))) (if (eql char (char string (1- len))) (subseq string 0 (1- len)) string))) (defun safe-namestring (pathname) (let ((string (namestring pathname))) (when (position #\space string) (setf string (concatenate 'string "\"" (chop-end-from-char string #\\) "\""))) string)) (defun child-pathname (pathname parent) "Returns `pathname' relative to `parent', assuming that it is infact a child of it while being rooted at the same root as `parent'." (let ((path-dir (pathname-directory pathname)) (parent-dir (pathname-directory parent))) (do ((p1 path-dir (cdr p1)) (p2 parent-dir (cdr p2))) ((or (endp p2) (not (equal (car p1) (car p2)))) (when (endp p2) (make-pathname :directory (cons :relative p1) :defaults pathname)))))) (defun file-newer (orig artifact) "Compares file date/time of `orig' and `artifact', returning `NIL' if `orig' is newer than `artifact'." (or (null (probe-file artifact)) (> (file-write-date orig) (file-write-date artifact)))) (defparameter *file-separator-char* (if (uiop:os-windows-p) #\\ #\/)) (defparameter *path-separator-char* (if (uiop:os-windows-p) #\; #\:)) (defparameter *tree-root* (make-pathname :device (pathname-device *load-truename*) :directory (pathname-directory *load-truename*))) (defparameter *build-root* (merge-pathnames "build/classes/" *tree-root*)) (defparameter *source-root* (merge-pathnames "src/" *tree-root*)) (defparameter *dist-root* (merge-pathnames "dist/" *tree-root*)) (defparameter *customizations-file* (merge-pathnames "customizations.lisp" *tree-root*)) (defparameter *abcl-dir* (merge-pathnames "src/org/armedbear/lisp/" *tree-root*)) (defparameter *jdk* nil) (defparameter *java-compiler* nil) (defparameter *javac-options* nil) (defparameter *jikes-options* nil) (defparameter *jar* nil) (defvar *classpath*) (defvar *java*) (defvar *java-compiler-options*) (defvar *java-compiler-command-line-prefix*) (defun initialize-build () ;;; FIXME: highly breakable; user shouldn't be reading (load (asdf:system-relative-pathname :build-abcl "src/org/abcl/lisp/build/customizations-default.lisp")) (setf *java* (introspect-path-for "java")) (unless *java* (error "Can't find Java executable.")) (unless *java-compiler* (setf *java-compiler* (introspect-path-for "java"))) (unless *jar* (setf *jar* (introspect-path-for "jar"))) (let ((classpath-components (list *source-root* (if (uiop:os-macosx-p) #p"/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar" (merge-pathnames "jre/lib/rt.jar" *jdk*))))) (setf *classpath* (with-output-to-string (s) (do* ((components classpath-components (cdr components)) (component (car components) (car components))) ((null components)) (princ (safe-namestring component) s) (unless (null (cdr components)) (write-char *path-separator-char* s)))))) (let ((prefix (concatenate 'string (safe-namestring *java-compiler*) " -classpath " *classpath*))) (setf *java-compiler-options* (if (string-equal (pathname-name (pathname *java-compiler*)) "jikes") *jikes-options* *javac-options*)) (setf prefix (if *java-compiler-options* (concatenate 'string prefix " " *java-compiler-options* " ") (concatenate 'string prefix " "))) (setf *java-compiler-command-line-prefix* prefix))) (defun substitute-in-string (string substitutions-alist) (dolist (entry substitutions-alist) (loop named replace for index = (search (car entry) string :test #'string=) do (unless index (return-from replace)) (setf string (concatenate 'string (subseq string 0 index) (cdr entry) (subseq string (+ index (length (car entry)))))))) string) (defun copy-with-substitutions (source-file target-file substitutions-alist) (with-open-file (in source-file :direction :input) (with-open-file (out target-file :direction :output :if-exists :supersede) (loop (let ((string (read-line in nil))) (when (null string) (return)) (write-line (substitute-in-string string substitutions-alist) out)))))) (defun build-javac-command-line (source-file) (concatenate 'string *java-compiler-command-line-prefix* " -d " (safe-namestring *build-root*) " " (namestring source-file))) (defun java-compile-file (source-file) (let ((command-line (build-javac-command-line source-file))) ;; TODO: detect failure of invocation (values (uiop:run-program command-line :directory *abcl-dir* :output :string)) command-line)) (defun do-compile-classes (force batch) (let* ((source-files (remove-if-not #'(lambda (name) (let ((output-name (merge-pathnames (make-pathname :type "class" :defaults (child-pathname name *source-root*)) *build-root*))) (or force (file-newer name output-name)))) (directory (merge-pathnames "**/*.java" *source-root*))))) (format t "~&JDK: ~A~%" *jdk*) (format t "Java compiler: ~A~%" *java-compiler*) (format t "Compiler options: ~A~%~%" (if *java-compiler-options* *java-compiler-options* "")) (format t "~&Compiling Java sources...") (finish-output) (cond ((null source-files) (format t "Classes are up to date.~%") (finish-output) t) (t (cond (batch (ensure-directories-exist *build-root*) (let* ((cmdline (with-output-to-string (s) (princ *java-compiler-command-line-prefix* s) (princ " -d " s) (princ (safe-namestring *build-root*) s) (princ #\Space s) (dolist (source-file source-files) (princ (safe-namestring (namestring source-file)) s) (princ #\space s)))) (status (run-shell-command cmdline :directory *tree-root*))) (format t " done.~%") (equal 0 status))) (t (ensure-directories-exist *build-root*) (dolist (source-file source-files t) (unless (java-compile-file (safe-namestring source-file)) (format t "Build failed.~%") (return nil))))))))) (defun make-jar () (let ((*default-pathname-defaults* *tree-root*) (jar-namestring (namestring *jar*))) (when (position #\space jar-namestring) (setf jar-namestring (concatenate 'string "\"" jar-namestring "\""))) (let ((substitutions-alist (acons "@JAR@" jar-namestring nil)) (source-file (if (uiop:os-windows-p) "make-jar.bat.in" "make-jar.in")) (target-file (if (uiop:os-windows-p) "make-jar.bat" "make-jar")) (command (if (uiop:os-windows-p) "make-jar.bat" "sh make-jar"))) (copy-with-substitutions source-file target-file substitutions-alist) (ensure-directories-exist *dist-root*) (let ((status (run-shell-command command :directory *tree-root*))) (unless (equal 0 status) (format t "~A returned ~S~%" command status)) status)))) (defun do-compile-system (&key (zip t)) (format t "~&Compiling Lisp sources...") (terpri) (finish-output) (let* ((java-namestring (safe-namestring *java*)) status (abcl-home (substitute-in-string (namestring *abcl-dir*) (when (uiop:os-windows-p) '(("\\" . "/") ("/" . "\\\\"))))) (output-path (substitute-in-string (namestring (merge-pathnames "build/classes/org/armedbear/lisp/" *tree-root*)) (when (uiop:os-windows-p) '(("\\" . "/"))))) (cmdline (format nil "~A -cp build/classes -Dabcl.home=\"~A\" ~ org.armedbear.lisp.Main --noinit --nosystem ~ --eval \"(compile-system :zip ~A :quit t :output-path \\\"~A\\\")\"~%" java-namestring abcl-home (not (not zip)) ;; because that ensures T or NIL output-path))) (ensure-directories-exist output-path) (setf status (run-shell-command cmdline :directory *tree-root*)) (format t " done.~%") status)) ;; abcl/abcl.bat (defun make-launch-script () ;; Use the -Xss4M and -Xmx256M flags so that the default launch script can be ;; used to build sbcl. (cond ((uiop:os-windows-p) (with-open-file (s (merge-pathnames "abcl.bat" *tree-root*) :direction :output :if-exists :supersede) (format s "~A -Xss4M -Xmx256M -cp \"~A\" org.armedbear.lisp.Main %1 %2 %3 %4 %5 %6 %7 %8 %9~%" (safe-namestring *java*) (namestring (merge-pathnames "dist\\abcl.jar" *tree-root*))))) (t (let ((pathname (merge-pathnames "abcl" *tree-root*))) (with-open-file (s pathname :direction :output :if-exists :supersede) (format s "#!/bin/sh~%exec ~A -Xss4M -Xmx256M -cp ~A org.armedbear.lisp.Main \"$@\"~%" (safe-namestring *java*) (safe-namestring (merge-pathnames "abcl.jar" *dist-root*)))) (run-shell-command (format nil "chmod +x ~A" (safe-namestring pathname)) :directory *tree-root*))))) (defun build-stamp () (multiple-value-bind (second minute hour date month year day daylight-p zone) (decode-universal-time (get-universal-time)) (declare (ignore daylight-p)) (setf day (nth day '("Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"))) (setf month (nth (1- month) '("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"))) (setf zone (* zone 100)) ;; FIXME (format nil "~A ~A ~D ~D ~2,'0D:~2,'0D:~2,'0D -~4,'0D" day month date year hour minute second zone))) (defun make-build-stamp () (with-open-file (s (merge-pathnames (make-pathname :name "build" :defaults *abcl-dir*)) :direction :output :if-exists :supersede) (format s "~A" (build-stamp)))) (defun delete-files (pathnames) (dolist (pathname pathnames) (let ((truename (probe-file pathname))) (when truename (delete-file truename))))) (defun clean () (format t "~&Cleaning compilation results.") (dolist (f (list (list *tree-root* "abcl.jar" "abcl.bat" "make-jar.bat" "compile-system.bat") ;; as of 0.14 'compile-system.bat' isn't created anymore ;; as of 0.14 'abcl.jar' is always created in dist/ (list *abcl-dir* "*.class" "*.abcl" "*.cls" "native.h" "libabcl.so" "build") ;; as of 0.14, native.h and libabcl.so have been removed (list (merge-pathnames "util/" *abcl-dir*) "*.class") (list (merge-pathnames "build/classes/org/armedbear/lisp/" *tree-root*) "*.class" "*.abcl" "*.cls" "native.h" "libabcl.so" "build") (list (merge-pathnames "build/classes/org/armedbear/lisp/util/" *tree-root*) "*.class" "*.abcl" "*.cls") (list *dist-root* "*.jar" "*.class" "*.abcl" "*.cls") (list (merge-pathnames "java/awt/" *abcl-dir*) "*.class"))) (let ((default (car f))) (when (probe-directory default) (delete-files (mapcan #'(lambda (name) (directory (merge-pathnames name default))) (cdr f))))))) #+(or) (defun build-abcl (&key force (batch t) compile-system jar clean full) (let ((start (get-internal-real-time))) #+lispworks (when (uiop:os-windows-p) (setf batch nil)) (initialize-build) (format t "~&Platform: ~A~%" (software-type)) (finish-output) ;; clean (when clean (clean)) ;; Compile Java source into classes (unless (do-compile-classes force batch) (format t "Build failed.~%") (return-from build-abcl nil)) ;; COMPILE-SYSTEM (when (or full compile-system) (let* ((zip (if (or full jar) nil t)) (status (do-compile-system :zip zip))) (unless (equal 0 status) (format t "Build failed.~%") (return-from build-abcl nil)))) ;; abcl.jar (when (or full jar) (let ((status (make-jar))) (unless (equal 0 status) (format t "Build failed.~%") (return-from build-abcl nil)))) ;; abcl/abcl.bat (make-launch-script) (make-build-stamp) (let ((end (get-internal-real-time))) (format t "Build completed successfully in ~A seconds.~%" (/ (float (- end start)) internal-time-units-per-second))) t)) (defun build-abcl-executable () (let* ((*default-pathname-defaults* *abcl-dir*) (source-files (directory "*.java")) (cmdline (with-output-to-string (s) (princ "gcj -g -O0 " s) (dolist (source-file source-files) (unless (string= (pathname-name source-file) "Native") (princ (pathname-name source-file) s) (princ ".java" s) (princ #\space s))) (princ "--main=org.armedbear.lisp.Main -o lisp" s))) (result (run-shell-command cmdline :directory *abcl-dir*))) (equal 0 result))) (defvar *copy-verbose* nil) (defun copy-file (source target) (when *copy-verbose* (format t "~A -> ~A~%" source target)) (let ((buffer (make-array 4096 :element-type '(unsigned-byte 8)))) (with-open-file (in source :direction :input :element-type '(unsigned-byte 8)) (with-open-file (out target :direction :output :element-type '(unsigned-byte 8) :if-exists :supersede) (loop (let ((end (read-sequence buffer in))) (when (zerop end) (return)) (write-sequence buffer out :end end))))))) (defun copy-files (files source-dir target-dir) (ensure-directories-exist target-dir) (dolist (file files) (copy-file (merge-pathnames file source-dir) (merge-pathnames file target-dir)))) (defun make-dist-dir (version-string) (unless (uiop:os-unix-p) (error "MAKE-DIST is only supported on Unices.")) (let ((target-root (pathname (concatenate 'string "/var/tmp/" version-string "/")))) (when (probe-directory target-root) (error "Target directory ~S already exists." target-root)) (let* ((source-dir *tree-root*) (target-dir target-root) (files (list "README" "COPYING" "build-abcl.lisp" "customizations.lisp" "make-jar.bat.in" "make-jar.in"))) (copy-files files source-dir target-dir)) (let* ((source-dir (merge-pathnames "examples/" *tree-root*)) (target-dir (merge-pathnames "examples/" target-root)) (files '("hello.java"))) (copy-files files source-dir target-dir)) (let* ((target-dir (merge-pathnames "src/" target-root)) (files '("manifest-abcl"))) (copy-files files *source-root* target-dir)) (let* ((source-dir *abcl-dir*) (target-dir (merge-pathnames "src/org/armedbear/lisp/" target-root)) (*default-pathname-defaults* source-dir) (files (mapcar #'file-namestring (append (directory "*.java") (directory "*.lisp") (list "LICENSE" "native.c"))))) (copy-files files source-dir target-dir)) (let* ((source-dir (merge-pathnames "tests/" *abcl-dir*)) (target-dir (merge-pathnames "src/org/armedbear/lisp/tests/" target-root)) (*default-pathname-defaults* source-dir) (files (append (mapcar #'file-namestring (directory "*.lisp")) (list "jl-config.cl")))) (copy-files files source-dir target-dir)) (let* ((source-dir (merge-pathnames "java/awt/" *abcl-dir*)) (target-dir (merge-pathnames "src/org/armedbear/lisp/java/awt/" target-root)) (*default-pathname-defaults* source-dir) (files (mapcar #'file-namestring (directory "*.java")))) (copy-files files source-dir target-dir)) target-root)) #+(or) (defun make-dist (version-string) (let* ((dist-dir (make-dist-dir version-string)) (parent-dir (merge-pathnames (make-pathname :directory '(:relative :back)) dist-dir))) (let* ((command (format nil "tar czf ~A~A.tar.gz ~A" (namestring parent-dir) version-string version-string)) (status (run-shell-command command :directory parent-dir))) (unless (equal 0 status) (format t "~A returned ~S~%" command status))) (let* ((command (format nil "zip -q -r ~A~A.zip ~A" (namestring parent-dir) version-string version-string)) (status (run-shell-command command :directory parent-dir))) (unless (equal 0 status) (format t "~A returned ~S~%" command status))))) abcl-src-1.9.0/contrib/abcl-build/build/install.lisp0100644 0000000 0000000 00000004620 14202767264 021046 0ustar000000000 0000000 #-abcl (error "Sorry, but this only currently works with the Bear.") (in-package :abcl/build) (defun xdg/abcl-install-root (uri) "Return the private xdg rooted installation location for URI." (merge-pathnames (make-pathname :directory `(:relative "abcl" "install" ,(pathname-name uri))) (uiop/configuration:xdg-data-home))) (defun xdg/abcl-download-root (&key (for-uri nil for-uri-p)) (declare (ignore for-uri-p)) (let ((root (merge-pathnames (make-pathname :directory '(:relative "abcl" "dist")) (uiop/configuration:xdg-data-home)))) ;; TODO move to proper XDG cache hierarchy (unless for-uri (return-from xdg/abcl-download-root root)) (let* ((uri (if (pathnamep for-uri) for-uri (pathname for-uri))) (name (pathname-name uri))) (merge-pathnames (make-pathname :directory `(:relative ,name)) root)))) (defgeneric xdg/install ((uri pathname) &key type) (:method ((uri pathname) &key (type :unzip)) (declare (ignore type)) (download-and-unzip uri))) (defun download-and-unzip (uri) (let ((archive (download uri)) (root (xdg/abcl-install-root uri))) (ensure-directories-exist root) (sys:unzip archive root) (values root (directory (merge-pathnames "**/*" root))))) (defun download (uri &key (destination (merge-pathnames (make-pathname :defaults uri :host nil :device nil :directory nil) (xdg/abcl-download-root)))) "Download the contents of URI to DESTINATION. Returns the local pathname of the download artifact." (ensure-directories-exist destination) (uiop:copy-file (open uri :direction :input) destination) destination) (defun xdg/executable (uri relative-path) (let* ((directory (xdg/abcl-install-root uri)) (root (let ((name (pathname-name uri))) (subseq name 0 (- (length name) (length "-bin"))))) (home (merge-pathnames (make-pathname :directory `(:relative ,root)) directory)) (path (merge-pathnames relative-path home))) (dolist (p (possible-executable-names path)) (when (probe-file p) (return-from xdg/executable (values (probe-file p) path)))) ;; failure (values nil path))) abcl-src-1.9.0/contrib/abcl-build/build/maven.lisp0100644 0000000 0000000 00000004105 14202767264 020504 0ustar000000000 0000000 (in-package :abcl/build) (defun maven-zip-uri () #p"https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip") (defun xdg/mvn-executable () (xdg/executable (maven-zip-uri) "bin/mvn")) (defparameter *maven-install-root* nil) (defun mvn/install () "Unless (XDG/MVN-EXECUTABLE) install a version of Maven in the XDG hierarchy Returns the local path of the resulting mvn executable." (unless (xdg/mvn-executable) (xdg/install (maven-zip-uri) :type :unzip)) (values (xdg/mvn-executable) (directory (merge-pathnames "**/*" (xdg/abcl-install-root (maven-zip-uri)))))) (defparameter *mvn-home* nil) (define-condition no-installed-maven (error) ((searched :initarg :searched)) (:report (lambda (condition stream) (declare (ignore condition)) (format stream "Unable to introspect local Apache Maven installation.")))) (defun ensure-maven (&key (mvn-home *mvn-home* mvn-home-p) (use-xdg-mvn nil use-xdg-mvn-p)) "Ensure that the implementation can find and execute the Maven build tool If MVN-HOME is specified, attempt to configure use of that directory." (declare (ignore use-xdg-mvn use-xdg-mvn-p)) (cond ((and (null mvn-home) mvn-home-p) (warn "Unimplemented explicit auto-configuration run.")) ((and mvn-home mvn-home-p) (warn "Unimplemented explicit configuration with specified directory directory.")) (t (if *mvn-home* *mvn-home* (restart-case (let ((mvn-home (some-directory-containing "mvn"))) (unless mvn-home (signal 'no-installed-maven)) (setf *mvn-home* mvn-home)) (install-maven () (mvn/install))))))) (defmacro with-ensured-mvn ((maven) &body body) `(progn (unless ,maven (setf ,maven (ensure-maven)) ,@body))) (defun mvn/call (pom-file target-or-targets) (let (mvn) (with-ensured-mvn (mvn) (uiop:run-program `(,mvn "--file" ,(stringify pom-file) ,@(listify target-or-targets)) :output :string)))) abcl-src-1.9.0/contrib/abcl-build/build/package.lisp0100644 0000000 0000000 00000002206 14202767264 020771 0ustar000000000 0000000 (in-package :cl-user) (defpackage build-abcl (:use :cl) (:nicknames :build-abcl :abcl-build :abcl/build) (:export #:abcl/build #:abcl/dist #:abcl/test ;; deprecated TODO: hook into new interfaces #:build-abcl #:make-dist ;; utility functions that should be moved into utility package #:introspect-path-for #:split-string #:possible-executable-names #:probe-for-executable #:stringify #:listify #:some-directory #:copy-directory-recursively ;;; lower-level #:xdg/abcl-install-root #:xdg/abcl-download-root #:xdg/install #:locally-install-and-unzip #:download-and-unzip #:download #:xdg/ant-executable #:with-ensured-ant #:ant/install #:ant/call #:with-ensured-maven #:ensure-maven #:mvn/install #:mvn/call #:directory-hashes #:hashes-report #:install-zip #:download-artifact) ;;; TODO: use UIOP, currently only used for deprecated, old build system #+abcl (:import-from #:extensions #:run-shell-command #:probe-directory) #+allegro (:import-from #:excl #:probe-directory) #+clisp (:import-from #:ext #:probe-directory)) abcl-src-1.9.0/contrib/abcl-build/build/report.lisp0100644 0000000 0000000 00000002034 14202767264 020710 0ustar000000000 0000000 (in-package :abcl/build) ;;; FIXME: will not work if DIRECTORY contains subdirectories (defun directory-hashes (directory) "Return the size and sha256 hash of every direct entry of DIRECTORY." (let ((d (if (typep directory 'pathname) directory (pathname (concatenate 'string directory "/"))))) (let ((result (loop :for file :in (directory (merge-pathnames "*.*" d)) :collecting (list file (with-open-file (s file :direction :input) (when s (file-length s))) (sys:sha256 file))))) (values result (hashes-report result))))) (defun hashes-report (report) (format nil "~{~a~}~%" (loop :for (file size hash) :in report :collecting (format nil "~%~%~t:size ~a ;~%~t:sha256 ~a ." file size hash)))) abcl-src-1.9.0/contrib/abcl-build/build/t/abcl-build.lisp0100644 0000000 0000000 00000001375 14202767264 021645 0ustar000000000 0000000 (in-package :cl-user) (if (not (ignore-errors (asdf:find-system :abcl))) (prove:diag "Unable to find 'abcl.asd'.~&Enable ASDF to find 'abcl.asd' by adding symlink to ~~/common-lisp/ to ABCL source directory.") (prove:subtest "Testing BUILD-ABCL." (prove:plan 2) (prove:ok (abcl-build:build-abcl) "Testing BUILD-ABCL…") (prove:ok (abcl-build:make-dist (format nil "test-" (random (expt 2 32)))) "Testing MAKE-DIST…") #+abcl-build-test-more (progn (prove:ok (abcl-build:build-abcl :clean t) "Testing BUILD:ABCL clean…")) #+abcl-build-test-more (prove:ok (abcl-build:build-abcl :force t) "Testing BUILD-ABCL force…"))) (prove:finalize) abcl-src-1.9.0/contrib/abcl-build/build/t/ant.lisp0100644 0000000 0000000 00000001205 14202767264 020421 0ustar000000000 0000000 (in-package :cl-user) (prove:plan 1) (prove:ok (build-abcl:ant/install) "Testing ABCL-specific Ant installation of Ant into XDG hierarchy…") (if (not (ignore-errors (asdf:find-system :abcl))) (prove:diag "Unable to find 'abcl.asd'.~&Enable ASDF to find 'abcl.asd' by adding symlink to ~~/common-lisp/ to ABCL source directory.") (let ((ant-file (asdf:system-relative-pathname :abcl "build.xml"))) (prove:plan 1) (prove:ok (abcl-build:ant/call ant-file "abcl.diagnostic") (format nil "Testing invocation of private Ant on main ABCL build artifact at ~&~2,t~a…" ant-file)))) (prove:finalize) abcl-src-1.9.0/contrib/abcl-build/build/t/install.lisp0100644 0000000 0000000 00000001314 14202767264 021306 0ustar000000000 0000000 (in-package :cl-user) (let ((uri #p"https://downloads.apache.org/ant/binaries/apache-ant-1.10.12-bin.zip")) (prove:plan 1) (prove:ok (abcl/build:xdg/abcl-install-root uri) (format nil "Suitable install root for <~a>" uri)) (prove:plan 2) (let ((path (ext:make-temp-directory))) (prove:diag (format nil "Testing binary unzip installation of~%~,2t<~a>~%to~%~,2t '~a'." uri path)) (multiple-value-bind (root contents) (abcl/build:xdg/install uri) (prove:ok (and root (probe-file root))) (prove:ok (and (consp contents) (> (length contents) 0)))))) (prove:finalize) abcl-src-1.9.0/contrib/abcl-build/build/t/maven.lisp0100644 0000000 0000000 00000001135 14202767264 020747 0ustar000000000 0000000 (in-package :cl-user) (prove:plan 1) (prove:ok (abcl/build:mvn/install) "Testing ABCL-specific Ant installation of Maven into XDG hierarchy…") (if (not (ignore-errors (asdf:find-system :abcl))) (prove:diag "Unable to find 'abcl.asd'.~&Enable ASDF to find 'abcl.asd' by adding symlink to ~~/common-lisp/ to ABCL source directory.") (let ((pom (asdf:system-relative-pathname :abcl "pom.xml"))) (prove:ok (abcl/build:mvn/call pom "install") (format nil "Testing invocation of private Maven on root ABCL POM at~&~2,t~a…" pom)))) (prove:finalize) abcl-src-1.9.0/contrib/abcl-build/build/t/util.lisp0100644 0000000 0000000 00000000356 14202767264 020622 0ustar000000000 0000000 (in-package :cl-user) (prove:plan 1) (prove:is-type (abcl/build:possible-executable-names "java") 'cons) (prove:plan 1) (prove:is (length (abcl/build:split-string "one.two.three." #\.)) 4) (prove:finalize) abcl-src-1.9.0/contrib/abcl-build/build/util.lisp0100644 0000000 0000000 00000007646 14202767264 020370 0ustar000000000 0000000 ;;;; TODO: move to a utility package (in-package :abcl/build) ;;; TODO remove (defun localize-executable-name (name) (let* ((p (if (pathnamep name) name (pathname name))) (type (pathname-type p))) (make-pathname :defaults p :type (if (uiop:os-windows-p) (when (null type) "exe") type)))) (defun possible-executable-names (name &key (suffixes '("exe" "cmd" "bat") suffixes-p)) (let* ((p (if (pathnamep name) name (pathname name))) (type (pathname-type p))) (declare (ignore type)) (unless (or (uiop:os-windows-p) suffixes-p) (return-from possible-executable-names (listify name))) (loop :for suffix :in suffixes :with result = (list p) :doing (push (make-pathname :defaults p :type suffix) result) :finally (return (nreverse result))))) (defun introspect-path-for (executable) (let ((which-command (if (uiop:os-windows-p) "where" "which"))) (when (ignore-errors (uiop:run-program (list which-command which-command) :output :string)) (dolist (p (possible-executable-names executable)) (let ((raw-result (ignore-errors (uiop:run-program (list which-command (namestring p)) :output :string)))) (when raw-result (let ((result (first (split-string raw-result #\Newline)))) (return-from introspect-path-for (values result (pathname result)))))))))) (defun probe-for-executable (directory executable) (dolist (executable (possible-executable-names executable)) (let ((pathname (probe-file (merge-pathnames executable directory)))) (when pathname (return-from probe-for-executable pathname))))) (defun split-string (string split-char) (loop :for i = 0 :then (1+ j) :as j = (position split-char string :test #'string-equal :start i) :collect (subseq string i j) :while j)) (defun stringify (thing) (cond ((pathnamep thing) (namestring thing)) ((stringp thing) thing) (t (error "Don't know how stringify ~a." thing)))) (defun listify (thing) (if (consp thing) thing (list thing))) (defun some-directory-containing (executable) ;; search path (let ((in-path (introspect-path-for executable))) (when in-path (return-from some-directory-containing in-path)) (dolist (d (if (uiop:os-windows-p) '(#p"c:/Program Files/") ;; TODO localize me! '(#p"/usr/local/bin/" #p"/opt/local/bin/" #p"/usr/bin/"))) (let* ((e (localize-executable-name (merge-pathnames executable d))) (p (probe-file e))) (when p (return-from some-directory-containing p)))))) (defun copy-directory-recursively (from to) (flet ((normalize-to-directory (p) (when (or (not (pathnamep p)) (not (and (null (pathname-name p)) (null (pathname-type p))))) (setf p (make-pathname :defaults p :name nil :type nil))) p)) (normalize-to-directory from) (normalize-to-directory to) (let ((wildcard (merge-pathnames "**/*" from))) (loop :for source :in (directory wildcard) :for relative = (enough-namestring source from) :for destination = (merge-pathnames relative to) :doing (progn (ensure-directories-exist destination) (when (or (pathname-name destination) (pathname-type destination)) (uiop:copy-file source destination))))))) abcl-src-1.9.0/contrib/abcl-introspect/README.org0100644 0000000 0000000 00000016631 14202767264 020156 0ustar000000000 0000000 * ABCL-INTROSPECT ** Introduction ABCL-INTROSPECT offers more extensive systems for inspecting the state of the implementation, most notably in integration with SLIME, where the back-trace mechanism is augmented to the point that local variables are inspectable. Version of SLIME 2.25 dramatically increases the utility of the available inspectors under ABCL. Unfortunately, this version of SLIME is unreleased, so please use something post . ** CL:DISASSEMBLE ABCL-INTROSPECT also contains a number of ASDF systems which provide modules to install as implementations for the JVM code analysis provided by CL:DISASSEMBLE. #+TABLE: Currently available decompilers as ASDF systems |------------+--------------------------+-----------------------------------------------------------------------------| | ASDF | status | URI | |------------+--------------------------+-----------------------------------------------------------------------------| | objectweb | working | | | javap | working | < | | cfr | working | | | jad | fails ABCL-BUILD/install | | | procyon | loading | | | fernflower | loading | | These systems may be used by first loading the appropiate ASDF definition then using the SYS:CHOOSE-DISASSEMBLER function to select the loaded system. Currently available disassemblers are contained in the SYS:*DISASSEMBLERS* variable. #+caption: Using the ~javap~ Tool to Disassemble a Function #+begin_src lisp (require :abcl-contrib) (asdf:load-system :javap) (sys:choose-disassembler :javap) (cl:disassemble #'cons) ; Classfile /var/folders/yb/xlwjwjfs3l73n3vrcjwqwqs40000gn/T/abcl3108750031103632433.class ; Last modified May 11, 2020; size 910 bytes ; MD5 checksum fec1c72a76ccbb35e17be8c2de9b315e ; Compiled from "Primitives.java" ; final class org.armedbear.lisp.Primitives$pf_cons extends org.armedbear.lisp.Primitive ; minor version: 0 ; major version: 52 ; flags: ACC_FINAL, ACC_SUPER ; Constant pool: ; #1 = Fieldref #24.#25 // org/armedbear/lisp/Symbol.CONS:Lorg/armedbear/lisp/Symbol; ; #2 = String #26 // object-1 object-2 ; #3 = Methodref #7.#27 // org/armedbear/lisp/Primitive."":(Lorg/armedbear/lisp/Symbol;Ljava/lang/String;)V ; #4 = Class #28 // org/armedbear/lisp/Cons ; #5 = Methodref #4.#29 // org/armedbear/lisp/Cons."":(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)V ; #6 = Class #31 // org/armedbear/lisp/Primitives$pf_cons ; #7 = Class #32 // org/armedbear/lisp/Primitive ; #8 = Utf8 ; #9 = Utf8 ()V ; #10 = Utf8 Code ; #11 = Utf8 LineNumberTable ; #12 = Utf8 LocalVariableTable ; #13 = Utf8 this ; #14 = Utf8 pf_cons ; #15 = Utf8 InnerClasses ; #16 = Utf8 Lorg/armedbear/lisp/Primitives$pf_cons; ; #17 = Utf8 execute ; #18 = Utf8 (Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject; ; #19 = Utf8 first ; #20 = Utf8 Lorg/armedbear/lisp/LispObject; ; #21 = Utf8 second ; #22 = Utf8 SourceFile ; #23 = Utf8 Primitives.java ; #24 = Class #33 // org/armedbear/lisp/Symbol ; #25 = NameAndType #34:#35 // CONS:Lorg/armedbear/lisp/Symbol; ; #26 = Utf8 object-1 object-2 ; #27 = NameAndType #8:#36 // "":(Lorg/armedbear/lisp/Symbol;Ljava/lang/String;)V ; #28 = Utf8 org/armedbear/lisp/Cons ; #29 = NameAndType #8:#37 // "":(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)V ; #30 = Class #38 // org/armedbear/lisp/Primitives ; #31 = Utf8 org/armedbear/lisp/Primitives$pf_cons ; #32 = Utf8 org/armedbear/lisp/Primitive ; #33 = Utf8 org/armedbear/lisp/Symbol ; #34 = Utf8 CONS ; #35 = Utf8 Lorg/armedbear/lisp/Symbol; ; #36 = Utf8 (Lorg/armedbear/lisp/Symbol;Ljava/lang/String;)V ; #37 = Utf8 (Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)V ; #38 = Utf8 org/armedbear/lisp/Primitives ; { ; org.armedbear.lisp.Primitives$pf_cons(); ; descriptor: ()V ; flags: ; Code: ; stack=3, locals=1, args_size=1 ; 0: aload_0 ; 1: getstatic #1 // Field org/armedbear/lisp/Symbol.CONS:Lorg/armedbear/lisp/Symbol; ; 4: ldc #2 // String object-1 object-2 ; 6: invokespecial #3 // Method org/armedbear/lisp/Primitive."":(Lorg/armedbear/lisp/Symbol;Ljava/lang/String;)V ; 9: return ; LineNumberTable: ; line 467: 0 ; line 468: 9 ; LocalVariableTable: ; Start Length Slot Name Signature ; 0 10 0 this Lorg/armedbear/lisp/Primitives$pf_cons; ; ; public org.armedbear.lisp.LispObject execute(org.armedbear.lisp.LispObject, org.armedbear.lisp.LispObject); ; descriptor: (Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject; ; flags: ACC_PUBLIC ; Code: ; stack=4, locals=3, args_size=3 ; 0: new #4 // class org/armedbear/lisp/Cons ; 3: dup ; 4: aload_1 ; 5: aload_2 ; 6: invokespecial #5 // Method org/armedbear/lisp/Cons."":(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)V ; 9: areturn ; LineNumberTable: ; line 474: 0 ; LocalVariableTable: ; Start Length Slot Name Signature ; 0 10 0 this Lorg/armedbear/lisp/Primitives$pf_cons; ; 0 10 1 first Lorg/armedbear/lisp/LispObject; ; 0 10 2 second Lorg/armedbear/lisp/LispObject; ; } ; SourceFile: "Primitives.java" #+end_src * Colophon #+caption: Metadata Colophon #+begin_src n3 <> dc:source ; dc:replaces ; dc:modified "<2020-05-12 Tue 10:21>" . #+end_src abcl-src-1.9.0/contrib/abcl-introspect/abcl-introspect-test.asd0100644 0000000 0000000 00000001141 14242627550 023232 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem abcl-introspect-test :author "Mark Evenson" :long-description "" :version "2.1.0" :defsystem-depends-on (prove-asdf) :depends-on (abcl-asdf ;; locate various testing dependencies via ABCL-ASDF prove) :components ((:module tests :pathname "t/" :components ((:test-file "disassemble") (:test-file "environments")))) :perform (asdf:test-op (op c) (uiop:symbol-call :prove-asdf 'run-test-system c))) abcl-src-1.9.0/contrib/abcl-introspect/abcl-introspect.asd0100644 0000000 0000000 00000001275 14242627550 022265 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem abcl-introspect :author ("Alan Ruttenberg" "Mark Evenson") :description "Introspection on compiled function to aid source location and other debugging functions." :long-description "" :version "2.1.0" :depends-on (jss) :components ((:module package :pathname #p"./" :components ((:file "packages"))) (:module source :pathname #p"./" :components ((:file "abcl-introspect") (:file "stacktrace") (:file "util")))) :in-order-to ((test-op (test-op abcl-introspect-test)))) abcl-src-1.9.0/contrib/abcl-introspect/abcl-introspect.lisp0100644 0000000 0000000 00000066013 14212332540 022453 0ustar000000000 0000000 (in-package :system) ;; Author: Alan Ruttenberg December 2016 ;; This code is released under Creative Common CC0 declaration ;; (https://wiki.creativecommons.org/wiki/CC0) and as such is intended ;; to be in the public domain. ;; A compiled function is an instance of a class - This class has ;; multiple instances if it represents a closure, or a single instance if ;; it represents a non-closed-over function. ;; The ABCL compiler stores constants that are used in function execution ;; as private java fields. This includes symbols used to invoke function, ;; locally-defined functions (such as via labels or flet) and string and ;; other literal constants. ;; This file provides access to those internal values, and uses them in ;; at least two ways. First, to annotate locally defined functions with ;; the top-level function they are defined within, and second to search ;; for callers of a give function(*). This may yield some false ;; positives, such as when a symbol that names a function is also used ;; for some other purpose. It can also have false negatives, as when a ;; function is inlined. Still, it's pretty useful. The second use to to ;; find source locations for frames in the debugger. If the source ;; location for a local function is asked for the location of its 'owner' ;; is instead returns. ;; (*) Since java functions are strings, local fields also have these ;; strings. In the context of looking for callers of a function you can ;; also give a string that names a java method. Same caveat re: false ;; positives. ;; In order to record information about local functions, ABCL defines a ;; function-plist, which is for the most part unused, but is used here ;; with set of keys indicating where the local function was defined and ;; in what manner, i.e. as normal local function, as a method function, ;; or as an initarg function. There may be other places functions are ;; stashed away (defstructs come to mind) and this file should be added ;; to to take them into account as they are discovered. ;; This file does not depend on jss, but provides a bit of ;; jss-specific functionality if jss *is* loaded. (defun function-internal-fields (f) "return a list of values of fields declared in the class implementing the function" (if (symbolp f) (setq f (symbol-function f))) ;; think about other fields (let ((fields (java:jcall "getDeclaredFields" (java:jcall "getClass" f)))) (loop for field across fields do (java:jcall "setAccessible" field t) collect (java:jcall "get" field f)))) (defun function-internals (f) "internal fields + closed-over values" (append (function-internal-fields f) (and (java:jcall "isInstance" (java::jclass "org.armedbear.lisp.CompiledClosure") f) (compiled-closure-context f)))) (defun compiled-closure-context (f) "For compiled closures, the values closed over" (let ((context (java:jcall "get" (load-time-value (java::jclass-field "org.armedbear.lisp.CompiledClosure" "ctx")) f))) (loop for binding across context collect (java:jcall "get" (load-time-value (java::jclass-field "org.armedbear.lisp.ClosureBinding" "value")) binding)))) (defun foreach-internal-field (fn-fn not-fn-fn &optional (fns :all) (definer nil)) "fn-n gets called with top, internal function, not-fn-fn gets called with top anything-but" (declare (optimize (speed 3) (safety 0))) (macrolet ((fields (c) `(java:jcall ,(java::jmethod "java.lang.Class" "getDeclaredFields") ,c)) (get (f i) `(java:jcall ,(java::jmethod "java.lang.reflect.Field" "get" "java.lang.Object") ,f ,i)) (access (f b) `(java:jcall ,(java::jmethod "java.lang.reflect.AccessibleObject" "setAccessible" "boolean") ,f ,b)) (getclass (o) `(java:jcall ,(java::jmethod "java.lang.Object" "getClass") ,o))) (labels ((function-internal-fields (f) (if (symbolp f) (setq f (symbol-function f))) (let ((fields (fields (getclass f)))) (loop for field across fields do (access field t) collect (get field f)))) (check (f top seen) (declare (optimize (speed 3) (safety 0))) (dolist (el (function-internal-fields f)) (if (functionp el) (let ((name? (third (multiple-value-list (function-lambda-expression el))))) (if (or (consp name?) (and name? (fboundp name?) (eq el (symbol-function name?))) ) (progn (when not-fn-fn (funcall not-fn-fn top name?)) (when (not (member el seen :test #'eq)) (push el seen) (check el top seen))) (when (not (member el seen :test #'eq)) (when fn-fn (funcall fn-fn top el)) (push el seen) (check el top seen)))) (when not-fn-fn (funcall not-fn-fn top el) ))))) (if (eq fns :all) (progn (dolist (p (list-all-packages)) (do-symbols (s p) (when (fboundp s) (check (symbol-function s) s nil)))) (each-non-symbol-compiled-function (lambda (definer f) (check f definer nil)))) (dolist (f fns) (check (if (not (symbolp f)) f (symbol-function f)) (or definer f) nil)) )))) (defun callers (thing &aux them) (foreach-internal-field nil (lambda(top el) (when (equal el thing) (pushnew top them) ))) them) (defun annotate-internal-functions (&optional (fns :all) definer) "Iterate over functions reachable from arg fns (all functions if :all). When not a top-level function add key: :internal-to-function value top-level thing in which the function is defined. definers are the top-level functions, This gets called after fset" (foreach-internal-field (lambda(top internal) (unless (eq (if (symbolp top) (symbol-function top) top) internal) (setf (getf (sys:function-plist internal) :internal-to-function) (or definer top)) )) nil fns definer)) (defvar *function-class-names* (make-hash-table :test 'equalp :weakness :value) "Table mapping java class names of function classes to their function. Value is either symbol or (:in symbol) if an internal function") (defun index-function-class-names (&optional (fns :all)) "Create a table mapping class names to function, for cases where the class name appears in backtrace (although perhaps that's a bug?)" (if (eq fns :all) (dolist (p (list-all-packages)) (do-symbols (s p) (when (and (eq (symbol-package s) p) (fboundp s) ;; system is touchy about #'autoload (not (eq (symbol-function s) #'autoload))) (unless (#"matches" (#"getName" (#"getClass" (symbol-function s))) ".*Closure$") (setf (gethash (#"getName" (#"getClass" (symbol-function s))) *function-class-names*) (symbol-function s)))))) (dolist (s fns) (setf (gethash (#"getName" (#"getClass" (if (symbolp s) (symbol-function s) s))) *function-class-names*) s))) (foreach-internal-field (lambda(top internal) (let ((fn (if (symbolp top) (symbol-function top) top))) (unless (or (eq fn internal) (#"matches" (#"getName" (#"getClass" fn)) ".*Closure$")) (setf (gethash (#"getName" (#"getClass" internal)) *function-class-names*) internal)))) nil fns nil)) (defun java-class-lisp-function (class-name) "Return either function-name or (:in function-name) or nil if class isn't that of lisp function" (gethash class-name *function-class-names* )) (defun annotate-clos-methods (&optional (which :all)) "Iterate over all clos methods, marking method-functions and method-fast-functions with the function plist indicator :method-function or :method-fast-function, value the method object. This gets called once." (flet ((annotate (method) (let ((method-function (mop::std-method-function method)) (fast-function (mop::std-method-fast-function method))) (when (and method-function (compiled-function-p method-function)) (setf (getf (sys:function-plist method-function) :method-function) method) (annotate-internal-functions (list method-function) method) (index-function-class-names (list method-function))) (when (and fast-function (compiled-function-p fast-function)) (setf (getf (sys:function-plist fast-function) :method-fast-function) method) (annotate-internal-functions (list fast-function) method) (index-function-class-names (list method-function)))))) (if (eq which :all) (loop for q = (list (find-class t)) then q for focus = (pop q) while focus do (setq q (append q (mop::class-direct-subclasses focus))) (loop for method in (mop::class-direct-methods focus) do (annotate method))) (dolist (f which) (annotate f) )))) (defun annotate-clos-slots (&optional (which :all)) "Iterate over all clos slots, marking compile-initarg functions as :initfunction value slot" (flet ((annotate (slot) (let ((initfunction (and (slot-boundp slot 'initfunction) (slot-value slot 'initfunction)))) (when initfunction (setf (getf (function-plist initfunction) :initfunction) slot) (annotate-internal-functions (list initfunction) slot))))) (if (eq which :all) (loop for q = (list (find-class t)) then q for focus = (pop q) while focus do (setq q (append q (mop::class-direct-subclasses focus))) (loop for slot in (mop::class-direct-slots focus) do (annotate slot))) (dolist (f which) (annotate f) )))) (defun method-spec-list (method) "Given a method object, translate it into specification (name qualifiers specializers)" `(,(mop::generic-function-name (mop::method-generic-function method)) ,(mop::method-qualifiers method) ,(mapcar #'(lambda (c) (if (typep c 'mop:eql-specializer) `(eql ,(mop:eql-specializer-object c)) (class-name c))) (mop:method-specializers method)))) ;; function names for printing, inspection and in the debugger (defun any-function-name (function &aux it) "Compute function name based on the actual function name, if it is a named function or the values on the function-plist that functions above have used annotate local functions" (cond ((typep function 'generic-function) (mop::generic-function-name function)) ((typep function 'mop::method) (mop::generic-function-name (mop::method-generic-function function))) (t (maybe-jss-function function) (let ((interpreted (not (compiled-function-p function)))) (let ((plist (sys::function-plist function))) (cond ((setq it (getf plist :internal-to-function)) `(:local-function ,@(if (java:jcall "getLambdaName" function) (list (java:jcall "getLambdaName" function)) (if (getf plist :jss-function) (list (concatenate 'string "#\"" (getf plist :jss-function) "\""))) ) ,@(if interpreted '((interpreted))) :in ,@(if (typep it 'mop::standard-method) (cons :method (method-spec-list it)) (list it)))) ((setq it (getf plist :method-function)) `(:method-function ,@(if interpreted '((interpreted))) ,@(sys::method-spec-list it))) ((setq it (getf plist :method-fast-function)) `(:method-fast-function ,@(if interpreted '("(interpreted)")) ,@(sys::method-spec-list it))) ((setq it (getf plist :initfunction)) (let ((class (and (slot-boundp it 'allocation-class) (slot-value it 'allocation-class)))) `(:slot-initfunction ,(slot-value it 'name ) ,@(if interpreted '((interpreted))) :for ,(if class (class-name class) '??)))) ((#"equals" function (symbol-function 'lambda)) '(:macro-function lambda)) ((equal (#"getName" (#"getClass" function)) "org.armedbear.lisp.MacroObject") `(:macro-object ,@(any-function-name #"{function}.expander"))) (t (or (and (nth-value 2 (function-lambda-expression function)) (if interpreted `(,(nth-value 2 (function-lambda-expression function)) ,'(interpreted)) (let ((name (nth-value 2 (function-lambda-expression function)))) (if (macro-function-p function) `(:macro ,name) name)))) (and (not (compiled-function-p function)) (let ((body (#"getBody" function))) (if (and (consp body) (consp (car body)) (eq (caar body) 'jss::invoke-restargs)) `(:interpreted-function ,(concatenate 'string "#\"" (cadar body) "\"")) `(:anonymous-interpreted-function)))) (function-name-by-where-loaded-from function))))))))) (defun function-name-by-where-loaded-from (function) "name of last resource - used the loaded-from field from the function to construct the name" (let* ((class (java:jcall "getClass" function)) (loaded-from (sys::get-loaded-from function)) (name (java:jcall "replace" (java:jcall "getName" class) "org.armedbear.lisp." "")) (where (and loaded-from (concatenate 'string (pathname-name loaded-from) "." (pathname-type loaded-from))))) `(:anonymous-function ,name ,@(if (sys::arglist function) (sys::arglist function)) ,@(if where (list (list :from where)))))) (defun maybe-jss-function (f) "Determing if function is something list #\"foo\" called as a function. If so add to function internal plist :jss-function and the name of the java methods" (and (find-package :jss) (compiled-function-p f) (or (getf (sys::function-plist f) :jss-function) (let ((internals (function-internal-fields f))) (and (= (length internals) 2) (eq (second internals) (intern "INVOKE-RESTARGS" :jss)) (stringp (first internals)) (setf (getf (sys:function-plist f) :jss-function) (first internals))))))) (defun local-function-p (function) "Helper function. Tests whether a function wasn't defined at top level based on function-plist annotations" (and (and (functionp function) (not (typep function 'generic-function))) (let ((plist (sys:function-plist function))) (or (getf plist :internal-to-function) (getf plist :method-function) (getf plist :method-fast-function) (getf plist :slot-initfunction))))) (defun local-function-owner (function) "For local function, return the 'owner' typically the top-level function or clos method" (local-function-p function)) (defvar *function-print-object-prefix* "function ") (defmethod print-object ((f function) stream) "Print a function using any-function-name. Requires a patch to system::output-ugly-object in order to prevent the function being printed by a java primitive" (if (or (typep f 'mop::generic-function) (typep f 'mop::method)) (call-next-method) (print-unreadable-object (f stream :identity t) (let ((name (any-function-name f))) (if (consp name) (format stream "~{~a~^ ~}" name) (format stream "~a~a" *function-print-object-prefix* name)))))) (defun each-non-symbol-compiled-function (f) (loop for q = (list (find-class t)) then q for focus = (pop q) while focus do (setq q (append q (mop::class-direct-subclasses focus))) (loop for method in (mop::class-direct-methods focus) do (when (compiled-function-p (mop::method-function method)) (funcall f method (mop::method-function method)))) (loop for slot in (mop::class-direct-slots focus) for initfunction = (and (slot-boundp slot 'initfunction) (slot-value slot 'initfunction)) do (and initfunction (compiled-function-p initfunction) (funcall f slot initfunction))))) ;; hooks into defining (defvar *fset-hooks* nil "functions on this list get called with name and function *after* the symbol-function is set") (defvar *annotate-function-backlog?* t "true before this file has been loaded and function annotations are placed") (defun fset-hook-annotate-internal-function (name function) "Called at the end of fset. If function annotations have not yet been added, add local function annotations to all functions. If not, just add annotations to function specified in the arglist" (when *annotate-function-backlog?* (setq *annotate-function-backlog?* nil) (annotate-internal-functions) (annotate-clos-methods) (annotate-clos-slots) (index-function-class-names) ;; still missing some cases e.g. generic functions and method functions ) (index-function-class-names (list function)) (annotate-internal-functions (list name))) ;; Here we hook into clos in order to have method and slot functions ;; annotated when they are defined. (defmethod mop::add-direct-method :after (class method) (annotate-clos-methods (list method))) (defmethod mop::ensure-class-using-class :after (class name &key direct-slots direct-default-initargs &allow-other-keys) (declare (ignore direct-slots direct-default-initargs)) (annotate-clos-slots (mop::class-direct-slots (find-class name)))) ;; Environments ;; Return a list of the variables and functions in an environment. The form of the list is ;; (kind name value) ;; where kind is either :lexical-variable or :lexical-function :special-variable (defun environment-parts (env) (append (loop for binding = (jss:get-java-field env "vars" t) then (jss:get-java-field binding "next" t) while binding for symbol = (jss:get-java-field binding "symbol" t) for value = (jss:get-java-field binding "value" t) for special = (jss:get-java-field binding "specialp" t) if (member symbol '(:catch)) collect `(,symbol ,value) into them else unless (find symbol them :key 'second) collect (list (if special :special-variable (if (jss:jtypep value 'lisp.SymbolMacro) :symbol-macro :lexical-variable)) symbol (if (jss:jtypep value 'lisp.SymbolMacro) (#"getExpansion" value) value)) into them finally (return them)) (loop for binding = (jss:get-java-field env "lastFunctionBinding" t) then (jss:get-java-field binding "next" t) while binding for name = (jss:get-java-field binding "name" t) for value = (jss:get-java-field binding "value" t) unless (find name them :key 'second) collect (list :lexical-function name value) into them finally (return them)) (loop for binding = (jss::get-java-field env "blocks" t) then (jss::get-java-field binding "next" t) while binding for name = (jss::get-java-field binding "symbol" t) for value = (jss::get-java-field binding "value" t) unless (find name them :key 'second) collect (list :block name value) into them finally (return them)))) ;; Locals ;; Locals are retrived from envStack, a stack of environments and ;; function call markers distinct from the call stack, one per ;; thread. Locals are only available for interpreted functions. The ;; envStack is distinct from the call stance because there are function ;; calls which create environments, for instance to special operators ;; like sf_let, that are not in the lisp call stack. ;; A function call marker in this context is an environment with a variable binding ;; whose symbol is nil. Implementing the markers this way means we don't have ;; to deal with different sorts of things on the envStack, which makes the ;; java side of things easier. ;; Environments are chained. So a binding of a new local, by e.g. let, will ;; have a new environment created which has the new binding and a pointer ;; to the environment with the previous binding. ;; Since all environments created are on the envStack, we have to figure ;; out which environment is the one that is the most current for a given ;; function being executed when we land in the debugger. ;; collapse-locals is responsible for filtering out the environments ;; that aren't the most current for each function being executed. It ;; returns a list whose head is the function being executed and whose ;; tail is a list of bindings from environment-parts. ;; have to get the stack contents using this instead of j2list as in ;; that case we get a concurrent modification exception as we iterate ;; through the iterator, when some other function call is made. ;; BEGIN use :abcl-introspect/system (in-package :abcl-introspect/system) (defun collapse-locals (thread) (flet ((stack-to-list (stack) (coerce (#"toArray" stack) 'list))) (loop for bindings in (mapcar 'sys::environment-parts (stack-to-list (jss:get-java-field thread "envStack" t))) with last-locals with last-function for binding = (car bindings) if (eq (second binding) nil) collect (prog1 (list last-function last-locals) (setq last-locals nil) (setq last-function (third binding))) else do (setq last-locals bindings)))) ;; Now that we have the pairings of function-executing and lexicals we need ;; to associate each such function with the stack frame for it being ;; called. To do that, for each function and locals we find and record the ;; first occurrence of the function in the backtrace. Functions may appear ;; more than once in the envStack because they have been called more than ;; once. In addition the envStack will have more functions than there are ;; frames. ;; In order for our envstack association to be an alignment with the stack, ;; the associations must be in ascending order. That is, if we start at ;; the top of the collapsed envstack, then the frame number each function ;; is associated with must be in ascending order. ;; So, first walk through the associations and remove any frame numbers ;; above that are greater than the index of this association. e.g. if we ;; have ;; (f1 frame#3 locals) ;; (f2 frame#2 locals) ;; then frame#3 must be a wrong pairing since it is out of order. So we ;; erase those to get ;; (f1 nil locals) ;; (f2 frame#2 locals) ;; Also, since there may be more than one call to a function we might have ;; something like ;; (f1 frame#2 locals) ;; (f2 frame#3 locals) ;; (f1 frame#2 locals) ;; Only the first one is right, so we erases subsequent ones, yielding ;; (f1 frame#2 locals) ;; (f2 frame#3 locals) ;; (f1 nil locals) ;; At this point we now have a some-to-one mapping of functions to frames ;; find-locals takes a backtrace and an index of a frame in that backtrace ;; and returns the locals for the frame. To get it we just search for the ;; first entry that has the required frame number. ;; find-locals still has debugging code in it which will be removed after ;; there has been sufficient testing. ;;; ME: presumably *debugging-locals-p* can go away now? (defvar *debugging-locals-p* nil "Whether SYS:FIND-LOCALS should be looking for local variables") (defun find-locals (index backtrace) "Return local variable bindings at INDEX in BACKTRACE Added by ABCL-INTROSPECT." (let ((thread (jss:get-java-field (nth index backtrace) "thread" t))) (and *debugging-locals-p* (print `(:collapse ,thread ,index))) (let ((collapsed (collapse-locals thread))) (and *debugging-locals-p* (map nil 'print collapsed)) (let ((alignment (loop for function-local-association in (reverse collapsed) with backtrace = (map 'list (if *debugging-locals-p* 'print 'identity) backtrace) for pos = (position (car function-local-association) backtrace :key (lambda(frame) (if (typep frame 'sys::lisp-stack-frame) (#"getOperator" frame) (jss:get-java-field frame "METHOD" t)))) collect (list (car function-local-association) pos (cdr function-local-association))))) (and *debugging-locals-p* (print :erase) (map nil 'print alignment)) ;; first erasure of out of order frames (loop for (nil pos) in alignment for i from 0 when pos do (loop for pair in (subseq alignment 0 i) for (nil pos2) = pair unless (null pos2) if (> pos2 pos) do (setf (second pair) nil))) (and *debugging-locals-p* (print :align) (map nil 'print alignment)) ;; second erasure of duplicate frame numbers (loop for (nil pos) in alignment for i from 0 do (loop for pair in (subseq alignment (1+ i)) for (nil pos2) = pair unless (null pos2) if (eql pos2 pos) do (setf (second pair) nil))) (and *debugging-locals-p* (map nil 'print alignment)) (if *debugging-locals-p* (print `(:find ,(cddr (find index alignment :key 'second :test 'eql))))) ;; finally, look up the locals for the given frame index (cddr (find index alignment :key 'second :test 'eql)))))) ;; END use :abcl-introspect/system (in-package :system) ;; needs to be the last thing. Some interaction with the fasl loader (pushnew 'fset-hook-annotate-internal-function sys::*fset-hooks*) (provide :abcl-introspect) abcl-src-1.9.0/contrib/abcl-introspect/byte-code.lisp0100644 0000000 0000000 00000000152 14202767264 021243 0ustar000000000 0000000 (in-package :abcl-introspect) (defun choose-disassemble () (warn "Unimplemented choose dissambler.")) abcl-src-1.9.0/contrib/abcl-introspect/cfr.asd0100644 0000000 0000000 00000000463 14202767264 017747 0ustar000000000 0000000 (defsystem cfr :homepage "https://www.benf.org/other/cfr" :description "CFR - a Class File Reader decompiler" :components ((:module mvn-libs :components ((:mvn "org.benf/cfr/0.149"))) (:module source :depends-on (mvn-libs) :pathname "" :components ((:file "cfr"))))) abcl-src-1.9.0/contrib/abcl-introspect/cfr.lisp0100644 0000000 0000000 00000001466 14202767264 020153 0ustar000000000 0000000 (defpackage :abcl-introspect/jvm/tools/cfr (:use :cl) (:export #:disassemble-class-bytes)) (in-package :abcl-introspect/jvm/tools/cfr) (defun cfr-jar-pathname () ;; Very ugly. How to make more intelligble? (slot-value (first (asdf:component-children (asdf:find-component :cfr "mvn-libs"))) 'asdf/interface::resolved-classpath)) (defun disassemble-class-bytes (object) (let ((sys::*disassembler* ;; FIXME: use same java that is hosting ABCL (format nil "java -jar ~a" (cfr-jar-pathname)))) (sys:disassemble-class-bytes object))) (eval-when (:load-toplevel :execute) (pushnew `(:cfr . abcl-introspect/jvm/tools/cfr::disassemble-class-bytes) sys::*disassemblers*) (format cl:*load-verbose* "~&; ~a: Successfully added cfr disassembler.~%" *package*)) abcl-src-1.9.0/contrib/abcl-introspect/fernflower.asd0100644 0000000 0000000 00000000664 14202767264 021351 0ustar000000000 0000000 (defsystem fernflower :depends-on (alexandria abcl-introspect) :homepage "https://github.com/fesh0r/fernflower" :version "1.0.0.20271018" :description "An analytical decompiler for Java" :components ((:module mvn-libs :components ((:mvn "org.jboss.windup.decompiler.fernflower/windup-fernflower/1.0.0.20171018"))) (:module source :depends-on (mvn-libs) :pathname "" :components ((:file "fernflower"))))) abcl-src-1.9.0/contrib/abcl-introspect/fernflower.lisp0100644 0000000 0000000 00000002507 14202767264 021547 0ustar000000000 0000000 (defpackage :abcl-introspect/jvm/tools/fernflower (:use :cl) (:export #:disassemble-class-bytes)) (in-package :abcl-introspect/jvm/tools/fernflower) (defun fernflower-classpath () ;; Very ugly. How to make more intelligble? (slot-value (first (asdf:component-children (asdf:find-component :fernflower "mvn-libs"))) 'asdf/interface::resolved-classpath)) (defun disassemble-class-bytes (object) (uiop/stream::with-temporary-file (:pathname p :type "class") (ext::write-class object p) (let* ((directory (namestring (truename (make-pathname :directory (pathname-directory p))))) (path (namestring (truename p))) (command (format nil "java -cp ~a org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler ~a ~a" (fernflower-classpath) p directory)) (output (namestring (make-pathname :defaults p :type "java")))) (uiop:run-program command) (let ((result (alexandria:read-file-into-string output))) (sys::print-lines-with-prefix result))))) (eval-when (:load-toplevel :execute) (pushnew `(:fernflower . abcl-introspect/jvm/tools/fernflower::disassemble-class-bytes) sys::*disassemblers*) (format cl:*load-verbose* "~&; ~a: Successfully added fernflower decompiler.~%" *package*)) abcl-src-1.9.0/contrib/abcl-introspect/jad.asd0100644 0000000 0000000 00000000325 14202767264 017730 0ustar000000000 0000000 (defsystem jad :homepage "http://www.javadecompilers.com/jad/" :description "Introspect runtime architecture, install appropiate JAD binary, use it." :depends-on (abcl-build) :components ((:file "jad"))) abcl-src-1.9.0/contrib/abcl-introspect/jad.lisp0100644 0000000 0000000 00000003062 14202767264 020131 0ustar000000000 0000000 (defpackage :abcl-introspect/jvm/tools/jad (:use #:cl) (:nicknames #:jvm/tools/jad #:jad) (:export #:disassemble-class-bytes)) #| |# (in-package :abcl-introspect/jvm/tools/jad) (defun introspect-jad-uri () (uiop:os-cond ((uiop/os:os-macosx-p) "http://www.javadecompilers.com/jad/Jad%201.5.8g%20for%20Mac%20OS%20X%2010.4.6%20on%20Intel%20platform.zip"))) (defvar *working-jad-executable* nil) (defun ensure-jad () (flet ((install-jad-returning-path (uri) (abcl-build:xdg/install (pathname uri) :type :unzip)) (working-jad-p (jad-path) (handler-case (uiop:run-program jad-path) (uiop/run-program:subprocess-error (e) nil)))) (if (null *working-jad-executable*) (let ((jad-path (abcl-build:introspect-path-for "jad"))) (if (and jad-path (working-jad-p jad-path)) (setf *working-jad-executable* jad-path) (progn (install-jad-returning-path (introspect-jad-uri)) (setf *working-jad-executable* jad-path)))) (unless (working-jad-p *working-jad-executable*) (setf *working-jad-executable* (install-jad-returning-path (introspect-jad-uri))))))) (defun disassemble-class-bytes (object) (ensure-jad) (let ((sys::*disassembler* (format nil "~s -a -p" *working-jad-executable*))) (sys:disassemble-class-bytes object))) abcl-src-1.9.0/contrib/abcl-introspect/javap.asd0100644 0000000 0000000 00000000332 14202767264 020271 0ustar000000000 0000000 (defsystem javap :homepage "" ;; FIXME :description "Utilization of the javap command line dissassembler" :components ((:file "javap"))) abcl-src-1.9.0/contrib/abcl-introspect/javap.lisp0100644 0000000 0000000 00000001276 14202767264 020501 0ustar000000000 0000000 (defpackage :abcl-introspect/jvm/tools/javap (:use #:cl) (:export #:disassemble-class-bytes)) ;;;; JDK javap #| (let ((sys::*disassembler* "javap -c -verbose")) (disassemble 'cons)) |# (in-package :abcl-introspect/jvm/tools/javap) (defun disassemble-class-bytes (object) (let ((sys::*disassembler* "javap -c -verbose")) (sys:disassemble-class-bytes object))) (eval-when (:load-toplevel :execute) (pushnew `(:javap . abcl-introspect/jvm/tools/javap::disassemble-class-bytes) sys::*disassemblers*) (format cl:*load-verbose* "~&; ~a ; Successfully added javap disassembler.~%" *package*)) abcl-src-1.9.0/contrib/abcl-introspect/objectweb.asd0100644 0000000 0000000 00000000612 14202767264 021135 0ustar000000000 0000000 (defsystem objectweb :homepage "https://asm.ow2.org" :description "Disassembly to JVM byte code via Objectweb" :version "8.0.1" :defsystem-depends-on (abcl-asdf) :components ((:module maven :components ((:mvn "org.ow2.asm/asm-util/8.0.1"))) (:module source :depends-on (maven) :pathname "" :components ((:file "objectweb"))))) abcl-src-1.9.0/contrib/abcl-introspect/objectweb.lisp0100644 0000000 0000000 00000001740 14202767264 021340 0ustar000000000 0000000 (defpackage :abcl-introspect/jvm/tools/objectweb (:use :cl) (:export #:disassemble-class-bytes)) (in-package :abcl-introspect/jvm/tools/objectweb) (defun disassemble-class-bytes (object) (let* ((reader (java:jnew "org.objectweb.asm.ClassReader" object)) (writer (java:jnew "java.io.StringWriter")) (printer (java:jnew "java.io.PrintWriter" writer)) (tracer (java:jnew "org.objectweb.asm.util.TraceClassVisitor" java:+null+ printer)) ;; this is to support both the 1.X and subsequent releases (flags (ignore-errors (java:jfield "org.objectweb.asm.ClassReader" "SKIP_DEBUG")))) (java:jcall-raw "accept" reader tracer (or flags java:+false+)) (java:jcall "toString" writer))) (eval-when (:load-toplevel :execute) (pushnew `(:objectweb . abcl-introspect/jvm/tools/objectweb::disassemble-class-bytes) sys::*disassemblers*) (format cl:*load-verbose* "~&; ~a ; Successfully added Objectweb disassembler.~%" *package*)) abcl-src-1.9.0/contrib/abcl-introspect/packages.lisp0100644 0000000 0000000 00000001227 14212332540 021134 0ustar000000000 0000000 (defpackage abcl-introspect/system (:nicknames #:abcl-introspect/sys) (:use :common-lisp) (:export #:*debugging-locals-p* #:find-locals)) ;;; Import and externalize all external symbols of ;;; ABCL-INTROSPECT/SYSTEM from the SYSTEM package. Following this ;;; discipline will allow us to sanely determine what symbols ;;; ABCL-INTROSPECT adds to SYSTEM. ;;; ;;; TODO: do this for the rest of abcl-introspect.lisp and ;;; stacktrace.lisp (eval-when (:compile-toplevel :load-toplevel) (loop :for symbol :being :the :external-symbols :of :abcl-introspect/system :doing (import symbol :system) (export symbol :system))) abcl-src-1.9.0/contrib/abcl-introspect/procyon.asd0100644 0000000 0000000 00000000646 14202767264 020671 0ustar000000000 0000000 (defsystem procyon :homepage "https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler" :description "A Java decompiler by Mike Strobel" :version "0.5.36" :depends-on (alexandria) :components ((:module mvn-libs :components ((:mvn "org.bitbucket.mstrobel/procyon-compilertools/0.5.36"))) (:module source :depends-on (mvn-libs) :pathname "" :components ((:file "procyon"))))) abcl-src-1.9.0/contrib/abcl-introspect/procyon.lisp0100644 0000000 0000000 00000002734 14202767264 021071 0ustar000000000 0000000 (defpackage :abcl-introspect/jvm/tools/procyon (:use :cl) (:export #:disassemble-class-bytes)) (in-package :abcl-introspect/jvm/tools/procyon) (defun disassemble-class-bytes (object) #| final DecompilerSettings settings = DecompilerSettings.javaDefaults(); try (final FileOutputStream stream = new FileOutputStream("path/to/file"); final OutputStreamWriter writer = new OutputStreamWriter(stream)) { Decompiler.decompile( "java/lang/String", new PlainTextOutput(writer), settings ); } catch (final IOException e) { // handle error } |# (let* ((settings (#"javaDefaults" 'DecompilerSettings)) (writer (jss:new 'java.io.StringWriter))) (#"decompile" 'Decompiler ;;; !!! need to reference as a type in the current VM ;;; c.f. object (jss:new 'PlainTextOutput writer) settings) (write (#"toString writer")))) (eval-when (:load-toplevel :execute) (pushnew `(:procyon . abcl-introspect/jvm/tools/procyon::disassemble-class-bytes) sys::*disassemblers*) (format cl:*load-verbose* "~&; ~a: Successfully added procyon disassembler.~%" *package*)) abcl-src-1.9.0/contrib/abcl-introspect/stacktrace.lisp0100644 0000000 0000000 00000040167 14202767264 021526 0ustar000000000 0000000 (in-package :system) (require :jss) ;; for now ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; I don't understand the algorithm that sys:backtrace uses, which seems ;; broken, so here's an alternative. ;; The lisp portion of the stack backtrace is computed as it is now. It ;; will have invoke-debugger at the top then some java stack frames that ;; abcl pushes (the "i don't understand") and then the rest of the ;; backtrace. We trim that by popping off the invoke-debugger and java ;; stack frames, leaving just lisp frames. ;; If there's a java exception. In that case we compare the stacktrace of ;; the exception to the java stack trace and grab the top part of it ;; that's unique to the exception. We prepend this to the lisp stack ;; trace. ;; The result will be that we will *not* see the call to invoke debugger, ;; or any of the swank handling, just what (I think) is relative. ;; What still needs to be investigated is how this plays in cases where ;; there are callbacks to lisp from java. ;; A good test to see the difference would be ;; (#"replaceAll" "" "(?o" "") ;; which should now show the calls within the regex code leading to ;; the exception. (defvar *use-old-backtrace* nil "set to t to fall back to the standard backtrace") (defvar *hide-swank-frames* t "set to nil if you want to see debugger internal frames") (defvar *unwelcome-java-frames* '("sun.reflect.Native.*AccessorImpl\\..*" "sun.reflect.Delegating.*AccessorImpl\\..*" "sun.reflect.Generated.*Accessor\\d+\\.invoke") "if a java frame matches any of these patterns, don't show it" ) (defvar *caught-frames* nil "When backtrace is called, it sets this to the java stack frames that are unique to the java exception, which is then subsequently used by slime to mark them") (defun swankish-frame (frame) "hackish test for whether a frame is some internal function from swank" (let ((el (car (sys::frame-to-list frame)))) (let ((package (cond ((and (symbolp el) (symbol-package el)) (package-name (symbol-package el))) ;; hack! really I mean anything with a function plist ((eq (type-of el) 'compiled-function) (let ((owner (getf (function-plist el) :internal-to-function))) (if (and (symbolp owner) (symbol-package owner)) (package-name (symbol-package owner)) ""))) (t "")))) (and package (#"matches" package "SWANK.*"))))) (defun javaframe (java-stack-frame) "Return the java StackFrame instance" (if (java::java-object-p java-stack-frame) java-stack-frame (#"get" (load-time-value (java::jclass-field "org.armedbear.lisp.JavaStackFrame" "javaFrame")) java-stack-frame))) (defun stackframe-head (frame &optional with-method) "If a lisp frame, the function (symbol or function). In a java frame the class name, with method if with-method is t" (if (null frame) nil (if (typep frame 'lisp-stack-frame) (#"getOperator" frame) (let ((frame (if (typep frame 'java-stack-frame) (javaframe frame) frame))) (if with-method (concatenate 'string (#"getClassName" frame) "." (#"getMethodName" frame)) (#"getClassName" frame)))))) (defun backtrace-invoke-debugger-position (stacktrace) "Position of the call to invoke-debugger" (let ((looking-for `(invoke-debugger ,#'invoke-debugger))) (position-if (lambda(e) (memq (#"getOperator" e) looking-for)) stacktrace))) (defun swank-p () "are we running with slime/swank? This should work without swank too" (find-package 'swank)) (defun repl-loop-position (stacktrace start) "Position of the frame starting the repl at this level" (if (swank-p) (position-if (lambda(e) (eq (stackframe-head e) (intern "SLDB-LOOP" 'swank))) stacktrace :start start) (position-if (lambda(e) (eq (stackframe-head e) 'debug-loop)) stacktrace :start start) )) (defun last-internal-calls-position (stacktrace) "Some java frames are replicates of the lisp stack frame. This gets the position of the closest to top non-user lisp call. It should leave intact frames corresponding to cases where a piece of lisp implemented in java calls another lisp function" (let ((pos (position-if (lambda(e) (and (not (typep e 'lisp-stack-frame)) (not (member (#"getMethodName" (javaframe e)) '("execute" "evalCall" "eval" "funcall" "apply") :test 'equal)))) stacktrace :from-end t))) pos)) (defun java-frame-segment (stacktrace) "Returns the bounds of the section of the backtrace that have been added with pushJavaStackFrame" (let ((start (position-if (lambda(e) (typep e 'java-stack-frame)) stacktrace))) (and start (list start (position-if (lambda(e) (typep e 'lisp-stack-frame)) stacktrace :start start))))) (defun splice-out (sequence from to) "remove elements from->to from sequence" (append (subseq sequence 0 from) (subseq sequence to))) (defun splice-out-java-stack-duplicating-lisp-stack (stacktrace) "cut out a section of java frames, maximally ending at the first lisp stack frame hit" (let ((extra-java-frames-pos (last-internal-calls-position stacktrace))) (let ((spliced (if extra-java-frames-pos (append (subseq stacktrace 0 extra-java-frames-pos) (let ((lisp-frame-pos (position 'lisp-stack-frame stacktrace :key 'type-of :start extra-java-frames-pos))) (and lisp-frame-pos (subseq stacktrace (position 'lisp-stack-frame stacktrace :key 'type-of :start extra-java-frames-pos))))) stacktrace))) spliced))) (defun difference-between-exception-stacktrace-and-after-caught-stacktrace (condition) "When there's a java exception, the condition has the stack trace as it was when the exception was thrown. Our backtrace is after it is caught. This function gets the difference - the frames unique to the exception" (let* ((exception-stack-trace (coerce (#"getStackTrace" (java::java-exception-cause condition)) 'list)) (debugger-stack-trace (coerce (subseq exception-stack-trace (position (#"getName" (#"getClass" #'invoke-debugger)) (#"getStackTrace" (#"currentThread" 'Thread)) :key #"getClassName" :test 'string-equal)) 'list))) (subseq exception-stack-trace 0 (position-if (lambda(frame) (find frame debugger-stack-trace :test (lambda(a b ) (eql (#"hashCode" a) (#"hashCode" b))))) exception-stack-trace)))) (defun remove-unsightly-java-frames (stacktrace) "Remove uninformative java frames, typically bits of the internals of the java implementation" (remove-if (lambda(frame) (member (stackframe-head frame t) *unwelcome-java-frames* :test #"matches")) stacktrace)) ;; 3: (invoke-debugger #) ;; 4: org.armedbear.lisp.Lisp.error(Lisp.java:385) ;; 5: (invoke-debugger #) ;; 6: (error #) ;; 7: (# #) ;; 8: (signal #) ;; 9: org.armedbear.lisp.Lisp.error(Lisp.java:385) (defun lisp-stack-exception-catching-frames (stacktrace) "The frames corresponding to ABCL's internal handling of an exception" (and (eq (stackframe-head (car stacktrace)) 'invoke-debugger) (let ((error-position (position "org.armedbear.lisp.Lisp.error" stacktrace :key (lambda(e) (stackframe-head e t)) :test 'equal))) (if error-position (subseq stacktrace 0 (1+ error-position)) (list (car stacktrace)) )))) (defun splice-out-spurious-error-frames (stacktrace) "if there are nested exceptions sometimes there are extra (error), , (signal) frames. we only want the first error. Remove repeated ones. Illiustrated by first getting an errors with an inconsistent ontology and then calling (read-from-string \"#<\") to generate a reader error. Get rid of these. Finally, if the next next frame after error is signal of the same condition, those two frames are also removed" (let ((error-position (position 'error stacktrace :key 'stackframe-head))) (if (and error-position (> (length stacktrace) (+ error-position 3))) (loop with trash = 0 for pos = error-position then next for next = (+ pos 3) until (not (eq (stackframe-head (nth next stacktrace)) 'error)) do (incf trash 3) finally (return (let ((spliced (if (> trash 1) (splice-out stacktrace (1+ error-position) (+ error-position trash 1)) stacktrace))) (if (and (eq (stackframe-head (nth (+ error-position 2) spliced)) 'signal) (eq (second (frame-to-list (nth error-position spliced))) (second (frame-to-list (nth (+ error-position 2) spliced))))) (splice-out spliced (1+ error-position) (+ error-position 3)) stacktrace)))) stacktrace))) (defun new-backtrace (condition) "New implementation of backtrace that tries to clean up the stack trace shown when an error occurs. There are a bunch of idiosyncrasies of what sys:backtrace generates which land up obscuring what the problem is, or at least making it more of a hunt than one would want. This backtrace tries to show only stuff I think matters - user function calls and, when there's an exception, calls inside the lisp implementation leading to the error" (if *use-old-backtrace* (backtrace) (let* ((lisp-stacktrace (#"backtrace" (threads::current-thread) 0)) (invoke-pos (backtrace-invoke-debugger-position lisp-stacktrace)) (repl-loop-pos (repl-loop-position lisp-stacktrace invoke-pos))) (let ((narrowed-lisp-stacktrace (splice-out-java-stack-duplicating-lisp-stack (subseq lisp-stacktrace invoke-pos (and repl-loop-pos (1+ repl-loop-pos)))))) (when *hide-swank-frames* (let ((swank-start (position-if 'swankish-frame narrowed-lisp-stacktrace))) (and swank-start (setq narrowed-lisp-stacktrace (append (subseq narrowed-lisp-stacktrace 0 swank-start) (if repl-loop-pos (last narrowed-lisp-stacktrace) nil)))))) (setq narrowed-lisp-stacktrace (splice-out-spurious-error-frames narrowed-lisp-stacktrace)) (if (typep condition 'java::java-exception) (progn (let* ((delta (difference-between-exception-stacktrace-and-after-caught-stacktrace condition)) (cleaned (splice-out-java-stack-duplicating-lisp-stack (remove-unsightly-java-frames delta))) (exception-frames (lisp-stack-exception-catching-frames narrowed-lisp-stacktrace))) (setq *caught-frames* delta) (let ((result (append exception-frames (mapcar (lambda(frame) (jss::new 'javastackframe frame)) cleaned) (subseq narrowed-lisp-stacktrace (length exception-frames))))) result ))) narrowed-lisp-stacktrace))))) #| (defmethod ho ((a t)) (read-from-string "(#\"setLambdaName\" # '(flet a))")) (defmethod no ((a t)) (read-from-string "(#\"setLambdaName\" # '(flet a))")) (defmethod fo () (ho 1) (no 1)) (defun bar () (fo)) (defun foo () (funcall #'bar)) (defun baz () (foo)) caused by reader-error Checking for execute isn't enough. Symbol.execute might be good So maybe modify: Find invoke-debugger position go down stack until you reach a symbol.execute, then skip rest of string of java frames. Right now I skip from invoke-debugger to next list but because signal is there it gets stuck. 5: (invoke-debugger #) below here ok 6: (error #) 7: (# #) 8: (signal #) 9: org.armedbear.lisp.Lisp.error(Lisp.java:385) 10: org.armedbear.lisp.LispReader$22.execute(LispReader.java:350) 11: org.armedbear.lisp.Stream.readDispatchChar(Stream.java:813) 12: org.armedbear.lisp.LispReader$6.execute(LispReader.java:130) 13: org.armedbear.lisp.Stream.processChar(Stream.java:588) 14: org.armedbear.lisp.Stream.readList(Stream.java:755) 15: org.armedbear.lisp.LispReader$3.execute(LispReader.java:88) 16: org.armedbear.lisp.Stream.processChar(Stream.java:588) 17: org.armedbear.lisp.Stream.readPreservingWhitespace(Stream.java:557) 18: org.armedbear.lisp.Stream.readPreservingWhitespace(Stream.java:566) 19: org.armedbear.lisp.Stream.read(Stream.java:501) above here is ok below here junk 20: org.armedbear.lisp.Stream$16.execute(Stream.java:2436) 21: org.armedbear.lisp.Symbol.execute(Symbol.java:826) 22: org.armedbear.lisp.LispThread.execute(LispThread.java:851) 23: org.armedbear.lisp.swank_528.execute(swank.lisp:1732) 24: org.armedbear.lisp.Symbol.execute(Symbol.java:803) 25: org.armedbear.lisp.LispThread.execute(LispThread.java:814) 26: org.armedbear.lisp.swank_repl_47.execute(swank-repl.lisp:270) 27: org.armedbear.lisp.LispThread.execute(LispThread.java:798) 28: org.armedbear.lisp.swank_repl_48.execute(swank-repl.lisp:283) 29: org.armedbear.lisp.Symbol.execute(Symbol.java:803) 30: org.armedbear.lisp.LispThread.execute(LispThread.java:814) 31: org.armedbear.lisp.swank_repl_46.execute(swank-repl.lisp:270) 32: org.armedbear.lisp.LispThread.execute(LispThread.java:798) 33: org.armedbear.lisp.swank_272.execute(swank.lisp:490) 34: org.armedbear.lisp.Symbol.execute(Symbol.java:814) 35: org.armedbear.lisp.LispThread.execute(LispThread.java:832) 36: org.armedbear.lisp.swank_repl_45.execute(swank-repl.lisp:270) 37: org.armedbear.lisp.LispThread.execute(LispThread.java:798) 38: abcl_fcbf3596_211f_4d83_bc8b_e11e207b8d21.execute(Unknown Source) 39: org.armedbear.lisp.LispThread.execute(LispThread.java:814) 40: org.armedbear.lisp.Lisp.funcall(Lisp.java:172) 41: org.armedbear.lisp.Primitives$pf_apply.execute(Primitives.java:2827) end junk 42: (read #S(system::string-input-stream) nil #S(system::string-input-stream)) 43: (swank::eval-region "(#\"setLambdaName\" # '(flet a))\n") 44: (#) From a compiled function looks different 0: (error #) 1: (# #) 2: (signal #) 3: org.armedbear.lisp.Lisp.error(Lisp.java:385) 4: org.armedbear.lisp.LispReader$22.execute(LispReader.java:350) 5: org.armedbear.lisp.Stream.readDispatchChar(Stream.java:813) 6: org.armedbear.lisp.LispReader$6.execute(LispReader.java:130) 7: org.armedbear.lisp.Stream.processChar(Stream.java:588) 8: org.armedbear.lisp.Stream.readList(Stream.java:755) 9: org.armedbear.lisp.LispReader$3.execute(LispReader.java:88) 10: org.armedbear.lisp.Stream.processChar(Stream.java:588) 11: org.armedbear.lisp.Stream.readPreservingWhitespace(Stream.java:557) 12: org.armedbear.lisp.Stream.readPreservingWhitespace(Stream.java:566) 13: org.armedbear.lisp.Stream.read(Stream.java:501) <- this is probably where we want the stack to stop. Looks like symbol.execute 14: org.armedbear.lisp.Stream$15.execute(Stream.java:2387) <= %read from string 15: org.armedbear.lisp.Symbol.execute(Symbol.java:867) 16: org.armedbear.lisp.LispThread.execute(LispThread.java:918) 17: org.armedbear.lisp.read_from_string_1.execute(read-from-string.lisp:33) 18: org.armedbear.lisp.CompiledClosure.execute(CompiledClosure.java:98) 19: org.armedbear.lisp.Symbol.execute(Symbol.java:803) 20: org.armedbear.lisp.LispThread.execute(LispThread.java:814) 21: abcl_2ad63c53_52f1_460b_91c2_1b153251d9f3.execute(Unknown Source) 22: org.armedbear.lisp.LispThread.execute(LispThread.java:798) 23: org.armedbear.lisp.Lisp.evalCall(Lisp.java:572) 24: org.armedbear.lisp.Lisp.eval(Lisp.java:543) 25: org.armedbear.lisp.Primitives$pf__eval.execute(Primitives.java:345) 26: (system::%read-from-string "(#\"setLambdaName\" # '(flet a))" t nil 0 nil nil) 27: (read-from-string "(#\"setLambdaName\" # '(flet a))") 28: (system::bar) |# #| Don't really want 456. Ban them outright? No - make a list 4: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 5: sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 6: sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 7: java.lang.reflect.Method.invoke(Method.java:497) |# ;; (#"setLambdaName" # '(flet a)) ;; reader error is still ugly. Maybe anything that calls signal. (provide :stacktrace) abcl-src-1.9.0/contrib/abcl-introspect/t/disassemble.lisp0100644 0000000 0000000 00000003351 14202767264 022132 0ustar000000000 0000000 (in-package :cl-user) (let ((disassembler (first (abcl-build:split-string ext:*disassembler* #\Space)))) (prove:plan 1) (prove:ok (abcl-build:introspect-path-for disassembler) (format nil "Testing invocation of ~a specified by EXT:*DISASSEMBLER*…" disassembler))) (let ((disassemblers '(:objectweb :javap :jad :fernflower :cfr :procyon))) (prove:plan (* 2 (length disassemblers))) (dolist (disassembler disassemblers) (prove:ok (asdf:load-system disassembler) (format nil "Loading ~a" disassembler)) (prove:ok (handler-case (let ((expected (intern :disassemble-class-bytes (format nil "ABCL-INTROSPECT/JVM/TOOLS/~a" (symbol-name disassembler))))) (equal (sys:choose-disassembler disassembler) expected)) (t (e) (progn (prove:diag (format nil "Choosing ~a failed: ~a" disassembler e)) nil))) (format nil "Able to choose ~a disassembler" disassembler))) (prove:plan (length disassemblers)) (dolist (disassembler disassemblers) (let ((output (make-string-output-stream))) (prove:ok (handler-case (let ((*standard-output* output)) (sys:choose-disassembler disassembler) (cl:disassemble #'cons) (let ((result (get-output-stream-string output))) (not (null (and result (stringp result) (> (length result) 0)))))) (t (e) (progn (prove:diag (format nil "Invocation failed: ~a" e)) nil))) (format nil "Invocation of ~a disassembler" disassembler))))) (prove:finalize) abcl-src-1.9.0/contrib/abcl-introspect/t/environments.lisp0100644 0000000 0000000 00000002030 14212332540 022341 0ustar000000000 0000000 (in-package :cl-user) (defmacro env-parts (&environment env) `(sys::environment-parts ,env)) (prove:plan 1) (prove:is (eval '(let ((a 10)) (env-parts))) '((:lexical-variable a 10)) "Lexical let binding captures local") (prove:plan 1) (prove:ok (let ((env-parts-information (eval '(let ((b 20)) (defun bar () (let ((a 10)) (env-parts))) (bar)))) (expected-clauses #| Testing envionment actually contains: ((:LEXICAL-VARIABLE A 10) (:LEXICAL-VARIABLE B 20) (:BLOCK BAR #)) |# '((:LEXICAL-VARIABLE A 10) (:LEXICAL-VARIABLE B 20)))) ;;; FIXME find a more idiomatic way to do this that also reports ;;; what fails. Use CL:INTERSECTION (reduce (lambda (a b) (and a b)) (mapcar (lambda (item) (member item env-parts-information :test #'equalp)) expected-clauses))) "Nested lexical bindings captures locals") (prove:finalize) abcl-src-1.9.0/contrib/abcl-introspect/util.lisp0100644 0000000 0000000 00000004547 14202767264 020361 0ustar000000000 0000000 (in-package :extensions) ;;; TODO: submit upstream patch to for removal (defun write-class (class-bytes pathname) "Write the Java byte[] array CLASS-BYTES to PATHNAME." (with-open-file (stream pathname :direction :output :element-type '(unsigned-byte 8)) (dotimes (i (java:jarray-length class-bytes)) (write-byte (java:jarray-ref class-bytes i) stream)))) (defun read-class (pathname) "Read the file at PATHNAME as a Java byte[] array" (with-open-file (stream pathname :direction :input :element-type '(unsigned-byte 8)) (let* ((length (file-length stream)) (array (make-array length :element-type '(unsigned-byte 8)))) (read-sequence array stream :end length) (java:jnew-array-from-array "byte" array)))) (export '(write-class read-class) :extensions) ;;; Determining the underlying unix file descriptor depends on ;;; navigating private member structures dependent on the hosting ;;; JVMs wrapping of native socket. The JAVA package currently does ;;; not have a means for such aggressive intropsection, so we add it ;;; as a utility here ;;; ;;; TODO test under :msdog ;;; TODO Should be in socket.lisp (defun stream-unix-fd (stream) "Return the integer of the underlying unix file descriptor for STREAM Added by ABCL-INTROSPECT." (check-type stream 'system::socket-stream) (flet ((get-java-fields (object fields) ;; Thanks to Cyrus Harmon (reduce (lambda (x y) (jss:get-java-field x y t)) fields :initial-value object)) (jvm-version () (read (make-string-input-stream (java:jstatic "getProperty" "java.lang.System" "java.specification.version"))))) (ignore-errors (get-java-fields (java:jcall "getWrappedInputStream" ;; TODO: define this as a constant (two-way-stream-input-stream stream)) (if (< (jvm-version) 14) '("in" "ch" "fdVal") '("in" "this$0" "sc" "fd" "fd")))))) (export '(stream-unix-fd) :extensions) abcl-src-1.9.0/contrib/asdf-jar/README.markdown0100644 0000000 0000000 00000004422 14202767264 017602 0ustar000000000 0000000 ASDF-JAR ======== ASDF-JAR provides a system for packaging ASDF systems into jar archives for ABCL. Given a running ABCL image with loadable ASDF systems the code in this package will recursively package all the required source and fasls in a jar archive . To install ASDF systems, [Quicklisp]() is probably the best contemporary solution. The QUICKLISP-ABCL may be used to install Quicklisp at runtime from within ABCL. [Quicklisp]: http://www.quicklisp.org Once the requisite ASDF systems have been installed, ensure that this contrib is loaded via CL-USER) (require :abcl-contrib) CL-USER> (require :asdf-jar) Then, to say package the Perl regular expression system ("CL-PPCRE"), one uses the ASDF-JAR:PACKAGE as follows: CL-USER> (asdf-jar:package :cl-ppcre) ; Loading #P"/home/evenson/quicklisp/dists/quicklisp/software/cl-ppcre-2.0.3/cl-ppcre.asd" ... ; Loaded #P"/home/evenson/quicklisp/dists/quicklisp/software/cl-ppcre-2.0.3/cl-ppcre.asd" (0.029 seconds) Packaging ASDF definition of # as /var/tmp/cl-ppcre-all-2.0.3.jar. Packaging contents in /var/tmp/cl-ppcre-all-2.0.3.jar with recursive dependencies. #P"/var/tmp/cl-ppcre-all-2.0.3.jar" The resulting jar contains all source and fasls required to run the ASDF system including any transitive ASDF dependencies. Each asdf system is packaged under its own top level directory within the jar archive. The jar archive itself is numbered with the version of the system that was specified in the packaging. To load the system from the jar one needs to add the ASDF file locations to the ASDF *CENTRAL-REGISTRY*. If one wishes to load the fasls from the jar alone, one needs to tell ASDF not to override its output translation rules. The function ASDF-JAR:ADD-TO-JAR does both of these options serving as the basis for customized load strategies tailored to end-user deployment needs. So, after CL-USER> (asdf-jar:add-to-asdf "/var/tmp/cl-ppcre-all-2.0.3.jar") a subsequent CL-USER> (asdf:load-system :cl-ppcre) should load the ASDF system from the jar. Setting CL:*LOAD-VERBOSE* will allow one to verify that the subsequent load is indeed coming from the jar. # Colophon Mark Evenson Created: 20-JUN-2011 Revised: 11-JUN-2017 abcl-src-1.9.0/contrib/asdf-jar/asdf-jar.asd0100644 0000000 0000000 00000000630 14242627550 017253 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem asdf-jar :author "Mark Evenson" :description "Packaging ASDF systems into jar files" :long-description "" :version "0.3.2" :components ((:module base :pathname "" :components ((:file "asdf-jar") (:static-file "README.markdown"))))) abcl-src-1.9.0/contrib/asdf-jar/asdf-jar.lisp0100644 0000000 0000000 00000020115 14202767264 017456 0ustar000000000 0000000 ;;; This file is part of ABCL contrib ;;; ;;; Copyright 2011 Mark (defpackage #:asdf-jar (:use :cl) (:export #:package ;; "Si vis pacem, para bellum" -- Publius Flavius Vegetius Renatus #:prepare-for-war #:add-to-asdf)) (in-package #:asdf-jar) (defvar *debug* nil) (defun add-system-files-to-mapping! (system mapping system-base system-name root &key (verbose nil)) "Add all the files of a SYSTEM to the MAPPING with a given SYSTEM-BASE and SYSTEM-NAME. This function destructively modifies MAPPING returning nil." (let ((abcl-file-type "abcl")) (loop :for component :in (all-files system) :for source = (slot-value component 'asdf::absolute-pathname) :for source-entry = (merge-pathnames (archive-relative-path system-base system-name source) (make-pathname :directory root)) :do (setf (gethash source mapping) source-entry) :do (format verbose "~&~A~& => ~A" source source-entry) :when (and (typep component 'asdf::source-file) (not (typep component 'asdf::static-file))) :do (let ((output (make-pathname :defaults (asdf:apply-output-translations source) :type abcl-file-type)) (output-entry (make-pathname :defaults source-entry :type abcl-file-type))) (format verbose "~&~A~& => ~A" output output-entry) (setf (gethash output mapping) output-entry))))) (defun systems->hash-table (systems root &key (verbose nil)) "Build a hash table from a list of SYSTEMS mapping absolute file names to of these systems into relative path names under the pathname directory component ROOT. This mapping will be used to zip the files of the system into a jar file." (let ((mapping (make-hash-table :test 'equal))) (dolist (system systems) (let ((base (slot-value system 'asdf::absolute-pathname)) (name (slot-value system 'asdf::name)) (asdf (slot-value system 'asdf::source-file))) (setf (gethash asdf mapping) (let ((relative-path (archive-relative-path base name asdf))) (merge-pathnames relative-path (make-pathname :directory root)))) (add-system-files-to-mapping! system mapping base name root :verbose verbose))) mapping)) (defun package (system &key (out #p"/var/tmp/") (recursive t) ; whether to package dependencies (force nil) ; whether to force ASDF compilation (root '(:relative)) (verbose nil)) "Compile and package the asdf SYSTEM in a jar. When RECURSIVE is true (the default), recursively add all asdf dependencies into the same jar. Place the resulting packaged jar in the OUT directory. If FORCE is true, force asdf to recompile all the necessary fasls. VERBOSE controls how many messages will be logged to *standard-output*. ROOT controls if the relative pathnames will be appended to something before being added to the mapping. The purpose of having this option is to add the paths to an internal directory, such as (list :relative \"META-INF\" \"resources\") for generating WAR files. Returns the pathname of the packaged jar archive. " (when (not (typep system 'asdf:system)) (setf system (asdf:find-system system))) (let* ((name (slot-value system 'asdf::name)) (version (let ((v (slot-value system 'asdf:version))) (when v v))) (package-jar-name (format nil "~A~A~A" name (if recursive "-all" "") (if version (format nil "-~A" version) ""))) (package-jar (make-pathname :name package-jar-name :type "jar" :defaults out))) (when verbose (format verbose "~&Packaging ASDF definition of ~A" system)) (when (and verbose force) (format verbose "~&Forcing recursive compilation of ~A." package-jar)) (asdf:compile-system system :force force) (when verbose (format verbose "~&Packaging contents in ~A" package-jar)) (system:zip package-jar (systems->hash-table (append (list system) (when recursive (let ((dependencies (dependent-systems system))) (when (and verbose dependencies) (format verbose "~& with recursive dependencies~{ ~A~^, ~}." dependencies)) (mapcar #'asdf:find-system dependencies)))) root :verbose verbose)))) (defun all-files (component) (loop :for c :being :each :hash-value :of (slot-value component 'asdf::children-by-name) :when (typep c 'asdf:module) :append (all-files c) :when (typep c 'asdf:source-file) :append (list c))) (defun dependent-systems (system) (when (not (typep system 'asdf:system)) (setf system (asdf:find-system system))) (let* ((dependencies (asdf::component-load-dependencies system)) (sub-depends (loop :for dependency :in dependencies :for sub = (dependent-systems dependency) :when sub :append sub))) (remove-duplicates `(,@dependencies ,@sub-depends)))) (defun archive-relative-path (base dir file) (let* ((relative (nthcdr (length (pathname-directory base)) (pathname-directory file))) (entry-dir `(:relative ,dir ,@relative))) (make-pathname :device nil :directory entry-dir :defaults file))) (defun tmpdir (name) "Return temporary directory." (let* ((temp-file (java:jcall "getAbsolutePath" (java:jstatic "createTempFile" "java.io.File" "foo" "tmp"))) (temp-path (pathname temp-file))) (make-pathname :directory (nconc (pathname-directory temp-path) (list name))))) (defun add-to-asdf (jar &key (use-jar-fasls t)) "Make a given JAR output by the package mechanism loadable by asdf. The parameter passed to :USE-JAR-FASLS determines whether to instruct asdf to use the fasls packaged in the jar. If this is nil, the fasls will be compiled with respect to the usual asdf output translation conventions." (when (not (typep jar 'pathname)) (setf jar (pathname jar))) (when (null (pathname-device jar)) (setf jar (make-pathname :device (list jar)))) ;;; Inform ASDF of all the system definitions in the jar (loop :for asd :in (directory (merge-pathnames "*/*.asd" jar)) :do (pushnew (make-pathname :defaults asd :name nil :type nil) asdf:*central-registry*)) ;;; Load the FASLs directly from the jar (when use-jar-fasls (asdf:initialize-output-translations `(:output-translations (,(merge-pathnames "/**/*.*" jar)) :inherit-configuration)))) (defun prepare-for-war (system &key (out #p"/var/tmp/") (recursive nil) ; whether to package dependencies (force nil) ; whether to force ASDF compilation (root (list :relative "META-INF" "resources")) (verbose t)) "Package named asdf SYSTEM for deployment in a Java Servlet container war file. c.f. PACKAGE for further options." (package system :out out :recursive recursive :force force :verbose verbose :root root)) (provide :asdf-jar) abcl-src-1.9.0/contrib/jfli/README0100644 0000000 0000000 00000002631 14242627550 015213 0ustar000000000 0000000 JFLI ==== The Java Foreign Linker Interface (JFLI) provides an abstraction to manipulate Java classes from Armed Bear Common Lisp that has been ported to other Lisp implementations. Incorporated into ABCL from . README ------ jfli (http://jfli.sf.net) is a library that provides access to Java from Lisp. jfli-abcl is jfli modified to work with ABCL (http://armedbear-j.sf.net); it provides the same interface to Java, but, since ABCL lives on the JVM, it doesn't need jni. jfli-abcl has an experimental NEW-CLASS macro that writes and loads a Java class at runtime, and defines the usual jfli-like Lisp interface to it. See the documentation of NEW-CLASS and the examples for the syntax. If you want to use it, make sure that (1) asm.jar (http://asm.objectweb.org) is in your classpath, and (2) the runtime generated Java classes are in the Java package of the same name as the Lisp package in which they're defined, like this: (in-package "FOO") (new-class "FOO.MyClass" ...) Caveats: jfli-abcl inherits all the bugs from jfli; see the archives of the jfli-users mailing list for a partial list. It probably also adds some of its own. I'm particularly interested in the latter type. Please send (ABCL-specific) bug reports, suggestions, examples, and whatever else you can think of, to asimon@math.bme.hu. # Colophon <> abcl:documents . abcl-src-1.9.0/contrib/jfli/examples/swing/README0100644 0000000 0000000 00000000471 14202767264 020163 0ustar000000000 0000000 This is a swing/jdbc example. To try it, (compile and) load table-gen.lisp and table.lisp (you need to modify it a bit first if you're not using PostgreSQL), in this order, then do (table:create-and-show-gui "select * from ") The cells are editable, so don't try it on an important db table. abcl-src-1.9.0/contrib/jfli/examples/swt/README0100644 0000000 0000000 00000002510 14202767264 017645 0ustar000000000 0000000 This example is a Lisp version of Explorer v9 from http://www-106.ibm.com/developerworks/opensource/library/os-ecgui3/ The gifs are from ftp://www6.software.ibm.com/software/developer/library/os-ecgui3/examples.zip To use it, (optionally compile) and load swt9jfli-gen.lisp first, and then swt9jfli.lisp. Start it with (swt0:main). But make sure first that besides asm.jar (http:/asm.objectweb.org), the various swt-related jars are in your classpath. I start abcl like this: /usr/java/jdk1.5.0/bin/java -cp /home/simon/java/j2/j/src/\ :/usr/share/java/pg74.215.jdbc3.jar\ :/home/simon/java/asm-1.5.1/lib/asm-1.5.1.jar\ :/opt/home/simon/java/eclipse/plugins/org.eclipse.core.boot_2.1.3/boot.jar\ :/opt/home/simon/java/eclipse/plugins/org.eclipse.core.runtime_2.1.1/runtime.jar\ :/opt/home/simon/java/eclipse/plugins/org.eclipse.jface_2.1.3/jface.jar\ :/opt/home/simon/java/eclipse/plugins/org.eclipse.jface.text_2.1.0/jfacetext.jar\ :/opt/home/simon/java/eclipse/plugins/org.eclipse.swt.gtk_2.1.3/ws/gtk/swt.jar\ :/opt/home/simon/java/eclipse/plugins/org.eclipse.swt.gtk_2.1.3/ws/gtk/swt-pi.jar\ -Djava.library.path=/opt/home/simon/java/eclipse/plugins/org.eclipse.swt.gtk_2.1.3/os/linux/x86/\ :/home/simon/java/jogl/\ org.armedbear.lisp.Main "$@" If everything goes well, a window like http://www.math.bme.hu/~asimon/lisp/swt.png should appear. abcl-src-1.9.0/contrib/jfli/examples/swt/file.gif0100644 0000000 0000000 00000000377 14202767264 020404 0ustar000000000 0000000 GIF89a���_������߿�ߟ���������___���!� ,E0�I+=8c+) x ��Y�@ň��y������ �K�|��eR�xH�sǜ������v����ȱD; abcl-src-1.9.0/contrib/jfli/examples/swt/folder.gif0100644 0000000 0000000 00000000407 14202767264 020732 0ustar000000000 0000000 GIF89a�������?���__?߿?��_��?߿_�ߟ���___���!� ,M��I��8���fK2��i� S� ��(F^�R@�D�P �b��Xh�>%��I��j/8�f���px 贚��3; abcl-src-1.9.0/contrib/jfli/jfli.asd0100644 0000000 0000000 00000000600 14242627550 015742 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem jfli :long-description "" :version "0.2.0" :components ((:file "jfli"))) ;;; Requires integration with IntelliJ IDEA editor (free download) (defsystem jfli/intellij-tests :version "0.2.0" :depends-on (jfli) :components ((:module test :components ((:file "yanking"))))) abcl-src-1.9.0/contrib/jfli/jfli.lisp0100644 0000000 0000000 00000153161 14202767264 016160 0ustar000000000 0000000 ; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Common Public License 1.0 (http://opensource.org/licenses/cpl.php) ; which can be found in the file CPL.TXT at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. ; Ported to ABCL by asimon@math.bme.hu. ; Minor ABCL fixes by: ; A. Vodonosov (avodonosov@yandex.ru). ; Alex Mizrahi (alex.mizrahi@gmail.com) (defpackage :jfli (:use :common-lisp :java) (:export :enable-java-proxies ;wrapper generation :def-java-class :get-jar-classnames :dump-wrapper-defs-to-file ;object creation etc :find-java-class :new :make-new :make-typed-ref :jeq ;array support :make-new-array :jlength :jref :jref-boolean :jref-byte :jref-char :jref-double :jref-float :jref-int :jref-short :jref-long ;proxy support :new-proxy :unregister-proxy ;conversions :box-boolean :box-byte :box-char :box-double :box-float :box-integer :box-long :box-short :box-string :unbox-boolean :unbox-byte :unbox-char :unbox-double :unbox-float :unbox-integer :unbox-long :unbox-short :unbox-string ; :ensure-package ; :member-symbol ; :class-symbol ; :constructor-symbol :*null* :new-class :super )) (in-package :jfli) (eval-when (:compile-toplevel :load-toplevel :execute) (defun string-append (&rest strings) (apply #'concatenate 'string (mapcar #'(lambda (s) (if (symbolp s) (symbol-name s) s)) strings))) (defun intern-and-unexport (string package) (multiple-value-bind (symbol status) (find-symbol string package) (when (and *compile-file-pathname* (eq status :external)) (unexport symbol package)) (intern string package))) ) (defun is-assignable-from (class-1 class-2) (jcall (jmethod "java.lang.Class" "isAssignableFrom" "java.lang.Class") class-2 class-1)) ;;not a typo #+abcl_not_used (defun new-object-array (len element-type initial-element) (jnew-array-from-array element-type (make-array (list len) :initial-element initial-element))) (defun java-ref-p (x) (java-object-p x)) (deftype java-ref () '(satisfies java-ref-p)) (defun split-package-and-class (name) (let ((p (position #\. name :from-end t))) (unless p (error "must supply package-qualified classname")) (values (subseq name 0 p) (subseq name (1+ p))))) (defun is-name-of-primitive (s) (member s '("boolean" "byte" "char" "short" "int" "long" "float" "double" "void") :test #'string-equal)) (defun is-primitive-class (class) (is-name-of-primitive (jclass-name class))) (defun convert-to-java-string (s) (jnew (jconstructor "java.lang.String" "java.lang.String") s)) (define-symbol-macro boolean.type (jfield "java.lang.Boolean" "TYPE")) (define-symbol-macro byte.type (jfield "java.lang.Byte" "TYPE")) (define-symbol-macro character.type (jfield "java.lang.Character" "TYPE")) (define-symbol-macro short.type (jfield "java.lang.Short" "TYPE")) (define-symbol-macro integer.type (jfield "java.lang.Integer" "TYPE")) (define-symbol-macro long.type (jfield "java.lang.Long" "TYPE")) (define-symbol-macro float.type (jfield "java.lang.Float" "TYPE")) (define-symbol-macro double.type (jfield "java.lang.Double" "TYPE")) (define-symbol-macro void.type (jfield "java.lang.Void" "TYPE")) #| (defconstant boolean.type (jfield "java.lang.Boolean" "TYPE")) (defconstant byte.type (jfield "java.lang.Byte" "TYPE")) (defconstant character.type (jfield "java.lang.Character" "TYPE")) (defconstant short.type (jfield "java.lang.Short" "TYPE")) (defconstant integer.type (jfield "java.lang.Integer" "TYPE")) (defconstant long.type (jfield "java.lang.Long" "TYPE")) (defconstant float.type (jfield "java.lang.Float" "TYPE")) (defconstant double.type (jfield "java.lang.Double" "TYPE")) |# (defconstant *null* java:+null+) (defun identity-or-nil (obj) (unless (equal obj *null*) obj)) ;;;;;;;;;;;;;;;;;;;;;;;;;;; utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (eval-when (:compile-toplevel :load-toplevel :execute) (defun ensure-package (name) "find the package or create it if it doesn't exist" (or (find-package name) (make-package name :use '()))) (intern "Object" (ensure-package "java.lang")) (intern "String" (ensure-package "java.lang"))) (defun enumeration.hasmoreelements (enum) (jcall (jmethod "java.util.Enumeration" "hasMoreElements") enum)) (defun enumeration.nextelement (enum) (jcall (jmethod "java.util.Enumeration" "nextElement") enum)) (defmacro doenum ((e enum) &body body) "jni-based, so not safe and not exported, but used by the implementation" (let ((genum (gensym))) `(let ((,genum ,enum)) (do () ((not (enumeration.hasmoreelements ,genum))) (let ((,e (enumeration.nextelement ,genum))) ,@body))))) ;probably insufficiently general, works as used here (defmacro get-or-init (place init-form) `(or ,place (setf ,place ,init-form))) (eval-when (:compile-toplevel) (intern-and-unexport "OBJECT." "java.lang")) ;create object. to bootstrap the hierarchy (defclass |java.lang|::object. () ((ref :reader ref :initarg :ref) (lisp-allocated :reader lisp-allocated-p :initarg :lisp-allocated :initform nil)) (:documentation "the superclass of all Java typed reference classes")) (defun get-ref (x) "any function taking an object can be passed a raw java-ref ptr or a typed reference instance. Will also convert strings for use as objects" ;; avodonosov: ;; typecase instead of etypecase ;; to allow not only jfli-wrapped objects ;; as a parameters of NEW-CLASS, but also native ;; Lisp objects too (in case of ABCL they are java ;; instances anyway). ;; For example that may be org.armedbear.lisp.Function. (typecase x (java-ref x) (|java.lang|::object. (ref x)) (string (convert-to-java-string x)) (null nil) ((or number character) x) ;; avodonosov: otherwise clause (otherwise x))) (defun is-same-object (obj1 obj2) (equal obj1 obj2)) (defun jeq (obj1 obj2) "are these 2 java objects the same object? Note that is not the same as Object.equals()" (is-same-object (get-ref obj1) (get-ref obj2))) ;;;;;;;;;;;;;;;;;;;;;;;; names and symbols ;;;;;;;;;;;;;;;;;;;;;;; #| The library does a lot with names and symbols, needing at various times to: - find stuff in Java - full names w/case required - create hopefully non-conflicting packages and member names When you (def-java-class "java.lang.String") you get a bunch of symbols/names: a package named '|java.lang| a class-symbol '|java.lang|:STRING. (note the dot and case), which can usually be used where a typename is required it also serves as the name of the Lisp typed reference class for string its symbol-value is the canonic-class-symbol (see below) a canonic-class-symbol '|java.lang|::|String| can be used to reconstitute the full class name I've started trying to flesh out the notion of a Java class designator, which can either be the full class name as a string, the class-symbol, or one of :boolean, :int etc |# (defun canonic-class-symbol (full-class-name) "(\"java.lang.Object\") -> '|java.lang|:|Object|" (multiple-value-bind (package class) (split-package-and-class full-class-name) (intern class (ensure-package package)))) (defun class-symbol (full-class-name) "(\"java.lang.Object\") -> '|java.lang|:object." (multiple-value-bind (package class) (split-package-and-class full-class-name) (intern (string-upcase (string-append class ".")) (ensure-package package)))) (defun unexported-class-symbol (full-class-name) "(\"java.lang.Object\") -> '|java.lang|::object." (multiple-value-bind (package class) (split-package-and-class full-class-name) (intern-and-unexport (string-upcase (string-append class ".")) (ensure-package package)))) (defun java-class-name (class-sym) "inverse of class-symbol, only valid on class-syms created by def-java-class" (let ((canonic-class-symbol (symbol-value class-sym))) (string-append (package-name (symbol-package canonic-class-symbol)) "." canonic-class-symbol))) (defun member-symbol (full-class-name member-name) "members are defined case-insensitively in case-sensitive packages, prefixed by 'classname.' - (member-symbol \"java.lang.Object\" \"toString\") -> '|java.lang|::OBJECT.TOSTRING" (multiple-value-bind (package class) (split-package-and-class full-class-name) (intern (string-upcase (string-append class "." member-name)) (ensure-package package)))) (defun unexported-member-symbol (full-class-name member-name) "members are defined case-insensitively in case-sensitive packages, prefixed by 'classname.' - (member-symbol \"java.lang.Object\" \"toString\") -> '|java.lang|::OBJECT.TOSTRING" (multiple-value-bind (package class) (split-package-and-class full-class-name) (intern-and-unexport (string-upcase (string-append class "." member-name)) (ensure-package package)))) (defun constructor-symbol (full-class-name) (member-symbol full-class-name "new")) (defun unexported-constructor-symbol (full-class-name) (unexported-member-symbol full-class-name "new")) (defun get-java-class-ref (canonic-class-symbol) "class-ref is cached on the plist of the canonic class symbol" (get-or-init (get canonic-class-symbol :class-ref) (let ((class-name (string-append (package-name (symbol-package canonic-class-symbol)) "." canonic-class-symbol))) (jclass class-name) ))) (defun find-java-class (class-sym-or-string) "Given a Java class designator, returns the Java Class object." (ctypecase class-sym-or-string (symbol (case class-sym-or-string (:int integer.type) (:char character.type) (:long long.type) (:float float.type) (:boolean boolean.type) (:short short.type) (:double double.type) (:byte byte.type) (:void void.type) (otherwise (get-java-class-ref class-sym-or-string)))) (string (get-java-class-ref (canonic-class-symbol class-sym-or-string))))) ;;;;;;;;;;;;;;;;;;;;;; typed reference support ;;;;;;;;;;;;;;;;;;;;;;;; #| The library maintains a hierarchy of typed reference classes that parallel the class hierarchy on the Java side new returns a typed reference, but other functions that return objects return raw references (for efficiency) make-typed-ref can create fully-typed wrappers when desired |# (defun get-superclass-names (full-class-name) (let* ((class (get-java-class-ref (canonic-class-symbol full-class-name))) (super (jclass-superclass class)) (interfaces (jclass-interfaces class)) (supers ())) (loop for i across interfaces do (push i supers)) ;hmmm - where should the base class go in the precedence list? ;is it more important than the interfaces? this says no (if super (push super supers) (push (jclass "java.lang.Object") supers)) (setf supers (nreverse supers)) ;now we need to fix up order so more derived classes are first ;but don't have a total ordering, so merge one at a time (let (result) (dolist (s supers) (setf result (merge 'list result (list s) (lambda (x y) (is-assignable-from x y))))) (mapcar #'jclass-name result)))) #| (defun get-superclass-names (full-class-name) (let* ((class (get-java-class-ref (canonic-class-symbol full-class-name))) (super (class.getsuperclass class)) (interfaces (class.getinterfaces class)) (supers ())) (do-jarray (i interfaces) (push (class.getname i) supers)) ;hmmm - where should the base class go in the precedence list? ;is it more important than the interfaces? this says no (if super (push (class.getname super) supers) (push "java.lang.Object" supers)) (nreverse supers))) |# (defun %ensure-java-class (full-class-name) "walks the superclass hierarchy and makes sure all the classes are fully defined (they may be undefined or just forward-referenced-class) caches this has been done on the class-symbol's plist" (let* ((class-sym (class-symbol full-class-name)) (class (find-class class-sym nil))) (if (or (eql class-sym '|java.lang|::object.) (get class-sym :ensured)) class (let ((supers (get-superclass-names full-class-name))) (dolist (super supers) (%ensure-java-class super)) (unless (and class (subtypep class 'standard-object)) (setf class #+abcl (mop::ensure-class class-sym :direct-superclasses (mapcar #'(lambda (c) (find-class (class-symbol c))) supers)))) (setf (get class-sym :ensured) t) class)))) (defun ensure-java-hierarchy (class-sym) "Works off class-sym for efficient use in new This will only work on class-syms created by def-java-class, as it depends upon symbol-value being the canonic class symbol" (unless (get class-sym :ensured) (%ensure-java-class (java-class-name class-sym)))) (defun make-typed-ref (java-ref) "Given a raw java-ref, determines the full type of the object and returns an instance of a typed reference wrapper" (when java-ref (let ((class (jobject-class java-ref))) (if (jclass-array-p class) (error "typed refs not supported for arrays (yet)") (make-instance (%ensure-java-class (jclass-name class)) :ref java-ref))))) ;;;;;;;;;;;;;;;;;;;;;;;;; Wrapper Generation ;;;;;;;;;;;;;;;;;;;;;;;;;;; #| In an effort to reduce the volume of stuff generated when wrapping entire libraries, the wrappers just generate minimal stubs, which, if and when invoked at runtime, complete the work of building thunking closures, so very little code is generated for things never called (Java libraries have huge numbers of symbols). Not sure if this approach matters, but that's how it works |# (defmacro def-java-class (full-class-name) "Given the package-qualified, case-correct name of a java class, will generate wrapper functions for its contructors, fields and methods." (multiple-value-bind (pacakge class) (split-package-and-class full-class-name) (declare (ignore class)) (let* ((class-sym (unexported-class-symbol full-class-name)) (defs (list* #+nil `(format t "!!!!!!!!!!~a~%" ,full-class-name) `(ensure-package ,pacakge) ;build a path from the simple class symbol to the canonic `(defconstant ,class-sym ',(canonic-class-symbol full-class-name)) `(export ',class-sym (symbol-package ',class-sym)) `(def-java-constructors ,full-class-name) `(def-java-methods ,full-class-name) `(def-java-fields ,full-class-name) (unless (string= full-class-name "java.lang.Object") (let* ((supers (mapcar #'unexported-class-symbol (get-superclass-names full-class-name))) (super-exports (mapcar #'(lambda (class-sym) `(export ',class-sym (symbol-package ',class-sym))) supers))) (append (mapcar (lambda (p) `(ensure-package ,(package-name p))) (remove (symbol-package class-sym) (remove-duplicates (mapcar #'symbol-package supers)))) super-exports (list `(defclass ,(class-symbol full-class-name) ,supers ())))))))) `(locally ,@defs)))) (defun jarfile.new (fn) (jnew (jconstructor "java.util.jar.JarFile" "java.lang.String") fn)) (defun jarfile.entries (jar) (jcall (jmethod "java.util.jar.JarFile" "entries") jar)) (defun zipentry.isdirectory (e) (jcall (jmethod "java.util.zip.ZipEntry" "isDirectory") e)) (defun zipentry.getname (e) (jcall (jmethod "java.util.zip.ZipEntry" "getName") e)) (defun get-jar-classnames (jar-file-name &rest packages) "returns a list of strings, packages should be of the form \"java/lang\" for recursive lookup and \"java/util/\" for non-recursive" (let* ((jar (jarfile.new jar-file-name)) (entries (jarfile.entries jar)) (names ())) (doenum (e entries) (unless (zipentry.isdirectory e) (let ((ename (zipentry.getname e))) (flet ((matches (package) (and (eql 0 (search package ename)) (or (not (eql #\/ (schar package (1- (length package))))) ;recursive (not (find #\/ ename :start (length package))))))) ;non-subdirectory (when (and (eql (search ".class" ename) (- (length ename) 6)) ;classname ;don't grab anonymous inner classes (not (and (find #\$ ename) (digit-char-p (schar ename (1+ (position #\$ ename)))))) (some #'matches packages)) (push (nsubstitute #\. #\/ (subseq ename 0 (- (length ename) 6))) names)))))) names)) (defun dump-wrapper-defs-to-file (filename classnames) "given a list of classnames (say from get-jar-classnames), writes calls to def-java-class to a file" (with-open-file (s filename :direction :output :if-exists :supersede) (dolist (name (sort classnames #'string-lessp)) (format s "(def-java-class ~S)~%" name)))) ;;;;;;;;;;;;;;;;;;;;;;;;; constructors and new ;;;;;;;;;;;;;;;;;;;;;;;;;; #| Every non-interface class with a public ctor will get; a constructor, classname.new a method defined on make-new, ultimately calling classname.new, specialized on (the value of) it's class-symbol (e.g. canonic sym) Note that if the ctor is overloaded, there is just one function (taking a rest arg), which handles overload resolution The new macro expands into a call to make-new |# (defgeneric make-new (class-sym &rest args) (:documentation "Allows for definition of before/after methods on ctors. The new macro expands into call to this")) (defun build-ctor-doc-string (name ctors) (with-output-to-string (s) (dolist (c ctors) (format s "~A(~{~#[~;~A~:;~A,~]~})~%" name (mapcar #'class-name-for-doc (jarray-to-list (jconstructor-params c))))))) (defmacro def-java-constructors (full-class-name) "creates and exports a ctor func classname.new, defines a method of make-new specialized on the class-symbol" (let ((ctor-list (get-ctor-list full-class-name))) (when ctor-list (let ((ctor-sym (unexported-constructor-symbol full-class-name)) (class-sym (class-symbol full-class-name))) `(locally (defun ,ctor-sym (&rest args) ,(build-ctor-doc-string full-class-name ctor-list) (apply #'install-constructors-and-call ,full-class-name args)) (export ',ctor-sym (symbol-package ',ctor-sym)) (defmethod make-new ((class-sym (eql ,class-sym)) &rest args) (apply (function ,ctor-sym) args))))))) (defun get-ctor-list (full-class-name) (let* ((class-sym (canonic-class-symbol full-class-name)) (class (get-java-class-ref class-sym)) (ctor-array (jclass-constructors class)) (ctor-list (jarray-to-list ctor-array))) ctor-list)) (defun install-constructors-and-call (full-class-name &rest args) "initially the constructor symbol for a class is bound to this function, when first called it will replace itself with the appropriate direct thunk, then call the requested ctor - subsequent calls will be direct" (install-constructors full-class-name) (apply (constructor-symbol full-class-name) args)) (defun install-constructors (full-class-name) (let* ((ctor-list (get-ctor-list full-class-name))) (when ctor-list (setf (fdefinition (constructor-symbol full-class-name)) (make-ctor-thunk ctor-list (class-symbol full-class-name)))))) (defun make-ctor-thunk (ctors class-sym) (if (rest ctors) ;overloaded (make-overloaded-ctor-thunk ctors class-sym) (make-non-overloaded-ctor-thunk (first ctors) class-sym))) (defun make-non-overloaded-ctor-thunk (ctor class-sym) (let ((arg-boxers (get-arg-boxers (jconstructor-params ctor)))) (lambda (&rest args) (let ((arglist (build-arglist args arg-boxers))) (ensure-java-hierarchy class-sym) (make-instance class-sym :ref (apply #'jnew ctor arglist) :lisp-allocated t))))) (defun make-overloaded-ctor-thunk (ctors class-sym) (let ((thunks (make-ctor-thunks-by-args-length ctors class-sym))) (lambda (&rest args) (let ((fn (cdr (assoc (length args) thunks)))) (if fn (apply fn args) (error "invalid arity")))))) (defun make-ctor-thunks-by-args-length (ctors class-sym) "returns an alist of thunks keyed by number of args" (let ((ctors-by-args-length (make-hash-table)) (thunks-by-args-length nil)) (dolist (ctor ctors) (let ((params-len (length (jconstructor-params ctor)))) (push ctor (gethash params-len ctors-by-args-length)))) (maphash #'(lambda (args-len ctors) (push (cons args-len (if (rest ctors);truly overloaded (make-type-overloaded-ctor-thunk ctors class-sym) ;only one ctor with this number of args (make-non-overloaded-ctor-thunk (first ctors) class-sym))) thunks-by-args-length)) ctors-by-args-length) thunks-by-args-length)) (defun make-type-overloaded-ctor-thunk (ctors class-sym) "these methods have the same number of args and must be distinguished by type" (let ((thunks (mapcar #'(lambda (ctor) (list (make-non-overloaded-ctor-thunk ctor class-sym) (jarray-to-list (jconstructor-params ctor)))) ctors))) (lambda (&rest args) (block fn (let ((arg-types (get-types-of-args args))) (dolist (thunk-info thunks) (destructuring-bind (thunk param-types) thunk-info (when (is-congruent-type-list param-types arg-types) (return-from fn (apply thunk args))))) (error "No matching constructor")))))) (defmacro new (class-spec &rest args) "new class-spec args class-spec -> class-name | (class-name this-name) class-name -> \"package.qualified.ClassName\" | classname. args -> [actual-arg]* [init-arg-spec]* init-arg-spec -> init-arg | (init-arg) init-arg -> :settable-field-or-method [params]* value ;note keyword | .method-name [args]* ;note dot Creates a new instance of class-name, using make-new generic function, then initializes it by setting fields or accessors and/or calling member functions If this-name is supplied it will be bound to the newly-allocated object and available to the init-args" (labels ((mem-sym? (x) (or (keywordp x) (and (symbolp x) (eql 0 (position #\. (symbol-name x)))))) (mem-form? (x) (and (listp x) (mem-sym? (first x)))) (mem-init? (x) (or (mem-sym? x) (mem-form? x))) (init-forms (x) (if x (if (mem-form? (first x)) (cons (first x) (init-forms (rest x))) (let ((more (member-if #'mem-init? (rest x)))) (cons (ldiff x more) (init-forms more))))))) (let* ((inits (member-if #'mem-init? args)) (real-args (ldiff args inits)) (class-atom (if (atom class-spec) class-spec (first class-spec))) (class-sym (if (symbolp class-atom) ;(find-symbol (string-append (symbol-name class-atom) ".")) class-atom (multiple-value-bind (package class) (split-package-and-class class-atom) (find-symbol (string-append (string-upcase class) ".") package)))) (class-name (subseq (symbol-name class-sym) 0 (1- (length (symbol-name class-sym))))) (gthis (gensym))) (flet ((expand-init (x) (if (keywordp (first x)) ;setf field or property `(setf (,(find-symbol (string-append class-name "." (symbol-name (first x)))) ,gthis ,@(butlast (rest x))) ,@(last (rest x))) ;.memfunc `(,(find-symbol (string-append class-name (symbol-name (first x)))) ,gthis ,@(rest x))))) `(let* ((,gthis (make-new ,class-sym ,@real-args)) ,@(when (listp class-spec) `((,(second class-spec) ,gthis)))) ,@(mapcar #'expand-init (init-forms inits)) ,gthis))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #| all public fields will get a getter function classname.fieldname and a setter - (setf classname.fieldname) instance fields take an first arg which is the instance static fields also get a symbol-macro *classname.fieldname* |# (defmacro def-java-fields (full-class-name) "fields will get a getter function classname.fieldname and a setter - (setf classname.fieldname) instance fields take an first arg which is the instance static fields also get a symbol-macro *classname.fieldname*" (let* ((class-sym (canonic-class-symbol full-class-name)) (class (get-java-class-ref class-sym)) (fields (jarray-to-list (jclass-fields class))) (defs nil)) (dolist (field fields) (let* ((field-name (jfield-name field)) (field-sym (unexported-member-symbol full-class-name field-name)) (is-static (jmember-static-p field))) (if is-static (let ((macsym (intern-and-unexport (string-append "*" (symbol-name field-sym) "*") (symbol-package field-sym)))) (push `(defun ,field-sym () (install-static-field-and-get ,full-class-name ,field-name)) defs) (push `(defun (setf ,field-sym) (val) (install-static-field-and-set ,full-class-name ,field-name val)) defs) (push `(export ',field-sym (symbol-package ',field-sym)) defs) (push `(define-symbol-macro ,macsym (,field-sym)) defs) (push `(export ',macsym (symbol-package ',macsym)) defs)) (progn (push `(defun ,field-sym (obj) (install-field-and-get ,full-class-name ,field-name obj)) defs) (push `(defun (setf ,field-sym) (val obj) (install-field-and-set ,full-class-name ,field-name val obj)) defs) (push `(export ',field-sym (symbol-package ',field-sym)) defs))))) `(locally ,@(nreverse defs)))) (defun install-field-and-get (full-class-name field-name obj) (install-field full-class-name field-name) (funcall (member-symbol full-class-name field-name) obj)) (defun install-field-and-set (full-class-name field-name val obj) (install-field full-class-name field-name) (funcall (fdefinition `(setf ,(member-symbol full-class-name field-name))) val obj)) (defun install-static-field-and-get (full-class-name field-name) (install-field full-class-name field-name) (funcall (member-symbol full-class-name field-name))) (defun install-static-field-and-set (full-class-name field-name val) (install-field full-class-name field-name) (funcall (fdefinition `(setf ,(member-symbol full-class-name field-name))) val)) (defun install-field (full-class-name field-name) (let* ((class-sym (canonic-class-symbol full-class-name)) (class (get-java-class-ref class-sym)) (field (jclass-field class field-name)) (field-sym (member-symbol full-class-name field-name)) (is-static (jmember-static-p field)) (field-type-name (jclass-name (jfield-type field))) (boxer (get-boxer-fn field-type-name)) (unboxer (get-unboxer-fn field-type-name))) (if is-static (progn (setf (fdefinition field-sym) (lambda () (funcall unboxer (jfield-raw class field-name) #+nil (field.get field nil)))) (setf (fdefinition `(setf ,field-sym)) (lambda (arg) (jfield field-name nil (get-ref (if (and boxer (not (boxed? arg))) (funcall boxer arg) arg))) arg))) (progn (setf (fdefinition field-sym) (lambda (obj) (funcall unboxer (jfield-raw class field-name (get-ref obj)) #+nil(field.get field (get-ref obj))))) (setf (fdefinition `(setf ,field-sym)) (lambda (arg obj) (jfield field-name (get-ref obj) (get-ref (if (and boxer (not (boxed? arg))) (funcall boxer arg) arg))) arg)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; methods ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #| defines wrappers for all public methods of the class As with ctors, if a method is overloaded a single wrapper is created that handles overload resolution. The wrappers have the name classname.methodname If a method follows the JavaBeans property protocol (i.e. it is called getSomething or isSomething and there is a corresponding setSomething, then a (setf classname.methodname) will be defined that calls the latter |# (defun class-name-for-doc (class) (let ((name (jclass-name class))) (if (jclass-array-p class) (decode-array-name name) name))) (defun build-method-doc-string (name methods) (with-output-to-string (s) (dolist (m methods) (format s "~A~A ~A(~{~#[~;~A~:;~A,~]~})~%" (if (jmember-static-p m) "static " "") (jclass-name (jmethod-return-type m)) name (mapcar #'class-name-for-doc (jarray-to-list (jmethod-params m))))))) (defmacro def-java-methods (full-class-name) (let ((methods-by-name (get-methods-by-name full-class-name)) (defs nil)) (maphash (lambda (name methods) (let ((method-sym (unexported-member-symbol full-class-name name))) (push `(defun ,method-sym (&rest args) ,(build-method-doc-string name methods) (apply #'install-methods-and-call ,full-class-name ,name args)) defs) (push `(export ',method-sym (symbol-package ',method-sym)) defs) ;build setters when finding beans property protocol (flet ((add-setter-if (prefix) (when (eql 0 (search prefix name)) (let ((setname (string-append "set" (subseq name (length prefix))))) (when (gethash setname methods-by-name) (push `(defun (setf ,method-sym) (val &rest args) (progn (apply #',(member-symbol full-class-name setname) (append args (list val))) val)) defs)))))) (add-setter-if "get") (add-setter-if "is")))) methods-by-name) `(locally ,@(nreverse defs)))) (defun install-methods-and-call (full-class-name method &rest args) "initially all the member function symbols for a class are bound to this function, when first called it will replace them with the appropriate direct thunks, then call the requested method - subsequent calls via those symbols will be direct" (install-methods full-class-name) (apply (member-symbol full-class-name method) args)) (defun decode-array-name (tn) (let ((prim (assoc tn '(("Z" . "boolean") ("B" . "byte") ("C" . "char") ("S" . "short") ("I" . "int") ("J" . "long") ("F" . "float") ("D" . "double") ("V" . "void")) :test #'string-equal))) (if prim (rest prim) (let ((array-depth (count #\[ tn))) (if (= 0 array-depth) (subseq tn 1 (1- (length tn))) ;strip leading L and trailing ; (with-output-to-string (s) (write-string (decode-array-name (subseq tn array-depth)) s) (dotimes (x array-depth) (write-string "[]" s)))))))) (defun jarray-to-list (array) (coerce array 'list)) (defun jmethod-made-accessible (method) "Return a method made accessible" (jcall (jmethod "java.lang.reflect.AccessibleObject" "setAccessible" "boolean") method java:+true+) method) (defun jclass-relevant-methods (class) "Return all public methods, and all protected declared methods" (append (jarray-to-list (jclass-methods class)) (map 'list #'jmethod-made-accessible (remove-if-not #'jmember-protected-p (jclass-methods class :declared t))))) (defun get-methods-by-name (full-class-name) "returns an #'equal hashtable of lists of java.lang.Method refs keyed by name" (let* ((class-sym (canonic-class-symbol full-class-name)) (class (get-java-class-ref class-sym)) (methods (jclass-relevant-methods class)) (methods-by-name (make-hash-table :test #'equal))) (loop for method in methods do (push method (gethash (jmethod-name method) methods-by-name))) methods-by-name)) (defun install-methods (full-class-name) (let ((methods-by-name (get-methods-by-name full-class-name))) (maphash (lambda (name methods) (setf (fdefinition (member-symbol full-class-name name)) (make-method-thunk methods))) methods-by-name))) (defun make-method-thunk (methods) (if (rest methods) ;overloaded (make-overloaded-thunk methods) (make-non-overloaded-thunk (first methods)))) (defun make-non-overloaded-thunk (method) (let* ((unboxer-fn (get-unboxer-fn (jclass-name (jmethod-return-type method)))) (arg-boxers (get-arg-boxers (jmethod-params method))) (is-static (jmember-static-p method)) (caller (if is-static #'jstatic-raw #'jcall-raw))) (lambda (&rest args) (let ((arglist (build-arglist (if is-static args (rest args)) arg-boxers))) (funcall unboxer-fn (apply caller method (if is-static nil (get-ref (first args))) arglist)))))) (defun make-overloaded-thunk (methods) (let ((thunks (make-thunks-by-args-length methods))) (lambda (&rest args) (let ((fn (cdr (assoc (length args) thunks)))) (if fn (apply fn args) (error "invalid arity")))))) (defun make-thunks-by-args-length (methods) "returns an alist of thunks keyed by number of args" (let ((methods-by-args-length (make-hash-table)) (thunks-by-args-length nil)) (dolist (method methods) (let ((is-static (jmember-static-p method)) (params-len (length (jmethod-params method)))) (push method (gethash (if is-static params-len (1+ params-len)) methods-by-args-length)))) (maphash #'(lambda (args-len methods) (push (cons args-len (if (rest methods);truly overloaded (make-type-overloaded-thunk methods) ;only one method with this number of args (make-non-overloaded-thunk (first methods)))) thunks-by-args-length)) methods-by-args-length) thunks-by-args-length)) (defun make-type-overloaded-thunk (methods) "these methods have the same number of args and must be distinguished by type" (let ((thunks (mapcar #'(lambda (method) (list (make-non-overloaded-thunk method) (jmember-static-p method) (jarray-to-list (jmethod-params method)))) methods))) (lambda (&rest args) (block fn (let ((arg-types (get-types-of-args args))) (dolist (thunk-info thunks) (destructuring-bind (thunk is-static param-types) thunk-info (when (is-congruent-type-list param-types (if is-static arg-types (rest arg-types))) (return-from fn (apply thunk args))))) (error "No matching method")))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;; array support ;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun jref (array &rest subscripts) (apply #'jarray-ref-raw array subscripts)) (defun (setf jref) (val array &rest subscripts) (apply #'jarray-set array val subscripts)) (eval-when (:compile-toplevel :load-toplevel :execute) (defmacro def-refs (&rest types) `(locally ,@(mapcan (lambda (type) (let ((ref-sym (intern (string-upcase (string-append "jref-" (symbol-name type)))))) (list `(defun ,ref-sym (array &rest subscripts) ,(format nil "like aref, for Java arrays of ~A, settable" (symbol-name type)) (assert (every #'integerp subscripts)) (apply #'jarray-ref array subscripts)) `(defun (setf ,ref-sym) (val array &rest subscripts) (assert (every #'integerp subscripts)) (apply #'jarray-set array ,(if (eql type 'boolean) '(box-boolean val) 'val) subscripts) )))) types)))) ;arrays of primitives have their own accessors (def-refs boolean byte char double float int short long) (defun jlength (array) "like length, for Java arrays" (jarray-length array)) ;(get-ref array)? (defgeneric make-new-array (type &rest dimensions) (:documentation "generic function, with methods for all Java class designators") (:method (type &rest dims) (assert (every #'integerp dims)) (apply #'jnew-array type dims))) (defmethod make-new-array ((type symbol) &rest dimensions) (apply #'make-new-array (get-java-class-ref type) dimensions)) (defmethod make-new-array ((type string) &rest dimensions) (apply #'make-new-array (find-java-class type) dimensions)) (defmethod make-new-array ((type (eql :char)) &rest dimensions) (apply #'make-new-array character.type dimensions)) (defmethod make-new-array ((type (eql :int)) &rest dimensions) (apply #'make-new-array integer.type dimensions)) (defmethod make-new-array ((type (eql :boolean)) &rest dimensions) (apply #'make-new-array boolean.type dimensions)) (defmethod make-new-array ((type (eql :double)) &rest dimensions) (apply #'make-new-array double.type dimensions)) (defmethod make-new-array ((type (eql :byte)) &rest dimensions) (apply #'make-new-array byte.type dimensions)) (defmethod make-new-array ((type (eql :float)) &rest dimensions) (apply #'make-new-array float.type dimensions)) (defmethod make-new-array ((type (eql :short)) &rest dimensions) (apply #'make-new-array short.type dimensions)) (defmethod make-new-array ((type (eql :long)) &rest dimensions) (apply #'make-new-array long.type dimensions)) ;;;;;;;;;;;;;;;;;;;;;;;;;; arg/param helpers ;;;;;;;;;;;;;;;;;;;;;; (defun get-arg-boxers (param-types) "returns a list with one entry per param, either nil or a function that boxes the arg" (loop for param-type across param-types collecting (get-boxer-fn (jclass-name param-type)))) (defun build-arglist (args arg-boxers) (when args (loop for arg in args for boxer in arg-boxers collecting (get-ref (if (and boxer (not (boxed? arg))) (funcall boxer arg) arg))))) (defun get-types-of-args (args) (let (ret) (dolist (arg args) (push (infer-box-type arg) ret)) (nreverse ret))) (defun is-congruent-type-list (param-types arg-types) (every #'(lambda (arg-type param-type) (if arg-type (is-assignable-from arg-type param-type) ;nil was passed - must be boolean or non-primitive target type (or (not (is-primitive-class param-type)) (jclass-superclass-p boolean.type param-type)))) arg-types param-types)) ;;;;;;;;;;;;;;;;;;;;;;;; argument conversion and boxing ;;;;;;;;;;;;;;;;;;;;;;;;;; (defun box-string (s) "Given a string or symbol, returns reference to a Java string" (convert-to-java-string s)) (defun unbox-string (ref &optional delete-local) "Given a reference to a Java string, returns a Lisp string" (declare (ignore delete-local)) (convert-from-java-string (get-ref ref))) (defun get-boxer-fn (class-name) (if (string= class-name "boolean") #'box-boolean nil)) (defun get-boxer-fn-sym (class-name) (if (string= class-name "boolean") 'box-boolean 'identity)) (defun boxed? (x) (or (java-ref-p x) (typep x '|java.lang|::object.))) (defun infer-box-type (x) (cond ((null x) nil) ((boxed? x) (jobject-class (get-ref x))) ((typep x '(integer -2147483648 +2147483647)) integer.type) ((typep x '(integer -9223372036854775808 +9223372036854775807)) long.type) ((numberp x) double.type) ; ((characterp x) character.type) ;;;FIXME!! ((eq x t) boolean.type) ((or (stringp x) (symbolp x)) (get-java-class-ref '|java.lang|::|String|)) (t (error "can't infer box type")))) (defun get-unboxer-fn (class-name) (if (string= class-name "void") #'unbox-void (if (or (is-name-of-primitive class-name) (string= class-name "java.lang.String")) #'jobject-lisp-value #'identity-or-nil))) (defun get-unboxer-fn-sym (class-name) (if (string= class-name "void") 'unbox-void (if (or (is-name-of-primitive class-name) (string= class-name "java.lang.String")) 'jobject-lisp-value 'identity-or-nil))) (defun unbox-void (x &optional delete-local) (declare (ignore x delete-local)) nil) (defun box-void (x) (declare (ignore x)) nil) (defun box-boolean (x) (if x java:+true+ java:+false+)) ;;;;;;;;;;;;;;;;;;;;;;;; proxy support ;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun enable-java-proxies () t) (defun find-java-class-in-macro (name) (find-java-class (if (symbolp name) (symbol-value name) name))) (defmacro new-proxy (&rest interface-defs) "interface-def -> (interface-name method-defs+) interface-name -> \"package.qualified.ClassName\" | classname. (must name a Java interface type) method-def -> (method-name arg-defs* body) arg-def -> arg-name | (arg-name arg-type) arg-type -> \"package.qualified.ClassName\" | classname. | :primitive method-name -> symbol | string (matched case-insensitively) Creates, registers and returns a Java object that implements the supplied interfaces" (let (defined-method-names) (labels ((process-idefs (idefs) (when (rest idefs) (error "Sorry, only one interface def at a time")) (process-idef (first idefs))) (process-idef (idef) (destructuring-bind (interface-name &rest method-defs) idef (let* ((methods (jclass-methods (find-java-class-in-macro interface-name))) (ret `((find-java-class ,interface-name) ,@(loop for method-def in method-defs appending (process-method-def method-def methods))))) ;;check to make sure every function is defined (loop for method across methods for mname = (jmethod-name method) unless (member mname defined-method-names :test #'string-equal) do (warn (format nil "proxy doesn't define:~%~A" mname))) ret))) (process-method-def (method-def methods) (destructuring-bind (method-name (&rest arg-defs) &body body) method-def (push method-name defined-method-names) (let ((method (matching-method method-name arg-defs methods)) (gargs (gensym))) `(,(jmethod-name method) (lambda (&rest ,gargs) (,(get-boxer-fn-sym (jclass-name (jmethod-return-type method))) (let ,(arg-lets arg-defs (jarray-to-list (jmethod-params method)) gargs 0) ,@body))))))) (arg-lets (arg-defs params gargs idx) (when arg-defs (let ((arg (first arg-defs)) (param (first params))) (cons `(,(if (atom arg) arg (first arg)) (,(get-unboxer-fn-sym (jclass-name param)) (nth ,idx ,gargs))) (arg-lets (rest arg-defs) (rest params) gargs (1+ idx)))))) (matching-method (method-name arg-defs methods) (let (match) (loop for method across methods when (method-matches method-name arg-defs method) do (if match (error (format nil "more than one method matches ~A" method-name)) (setf match method))) (or match (error (format nil "no method matches ~A" method-name))))) (method-matches (method-name arg-defs method) (when (string-equal method-name (jmethod-name method)) (let ((params (jmethod-params method))) (when (= (length arg-defs) (length params)) (is-congruent arg-defs params))))) (is-congruent (arg-defs params) (every (lambda (arg param) (or (atom arg) ;no type spec matches anything (jeq (find-java-class-in-macro (second arg)) param))) arg-defs (jarray-to-list params)))) `(java::%jnew-proxy ,@(process-idefs interface-defs))))) #+nil (defun jrc (class-name super-name interfaces constructors methods fields &optional filename) "A friendlier version of jnew-runtime-class." #+nil (format t "~s~%~s~%~s~%~s~%~s~%~s~%" class-name super-name interfaces constructors methods fields filename) (if (java:jruntime-class-exists-p class-name) (progn (warn "Java class ~a already exists. Redefining methods." class-name) (loop for (argument-types function super-invocation-args) in constructors do (java:jredefine-method class-name nil argument-types function)) (loop for (method-name return-type argument-types function &rest modifiers) in methods do (java:jredefine-method class-name method-name argument-types function))) (java:jnew-runtime-class class-name super-name interfaces constructors methods fields filename))) (defun get-modifiers (member) (jcall (jmethod "java.lang.reflect.Member" "getModifiers") member)) (defun get-modifier-list (member) (let ((mods (get-modifiers member))) (loop for (mod . mod-call) in '(("public" . "isPublic") ("protected" . "isProtected") ("private" . "isPrivate") ("static" . "isStatic") ;("abstract" . "isAbstract") ("final" . "isFinal") ("transient" . "isTransient") ("volatile" . "isVolatile") ("synchronized" . "isSynchronized")) when (jstatic (jmethod "java.lang.reflect.Modifier" mod-call "int") "java.lang.reflect.Modifier" mods) collect mod))) (defun get-java-object (x) (typecase x (|java.lang|::object. (ref x)) (t x))) (defun find-java-class-name-in-macro (c) (etypecase c (symbol (jclass-name (find-java-class (symbol-value c)))) (string c))) #+nil (defmacro new-class (class-name super-and-interface-names constructor-defs method-defs field-defs) "class-name -> string super-and-interface-names -> class-name | (class-name interface-name*) constructor-defs -> (constructor-def*) constructor-def -> (ctr-arg-defs body) /the first form in body may be (super arg-name+); this will call the constructor of the superclass with the listed arguments/ ctr-arg-def -> (arg-name arg-type) method-def -> (method-name return-type access-modifiers arg-defs* body) /access-modifiers may be nil (to get the modifiers from the superclass), a keyword, or a list of keywords/ method-name -> string arg-def -> arg-name | (arg-name arg-type) arg-type -> \"package.qualified.ClassName\" | classname. | :primitive class-name -> \"package.qualified.ClassName\" | classname. interface-name -> \"package.qualified.InterfaceName\" | interfacename. Creates, registers and returns a Java object that implements the supplied interfaces" (let ((this (intern "THIS" *package*)) (defined-method-names)) (labels ((process-ctr-def (ctr-def ctrs) (destructuring-bind ((&rest arg-defs) &body body) ctr-def (let ((ctr-param-names (mapcar #'(lambda (arg-def) (find-java-class-name-in-macro (cadr arg-def))) arg-defs)) ;(ctr-param-names (mapcar #'cadr arg-defs)) (gargs (gensym)) (head (car body)) (sia)) (when (and (consp head) (eq (car head) 'super)) (setq sia (mapcar #'(lambda (arg-name) (1+ (position arg-name arg-defs :key #'car))) (cdr head)) body (cdr body))) `(,ctr-param-names (lambda (&rest ,gargs) (let ,(arg-lets (append arg-defs (list this)) (append ctr-param-names (list class-name)) gargs 0) ,@body)) ,sia)))) (process-method-def (method-def methods) (destructuring-bind (method-name return-type modifiers (&rest arg-defs) &body body) method-def (push method-name defined-method-names) (let* ((method (matching-method method-name arg-defs methods)) (method-params (if method (jarray-to-list (jmethod-params method)) (mapcar #'(lambda (arg-def) (find-java-class-in-macro (cadr arg-def))) arg-defs))) (method-param-names #+nil (if method (mapcar #'jclass-name (jarray-to-list method-params)) (mapcar #'cadr arg-defs)) (mapcar #'jclass-name method-params)) (return-type-name (jclass-name (if method (jmethod-return-type method) (find-java-class-in-macro return-type)))) (modifiers #+nil (if method (get-modifier-list method) '("public")) (cond ((and (null modifiers) method) (get-modifier-list method)) ((symbolp modifiers) (list (string-downcase (symbol-name modifiers)))) ((consp modifiers) (mapcar #'(lambda (m) (string-downcase (symbol-name m))) modifiers)) (t (error (format t "Need to provide modifiers for method ~A" method-name))))) (gargs (gensym))) `(,method-name ,return-type-name ,method-param-names (lambda (&rest ,gargs) ;;(,(get-boxer-fn-sym return-type-name) (get-java-object ;;check! (let ,(arg-lets (append arg-defs (list this)) (append method-param-names #+nil (map 'list #'(lambda (p) (jclass-name p)) method-params) (list class-name)) gargs 0) ,@body)) ) ,@modifiers)))) (arg-lets (arg-defs params gargs idx) (when arg-defs (let ((arg (first arg-defs)) (param (first params))) (cons `(,(if (atom arg) arg (first arg)) (,(get-unboxer-fn-sym param) (nth ,idx ,gargs))) (arg-lets (rest arg-defs) (rest params) gargs (1+ idx)))))) (matching-method (method-name arg-defs methods) (let (match) (loop for method across methods when (method-matches method-name arg-defs method) do (if match (error (format nil "more than one method matches ~A" method-name)) (setf match method))) match)) (method-matches (method-name arg-defs method) (when (string-equal method-name (jmethod-name method)) (let ((params (jmethod-params method))) (when (= (length arg-defs) (length params)) (is-congruent arg-defs params))))) (is-congruent (arg-defs params) (every (lambda (arg param) (or (atom arg) ;no type spec matches anything (jeq (find-java-class-in-macro (second arg)) param))) arg-defs (jarray-to-list params)))) (unless (consp super-and-interface-names) (setq super-and-interface-names (list super-and-interface-names))) (let* ((super-name (find-java-class-name-in-macro (car super-and-interface-names))) (interfaces (mapcar #'find-java-class-name-in-macro (cdr super-and-interface-names))) (super (jclass super-name)) (super-ctrs (jclass-constructors super)) (ctrs-ret (loop for ctr-def in constructor-defs collecting (process-ctr-def ctr-def super-ctrs))) (super-methods (jclass-methods super)) (iface-methods (apply #'concatenate 'vector (mapcar #'(lambda (ifn) (jclass-methods (jclass ifn))) interfaces))) (methods-ret (loop for method-def in method-defs collecting (process-method-def method-def (concatenate 'vector super-methods iface-methods))))) ;;check to make sure every function is defined (loop for method across iface-methods for mname = (jmethod-name method) unless (member mname defined-method-names :test #'string-equal) do (warn (format nil "class doesn't define:~%~A" mname))) `(progn (jrc ,class-name ,super-name ,interfaces ',ctrs-ret ',methods-ret (loop for (fn type . mods) in ',field-defs collecting `(,fn ,(find-java-class-name-in-macro type) ,@(mapcar #'(lambda (mod) (string-downcase (symbol-name mod))) mods))) #+nil ,(namestring (merge-pathnames class-name "/tmp/"))) (eval '(def-java-class ,class-name))))))) abcl-src-1.9.0/contrib/jfli/test/yanking.lisp0100644 0000000 0000000 00000035453 14202767264 017656 0ustar000000000 0000000 (defpackage :my (:use :cl)) (in-package :my) ;; runtime-class.lisp is a part of ABCL, but it is excluded from ABCL build, ;; because it requires asm.jar to be present in classpath during the build. ;; ;; The functionality it provides is necessary for dynamic creation of ;; new java classes from Lisp (in particular for the ;; NEW-CLASS macro of jfli ABCL port) (load (concatenate 'string abclidea:*lisp-dir* "org/armedbear/lisp/runtime-class.lisp")) ;; Load jfli (load (concatenate 'string abclidea:*lisp-dir* "jfli-abcl/jfli-abcl.lisp")) (use-package :jfli) ;; "Import" java classes we use. ;; ;; You may produce DEF-JAVA-CLASS forms for all the IDEA API classes automatically: ;; ;; (jfli:dump-wrapper-defs-to-file (concatenate 'string abclidea:*lisp-dir* "idea-api.lisp") ;; (jfli:get-jar-classnames "path/to/idea/openapi.jar" ;; "com/intellij")) ;; ;; ;; In result they will be stored in idea-api.lisp file. ;; ;; But we do it manually, because there are not so many classes we use. (def-java-class "com.intellij.openapi.ui.Messages") (use-package "com.intellij.openapi.ui") (def-java-class "com.intellij.openapi.application.ModalityState") (def-java-class "com.intellij.openapi.application.Application") (def-java-class "com.intellij.openapi.application.ApplicationManager") (use-package "com.intellij.openapi.application") (def-java-class "com.intellij.openapi.actionSystem.AnAction") (def-java-class "com.intellij.openapi.actionSystem.AnActionEvent") (def-java-class "com.intellij.openapi.actionSystem.ActionManager") (def-java-class "com.intellij.openapi.actionSystem.DefaultActionGroup") (def-java-class "com.intellij.openapi.actionSystem.CustomShortcutSet") (def-java-class "com.intellij.openapi.actionSystem.Shortcut") (def-java-class "com.intellij.openapi.actionSystem.KeyboardShortcut") (def-java-class "com.intellij.openapi.actionSystem.CustomShortcutSet") (use-package "com.intellij.openapi.actionSystem") (def-java-class "com.intellij.openapi.ide.CopyPasteManager") (use-package "com.intellij.openapi.ide") (def-java-class "com.intellij.openapi.keymap.KeymapManager") (def-java-class "com.intellij.openapi.keymap.Keymap") (use-package "com.intellij.openapi.keymap") (def-java-class "com.intellij.openapi.project.ProjectManager") (use-package "com.intellij.openapi.project") (def-java-class "com.intellij.openapi.editor.Editor") (def-java-class "com.intellij.openapi.editor.Document") (def-java-class "com.intellij.openapi.editor.SelectionModel") (use-package "com.intellij.openapi.editor") (def-java-class "com.intellij.openapi.fileEditor.FileEditorManager") (def-java-class "com.intellij.openapi.fileEditor.FileEditor") (def-java-class "com.intellij.openapi.fileEditor.TextEditor") (use-package "com.intellij.openapi.fileEditor") (def-java-class "com.intellij.openapi.command.CommandProcessor") (def-java-class "com.intellij.openapi.command.CommandAdapter") (def-java-class "com.intellij.openapi.command.CommandEvent") (use-package "com.intellij.openapi.command") (def-java-class "com.intellij.openapi.wm.WindowManager") (def-java-class "com.intellij.openapi.wm.StatusBar") (use-package "com.intellij.openapi.wm") (def-java-class "java.lang.Runnable") (def-java-class "java.lang.Thread") (def-java-class "java.lang.Object") (def-java-class "java.lang.Class") (def-java-class "java.lang.String") (use-package "java.lang") (def-java-class "java.awt.datatransfer.Transferable") (def-java-class "java.awt.datatransfer.DataFlavor") (use-package "java.awt.datatransfer") (def-java-class "javax.swing.KeyStroke") (use-package "javax.swing") (define-condition action-is-not-applicable () ((why :initarg :why :reader why)) (:report (lambda (condition stream) (format stream "Action is not applicable: ~A" (why condition))))) (defun cur-prj () (let ((all-prjs (projectmanager.getopenprojects (projectmanager.getinstance)))) (when (> (jlength all-prjs) 0) (jref all-prjs 0)))) (defun cur-prj-safe () (or (cur-prj) (error 'action-is-not-applicable :why "no current project"))) (defun cur-editor (prj) (fileeditormanager.getselectedtexteditor (fileeditormanager.getinstance prj))) (defun cur-editor-safe (prj) (or (cur-editor prj) (error 'action-is-not-applicable :why "no text editor is selected"))) ;; region object (defun make-region (start end) (cons start end)) (defun region-start (region) (car region)) (defun region-end (region) (cdr region)) (defun get-sel-region() "Selection in the currently active editor" (let* ((cur-prj (cur-prj-safe)) (cur-editor (cur-editor-safe cur-prj)) (sel-model (editor.getselectionmodel cur-editor))) (make-region (selectionmodel.getselectionstart sel-model) (selectionmodel.getselectionend sel-model)))) (defun replace-region (replacement-text region) "Replace text in the curently active editor" (let* ((cur-prj (cur-prj-safe)) (cur-editor (cur-editor-safe cur-prj)) (cur-doc (editor.getdocument cur-editor))) (document.replacestring cur-doc (region-start region) (region-end region) replacement-text))) (defvar *yank-index* 0 "Index of clipboard item that will be pasted by the next yank or yank-pop operation \(similar to kill-ring-yank-pointer in Emacs\).") (defvar *yank-region* nil "Region of text that was inserted by previous yank or yank-pop command, and that must be replaced by next yank-pop.") (defvar *yank-undo-id* 0 "Yank following by a sequence of yank-pop must be considered as a single action by undo mechanism. This variable is unique identifier of such an compound action.") (defun get-yank-text (&optional (index 0)) (let ((all-contents (copypastemanager.getallcontents (copypastemanager.getinstance))) content) (when (zerop (jlength all-contents)) (RETURN-FROM get-yank-tex nil)) (setf content (jref all-contents (mod index (jlength all-contents)))) (transferable.gettransferdata content (dataflavor.stringflavor)))) (defun get-yank-text-safe (&optional (index 0)) (or (get-yank-text index) (error 'action-is-not-applicable :why "clipboard is empty"))) (defun next-yank-region (cur-selection-region replacement-text) (make-region (region-start cur-selection-region) (+ (region-start cur-selection-region) (length (java:jobject-lisp-value replacement-text))))) (defun yank() (let ((sel-region (get-sel-region)) (yank-text (get-yank-text-safe))) (replace-region yank-text sel-region) (setf *yank-region* (next-yank-region sel-region yank-text)) (setf *yank-index* 1))) (defun make-runnable (fun) (java:jinterface-implementation "java.lang.Runnable" "run" ;; wrap FUN into lambda to allow it to be ;; not only function objects, but also symbols ;; (java:jinterface-implementation supports ;; only function objects) (lambda () (funcall fun)))) (defmacro runnable (&body body) `(make-runnable (lambda () ,@body))) (defun run-write-action (fun) (let ((app (applicationmanager.getapplication)) (runnable (make-runnable fun))) (application.runwriteaction app runnable))) (defun exec-cmd (fun name group-id) (commandprocessor.executecommand (commandprocessor.getinstance) (cur-prj) (make-runnable fun) name group-id)) ;; set status bar text (defun set-status (status-text) (statusbar.setinfo (windowmanager.getstatusbar (windowmanager.getinstance) (cur-prj)) status-text)) (new-class "MY.MyAction" ;; class name anaction. ;; super class ;; constructors ( (((text "java.lang.String") (func "java.lang.Object")) (super text) (setf (myaction.func this) func)) ) ;; methods ( ("actionPerformed" :void :public (action-event) ;; It's usefull to setup a restart before ;; calling FUNC. ;; ;; It helps when slime is connected to ;; the IDEA and error happens ;; during action execution. ;; ;; Slime debugger hooks the error, ;; but as actions are invoked from ;; idea UI event dispatching thread, ;; no slime restarts are set ;; and our restart is the only ;; way to leave SLIME debugger. (restart-case (handler-case (funcall (myaction.func this) action-event) (action-is-not-applicable () ;; NOTE: it is not guaranteed ;; that execution will be passed to this ;; handler, even if your code signals ;; ACTION-IS-NOT-APPLICABLE. ;; ;; It's so because ABCL impements ;; non local exits using java exceptions ;; (org.armedbear.lisp.Go); if somewhere ;; in the call stack below our HANDLER-CASE ;; and above the SIGNAL there is a ;; ;; catch (Throwable) ;; ;; then ABCL's Go exception will be catched. ;; ;; catch (Throwable) is in partiular ;; used by IDEA methods that accept Runnable ;; (like CommandProcessor.executeCommand, ;; Application.runWriteAction) ;; ;; But even despite that, HANDLER-CASE ;; is useful, because ACTION-IS-NOT-APPLICABLE ;; is not trapped by Slime debugger. )) (continue () :report "Return from IDEA action" nil))) ) ;; fields ( ("func" "java.lang.Object" :public)) ) (setf act-yank (myaction.new "yank" nil)) (setf (myaction.func act-yank) #'(lambda (action-event) (declare (ignore action-event)) (incf *yank-undo-id*) (exec-cmd (lambda () (run-write-action 'yank)) "yank" (format nil "yank-~A" *yank-undo-id*)))) (setf edit-menu (actionmanager.getaction (actionmanager.getinstance) "EditMenu")) (actionmanager.registeraction (actionmanager.getinstance) "yank" act-yank) (defaultactiongroup.add edit-menu act-yank) ;;(actionmanager.unregisteraction (actionmanager.getinstance) "yank") ;;(defaultactiongroup.remove edit-menu act-yank) ;; assign keyboard shortcut Ctrl-Y to our action ;; (by default Ctrl-Y is used for delete-line operation in IDEA; ;; override this by unregistering Ctrl-Y from delete-line) (defun action-shortcut (anaction) "The first element of AnAction.getShorcuts()" (jref (customshortcutset.getshortcuts (anaction.getshortcutset anaction)) 0)) (defun remove-shortcut (keystroke-str) "Unregister all the shortcuts specified by KEYSTROKE-STR for all the actions in the active keymap. Example \(REMOVE-SHORTCUT \"control Y\"\)" (let* ((keymap (keymapmanager.getactivekeymap (keymapmanager.getinstance))) (keystroke (keystroke.getkeystroke keystroke-str)) (act-ids (keymap.getactionids keymap keystroke))) (dotimes (i (jlength act-ids)) (let ((shortcuts (keymap.getshortcuts keymap (jref act-ids i)))) (dotimes (j (jlength shortcuts)) (let ((shortcut (jref shortcuts j))) (when (class.isinstance (class.forname "com.intellij.openapi.actionSystem.KeyboardShortcut") shortcut) (when (jeq (keyboardshortcut.getfirstkeystroke shortcut) keystroke) (keymap.removeshortcut keymap (jref act-ids i) shortcut))))))))) ;; this is to display shortcut correctly in the menu (anaction.setshortcutset act-yank (customshortcutset.new (keystroke.getkeystroke "control Y"))) ;; this is to make it actually fired when user presses the key combination (remove-shortcut "control Y") (keymap.addshortcut (keymapmanager.getactivekeymap (keymapmanager.getinstance)) "yank" (action-shortcut act-yank)) ;; yank-pop is allowed only if previous command was yank or yank-pop. ;; Add a command listentener that clears *yank-region* when any ;; other command is executed, and thus makes yank-pop impossible. (new-class "MY.MyCommandListener" ;; class name commandadapter. ;; super class ;; constructors () ;; methods ( ("commandFinished" :void :public (command-event) (unless (member (java:jobject-lisp-value (commandevent.getcommandname command-event)) '("yank" "yank-pop") :test #'string=) (setf *yank-region* nil))) ) ;; fields () ) (setf my-cmd-listener (mycommandlistener.new)) (commandprocessor.addcommandlistener (commandprocessor.getinstance) my-cmd-listener) ;; (actionmanager.unregisteraction (actionmanager.getinstance) "yank-pop") ;; (defaultactiongroup.remove edit-menu act-yank-pop) (defun yank-pop () (let ((yank-text (get-yank-text *yank-index*))) (replace-region yank-text *yank-region*) (setf *yank-region* (make-region (region-start *yank-region*) (+ (region-start *yank-region*) (string.length yank-text))))) (incf *yank-index*)) (setf act-yank-pop (myaction.new "yank-pop" nil)) (setf (myaction.func act-yank-pop) #'(lambda (action-event) (if *yank-region* (exec-cmd (lambda () (run-write-action 'yank-pop)) "yank-pop" (format nil "yank-~A" *yank-undo-id*)) (set-status "Previous command was not a yank")))) (actionmanager.registeraction (actionmanager.getinstance) "yank-pop" act-yank-pop) (defaultactiongroup.add edit-menu act-yank-pop) (anaction.setshortcutset act-yank-pop (customshortcutset.new (keystroke.getkeystroke "alt Y"))) (keymap.addshortcut (keymapmanager.getactivekeymap (keymapmanager.getinstance)) "yank-pop" (action-shortcut act-yank-pop)) abcl-src-1.9.0/contrib/jss/README.markdown0100644 0000000 0000000 00000011331 14223403213 016667 0ustar000000000 0000000 JSS === Created by Alan Ruttenberg JSS stands for either "Java Simple Syntax" or "Java Syntax Sucks", depending on your mood. The dynamic dispatch of the java.lang.reflect package is used to make it real easy, if perhaps less efficient, to write Java code since you don't need to be bothered with imports, or with figuring out which method to call. The only time that you need to know a class name is when you want to call a static method, or a constructor, and in those cases, you only need to know enough of the class name that is unique wrt to the classes on your classpath. Java methods look like this: #"toString". Java classes are represented as symbols, which are resolved to the appropriate java class name. When ambiguous, you need to be more specific. A simple example from CL-USER: (require :jss) (let ((sw (new 'StringWriter))) (#"write" sw "Hello ") (#"write" sw "World") (print (#"toString" sw))) What's happened here? First, all the classes in all the jars in the classpath have been collected. For each class a.b.C.d, we have recorded that b.c.d, b.C.d, C.d, c.d, and d potentially refer to this class. In your call to new, as long as the symbol can refer to only one class, we use that class. In this case, it is java.io.StringWriter. You could also have written (new 'io.stringwriter) or (new '|io.StringWriter|) or (new 'java.io.StringWriter) The call (#"write" sw "Hello ") uses the code in invoke.java to call the method named "write" with the arguments sw and "Hello ". JSS figures out the right java method to call, and calls it. An interactive restart is available to resolve class ambiguity. Static calls are possible as well with the SHARPSIGN-QUOTATION_MARK macro, but the first argument *must* be a symbol to distinguish (#"getProperties" "java.lang.System") from (#"getProperties" 'java.lang.System) The first attempts to call a method on the java.lang.String object with the contents "java.lang.System", which results in an error, while the second invokes the static java.lang.System.getProperties() method. If you want to do a raw java call, use #0"toString". Raw calls return their results as Java objects, avoiding doing the usual Java object to Lisp object conversions that ABCL does. (with-constant-signature ((name jname raw?)*) &body body) binds a macro which expands to a jcall, promising that the same method will be called every time. Use this if you are making a lot of calls and want to avoid the overhead of a the dynamic dispatch. e.g. (with-constant-signature ((tostring "toString")) (time (dotimes (i 10000) (tostring "foo")))) runs about three times faster than (time (dotimes (i 10000) (#"toString" "foo"))) So, something like (with-constant-signature ((tostring "toString" t)) ...) will cause the toString to be a raw java call. See JSS::GET-ALL-JAR-CLASSNAMES for an example. Implementation is that the first time the function is called, the method is looked up based on the arguments passed, and thereafter that method is called directly. Doesn't work for static methods at the moment (lazy) (japropos string) finds all class names matching STRING. (jcmn class-name) lists the names of all methods for the CLASS-NAME. Java static fields may be addressed via the SHARPSIGN-QUOTATION_MARK macro as (#"java.lang.System.out") Java fields can by dynamically accessed with (let ((class 'java.lang.system) (field "out")) #"{class}.{field}") ### Javaparser Use #1"" to use JAVAPARSER to parse an expression. JAVAPARSER will be loaded on first use. (#1"new ByteBuddy() .subclass(Object.class,t) .method(ElementMatchers.named("toString")) .intercept(FixedValue.value("Hello World!")) .make() .load(getClass().getClassLoader()) .getLoaded()" # Compatibility The function ENSURE-COMPATIBILITY attempts to provide a compatibility mode to existing users of JSS by importing the necessary symbols into CL-USER. Some notes on other compatibility issues: *classpath-manager* Since we are no longer using Beanshell, this is no longer present. For obtaining the current classloader use JAVA:*CLASSLOADER*. # API 1.0 Equivalent to Alan Ruttenberg's version included with the original [lsw2](). [lsw]: http://mumble.net:8080/svn/lsw/trunk/ [lsw2]: https://github.com/alanruttenberg/lsw2 3.0 The results the of having JSS package loaded from [abcl-contrib][] [abcl-contrib]: http://abcl.org/svn/trunk/abcl/contrib/ # Colophon <> dc:created "2005" ; dc:author "Mark "; dc:revised "11-JUN-2017" . abcl-src-1.9.0/contrib/jss/classpath.lisp0100644 0000000 0000000 00000001003 14202767264 017054 0ustar000000000 0000000 (in-package :java) (defmethod add-to-classpath :after ((uri-or-uris t) &optional classloader) (declare (ignore classloader)) (let ((paths (if (listp uri-or-uris) uri-or-uris (list uri-or-uris)))) (dolist (path paths) (let ((absolute (namestring (truename path)))) (cond ((equal (pathname-type absolute) "jar") (jss:jar-import absolute)) ((ext:file-directory-p absolute) (jss:classfiles-import absolute))))))) abcl-src-1.9.0/contrib/jss/collections.lisp0100644 0000000 0000000 00000024132 14202767264 017420 0ustar000000000 0000000 (in-package :jss) (defun set-to-list (set) "Convert the java.util.Set named in SET to a Lisp list." (declare (optimize (speed 3) (safety 0))) (with-constant-signature ((iterator "iterator" t) (hasnext "hasNext") (next "next")) (loop with iterator = (iterator set) while (hasNext iterator) for item = (next iterator) collect item))) (defun jlist-to-list (list) "Convert a LIST implementing java.util.List to a Lisp list." (declare (optimize (speed 3) (safety 0))) (loop :for i :from 0 :below (jcall "size" list) :collecting (jcall "get" list i))) (defun jarray-to-list (jarray) "Convert the Java array named by JARRARY into a Lisp list." (declare (optimize (speed 3) (safety 0))) (loop :for i :from 0 :below (jarray-length jarray) :collecting (jarray-ref jarray i))) ;;; Deprecated ;;; ;;; XXX unclear what sort of list this would actually work on, as it ;;; certainly doesn't seem to be any of the Java collection types ;;; (what implements getNext())? (defun list-to-list (list) (declare (optimize (speed 3) (safety 0))) (with-constant-signature ((isEmpty "isEmpty") (getfirst "getFirst") (getNext "getNext")) (loop until (isEmpty list) collect (getFirst list) do (setq list (getNext list))))) ;; Contribution of Luke Hope. (Thanks!) (defun iterable-to-list (iterable) "Return the items contained the java.lang.Iterable ITERABLE as a list." (declare (optimize (speed 3) (safety 0))) (let ((it (#"iterator" iterable))) (with-constant-signature ((has-next "hasNext") (next "next")) (loop :while (has-next it) :collect (next it))))) (defun vector-to-list (vector) "Return the elements of java.lang.Vector VECTOR as a list." (declare (optimize (speed 3) (safety 0))) (with-constant-signature ((has-more "hasMoreElements") (next "nextElement")) (let ((elements (#"elements" vector))) (loop :while (has-more elements) :collect (next elements))))) (defun hashmap-to-hashtable (hashmap &rest rest &key (keyfun #'identity) (valfun #'identity) (invert? nil) table &allow-other-keys ) "Converts the a HASHMAP reference to a java.util.HashMap object to a Lisp hashtable. The REST paramter specifies arguments to the underlying MAKE-HASH-TABLE call. KEYFUN and VALFUN specifies functions to be run on the keys and values of the HASHMAP right before they are placed in the hashtable. If INVERT? is non-nil than reverse the keys and values in the resulting hashtable." (let ((keyset (#"keySet" hashmap)) (table (or table (apply 'make-hash-table (loop for (key value) on rest by #'cddr unless (member key '(:invert? :valfun :keyfun :table)) collect key and collect value))))) (with-constant-signature ((iterator "iterator" t) (hasnext "hasNext") (next "next")) (loop with iterator = (iterator keyset) while (hasNext iterator) for item = (next iterator) do (if invert? (setf (gethash (funcall valfun (#"get" hashmap item)) table) (funcall keyfun item)) (setf (gethash (funcall keyfun item) table) (funcall valfun (#"get" hashmap item))))) table))) ;; **************************************************************** ;; But needing to remember is annoying ;; Here's a summary I gleaned: ;; java.util.Dictionary -> #"elements" yields java.util.Collections$3 ;; java.util.AbstractCollection -> #"iterator" yields java.util.Iterator? ;; org.apache.felix.framework.util.CompoundEnumeration -> implements java.util.Enumeration ;; java.util.Collections -> doc says #"iterator" yields java.util.Iterator ;; java.util.Collections$1) -> implements java.util.Iterator ;; java.util.Collections$2) -> implements java.util.Spliterator (#"iterator" (#"stream" 'StreamSupport )) -> java.util.Iterator ;; java.util.Collections$3) -> implements java.util.Enumeration ;; java.util.Iterator ;; ("next" "hasNext") ;; java.util.Enumeration) ;; ("nextElement" "hasMoreElements") ;; TODO: maybe do it even more MAPC-style and accept multiple sequences too? (defun jmap (function thing) "Call FUNCTION for every element in the THING. Returns NIL. THING may be a wide range of Java collection types, their common iterators or a Java array. In case the THING is a map-like object, FUNCTION will be called with two arguments, key and value." (flet ((iterator-run (iterator) (with-constant-signature ((has-next "hasNext") (next "next")) (loop :while (has-next iterator) :do (funcall function (next iterator))))) (enumeration-run (enumeration) (with-constant-signature ((has-next "hasMoreElements") (next "nextElement")) (loop :while (has-next enumeration) :do (funcall function (next enumeration))))) (map-run (map) (with-constant-signature ((has-next "hasMoreElements") (next "nextElement")) (let ((keyiterator (#"iterator" (#"keyset" map)))) (loop :while (has-next keyiterator) :for key = (next keyiterator) :do (funcall function key (#"get" map key))))))) (let ((isinstance (load-time-value (jmethod "java.lang.Class" "isInstance" "java.lang.Object")))) (cond ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.AbstractCollection"))) thing) (iterator-run (#"iterator" thing))) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Iterator"))) thing) (iterator-run thing)) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.lang.Iterable"))) thing) (iterator-run (#"iterator" thing))) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Enumeration"))) thing) (enumeration-run thing)) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.AbstractMap"))) thing) (map-run thing)) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Collections"))) thing) (iterator-run (#"iterator" thing))) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Spliterator"))) thing) (iterator-run (#"iterator" (#"stream" 'StreamSupport thing)))) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Dictionary"))) thing) (iterator-run (#"elements" thing))) (t (let ((jarray (ignore-errors (or (and (jclass-array-p (jclass-of thing)) thing) (#"toArray" thing))))) (if jarray (loop :for i :from 0 :below (jarray-length jarray) :do (funcall function (jarray-ref jarray i))) (error "yet another iteration type - fix it: ~a" (jclass-name (jobject-class thing))))))))) NIL) (defun j2list (thing) "Attempt to construct a Lisp list out of a Java THING. THING may be a wide range of Java collection types, their common iterators or a Java array." (declare (optimize (speed 3) (safety 0))) (flet ((iterator-collect (iterator) (with-constant-signature ((has-next "hasNext") (next "next")) (loop :while (has-next iterator) :collect (next iterator)))) (enumeration-collect (enumeration) (with-constant-signature ((has-next "hasMoreElements") (next "nextElement")) (loop :while (has-next enumeration) :collect (next enumeration)))) (map-collect (map) (with-constant-signature ((has-next "hasMoreElements") (next "nextElement")) (let ((keyiterator (#"iterator" (#"keyset" map)))) (loop :while (has-next keyiterator) :for key = (next keyiterator) :collect (cons key (#"get" map key))))))) (let ((isinstance (load-time-value (jmethod "java.lang.Class" "isInstance" "java.lang.Object")))) (cond ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.AbstractCollection"))) thing) (iterator-collect (#"iterator" thing))) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Iterator"))) thing) (iterator-collect thing)) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.lang.Iterable"))) thing) (iterator-collect (#"iterator" thing))) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Enumeration"))) thing) (enumeration-collect thing)) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.AbstractMap"))) thing) (map-collect thing)) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Collections"))) thing) (iterator-collect (#"iterator" thing))) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Spliterator"))) thing) (iterator-collect (#"iterator" (#"stream" 'StreamSupport thing)))) ((jcall isinstance (load-time-value (ignore-errors (jclass "java.util.Dictionary"))) thing) (iterator-collect (#"elements" thing))) (t (let ((jarray (ignore-errors (or (and (jclass-array-p (jclass-of thing)) thing) (#"toArray" thing))))) (if jarray (loop :for i :from 0 :below (jarray-length jarray) :collect (jarray-ref jarray i)) (error "yet another iteration type - fix it: ~a" (jclass-name (jobject-class thing)))))))))) (defun to-hashset (list) "Convert LIST to the java.util.HashSet contract" (let ((set (new 'java.util.hashset))) (loop for l in list do (#"add" set l)) set)) abcl-src-1.9.0/contrib/jss/compat.lisp0100644 0000000 0000000 00000001630 14202767264 016363 0ustar000000000 0000000 (in-package :jss) (defparameter *cl-user-compatibility* nil "Whether backwards compatibility with JSS's use of CL-USER has been enabled.") (defun ensure-compatibility () "Ensure backwards compatibility with JSS's use of CL-USER." (require 'abcl-asdf) (loop :for symbol :in '("add-directory-jars-to-class-path" "need-to-add-directory-jar?") :do (unintern (intern symbol "CL-USER") :cl-user) :do (import (intern symbol "ABCL-ASDF") :cl-user)) (let ((dont-export '(*cl-user-compatibility* add-to-classpath))) (loop :for symbol :being :each :external-symbol :in :jss :when (not (find symbol dont-export)) :do (unintern symbol :cl-user) :and :do (import symbol :cl-user))) (setf *cl-user-compatibility* t)) ;;; Because we're the last file in the ASDF system at the moment (provide 'jss) abcl-src-1.9.0/contrib/jss/invoke.lisp0100644 0000000 0000000 00000077052 14223403213 016366 0ustar000000000 0000000 ;; Copyright (C) 2005 Alan Ruttenberg ;; Copyright (C) 2011-2 Mark Evenson ;; ;; Since JSS 1.0 was largely derivative of the Jscheme System, the ;; current system is licensed under the same terms, namely: ;; This software is provided 'as-is', without any express or ;; implied warranty. ;; In no event will the author be held liable for any damages ;; arising from the use of this software. ;; Permission is granted to anyone to use this software for any ;; purpose, including commercial applications, and to alter it ;; and redistribute it freely, subject to the following ;; restrictions: ;; 1. The origin of this software must not be misrepresented; you ;; must not claim that you wrote the original software. If you ;; use this software in a product, an acknowledgment in the ;; product documentation would be appreciated but is not ;; required. ;; 2. Altered source versions must be plainly marked as such, and ;; must not be misrepresented as being the original software. ;; 3. This notice may not be removed or altered from any source ;; distribution. ;; The dynamic dispatch of the java.lang.reflect package is used to ;; make it real easy, if perhaps less efficient, to write Java code ;; since you don't need to be bothered with imports, or with figuring ;; out which method to call. The only time that you need to know a ;; class name is when you want to call a static method, or a ;; constructor, and in those cases, you only need to know enough of ;; the class name that is unique wrt to the classes on your classpath. ;; ;; Java methods look like this: #"toString". Java classes are ;; represented as symbols, which are resolved to the appropriate java ;; class name. When ambiguous, you need to be more specific. A simple example: ;; (let ((sw (new 'StringWriter))) ;; (#"write" sw "Hello ") ;; (#"write" sw "World") ;; (print (#"toString" sw))) ;; What's happened here? First, all the classes in all the jars in the ;; classpath have been collected. For each class a.b.C.d, we have ;; recorded that b.c.d, b.C.d, C.d, c.d, and d potentially refer to ;; this class. In your call to new, as long as the symbol can refer to ;; only one class, we use that class. In this case, it is ;; java.io.StringWriter. You could also have written (new ;; 'io.stringwriter), (new '|io.StringWriter|), (new ;; 'java.io.StringWriter)... ;; the call (#"write" sw "Hello "), uses the code in invoke.java to ;; call the method named "write" with the arguments sw and "Hello ". ;; JSS figures out the right java method to call, and calls it. ;; If you want to do a raw java call, use #0"toString". Raw calls ;; return their results as Java objects, avoiding doing the usual Java ;; object to Lisp object conversions that ABCL does. ;; (with-constant-signature ((name jname raw?)*) &body body) ;; binds a macro which expands to a jcall, promising that the same method ;; will be called every time. Use this if you are making a lot of calls and ;; want to avoid the overhead of a the dynamic dispatch. ;; e.g. (with-constant-signature ((tostring "toString")) ;; (time (dotimes (i 10000) (tostring "foo")))) ;; runs about 3x faster than (time (dotimes (i 10000) (#"toString" "foo"))) ;; ;; (with-constant-signature ((tostring "toString" t)) ...) will cause the ;; toString to be a raw java call. see get-all-jar-classnames below for an example. ;; ;; Implementation is that the first time the function is called, the ;; method is looked up based on the arguments passed, and thereafter ;; that method is called directly. Doesn't work for static methods at ;; the moment (lazy) ;; ;; (japropos string) finds all class names matching string ;; (jcmn class-name) lists the names of all methods for the class ;; ;; TODO ;; - Make with-constant-signature work for static methods too. ;; - #2"toString" to work like function scoped (with-constant-signature ((tostring "toString")) ...) ;; - #3"toString" to work like runtime scoped (with-constant-signature ((tostring "toString")) ...) ;; (both probably need compiler support to work) ;; - Maybe get rid of second " in reader macro. #"toString looks nicer, but might ;; confuse lisp mode. ;; - write jmap, analogous to map, but can take java collections, java arrays etc. ;; In progress with jss-3.5.0's JSS:MAP ;; - write loop clauses for java collections. ;; - Register classes in .class files below classpath directories (when :wild-inferiors works) ;; - Make documentation like Edi Weitz ;; ;; Thanks: Peter Graves, Jscheme developers, Mike Travers for skij, ;; Andras Simon for jfli-abcl which bootstrapped me and taught me how to do ;; get-all-jar-classnames ;; ;; changelog ;; Sat January 28, 2006, alanr: ;; Change imports strategy. Only index by last part of class name, ;; case insensitive. Make the lookup-class-name logic be a bit more ;; complicated. This substantially reduces the time it takes to do the ;; auto imports and since class name lookup is relatively infrequent, ;; and in any case cached, this doesn't effect run time speed. (did ;; try caching, but didn't pay - more time was spent reading and ;; populating large hash table) ;; ;; Split class path by ";" in addition to ":" for windows. ;; ;; Tested on windows, linux. ;; 2011-05-21 Mark Evenson ;; "ported" to native ABCL without needing the jscheme.jar or bsh-2.0b4.jar (in-package :jss) (eval-when (:compile-toplevel :load-toplevel :execute) (defvar *do-auto-imports* t "Whether to automatically introspect all Java classes on the classpath when JSS is loaded.") (defvar *muffle-warnings* t "Attempt to make JSS less chatting about how things are going.") (defvar *imports-resolved-classes* (make-hash-table :test 'equalp) "Hashtable of all resolved imports by the current process.")) (defun find-java-class (name) "Returns the java.lang.Class representation of NAME. NAME can either string or a symbol according to the usual JSS conventions." (jclass (maybe-resolve-class-against-imports name))) (defmacro invoke-add-imports (&rest imports) "Push these imports onto the search path. If multiple, earlier in list take precedence" `(eval-when (:compile-toplevel :load-toplevel :execute) (clrhash *imports-resolved-classes*) (dolist (i (reverse ',imports)) (setq *imports-resolved-classes* (delete i *imports-resolved-classes* :test 'equal)) ))) (defun clear-invoke-imports () (clrhash *imports-resolved-classes*)) (defun maybe-resolve-class-against-imports (classname) (or (gethash (string classname) *imports-resolved-classes*) (let ((found (lookup-class-name classname))) (if found (progn (setf (gethash classname *imports-resolved-classes*) found) found) (string classname))))) (defvar *class-name-to-full-case-insensitive* (make-hash-table :test 'equalp)) ;; This is the function that calls invoke to call your java ;; method. The first argument is the method name or 'new. The second ;; is the object you are calling it on, followed by the rest of the ;; arguments. If the "object" is a symbol, then that symbol is assumed ;; to be a java class, and a static method on the class is called, ;; otherwise a regular method is called. (defun invoke (method object &rest args) (invoke-restargs method object args)) (defun invoke-restargs (method object args &optional (raw? nil)) (let* ((object-as-class-name (if (symbolp object) (maybe-resolve-class-against-imports object))) (object-as-class (if object-as-class-name (find-java-class object-as-class-name)))) (if (eq method 'new) (apply #'jnew (or object-as-class-name object) args) (if raw? (if (symbolp object) (apply #'jstatic-raw method object-as-class args) (apply #'jcall-raw method object args)) (if (symbolp object) (apply #'jstatic method object-as-class args) (apply #'jcall method object args)))))) (defconstant +set-accessible+ (jmethod "java.lang.reflect.AccessibleObject" "setAccessible" "boolean")) (defun invoke-find-method (method object args) (let ((result (if (symbolp object) ;;; static method (apply #'jmethod (lookup-class-name object) method (mapcar #'jobject-class args)) ;;; instance method (apply #'jresolve-method method object args)))) (jcall +set-accessible+ result +true+) result)) ;; This is the reader macro for java methods. it translates the method ;; into a lambda form that calls invoke. Which is nice because you ;; can, e.g. do this: (mapcar #"toString" list-of-java-objects). The reader ;; macro takes one arg. If 0, then jstatic-raw is called, so that abcl doesn't ;; automagically convert the returned java object into a lisp object. So ;; #0"toString" returns a java.lang.String object, where as #"toString" returns ;; a regular Lisp string as ABCL converts the Java string to a Lisp string. (eval-when (:compile-toplevel :load-toplevel :execute) (defun read-invoke (stream char arg) (if (eql arg 1) (progn (asdf:make 'javaparser) (read-sharp-java-expression stream)) (progn (unread-char char stream) (let ((name (read stream))) (if (or (find #\. name) (find #\{ name)) (jss-transform-to-field name arg) (let ((object-var (gensym)) (args-var (gensym))) `(lambda (,object-var &rest ,args-var) (invoke-restargs ,name ,object-var ,args-var ,(eql arg 0))))))))) (set-dispatch-macro-character #\# #\" 'read-invoke)) (defmacro with-constant-signature (fname-jname-pairs &body body) "Expand all references to FNAME-JNAME-PAIRS in BODY into static function calls promising that the same function bound in the FNAME-JNAME-PAIRS will be invoked with the same argument signature. FNAME-JNAME-PAIRS is a list of (symbol function &optional raw) elements where symbol will be the symbol bound to the method named by the string function. If the optional parameter raw is non-nil, the result will be the raw JVM object, uncoerced by the usual conventions. Use this macro if you are making a lot of calls and want to avoid the overhead of the dynamic dispatch." (if (null fname-jname-pairs) `(progn ,@body) (destructuring-bind ((fname jname &optional raw) &rest ignore) fname-jname-pairs (declare (ignore ignore)) (let ((varname (gensym))) `(let ((,varname nil)) (macrolet ((,fname (&rest args) `(if ,',varname (if ,',raw (jcall-raw ,',varname ,@args) (jcall ,',varname ,@args)) (progn (setq ,',varname (invoke-find-method ,',jname ,(car args) (list ,@(rest args)))) (if ,',raw (jcall-raw ,',varname ,@args) (jcall ,',varname ,@args)))))) (with-constant-signature ,(cdr fname-jname-pairs) ,@body))))))) (defvar *class-lookup-overrides*) (defmacro with-class-lookup-disambiguated (overrides &body body) "Suppose you have code that references class using the symbol 'object, and this is ambiguous. E.g. in my system java.lang.Object, org.omg.CORBA.Object. Use (with-class-lookup-disambiguated (lang.object) ...). Within dynamic scope, find-java-class first sees if any of these match, and if so uses them to lookup the class." `(let ((*class-lookup-overrides* ',overrides)) ,@body)) (defun maybe-found-in-overridden (name) (when (boundp '*class-lookup-overrides*) (let ((found (find-if (lambda(el) (#"matches" (string el) (concatenate 'string "(?i).*" (string name) "$"))) *class-lookup-overrides*))) (if found (let ((*class-lookup-overrides* nil)) (lookup-class-name found)))))) (defun lookup-class-name (name &key (table *class-name-to-full-case-insensitive*) (muffle-warning *muffle-warnings*) (return-ambiguous nil)) (let ((overridden (maybe-found-in-overridden name))) (when overridden (return-from lookup-class-name overridden))) (setq name (string name)) (let* (;; cant (last-name-pattern (#"compile" '|java.util.regex.Pattern| ".*?([^.]*)$")) ;; reason: bootstrap - the class name would have to be looked up... (last-name-pattern (load-time-value (jstatic (jmethod "java.util.regex.Pattern" "compile" (jclass "java.lang.String")) (jclass "java.util.regex.Pattern") ".*?([^.]*)$"))) (last-name (let ((matcher (#0"matcher" last-name-pattern name))) (#"matches" matcher) (#"group" matcher 1)))) (let* ((bucket (gethash last-name *class-name-to-full-case-insensitive*)) (bucket-length (length bucket))) (or (find name bucket :test 'equalp) (flet ((matches-end (end full test) (= (+ (or (search end full :from-end t :test test) -10) (length end)) (length full))) (ambiguous (choices) (if return-ambiguous (return-from lookup-class-name choices) (error "Ambiguous class name: ~a can be ~{~a~^, ~}" name choices)))) (if (zerop bucket-length) (progn (unless muffle-warning (warn "can't find class named ~a" name)) nil) (let ((matches (loop for el in bucket when (matches-end name el 'char=) collect el))) (if (= (length matches) 1) (car matches) (if (= (length matches) 0) (let ((matches (loop for el in bucket when (matches-end name el 'char-equal) collect el))) (if (= (length matches) 1) (car matches) (if (= (length matches) 0) (progn (unless muffle-warning (warn "can't find class named ~a" name)) nil) (ambiguous matches)))) (ambiguous matches)))))))))) #+(or) (defun get-all-jar-classnames (jar-file-name) (let* ((jar (jnew (jconstructor "java.util.jar.JarFile" (jclass "java.lang.String")) (namestring (truename jar-file-name)))) (entries (#"entries" jar))) (with-constant-signature ((matcher "matcher" t) (substring "substring") (jreplace "replace" t) (jlength "length") (matches "matches") (getname "getName" t) (next "nextElement" t) (hasmore "hasMoreElements") (group "group")) (loop while (hasmore entries) for name = (getname (next entries)) with class-pattern = (jstatic "compile" "java.util.regex.Pattern" ".*\\.class$") with name-pattern = (jstatic "compile" "java.util.regex.Pattern" ".*?([^.]*)$") when (matches (matcher class-pattern name)) collect (let* ((fullname (substring (jreplace name #\/ #\.) 0 (- (jlength name) 6))) (matcher (matcher name-pattern fullname)) (name (progn (matches matcher) (group matcher 1)))) (cons name fullname)) )))) #| Under openjdk11 this is around 10x slower than (list (time (jss::get-all-jar-classnames "/Users/evenson/work/abcl-jdk11/dist/abcl.jar")) (time (jss::%get-all-jar-classnames "/Users/evenson/work/abcl-jdk11/dist/abcl.jar"))) 0.034 seconds real time 2268 cons cells 0.12 seconds real time 209164 cons cells |# (defun get-all-jar-classnames (jar-pathname-or-string) (let* ((jar (if (ext:pathname-jar-p jar-pathname-or-string) jar-pathname-or-string ;; better be a string (ext:as-jar-pathname-archive jar-pathname-or-string))) (entries (directory (merge-pathnames "**/*" jar)))) (loop :for entry :in entries :for name = (pathname-name entry) :for type = (pathname-type entry) :when (equal type "class") :collect (cons name ;;; Fully qualified classname be like 'org.armedbear.lisp.ArgumentListProcessor$ArgumentMatcher' (format nil "~{~a.~}~a" (rest (pathname-directory entry)) name))))) (defun jar-import (file) "Import all the Java classes contained in the pathname FILE into the JSS dynamic lookup cache." (when (probe-file file) (loop for (name . full-class-name) in (get-all-jar-classnames file) do (pushnew full-class-name (gethash name *class-name-to-full-case-insensitive*) :test 'equal)))) (defun new (class-name &rest args) "Invoke the Java constructor for CLASS-NAME with ARGS. CLASS-NAME may either be a symbol or a string according to the usual JSS conventions." (invoke-restargs 'new class-name args)) (defvar *running-in-osgi* (ignore-errors (jclass "org.osgi.framework.BundleActivator"))) (define-condition no-such-java-field (error) ((field-name :initarg :field-name :reader field-name ) (object :initarg :object :reader object )) (:report (lambda (c stream) (format stream "Unable to find a FIELD named ~a for ~a" (field-name c) (object c)))) ) (defun get-java-field (object field &optional (try-harder *running-in-osgi*)) "Get the value of the FIELD contained in OBJECT. If OBJECT is a symbol it names a dot qualified static FIELD." (if try-harder (let* ((class (if (symbolp object) (setq object (find-java-class object)) (if (equal "java.lang.Class" (jclass-name (jobject-class object))) object (jobject-class object)))) (jfield (if (java-object-p field) field (or (find-declared-field field class) (error 'no-such-java-field :field-name field :object object))))) (#"setAccessible" jfield +true+) (values (#"get" jfield object) jfield)) (if (symbolp object) (let ((class (find-java-class object))) (jfield class field)) (jfield field object)))) (defun find-declared-field (field class) "Return a FIELD object corresponding to the definition of FIELD \(a string\) visible at CLASS. *Not* restricted to public classes, and checks all superclasses of CLASS. Returns NIL if no field object is found." (loop while class for field-obj = (get-declared-field class field) if field-obj do (return-from find-declared-field field-obj) else do (setf class (jclass-superclass class))) nil) (defun get-declared-field (class fieldname) (find fieldname (#"getDeclaredFields" class) :key 'jfield-name :test 'equal)) ;; TODO use #"getSuperclass" and #"getInterfaces" to see whether there ;; are fields in superclasses that we might set (defun set-java-field (object field value &optional (try-harder *running-in-osgi*)) "Set the FIELD of OBJECT to VALUE. If OBJECT is a symbol, it names a dot qualified Java class to look for a static FIELD. If OBJECT is an instance of java:java-object, the associated is used to look up the static FIELD." (if try-harder (let* ((class (if (symbolp object) (setq object (find-java-class object)) (if (equal "java.lang.Class" (jclass-name (jobject-class object)) ) object (jobject-class object)))) (jfield (if (java-object-p field) field (or (find-declared-field field class) (error 'no-such-java-field :field-name field :object object))))) (#"setAccessible" jfield +true+) (values (#"set" jfield object value) jfield)) (if (symbolp object) (let ((class (find-java-class object))) (setf (jfield (#"getName" class) field) value)) (if (typep object 'java-object) (setf (jfield (jclass-of object) field) value) (setf (jfield object field) value))))) (defun (setf get-java-field) (value object field &optional (try-harder *running-in-osgi*)) (set-java-field object field value try-harder)) (defconstant +for-name+ (jmethod "java.lang.Class" "forName" "java.lang.String" "boolean" "java.lang.ClassLoader")) (defun find-java-class (name) (or (jstatic +for-name+ "java.lang.Class" (maybe-resolve-class-against-imports name) +true+ java::*classloader*) (ignore-errors (jclass (maybe-resolve-class-against-imports name))))) (defmethod print-object ((obj (jclass "java.lang.Class")) stream) (print-unreadable-object (obj stream :identity nil) (format stream "java class ~a" (jclass-name obj)))) (defmethod print-object ((obj (jclass "java.lang.reflect.Method")) stream) (print-unreadable-object (obj stream :identity nil) (format stream "method ~a" (#"toString" obj)))) (defun do-auto-imports () (if (sys::system-artifacts-are-jars-p) (do-auto-imports-from-jars) (progn ;;; First, import all the classes available from the module system (do-auto-imports-from-modules) ;;; Then, introspect any jars that appear on the classpath (loop :for entry :in (second (multiple-value-list (sys::java.class.path))) :doing (let ((p (pathname entry))) (when (string-equal (pathname-type p) "jar") (jar-import p))))))) (defun do-auto-imports-from-modules () (loop :for (name . full-class-name) :in (all-class-names-from-modules) :doing (pushnew full-class-name (gethash name *class-name-to-full-case-insensitive*) :test 'equal))) (defun all-class-names-from-modules () (let ((class-pattern (jstatic "compile" "java.util.regex.Pattern" ".*\\.class$")) (name-pattern (jstatic "compile" "java.util.regex.Pattern" ".*?([^.]*)$"))) (loop :for module :across (chain (jstatic "boot" "java.lang.ModuleLayer") "configuration" "modules" "stream" "toArray") :appending (loop :for class-as-path :across (chain module "reference" "open" "list" "toArray") :when (jcall "matches" (jcall "matcher" class-pattern class-as-path)) :collect (let* ((full-name (jcall "substring" (jcall "replace" class-as-path #\/ #\.) 0 (- (jcall "length" class-as-path) (jcall "length" ".class")))) (matcher (jcall "matcher" name-pattern full-name)) (name (progn (jcall "matches" matcher) (jcall "group" matcher 1)))) (cons name full-name)))))) (defun do-auto-imports-from-jars () (labels ((expand-paths (cp) (loop :for s :in cp :appending (loop :for entry :in (let ((p (pathname s))) (if (wild-pathname-p p) (directory p) (list p))) :collecting entry))) (import-classpath (cp) (mapcar (lambda (p) (when *load-verbose* (format t ";; Importing ~A~%" p)) (cond ((file-directory-p p) ) ((equal (pathname-type p) "jar") (jar-import (merge-pathnames p (format nil "~a/" (jstatic "getProperty" "java.lang.System" "user.dir"))))))) cp)) (split-classpath (cp) (coerce (jcall "split" cp (string (jfield (jclass "java.io.File") "pathSeparatorChar"))) 'cons)) (do-imports (cp) (import-classpath (expand-paths (split-classpath cp))))) (let ((mx-bean (jstatic "getRuntimeMXBean" '|java.lang.management.ManagementFactory|))) (do-imports (jcall "getClassPath" mx-bean)) (do-imports (jcall "getBootClassPath" mx-bean))))) (eval-when (:load-toplevel :execute) (when *do-auto-imports* (do-auto-imports))) (defun japropos (string) "Output the names of all Java class names loaded in the current process which match STRING.." (setq string (string string)) (let ((matches nil)) (maphash (lambda(key value) (declare (ignore key)) (loop for class in value when (search string class :test 'string-equal) do (pushnew (list class "Java Class") matches :test 'equal))) *class-name-to-full-case-insensitive*) (loop for (match type) in (sort matches 'string-lessp :key 'car) do (format t "~a: ~a~%" match type)) )) (defun jclass-method-names (class &optional full) (if (java-object-p class) (if (equal (jclass-name (jobject-class class)) "java.lang.Class") (setq class (jclass-name class)) (setq class (jclass-name (jobject-class class))))) (union (remove-duplicates (map 'list (if full #"toString" 'jmethod-name) (#"getMethods" (find-java-class class))) :test 'equal) (ignore-errors (remove-duplicates (map 'list (if full #"toString" 'jmethod-name) (#"getConstructors" (find-java-class class))) :test 'equal)))) (defun java-class-method-names (class &optional stream) "Return a list of the public methods encapsulated by the JVM CLASS. If STREAM non-nil, output a verbose description to the named output stream. CLASS may either be a string naming a fully qualified JVM class in dot notation, or a symbol resolved against all class entries in the current classpath." (if stream (dolist (method (jclass-method-names class t)) (format stream "~a~%" method)) (jclass-method-names class))) (setf (symbol-function 'jcmn) #'java-class-method-names) (defun path-to-class (classname) (let ((full (lookup-class-name classname))) (#"toString" (#"getResource" (find-java-class full) (concatenate 'string "/" (substitute #\/ #\. full) ".class"))))) ;; http://www.javaworld.com/javaworld/javaqa/2003-07/02-qa-0725-classsrc2.html (defun all-loaded-classes () (let ((classes-field (find "classes" (#"getDeclaredFields" (jclass "java.lang.ClassLoader")) :key #"getName" :test 'equal))) (#"setAccessible" classes-field +true+) (loop for classloader in (mapcar #'first (dump-classpath)) append (loop with classesv = (#"get" classes-field classloader) for i below (#"size" classesv) collect (#"getName" (#"elementAt" classesv i))) append (loop with classesv = (#"get" classes-field (#"getParent" classloader)) for i below (#"size" classesv) collect (#"getName" (#"elementAt" classesv i)))))) (defun get-dynamic-class-path () (rest (find-if (lambda (loader) (string= "org.armedbear.lisp.JavaClassLoader" (jclass-name (jobject-class loader)))) (dump-classpath) :key #'car))) (defun java-gc () (#"gc" (#"getRuntime" 'java.lang.runtime)) (#"runFinalization" (#"getRuntime" 'java.lang.runtime)) (#"gc" (#"getRuntime" 'java.lang.runtime)) (java-room)) (defun java-room () (let ((rt (#"getRuntime" 'java.lang.runtime))) (values (- (#"totalMemory" rt) (#"freeMemory" rt)) (#"totalMemory" rt) (#"freeMemory" rt) (list :used :total :free)))) (defun verbose-gc (&optional (new-value nil new-value-supplied)) (if new-value-supplied (progn (#"setVerbose" (#"getMemoryMXBean" 'java.lang.management.ManagementFactory) new-value) new-value) (#"isVerbose" (#"getMemoryMXBean" 'java.lang.management.ManagementFactory)))) (defun all-jars-below (directory) (loop with q = (system:list-directory directory) while q for top = (pop q) if (null (pathname-name top)) do (setq q (append q (all-jars-below top))) if (equal (pathname-type top) "jar") collect top)) (defun all-classfiles-below (directory) (loop with q = (system:list-directory directory) while q for top = (pop q) if (null (pathname-name top)) do (setq q (append q (all-classfiles-below top ))) if (equal (pathname-type top) "class") collect top )) (defun all-classes-below-directory (directory) (loop for file in (all-classfiles-below directory) collect (format nil "~{~a.~}~a" (subseq (pathname-directory file) (length (pathname-directory directory))) (pathname-name file)) )) (defun classfiles-import (directory) "Load all Java classes recursively contained under DIRECTORY in the current process." (setq directory (truename directory)) (loop for full-class-name in (all-classes-below-directory directory) for name = (#"replaceAll" full-class-name "^.*\\." "") do (pushnew full-class-name (gethash name *class-name-to-full-case-insensitive*) :test 'equal))) (defun jclass-all-interfaces (class) "Return a list of interfaces the class implements" (unless (java-object-p class) (setq class (find-java-class class))) (loop for aclass = class then (#"getSuperclass" aclass) while aclass append (coerce (#"getInterfaces" aclass) 'list))) (defun safely (f name) (let ((fname (gensym))) (compile fname `(lambda(&rest args) (with-simple-restart (top-level "Return from lisp method implementation for ~a." ,name) (apply ,f args)))) (symbol-function fname))) (defun jdelegating-interface-implementation (interface dispatch-to &rest method-names-and-defs) "Creates and returns an implementation of a Java interface with methods calling Lisp closures as given in METHOD-NAMES-AND-DEFS. INTERFACE is an interface DISPATCH-TO is an existing Java object METHOD-NAMES-AND-DEFS is an alternating list of method names (strings) and method definitions (closures). For missing methods, a dummy implementation is provided that calls the method on DISPATCH-TO." (let ((implemented-methods (loop for m in method-names-and-defs for i from 0 if (evenp i) do (assert (stringp m) (m) "Method names must be strings: ~s" m) and collect m else do (assert (or (symbolp m) (functionp m)) (m) "Methods must be function designators: ~s" m)))) (let ((safe-method-names-and-defs (loop for (name function) on method-names-and-defs by #'cddr collect name collect (safely function name)))) (loop for method across (jclass-methods interface :declared nil :public t) for method-name = (jmethod-name method) when (not (member method-name implemented-methods :test #'string=)) do (let* ((def `(lambda (&rest args) (invoke-restargs ,(jmethod-name method) ,dispatch-to args t) ))) (push (coerce def 'function) safe-method-names-and-defs) (push method-name safe-method-names-and-defs))) (apply #'java::%jnew-proxy interface safe-method-names-and-defs)))) abcl-src-1.9.0/contrib/jss/javaparser-tests.asd0100644 0000000 0000000 00000000570 14223403213 020160 0ustar000000000 0000000 (in-package :asdf) (defsystem javaparser-tests :defsystem-depends-on (prove-asdf) :depends-on (javaparser prove) :components ((:module tests :pathname "t" :components ((:test-file "javaparser")))) :perform (asdf:test-op (op c) (uiop:symbol-call :prove-asdf 'run-test-system c))) abcl-src-1.9.0/contrib/jss/javaparser.asd0100644 0000000 0000000 00000001011 14223403213 017007 0ustar000000000 0000000 (defsystem javaparser :description "https://github.com/javaparser/javaparser" :defsystem-depends-on (abcl-asdf) :components ((:module jar :components ((:mvn "com.github.javaparser/javaparser-core/3.24.2"))) (:module source :depends-on (jar) :pathname "" :serial t :components ((:file "javaparser") (:file "read-sharp-quote-expression")))) :perform (asdf:test-op (op c) (asdf:test-system :javaparser-tests))) abcl-src-1.9.0/contrib/jss/javaparser.lisp0100644 0000000 0000000 00000006047 14233147074 017240 0ustar000000000 0000000 (in-package :jss) (defvar *class-to-last-component* (make-hash-table :test 'equalp)) (defclass javaparser () ((parser :accessor parser))) (defmethod initialize-instance ((p javaparser)&key) (call-next-method) (setf (parser p) (new 'javaparser))) (defmacro def-java-read (ast-class class fields &body body) (let ((jclass (find-java-class (concatenate 'string "com.github.javaparser.ast.expr." (string ast-class))))) `(progn (setf (gethash ,jclass *class-to-last-component*) ',ast-class) (defmethod ,ast-class ((obj ,class) node &optional ,@(loop for field in fields collect `(,(intern (string-upcase field)) (get-java-field node ,field t)))) ,@body)))) (defvar *object-for-this* (new 'lang.object)) (defmethod get-optional ((r javaparser) node) (if (equal node (load-time-value (#"empty" 'java.util.Optional ))) nil (#"get" node))) (defmethod process-node ((r javaparser) node) (when (jinstance-of-p node "java.util.Optional") (setq node (get-optional r node))) (when (null node) (return-from process-node nil)) (if (java-object-p node) (funcall (gethash (jobject-class node) *class-to-last-component*) r node) node)) (defmethod read-java-expression ((r javaparser) expression) `(let ((this *object-for-this*)) (declare (ignorable this)) ,(process-node r (#"getResult" (#"parseExpression" (parser r) expression))))) (def-java-read LongLiteralExpr javaparser () (read-from-string (#"replaceFirst" (#"getValue" node) "L" ""))) (def-java-read BooleanLiteralExpr javaparser () (if (equal (#"getValue" node) "true") t nil)) (def-java-read IntegerLiteralExpr javaparser nil (parse-integer (#"getValue" node))) (def-java-read DoubleLiteralExpr javaparser nil (let ((raw (#"getValue" node))) (setq raw (#"replaceAll" raw "_" "")) (if (#"matches" raw ".*[dD]$") (read-from-string (#"replaceFirst" (subseq raw 0 (1- (length raw))) "e" "d")) (if (#"matches" raw ".*[fF]$") (read-from-string (subseq raw 0 (1- (length raw)))) (read-from-string raw))))) (def-java-read CharLiteralExpr javaparser nil (#"getValue" node)) (def-java-read StringLiteralExpr javaparser nil (#"getValue" node)) (def-java-read NullLiteralExpr javaparser nil +null+) (def-java-read SimpleName javaparser () (let ((symbol (intern (#"getIdentifier" node)))) symbol)) (def-java-read NameExpr javaparser () (let ((symbol (intern (#"getIdentifier" (#"getName" node))))) symbol)) (eval-when (:compile-toplevel :load-toplevel :execute) (defun read-invoke/javaparser (stream char arg) (if (eql arg 1) (if (ignore-errors (jclass "com.github.javaparser.ParseStart")) ;; chosen randomly, TODO memoize (read-sharp-java-expression stream) ;; Deal with possiblity of not loading jar (error "Cannot load javaparser code needed for the #1 macro")) (read-invoke stream char arg))) (set-dispatch-macro-character #\# #\" 'read-invoke/javaparser)) abcl-src-1.9.0/contrib/jss/jss-tests.asd0100644 0000000 0000000 00000000751 14223403213 016622 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (in-package :asdf) (defsystem jss-tests :defsystem-depends-on (quicklisp-abcl prove-asdf) :depends-on (jss prove) :components ((:module tests :pathname "t" :components ((:test-file "jss-tests") (:test-file "collections")))) :perform (asdf:test-op (op c) (uiop:symbol-call :prove-asdf 'run-test-system c))) abcl-src-1.9.0/contrib/jss/jss.asd0100644 0000000 0000000 00000001531 14242627550 015474 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem jss :author "Alan Ruttenberg, Mark Evenson" :long-description "" :version "3.7.0" :components ((:module base :pathname "" :serial t :components ((:file "packages") (:file "invoke") (:file "collections") (:file "optimize-java-call") (:file "classpath") (:file "transform-to-field") (:file "compat") (:file "jtypecase") (:file "util")))) :perform (asdf:test-op (op c) (asdf:test-system :jss-tests))) abcl-src-1.9.0/contrib/jss/jtypecase.lisp0100644 0000000 0000000 00000001272 14202767264 017071 0ustar000000000 0000000 (in-package :jss) (defvar *jtypecache* (make-hash-table :test 'eq)) (defun jtypep (object type) (declare (optimize (speed 3) (safety 0))) (let ((class (or (gethash type *jtypecache*) (ignore-errors (setf (gethash type *jtypecache*) (find-java-class type))))) (method (load-time-value (jmethod "java.lang.Class" "isInstance" "java.lang.Object")))) (and class (jcall method class object)))) (defmacro jtypecase (keyform &body cases) "JTYPECASE Keyform {(Type Form*)}* Evaluates the Forms in the first clause for which Type names a class that Keyform isInstance of is true." (sys::case-body 'jtypecase keyform cases t 'jtypep nil nil nil)) abcl-src-1.9.0/contrib/jss/optimize-java-call.lisp0100644 0000000 0000000 00000002763 14202767264 020600 0ustar000000000 0000000 (in-package :jss) (defvar *inhibit-jss-optimization* nil) ;; https://mailman.common-lisp.net/pipermail/armedbear-devel/2016-October/003726.html (precompiler::define-function-position-lambda-transform jss::invoke-restargs (arglist form args) (declare (ignore arglist)) (unless *inhibit-jss-optimization* (precompiler::precompile-function-call `(jss::invoke-restargs-macro ,(second form) ,(car args) (list ,@(cdr args)) ,(fifth form))))) (defmacro invoke-restargs-macro ( method object args &optional (raw? nil)) (assert (eq (car args) 'list)) (setq args (cdr args)) (if (and (consp object) (eq (car object) 'quote)) (let ((object (eval object))) (let* ((object-as-class (or (ignore-errors (let ((*muffle-warnings* t)) (find-java-class object))) `(find-java-class ',object)))) (if raw? `(jstatic-raw ,method ,object-as-class ,@args) `(jstatic ,method ,object-as-class ,@args)))) (let ((objectvar (make-symbol "INVOKE-RESTARGS-ARG1"))) (if raw? `(let ((,objectvar ,object)) (if (symbolp ,objectvar) (jstatic-raw ,method (find-java-class ,objectvar) ,@args) (jcall-raw ,method ,objectvar ,@args))) `(let ((,objectvar ,object)) (if (symbolp ,objectvar) (jstatic ,method (find-java-class ,objectvar) ,@args) (jcall ,method ,objectvar ,@args))))))) abcl-src-1.9.0/contrib/jss/packages.lisp0100644 0000000 0000000 00000001764 14206360343 016655 0ustar000000000 0000000 (defpackage :jss (:nicknames "java-simple-syntax" "java-syntax-sucks") (:use :common-lisp :extensions :java) (:export #:*inhibit-add-to-classpath* #:*added-to-classpath* #:*do-auto-imports* #:*muffle-warnings* #:invoke-restargs #:with-constant-signature #:invoke-add-imports #:find-java-class #:jcmn #:java-class-method-names #:japropos #:new #:jar-import #:classfiles-import ;;; Useful utilities to convert common Java items to Lisp counterparts #:hashmap-to-hashtable #:iterable-to-list #:jlist-to-list #:set-to-list #:vector-to-list #:jarray-to-list #:to-hashset #:j2list #:jmap #:jtypep #:jtypecase ;;; XXX Necessary to work in OSGi? #:get-java-field ; use JAVA:JFIELD #:set-java-field ; use JAVA-JFIELD ;;; deprecated #:list-to-list ;;; Move to JAVA? #:jclass-all-interfaces ;;; Enable compatibility with jss-1.0 by placing symbols in CL-USER #:ensure-compatibility #:*cl-user-compatibility*)) abcl-src-1.9.0/contrib/jss/read-sharp-quote-expression.lisp0100644 0000000 0000000 00000011046 14233147074 022453 0ustar000000000 0000000 (in-package :jss) (defclass sharp-quote-expression-reader (javaparser) ()) (defun read-sharp-java-expression (stream) (read-sharp-quote-expression (with-output-to-string (s) (loop with embedded-string = nil for last = #\space then char for char = (read-char stream) until (and (char= char #\") ;; really end if: we've established embedded string and the peek is a space ;; we're not about to start embedded string. We're about to start embedded string if next character isn't #\). ;; we're not embedded-string and not about to start one (cond ((null (peek-char nil stream nil)) t) ;; eof (embedded-string (system:whitespacep (peek-char nil stream))) ; embedded " needs "" to end ((find last ",(+=" :test 'char=) (setq embedded-string t) nil) (t t))) do (write-char char s))))) (defun read-sharp-quote-expression (string) (multiple-value-bind (bindings de-lisped) (extract-lisp-expressions string) (let ((read (read-java-expression (make-instance 'sharp-quote-expression-reader) de-lisped))) (loop for (var nil) in bindings do (setq read (tree-replace (lambda(e) (if (equalp e (string var)) var e)) read ))) (if bindings `(let ,bindings ,read) read)))) (defun extract-lisp-expressions (string) (let ((bindings nil)) (let ((de-lisped (replace-all string "\\{(.*?)\\}" (lambda(match) (let ((replacevar (find-symbol-not-matching string (mapcar 'car bindings)))) (push (list replacevar (read-from-string match)) bindings) (string replacevar))) 1))) (values bindings de-lisped)))) (defun find-symbol-not-matching (string already) (loop for candidate = (format nil "JSS_~a" (random 10000)) until (and (not (member candidate already :test 'equalp :key 'string)) (not (search string already))) finally (return-from find-symbol-not-matching (intern candidate :jss)))) (defun maybe-class (el) (if (and (symbolp el) (upper-case-p (char (string el) 0)) (not (eql (search "JSS_" (string el)) 0))) `(find-java-class ',el) (if (symbolp el) (intern (string-upcase el)) el))) (def-java-read ObjectCreationExpr sharp-quote-expression-reader () `(new ',(process-node obj (#"getName" (#"getType" node))) ,@(mapcar (lambda(e) (process-node obj e)) (j2list (#"getArguments" node)))) ) (def-java-read MethodCallExpr sharp-quote-expression-reader () (let* ((scope1 (process-node obj (process-node obj (#"getScope" node)))) (how (if (and (symbolp scope1) (not (null scope1)) (upper-case-p (char (string scope1) 0))) 'jstatic 'jcall))) (if (and (symbolp scope1) (not (null scope1)) (upper-case-p (char (string scope1) 0))) (setq scope1 `(find-java-class ',scope1))) `(,how ,(#"getIdentifier" (#"getName" node)) ,(or scope1 'this) ,@(mapcar 'maybe-class (mapcar (lambda(el) (process-node obj el)) (j2list (#"getArguments" node))))) )) (def-java-read FieldAccessExpr sharp-quote-expression-reader () (let ((scope (process-node obj (#"getScope" node)))) (if (and (symbolp scope) (upper-case-p (char (string scope) 0))) `(get-java-field ',(process-node obj (#"getScope" node)) ,(#"getIdentifier" (#"getName" node)) t) `(get-java-field ,(maybe-class (process-node obj (#"getScope" node))) ,(#"getIdentifier" (#"getName" node)) t)))) (def-java-read ArrayAccessExpr sharp-quote-expression-reader () (let ((index (process-node obj (#"getIndex" node)))) (if (symbolp index) (setq index (intern (string-upcase index)))) `(aref ,(process-node obj (#"getName" node)) ,index))) (def-java-read ClassExpr sharp-quote-expression-reader () (let ((name (process-node obj (#"getName" (#"getType" node))))) (if (eql (search "JSS_" (string name) :test 'equalp) 0) name `(find-java-class ',name)))) (def-java-read NameExpr sharp-quote-expression-reader () (process-node obj (#"getName" node))) abcl-src-1.9.0/contrib/jss/t/collections.lisp0100644 0000000 0000000 00000002356 14202767264 017667 0ustar000000000 0000000 (in-package :cl-user) (prove:plan 5) (let ((set (list 2 3 5 7 11))) (prove:is-type (jss:to-hashset set) 'java:java-object "Checking whether JSS:TO-HASHSET produces a Java object…") (let ((result 0)) (jss:jmap (lambda (x) (incf result)) (java:jnew-array "java.lang.Integer" 10)) (prove:is result 10 "Checking JSS:JMAP on Java array of java.lang.Integer…")) (prove:ok (jss:j2list (java:jnew-array "java.lang.Integer" 10)) "Checking JSS:J2LIST on Java array of java.langInteger…") (prove:is (let (list) (jss:jmap (lambda (x) (push x list)) (let ((jarray (java:jnew-array "int" 3))) (jarray-set jarray 1 1) (jarray-set jarray 2 2) jarray)) (nreverse list)) '(0 1 2) "Checking JSS:JMAP on Java array of int…") (prove:is (jss:j2list (let ((jarray (java:jnew-array "int" 3))) (jarray-set jarray 1 1) (jarray-set jarray 2 2) jarray)) '(0 1 2) "Checking JSS:J2LIST on Java array of int…")) (prove:finalize) abcl-src-1.9.0/contrib/jss/t/javaparser.lisp0100644 0000000 0000000 00000002400 14223403213 017455 0ustar000000000 0000000 (in-package :cl-user) (defparameter expanded '(let ((jss::this jss::*object-for-this*)) (declare (ignorable jss::this)) (jcall "getLoaded" (jcall "load" (jcall "make" (jcall "intercept" (jcall "method" (jcall "subclass" (new '|ByteBuddy|) (find-java-class '|Object|) t) (jstatic "named" (find-java-class '|ElementMatchers|) "toString")) (jstatic "value" (find-java-class '|FixedValue|) "Hello World!"))) (jcall "getClassLoader" (jcall "getClass" jss::this)))))) (defparameter source '#1"new ByteBuddy().subclass(Object.class,t) .method(ElementMatchers.named("toString")) .intercept(FixedValue.value("Hello World!")) .make() .load(getClass().getClassLoader()) .getLoaded()" ) (prove:plan 1) (prove:is source expanded) (prove:finalize) abcl-src-1.9.0/contrib/jss/t/jss-tests.lisp0100644 0000000 0000000 00000005056 14202767264 017310 0ustar000000000 0000000 (in-package :cl-user) (prove:plan 8) (prove:is (read-from-string "#\"{bar}.{foo}\"") '(jss:get-java-field bar foo t)) (prove:is (read-from-string "#\"q.bar.{foo}\"") '(jss:get-java-field (load-time-value (jss:find-java-class "q.bar")) foo t)) (prove:is (read-from-string "#\"{bar}.foo\"") '(jss:get-java-field bar "foo" t)) (prove:is-error (read-from-string "#\".bar.foo\"") 'simple-error) ;;; http://abcl.org/trac/ticket/205 (prove:is (jss:with-constant-signature ((substring "substring")) (substring "01234" 2)) "234") ;;; http://abcl.org/trac/ticket/229 - note: version of test for this ticket was broken in tests.lisp (prove:is (#"toString" (find "size" (#"getMethods" (jss:find-java-class "java.util.Collections$UnmodifiableMap")) :test 'string-equal :key #"getName")) (#"toString" (java::jmethod "java.util.Collections$UnmodifiableMap" "size" ))) (prove:is (jss::with-class-lookup-disambiguated (lang.object) (jss:find-java-class 'object)) (jss:find-java-class 'java.lang.object)) ;; Object is ambiguous in default java (prove:is-error (jss:find-java-class 'object) 'simple-error) ;; test that optimized jss is much faster than unoptimized (let () (defun optimized-jss (count) (loop repeat count do (#"compile" 'regex.Pattern ".*"))) (let ((jss::*inhibit-jss-optimization* t)) (defun unoptimized-jss (count) (loop repeat count do (#"compile" 'regex.Pattern ".*")))) (defun just-loop (count) (loop repeat count)) (let ((jss::*inhibit-jss-optimization* nil)) (compile 'just-loop) (compile 'optimized-jss)) (let ((jss::*inhibit-jss-optimization* t)) (compile 'unoptimized-jss)) (defmacro timeit (&body body) `(let ((start (#"currentTimeMillis" 'system))) ,@body (- (#"currentTimeMillis" 'system) start))) (prove:plan 1) (prove:is-type (let ((just-loop (timeit (just-loop 10000)))) (+ 0.0 (/ (- (timeit (optimized-jss 10000)) just-loop) (- (timeit (unoptimized-jss 10000)) just-loop)))) '(float 0 0.1) "Testing JSS compiler optimization…")) (prove:plan 2) (let* ((jss::*inhibit-jss-optimization* nil) (optimized-jss (macroexpand (precompiler::precompile-form '(#"compile" 'regex.Pattern ".*") t)))) (let* ((jss::*inhibit-jss-optimization* t) (unoptimized-jss (macroexpand (precompiler::precompile-form '(#"compile" 'regex.Pattern ".*") t)))) (prove:is (car optimized-jss) 'java:jstatic) (prove:is (caar unoptimized-jss) 'lambda))) (prove:finalize) abcl-src-1.9.0/contrib/jss/transform-to-field.lisp0100644 0000000 0000000 00000011440 14202767264 020614 0ustar000000000 0000000 (in-package :jss) ;; JSS syntax for fields ;; #"[]." ;; ;; is empty or "==". scope is only paid attention to when is a literal string ;; ;; is either {} or a class name or abbreviation that find-java-class can use ;; If is a lisp expression, then it is evaluated (in the lexical environment) and used as an instance ;; when is "==" you promise that instance will always be of the same class, and so field lookup ;; is done once and cached. ;; If is a class name the result of find-java-class is used and a static field access is done. ;; when is "==" you promise the static field is final and so the result is wrapped in (load-time-value ...) ;; ;; is either { is a lisp expression it should evaluate to a string that names a field ;; If is a string (no quotes) it is used as the field name ;; ;; eg. #"foo.bar.baz" -> (get-java-field (find-java-class 'foo.bar) "baz" t) ;; #"{foo}.baz" -> (get-java-field (find-java-class foo) "baz" t) ;; #"==foo.baz" -> (load-time-value (get-java-field (find-java-class "foo") "bar" t)) ;; #"=={foo}.baz" -> TL;DR (only look up baz field once based on class of foo, and cache) (defun jss-transform-to-field (string sharp-arg) (let* ((pattern (#"compile" 'java.util.regex.Pattern "((==){0,1})(.*)\\.([^.]+)$")) (matcher (#"matcher" pattern string))) (#"find" matcher) (let ((parts (list (#"group" matcher 3) (#"group" matcher 4))) (scope (#"group" matcher 1))) (check-class-or-eval (first parts)) (check-field-or-eval (second parts)) (apply 'field-access-expression sharp-arg scope parts )))) ;; http://stackoverflow.com/questions/5205339/regular-expression-matching-fully-qualified-class-names (defun check-class-or-eval (string) (assert (or (#"matches" string "^((\\p{javaJavaIdentifierStart}(\\p{javaJavaIdentifierPart})*)+)(\\.\\p{javaJavaIdentifierStart}(\\p{javaJavaIdentifierPart})*)*$") (#"matches" string "^\\{.+}$")) (string) "inside #\"..\" expected either an abbreviated class name or an expression surrounded by {}. Found: #~s" string)) (defun check-field-or-eval (string) (assert (or (#"matches" string "^(\\p{javaJavaIdentifierStart}(\\p{javaJavaIdentifierPart})*)+$") (#"matches" string "^\\{.+\\}$")) (string) "inside #\"..\" expected either a field name or an expression surrounded by {}. Found: #~s" string)) (defun field-access-expression (sharp-arg scope thing field ) (if (and (not (char= (char thing 0) #\{)) (not (char= (char field 0) #\{))) (static-field-ref-transform thing field sharp-arg scope) (if (and (equal scope "==") (char= (char thing 0) #\{) (not (char= (char field 0) #\{))) (always-same-signature-field-ref-transform sharp-arg thing field) `(get-java-field ,(if (char= (char thing 0) #\{) (read-from-string (subseq thing 1 (- (length thing) 1))) `(load-time-value (find-java-class ,thing))) ,(if (char= (char field 0) #\{) (read-from-string (subseq field 1 (- (length field) 1))) field) t)))) ;; If a class name and explicit field name we can look everything up at load time (defun static-field-ref-transform (class field sharp-arg scope) (if (equal scope "==") `(load-time-value (get-java-field (find-java-class ,class) ,field t)) `(,(if (eql sharp-arg 0) 'jcall-raw 'jcall) (load-time-value (jmethod "java.lang.reflect.Field" "get" "java.lang.Object")) (load-time-value (let ((jfield (find-declared-field ,field (find-java-class ,class)))) (#"setAccessible" jfield t) jfield)) (load-time-value (find-java-class ',class))))) ;; 1 case: =={var}.foo ;; Globally cache the field accessor for the first value of {var}. Subsequent calls ignore the class of var. (defun always-same-signature-field-ref-transform (sharp-arg object field) (let ((cached (make-symbol (format nil "CACHED-FIELD-field"))) (object (intern (string-upcase (subseq object 1 (- (length object) 1)))))) `(,(if (eql sharp-arg 0) 'jcall-raw 'jcall) (load-time-value (jmethod "java.lang.reflect.Field" "get" "java.lang.Object")) (locally (declare (special ,cached)) (if (boundp ',cached) ,cached (progn (setq ,cached (find-declared-field ,field (jcall (load-time-value (jmethod "java.lang.Object" "getClass")) ,object))) (jcall (load-time-value (jmethod "java.lang.reflect.Field" "setAccessible" "boolean")) ,cached t) ,cached))) ,object))) abcl-src-1.9.0/contrib/jss/util.lisp0100644 0000000 0000000 00000002165 14202767264 016061 0ustar000000000 0000000 (in-package :jss) (defun tree-replace (replace-fn tree) "create new tree replacing each element with the result of calling replace-fn on it" (labels ((tr-internal (tree) (cond ((atom tree) (funcall replace-fn tree)) (t (let ((replacement (funcall replace-fn tree))) (if (eq replacement tree) (mapcar #'tr-internal tree) replacement)))))) (tr-internal tree))) (defun replace-all (string regex function &rest which) (let ((matcher (#"matcher" (if (java-object-p regex) regex (#"compile" 'java.util.regex.pattern regex)) string)) (sb (new 'stringbuffer))) (with-constant-signature ((append "appendReplacement")) (loop for found = (#"find" matcher) while found do (#"appendReplacement" matcher sb (apply function (loop for g in which collect (#"group" matcher g))))) ) (#"appendTail" matcher sb) (#"toString" sb))) abcl-src-1.9.0/contrib/mvn/jna-asdf.lisp0100644 0000000 0000000 00000000370 14202767264 016564 0ustar000000000 0000000 (in-package :cl-user) (defpackage jna (:nicknames :jna) (:use :cl)) (in-package :jna) (defmethod asdf:perform :after ((o asdf:load-op) (c (eql (asdf:find-system :jna)))) (when (jss:find-java-class "com.sun.jna.Native") (provide :jna))) abcl-src-1.9.0/contrib/mvn/jna.asd0100644 0000000 0000000 00000000707 14242627550 015452 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- ;;;; Need to have jna.jar present for CFFI to work. (defsystem jna :long-description "" :version "5.9.0" :defsystem-depends-on (jss abcl-asdf) :components ((:mvn "net.java.dev.jna/jna/5.9.0" :alternate-uri "https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.9.0/jna-5.9.0.jar" :classname "com.sun.jna.Native"))) abcl-src-1.9.0/contrib/mvn/log4j.asd0100644 0000000 0000000 00000000257 14202767264 015724 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem log4j :defsystem-depends-on (abcl-asdf) :components ((:module log4j.jar :components ((:mvn "log4j/log4j"))))) abcl-src-1.9.0/contrib/named-readtables/LICENSE0100644 0000000 0000000 00000003252 14202767264 017607 0ustar000000000 0000000 Copyright (c) 2007 - 2009 Tobias C. Rittweiler Copyright (c) 2007, Robert P. Goldman and SIFT, LLC All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the names of Tobias C. Rittweiler, Robert P. Goldman, SIFT, LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Tobias C. Rittweiler, Robert P. Goldman and SIFT, LLC ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tobias C. Rittweiler, Robert P. Goldman or SIFT, LLC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. abcl-src-1.9.0/contrib/named-readtables/README0100644 0000000 0000000 00000030000 14202767264 017451 0ustar000000000 0000000 # Named Readtables Manual ###### \[in package EDITOR-HINTS.NAMED-READTABLES\] ## named-readtables ASDF System Details - Version: 0.9 - Description: Library that creates a namespace for named readtable akin to the namespace of packages. - Licence: BSD, see LICENSE - Author: Tobias C. Rittweiler - Maintainer: Gábor Melis - Mailto: [mega@retes.hu](mailto:mega@retes.hu) ## Introduction Named-Readtables is a library that provides a namespace for readtables akin to the already-existing namespace of packages. In particular: - you can associate readtables with names, and retrieve readtables by names; - you can associate source files with readtable names, and be sure that the right readtable is active when compiling/loading the file; - similiarly, your development environment now has a chance to automatically determine what readtable should be active while processing source forms on interactive commands. (E.g. think of `C-c C-c` in Slime (yet to be done)) It follows that Named-Readtables is a facility for using readtables in a localized way. Additionally, it also attempts to become a facility for using readtables in a *modular* way. In particular: - it provides a macro to specify the content of a readtable at a glance; - it makes it possible to use multiple inheritance between readtables. ### Links Here is the [official repository][named-readtables-repo] and the [HTML documentation][named-readtables-doc] for the latest version. [named-readtables-repo]: https://github.com/melisgl/named-readtables [named-readtables-doc]: http://melisgl.github.io/mgl-pax-world/named-readtables-manual.html ### Acknowledgements Thanks to Robert Goldman for making me want to write this library. Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart Botta, David Crawford, and Pascal Costanza for being early adopters, providing comments and bugfixes. ## Overview ### Notes on the API The API heavily imitates the API of packages. This has the nice property that any experienced Common Lisper will take it up without effort. DEFREADTABLE - DEFPACKAGE IN-READTABLE - IN-PACKAGE MERGE-READTABLES-INTO - USE-PACKAGE MAKE-READTABLE - MAKE-PACKAGE UNREGISTER-READTABLE - DELETE-PACKAGE RENAME-READTABLE - RENAME-PACKAGE FIND-READTABLE - FIND-PACKAGE READTABLE-NAME - PACKAGE-NAME LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES ### Important API idiosyncrasies There are three major differences between the API of Named-Readtables, and the API of packages. 1. Readtable names are symbols not strings. Time has shown that the fact that packages are named by strings causes severe headache because of the potential of package names colliding with each other. Hence, readtables are named by symbols lest to make the situation worse than it already is. Consequently, readtables named `CL-ORACLE:SQL-SYNTAX` and `CL-MYSQL:SQL-SYNTAX` can happily coexist next to each other. Or, taken to an extreme, `SCHEME:SYNTAX` and `ELISP:SYNTAX`. If, for example to duly signify the importance of your cool readtable hack, you really think it deserves a global name, you can always resort to keywords. 2. The inheritance is resolved statically, not dynamically. A package that uses another package will have access to all the other package's exported symbols, even to those that will be added after its definition. I.e. the inheritance is resolved at run-time, that is dynamically. Unfortunately, we cannot do the same for readtables in a portable manner. Therefore, we do not talk about "using" another readtable but about "merging" the other readtable's definition into the readtable we are going to define. I.e. the inheritance is resolved once at definition time, that is statically. (Such merging can more or less be implemented portably albeit at a certain cost. Most of the time, this cost manifests itself at the time a readtable is defined, i.e. once at compile-time, so it may not bother you. Nonetheless, we provide extra support for Sbcl, ClozureCL, and AllegroCL at the moment. Patches for your implementation of choice are welcome, of course.) 3. DEFREADTABLE does not have compile-time effects. If you define a package via DEFPACKAGE, you can make that package the currently active package for the subsequent compilation of the same file via IN-PACKAGE. The same is, however, not true for DEFREADTABLE and IN-READTABLE for the following reason: It's unlikely that the need for special reader-macros arises for a problem which can be solved in just one file. Most often, you're going to define the reader macro functions, and set up the corresponding readtable in an extra file. If DEFREADTABLE had compile-time effects, you'd have to wrap each definition of a reader-macro function in an EVAL-WHEN to make its definition available at compile-time. Because that's simply not the common case, DEFREADTABLE does not have a compile-time effect. If you want to use a readtable within the same file as its definition, wrap the DEFREADTABLE and the reader-macro function definitions in an explicit EVAL-WHEN. ### Preregistered Readtables - NIL, :STANDARD, and :COMMON-LISP designate the *standard readtable*. - :MODERN designates a *case-preserving* *standard-readtable*. - :CURRENT designates the *current readtable*. ### Examples ```commonlisp (defreadtable elisp:syntax (:merge :standard) (:macro-char #\? #'elisp::read-character-literal t) (:macro-char #\[ #'elisp::read-vector-literal t) ... (:case :preserve)) (defreadtable scheme:syntax (:merge :standard) (:macro-char #\[ #'(lambda (stream char) (read-delimited-list #\] stream))) (:macro-char #\# :dispatch) (:dispatch-macro-char #\# #\t #'scheme::read-#t) (:dispatch-macro-char #\# #\f #'scheme::read-#f) ... (:case :preserve)) (in-readtable elisp:syntax) ... (in-readtable scheme:syntax) ... ``` ## Reference - [macro] DEFREADTABLE NAME &BODY OPTIONS Define a new named readtable, whose name is given by the symbol NAME. Or, if a readtable is already registered under that name, redefine that one. The readtable can be populated using the following OPTIONS: - `(:MERGE READTABLE-DESIGNATORS+)` Merge the readtables designated into the new readtable being defined as per MERGE-READTABLES-INTO. If no :MERGE clause is given, an empty readtable is used. See MAKE-READTABLE. - `(:FUSE READTABLE-DESIGNATORS+)` Like :MERGE except: Error conditions of type READER-MACRO-CONFLICT that are signaled during the merge operation will be silently *continued*. It follows that reader macros in earlier entries will be overwritten by later ones. For backward compatibility, :FUZE is accepted as an alias of :FUSE. - `(:DISPATCH-MACRO-CHAR MACRO-CHAR SUB-CHAR FUNCTION)` Define a new sub character `SUB-CHAR` for the dispatching macro character `MACRO-CHAR`, per SET-DISPATCH-MACRO-CHARACTER. You probably have to define `MACRO-CHAR` as a dispatching macro character by the following option first. - `(:MACRO-CHAR MACRO-CHAR FUNCTION [NON-TERMINATING-P])` Define a new macro character in the readtable, per SET-MACRO-CHARACTER. If `FUNCTION` is the keyword :DISPATCH, `MACRO-CHAR` is made a dispatching macro character, per MAKE-DISPATCH-MACRO-CHARACTER. - `(:SYNTAX-FROM FROM-READTABLE-DESIGNATOR FROM-CHAR TO-CHAR)` Set the character syntax of TO-CHAR in the readtable being defined to the same syntax as FROM-CHAR as per SET-SYNTAX-FROM-CHAR. - `(:CASE CASE-MODE)` Defines the *case sensitivity mode* of the resulting readtable. Any number of option clauses may appear. The options are grouped by their type, but in each group the order the options appeared textually is preserved. The following groups exist and are executed in the following order: :MERGE and :FUSE (one group), :CASE, :MACRO-CHAR and :DISPATCH-MACRO-CHAR (one group), finally :SYNTAX-FROM. Notes: The readtable is defined at load-time. If you want to have it available at compilation time -- say to use its reader-macros in the same file as its definition -- you have to wrap the DEFREADTABLE form in an explicit EVAL-WHEN. On redefinition, the target readtable is made empty first before it's refilled according to the clauses. NIL, :STANDARD, :COMMON-LISP, :MODERN, and :CURRENT are preregistered readtable names. - [macro] IN-READTABLE NAME Set *READTABLE* to the readtable referred to by the symbol NAME. - [function] MAKE-READTABLE &OPTIONAL (NAME NIL NAME-SUPPLIED-P) &KEY MERGE Creates and returns a new readtable under the specified NAME. MERGE takes a list of NAMED-READTABLE-DESIGNATORS and specifies the readtables the new readtable is created from. (See the :MERGE clause of DEFREADTABLE for details.) If MERGE is NIL, an empty readtable is used instead. If NAME is not given, an anonymous empty readtable is returned. Notes: An empty readtable is a readtable where each character's syntax is the same as in the *standard readtable* except that each macro character has been made a constituent. Basically: whitespace stays whitespace, everything else is constituent. - [function] MERGE-READTABLES-INTO RESULT-READTABLE &REST NAMED-READTABLES Copy the contents of each readtable in NAMED-READTABLES into RESULT-READTABLE. If a macro character appears in more than one of the readtables, i.e. if a conflict is discovered during the merge, an error of type READER-MACRO-CONFLICT is signaled. - [function] FIND-READTABLE NAME Looks for the readtable specified by NAME and returns it if it is found. Returns NIL otherwise. - [function] ENSURE-READTABLE NAME &OPTIONAL (DEFAULT NIL DEFAULT-P) Looks up the readtable specified by NAME and returns it if it's found. If it is not found, it registers the readtable designated by DEFAULT under the name represented by NAME; or if no default argument is given, it signals an error of type READTABLE-DOES-NOT-EXIST instead. - [function] RENAME-READTABLE OLD-NAME NEW-NAME Replaces the associated name of the readtable designated by OLD-NAME with NEW-NAME. If a readtable is already registered under NEW-NAME, an error of type READTABLE-DOES-ALREADY-EXIST is signaled. - [function] READTABLE-NAME NAMED-READTABLE Returns the name of the readtable designated by NAMED-READTABLE, or NIL. - [function] REGISTER-READTABLE NAME READTABLE Associate READTABLE with NAME. Returns the readtable. - [function] UNREGISTER-READTABLE NAMED-READTABLE Remove the association of NAMED-READTABLE. Returns T if successfull, NIL otherwise. - [function] COPY-NAMED-READTABLE NAMED-READTABLE Like COPY-READTABLE but takes a NAMED-READTABLE-DESIGNATOR as argument. - [function] LIST-ALL-NAMED-READTABLES Returns a list of all registered readtables. The returned list is guaranteed to be fresh, but may contain duplicates. - [type] NAMED-READTABLE-DESIGNATOR Either a symbol or a readtable itself. - [condition] READER-MACRO-CONFLICT READTABLE-ERROR Continuable. This condition is signaled during the merge process if a reader macro (be it a macro character or the sub character of a dispatch macro character) is present in the both source and the target readtable and the two respective reader macro functions differ. - [condition] READTABLE-DOES-ALREADY-EXIST READTABLE-ERROR Continuable. - [condition] READTABLE-DOES-NOT-EXIST READTABLE-ERROR * * * ###### \[generated by [MGL-PAX](https://github.com/melisgl/mgl-pax)\] abcl-src-1.9.0/contrib/named-readtables/README.md0100644 0000000 0000000 00000044312 14202767264 020063 0ustar000000000 0000000 # Named Readtables Manual ## Table of Contents - [1 named-readtables ASDF System Details][9b5b] - [2 Introduction][6faf] - [2.1 Links][8688] - [2.2 Acknowledgements][059d] - [3 Overview][0bc2] - [3.1 Notes on the API][e4cd] - [3.2 Important API idiosyncrasies][62b8] - [3.3 Preregistered Readtables][58c6] - [3.4 Examples][cf94] - [4 Reference][373d] ###### \[in package EDITOR-HINTS.NAMED-READTABLES\] ## 1 named-readtables ASDF System Details - Version: 0.9 - Description: Library that creates a namespace for named readtable akin to the namespace of packages. - Licence: BSD, see LICENSE - Author: Tobias C. Rittweiler - Maintainer: Gábor Melis - Mailto: [mega@retes.hu](mailto:mega@retes.hu) ## 2 Introduction Named-Readtables is a library that provides a namespace for readtables akin to the already-existing namespace of packages. In particular: - you can associate readtables with names, and retrieve readtables by names; - you can associate source files with readtable names, and be sure that the right readtable is active when compiling/loading the file; - similiarly, your development environment now has a chance to automatically determine what readtable should be active while processing source forms on interactive commands. (E.g. think of `C-c C-c` in Slime (yet to be done)) It follows that Named-Readtables is a facility for using readtables in a localized way. Additionally, it also attempts to become a facility for using readtables in a *modular* way. In particular: - it provides a macro to specify the content of a readtable at a glance; - it makes it possible to use multiple inheritance between readtables. ### 2.1 Links Here is the [official repository][named-readtables-repo] and the [HTML documentation][named-readtables-doc] for the latest version. [named-readtables-repo]: https://github.com/melisgl/named-readtables [named-readtables-doc]: http://melisgl.github.io/mgl-pax-world/named-readtables-manual.html ### 2.2 Acknowledgements Thanks to Robert Goldman for making me want to write this library. Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart Botta, David Crawford, and Pascal Costanza for being early adopters, providing comments and bugfixes. ## 3 Overview ### 3.1 Notes on the API The API heavily imitates the API of packages. This has the nice property that any experienced Common Lisper will take it up without effort. DEFREADTABLE - DEFPACKAGE IN-READTABLE - IN-PACKAGE MERGE-READTABLES-INTO - USE-PACKAGE MAKE-READTABLE - MAKE-PACKAGE UNREGISTER-READTABLE - DELETE-PACKAGE RENAME-READTABLE - RENAME-PACKAGE FIND-READTABLE - FIND-PACKAGE READTABLE-NAME - PACKAGE-NAME LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES ### 3.2 Important API idiosyncrasies There are three major differences between the API of Named-Readtables, and the API of packages. 1. Readtable names are symbols not strings. Time has shown that the fact that packages are named by strings causes severe headache because of the potential of package names colliding with each other. Hence, readtables are named by symbols lest to make the situation worse than it already is. Consequently, readtables named `CL-ORACLE:SQL-SYNTAX` and `CL-MYSQL:SQL-SYNTAX` can happily coexist next to each other. Or, taken to an extreme, `SCHEME:SYNTAX` and `ELISP:SYNTAX`. If, for example to duly signify the importance of your cool readtable hack, you really think it deserves a global name, you can always resort to keywords. 2. The inheritance is resolved statically, not dynamically. A package that uses another package will have access to all the other package's exported symbols, even to those that will be added after its definition. I.e. the inheritance is resolved at run-time, that is dynamically. Unfortunately, we cannot do the same for readtables in a portable manner. Therefore, we do not talk about "using" another readtable but about "merging" the other readtable's definition into the readtable we are going to define. I.e. the inheritance is resolved once at definition time, that is statically. (Such merging can more or less be implemented portably albeit at a certain cost. Most of the time, this cost manifests itself at the time a readtable is defined, i.e. once at compile-time, so it may not bother you. Nonetheless, we provide extra support for Sbcl, ClozureCL, and AllegroCL at the moment. Patches for your implementation of choice are welcome, of course.) 3. [`DEFREADTABLE`][8b94] does not have compile-time effects. If you define a package via `DEFPACKAGE`, you can make that package the currently active package for the subsequent compilation of the same file via `IN-PACKAGE`. The same is, however, not true for [`DEFREADTABLE`][8b94] and [`IN-READTABLE`][de3b] for the following reason: It's unlikely that the need for special reader-macros arises for a problem which can be solved in just one file. Most often, you're going to define the reader macro functions, and set up the corresponding readtable in an extra file. If [`DEFREADTABLE`][8b94] had compile-time effects, you'd have to wrap each definition of a reader-macro function in an `EVAL-WHEN` to make its definition available at compile-time. Because that's simply not the common case, [`DEFREADTABLE`][8b94] does not have a compile-time effect. If you want to use a readtable within the same file as its definition, wrap the [`DEFREADTABLE`][8b94] and the reader-macro function definitions in an explicit `EVAL-WHEN`. ### 3.3 Preregistered Readtables - `NIL`, `:STANDARD`, and `:COMMON-LISP` designate the *standard readtable*. - `:MODERN` designates a *case-preserving* *standard-readtable*. - `:CURRENT` designates the *current readtable*. ### 3.4 Examples ```commonlisp (defreadtable elisp:syntax (:merge :standard) (:macro-char #\? #'elisp::read-character-literal t) (:macro-char #\[ #'elisp::read-vector-literal t) ... (:case :preserve)) (defreadtable scheme:syntax (:merge :standard) (:macro-char #\[ #'(lambda (stream char) (read-delimited-list #\] stream))) (:macro-char #\# :dispatch) (:dispatch-macro-char #\# #\t #'scheme::read-#t) (:dispatch-macro-char #\# #\f #'scheme::read-#f) ... (:case :preserve)) (in-readtable elisp:syntax) ... (in-readtable scheme:syntax) ... ``` ## 4 Reference - [macro] **DEFREADTABLE** *NAME &BODY OPTIONS* Define a new named readtable, whose name is given by the symbol `NAME`. Or, if a readtable is already registered under that name, redefine that one. The readtable can be populated using the following `OPTIONS`: - `(:MERGE READTABLE-DESIGNATORS+)` Merge the readtables designated into the new readtable being defined as per [`MERGE-READTABLES-INTO`][77fa]. If no `:MERGE` clause is given, an empty readtable is used. See [`MAKE-READTABLE`][958e]. - `(:FUSE READTABLE-DESIGNATORS+)` Like `:MERGE` except: Error conditions of type [`READER-MACRO-CONFLICT`][acb7] that are signaled during the merge operation will be silently *continued*. It follows that reader macros in earlier entries will be overwritten by later ones. For backward compatibility, `:FUZE` is accepted as an alias of `:FUSE`. - `(:DISPATCH-MACRO-CHAR MACRO-CHAR SUB-CHAR FUNCTION)` Define a new sub character `SUB-CHAR` for the dispatching macro character `MACRO-CHAR`, per `SET-DISPATCH-MACRO-CHARACTER`. You probably have to define `MACRO-CHAR` as a dispatching macro character by the following option first. - `(:MACRO-CHAR MACRO-CHAR FUNCTION [NON-TERMINATING-P])` Define a new macro character in the readtable, per `SET-MACRO-CHARACTER`. If `FUNCTION` is the keyword `:DISPATCH`, `MACRO-CHAR` is made a dispatching macro character, per `MAKE-DISPATCH-MACRO-CHARACTER`. - `(:SYNTAX-FROM FROM-READTABLE-DESIGNATOR FROM-CHAR TO-CHAR)` Set the character syntax of `TO-CHAR` in the readtable being defined to the same syntax as `FROM-CHAR` as per `SET-SYNTAX-FROM-CHAR`. - `(:CASE CASE-MODE)` Defines the *case sensitivity mode* of the resulting readtable. Any number of option clauses may appear. The options are grouped by their type, but in each group the order the options appeared textually is preserved. The following groups exist and are executed in the following order: `:MERGE` and `:FUSE` (one group), `:CASE`, `:MACRO-CHAR` and `:DISPATCH-MACRO-CHAR` (one group), finally `:SYNTAX-FROM`. Notes: The readtable is defined at load-time. If you want to have it available at compilation time -- say to use its reader-macros in the same file as its definition -- you have to wrap the [`DEFREADTABLE`][8b94] form in an explicit `EVAL-WHEN`. On redefinition, the target readtable is made empty first before it's refilled according to the clauses. `NIL`, `:STANDARD`, `:COMMON-LISP`, `:MODERN`, and `:CURRENT` are preregistered readtable names. - [macro] **IN-READTABLE** *NAME* Set `*READTABLE*` to the readtable referred to by the symbol `NAME`. - [function] **MAKE-READTABLE** *&OPTIONAL (NAME NIL NAME-SUPPLIED-P) &KEY MERGE* Creates and returns a new readtable under the specified `NAME`. `MERGE` takes a list of NAMED-READTABLE-DESIGNATORS and specifies the readtables the new readtable is created from. (See the `:MERGE` clause of [`DEFREADTABLE`][8b94] for details.) If `MERGE` is `NIL`, an empty readtable is used instead. If `NAME` is not given, an anonymous empty readtable is returned. Notes: An empty readtable is a readtable where each character's syntax is the same as in the *standard readtable* except that each macro character has been made a constituent. Basically: whitespace stays whitespace, everything else is constituent. - [function] **MERGE-READTABLES-INTO** *RESULT-READTABLE &REST NAMED-READTABLES* Copy the contents of each readtable in `NAMED-READTABLES`([`0`][] [`1`][9b5b]) into `RESULT-READTABLE`. If a macro character appears in more than one of the readtables, i.e. if a conflict is discovered during the merge, an error of type [`READER-MACRO-CONFLICT`][acb7] is signaled. - [function] **FIND-READTABLE** *NAME* Looks for the readtable specified by `NAME` and returns it if it is found. Returns `NIL` otherwise. - [function] **ENSURE-READTABLE** *NAME &OPTIONAL (DEFAULT NIL DEFAULT-P)* Looks up the readtable specified by `NAME` and returns it if it's found. If it is not found, it registers the readtable designated by `DEFAULT` under the name represented by NAME; or if no default argument is given, it signals an error of type [`READTABLE-DOES-NOT-EXIST`][437a] instead. - [function] **RENAME-READTABLE** *OLD-NAME NEW-NAME* Replaces the associated name of the readtable designated by `OLD-NAME` with `NEW-NAME`. If a readtable is already registered under `NEW-NAME`, an error of type [`READTABLE-DOES-ALREADY-EXIST`][4b51] is signaled. - [function] **READTABLE-NAME** *NAMED-READTABLE* Returns the name of the readtable designated by `NAMED-READTABLE`, or `NIL`. - [function] **REGISTER-READTABLE** *NAME READTABLE* Associate `READTABLE` with `NAME`. Returns the readtable. - [function] **UNREGISTER-READTABLE** *NAMED-READTABLE* Remove the association of `NAMED-READTABLE`. Returns `T` if successfull, `NIL` otherwise. - [function] **COPY-NAMED-READTABLE** *NAMED-READTABLE* Like `COPY-READTABLE` but takes a [`NAMED-READTABLE-DESIGNATOR`][fa0c] as argument. - [function] **LIST-ALL-NAMED-READTABLES** Returns a list of all registered readtables. The returned list is guaranteed to be fresh, but may contain duplicates. - [type] **NAMED-READTABLE-DESIGNATOR** Either a symbol or a readtable itself. - [condition] **READER-MACRO-CONFLICT** *READTABLE-ERROR* Continuable. This condition is signaled during the merge process if a reader macro (be it a macro character or the sub character of a dispatch macro character) is present in the both source and the target readtable and the two respective reader macro functions differ. - [condition] **READTABLE-DOES-ALREADY-EXIST** *READTABLE-ERROR* Continuable. - [condition] **READTABLE-DOES-NOT-EXIST** *READTABLE-ERROR* [059d]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-ACKNOWLEDGEMENTS-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-ACKNOWLEDGEMENTS MGL-PAX:SECTION)" [0bc2]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-OVERVIEW-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-OVERVIEW MGL-PAX:SECTION)" [373d]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-REFERENCE-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-REFERENCE MGL-PAX:SECTION)" [437a]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AREADTABLE-DOES-NOT-EXIST-20CONDITION-29 "(EDITOR-HINTS.NAMED-READTABLES:READTABLE-DOES-NOT-EXIST CONDITION)" [4b51]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AREADTABLE-DOES-ALREADY-EXIST-20CONDITION-29 "(EDITOR-HINTS.NAMED-READTABLES:READTABLE-DOES-ALREADY-EXIST CONDITION)" [58c6]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-PREREGISTERED-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-PREREGISTERED MGL-PAX:SECTION)" [62b8]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-API-IDIOSYNCRASIES-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-API-IDIOSYNCRASIES MGL-PAX:SECTION)" [6faf]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-INTRODUCTION-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-INTRODUCTION MGL-PAX:SECTION)" [77fa]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AMERGE-READTABLES-INTO-20FUNCTION-29 "(EDITOR-HINTS.NAMED-READTABLES:MERGE-READTABLES-INTO FUNCTION)" [8688]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-LINKS-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-LINKS MGL-PAX:SECTION)" [8b94]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3ADEFREADTABLE-20-28MGL-PAX-3AMACRO-29-29 "(EDITOR-HINTS.NAMED-READTABLES:DEFREADTABLE (MGL-PAX:MACRO))" [958e]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AMAKE-READTABLE-20FUNCTION-29 "(EDITOR-HINTS.NAMED-READTABLES:MAKE-READTABLE FUNCTION)" [9b5b]: #x-28-22named-readtables-22-20ASDF-2FSYSTEM-3ASYSTEM-29 "(\"named-readtables\" ASDF/SYSTEM:SYSTEM)" [acb7]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AREADER-MACRO-CONFLICT-20CONDITION-29 "(EDITOR-HINTS.NAMED-READTABLES:READER-MACRO-CONFLICT CONDITION)" [cf94]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-EXAMPLES-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-EXAMPLES MGL-PAX:SECTION)" [de3b]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AIN-READTABLE-20-28MGL-PAX-3AMACRO-29-29 "(EDITOR-HINTS.NAMED-READTABLES:IN-READTABLE (MGL-PAX:MACRO))" [e4cd]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-API-NOTES-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-API-NOTES MGL-PAX:SECTION)" [fa0c]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3ANAMED-READTABLE-DESIGNATOR-20-28TYPE-29-29 "(EDITOR-HINTS.NAMED-READTABLES:NAMED-READTABLE-DESIGNATOR (TYPE))" * * * ###### \[generated by [MGL-PAX](https://github.com/melisgl/mgl-pax)\] abcl-src-1.9.0/contrib/named-readtables/doc/named-readtables.html0100644 0000000 0000000 00000105067 14202767264 023434 0ustar000000000 0000000 EDITOR-HINTS.NAMED-READTABLES - 0.9

EDITOR-HINTS.NAMED-READTABLES - 0.9

     by Tobias C Rittweiler
Repository:
 
     darcs get http://common-lisp.net/project/editor-hints/darcs/named-readtables/
 
Download:
 
     editor-hints.named-readtables-0.9.tar.gz
 

Contents

  1. What are Named-Readtables?
  2. Notes on the API
  3. Important API idiosyncrasies
  4. Preregistered Readtables
  5. Examples
  6. Acknowledgements
  7. Dictionary
    1. COPY-NAMED-READTABLE
    2. DEFREADTABLE
    3. ENSURE-READTABLE
    4. FIND-READTABLE
    5. IN-READTABLE
    6. LIST-ALL-NAMED-READTABLES
    7. MAKE-READTABLE
    8. MERGE-READTABLES-INTO
    9. NAMED-READTABLE-DESIGNATOR
    10. READER-MACRO-CONFLICT
    11. READTABLE-DOES-ALREADY-EXIST
    12. READTABLE-DOES-NOT-EXIST
    13. READTABLE-NAME
    14. REGISTER-READTABLE
    15. RENAME-READTABLE
    16. UNREGISTER-READTABLE

 

What are Named-Readtables?

    Named-Readtables is a library that provides a namespace for readtables akin to the
    already-existing namespace of packages. In particular:
             
  • you can associate readtables with names, and retrieve readtables by names;
  •          
  • you can associate source files with readtable names, and be sure that the right readtable is
    active when compiling/loading the file;
  •          
  • similiarly, your development environment now has a chance to automatically determine what
    readtable should be active while processing source forms on interactive commands. (E.g. think
    of `C-c C-c' in Slime [yet to be done])
    Additionally, it also attempts to become a facility for using readtables in a modular way. In
    particular:
             
  • it provides a macro to specify the content of a readtable at a glance;
  •          
  • it makes it possible to use multiple inheritance between readtables.

 

Notes on the API

    The API heavily imitates the API of packages. This has the nice property that any experienced
    Common Lisper will take it up without effort.

            DEFREADTABLE - DEFPACKAGE

            IN-READTABLE - IN-PACKAGE

            MERGE-READTABLES-INTO - USE-PACKAGE

            MAKE-READTABLE - MAKE-PACKAGE

            UNREGISTER-READTABLE - DELETE-PACKAGE

            RENAME-READTABLE - RENAME-PACKAGE

            FIND-READTABLE - FIND-PACKAGE

            READTABLE-NAME - PACKAGE-NAME

            LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES
 

Important API idiosyncrasies

    There are three major differences between the API of Named-Readtables, and the API of packages.

      1. Readtable names are symbols not strings.

                Time has shown that the fact that packages are named by strings causes severe headache because of
                the potential of package names colliding with each other.

                Hence, readtables are named by symbols lest to make the situation worse than it already is.
                Consequently, readtables named CL-ORACLE:SQL-SYNTAX and CL-MYSQL:SQL-SYNTAX can happily coexist
                next to each other. Or, taken to an extreme, SCHEME:SYNTAX and ELISP:SYNTAX.

                If, for example to duly signify the importance of your cool readtable hack, you really think it
                deserves a global name, you can always resort to keywords.

      2. The inheritance is resolved statically, not dynamically.

                A package that uses another package will have access to all the other package's exported
                symbols, even to those that will be added after its definition. I.e. the inheritance is resolved at
                run-time, that is dynamically.

                Unfortunately, we cannot do the same for readtables in a portable manner.

                Therefore, we do not talk about "using" another readtable but about "merging"
                the other readtable's definition into the readtable we are going to define. I.e. the
                inheritance is resolved once at definition time, that is statically.

                (Such merging can more or less be implemented portably albeit at a certain cost. Most of the time,
                this cost manifests itself at the time a readtable is defined, i.e. once at compile-time, so it may
                not bother you. Nonetheless, we provide extra support for Sbcl, ClozureCL, and AllegroCL at the
                moment. Patches for your implementation of choice are welcome, of course.)

      3. DEFREADTABLE does not have compile-time effects.

                If you define a package via DEFPACKAGE, you can make that package the currently active package for
                the subsequent compilation of the same file via IN-PACKAGE. The same is, however, not true for
                DEFREADTABLE and IN-READTABLE for the following reason:

                It's unlikely that the need for special reader-macros arises for a problem which can be
                solved in just one file. Most often, you're going to define the reader macro functions, and
                set up the corresponding readtable in an extra file.

                If DEFREADTABLE had compile-time effects, you'd have to wrap each definition of a
                reader-macro function in an EVAL-WHEN to make its definition available at compile-time. Because
                that's simply not the common case, DEFREADTABLE does not have a compile-time effect.

                If you want to use a readtable within the same file as its definition, wrap the DEFREADTABLE and
                the reader-macro function definitions in an explicit EVAL-WHEN.
 

Preregistered Readtables

        - NIL, :STANDARD, and :COMMON-LISP designate the standard readtable.

        - :MODERN designates a case-preserving standard-readtable.

        - :CURRENT designates the current readtable.
 

Examples

     (defreadtable elisp:syntax
        (:merge :standard)
        (:macro-char #\? #'elisp::read-character-literal t)
        (:macro-char #\[ #'elisp::read-vector-literal t)
        ...
        (:case :preserve))
    
     (defreadtable scheme:syntax
        (:merge :standard)
        (:macro-char #\[ #'(lambda (stream char)
                              (read-delimited-list #\] stream)))
        (:macro-char #\# :dispatch)
        (:dispatch-macro-char #\# #\t #'scheme::read-#t)
        (:dispatch-macro-char #\# #\f #'scheme::read-#f)
        ...
        (:case :preserve))
    
     (in-readtable elisp:syntax)
    
     ...
    
     (in-readtable scheme:syntax)
    
     ...

 

Acknowledgements

    Thanks to Robert Goldman for making me want to write this library.

    Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart Botta, David Crawford, and Pascal
    Costanza for being early adopters, providing comments and bugfixes.
 

 

Dictionary


[Function]
copy-named-readtable named-readtable => result

  Argument and Values:

named-readtable: (OR READTABLE SYMBOL)
result: READTABLE
  Description:
Like COPY-READTABLE but takes a NAMED-READTABLE-DESIGNATOR as argument.


[Macro]
defreadtable name &body options => result

  Description:

Define a new named readtable, whose name is given by the symbol name. Or, if a readtable is
already registered under that name, redefine that one.

The readtable can be populated using the following options:

    (:MERGE readtable-designators+)

            Merge the readtables designated into the new readtable being defined as per MERGE-READTABLES-INTO.

            If no :MERGE clause is given, an empty readtable is used. See MAKE-READTABLE.

    (:FUZE readtable-designators+)

            Like :MERGE except:

            Error conditions of type READER-MACRO-CONFLICT that are signaled during the merge operation will
            be silently continued. It follows that reader macros in earlier entries will be overwritten by
            later ones.

    (:DISPATCH-MACRO-CHAR macro-char sub-char function)

            Define a new sub character sub-char for the dispatching macro character macro-char,
            per SET-DISPATCH-MACRO-CHARACTER. You probably have to define macro-char as a dispatching
            macro character by the following option first.

    (:MACRO-CHAR macro-char function [non-terminating-p])

            Define a new macro character in the readtable, per SET-MACRO-CHARACTER. If function is the
            keyword :DISPATCH, macro-char is made a dispatching macro character, per
            MAKE-DISPATCH-MACRO-CHARACTER.

    (:SYNTAX-FROM from-readtable-designator from-char to-char)

            Set the character syntax of to-char in the readtable being defined to the same syntax as
            from-char as per SET-SYNTAX-FROM-CHAR.

    (:CASE case-mode)

            Defines the case sensitivity mode of the resulting readtable.

Any number of option clauses may appear. The options are grouped by their type, but in each group
the order the options appeared textually is preserved. The following groups exist and are executed
in the following order: :MERGE and :FUZE (one group), :CASE, :MACRO-CHAR and :DISPATCH-MACRO-CHAR
(one group), finally :SYNTAX-FROM.

Notes:

    The readtable is defined at load-time. If you want to have it available at compilation time -- say
    to use its reader-macros in the same file as its definition -- you have to wrap the DEFREADTABLE
    form in an explicit EVAL-WHEN.

    On redefinition, the target readtable is made empty first before it's refilled according to
    the clauses.

    NIL, :STANDARD, :COMMON-LISP, :MODERN, and :CURRENT are preregistered readtable names.


[Function]
ensure-readtable name &optional default => result

  Argument and Values:

name: (OR READTABLE SYMBOL)
default: (OR READTABLE SYMBOL)
result: READTABLE
  Description:
Looks up the readtable specified by name and returns it if it's found. If it is not
found, it registers the readtable designated by default under the name represented by
name; or if no default argument is given, it signals an error of type
READTABLE-DOES-NOT-EXIST instead.


[Function]
find-readtable name => result

  Argument and Values:

name: (OR READTABLE SYMBOL)
result: (OR READTABLE NULL)
  Description:
Looks for the readtable specified by name and returns it if it is found. Returns NIL
otherwise.


[Macro]
in-readtable name => result

  Description:

Set *READTABLE* to the readtable referred to by the symbol name.


[Function]
list-all-named-readtables => result

  Argument and Values:

result: LIST
  Description:
Returns a list of all registered readtables. The returned list is guaranteed to be fresh, but may
contain duplicates.


[Function]
make-readtable &optional name &key merge => result

  Argument and Values:

name: (OR READTABLE SYMBOL)
merge: LIST
result: READTABLE
  Description:
Creates and returns a new readtable under the specified name.

merge takes a list of NAMED-READTABLE-DESIGNATORS and specifies the readtables the new
readtable is created from. (See the :MERGE clause of DEFREADTABLE for details.)

If merge is NIL, an empty readtable is used instead.

If name is not given, an anonymous empty readtable is returned.

Notes:

    An empty readtable is a readtable where each character's syntax is the same as in the
    standard readtable except that each macro character has been made a constituent. Basically:
    whitespace stays whitespace, everything else is constituent.


[Function]
merge-readtables-into result-readtable &rest named-readtables => result

  Argument and Values:

result-readtable: (OR READTABLE SYMBOL)
named-readtables: (OR READTABLE SYMBOL)
result: READTABLE
  Description:
Copy the contents of each readtable in named-readtables into result-table.

If a macro character appears in more than one of the readtables, i.e. if a conflict is discovered
during the merge, an error of type READER-MACRO-CONFLICT is signaled.


[Type]
named-readtable-designator

  Description:

Either a symbol or a readtable itself.


[Condition type]
reader-macro-conflict

  Description:

Continuable.

This condition is signaled during the merge process if a) a reader macro (be it a macro character
or the sub character of a dispatch macro character) is both present in the source as well as the
target readtable, and b) if and only if the two respective reader macro functions differ.


[Condition type]
readtable-does-already-exist

  Description:

Continuable.


[Condition type]
readtable-does-not-exist


[Function]
readtable-name named-readtable => result

  Argument and Values:

named-readtable: (OR READTABLE SYMBOL)
result: SYMBOL
  Description:
Returns the name of the readtable designated by named-readtable, or NIL.


[Function]
register-readtable name readtable => result

  Argument and Values:

name: SYMBOL
readtable: READTABLE
result: READTABLE
  Description:
Associate readtable with name. Returns the readtable.


[Function]
rename-readtable old-name new-name => result

  Argument and Values:

old-name: (OR READTABLE SYMBOL)
new-name: SYMBOL
result: READTABLE
  Description:
Replaces the associated name of the readtable designated by old-name with new-name.
If a readtable is already registered under new-name, an error of type
READTABLE-DOES-ALREADY-EXIST is signaled.


[Function]
unregister-readtable named-readtable => result

  Argument and Values:

named-readtable: (OR READTABLE SYMBOL)
result: (MEMBER T NIL)
  Description:
Remove the association of named-readtable. Returns T if successfull, NIL otherwise.

This documentation was generated on 2009-11-5 from a Lisp image using some home-brewn, duct-taped,
evolutionary hacked extension of Edi Weitz' DOCUMENTATION-TEMPLATE.

abcl-src-1.9.0/contrib/named-readtables/named-readtables.asd0100644 0000000 0000000 00000003172 14202767264 022464 0ustar000000000 0000000 ;;;; -*- mode: Lisp -*- (in-package :asdf) (defclass named-readtables-source-file (cl-source-file) ()) #+sbcl (defmethod perform :around ((o compile-op) (c named-readtables-source-file)) (let ((sb-ext:*derive-function-types* t)) (call-next-method))) (defsystem "named-readtables" :description "Library that creates a namespace for named readtable akin to the namespace of packages." :author "Tobias C. Rittweiler " :maintainer "Gábor Melis" :mailto "mega@retes.hu" :version "0.9" :licence "BSD, see LICENSE" :default-component-class named-readtables-source-file :pathname "src" :serial t :components ((:file "package") (:file "utils") (:file "define-api") (:file "cruft") (:file "named-readtables")) :in-order-to ((test-op (test-op "named-readtables/test")))) (defsystem "named-readtables/test" :description "Test suite for the Named-Readtables library." :author "Tobias C. Rittweiler " :maintainer "Gábor Melis" :mailto "mega@retes.hu" :depends-on ("named-readtables") :pathname "test" :serial t :default-component-class named-readtables-source-file :components ((:file "package") (:file "rt") (:file "tests")) :perform (test-op (o c) (symbol-call :named-readtables-test '#:do-tests))) ;;; MGL-PAX depends on NAMED-READTABLES so we must put documentation ;;; in a separate system in order to be able to use MGL-PAX. (defsystem "named-readtables/doc" :depends-on ("named-readtables" "mgl-pax") :pathname "src" :components ((:file "doc"))) abcl-src-1.9.0/contrib/named-readtables/src/cruft.lisp0100644 0000000 0000000 00000042037 14202767264 021411 0ustar000000000 0000000 ;;;; ;;;; Copyright (c) 2008 - 2009 Tobias C. Rittweiler ;;;; ;;;; All rights reserved. ;;;; ;;;; See LICENSE for details. ;;;; (in-package :editor-hints.named-readtables) (defmacro define-cruft (name lambda-list &body (docstring . alternatives)) (assert (typep docstring 'string) (docstring) "Docstring missing!") (assert (not (null alternatives))) `(progn (declaim (inline ,name)) (defun ,name ,lambda-list ,docstring ,(first alternatives)))) (eval-when (:compile-toplevel :execute) #+sbcl (when (find-symbol "ASSERT-NOT-STANDARD-READTABLE" (find-package "SB-IMPL")) (pushnew :sbcl+safe-standard-readtable *features*))) ;;;;; Implementation-dependent cruft ;;;; Mapping between a readtable object and its readtable-name. (defvar *readtable-names* (make-hash-table :test 'eq)) (define-cruft %associate-readtable-with-name (name readtable) "Associate READTABLE with NAME for READTABLE-NAME to work." #+ :common-lisp (setf (gethash readtable *readtable-names*) name)) (define-cruft %unassociate-readtable-from-name (name readtable) "Remove the association between READTABLE and NAME." #+ :common-lisp (progn (assert (eq name (gethash readtable *readtable-names*))) (remhash readtable *readtable-names*))) (define-cruft %readtable-name (readtable) "Return the name associated with READTABLE." #+ :common-lisp (values (gethash readtable *readtable-names*))) (define-cruft %list-all-readtable-names () "Return a list of all available readtable names." #+ :common-lisp (list* :standard :current (loop for name being each hash-value of *readtable-names* collect name))) ;;;; Mapping between a readtable-name and the actual readtable object. ;;; On Allegro we reuse their named-readtable support so we work ;;; nicely on their infrastructure. #-allegro (defvar *named-readtables* (make-hash-table :test 'eq)) #+allegro (defun readtable-name-for-allegro (symbol) (multiple-value-bind (kwd status) (if (keywordp symbol) (values symbol nil) ;; Kludge: ACL uses keywords to name readtables, we allow ;; arbitrary symbols. (intern (format nil "~A.~A" (package-name (symbol-package symbol)) (symbol-name symbol)) :keyword)) (prog1 kwd (assert (or (not status) (get kwd 'named-readtable-designator))) (setf (get kwd 'named-readtable-designator) t)))) (define-cruft %associate-name-with-readtable (name readtable) "Associate NAME with READTABLE for FIND-READTABLE to work." #+ :allegro (setf (excl:named-readtable (readtable-name-for-allegro name)) readtable) #+ :common-lisp (setf (gethash name *named-readtables*) readtable)) (define-cruft %unassociate-name-from-readtable (name readtable) "Remove the association between NAME and READTABLE" #+ :allegro (let ((n (readtable-name-for-allegro name))) (assert (eq readtable (excl:named-readtable n))) (setf (excl:named-readtable n) nil)) #+ :common-lisp (progn (assert (eq readtable (gethash name *named-readtables*))) (remhash name *named-readtables*))) (define-cruft %find-readtable (name) "Return the readtable named NAME." #+ :allegro (excl:named-readtable (readtable-name-for-allegro name) nil) #+ :common-lisp (values (gethash name *named-readtables* nil))) ;;;; Reader-macro related predicates ;;; CLISP creates new function objects for standard reader macros on ;;; each readtable copy. (define-cruft function= (fn1 fn2) "Are reader-macro function-designators FN1 and FN2 the same?" #+ :clisp (let* ((fn1 (ensure-function fn1)) (fn2 (ensure-function fn2)) (n1 (system::function-name fn1)) (n2 (system::function-name fn2))) (if (and (eq n1 :lambda) (eq n2 :lambda)) (eq fn1 fn2) (equal n1 n2))) #+ :sbcl (let ((fn1 (ensure-function fn1)) (fn2 (ensure-function fn2))) (or (eq fn1 fn2) ;; After SBCL 1.1.18, for dispatch macro characters ;; GET-MACRO-CHARACTER returns closures whose name is: ;; ;; (LAMBDA (STREAM CHAR) :IN SB-IMPL::%MAKE-DISPATCH-MACRO-CHAR) ;; ;; Treat all these closures equivalent. (flet ((internal-dispatch-macro-closure-name-p (name) (find "SB-IMPL::%MAKE-DISPATCH-MACRO-CHAR" name :key #'prin1-to-string :test #'string-equal))) (let ((n1 (sb-impl::%fun-name fn1)) (n2 (sb-impl::%fun-name fn2))) (and (listp n1) (listp n2) (internal-dispatch-macro-closure-name-p n1) (internal-dispatch-macro-closure-name-p n2)))))) #+ :common-lisp (eq (ensure-function fn1) (ensure-function fn2))) ;;; CLISP will incorrectly fold the call to G-D-M-C away ;;; if not declared inline. (define-cruft dispatch-macro-char-p (char rt) "Is CHAR a dispatch macro character in RT?" #+ :common-lisp (handler-case (locally #+clisp (declare (notinline get-dispatch-macro-character)) (get-dispatch-macro-character char #\x rt) t) (error () nil))) ;; (defun macro-char-p (char rt) ;; (let ((reader-fn (%get-macro-character char rt))) ;; (and reader-fn t))) ;; (defun standard-macro-char-p (char rt) ;; (multiple-value-bind (rt-fn rt-flag) (get-macro-character char rt) ;; (multiple-value-bind (std-fn std-flag) (get-macro-character char *standard-readtable*) ;; (and (eq rt-fn std-fn) ;; (eq rt-flag std-flag))))) ;; (defun standard-dispatch-macro-char-p (disp-char sub-char rt) ;; (flet ((non-terminating-p (ch rt) (nth-value 1 (get-macro-character ch rt)))) ;; (and (eq (non-terminating-p disp-char rt) ;; (non-terminating-p disp-char *standard-readtable*)) ;; (eq (get-dispatch-macro-character disp-char sub-char rt) ;; (get-dispatch-macro-character disp-char sub-char *standard-readtable*))))) ;;;; Readtables Iterators (defmacro with-readtable-iterator ((name readtable) &body body) (let ((it (gensym))) `(let ((,it (%make-readtable-iterator ,readtable))) (macrolet ((,name () `(funcall ,',it))) ,@body)))) #+sbcl (defun %make-readtable-iterator (readtable) (let ((char-macro-array (sb-impl::character-macro-array readtable)) (char-macro-ht (sb-impl::character-macro-hash-table readtable)) (dispatch-tables (sb-impl::dispatch-tables readtable)) (char-code 0)) (with-hash-table-iterator (ht-iterator char-macro-ht) (labels ((grovel-base-chars () (if (>= char-code sb-int:base-char-code-limit) (grovel-unicode-chars) (let ((reader-fn (svref char-macro-array char-code)) (char (code-char (shiftf char-code (1+ char-code))))) (if reader-fn (yield char) (grovel-base-chars))))) (grovel-unicode-chars () (multiple-value-bind (more? char) (ht-iterator) (if (not more?) (values nil nil nil nil nil) (yield char)))) (yield (char) (let ((disp-fn (get-macro-character char readtable)) (disp-ht)) (cond ((setq disp-ht (cdr (assoc char dispatch-tables))) (let ((sub-char-alist)) (maphash (lambda (k v) (push (cons k v) sub-char-alist)) disp-ht) (values t char disp-fn t sub-char-alist))) (t (values t char disp-fn nil nil)))))) #'grovel-base-chars)))) #+clozure (defun %make-readtable-iterator (readtable) (flet ((ensure-alist (x) #.`(etypecase x (list x) ,@(uiop:if-let (sv (uiop:find-symbol* '#:sparse-vector :ccl nil)) `((,sv (let ((table (uiop:symbol-call :ccl '#:sparse-vector-table x))) (uiop:while-collecting (c) (loop for i below (length table) do (uiop:if-let ((v (svref table i))) (loop with i8 = (ash i 8) for j below (length v) do (uiop:if-let ((datum (svref v j))) (c (cons (code-char (+ i8 j)) datum)))))))))))))) (let ((char-macros (ensure-alist (#.(or (uiop:find-symbol* '#:rdtab.macros :ccl nil) (uiop:find-symbol* '#:rdtab.alist :ccl)) readtable)))) (lambda () (if char-macros (destructuring-bind (char . defn) (pop char-macros) (if (consp defn) (values t char (car defn) t (ensure-alist (cdr defn))) (values t char defn nil nil))) (values nil nil nil nil nil)))))) ;;; Written on ACL 8.0. #+allegro (defun %make-readtable-iterator (readtable) (declare (optimize speed)) ; for TCO (check-type readtable readtable) (let* ((macro-table (first (excl::readtable-macro-table readtable))) (dispatch-tables (excl::readtable-dispatch-tables readtable)) (table-length (length macro-table)) (idx 0)) (labels ((grovel-macro-chars () (if (>= idx table-length) (grovel-dispatch-chars) (let ((read-fn (svref macro-table idx)) (oidx idx)) (incf idx) (if (or (eq read-fn #'excl::read-token) (eq read-fn #'excl::read-dispatch-char) (eq read-fn #'excl::undefined-macro-char)) (grovel-macro-chars) (values t (code-char oidx) read-fn nil nil))))) (grovel-dispatch-chars () (if (null dispatch-tables) (values nil nil nil nil nil) (destructuring-bind (disp-char sub-char-table) (first dispatch-tables) (setf dispatch-tables (rest dispatch-tables)) ;;; Kludge. We can't fully clear dispatch tables ;;; in %CLEAR-READTABLE. (when (eq (svref macro-table (char-code disp-char)) #'excl::read-dispatch-char) (values t disp-char (svref macro-table (char-code disp-char)) t (loop for subch-fn across sub-char-table for subch-code from 0 when subch-fn collect (cons (code-char subch-code) subch-fn)))))))) #'grovel-macro-chars))) #-(or sbcl clozure allegro) (eval-when (:compile-toplevel) (let ((*print-pretty* t)) (simple-style-warn "~&~@< ~@;~A has not been ported to ~A. ~ We fall back to a portable implementation of readtable iterators. ~ This implementation has to grovel through all available characters. ~ On Unicode-aware implementations this may come with some costs.~@:>" (package-name '#.*package*) (lisp-implementation-type)))) #-(or sbcl clozure allegro) (defun %make-readtable-iterator (readtable) (check-type readtable readtable) (let ((char-code 0)) #'(lambda () (prog () :GROVEL (when (< char-code char-code-limit) (let ((char (code-char char-code))) (incf char-code) (when (not char) (go :GROVEL)) (let ((fn (get-macro-character char readtable))) (when (not fn) (go :GROVEL)) (multiple-value-bind (disp? alist) (handler-case ; grovel dispatch macro characters. (values t ;; Only grovel upper case characters to ;; avoid duplicates. (loop for code from 0 below char-code-limit for subchar = (non-lowercase-code-char code) for disp-fn = (and subchar (get-dispatch-macro-character char subchar readtable)) when disp-fn collect (cons subchar disp-fn))) (error () nil)) (return (values t char fn disp? alist)))))))))) #-(or sbcl clozure allegro) (defun non-lowercase-code-char (code) (let ((ch (code-char code))) (when (and ch (or (not (alpha-char-p ch)) (upper-case-p ch))) ch))) (defmacro do-readtable ((entry-designator readtable &optional result) &body body) "Iterate through a readtable's macro characters, and dispatch macro characters." (destructuring-bind (char &optional reader-fn non-terminating-p disp? table) (if (symbolp entry-designator) (list entry-designator) entry-designator) (let ((iter (gensym "ITER+")) (more? (gensym "MORE?+")) (rt (gensym "READTABLE+"))) `(let ((,rt ,readtable)) (with-readtable-iterator (,iter ,rt) (loop (multiple-value-bind (,more? ,char ,@(when reader-fn (list reader-fn)) ,@(when disp? (list disp?)) ,@(when table (list table))) (,iter) (unless ,more? (return ,result)) (let ,(when non-terminating-p ;; FIXME: N-T-P should be incorporated in iterators. `((,non-terminating-p (nth-value 1 (get-macro-character ,char ,rt))))) ,@body)))))))) ;;;; Misc ;;; This should return an implementation's actual standard readtable ;;; object only if the implementation makes the effort to guard against ;;; modification of that object. Otherwise it should better return a ;;; copy. (define-cruft %standard-readtable () "Return the standard readtable." #+ :sbcl+safe-standard-readtable sb-impl::*standard-readtable* #+ :common-lisp (copy-readtable nil)) ;;; On SBCL, SET-SYNTAX-FROM-CHAR does not get rid of a ;;; readtable's dispatch table properly. ;;; Same goes for Allegro but that does not seem to provide a ;;; setter for their readtable's dispatch tables. Hence this ugly ;;; workaround. (define-cruft %clear-readtable (readtable) "Make all macro characters in READTABLE be constituents." #+ :sbcl (prog1 readtable (do-readtable (char readtable) (set-syntax-from-char char #\A readtable)) (setf (sb-impl::dispatch-tables readtable) nil)) #+ :allegro (prog1 readtable (do-readtable (char readtable) (set-syntax-from-char char #\A readtable)) (let ((dispatch-tables (excl::readtable-dispatch-tables readtable))) (setf (cdr dispatch-tables) nil) (setf (caar dispatch-tables) #\Backspace) (setf (cadar dispatch-tables) (fill (cadar dispatch-tables) nil)))) #+ :common-lisp (do-readtable (char readtable readtable) (set-syntax-from-char char #\A readtable))) ;;; See Clozure Trac Ticket 601. This is supposed to be removed at ;;; some point in the future. (define-cruft %get-dispatch-macro-character (char subchar rt) "Ensure ANSI behaviour for GET-DISPATCH-MACRO-CHARACTER." #+ :ccl (ignore-errors (get-dispatch-macro-character char subchar rt)) #+ :common-lisp (get-dispatch-macro-character char subchar rt)) ;;; Allegro stores READ-TOKEN as reader macro function of each ;;; constituent character. (define-cruft %get-macro-character (char rt) "Ensure ANSI behaviour for GET-MACRO-CHARACTER." #+ :allegro (let ((fn (get-macro-character char rt))) (cond ((not fn) nil) ((function= fn #'excl::read-token) nil) (t fn))) #+ :common-lisp (get-macro-character char rt)) ;;;; Specialized PRINT-OBJECT for named readtables. ;;; As per #19 in CLHS 11.1.2.1.2 defining a method for PRINT-OBJECT ;;; that specializes on READTABLE is actually forbidden. It's quite ;;; likely to work (modulo package-locks) on most implementations, ;;; though. ;;; We don't need this on Allegro CL's as we hook into their ;;; named-readtable facility, and they provide such a method already. #-allegro (without-package-lock (:common-lisp #+lispworks :implementation) (defmethod print-object :around ((rt readtable) stream) (let ((name (readtable-name rt))) (if name (print-unreadable-object (rt stream :type nil :identity t) (format stream "~A ~S" :named-readtable name)) (call-next-method))))) abcl-src-1.9.0/contrib/named-readtables/src/define-api.lisp0100644 0000000 0000000 00000005543 14202767264 022270 0ustar000000000 0000000 (in-package :named-readtables) (defmacro define-api (name lambda-list type-list &body body) (flet ((parse-type-list (type-list) (let ((pos (position '=> type-list))) (assert pos () "You forgot to specify return type (`=>' missing.)") (values (subseq type-list 0 pos) `(values ,@(nthcdr (1+ pos) type-list) &optional))))) (multiple-value-bind (body decls docstring) (parse-body body :documentation t :whole `(define-api ,name)) (multiple-value-bind (arg-typespec value-typespec) (parse-type-list type-list) (multiple-value-bind (reqs opts rest keys) (parse-ordinary-lambda-list lambda-list) (declare (ignorable reqs opts rest keys)) `(progn (declaim (ftype (function ,arg-typespec ,value-typespec) ,name)) (locally ;;; Muffle the annoying "&OPTIONAL and &KEY found in ;;; the same lambda list" style-warning #+sbcl (declare (sb-ext:muffle-conditions style-warning)) (defun ,name ,lambda-list ,docstring #+sbcl (declare (sb-ext:unmuffle-conditions style-warning)) ,@decls ;; SBCL will interpret the ftype declaration as ;; assertion and will insert type checks for us. #-sbcl (progn ;; CHECK-TYPE required parameters ,@(loop for req-arg in reqs for req-type = (pop type-list) do (assert req-type) collect `(check-type ,req-arg ,req-type)) ;; CHECK-TYPE optional parameters ,@(loop initially (assert (or (null opts) (eq (pop type-list) '&optional))) for (opt-arg . nil) in opts for opt-type = (pop type-list) do (assert opt-type) collect `(check-type ,opt-arg ,opt-type)) ;; CHECK-TYPE rest parameter ,@(when rest (assert (eq (pop type-list) '&rest)) (let ((rest-type (pop type-list))) (assert rest-type) `((dolist (x ,rest) (check-type x ,rest-type))))) ;; CHECK-TYPE key parameters ,@(loop initially (assert (or (null keys) (eq (pop type-list) '&key))) for ((keyword key-arg) . nil) in keys for (nil key-type) = (find keyword type-list :key #'car) collect `(check-type ,key-arg ,key-type))) ,@body)))))))) abcl-src-1.9.0/contrib/named-readtables/src/doc.lisp0100644 0000000 0000000 00000021117 14202767264 021027 0ustar000000000 0000000 (in-package :named-readtables) (eval-when (:compile-toplevel :load-toplevel :execute) (use-package :mgl-pax)) (defsection @named-readtables-manual (:title "Named Readtables Manual") (named-readtables asdf:system) (@named-readtables-introduction section) (@named-readtables-overview section) (@named-readtables-reference section)) (defsection @named-readtables-introduction (:title "Introduction") "Named-Readtables is a library that provides a namespace for readtables akin to the already-existing namespace of packages. In particular: * you can associate readtables with names, and retrieve readtables by names; * you can associate source files with readtable names, and be sure that the right readtable is active when compiling/loading the file; * similiarly, your development environment now has a chance to automatically determine what readtable should be active while processing source forms on interactive commands. (E.g. think of `C-c C-c` in Slime (yet to be done)) It follows that Named-Readtables is a facility for using readtables in a localized way. Additionally, it also attempts to become a facility for using readtables in a _modular_ way. In particular: * it provides a macro to specify the content of a readtable at a glance; * it makes it possible to use multiple inheritance between readtables." (@named-readtables-links section) (@named-readtables-acknowledgements section)) (defsection @named-readtables-links (:title "Links") "Here is the [official repository][named-readtables-repo] and the [HTML documentation][named-readtables-doc] for the latest version. [named-readtables-repo]: https://github.com/melisgl/named-readtables [named-readtables-doc]: http://melisgl.github.io/mgl-pax-world/named-readtables-manual.html") (defsection @named-readtables-acknowledgements (:title "Acknowledgements") "Thanks to Robert Goldman for making me want to write this library. Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart Botta, David Crawford, and Pascal Costanza for being early adopters, providing comments and bugfixes.") (defsection @named-readtables-overview (:title "Overview") (@named-readtables-api-notes section) (@named-readtables-api-idiosyncrasies section) (@named-readtables-preregistered section) (@named-readtables-examples section)) (defsection @named-readtables-api-notes (:title "Notes on the API" :export nil) "The API heavily imitates the API of packages. This has the nice property that any experienced Common Lisper will take it up without effort. DEFREADTABLE - DEFPACKAGE IN-READTABLE - IN-PACKAGE MERGE-READTABLES-INTO - USE-PACKAGE MAKE-READTABLE - MAKE-PACKAGE UNREGISTER-READTABLE - DELETE-PACKAGE RENAME-READTABLE - RENAME-PACKAGE FIND-READTABLE - FIND-PACKAGE READTABLE-NAME - PACKAGE-NAME LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES") (defsection @named-readtables-api-idiosyncrasies (:title "Important API idiosyncrasies" :export nil) "There are three major differences between the API of Named-Readtables, and the API of packages. 1. Readtable names are symbols not strings. Time has shown that the fact that packages are named by strings causes severe headache because of the potential of package names colliding with each other. Hence, readtables are named by symbols lest to make the situation worse than it already is. Consequently, readtables named `CL-ORACLE:SQL-SYNTAX` and `CL-MYSQL:SQL-SYNTAX` can happily coexist next to each other. Or, taken to an extreme, `SCHEME:SYNTAX` and `ELISP:SYNTAX`. If, for example to duly signify the importance of your cool readtable hack, you really think it deserves a global name, you can always resort to keywords. 2. The inheritance is resolved statically, not dynamically. A package that uses another package will have access to all the other package's exported symbols, even to those that will be added after its definition. I.e. the inheritance is resolved at run-time, that is dynamically. Unfortunately, we cannot do the same for readtables in a portable manner. Therefore, we do not talk about \"using\" another readtable but about \"merging\" the other readtable's definition into the readtable we are going to define. I.e. the inheritance is resolved once at definition time, that is statically. (Such merging can more or less be implemented portably albeit at a certain cost. Most of the time, this cost manifests itself at the time a readtable is defined, i.e. once at compile-time, so it may not bother you. Nonetheless, we provide extra support for Sbcl, ClozureCL, and AllegroCL at the moment. Patches for your implementation of choice are welcome, of course.) 3. DEFREADTABLE does not have compile-time effects. If you define a package via DEFPACKAGE, you can make that package the currently active package for the subsequent compilation of the same file via IN-PACKAGE. The same is, however, not true for DEFREADTABLE and IN-READTABLE for the following reason: It's unlikely that the need for special reader-macros arises for a problem which can be solved in just one file. Most often, you're going to define the reader macro functions, and set up the corresponding readtable in an extra file. If DEFREADTABLE had compile-time effects, you'd have to wrap each definition of a reader-macro function in an EVAL-WHEN to make its definition available at compile-time. Because that's simply not the common case, DEFREADTABLE does not have a compile-time effect. If you want to use a readtable within the same file as its definition, wrap the DEFREADTABLE and the reader-macro function definitions in an explicit EVAL-WHEN.") (defsection @named-readtables-preregistered (:title "Preregistered Readtables" :export nil) "- NIL, :STANDARD, and :COMMON-LISP designate the _standard readtable_. - :MODERN designates a _case-preserving_ _standard-readtable_. - :CURRENT designates the _current readtable_.") (defsection @named-readtables-examples (:title "Examples" :export nil) "```commonlisp (defreadtable elisp:syntax (:merge :standard) (:macro-char #\\? #'elisp::read-character-literal t) (:macro-char #\\[ #'elisp::read-vector-literal t) ... (:case :preserve)) (defreadtable scheme:syntax (:merge :standard) (:macro-char #\\[ #'(lambda (stream char) (read-delimited-list #\\] stream))) (:macro-char #\\# :dispatch) (:dispatch-macro-char #\\# #\\t #'scheme::read-#t) (:dispatch-macro-char #\\# #\\f #'scheme::read-#f) ... (:case :preserve)) (in-readtable elisp:syntax) ... (in-readtable scheme:syntax) ... ```") (defsection @named-readtables-reference (:title "Reference") (defreadtable macro) (in-readtable macro) (make-readtable function) (merge-readtables-into function) (find-readtable function) (ensure-readtable function) (rename-readtable function) (readtable-name function) (register-readtable function) (unregister-readtable function) (copy-named-readtable function) (list-all-named-readtables function) (named-readtable-designator type) (reader-macro-conflict condition) (readtable-does-already-exist condition) (readtable-does-not-exist condition)) ;;;; Generating own docs (defun update-readmes () (with-open-file (stream (asdf:system-relative-pathname :named-readtables "README.md") :direction :output :if-does-not-exist :create :if-exists :supersede) (document @named-readtables-manual :stream stream) (print-markdown-footer stream)) (with-open-file (stream (asdf:system-relative-pathname :named-readtables "README") :direction :output :if-does-not-exist :create :if-exists :supersede) (describe @named-readtables-manual stream) (print-markdown-footer stream))) (defun print-markdown-footer (stream) (format stream "~%* * *~%") (format stream "###### \\[generated by ~ [MGL-PAX](https://github.com/melisgl/mgl-pax)\\]~%")) #| (update-readmes) |# abcl-src-1.9.0/contrib/named-readtables/src/named-readtables.lisp0100644 0000000 0000000 00000053675 14202767264 023470 0ustar000000000 0000000 ;;;; -*- Mode:Lisp -*- ;;;; ;;;; Copyright (c) 2007 - 2009 Tobias C. Rittweiler ;;;; Copyright (c) 2007, Robert P. Goldman and SIFT, LLC ;;;; ;;;; All rights reserved. ;;;; ;;;; See LICENSE for details. ;;;; (in-package :editor-hints.named-readtables) ;;; ;;; ``This is enough of a foothold to implement a more elaborate ;;; facility for using readtables in a localized way.'' ;;; ;;; (X3J13 Cleanup Issue IN-SYNTAX) ;;; ;;;;;; DEFREADTABLE &c. (defmacro defreadtable (name &body options) "Define a new named readtable, whose name is given by the symbol NAME. Or, if a readtable is already registered under that name, redefine that one. The readtable can be populated using the following OPTIONS: - `(:MERGE READTABLE-DESIGNATORS+)` Merge the readtables designated into the new readtable being defined as per MERGE-READTABLES-INTO. If no :MERGE clause is given, an empty readtable is used. See MAKE-READTABLE. - `(:FUSE READTABLE-DESIGNATORS+)` Like :MERGE except: Error conditions of type READER-MACRO-CONFLICT that are signaled during the merge operation will be silently _continued_. It follows that reader macros in earlier entries will be overwritten by later ones. For backward compatibility, :FUZE is accepted as an alias of :FUSE. - `(:DISPATCH-MACRO-CHAR MACRO-CHAR SUB-CHAR FUNCTION)` Define a new sub character `SUB-CHAR` for the dispatching macro character `MACRO-CHAR`, per SET-DISPATCH-MACRO-CHARACTER. You probably have to define `MACRO-CHAR` as a dispatching macro character by the following option first. - `(:MACRO-CHAR MACRO-CHAR FUNCTION [NON-TERMINATING-P])` Define a new macro character in the readtable, per SET-MACRO-CHARACTER. If `FUNCTION` is the keyword :DISPATCH, `MACRO-CHAR` is made a dispatching macro character, per MAKE-DISPATCH-MACRO-CHARACTER. - `(:SYNTAX-FROM FROM-READTABLE-DESIGNATOR FROM-CHAR TO-CHAR)` Set the character syntax of TO-CHAR in the readtable being defined to the same syntax as FROM-CHAR as per SET-SYNTAX-FROM-CHAR. - `(:CASE CASE-MODE)` Defines the _case sensitivity mode_ of the resulting readtable. Any number of option clauses may appear. The options are grouped by their type, but in each group the order the options appeared textually is preserved. The following groups exist and are executed in the following order: :MERGE and :FUSE (one group), :CASE, :MACRO-CHAR and :DISPATCH-MACRO-CHAR (one group), finally :SYNTAX-FROM. Notes: The readtable is defined at load-time. If you want to have it available at compilation time -- say to use its reader-macros in the same file as its definition -- you have to wrap the DEFREADTABLE form in an explicit EVAL-WHEN. On redefinition, the target readtable is made empty first before it's refilled according to the clauses. NIL, :STANDARD, :COMMON-LISP, :MODERN, and :CURRENT are preregistered readtable names." (check-type name symbol) (when (reserved-readtable-name-p name) (error "~A is the designator for a predefined readtable. ~ Not acceptable as a user-specified readtable name." name)) (flet ((process-option (option var) (destructure-case option ((:merge &rest readtable-designators) `(merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) readtable-designators))) ((:fuse &rest readtable-designators) `(handler-bind ((reader-macro-conflict #'continue)) (merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) readtable-designators)))) ;; alias for :FUSE ((:fuze &rest readtable-designators) `(handler-bind ((reader-macro-conflict #'continue)) (merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) readtable-designators)))) ((:dispatch-macro-char disp-char sub-char function) `(set-dispatch-macro-character ,disp-char ,sub-char ,function ,var)) ((:macro-char char function &optional non-terminating-p) (if (eq function :dispatch) `(make-dispatch-macro-character ,char ,non-terminating-p ,var) `(set-macro-character ,char ,function ,non-terminating-p ,var))) ((:syntax-from from-rt-designator from-char to-char) `(set-syntax-from-char ,to-char ,from-char ,var (find-readtable ,from-rt-designator))) ((:case mode) `(setf (readtable-case ,var) ,mode)))) (remove-clauses (clauses options) (setq clauses (if (listp clauses) clauses (list clauses))) (remove-if-not #'(lambda (x) (member x clauses)) options :key #'first))) (let* ((merge-clauses (remove-clauses '(:merge :fuze :fuse) options)) (case-clauses (remove-clauses :case options)) (macro-clauses (remove-clauses '(:macro-char :dispatch-macro-char) options)) (syntax-clauses (remove-clauses :syntax-from options)) (other-clauses (set-difference options (append merge-clauses case-clauses macro-clauses syntax-clauses)))) (cond ((not (null other-clauses)) (error "Bogus DEFREADTABLE clauses: ~/PPRINT-LINEAR/" other-clauses)) (t `(eval-when (:load-toplevel :execute) ;; The (FIND-READTABLE ...) isqrt important for proper ;; redefinition semantics, as redefining has to modify the ;; already existing readtable object. (let ((readtable (find-readtable ',name))) (cond ((not readtable) (setq readtable (make-readtable ',name))) (t (setq readtable (%clear-readtable readtable)) (simple-style-warn "Overwriting already existing readtable ~S." readtable))) ,@(loop for option in merge-clauses collect (process-option option 'readtable)) ,@(loop for option in case-clauses collect (process-option option 'readtable)) ,@(loop for option in macro-clauses collect (process-option option 'readtable)) ,@(loop for option in syntax-clauses collect (process-option option 'readtable)) readtable))))))) (defmacro in-readtable (name) "Set *READTABLE* to the readtable referred to by the symbol NAME." (check-type name symbol) `(eval-when (:compile-toplevel :load-toplevel :execute) ;; NB. The :LOAD-TOPLEVEL is needed for cases like (DEFVAR *FOO* ;; (GET-MACRO-CHARACTER #\")) (setf *readtable* (ensure-readtable ',name)) (when (find-package :swank) (%frob-swank-readtable-alist *package* *readtable*)))) ;;; KLUDGE: [interim solution] ;;; ;;; We need support for this in Slime itself, because we want IN-READTABLE ;;; to work on a per-file basis, and not on a per-package basis. ;;; (defun %frob-swank-readtable-alist (package readtable) (let ((readtable-alist (find-symbol (string '#:*readtable-alist*) (find-package :swank)))) (when (boundp readtable-alist) (pushnew (cons (package-name package) readtable) (symbol-value readtable-alist) :test #'(lambda (entry1 entry2) (destructuring-bind (pkg-name1 . rt1) entry1 (destructuring-bind (pkg-name2 . rt2) entry2 (and (string= pkg-name1 pkg-name2) (eq rt1 rt2))))))))) (deftype readtable-designator () `(or null readtable)) (deftype named-readtable-designator () "Either a symbol or a readtable itself." `(or readtable-designator symbol)) ;;;;; Compiler macros ;;; Since the :STANDARD readtable is interned, and we can't enforce ;;; its immutability, we signal a style-warning for suspicious uses ;;; that may result in strange behaviour: ;;; Modifying the standard readtable would, obviously, lead to a ;;; propagation of this change to all places which use the :STANDARD ;;; readtable (and thus rendering this readtable to be non-standard, ;;; in fact.) (eval-when (:compile-toplevel :load-toplevel :execute) (defun constant-standard-readtable-expression-p (thing) (or (null thing) (eq thing :standard) (and (consp thing) (find thing '((find-readtable nil) (find-readtable :standard) (ensure-readtable nil) (ensure-readtable :standard)) :test #'equal)))) (defun signal-suspicious-registration-warning (name-expr readtable-expr) (when (constant-standard-readtable-expression-p readtable-expr) (simple-style-warn "Caution: ~~% ~S" (list name-expr name-expr) readtable-expr)))) (define-compiler-macro register-readtable (&whole form name readtable) (signal-suspicious-registration-warning name readtable) form) (define-compiler-macro ensure-readtable (&whole form name &optional (default nil default-p)) (when default-p (signal-suspicious-registration-warning name default)) form) (declaim (special *standard-readtable* *empty-readtable*)) (define-api make-readtable (&optional (name nil name-supplied-p) &key merge) (&optional named-readtable-designator &key (:merge list) => readtable) "Creates and returns a new readtable under the specified NAME. MERGE takes a list of NAMED-READTABLE-DESIGNATORS and specifies the readtables the new readtable is created from. (See the :MERGE clause of DEFREADTABLE for details.) If MERGE is NIL, an empty readtable is used instead. If NAME is not given, an anonymous empty readtable is returned. Notes: An empty readtable is a readtable where each character's syntax is the same as in the _standard readtable_ except that each macro character has been made a constituent. Basically: whitespace stays whitespace, everything else is constituent." (cond ((not name-supplied-p) (copy-readtable *empty-readtable*)) ((reserved-readtable-name-p name) (error "~A is the designator for a predefined readtable. ~ Not acceptable as a user-specified readtable name." name)) ((let ((rt (find-readtable name))) (and rt (prog1 nil (cerror "Overwrite existing entry." 'readtable-does-already-exist :readtable-name name) ;; Explicitly unregister to make sure that we do ;; not hold on of any reference to RT. (unregister-readtable rt))))) (t (let ((result (apply #'merge-readtables-into ;; The first readtable specified in ;; the :merge list is taken as the ;; basis for all subsequent ;; (destructive!) modifications (and ;; hence it's copied.) (copy-readtable (if merge (ensure-readtable (first merge)) *empty-readtable*)) (rest merge)))) (register-readtable name result))))) (define-api rename-readtable (old-name new-name) (named-readtable-designator symbol => readtable) "Replaces the associated name of the readtable designated by OLD-NAME with NEW-NAME. If a readtable is already registered under NEW-NAME, an error of type READTABLE-DOES-ALREADY-EXIST is signaled." (when (find-readtable new-name) (cerror "Overwrite existing entry." 'readtable-does-already-exist :readtable-name new-name)) (let* ((readtable (ensure-readtable old-name)) (readtable-name (readtable-name readtable))) ;; We use the internal functions directly to omit repeated ;; type-checking. (%unassociate-name-from-readtable readtable-name readtable) (%unassociate-readtable-from-name readtable-name readtable) (%associate-name-with-readtable new-name readtable) (%associate-readtable-with-name new-name readtable) readtable)) (define-api merge-readtables-into (result-readtable &rest named-readtables) (named-readtable-designator &rest named-readtable-designator => readtable) "Copy the contents of each readtable in NAMED-READTABLES into RESULT-READTABLE. If a macro character appears in more than one of the readtables, i.e. if a conflict is discovered during the merge, an error of type READER-MACRO-CONFLICT is signaled." (flet ((merge-into (to from) (do-readtable ((char reader-fn non-terminating-p disp? table) from) (check-reader-macro-conflict from to char) (cond ((not disp?) (set-macro-character char reader-fn non-terminating-p to)) (t (ensure-dispatch-macro-character char non-terminating-p to) (loop for (subchar . subfn) in table do (check-reader-macro-conflict from to char subchar) (set-dispatch-macro-character char subchar subfn to))))) to)) (let ((result-table (ensure-readtable result-readtable))) (dolist (table (mapcar #'ensure-readtable named-readtables)) (merge-into result-table table)) result-table))) (defun ensure-dispatch-macro-character (char &optional non-terminating-p (readtable *readtable*)) (if (dispatch-macro-char-p char readtable) t (make-dispatch-macro-character char non-terminating-p readtable))) (define-api copy-named-readtable (named-readtable) (named-readtable-designator => readtable) "Like COPY-READTABLE but takes a NAMED-READTABLE-DESIGNATOR as argument." (copy-readtable (ensure-readtable named-readtable))) (define-api list-all-named-readtables () (=> list) "Returns a list of all registered readtables. The returned list is guaranteed to be fresh, but may contain duplicates." (mapcar #'ensure-readtable (%list-all-readtable-names))) (define-condition readtable-error (error) ()) (define-condition readtable-does-not-exist (readtable-error) ((readtable-name :initarg :readtable-name :initform (required-argument) :accessor missing-readtable-name :type named-readtable-designator)) (:report (lambda (condition stream) (format stream "A readtable named ~S does not exist." (missing-readtable-name condition))))) (define-condition readtable-does-already-exist (readtable-error) ((readtable-name :initarg :readtable-name :initform (required-argument) :accessor existing-readtable-name :type named-readtable-designator)) (:report (lambda (condition stream) (format stream "A readtable named ~S already exists." (existing-readtable-name condition)))) (:documentation "Continuable.")) (define-condition reader-macro-conflict (readtable-error) ((macro-char :initarg :macro-char :initform (required-argument) :accessor conflicting-macro-char :type character) (sub-char :initarg :sub-char :initform nil :accessor conflicting-dispatch-sub-char :type (or null character)) (from-readtable :initarg :from-readtable :initform (required-argument) :accessor from-readtable :type readtable) (to-readtable :initarg :to-readtable :initform (required-argument) :accessor to-readtable :type readtable)) (:report (lambda (condition stream) (format stream "~@" (conflicting-dispatch-sub-char condition) (conflicting-macro-char condition) (conflicting-dispatch-sub-char condition) (from-readtable condition) (to-readtable condition)))) (:documentation "Continuable. This condition is signaled during the merge process if a reader macro (be it a macro character or the sub character of a dispatch macro character) is present in the both source and the target readtable and the two respective reader macro functions differ.")) (defun check-reader-macro-conflict (from to char &optional subchar) (flet ((conflictp (from-fn to-fn) (assert from-fn () "Bug in readtable iterators or concurrent access?") (and to-fn (not (function= to-fn from-fn))))) (when (if subchar (conflictp (%get-dispatch-macro-character char subchar from) (%get-dispatch-macro-character char subchar to)) (conflictp (%get-macro-character char from) (%get-macro-character char to))) (cerror (format nil "Overwrite ~@C in ~A." char to) 'reader-macro-conflict :from-readtable from :to-readtable to :macro-char char :sub-char subchar)))) ;;; Although there is no way to get at the standard readtable in ;;; Common Lisp (cf. /standard readtable/, CLHS glossary), we make ;;; up the perception of its existence by interning a copy of it. ;;; ;;; We do this for reverse lookup (cf. READTABLE-NAME), i.e. for ;;; ;;; (equal (readtable-name (find-readtable :standard)) "STANDARD") ;;; ;;; holding true. ;;; ;;; We, however, inherit the restriction that the :STANDARD ;;; readtable _must not be modified_ (cf. CLHS 2.1.1.2), although it'd ;;; technically be feasible (as *STANDARD-READTABLE* will contain a ;;; mutable copy of the implementation-internal standard readtable.) ;;; We cannot enforce this restriction without shadowing ;;; CL:SET-MACRO-CHARACTER and CL:SET-DISPATCH-MACRO-FUNCTION which ;;; is out of scope of this library, though. So we just threaten ;;; with nasal demons. ;;; (defvar *standard-readtable* (%standard-readtable)) (defvar *empty-readtable* (%clear-readtable (copy-readtable nil))) (defvar *case-preserving-standard-readtable* (let ((readtable (copy-readtable nil))) (setf (readtable-case readtable) :preserve) readtable)) (defparameter *reserved-readtable-names* '(nil :standard :common-lisp :modern :current)) (defun reserved-readtable-name-p (name) (and (member name *reserved-readtable-names*) t)) ;;; In principle, we could DEFREADTABLE some of these. But we do ;;; reserved readtable lookup seperately, since we can't register a ;;; readtable for :CURRENT anyway. (defun find-reserved-readtable (reserved-name) (cond ((eq reserved-name nil) *standard-readtable*) ((eq reserved-name :standard) *standard-readtable*) ((eq reserved-name :common-lisp) *standard-readtable*) ((eq reserved-name :modern) *case-preserving-standard-readtable*) ((eq reserved-name :current) *readtable*) (t (error "Bug: no such reserved readtable: ~S" reserved-name)))) (define-api find-readtable (name) (named-readtable-designator => (or readtable null)) "Looks for the readtable specified by NAME and returns it if it is found. Returns NIL otherwise." (cond ((readtablep name) name) ((reserved-readtable-name-p name) (find-reserved-readtable name)) ((%find-readtable name)))) ;;; FIXME: This doesn't take a NAMED-READTABLE-DESIGNATOR, but only a ;;; STRING-DESIGNATOR. (When fixing, heed interplay with compiler ;;; macros below.) (defsetf find-readtable register-readtable) (define-api ensure-readtable (name &optional (default nil default-p)) (named-readtable-designator &optional (or named-readtable-designator null) => readtable) "Looks up the readtable specified by NAME and returns it if it's found. If it is not found, it registers the readtable designated by DEFAULT under the name represented by NAME; or if no default argument is given, it signals an error of type READTABLE-DOES-NOT-EXIST instead." (cond ((find-readtable name)) ((not default-p) (error 'readtable-does-not-exist :readtable-name name)) (t (setf (find-readtable name) (ensure-readtable default))))) (define-api register-readtable (name readtable) (symbol readtable => readtable) "Associate READTABLE with NAME. Returns the readtable." (assert (typep name '(not (satisfies reserved-readtable-name-p)))) (%associate-readtable-with-name name readtable) (%associate-name-with-readtable name readtable) readtable) (define-api unregister-readtable (named-readtable) (named-readtable-designator => boolean) "Remove the association of NAMED-READTABLE. Returns T if successfull, NIL otherwise." (let* ((readtable (find-readtable named-readtable)) (readtable-name (and readtable (readtable-name readtable)))) (if (not readtable-name) nil (prog1 t (check-type readtable-name (not (satisfies reserved-readtable-name-p))) (%unassociate-readtable-from-name readtable-name readtable) (%unassociate-name-from-readtable readtable-name readtable))))) (define-api readtable-name (named-readtable) (named-readtable-designator => symbol) "Returns the name of the readtable designated by NAMED-READTABLE, or NIL." (let ((readtable (ensure-readtable named-readtable))) (cond ((%readtable-name readtable)) ((eq readtable *readtable*) :current) ((eq readtable *standard-readtable*) :common-lisp) ((eq readtable *case-preserving-standard-readtable*) :modern) (t nil)))) abcl-src-1.9.0/contrib/named-readtables/src/package.lisp0100644 0000000 0000000 00000002347 14202767264 021661 0ustar000000000 0000000 (in-package :common-lisp-user) ;;; This is is basically MGL-PAX:DEFINE-PACKAGE but we don't have it ;;; defined yet. The package variance stuff is because we export ;;; documentation from the NAMED-READTABLES-DOC system. (eval-when (:compile-toplevel :load-toplevel :execute) (locally (declare #+sbcl (sb-ext:muffle-conditions sb-kernel::package-at-variance)) (handler-bind (#+sbcl (sb-kernel::package-at-variance #'muffle-warning)) (defpackage :editor-hints.named-readtables (:use :common-lisp) (:nicknames :named-readtables) (:export #:defreadtable #:in-readtable #:make-readtable #:merge-readtables-into #:find-readtable #:ensure-readtable #:rename-readtable #:readtable-name #:register-readtable #:unregister-readtable #:copy-named-readtable #:list-all-named-readtables ;; Types #:named-readtable-designator ;; Conditions #:reader-macro-conflict #:readtable-does-already-exist #:readtable-does-not-exist) (:documentation "See NAMED-READTABLES:@NAMED-READTABLES-MANUAL."))))) (pushnew :named-readtables *features*) abcl-src-1.9.0/contrib/named-readtables/src/utils.lisp0100644 0000000 0000000 00000023445 14202767264 021430 0ustar000000000 0000000 ;;;; ;;;; Copyright (c) 2008 - 2009 Tobias C. Rittweiler ;;;; ;;;; All rights reserved. ;;;; ;;;; See LICENSE for details. ;;;; (in-package :editor-hints.named-readtables) (defmacro without-package-lock ((&rest package-names) &body body) (declare (ignorable package-names)) #+clisp (return-from without-package-lock `(ext:without-package-lock (,@package-names) ,@body)) #+lispworks (return-from without-package-lock `(let ((hcl:*packages-for-warn-on-redefinition* (set-difference hcl:*packages-for-warn-on-redefinition* '(,@package-names) :key (lambda (package-designator) (if (packagep package-designator) (package-name package-designator) package-designator)) :test #'string=))) ,@body)) `(progn ,@body)) ;;; Taken from SWANK (which is Public Domain.) (defmacro destructure-case (value &body patterns) "Dispatch VALUE to one of PATTERNS. A cross between `case' and `destructuring-bind'. The pattern syntax is: ((HEAD . ARGS) . BODY) The list of patterns is searched for a HEAD `eq' to the car of VALUE. If one is found, the BODY is executed with ARGS bound to the corresponding values in the CDR of VALUE." (let ((operator (gensym "op-")) (operands (gensym "rand-")) (tmp (gensym "tmp-"))) `(let* ((,tmp ,value) (,operator (car ,tmp)) (,operands (cdr ,tmp))) (case ,operator ,@(loop for (pattern . body) in patterns collect (if (eq pattern t) `(t ,@body) (destructuring-bind (op &rest rands) pattern `(,op (destructuring-bind ,rands ,operands ,@body))))) ,@(if (eq (caar (last patterns)) t) '() `((t (error "destructure-case failed: ~S" ,tmp)))))))) ;;; Taken from Alexandria (which is Public Domain, or BSD.) (define-condition simple-style-warning (simple-warning style-warning) ()) (defun simple-style-warn (format-control &rest format-args) (warn 'simple-style-warning :format-control format-control :format-arguments format-args)) (define-condition simple-program-error (simple-error program-error) ()) (defun simple-program-error (message &rest args) (error 'simple-program-error :format-control message :format-arguments args)) (defun required-argument (&optional name) "Signals an error for a missing argument of NAME. Intended for use as an initialization form for structure and class-slots, and a default value for required keyword arguments." (error "Required argument ~@[~S ~]missing." name)) (defun ensure-list (list) "If LIST is a list, it is returned. Otherwise returns the list designated by LIST." (if (listp list) list (list list))) (declaim (inline ensure-function)) ; to propagate return type. (declaim (ftype (function (t) (values function &optional)) ensure-function)) (defun ensure-function (function-designator) "Returns the function designated by FUNCTION-DESIGNATOR: if FUNCTION-DESIGNATOR is a function, it is returned, otherwise it must be a function name and its FDEFINITION is returned." (if (functionp function-designator) function-designator (fdefinition function-designator))) (defun parse-body (body &key documentation whole) "Parses BODY into (values remaining-forms declarations doc-string). Documentation strings are recognized only if DOCUMENTATION is true. Syntax errors in body are signalled and WHOLE is used in the signal arguments when given." (let ((doc nil) (decls nil) (current nil)) (tagbody :declarations (setf current (car body)) (when (and documentation (stringp current) (cdr body)) (if doc (error "Too many documentation strings in ~S." (or whole body)) (setf doc (pop body))) (go :declarations)) (when (and (listp current) (eql (first current) 'declare)) (push (pop body) decls) (go :declarations))) (values body (nreverse decls) doc))) (defun parse-ordinary-lambda-list (lambda-list) "Parses an ordinary lambda-list, returning as multiple values: 1. Required parameters. 2. Optional parameter specifications, normalized into form (NAME INIT SUPPLIEDP) where SUPPLIEDP is NIL if not present. 3. Name of the rest parameter, or NIL. 4. Keyword parameter specifications, normalized into form ((KEYWORD-NAME NAME) INIT SUPPLIEDP) where SUPPLIEDP is NIL if not present. 5. Boolean indicating &ALLOW-OTHER-KEYS presence. 6. &AUX parameter specifications, normalized into form (NAME INIT). Signals a PROGRAM-ERROR is the lambda-list is malformed." (let ((state :required) (allow-other-keys nil) (auxp nil) (required nil) (optional nil) (rest nil) (keys nil) (aux nil)) (labels ((simple-program-error (format-string &rest format-args) (error 'simple-program-error :format-control format-string :format-arguments format-args)) (fail (elt) (simple-program-error "Misplaced ~S in ordinary lambda-list:~% ~S" elt lambda-list)) (check-variable (elt what) (unless (and (symbolp elt) (not (constantp elt))) (simple-program-error "Invalid ~A ~S in ordinary lambda-list:~% ~S" what elt lambda-list))) (check-spec (spec what) (destructuring-bind (init suppliedp) spec (declare (ignore init)) (check-variable suppliedp what))) (make-keyword (name) "Interns the string designated by NAME in the KEYWORD package." (intern (string name) :keyword))) (dolist (elt lambda-list) (case elt (&optional (if (eq state :required) (setf state elt) (fail elt))) (&rest (if (member state '(:required &optional)) (setf state elt) (progn (break "state=~S" state) (fail elt)))) (&key (if (member state '(:required &optional :after-rest)) (setf state elt) (fail elt))) (&allow-other-keys (if (eq state '&key) (setf allow-other-keys t state elt) (fail elt))) (&aux (cond ((eq state '&rest) (fail elt)) (auxp (simple-program-error "Multiple ~S in ordinary lambda-list:~% ~S" elt lambda-list)) (t (setf auxp t state elt)) )) (otherwise (when (member elt '#.(set-difference lambda-list-keywords '(&optional &rest &key &allow-other-keys &aux))) (simple-program-error "Bad lambda-list keyword ~S in ordinary lambda-list:~% ~S" elt lambda-list)) (case state (:required (check-variable elt "required parameter") (push elt required)) (&optional (cond ((consp elt) (destructuring-bind (name &rest tail) elt (check-variable name "optional parameter") (if (cdr tail) (check-spec tail "optional-supplied-p parameter") (setf elt (append elt '(nil)))))) (t (check-variable elt "optional parameter") (setf elt (cons elt '(nil nil))))) (push elt optional)) (&rest (check-variable elt "rest parameter") (setf rest elt state :after-rest)) (&key (cond ((consp elt) (destructuring-bind (var-or-kv &rest tail) elt (cond ((consp var-or-kv) (destructuring-bind (keyword var) var-or-kv (unless (symbolp keyword) (simple-program-error "Invalid keyword name ~S in ordinary ~ lambda-list:~% ~S" keyword lambda-list)) (check-variable var "keyword parameter"))) (t (check-variable var-or-kv "keyword parameter") (setf var-or-kv (list (make-keyword var-or-kv) var-or-kv)))) (if (cdr tail) (check-spec tail "keyword-supplied-p parameter") (setf tail (append tail '(nil)))) (setf elt (cons var-or-kv tail)))) (t (check-variable elt "keyword parameter") (setf elt (list (list (make-keyword elt) elt) nil nil)))) (push elt keys)) (&aux (if (consp elt) (destructuring-bind (var &optional init) elt (declare (ignore init)) (check-variable var "&aux parameter")) (check-variable elt "&aux parameter")) (push elt aux)) (t (simple-program-error "Invalid ordinary lambda-list:~% ~S" lambda-list))))))) (values (nreverse required) (nreverse optional) rest (nreverse keys) allow-other-keys (nreverse aux)))) abcl-src-1.9.0/contrib/named-readtables/test/LICENSE0100644 0000000 0000000 00000003252 14202767264 020566 0ustar000000000 0000000 Copyright (c) 2007 - 2009 Tobias C. Rittweiler Copyright (c) 2007, Robert P. Goldman and SIFT, LLC All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the names of Tobias C. Rittweiler, Robert P. Goldman, SIFT, LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Tobias C. Rittweiler, Robert P. Goldman and SIFT, LLC ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tobias C. Rittweiler, Robert P. Goldman or SIFT, LLC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. abcl-src-1.9.0/contrib/named-readtables/test/README0100644 0000000 0000000 00000030000 14202767264 020430 0ustar000000000 0000000 # Named Readtables Manual ###### \[in package EDITOR-HINTS.NAMED-READTABLES\] ## named-readtables ASDF System Details - Version: 0.9 - Description: Library that creates a namespace for named readtable akin to the namespace of packages. - Licence: BSD, see LICENSE - Author: Tobias C. Rittweiler - Maintainer: Gábor Melis - Mailto: [mega@retes.hu](mailto:mega@retes.hu) ## Introduction Named-Readtables is a library that provides a namespace for readtables akin to the already-existing namespace of packages. In particular: - you can associate readtables with names, and retrieve readtables by names; - you can associate source files with readtable names, and be sure that the right readtable is active when compiling/loading the file; - similiarly, your development environment now has a chance to automatically determine what readtable should be active while processing source forms on interactive commands. (E.g. think of `C-c C-c` in Slime (yet to be done)) It follows that Named-Readtables is a facility for using readtables in a localized way. Additionally, it also attempts to become a facility for using readtables in a *modular* way. In particular: - it provides a macro to specify the content of a readtable at a glance; - it makes it possible to use multiple inheritance between readtables. ### Links Here is the [official repository][named-readtables-repo] and the [HTML documentation][named-readtables-doc] for the latest version. [named-readtables-repo]: https://github.com/melisgl/named-readtables [named-readtables-doc]: http://melisgl.github.io/mgl-pax-world/named-readtables-manual.html ### Acknowledgements Thanks to Robert Goldman for making me want to write this library. Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart Botta, David Crawford, and Pascal Costanza for being early adopters, providing comments and bugfixes. ## Overview ### Notes on the API The API heavily imitates the API of packages. This has the nice property that any experienced Common Lisper will take it up without effort. DEFREADTABLE - DEFPACKAGE IN-READTABLE - IN-PACKAGE MERGE-READTABLES-INTO - USE-PACKAGE MAKE-READTABLE - MAKE-PACKAGE UNREGISTER-READTABLE - DELETE-PACKAGE RENAME-READTABLE - RENAME-PACKAGE FIND-READTABLE - FIND-PACKAGE READTABLE-NAME - PACKAGE-NAME LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES ### Important API idiosyncrasies There are three major differences between the API of Named-Readtables, and the API of packages. 1. Readtable names are symbols not strings. Time has shown that the fact that packages are named by strings causes severe headache because of the potential of package names colliding with each other. Hence, readtables are named by symbols lest to make the situation worse than it already is. Consequently, readtables named `CL-ORACLE:SQL-SYNTAX` and `CL-MYSQL:SQL-SYNTAX` can happily coexist next to each other. Or, taken to an extreme, `SCHEME:SYNTAX` and `ELISP:SYNTAX`. If, for example to duly signify the importance of your cool readtable hack, you really think it deserves a global name, you can always resort to keywords. 2. The inheritance is resolved statically, not dynamically. A package that uses another package will have access to all the other package's exported symbols, even to those that will be added after its definition. I.e. the inheritance is resolved at run-time, that is dynamically. Unfortunately, we cannot do the same for readtables in a portable manner. Therefore, we do not talk about "using" another readtable but about "merging" the other readtable's definition into the readtable we are going to define. I.e. the inheritance is resolved once at definition time, that is statically. (Such merging can more or less be implemented portably albeit at a certain cost. Most of the time, this cost manifests itself at the time a readtable is defined, i.e. once at compile-time, so it may not bother you. Nonetheless, we provide extra support for Sbcl, ClozureCL, and AllegroCL at the moment. Patches for your implementation of choice are welcome, of course.) 3. DEFREADTABLE does not have compile-time effects. If you define a package via DEFPACKAGE, you can make that package the currently active package for the subsequent compilation of the same file via IN-PACKAGE. The same is, however, not true for DEFREADTABLE and IN-READTABLE for the following reason: It's unlikely that the need for special reader-macros arises for a problem which can be solved in just one file. Most often, you're going to define the reader macro functions, and set up the corresponding readtable in an extra file. If DEFREADTABLE had compile-time effects, you'd have to wrap each definition of a reader-macro function in an EVAL-WHEN to make its definition available at compile-time. Because that's simply not the common case, DEFREADTABLE does not have a compile-time effect. If you want to use a readtable within the same file as its definition, wrap the DEFREADTABLE and the reader-macro function definitions in an explicit EVAL-WHEN. ### Preregistered Readtables - NIL, :STANDARD, and :COMMON-LISP designate the *standard readtable*. - :MODERN designates a *case-preserving* *standard-readtable*. - :CURRENT designates the *current readtable*. ### Examples ```commonlisp (defreadtable elisp:syntax (:merge :standard) (:macro-char #\? #'elisp::read-character-literal t) (:macro-char #\[ #'elisp::read-vector-literal t) ... (:case :preserve)) (defreadtable scheme:syntax (:merge :standard) (:macro-char #\[ #'(lambda (stream char) (read-delimited-list #\] stream))) (:macro-char #\# :dispatch) (:dispatch-macro-char #\# #\t #'scheme::read-#t) (:dispatch-macro-char #\# #\f #'scheme::read-#f) ... (:case :preserve)) (in-readtable elisp:syntax) ... (in-readtable scheme:syntax) ... ``` ## Reference - [macro] DEFREADTABLE NAME &BODY OPTIONS Define a new named readtable, whose name is given by the symbol NAME. Or, if a readtable is already registered under that name, redefine that one. The readtable can be populated using the following OPTIONS: - `(:MERGE READTABLE-DESIGNATORS+)` Merge the readtables designated into the new readtable being defined as per MERGE-READTABLES-INTO. If no :MERGE clause is given, an empty readtable is used. See MAKE-READTABLE. - `(:FUSE READTABLE-DESIGNATORS+)` Like :MERGE except: Error conditions of type READER-MACRO-CONFLICT that are signaled during the merge operation will be silently *continued*. It follows that reader macros in earlier entries will be overwritten by later ones. For backward compatibility, :FUZE is accepted as an alias of :FUSE. - `(:DISPATCH-MACRO-CHAR MACRO-CHAR SUB-CHAR FUNCTION)` Define a new sub character `SUB-CHAR` for the dispatching macro character `MACRO-CHAR`, per SET-DISPATCH-MACRO-CHARACTER. You probably have to define `MACRO-CHAR` as a dispatching macro character by the following option first. - `(:MACRO-CHAR MACRO-CHAR FUNCTION [NON-TERMINATING-P])` Define a new macro character in the readtable, per SET-MACRO-CHARACTER. If `FUNCTION` is the keyword :DISPATCH, `MACRO-CHAR` is made a dispatching macro character, per MAKE-DISPATCH-MACRO-CHARACTER. - `(:SYNTAX-FROM FROM-READTABLE-DESIGNATOR FROM-CHAR TO-CHAR)` Set the character syntax of TO-CHAR in the readtable being defined to the same syntax as FROM-CHAR as per SET-SYNTAX-FROM-CHAR. - `(:CASE CASE-MODE)` Defines the *case sensitivity mode* of the resulting readtable. Any number of option clauses may appear. The options are grouped by their type, but in each group the order the options appeared textually is preserved. The following groups exist and are executed in the following order: :MERGE and :FUSE (one group), :CASE, :MACRO-CHAR and :DISPATCH-MACRO-CHAR (one group), finally :SYNTAX-FROM. Notes: The readtable is defined at load-time. If you want to have it available at compilation time -- say to use its reader-macros in the same file as its definition -- you have to wrap the DEFREADTABLE form in an explicit EVAL-WHEN. On redefinition, the target readtable is made empty first before it's refilled according to the clauses. NIL, :STANDARD, :COMMON-LISP, :MODERN, and :CURRENT are preregistered readtable names. - [macro] IN-READTABLE NAME Set *READTABLE* to the readtable referred to by the symbol NAME. - [function] MAKE-READTABLE &OPTIONAL (NAME NIL NAME-SUPPLIED-P) &KEY MERGE Creates and returns a new readtable under the specified NAME. MERGE takes a list of NAMED-READTABLE-DESIGNATORS and specifies the readtables the new readtable is created from. (See the :MERGE clause of DEFREADTABLE for details.) If MERGE is NIL, an empty readtable is used instead. If NAME is not given, an anonymous empty readtable is returned. Notes: An empty readtable is a readtable where each character's syntax is the same as in the *standard readtable* except that each macro character has been made a constituent. Basically: whitespace stays whitespace, everything else is constituent. - [function] MERGE-READTABLES-INTO RESULT-READTABLE &REST NAMED-READTABLES Copy the contents of each readtable in NAMED-READTABLES into RESULT-READTABLE. If a macro character appears in more than one of the readtables, i.e. if a conflict is discovered during the merge, an error of type READER-MACRO-CONFLICT is signaled. - [function] FIND-READTABLE NAME Looks for the readtable specified by NAME and returns it if it is found. Returns NIL otherwise. - [function] ENSURE-READTABLE NAME &OPTIONAL (DEFAULT NIL DEFAULT-P) Looks up the readtable specified by NAME and returns it if it's found. If it is not found, it registers the readtable designated by DEFAULT under the name represented by NAME; or if no default argument is given, it signals an error of type READTABLE-DOES-NOT-EXIST instead. - [function] RENAME-READTABLE OLD-NAME NEW-NAME Replaces the associated name of the readtable designated by OLD-NAME with NEW-NAME. If a readtable is already registered under NEW-NAME, an error of type READTABLE-DOES-ALREADY-EXIST is signaled. - [function] READTABLE-NAME NAMED-READTABLE Returns the name of the readtable designated by NAMED-READTABLE, or NIL. - [function] REGISTER-READTABLE NAME READTABLE Associate READTABLE with NAME. Returns the readtable. - [function] UNREGISTER-READTABLE NAMED-READTABLE Remove the association of NAMED-READTABLE. Returns T if successfull, NIL otherwise. - [function] COPY-NAMED-READTABLE NAMED-READTABLE Like COPY-READTABLE but takes a NAMED-READTABLE-DESIGNATOR as argument. - [function] LIST-ALL-NAMED-READTABLES Returns a list of all registered readtables. The returned list is guaranteed to be fresh, but may contain duplicates. - [type] NAMED-READTABLE-DESIGNATOR Either a symbol or a readtable itself. - [condition] READER-MACRO-CONFLICT READTABLE-ERROR Continuable. This condition is signaled during the merge process if a reader macro (be it a macro character or the sub character of a dispatch macro character) is present in the both source and the target readtable and the two respective reader macro functions differ. - [condition] READTABLE-DOES-ALREADY-EXIST READTABLE-ERROR Continuable. - [condition] READTABLE-DOES-NOT-EXIST READTABLE-ERROR * * * ###### \[generated by [MGL-PAX](https://github.com/melisgl/mgl-pax)\] abcl-src-1.9.0/contrib/named-readtables/test/README.md0100644 0000000 0000000 00000044312 14202767264 021042 0ustar000000000 0000000 # Named Readtables Manual ## Table of Contents - [1 named-readtables ASDF System Details][9b5b] - [2 Introduction][6faf] - [2.1 Links][8688] - [2.2 Acknowledgements][059d] - [3 Overview][0bc2] - [3.1 Notes on the API][e4cd] - [3.2 Important API idiosyncrasies][62b8] - [3.3 Preregistered Readtables][58c6] - [3.4 Examples][cf94] - [4 Reference][373d] ###### \[in package EDITOR-HINTS.NAMED-READTABLES\] ## 1 named-readtables ASDF System Details - Version: 0.9 - Description: Library that creates a namespace for named readtable akin to the namespace of packages. - Licence: BSD, see LICENSE - Author: Tobias C. Rittweiler - Maintainer: Gábor Melis - Mailto: [mega@retes.hu](mailto:mega@retes.hu) ## 2 Introduction Named-Readtables is a library that provides a namespace for readtables akin to the already-existing namespace of packages. In particular: - you can associate readtables with names, and retrieve readtables by names; - you can associate source files with readtable names, and be sure that the right readtable is active when compiling/loading the file; - similiarly, your development environment now has a chance to automatically determine what readtable should be active while processing source forms on interactive commands. (E.g. think of `C-c C-c` in Slime (yet to be done)) It follows that Named-Readtables is a facility for using readtables in a localized way. Additionally, it also attempts to become a facility for using readtables in a *modular* way. In particular: - it provides a macro to specify the content of a readtable at a glance; - it makes it possible to use multiple inheritance between readtables. ### 2.1 Links Here is the [official repository][named-readtables-repo] and the [HTML documentation][named-readtables-doc] for the latest version. [named-readtables-repo]: https://github.com/melisgl/named-readtables [named-readtables-doc]: http://melisgl.github.io/mgl-pax-world/named-readtables-manual.html ### 2.2 Acknowledgements Thanks to Robert Goldman for making me want to write this library. Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart Botta, David Crawford, and Pascal Costanza for being early adopters, providing comments and bugfixes. ## 3 Overview ### 3.1 Notes on the API The API heavily imitates the API of packages. This has the nice property that any experienced Common Lisper will take it up without effort. DEFREADTABLE - DEFPACKAGE IN-READTABLE - IN-PACKAGE MERGE-READTABLES-INTO - USE-PACKAGE MAKE-READTABLE - MAKE-PACKAGE UNREGISTER-READTABLE - DELETE-PACKAGE RENAME-READTABLE - RENAME-PACKAGE FIND-READTABLE - FIND-PACKAGE READTABLE-NAME - PACKAGE-NAME LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES ### 3.2 Important API idiosyncrasies There are three major differences between the API of Named-Readtables, and the API of packages. 1. Readtable names are symbols not strings. Time has shown that the fact that packages are named by strings causes severe headache because of the potential of package names colliding with each other. Hence, readtables are named by symbols lest to make the situation worse than it already is. Consequently, readtables named `CL-ORACLE:SQL-SYNTAX` and `CL-MYSQL:SQL-SYNTAX` can happily coexist next to each other. Or, taken to an extreme, `SCHEME:SYNTAX` and `ELISP:SYNTAX`. If, for example to duly signify the importance of your cool readtable hack, you really think it deserves a global name, you can always resort to keywords. 2. The inheritance is resolved statically, not dynamically. A package that uses another package will have access to all the other package's exported symbols, even to those that will be added after its definition. I.e. the inheritance is resolved at run-time, that is dynamically. Unfortunately, we cannot do the same for readtables in a portable manner. Therefore, we do not talk about "using" another readtable but about "merging" the other readtable's definition into the readtable we are going to define. I.e. the inheritance is resolved once at definition time, that is statically. (Such merging can more or less be implemented portably albeit at a certain cost. Most of the time, this cost manifests itself at the time a readtable is defined, i.e. once at compile-time, so it may not bother you. Nonetheless, we provide extra support for Sbcl, ClozureCL, and AllegroCL at the moment. Patches for your implementation of choice are welcome, of course.) 3. [`DEFREADTABLE`][8b94] does not have compile-time effects. If you define a package via `DEFPACKAGE`, you can make that package the currently active package for the subsequent compilation of the same file via `IN-PACKAGE`. The same is, however, not true for [`DEFREADTABLE`][8b94] and [`IN-READTABLE`][de3b] for the following reason: It's unlikely that the need for special reader-macros arises for a problem which can be solved in just one file. Most often, you're going to define the reader macro functions, and set up the corresponding readtable in an extra file. If [`DEFREADTABLE`][8b94] had compile-time effects, you'd have to wrap each definition of a reader-macro function in an `EVAL-WHEN` to make its definition available at compile-time. Because that's simply not the common case, [`DEFREADTABLE`][8b94] does not have a compile-time effect. If you want to use a readtable within the same file as its definition, wrap the [`DEFREADTABLE`][8b94] and the reader-macro function definitions in an explicit `EVAL-WHEN`. ### 3.3 Preregistered Readtables - `NIL`, `:STANDARD`, and `:COMMON-LISP` designate the *standard readtable*. - `:MODERN` designates a *case-preserving* *standard-readtable*. - `:CURRENT` designates the *current readtable*. ### 3.4 Examples ```commonlisp (defreadtable elisp:syntax (:merge :standard) (:macro-char #\? #'elisp::read-character-literal t) (:macro-char #\[ #'elisp::read-vector-literal t) ... (:case :preserve)) (defreadtable scheme:syntax (:merge :standard) (:macro-char #\[ #'(lambda (stream char) (read-delimited-list #\] stream))) (:macro-char #\# :dispatch) (:dispatch-macro-char #\# #\t #'scheme::read-#t) (:dispatch-macro-char #\# #\f #'scheme::read-#f) ... (:case :preserve)) (in-readtable elisp:syntax) ... (in-readtable scheme:syntax) ... ``` ## 4 Reference - [macro] **DEFREADTABLE** *NAME &BODY OPTIONS* Define a new named readtable, whose name is given by the symbol `NAME`. Or, if a readtable is already registered under that name, redefine that one. The readtable can be populated using the following `OPTIONS`: - `(:MERGE READTABLE-DESIGNATORS+)` Merge the readtables designated into the new readtable being defined as per [`MERGE-READTABLES-INTO`][77fa]. If no `:MERGE` clause is given, an empty readtable is used. See [`MAKE-READTABLE`][958e]. - `(:FUSE READTABLE-DESIGNATORS+)` Like `:MERGE` except: Error conditions of type [`READER-MACRO-CONFLICT`][acb7] that are signaled during the merge operation will be silently *continued*. It follows that reader macros in earlier entries will be overwritten by later ones. For backward compatibility, `:FUZE` is accepted as an alias of `:FUSE`. - `(:DISPATCH-MACRO-CHAR MACRO-CHAR SUB-CHAR FUNCTION)` Define a new sub character `SUB-CHAR` for the dispatching macro character `MACRO-CHAR`, per `SET-DISPATCH-MACRO-CHARACTER`. You probably have to define `MACRO-CHAR` as a dispatching macro character by the following option first. - `(:MACRO-CHAR MACRO-CHAR FUNCTION [NON-TERMINATING-P])` Define a new macro character in the readtable, per `SET-MACRO-CHARACTER`. If `FUNCTION` is the keyword `:DISPATCH`, `MACRO-CHAR` is made a dispatching macro character, per `MAKE-DISPATCH-MACRO-CHARACTER`. - `(:SYNTAX-FROM FROM-READTABLE-DESIGNATOR FROM-CHAR TO-CHAR)` Set the character syntax of `TO-CHAR` in the readtable being defined to the same syntax as `FROM-CHAR` as per `SET-SYNTAX-FROM-CHAR`. - `(:CASE CASE-MODE)` Defines the *case sensitivity mode* of the resulting readtable. Any number of option clauses may appear. The options are grouped by their type, but in each group the order the options appeared textually is preserved. The following groups exist and are executed in the following order: `:MERGE` and `:FUSE` (one group), `:CASE`, `:MACRO-CHAR` and `:DISPATCH-MACRO-CHAR` (one group), finally `:SYNTAX-FROM`. Notes: The readtable is defined at load-time. If you want to have it available at compilation time -- say to use its reader-macros in the same file as its definition -- you have to wrap the [`DEFREADTABLE`][8b94] form in an explicit `EVAL-WHEN`. On redefinition, the target readtable is made empty first before it's refilled according to the clauses. `NIL`, `:STANDARD`, `:COMMON-LISP`, `:MODERN`, and `:CURRENT` are preregistered readtable names. - [macro] **IN-READTABLE** *NAME* Set `*READTABLE*` to the readtable referred to by the symbol `NAME`. - [function] **MAKE-READTABLE** *&OPTIONAL (NAME NIL NAME-SUPPLIED-P) &KEY MERGE* Creates and returns a new readtable under the specified `NAME`. `MERGE` takes a list of NAMED-READTABLE-DESIGNATORS and specifies the readtables the new readtable is created from. (See the `:MERGE` clause of [`DEFREADTABLE`][8b94] for details.) If `MERGE` is `NIL`, an empty readtable is used instead. If `NAME` is not given, an anonymous empty readtable is returned. Notes: An empty readtable is a readtable where each character's syntax is the same as in the *standard readtable* except that each macro character has been made a constituent. Basically: whitespace stays whitespace, everything else is constituent. - [function] **MERGE-READTABLES-INTO** *RESULT-READTABLE &REST NAMED-READTABLES* Copy the contents of each readtable in `NAMED-READTABLES`([`0`][] [`1`][9b5b]) into `RESULT-READTABLE`. If a macro character appears in more than one of the readtables, i.e. if a conflict is discovered during the merge, an error of type [`READER-MACRO-CONFLICT`][acb7] is signaled. - [function] **FIND-READTABLE** *NAME* Looks for the readtable specified by `NAME` and returns it if it is found. Returns `NIL` otherwise. - [function] **ENSURE-READTABLE** *NAME &OPTIONAL (DEFAULT NIL DEFAULT-P)* Looks up the readtable specified by `NAME` and returns it if it's found. If it is not found, it registers the readtable designated by `DEFAULT` under the name represented by NAME; or if no default argument is given, it signals an error of type [`READTABLE-DOES-NOT-EXIST`][437a] instead. - [function] **RENAME-READTABLE** *OLD-NAME NEW-NAME* Replaces the associated name of the readtable designated by `OLD-NAME` with `NEW-NAME`. If a readtable is already registered under `NEW-NAME`, an error of type [`READTABLE-DOES-ALREADY-EXIST`][4b51] is signaled. - [function] **READTABLE-NAME** *NAMED-READTABLE* Returns the name of the readtable designated by `NAMED-READTABLE`, or `NIL`. - [function] **REGISTER-READTABLE** *NAME READTABLE* Associate `READTABLE` with `NAME`. Returns the readtable. - [function] **UNREGISTER-READTABLE** *NAMED-READTABLE* Remove the association of `NAMED-READTABLE`. Returns `T` if successfull, `NIL` otherwise. - [function] **COPY-NAMED-READTABLE** *NAMED-READTABLE* Like `COPY-READTABLE` but takes a [`NAMED-READTABLE-DESIGNATOR`][fa0c] as argument. - [function] **LIST-ALL-NAMED-READTABLES** Returns a list of all registered readtables. The returned list is guaranteed to be fresh, but may contain duplicates. - [type] **NAMED-READTABLE-DESIGNATOR** Either a symbol or a readtable itself. - [condition] **READER-MACRO-CONFLICT** *READTABLE-ERROR* Continuable. This condition is signaled during the merge process if a reader macro (be it a macro character or the sub character of a dispatch macro character) is present in the both source and the target readtable and the two respective reader macro functions differ. - [condition] **READTABLE-DOES-ALREADY-EXIST** *READTABLE-ERROR* Continuable. - [condition] **READTABLE-DOES-NOT-EXIST** *READTABLE-ERROR* [059d]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-ACKNOWLEDGEMENTS-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-ACKNOWLEDGEMENTS MGL-PAX:SECTION)" [0bc2]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-OVERVIEW-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-OVERVIEW MGL-PAX:SECTION)" [373d]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-REFERENCE-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-REFERENCE MGL-PAX:SECTION)" [437a]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AREADTABLE-DOES-NOT-EXIST-20CONDITION-29 "(EDITOR-HINTS.NAMED-READTABLES:READTABLE-DOES-NOT-EXIST CONDITION)" [4b51]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AREADTABLE-DOES-ALREADY-EXIST-20CONDITION-29 "(EDITOR-HINTS.NAMED-READTABLES:READTABLE-DOES-ALREADY-EXIST CONDITION)" [58c6]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-PREREGISTERED-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-PREREGISTERED MGL-PAX:SECTION)" [62b8]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-API-IDIOSYNCRASIES-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-API-IDIOSYNCRASIES MGL-PAX:SECTION)" [6faf]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-INTRODUCTION-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-INTRODUCTION MGL-PAX:SECTION)" [77fa]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AMERGE-READTABLES-INTO-20FUNCTION-29 "(EDITOR-HINTS.NAMED-READTABLES:MERGE-READTABLES-INTO FUNCTION)" [8688]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-LINKS-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-LINKS MGL-PAX:SECTION)" [8b94]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3ADEFREADTABLE-20-28MGL-PAX-3AMACRO-29-29 "(EDITOR-HINTS.NAMED-READTABLES:DEFREADTABLE (MGL-PAX:MACRO))" [958e]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AMAKE-READTABLE-20FUNCTION-29 "(EDITOR-HINTS.NAMED-READTABLES:MAKE-READTABLE FUNCTION)" [9b5b]: #x-28-22named-readtables-22-20ASDF-2FSYSTEM-3ASYSTEM-29 "(\"named-readtables\" ASDF/SYSTEM:SYSTEM)" [acb7]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AREADER-MACRO-CONFLICT-20CONDITION-29 "(EDITOR-HINTS.NAMED-READTABLES:READER-MACRO-CONFLICT CONDITION)" [cf94]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-EXAMPLES-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-EXAMPLES MGL-PAX:SECTION)" [de3b]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3AIN-READTABLE-20-28MGL-PAX-3AMACRO-29-29 "(EDITOR-HINTS.NAMED-READTABLES:IN-READTABLE (MGL-PAX:MACRO))" [e4cd]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3A-40NAMED-READTABLES-API-NOTES-20MGL-PAX-3ASECTION-29 "(EDITOR-HINTS.NAMED-READTABLES:@NAMED-READTABLES-API-NOTES MGL-PAX:SECTION)" [fa0c]: #x-28EDITOR-HINTS-2ENAMED-READTABLES-3ANAMED-READTABLE-DESIGNATOR-20-28TYPE-29-29 "(EDITOR-HINTS.NAMED-READTABLES:NAMED-READTABLE-DESIGNATOR (TYPE))" * * * ###### \[generated by [MGL-PAX](https://github.com/melisgl/mgl-pax)\] abcl-src-1.9.0/contrib/named-readtables/test/doc/named-readtables.html0100644 0000000 0000000 00000105067 14202767264 024413 0ustar000000000 0000000 EDITOR-HINTS.NAMED-READTABLES - 0.9

EDITOR-HINTS.NAMED-READTABLES - 0.9

     by Tobias C Rittweiler
Repository:
 
     darcs get http://common-lisp.net/project/editor-hints/darcs/named-readtables/
 
Download:
 
     editor-hints.named-readtables-0.9.tar.gz
 

Contents

  1. What are Named-Readtables?
  2. Notes on the API
  3. Important API idiosyncrasies
  4. Preregistered Readtables
  5. Examples
  6. Acknowledgements
  7. Dictionary
    1. COPY-NAMED-READTABLE
    2. DEFREADTABLE
    3. ENSURE-READTABLE
    4. FIND-READTABLE
    5. IN-READTABLE
    6. LIST-ALL-NAMED-READTABLES
    7. MAKE-READTABLE
    8. MERGE-READTABLES-INTO
    9. NAMED-READTABLE-DESIGNATOR
    10. READER-MACRO-CONFLICT
    11. READTABLE-DOES-ALREADY-EXIST
    12. READTABLE-DOES-NOT-EXIST
    13. READTABLE-NAME
    14. REGISTER-READTABLE
    15. RENAME-READTABLE
    16. UNREGISTER-READTABLE

 

What are Named-Readtables?

    Named-Readtables is a library that provides a namespace for readtables akin to the
    already-existing namespace of packages. In particular:
             
  • you can associate readtables with names, and retrieve readtables by names;
  •          
  • you can associate source files with readtable names, and be sure that the right readtable is
    active when compiling/loading the file;
  •          
  • similiarly, your development environment now has a chance to automatically determine what
    readtable should be active while processing source forms on interactive commands. (E.g. think
    of `C-c C-c' in Slime [yet to be done])
    Additionally, it also attempts to become a facility for using readtables in a modular way. In
    particular:
             
  • it provides a macro to specify the content of a readtable at a glance;
  •          
  • it makes it possible to use multiple inheritance between readtables.

 

Notes on the API

    The API heavily imitates the API of packages. This has the nice property that any experienced
    Common Lisper will take it up without effort.

            DEFREADTABLE - DEFPACKAGE

            IN-READTABLE - IN-PACKAGE

            MERGE-READTABLES-INTO - USE-PACKAGE

            MAKE-READTABLE - MAKE-PACKAGE

            UNREGISTER-READTABLE - DELETE-PACKAGE

            RENAME-READTABLE - RENAME-PACKAGE

            FIND-READTABLE - FIND-PACKAGE

            READTABLE-NAME - PACKAGE-NAME

            LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES
 

Important API idiosyncrasies

    There are three major differences between the API of Named-Readtables, and the API of packages.

      1. Readtable names are symbols not strings.

                Time has shown that the fact that packages are named by strings causes severe headache because of
                the potential of package names colliding with each other.

                Hence, readtables are named by symbols lest to make the situation worse than it already is.
                Consequently, readtables named CL-ORACLE:SQL-SYNTAX and CL-MYSQL:SQL-SYNTAX can happily coexist
                next to each other. Or, taken to an extreme, SCHEME:SYNTAX and ELISP:SYNTAX.

                If, for example to duly signify the importance of your cool readtable hack, you really think it
                deserves a global name, you can always resort to keywords.

      2. The inheritance is resolved statically, not dynamically.

                A package that uses another package will have access to all the other package's exported
                symbols, even to those that will be added after its definition. I.e. the inheritance is resolved at
                run-time, that is dynamically.

                Unfortunately, we cannot do the same for readtables in a portable manner.

                Therefore, we do not talk about "using" another readtable but about "merging"
                the other readtable's definition into the readtable we are going to define. I.e. the
                inheritance is resolved once at definition time, that is statically.

                (Such merging can more or less be implemented portably albeit at a certain cost. Most of the time,
                this cost manifests itself at the time a readtable is defined, i.e. once at compile-time, so it may
                not bother you. Nonetheless, we provide extra support for Sbcl, ClozureCL, and AllegroCL at the
                moment. Patches for your implementation of choice are welcome, of course.)

      3. DEFREADTABLE does not have compile-time effects.

                If you define a package via DEFPACKAGE, you can make that package the currently active package for
                the subsequent compilation of the same file via IN-PACKAGE. The same is, however, not true for
                DEFREADTABLE and IN-READTABLE for the following reason:

                It's unlikely that the need for special reader-macros arises for a problem which can be
                solved in just one file. Most often, you're going to define the reader macro functions, and
                set up the corresponding readtable in an extra file.

                If DEFREADTABLE had compile-time effects, you'd have to wrap each definition of a
                reader-macro function in an EVAL-WHEN to make its definition available at compile-time. Because
                that's simply not the common case, DEFREADTABLE does not have a compile-time effect.

                If you want to use a readtable within the same file as its definition, wrap the DEFREADTABLE and
                the reader-macro function definitions in an explicit EVAL-WHEN.
 

Preregistered Readtables

        - NIL, :STANDARD, and :COMMON-LISP designate the standard readtable.

        - :MODERN designates a case-preserving standard-readtable.

        - :CURRENT designates the current readtable.
 

Examples

     (defreadtable elisp:syntax
        (:merge :standard)
        (:macro-char #\? #'elisp::read-character-literal t)
        (:macro-char #\[ #'elisp::read-vector-literal t)
        ...
        (:case :preserve))
    
     (defreadtable scheme:syntax
        (:merge :standard)
        (:macro-char #\[ #'(lambda (stream char)
                              (read-delimited-list #\] stream)))
        (:macro-char #\# :dispatch)
        (:dispatch-macro-char #\# #\t #'scheme::read-#t)
        (:dispatch-macro-char #\# #\f #'scheme::read-#f)
        ...
        (:case :preserve))
    
     (in-readtable elisp:syntax)
    
     ...
    
     (in-readtable scheme:syntax)
    
     ...

 

Acknowledgements

    Thanks to Robert Goldman for making me want to write this library.

    Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart Botta, David Crawford, and Pascal
    Costanza for being early adopters, providing comments and bugfixes.
 

 

Dictionary


[Function]
copy-named-readtable named-readtable => result

  Argument and Values:

named-readtable: (OR READTABLE SYMBOL)
result: READTABLE
  Description:
Like COPY-READTABLE but takes a NAMED-READTABLE-DESIGNATOR as argument.


[Macro]
defreadtable name &body options => result

  Description:

Define a new named readtable, whose name is given by the symbol name. Or, if a readtable is
already registered under that name, redefine that one.

The readtable can be populated using the following options:

    (:MERGE readtable-designators+)

            Merge the readtables designated into the new readtable being defined as per MERGE-READTABLES-INTO.

            If no :MERGE clause is given, an empty readtable is used. See MAKE-READTABLE.

    (:FUZE readtable-designators+)

            Like :MERGE except:

            Error conditions of type READER-MACRO-CONFLICT that are signaled during the merge operation will
            be silently continued. It follows that reader macros in earlier entries will be overwritten by
            later ones.

    (:DISPATCH-MACRO-CHAR macro-char sub-char function)

            Define a new sub character sub-char for the dispatching macro character macro-char,
            per SET-DISPATCH-MACRO-CHARACTER. You probably have to define macro-char as a dispatching
            macro character by the following option first.

    (:MACRO-CHAR macro-char function [non-terminating-p])

            Define a new macro character in the readtable, per SET-MACRO-CHARACTER. If function is the
            keyword :DISPATCH, macro-char is made a dispatching macro character, per
            MAKE-DISPATCH-MACRO-CHARACTER.

    (:SYNTAX-FROM from-readtable-designator from-char to-char)

            Set the character syntax of to-char in the readtable being defined to the same syntax as
            from-char as per SET-SYNTAX-FROM-CHAR.

    (:CASE case-mode)

            Defines the case sensitivity mode of the resulting readtable.

Any number of option clauses may appear. The options are grouped by their type, but in each group
the order the options appeared textually is preserved. The following groups exist and are executed
in the following order: :MERGE and :FUZE (one group), :CASE, :MACRO-CHAR and :DISPATCH-MACRO-CHAR
(one group), finally :SYNTAX-FROM.

Notes:

    The readtable is defined at load-time. If you want to have it available at compilation time -- say
    to use its reader-macros in the same file as its definition -- you have to wrap the DEFREADTABLE
    form in an explicit EVAL-WHEN.

    On redefinition, the target readtable is made empty first before it's refilled according to
    the clauses.

    NIL, :STANDARD, :COMMON-LISP, :MODERN, and :CURRENT are preregistered readtable names.


[Function]
ensure-readtable name &optional default => result

  Argument and Values:

name: (OR READTABLE SYMBOL)
default: (OR READTABLE SYMBOL)
result: READTABLE
  Description:
Looks up the readtable specified by name and returns it if it's found. If it is not
found, it registers the readtable designated by default under the name represented by
name; or if no default argument is given, it signals an error of type
READTABLE-DOES-NOT-EXIST instead.


[Function]
find-readtable name => result

  Argument and Values:

name: (OR READTABLE SYMBOL)
result: (OR READTABLE NULL)
  Description:
Looks for the readtable specified by name and returns it if it is found. Returns NIL
otherwise.


[Macro]
in-readtable name => result

  Description:

Set *READTABLE* to the readtable referred to by the symbol name.


[Function]
list-all-named-readtables => result

  Argument and Values:

result: LIST
  Description:
Returns a list of all registered readtables. The returned list is guaranteed to be fresh, but may
contain duplicates.


[Function]
make-readtable &optional name &key merge => result

  Argument and Values:

name: (OR READTABLE SYMBOL)
merge: LIST
result: READTABLE
  Description:
Creates and returns a new readtable under the specified name.

merge takes a list of NAMED-READTABLE-DESIGNATORS and specifies the readtables the new
readtable is created from. (See the :MERGE clause of DEFREADTABLE for details.)

If merge is NIL, an empty readtable is used instead.

If name is not given, an anonymous empty readtable is returned.

Notes:

    An empty readtable is a readtable where each character's syntax is the same as in the
    standard readtable except that each macro character has been made a constituent. Basically:
    whitespace stays whitespace, everything else is constituent.


[Function]
merge-readtables-into result-readtable &rest named-readtables => result

  Argument and Values:

result-readtable: (OR READTABLE SYMBOL)
named-readtables: (OR READTABLE SYMBOL)
result: READTABLE
  Description:
Copy the contents of each readtable in named-readtables into result-table.

If a macro character appears in more than one of the readtables, i.e. if a conflict is discovered
during the merge, an error of type READER-MACRO-CONFLICT is signaled.


[Type]
named-readtable-designator

  Description:

Either a symbol or a readtable itself.


[Condition type]
reader-macro-conflict

  Description:

Continuable.

This condition is signaled during the merge process if a) a reader macro (be it a macro character
or the sub character of a dispatch macro character) is both present in the source as well as the
target readtable, and b) if and only if the two respective reader macro functions differ.


[Condition type]
readtable-does-already-exist

  Description:

Continuable.


[Condition type]
readtable-does-not-exist


[Function]
readtable-name named-readtable => result

  Argument and Values:

named-readtable: (OR READTABLE SYMBOL)
result: SYMBOL
  Description:
Returns the name of the readtable designated by named-readtable, or NIL.


[Function]
register-readtable name readtable => result

  Argument and Values:

name: SYMBOL
readtable: READTABLE
result: READTABLE
  Description:
Associate readtable with name. Returns the readtable.


[Function]
rename-readtable old-name new-name => result

  Argument and Values:

old-name: (OR READTABLE SYMBOL)
new-name: SYMBOL
result: READTABLE
  Description:
Replaces the associated name of the readtable designated by old-name with new-name.
If a readtable is already registered under new-name, an error of type
READTABLE-DOES-ALREADY-EXIST is signaled.


[Function]
unregister-readtable named-readtable => result

  Argument and Values:

named-readtable: (OR READTABLE SYMBOL)
result: (MEMBER T NIL)
  Description:
Remove the association of named-readtable. Returns T if successfull, NIL otherwise.

This documentation was generated on 2009-11-5 from a Lisp image using some home-brewn, duct-taped,
evolutionary hacked extension of Edi Weitz' DOCUMENTATION-TEMPLATE.

abcl-src-1.9.0/contrib/named-readtables/test/named-readtables.asd0100644 0000000 0000000 00000003172 14202767264 023443 0ustar000000000 0000000 ;;;; -*- mode: Lisp -*- (in-package :asdf) (defclass named-readtables-source-file (cl-source-file) ()) #+sbcl (defmethod perform :around ((o compile-op) (c named-readtables-source-file)) (let ((sb-ext:*derive-function-types* t)) (call-next-method))) (defsystem "named-readtables" :description "Library that creates a namespace for named readtable akin to the namespace of packages." :author "Tobias C. Rittweiler " :maintainer "Gábor Melis" :mailto "mega@retes.hu" :version "0.9" :licence "BSD, see LICENSE" :default-component-class named-readtables-source-file :pathname "src" :serial t :components ((:file "package") (:file "utils") (:file "define-api") (:file "cruft") (:file "named-readtables")) :in-order-to ((test-op (test-op "named-readtables/test")))) (defsystem "named-readtables/test" :description "Test suite for the Named-Readtables library." :author "Tobias C. Rittweiler " :maintainer "Gábor Melis" :mailto "mega@retes.hu" :depends-on ("named-readtables") :pathname "test" :serial t :default-component-class named-readtables-source-file :components ((:file "package") (:file "rt") (:file "tests")) :perform (test-op (o c) (symbol-call :named-readtables-test '#:do-tests))) ;;; MGL-PAX depends on NAMED-READTABLES so we must put documentation ;;; in a separate system in order to be able to use MGL-PAX. (defsystem "named-readtables/doc" :depends-on ("named-readtables" "mgl-pax") :pathname "src" :components ((:file "doc"))) abcl-src-1.9.0/contrib/named-readtables/test/package.lisp0100644 0000000 0000000 00000000424 14202767264 022043 0ustar000000000 0000000 ;;; -*- Mode:Lisp -*- (in-package :cl-user) (defpackage :named-readtables-test (:use :cl :named-readtables) (:import-from :named-readtables #:dispatch-macro-char-p #:do-readtable #:ensure-function #:ensure-dispatch-macro-character #:function=)) abcl-src-1.9.0/contrib/named-readtables/test/rt.lisp0100644 0000000 0000000 00000021456 14202767264 021105 0ustar000000000 0000000 #|----------------------------------------------------------------------------| | Copyright 1990 by the Massachusetts Institute of Technology, Cambridge MA. | | | | Permission to use, copy, modify, and distribute this software and its | | documentation for any purpose and without fee is hereby granted, provided | | that this copyright and permission notice appear in all copies and | | supporting documentation, and that the name of M.I.T. not be used in | | advertising or publicity pertaining to distribution of the software | | without specific, written prior permission. M.I.T. makes no | | representations about the suitability of this software for any purpose. | | It is provided "as is" without express or implied warranty. | | | | M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | | M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | | SOFTWARE. | |----------------------------------------------------------------------------|# ;; (defpackage :rt ;; (:use #:cl) ;; (:export #:*do-tests-when-defined* #:*test* #:continue-testing ;; #:deftest #:do-test #:do-tests #:get-test #:pending-tests ;; #:rem-all-tests #:rem-test) ;; (:documentation "The MIT regression tester")) ;; (in-package :rt) (in-package :named-readtables-test) (defvar *test* nil "Current test name") (defvar *do-tests-when-defined* nil) (defvar *entries* '(nil) "Test database") (defvar *in-test* nil "Used by TEST") (defvar *debug* nil "For debugging") (defvar *catch-errors* t "When true, causes errors in a test to be caught.") (defvar *print-circle-on-failure* nil "Failure reports are printed with *PRINT-CIRCLE* bound to this value.") (defvar *compile-tests* nil "When true, compile the tests before running them.") (defvar *optimization-settings* '((safety 3))) (defvar *expected-failures* nil "A list of test names that are expected to fail.") (defstruct (entry (:conc-name nil) (:type list)) pend name form) (defmacro vals (entry) `(cdddr ,entry)) (defmacro defn (entry) `(cdr ,entry)) (defun pending-tests () (do ((l (cdr *entries*) (cdr l)) (r nil)) ((null l) (nreverse r)) (when (pend (car l)) (push (name (car l)) r)))) (defun rem-all-tests () (setq *entries* (list nil)) nil) (defun rem-test (&optional (name *test*)) (do ((l *entries* (cdr l))) ((null (cdr l)) nil) (when (equal (name (cadr l)) name) (setf (cdr l) (cddr l)) (return name)))) (defun get-test (&optional (name *test*)) (defn (get-entry name))) (defun get-entry (name) (let ((entry (find name (cdr *entries*) :key #'name :test #'equal))) (when (null entry) (report-error t "~%No test with name ~:@(~S~)." name)) entry)) (defmacro deftest (name form &rest values) `(add-entry '(t ,name ,form .,values))) (defun add-entry (entry) (setq entry (copy-list entry)) (do ((l *entries* (cdr l))) (nil) (when (null (cdr l)) (setf (cdr l) (list entry)) (return nil)) (when (equal (name (cadr l)) (name entry)) (setf (cadr l) entry) (report-error nil "Redefining test ~:@(~S~)" (name entry)) (return nil))) (when *do-tests-when-defined* (do-entry entry)) (setq *test* (name entry))) (defun report-error (error? &rest args) (cond (*debug* (apply #'format t args) (if error? (throw '*debug* nil))) (error? (apply #'error args)) (t (apply #'warn args)))) (defun do-test (&optional (name *test*)) (do-entry (get-entry name))) (defun equalp-with-case (x y) "Like EQUALP, but doesn't do case conversion of characters." (cond ((eq x y) t) ((consp x) (and (consp y) (equalp-with-case (car x) (car y)) (equalp-with-case (cdr x) (cdr y)))) ((and (typep x 'array) (= (array-rank x) 0)) (equalp-with-case (aref x) (aref y))) ((typep x 'vector) (and (typep y 'vector) (let ((x-len (length x)) (y-len (length y))) (and (eql x-len y-len) (loop for e1 across x for e2 across y always (equalp-with-case e1 e2)))))) ((and (typep x 'array) (typep y 'array) (not (equal (array-dimensions x) (array-dimensions y)))) nil) ((typep x 'array) (and (typep y 'array) (let ((size (array-total-size x))) (loop for i from 0 below size always (equalp-with-case (row-major-aref x i) (row-major-aref y i)))))) (t (eql x y)))) (defun do-entry (entry &optional (s *standard-output*)) (catch '*in-test* (setq *test* (name entry)) (setf (pend entry) t) (let* ((*in-test* t) ;; (*break-on-warnings* t) (aborted nil) r) ;; (declare (special *break-on-warnings*)) (block aborted (setf r (flet ((%do () (if *compile-tests* (multiple-value-list (funcall (compile nil `(lambda () (declare (optimize ,@*optimization-settings*)) ,(form entry))))) (multiple-value-list (eval (form entry)))))) (if *catch-errors* (handler-bind ((style-warning #'muffle-warning) (error #'(lambda (c) (setf aborted t) (setf r (list c)) (return-from aborted nil)))) (%do)) (%do))))) (setf (pend entry) (or aborted (not (equalp-with-case r (vals entry))))) (when (pend entry) (let ((*print-circle* *print-circle-on-failure*)) (format s "~&Test ~:@(~S~) failed~ ~%Form: ~S~ ~%Expected value~P: ~ ~{~S~^~%~17t~}~%" *test* (form entry) (length (vals entry)) (vals entry)) (format s "Actual value~P: ~ ~{~S~^~%~15t~}.~%" (length r) r))))) (when (not (pend entry)) *test*)) (defun continue-testing () (if *in-test* (throw '*in-test* nil) (do-entries *standard-output*))) (defun do-tests (&optional (out *standard-output*)) (dolist (entry (cdr *entries*)) (setf (pend entry) t)) (if (streamp out) (do-entries out) (with-open-file (stream out :direction :output) (do-entries stream)))) (defun do-entries (s) (format s "~&Doing ~A pending test~:P ~ of ~A tests total.~%" (count t (cdr *entries*) :key #'pend) (length (cdr *entries*))) (dolist (entry (cdr *entries*)) (when (pend entry) (format s "~@[~<~%~:; ~:@(~S~)~>~]" (do-entry entry s)))) (let ((pending (pending-tests)) (expected-table (make-hash-table :test #'equal))) (dolist (ex *expected-failures*) (setf (gethash ex expected-table) t)) (let ((new-failures (loop for pend in pending unless (gethash pend expected-table) collect pend))) (if (null pending) (format s "~&No tests failed.") (progn (format s "~&~A out of ~A ~ total tests failed: ~ ~:@(~{~<~% ~1:;~S~>~ ~^, ~}~)." (length pending) (length (cdr *entries*)) pending) (if (null new-failures) (format s "~&No unexpected failures.") (when *expected-failures* (format s "~&~A unexpected failures: ~ ~:@(~{~<~% ~1:;~S~>~ ~^, ~}~)." (length new-failures) new-failures))) )) (finish-output s) (null pending)))) abcl-src-1.9.0/contrib/named-readtables/test/src/cruft.lisp0100644 0000000 0000000 00000042037 14202767264 022370 0ustar000000000 0000000 ;;;; ;;;; Copyright (c) 2008 - 2009 Tobias C. Rittweiler ;;;; ;;;; All rights reserved. ;;;; ;;;; See LICENSE for details. ;;;; (in-package :editor-hints.named-readtables) (defmacro define-cruft (name lambda-list &body (docstring . alternatives)) (assert (typep docstring 'string) (docstring) "Docstring missing!") (assert (not (null alternatives))) `(progn (declaim (inline ,name)) (defun ,name ,lambda-list ,docstring ,(first alternatives)))) (eval-when (:compile-toplevel :execute) #+sbcl (when (find-symbol "ASSERT-NOT-STANDARD-READTABLE" (find-package "SB-IMPL")) (pushnew :sbcl+safe-standard-readtable *features*))) ;;;;; Implementation-dependent cruft ;;;; Mapping between a readtable object and its readtable-name. (defvar *readtable-names* (make-hash-table :test 'eq)) (define-cruft %associate-readtable-with-name (name readtable) "Associate READTABLE with NAME for READTABLE-NAME to work." #+ :common-lisp (setf (gethash readtable *readtable-names*) name)) (define-cruft %unassociate-readtable-from-name (name readtable) "Remove the association between READTABLE and NAME." #+ :common-lisp (progn (assert (eq name (gethash readtable *readtable-names*))) (remhash readtable *readtable-names*))) (define-cruft %readtable-name (readtable) "Return the name associated with READTABLE." #+ :common-lisp (values (gethash readtable *readtable-names*))) (define-cruft %list-all-readtable-names () "Return a list of all available readtable names." #+ :common-lisp (list* :standard :current (loop for name being each hash-value of *readtable-names* collect name))) ;;;; Mapping between a readtable-name and the actual readtable object. ;;; On Allegro we reuse their named-readtable support so we work ;;; nicely on their infrastructure. #-allegro (defvar *named-readtables* (make-hash-table :test 'eq)) #+allegro (defun readtable-name-for-allegro (symbol) (multiple-value-bind (kwd status) (if (keywordp symbol) (values symbol nil) ;; Kludge: ACL uses keywords to name readtables, we allow ;; arbitrary symbols. (intern (format nil "~A.~A" (package-name (symbol-package symbol)) (symbol-name symbol)) :keyword)) (prog1 kwd (assert (or (not status) (get kwd 'named-readtable-designator))) (setf (get kwd 'named-readtable-designator) t)))) (define-cruft %associate-name-with-readtable (name readtable) "Associate NAME with READTABLE for FIND-READTABLE to work." #+ :allegro (setf (excl:named-readtable (readtable-name-for-allegro name)) readtable) #+ :common-lisp (setf (gethash name *named-readtables*) readtable)) (define-cruft %unassociate-name-from-readtable (name readtable) "Remove the association between NAME and READTABLE" #+ :allegro (let ((n (readtable-name-for-allegro name))) (assert (eq readtable (excl:named-readtable n))) (setf (excl:named-readtable n) nil)) #+ :common-lisp (progn (assert (eq readtable (gethash name *named-readtables*))) (remhash name *named-readtables*))) (define-cruft %find-readtable (name) "Return the readtable named NAME." #+ :allegro (excl:named-readtable (readtable-name-for-allegro name) nil) #+ :common-lisp (values (gethash name *named-readtables* nil))) ;;;; Reader-macro related predicates ;;; CLISP creates new function objects for standard reader macros on ;;; each readtable copy. (define-cruft function= (fn1 fn2) "Are reader-macro function-designators FN1 and FN2 the same?" #+ :clisp (let* ((fn1 (ensure-function fn1)) (fn2 (ensure-function fn2)) (n1 (system::function-name fn1)) (n2 (system::function-name fn2))) (if (and (eq n1 :lambda) (eq n2 :lambda)) (eq fn1 fn2) (equal n1 n2))) #+ :sbcl (let ((fn1 (ensure-function fn1)) (fn2 (ensure-function fn2))) (or (eq fn1 fn2) ;; After SBCL 1.1.18, for dispatch macro characters ;; GET-MACRO-CHARACTER returns closures whose name is: ;; ;; (LAMBDA (STREAM CHAR) :IN SB-IMPL::%MAKE-DISPATCH-MACRO-CHAR) ;; ;; Treat all these closures equivalent. (flet ((internal-dispatch-macro-closure-name-p (name) (find "SB-IMPL::%MAKE-DISPATCH-MACRO-CHAR" name :key #'prin1-to-string :test #'string-equal))) (let ((n1 (sb-impl::%fun-name fn1)) (n2 (sb-impl::%fun-name fn2))) (and (listp n1) (listp n2) (internal-dispatch-macro-closure-name-p n1) (internal-dispatch-macro-closure-name-p n2)))))) #+ :common-lisp (eq (ensure-function fn1) (ensure-function fn2))) ;;; CLISP will incorrectly fold the call to G-D-M-C away ;;; if not declared inline. (define-cruft dispatch-macro-char-p (char rt) "Is CHAR a dispatch macro character in RT?" #+ :common-lisp (handler-case (locally #+clisp (declare (notinline get-dispatch-macro-character)) (get-dispatch-macro-character char #\x rt) t) (error () nil))) ;; (defun macro-char-p (char rt) ;; (let ((reader-fn (%get-macro-character char rt))) ;; (and reader-fn t))) ;; (defun standard-macro-char-p (char rt) ;; (multiple-value-bind (rt-fn rt-flag) (get-macro-character char rt) ;; (multiple-value-bind (std-fn std-flag) (get-macro-character char *standard-readtable*) ;; (and (eq rt-fn std-fn) ;; (eq rt-flag std-flag))))) ;; (defun standard-dispatch-macro-char-p (disp-char sub-char rt) ;; (flet ((non-terminating-p (ch rt) (nth-value 1 (get-macro-character ch rt)))) ;; (and (eq (non-terminating-p disp-char rt) ;; (non-terminating-p disp-char *standard-readtable*)) ;; (eq (get-dispatch-macro-character disp-char sub-char rt) ;; (get-dispatch-macro-character disp-char sub-char *standard-readtable*))))) ;;;; Readtables Iterators (defmacro with-readtable-iterator ((name readtable) &body body) (let ((it (gensym))) `(let ((,it (%make-readtable-iterator ,readtable))) (macrolet ((,name () `(funcall ,',it))) ,@body)))) #+sbcl (defun %make-readtable-iterator (readtable) (let ((char-macro-array (sb-impl::character-macro-array readtable)) (char-macro-ht (sb-impl::character-macro-hash-table readtable)) (dispatch-tables (sb-impl::dispatch-tables readtable)) (char-code 0)) (with-hash-table-iterator (ht-iterator char-macro-ht) (labels ((grovel-base-chars () (if (>= char-code sb-int:base-char-code-limit) (grovel-unicode-chars) (let ((reader-fn (svref char-macro-array char-code)) (char (code-char (shiftf char-code (1+ char-code))))) (if reader-fn (yield char) (grovel-base-chars))))) (grovel-unicode-chars () (multiple-value-bind (more? char) (ht-iterator) (if (not more?) (values nil nil nil nil nil) (yield char)))) (yield (char) (let ((disp-fn (get-macro-character char readtable)) (disp-ht)) (cond ((setq disp-ht (cdr (assoc char dispatch-tables))) (let ((sub-char-alist)) (maphash (lambda (k v) (push (cons k v) sub-char-alist)) disp-ht) (values t char disp-fn t sub-char-alist))) (t (values t char disp-fn nil nil)))))) #'grovel-base-chars)))) #+clozure (defun %make-readtable-iterator (readtable) (flet ((ensure-alist (x) #.`(etypecase x (list x) ,@(uiop:if-let (sv (uiop:find-symbol* '#:sparse-vector :ccl nil)) `((,sv (let ((table (uiop:symbol-call :ccl '#:sparse-vector-table x))) (uiop:while-collecting (c) (loop for i below (length table) do (uiop:if-let ((v (svref table i))) (loop with i8 = (ash i 8) for j below (length v) do (uiop:if-let ((datum (svref v j))) (c (cons (code-char (+ i8 j)) datum)))))))))))))) (let ((char-macros (ensure-alist (#.(or (uiop:find-symbol* '#:rdtab.macros :ccl nil) (uiop:find-symbol* '#:rdtab.alist :ccl)) readtable)))) (lambda () (if char-macros (destructuring-bind (char . defn) (pop char-macros) (if (consp defn) (values t char (car defn) t (ensure-alist (cdr defn))) (values t char defn nil nil))) (values nil nil nil nil nil)))))) ;;; Written on ACL 8.0. #+allegro (defun %make-readtable-iterator (readtable) (declare (optimize speed)) ; for TCO (check-type readtable readtable) (let* ((macro-table (first (excl::readtable-macro-table readtable))) (dispatch-tables (excl::readtable-dispatch-tables readtable)) (table-length (length macro-table)) (idx 0)) (labels ((grovel-macro-chars () (if (>= idx table-length) (grovel-dispatch-chars) (let ((read-fn (svref macro-table idx)) (oidx idx)) (incf idx) (if (or (eq read-fn #'excl::read-token) (eq read-fn #'excl::read-dispatch-char) (eq read-fn #'excl::undefined-macro-char)) (grovel-macro-chars) (values t (code-char oidx) read-fn nil nil))))) (grovel-dispatch-chars () (if (null dispatch-tables) (values nil nil nil nil nil) (destructuring-bind (disp-char sub-char-table) (first dispatch-tables) (setf dispatch-tables (rest dispatch-tables)) ;;; Kludge. We can't fully clear dispatch tables ;;; in %CLEAR-READTABLE. (when (eq (svref macro-table (char-code disp-char)) #'excl::read-dispatch-char) (values t disp-char (svref macro-table (char-code disp-char)) t (loop for subch-fn across sub-char-table for subch-code from 0 when subch-fn collect (cons (code-char subch-code) subch-fn)))))))) #'grovel-macro-chars))) #-(or sbcl clozure allegro) (eval-when (:compile-toplevel) (let ((*print-pretty* t)) (simple-style-warn "~&~@< ~@;~A has not been ported to ~A. ~ We fall back to a portable implementation of readtable iterators. ~ This implementation has to grovel through all available characters. ~ On Unicode-aware implementations this may come with some costs.~@:>" (package-name '#.*package*) (lisp-implementation-type)))) #-(or sbcl clozure allegro) (defun %make-readtable-iterator (readtable) (check-type readtable readtable) (let ((char-code 0)) #'(lambda () (prog () :GROVEL (when (< char-code char-code-limit) (let ((char (code-char char-code))) (incf char-code) (when (not char) (go :GROVEL)) (let ((fn (get-macro-character char readtable))) (when (not fn) (go :GROVEL)) (multiple-value-bind (disp? alist) (handler-case ; grovel dispatch macro characters. (values t ;; Only grovel upper case characters to ;; avoid duplicates. (loop for code from 0 below char-code-limit for subchar = (non-lowercase-code-char code) for disp-fn = (and subchar (get-dispatch-macro-character char subchar readtable)) when disp-fn collect (cons subchar disp-fn))) (error () nil)) (return (values t char fn disp? alist)))))))))) #-(or sbcl clozure allegro) (defun non-lowercase-code-char (code) (let ((ch (code-char code))) (when (and ch (or (not (alpha-char-p ch)) (upper-case-p ch))) ch))) (defmacro do-readtable ((entry-designator readtable &optional result) &body body) "Iterate through a readtable's macro characters, and dispatch macro characters." (destructuring-bind (char &optional reader-fn non-terminating-p disp? table) (if (symbolp entry-designator) (list entry-designator) entry-designator) (let ((iter (gensym "ITER+")) (more? (gensym "MORE?+")) (rt (gensym "READTABLE+"))) `(let ((,rt ,readtable)) (with-readtable-iterator (,iter ,rt) (loop (multiple-value-bind (,more? ,char ,@(when reader-fn (list reader-fn)) ,@(when disp? (list disp?)) ,@(when table (list table))) (,iter) (unless ,more? (return ,result)) (let ,(when non-terminating-p ;; FIXME: N-T-P should be incorporated in iterators. `((,non-terminating-p (nth-value 1 (get-macro-character ,char ,rt))))) ,@body)))))))) ;;;; Misc ;;; This should return an implementation's actual standard readtable ;;; object only if the implementation makes the effort to guard against ;;; modification of that object. Otherwise it should better return a ;;; copy. (define-cruft %standard-readtable () "Return the standard readtable." #+ :sbcl+safe-standard-readtable sb-impl::*standard-readtable* #+ :common-lisp (copy-readtable nil)) ;;; On SBCL, SET-SYNTAX-FROM-CHAR does not get rid of a ;;; readtable's dispatch table properly. ;;; Same goes for Allegro but that does not seem to provide a ;;; setter for their readtable's dispatch tables. Hence this ugly ;;; workaround. (define-cruft %clear-readtable (readtable) "Make all macro characters in READTABLE be constituents." #+ :sbcl (prog1 readtable (do-readtable (char readtable) (set-syntax-from-char char #\A readtable)) (setf (sb-impl::dispatch-tables readtable) nil)) #+ :allegro (prog1 readtable (do-readtable (char readtable) (set-syntax-from-char char #\A readtable)) (let ((dispatch-tables (excl::readtable-dispatch-tables readtable))) (setf (cdr dispatch-tables) nil) (setf (caar dispatch-tables) #\Backspace) (setf (cadar dispatch-tables) (fill (cadar dispatch-tables) nil)))) #+ :common-lisp (do-readtable (char readtable readtable) (set-syntax-from-char char #\A readtable))) ;;; See Clozure Trac Ticket 601. This is supposed to be removed at ;;; some point in the future. (define-cruft %get-dispatch-macro-character (char subchar rt) "Ensure ANSI behaviour for GET-DISPATCH-MACRO-CHARACTER." #+ :ccl (ignore-errors (get-dispatch-macro-character char subchar rt)) #+ :common-lisp (get-dispatch-macro-character char subchar rt)) ;;; Allegro stores READ-TOKEN as reader macro function of each ;;; constituent character. (define-cruft %get-macro-character (char rt) "Ensure ANSI behaviour for GET-MACRO-CHARACTER." #+ :allegro (let ((fn (get-macro-character char rt))) (cond ((not fn) nil) ((function= fn #'excl::read-token) nil) (t fn))) #+ :common-lisp (get-macro-character char rt)) ;;;; Specialized PRINT-OBJECT for named readtables. ;;; As per #19 in CLHS 11.1.2.1.2 defining a method for PRINT-OBJECT ;;; that specializes on READTABLE is actually forbidden. It's quite ;;; likely to work (modulo package-locks) on most implementations, ;;; though. ;;; We don't need this on Allegro CL's as we hook into their ;;; named-readtable facility, and they provide such a method already. #-allegro (without-package-lock (:common-lisp #+lispworks :implementation) (defmethod print-object :around ((rt readtable) stream) (let ((name (readtable-name rt))) (if name (print-unreadable-object (rt stream :type nil :identity t) (format stream "~A ~S" :named-readtable name)) (call-next-method))))) abcl-src-1.9.0/contrib/named-readtables/test/src/define-api.lisp0100644 0000000 0000000 00000005543 14202767264 023247 0ustar000000000 0000000 (in-package :named-readtables) (defmacro define-api (name lambda-list type-list &body body) (flet ((parse-type-list (type-list) (let ((pos (position '=> type-list))) (assert pos () "You forgot to specify return type (`=>' missing.)") (values (subseq type-list 0 pos) `(values ,@(nthcdr (1+ pos) type-list) &optional))))) (multiple-value-bind (body decls docstring) (parse-body body :documentation t :whole `(define-api ,name)) (multiple-value-bind (arg-typespec value-typespec) (parse-type-list type-list) (multiple-value-bind (reqs opts rest keys) (parse-ordinary-lambda-list lambda-list) (declare (ignorable reqs opts rest keys)) `(progn (declaim (ftype (function ,arg-typespec ,value-typespec) ,name)) (locally ;;; Muffle the annoying "&OPTIONAL and &KEY found in ;;; the same lambda list" style-warning #+sbcl (declare (sb-ext:muffle-conditions style-warning)) (defun ,name ,lambda-list ,docstring #+sbcl (declare (sb-ext:unmuffle-conditions style-warning)) ,@decls ;; SBCL will interpret the ftype declaration as ;; assertion and will insert type checks for us. #-sbcl (progn ;; CHECK-TYPE required parameters ,@(loop for req-arg in reqs for req-type = (pop type-list) do (assert req-type) collect `(check-type ,req-arg ,req-type)) ;; CHECK-TYPE optional parameters ,@(loop initially (assert (or (null opts) (eq (pop type-list) '&optional))) for (opt-arg . nil) in opts for opt-type = (pop type-list) do (assert opt-type) collect `(check-type ,opt-arg ,opt-type)) ;; CHECK-TYPE rest parameter ,@(when rest (assert (eq (pop type-list) '&rest)) (let ((rest-type (pop type-list))) (assert rest-type) `((dolist (x ,rest) (check-type x ,rest-type))))) ;; CHECK-TYPE key parameters ,@(loop initially (assert (or (null keys) (eq (pop type-list) '&key))) for ((keyword key-arg) . nil) in keys for (nil key-type) = (find keyword type-list :key #'car) collect `(check-type ,key-arg ,key-type))) ,@body)))))))) abcl-src-1.9.0/contrib/named-readtables/test/src/doc.lisp0100644 0000000 0000000 00000021117 14202767264 022006 0ustar000000000 0000000 (in-package :named-readtables) (eval-when (:compile-toplevel :load-toplevel :execute) (use-package :mgl-pax)) (defsection @named-readtables-manual (:title "Named Readtables Manual") (named-readtables asdf:system) (@named-readtables-introduction section) (@named-readtables-overview section) (@named-readtables-reference section)) (defsection @named-readtables-introduction (:title "Introduction") "Named-Readtables is a library that provides a namespace for readtables akin to the already-existing namespace of packages. In particular: * you can associate readtables with names, and retrieve readtables by names; * you can associate source files with readtable names, and be sure that the right readtable is active when compiling/loading the file; * similiarly, your development environment now has a chance to automatically determine what readtable should be active while processing source forms on interactive commands. (E.g. think of `C-c C-c` in Slime (yet to be done)) It follows that Named-Readtables is a facility for using readtables in a localized way. Additionally, it also attempts to become a facility for using readtables in a _modular_ way. In particular: * it provides a macro to specify the content of a readtable at a glance; * it makes it possible to use multiple inheritance between readtables." (@named-readtables-links section) (@named-readtables-acknowledgements section)) (defsection @named-readtables-links (:title "Links") "Here is the [official repository][named-readtables-repo] and the [HTML documentation][named-readtables-doc] for the latest version. [named-readtables-repo]: https://github.com/melisgl/named-readtables [named-readtables-doc]: http://melisgl.github.io/mgl-pax-world/named-readtables-manual.html") (defsection @named-readtables-acknowledgements (:title "Acknowledgements") "Thanks to Robert Goldman for making me want to write this library. Thanks to Stephen Compall, Ariel Badichi, David Lichteblau, Bart Botta, David Crawford, and Pascal Costanza for being early adopters, providing comments and bugfixes.") (defsection @named-readtables-overview (:title "Overview") (@named-readtables-api-notes section) (@named-readtables-api-idiosyncrasies section) (@named-readtables-preregistered section) (@named-readtables-examples section)) (defsection @named-readtables-api-notes (:title "Notes on the API" :export nil) "The API heavily imitates the API of packages. This has the nice property that any experienced Common Lisper will take it up without effort. DEFREADTABLE - DEFPACKAGE IN-READTABLE - IN-PACKAGE MERGE-READTABLES-INTO - USE-PACKAGE MAKE-READTABLE - MAKE-PACKAGE UNREGISTER-READTABLE - DELETE-PACKAGE RENAME-READTABLE - RENAME-PACKAGE FIND-READTABLE - FIND-PACKAGE READTABLE-NAME - PACKAGE-NAME LIST-ALL-NAMED-READTABLES - LIST-ALL-PACKAGES") (defsection @named-readtables-api-idiosyncrasies (:title "Important API idiosyncrasies" :export nil) "There are three major differences between the API of Named-Readtables, and the API of packages. 1. Readtable names are symbols not strings. Time has shown that the fact that packages are named by strings causes severe headache because of the potential of package names colliding with each other. Hence, readtables are named by symbols lest to make the situation worse than it already is. Consequently, readtables named `CL-ORACLE:SQL-SYNTAX` and `CL-MYSQL:SQL-SYNTAX` can happily coexist next to each other. Or, taken to an extreme, `SCHEME:SYNTAX` and `ELISP:SYNTAX`. If, for example to duly signify the importance of your cool readtable hack, you really think it deserves a global name, you can always resort to keywords. 2. The inheritance is resolved statically, not dynamically. A package that uses another package will have access to all the other package's exported symbols, even to those that will be added after its definition. I.e. the inheritance is resolved at run-time, that is dynamically. Unfortunately, we cannot do the same for readtables in a portable manner. Therefore, we do not talk about \"using\" another readtable but about \"merging\" the other readtable's definition into the readtable we are going to define. I.e. the inheritance is resolved once at definition time, that is statically. (Such merging can more or less be implemented portably albeit at a certain cost. Most of the time, this cost manifests itself at the time a readtable is defined, i.e. once at compile-time, so it may not bother you. Nonetheless, we provide extra support for Sbcl, ClozureCL, and AllegroCL at the moment. Patches for your implementation of choice are welcome, of course.) 3. DEFREADTABLE does not have compile-time effects. If you define a package via DEFPACKAGE, you can make that package the currently active package for the subsequent compilation of the same file via IN-PACKAGE. The same is, however, not true for DEFREADTABLE and IN-READTABLE for the following reason: It's unlikely that the need for special reader-macros arises for a problem which can be solved in just one file. Most often, you're going to define the reader macro functions, and set up the corresponding readtable in an extra file. If DEFREADTABLE had compile-time effects, you'd have to wrap each definition of a reader-macro function in an EVAL-WHEN to make its definition available at compile-time. Because that's simply not the common case, DEFREADTABLE does not have a compile-time effect. If you want to use a readtable within the same file as its definition, wrap the DEFREADTABLE and the reader-macro function definitions in an explicit EVAL-WHEN.") (defsection @named-readtables-preregistered (:title "Preregistered Readtables" :export nil) "- NIL, :STANDARD, and :COMMON-LISP designate the _standard readtable_. - :MODERN designates a _case-preserving_ _standard-readtable_. - :CURRENT designates the _current readtable_.") (defsection @named-readtables-examples (:title "Examples" :export nil) "```commonlisp (defreadtable elisp:syntax (:merge :standard) (:macro-char #\\? #'elisp::read-character-literal t) (:macro-char #\\[ #'elisp::read-vector-literal t) ... (:case :preserve)) (defreadtable scheme:syntax (:merge :standard) (:macro-char #\\[ #'(lambda (stream char) (read-delimited-list #\\] stream))) (:macro-char #\\# :dispatch) (:dispatch-macro-char #\\# #\\t #'scheme::read-#t) (:dispatch-macro-char #\\# #\\f #'scheme::read-#f) ... (:case :preserve)) (in-readtable elisp:syntax) ... (in-readtable scheme:syntax) ... ```") (defsection @named-readtables-reference (:title "Reference") (defreadtable macro) (in-readtable macro) (make-readtable function) (merge-readtables-into function) (find-readtable function) (ensure-readtable function) (rename-readtable function) (readtable-name function) (register-readtable function) (unregister-readtable function) (copy-named-readtable function) (list-all-named-readtables function) (named-readtable-designator type) (reader-macro-conflict condition) (readtable-does-already-exist condition) (readtable-does-not-exist condition)) ;;;; Generating own docs (defun update-readmes () (with-open-file (stream (asdf:system-relative-pathname :named-readtables "README.md") :direction :output :if-does-not-exist :create :if-exists :supersede) (document @named-readtables-manual :stream stream) (print-markdown-footer stream)) (with-open-file (stream (asdf:system-relative-pathname :named-readtables "README") :direction :output :if-does-not-exist :create :if-exists :supersede) (describe @named-readtables-manual stream) (print-markdown-footer stream))) (defun print-markdown-footer (stream) (format stream "~%* * *~%") (format stream "###### \\[generated by ~ [MGL-PAX](https://github.com/melisgl/mgl-pax)\\]~%")) #| (update-readmes) |# abcl-src-1.9.0/contrib/named-readtables/test/src/named-readtables.lisp0100644 0000000 0000000 00000053675 14202767264 024447 0ustar000000000 0000000 ;;;; -*- Mode:Lisp -*- ;;;; ;;;; Copyright (c) 2007 - 2009 Tobias C. Rittweiler ;;;; Copyright (c) 2007, Robert P. Goldman and SIFT, LLC ;;;; ;;;; All rights reserved. ;;;; ;;;; See LICENSE for details. ;;;; (in-package :editor-hints.named-readtables) ;;; ;;; ``This is enough of a foothold to implement a more elaborate ;;; facility for using readtables in a localized way.'' ;;; ;;; (X3J13 Cleanup Issue IN-SYNTAX) ;;; ;;;;;; DEFREADTABLE &c. (defmacro defreadtable (name &body options) "Define a new named readtable, whose name is given by the symbol NAME. Or, if a readtable is already registered under that name, redefine that one. The readtable can be populated using the following OPTIONS: - `(:MERGE READTABLE-DESIGNATORS+)` Merge the readtables designated into the new readtable being defined as per MERGE-READTABLES-INTO. If no :MERGE clause is given, an empty readtable is used. See MAKE-READTABLE. - `(:FUSE READTABLE-DESIGNATORS+)` Like :MERGE except: Error conditions of type READER-MACRO-CONFLICT that are signaled during the merge operation will be silently _continued_. It follows that reader macros in earlier entries will be overwritten by later ones. For backward compatibility, :FUZE is accepted as an alias of :FUSE. - `(:DISPATCH-MACRO-CHAR MACRO-CHAR SUB-CHAR FUNCTION)` Define a new sub character `SUB-CHAR` for the dispatching macro character `MACRO-CHAR`, per SET-DISPATCH-MACRO-CHARACTER. You probably have to define `MACRO-CHAR` as a dispatching macro character by the following option first. - `(:MACRO-CHAR MACRO-CHAR FUNCTION [NON-TERMINATING-P])` Define a new macro character in the readtable, per SET-MACRO-CHARACTER. If `FUNCTION` is the keyword :DISPATCH, `MACRO-CHAR` is made a dispatching macro character, per MAKE-DISPATCH-MACRO-CHARACTER. - `(:SYNTAX-FROM FROM-READTABLE-DESIGNATOR FROM-CHAR TO-CHAR)` Set the character syntax of TO-CHAR in the readtable being defined to the same syntax as FROM-CHAR as per SET-SYNTAX-FROM-CHAR. - `(:CASE CASE-MODE)` Defines the _case sensitivity mode_ of the resulting readtable. Any number of option clauses may appear. The options are grouped by their type, but in each group the order the options appeared textually is preserved. The following groups exist and are executed in the following order: :MERGE and :FUSE (one group), :CASE, :MACRO-CHAR and :DISPATCH-MACRO-CHAR (one group), finally :SYNTAX-FROM. Notes: The readtable is defined at load-time. If you want to have it available at compilation time -- say to use its reader-macros in the same file as its definition -- you have to wrap the DEFREADTABLE form in an explicit EVAL-WHEN. On redefinition, the target readtable is made empty first before it's refilled according to the clauses. NIL, :STANDARD, :COMMON-LISP, :MODERN, and :CURRENT are preregistered readtable names." (check-type name symbol) (when (reserved-readtable-name-p name) (error "~A is the designator for a predefined readtable. ~ Not acceptable as a user-specified readtable name." name)) (flet ((process-option (option var) (destructure-case option ((:merge &rest readtable-designators) `(merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) readtable-designators))) ((:fuse &rest readtable-designators) `(handler-bind ((reader-macro-conflict #'continue)) (merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) readtable-designators)))) ;; alias for :FUSE ((:fuze &rest readtable-designators) `(handler-bind ((reader-macro-conflict #'continue)) (merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) readtable-designators)))) ((:dispatch-macro-char disp-char sub-char function) `(set-dispatch-macro-character ,disp-char ,sub-char ,function ,var)) ((:macro-char char function &optional non-terminating-p) (if (eq function :dispatch) `(make-dispatch-macro-character ,char ,non-terminating-p ,var) `(set-macro-character ,char ,function ,non-terminating-p ,var))) ((:syntax-from from-rt-designator from-char to-char) `(set-syntax-from-char ,to-char ,from-char ,var (find-readtable ,from-rt-designator))) ((:case mode) `(setf (readtable-case ,var) ,mode)))) (remove-clauses (clauses options) (setq clauses (if (listp clauses) clauses (list clauses))) (remove-if-not #'(lambda (x) (member x clauses)) options :key #'first))) (let* ((merge-clauses (remove-clauses '(:merge :fuze :fuse) options)) (case-clauses (remove-clauses :case options)) (macro-clauses (remove-clauses '(:macro-char :dispatch-macro-char) options)) (syntax-clauses (remove-clauses :syntax-from options)) (other-clauses (set-difference options (append merge-clauses case-clauses macro-clauses syntax-clauses)))) (cond ((not (null other-clauses)) (error "Bogus DEFREADTABLE clauses: ~/PPRINT-LINEAR/" other-clauses)) (t `(eval-when (:load-toplevel :execute) ;; The (FIND-READTABLE ...) isqrt important for proper ;; redefinition semantics, as redefining has to modify the ;; already existing readtable object. (let ((readtable (find-readtable ',name))) (cond ((not readtable) (setq readtable (make-readtable ',name))) (t (setq readtable (%clear-readtable readtable)) (simple-style-warn "Overwriting already existing readtable ~S." readtable))) ,@(loop for option in merge-clauses collect (process-option option 'readtable)) ,@(loop for option in case-clauses collect (process-option option 'readtable)) ,@(loop for option in macro-clauses collect (process-option option 'readtable)) ,@(loop for option in syntax-clauses collect (process-option option 'readtable)) readtable))))))) (defmacro in-readtable (name) "Set *READTABLE* to the readtable referred to by the symbol NAME." (check-type name symbol) `(eval-when (:compile-toplevel :load-toplevel :execute) ;; NB. The :LOAD-TOPLEVEL is needed for cases like (DEFVAR *FOO* ;; (GET-MACRO-CHARACTER #\")) (setf *readtable* (ensure-readtable ',name)) (when (find-package :swank) (%frob-swank-readtable-alist *package* *readtable*)))) ;;; KLUDGE: [interim solution] ;;; ;;; We need support for this in Slime itself, because we want IN-READTABLE ;;; to work on a per-file basis, and not on a per-package basis. ;;; (defun %frob-swank-readtable-alist (package readtable) (let ((readtable-alist (find-symbol (string '#:*readtable-alist*) (find-package :swank)))) (when (boundp readtable-alist) (pushnew (cons (package-name package) readtable) (symbol-value readtable-alist) :test #'(lambda (entry1 entry2) (destructuring-bind (pkg-name1 . rt1) entry1 (destructuring-bind (pkg-name2 . rt2) entry2 (and (string= pkg-name1 pkg-name2) (eq rt1 rt2))))))))) (deftype readtable-designator () `(or null readtable)) (deftype named-readtable-designator () "Either a symbol or a readtable itself." `(or readtable-designator symbol)) ;;;;; Compiler macros ;;; Since the :STANDARD readtable is interned, and we can't enforce ;;; its immutability, we signal a style-warning for suspicious uses ;;; that may result in strange behaviour: ;;; Modifying the standard readtable would, obviously, lead to a ;;; propagation of this change to all places which use the :STANDARD ;;; readtable (and thus rendering this readtable to be non-standard, ;;; in fact.) (eval-when (:compile-toplevel :load-toplevel :execute) (defun constant-standard-readtable-expression-p (thing) (or (null thing) (eq thing :standard) (and (consp thing) (find thing '((find-readtable nil) (find-readtable :standard) (ensure-readtable nil) (ensure-readtable :standard)) :test #'equal)))) (defun signal-suspicious-registration-warning (name-expr readtable-expr) (when (constant-standard-readtable-expression-p readtable-expr) (simple-style-warn "Caution: ~~% ~S" (list name-expr name-expr) readtable-expr)))) (define-compiler-macro register-readtable (&whole form name readtable) (signal-suspicious-registration-warning name readtable) form) (define-compiler-macro ensure-readtable (&whole form name &optional (default nil default-p)) (when default-p (signal-suspicious-registration-warning name default)) form) (declaim (special *standard-readtable* *empty-readtable*)) (define-api make-readtable (&optional (name nil name-supplied-p) &key merge) (&optional named-readtable-designator &key (:merge list) => readtable) "Creates and returns a new readtable under the specified NAME. MERGE takes a list of NAMED-READTABLE-DESIGNATORS and specifies the readtables the new readtable is created from. (See the :MERGE clause of DEFREADTABLE for details.) If MERGE is NIL, an empty readtable is used instead. If NAME is not given, an anonymous empty readtable is returned. Notes: An empty readtable is a readtable where each character's syntax is the same as in the _standard readtable_ except that each macro character has been made a constituent. Basically: whitespace stays whitespace, everything else is constituent." (cond ((not name-supplied-p) (copy-readtable *empty-readtable*)) ((reserved-readtable-name-p name) (error "~A is the designator for a predefined readtable. ~ Not acceptable as a user-specified readtable name." name)) ((let ((rt (find-readtable name))) (and rt (prog1 nil (cerror "Overwrite existing entry." 'readtable-does-already-exist :readtable-name name) ;; Explicitly unregister to make sure that we do ;; not hold on of any reference to RT. (unregister-readtable rt))))) (t (let ((result (apply #'merge-readtables-into ;; The first readtable specified in ;; the :merge list is taken as the ;; basis for all subsequent ;; (destructive!) modifications (and ;; hence it's copied.) (copy-readtable (if merge (ensure-readtable (first merge)) *empty-readtable*)) (rest merge)))) (register-readtable name result))))) (define-api rename-readtable (old-name new-name) (named-readtable-designator symbol => readtable) "Replaces the associated name of the readtable designated by OLD-NAME with NEW-NAME. If a readtable is already registered under NEW-NAME, an error of type READTABLE-DOES-ALREADY-EXIST is signaled." (when (find-readtable new-name) (cerror "Overwrite existing entry." 'readtable-does-already-exist :readtable-name new-name)) (let* ((readtable (ensure-readtable old-name)) (readtable-name (readtable-name readtable))) ;; We use the internal functions directly to omit repeated ;; type-checking. (%unassociate-name-from-readtable readtable-name readtable) (%unassociate-readtable-from-name readtable-name readtable) (%associate-name-with-readtable new-name readtable) (%associate-readtable-with-name new-name readtable) readtable)) (define-api merge-readtables-into (result-readtable &rest named-readtables) (named-readtable-designator &rest named-readtable-designator => readtable) "Copy the contents of each readtable in NAMED-READTABLES into RESULT-READTABLE. If a macro character appears in more than one of the readtables, i.e. if a conflict is discovered during the merge, an error of type READER-MACRO-CONFLICT is signaled." (flet ((merge-into (to from) (do-readtable ((char reader-fn non-terminating-p disp? table) from) (check-reader-macro-conflict from to char) (cond ((not disp?) (set-macro-character char reader-fn non-terminating-p to)) (t (ensure-dispatch-macro-character char non-terminating-p to) (loop for (subchar . subfn) in table do (check-reader-macro-conflict from to char subchar) (set-dispatch-macro-character char subchar subfn to))))) to)) (let ((result-table (ensure-readtable result-readtable))) (dolist (table (mapcar #'ensure-readtable named-readtables)) (merge-into result-table table)) result-table))) (defun ensure-dispatch-macro-character (char &optional non-terminating-p (readtable *readtable*)) (if (dispatch-macro-char-p char readtable) t (make-dispatch-macro-character char non-terminating-p readtable))) (define-api copy-named-readtable (named-readtable) (named-readtable-designator => readtable) "Like COPY-READTABLE but takes a NAMED-READTABLE-DESIGNATOR as argument." (copy-readtable (ensure-readtable named-readtable))) (define-api list-all-named-readtables () (=> list) "Returns a list of all registered readtables. The returned list is guaranteed to be fresh, but may contain duplicates." (mapcar #'ensure-readtable (%list-all-readtable-names))) (define-condition readtable-error (error) ()) (define-condition readtable-does-not-exist (readtable-error) ((readtable-name :initarg :readtable-name :initform (required-argument) :accessor missing-readtable-name :type named-readtable-designator)) (:report (lambda (condition stream) (format stream "A readtable named ~S does not exist." (missing-readtable-name condition))))) (define-condition readtable-does-already-exist (readtable-error) ((readtable-name :initarg :readtable-name :initform (required-argument) :accessor existing-readtable-name :type named-readtable-designator)) (:report (lambda (condition stream) (format stream "A readtable named ~S already exists." (existing-readtable-name condition)))) (:documentation "Continuable.")) (define-condition reader-macro-conflict (readtable-error) ((macro-char :initarg :macro-char :initform (required-argument) :accessor conflicting-macro-char :type character) (sub-char :initarg :sub-char :initform nil :accessor conflicting-dispatch-sub-char :type (or null character)) (from-readtable :initarg :from-readtable :initform (required-argument) :accessor from-readtable :type readtable) (to-readtable :initarg :to-readtable :initform (required-argument) :accessor to-readtable :type readtable)) (:report (lambda (condition stream) (format stream "~@" (conflicting-dispatch-sub-char condition) (conflicting-macro-char condition) (conflicting-dispatch-sub-char condition) (from-readtable condition) (to-readtable condition)))) (:documentation "Continuable. This condition is signaled during the merge process if a reader macro (be it a macro character or the sub character of a dispatch macro character) is present in the both source and the target readtable and the two respective reader macro functions differ.")) (defun check-reader-macro-conflict (from to char &optional subchar) (flet ((conflictp (from-fn to-fn) (assert from-fn () "Bug in readtable iterators or concurrent access?") (and to-fn (not (function= to-fn from-fn))))) (when (if subchar (conflictp (%get-dispatch-macro-character char subchar from) (%get-dispatch-macro-character char subchar to)) (conflictp (%get-macro-character char from) (%get-macro-character char to))) (cerror (format nil "Overwrite ~@C in ~A." char to) 'reader-macro-conflict :from-readtable from :to-readtable to :macro-char char :sub-char subchar)))) ;;; Although there is no way to get at the standard readtable in ;;; Common Lisp (cf. /standard readtable/, CLHS glossary), we make ;;; up the perception of its existence by interning a copy of it. ;;; ;;; We do this for reverse lookup (cf. READTABLE-NAME), i.e. for ;;; ;;; (equal (readtable-name (find-readtable :standard)) "STANDARD") ;;; ;;; holding true. ;;; ;;; We, however, inherit the restriction that the :STANDARD ;;; readtable _must not be modified_ (cf. CLHS 2.1.1.2), although it'd ;;; technically be feasible (as *STANDARD-READTABLE* will contain a ;;; mutable copy of the implementation-internal standard readtable.) ;;; We cannot enforce this restriction without shadowing ;;; CL:SET-MACRO-CHARACTER and CL:SET-DISPATCH-MACRO-FUNCTION which ;;; is out of scope of this library, though. So we just threaten ;;; with nasal demons. ;;; (defvar *standard-readtable* (%standard-readtable)) (defvar *empty-readtable* (%clear-readtable (copy-readtable nil))) (defvar *case-preserving-standard-readtable* (let ((readtable (copy-readtable nil))) (setf (readtable-case readtable) :preserve) readtable)) (defparameter *reserved-readtable-names* '(nil :standard :common-lisp :modern :current)) (defun reserved-readtable-name-p (name) (and (member name *reserved-readtable-names*) t)) ;;; In principle, we could DEFREADTABLE some of these. But we do ;;; reserved readtable lookup seperately, since we can't register a ;;; readtable for :CURRENT anyway. (defun find-reserved-readtable (reserved-name) (cond ((eq reserved-name nil) *standard-readtable*) ((eq reserved-name :standard) *standard-readtable*) ((eq reserved-name :common-lisp) *standard-readtable*) ((eq reserved-name :modern) *case-preserving-standard-readtable*) ((eq reserved-name :current) *readtable*) (t (error "Bug: no such reserved readtable: ~S" reserved-name)))) (define-api find-readtable (name) (named-readtable-designator => (or readtable null)) "Looks for the readtable specified by NAME and returns it if it is found. Returns NIL otherwise." (cond ((readtablep name) name) ((reserved-readtable-name-p name) (find-reserved-readtable name)) ((%find-readtable name)))) ;;; FIXME: This doesn't take a NAMED-READTABLE-DESIGNATOR, but only a ;;; STRING-DESIGNATOR. (When fixing, heed interplay with compiler ;;; macros below.) (defsetf find-readtable register-readtable) (define-api ensure-readtable (name &optional (default nil default-p)) (named-readtable-designator &optional (or named-readtable-designator null) => readtable) "Looks up the readtable specified by NAME and returns it if it's found. If it is not found, it registers the readtable designated by DEFAULT under the name represented by NAME; or if no default argument is given, it signals an error of type READTABLE-DOES-NOT-EXIST instead." (cond ((find-readtable name)) ((not default-p) (error 'readtable-does-not-exist :readtable-name name)) (t (setf (find-readtable name) (ensure-readtable default))))) (define-api register-readtable (name readtable) (symbol readtable => readtable) "Associate READTABLE with NAME. Returns the readtable." (assert (typep name '(not (satisfies reserved-readtable-name-p)))) (%associate-readtable-with-name name readtable) (%associate-name-with-readtable name readtable) readtable) (define-api unregister-readtable (named-readtable) (named-readtable-designator => boolean) "Remove the association of NAMED-READTABLE. Returns T if successfull, NIL otherwise." (let* ((readtable (find-readtable named-readtable)) (readtable-name (and readtable (readtable-name readtable)))) (if (not readtable-name) nil (prog1 t (check-type readtable-name (not (satisfies reserved-readtable-name-p))) (%unassociate-readtable-from-name readtable-name readtable) (%unassociate-name-from-readtable readtable-name readtable))))) (define-api readtable-name (named-readtable) (named-readtable-designator => symbol) "Returns the name of the readtable designated by NAMED-READTABLE, or NIL." (let ((readtable (ensure-readtable named-readtable))) (cond ((%readtable-name readtable)) ((eq readtable *readtable*) :current) ((eq readtable *standard-readtable*) :common-lisp) ((eq readtable *case-preserving-standard-readtable*) :modern) (t nil)))) abcl-src-1.9.0/contrib/named-readtables/test/src/package.lisp0100644 0000000 0000000 00000002347 14202767264 022640 0ustar000000000 0000000 (in-package :common-lisp-user) ;;; This is is basically MGL-PAX:DEFINE-PACKAGE but we don't have it ;;; defined yet. The package variance stuff is because we export ;;; documentation from the NAMED-READTABLES-DOC system. (eval-when (:compile-toplevel :load-toplevel :execute) (locally (declare #+sbcl (sb-ext:muffle-conditions sb-kernel::package-at-variance)) (handler-bind (#+sbcl (sb-kernel::package-at-variance #'muffle-warning)) (defpackage :editor-hints.named-readtables (:use :common-lisp) (:nicknames :named-readtables) (:export #:defreadtable #:in-readtable #:make-readtable #:merge-readtables-into #:find-readtable #:ensure-readtable #:rename-readtable #:readtable-name #:register-readtable #:unregister-readtable #:copy-named-readtable #:list-all-named-readtables ;; Types #:named-readtable-designator ;; Conditions #:reader-macro-conflict #:readtable-does-already-exist #:readtable-does-not-exist) (:documentation "See NAMED-READTABLES:@NAMED-READTABLES-MANUAL."))))) (pushnew :named-readtables *features*) abcl-src-1.9.0/contrib/named-readtables/test/src/utils.lisp0100644 0000000 0000000 00000023445 14202767264 022407 0ustar000000000 0000000 ;;;; ;;;; Copyright (c) 2008 - 2009 Tobias C. Rittweiler ;;;; ;;;; All rights reserved. ;;;; ;;;; See LICENSE for details. ;;;; (in-package :editor-hints.named-readtables) (defmacro without-package-lock ((&rest package-names) &body body) (declare (ignorable package-names)) #+clisp (return-from without-package-lock `(ext:without-package-lock (,@package-names) ,@body)) #+lispworks (return-from without-package-lock `(let ((hcl:*packages-for-warn-on-redefinition* (set-difference hcl:*packages-for-warn-on-redefinition* '(,@package-names) :key (lambda (package-designator) (if (packagep package-designator) (package-name package-designator) package-designator)) :test #'string=))) ,@body)) `(progn ,@body)) ;;; Taken from SWANK (which is Public Domain.) (defmacro destructure-case (value &body patterns) "Dispatch VALUE to one of PATTERNS. A cross between `case' and `destructuring-bind'. The pattern syntax is: ((HEAD . ARGS) . BODY) The list of patterns is searched for a HEAD `eq' to the car of VALUE. If one is found, the BODY is executed with ARGS bound to the corresponding values in the CDR of VALUE." (let ((operator (gensym "op-")) (operands (gensym "rand-")) (tmp (gensym "tmp-"))) `(let* ((,tmp ,value) (,operator (car ,tmp)) (,operands (cdr ,tmp))) (case ,operator ,@(loop for (pattern . body) in patterns collect (if (eq pattern t) `(t ,@body) (destructuring-bind (op &rest rands) pattern `(,op (destructuring-bind ,rands ,operands ,@body))))) ,@(if (eq (caar (last patterns)) t) '() `((t (error "destructure-case failed: ~S" ,tmp)))))))) ;;; Taken from Alexandria (which is Public Domain, or BSD.) (define-condition simple-style-warning (simple-warning style-warning) ()) (defun simple-style-warn (format-control &rest format-args) (warn 'simple-style-warning :format-control format-control :format-arguments format-args)) (define-condition simple-program-error (simple-error program-error) ()) (defun simple-program-error (message &rest args) (error 'simple-program-error :format-control message :format-arguments args)) (defun required-argument (&optional name) "Signals an error for a missing argument of NAME. Intended for use as an initialization form for structure and class-slots, and a default value for required keyword arguments." (error "Required argument ~@[~S ~]missing." name)) (defun ensure-list (list) "If LIST is a list, it is returned. Otherwise returns the list designated by LIST." (if (listp list) list (list list))) (declaim (inline ensure-function)) ; to propagate return type. (declaim (ftype (function (t) (values function &optional)) ensure-function)) (defun ensure-function (function-designator) "Returns the function designated by FUNCTION-DESIGNATOR: if FUNCTION-DESIGNATOR is a function, it is returned, otherwise it must be a function name and its FDEFINITION is returned." (if (functionp function-designator) function-designator (fdefinition function-designator))) (defun parse-body (body &key documentation whole) "Parses BODY into (values remaining-forms declarations doc-string). Documentation strings are recognized only if DOCUMENTATION is true. Syntax errors in body are signalled and WHOLE is used in the signal arguments when given." (let ((doc nil) (decls nil) (current nil)) (tagbody :declarations (setf current (car body)) (when (and documentation (stringp current) (cdr body)) (if doc (error "Too many documentation strings in ~S." (or whole body)) (setf doc (pop body))) (go :declarations)) (when (and (listp current) (eql (first current) 'declare)) (push (pop body) decls) (go :declarations))) (values body (nreverse decls) doc))) (defun parse-ordinary-lambda-list (lambda-list) "Parses an ordinary lambda-list, returning as multiple values: 1. Required parameters. 2. Optional parameter specifications, normalized into form (NAME INIT SUPPLIEDP) where SUPPLIEDP is NIL if not present. 3. Name of the rest parameter, or NIL. 4. Keyword parameter specifications, normalized into form ((KEYWORD-NAME NAME) INIT SUPPLIEDP) where SUPPLIEDP is NIL if not present. 5. Boolean indicating &ALLOW-OTHER-KEYS presence. 6. &AUX parameter specifications, normalized into form (NAME INIT). Signals a PROGRAM-ERROR is the lambda-list is malformed." (let ((state :required) (allow-other-keys nil) (auxp nil) (required nil) (optional nil) (rest nil) (keys nil) (aux nil)) (labels ((simple-program-error (format-string &rest format-args) (error 'simple-program-error :format-control format-string :format-arguments format-args)) (fail (elt) (simple-program-error "Misplaced ~S in ordinary lambda-list:~% ~S" elt lambda-list)) (check-variable (elt what) (unless (and (symbolp elt) (not (constantp elt))) (simple-program-error "Invalid ~A ~S in ordinary lambda-list:~% ~S" what elt lambda-list))) (check-spec (spec what) (destructuring-bind (init suppliedp) spec (declare (ignore init)) (check-variable suppliedp what))) (make-keyword (name) "Interns the string designated by NAME in the KEYWORD package." (intern (string name) :keyword))) (dolist (elt lambda-list) (case elt (&optional (if (eq state :required) (setf state elt) (fail elt))) (&rest (if (member state '(:required &optional)) (setf state elt) (progn (break "state=~S" state) (fail elt)))) (&key (if (member state '(:required &optional :after-rest)) (setf state elt) (fail elt))) (&allow-other-keys (if (eq state '&key) (setf allow-other-keys t state elt) (fail elt))) (&aux (cond ((eq state '&rest) (fail elt)) (auxp (simple-program-error "Multiple ~S in ordinary lambda-list:~% ~S" elt lambda-list)) (t (setf auxp t state elt)) )) (otherwise (when (member elt '#.(set-difference lambda-list-keywords '(&optional &rest &key &allow-other-keys &aux))) (simple-program-error "Bad lambda-list keyword ~S in ordinary lambda-list:~% ~S" elt lambda-list)) (case state (:required (check-variable elt "required parameter") (push elt required)) (&optional (cond ((consp elt) (destructuring-bind (name &rest tail) elt (check-variable name "optional parameter") (if (cdr tail) (check-spec tail "optional-supplied-p parameter") (setf elt (append elt '(nil)))))) (t (check-variable elt "optional parameter") (setf elt (cons elt '(nil nil))))) (push elt optional)) (&rest (check-variable elt "rest parameter") (setf rest elt state :after-rest)) (&key (cond ((consp elt) (destructuring-bind (var-or-kv &rest tail) elt (cond ((consp var-or-kv) (destructuring-bind (keyword var) var-or-kv (unless (symbolp keyword) (simple-program-error "Invalid keyword name ~S in ordinary ~ lambda-list:~% ~S" keyword lambda-list)) (check-variable var "keyword parameter"))) (t (check-variable var-or-kv "keyword parameter") (setf var-or-kv (list (make-keyword var-or-kv) var-or-kv)))) (if (cdr tail) (check-spec tail "keyword-supplied-p parameter") (setf tail (append tail '(nil)))) (setf elt (cons var-or-kv tail)))) (t (check-variable elt "keyword parameter") (setf elt (list (list (make-keyword elt) elt) nil nil)))) (push elt keys)) (&aux (if (consp elt) (destructuring-bind (var &optional init) elt (declare (ignore init)) (check-variable var "&aux parameter")) (check-variable elt "&aux parameter")) (push elt aux)) (t (simple-program-error "Invalid ordinary lambda-list:~% ~S" lambda-list))))))) (values (nreverse required) (nreverse optional) rest (nreverse keys) allow-other-keys (nreverse aux)))) abcl-src-1.9.0/contrib/named-readtables/test/tests.lisp0100644 0000000 0000000 00000022071 14202767264 021614 0ustar000000000 0000000 ;;; -*- Mode:Lisp -*- (in-package :named-readtables-test) (defun map-alist (car-fn cdr-fn alist) (mapcar #'(lambda (entry) (cons (funcall car-fn (car entry)) (funcall cdr-fn (cdr entry)))) alist)) (defun length=1 (list) (and list (null (cdr list)))) (defmacro signals-condition-p (name &body body) `(handler-case (prog1 nil ,@body) (,(second name) () t))) (defmacro continue-condition (name &body body) `(handler-bind ((,(second name) #'continue)) ,@body)) (defun read-with-readtable (name string) (let ((*package* '#.*package*) (*readtable* (find-readtable name))) (values (read-from-string string)))) (defun random-named-readtable () (let ((readtables (list-all-named-readtables))) (nth (random (length readtables)) readtables))) (defun readtable-content (named-readtable-designator) (let ((readtable (ensure-readtable named-readtable-designator)) (result '())) ;; Make sure to canonicalize the order and function designators so ;; we can compare easily. (do-readtable ((char reader-fn ntp disp? table) readtable) (setq table (sort (copy-list table) #'char< :key #'car)) (push (list* char (ensure-function reader-fn) ntp (and disp? (list (map-alist #'identity #'ensure-function table)))) result)) (sort result #'char< :key #'car))) (defun readtable= (rt1 rt2) (tree-equal (readtable-content rt1) (readtable-content rt2) :test #'(lambda (x y) (if (and (functionp x) (functionp y)) (function= x y) (eql x y))))) (defun read-A (stream c) (declare (ignore stream c)) :a) (defun read-A-as-X (stream c) (declare (ignore stream c)) :x) (defun read-B (stream c) (declare (ignore stream c)) :b) (defun read-sharp-paren (stream c n) (declare (ignore stream c n)) 'sharp-paren) (defun read-C (stream c) (declare (ignore stream c)) :c) (defreadtable A (:macro-char #\A #'read-A)) (defreadtable A-as-X (:macro-char #\A #'read-A-as-X)) (defreadtable A-dispatch (:macro-char #\A :dispatch) (:dispatch-macro-char #\A #\A #'read-A)) (defreadtable A-dispatch-as-X (:macro-char #\A :dispatch) (:dispatch-macro-char #\A #\A #'read-A-as-X)) (defreadtable B (:macro-char #\B #'read-B)) (defreadtable C (:macro-char #\C #'read-C)) (defreadtable A+B+C (:merge A B C)) (defreadtable standard+A+B+C (:merge :standard A+B+C)) (defreadtable sharp-paren (:macro-char #\# :dispatch) (:dispatch-macro-char #\# #\( #'read-sharp-paren)) (deftest cruft.1 (function= (get-macro-character #\" (copy-readtable nil)) (get-macro-character #\" (copy-readtable nil))) t) (deftest cruft.2 (dispatch-macro-char-p #\# (find-readtable :standard)) t) (deftest cruft.3 (dispatch-macro-char-p #\# (make-readtable)) nil) (deftest cruft.4 (let ((rt (copy-named-readtable :standard))) (ensure-dispatch-macro-character #\# t rt) (dispatch-macro-char-p #\# rt)) t) (deftest cruft.5 (let ((rt (make-readtable))) (values (dispatch-macro-char-p #\$ rt) (ensure-dispatch-macro-character #\$ t rt) (dispatch-macro-char-p #\$ rt))) nil t t) (deftest cruft.6 (let ((rt (make-readtable)) (fn (constantly nil))) (ensure-dispatch-macro-character #\$ t rt) (set-dispatch-macro-character #\$ #\# fn rt) (values (eq fn (get-dispatch-macro-character #\$ #\# rt)) (length=1 (readtable-content rt)))) t t) (deftest cruft.7 (let ((rt (make-readtable)) (fn (constantly nil))) (set-macro-character #\$ fn t rt) (values (eq fn (get-macro-character #\$ rt)) (length=1 (readtable-content rt)))) t t) (deftest standard.1 (read-with-readtable :standard "ABC") ABC) (deftest standard.2 (read-with-readtable :standard "(A B C)") (A B C)) (deftest standard.3 (let ((x (find-readtable nil)) (y (find-readtable :standard)) (z (find-readtable :common-lisp))) (and (eq x y) (eq y z))) t) (deftest modern.1 (read-with-readtable :modern "FooF") |FooF|) (deftest empty.1 (null (readtable-content (make-readtable))) t) (deftest empty.2 (readtable= (merge-readtables-into (make-readtable) :standard) (find-readtable :standard)) t) (deftest empty.3 (let ((rt (copy-named-readtable :standard))) (readtable= (merge-readtables-into (make-readtable) rt) (merge-readtables-into rt (make-readtable)))) t) (deftest basics.1 (read-with-readtable 'A "A") :a) (deftest basics.2 (read-with-readtable 'A-as-X "A") :x) (deftest basics.3 (read-with-readtable 'A "B") B) (deftest basics.4 (read-with-readtable 'A "(A B C)") |(|) (deftest unregister.1 (let ((rt (find-readtable 'A))) (register-readtable 'does-not-exist rt) (values (and (find-readtable 'does-not-exist) t) (unregister-readtable 'does-not-exist) (and (find-readtable 'does-not-exist) t))) t t nil) (deftest name.1 (let ((rt (random-named-readtable))) (eq rt (find-readtable (readtable-name rt)))) t) (deftest ensure.1 (unwind-protect (let* ((x (ensure-readtable 'does-not-exist (find-readtable 'A))) (y (find-readtable 'A)) (z (find-readtable 'does-not-exist))) (and (eq x y) (eq y z))) (unregister-readtable 'does-not-exist)) t) (deftest merge.1 (values (read-with-readtable 'A+B+C "A") (read-with-readtable 'A+B+C "B") (read-with-readtable 'A+B+C "C")) :a :b :c) (deftest merge.2 (read-with-readtable 'standard+A+B+C "(A B C)") (:a :b :c)) (deftest merge.3 (read-with-readtable 'standard+A+B+C "#(A B C)") #(:a :b :c)) (deftest merge.4 (let ((A+B+C+standard (merge-readtables-into (copy-named-readtable 'A+B+C) :standard))) (readtable= 'standard+A+B+C A+B+C+standard)) t) (deftest rename.1 (unwind-protect (progn (make-readtable 'A* :merge '(A)) (rename-readtable 'A* 'A**) (values (and (find-readtable 'A*) t) (and (find-readtable 'A**) t))) (unregister-readtable 'A*) (unregister-readtable 'A**)) nil t) (deftest reader-macro-conflict.1 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) 'A 'A-as-X)) t) (deftest reader-macro-conflict.2 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) :standard :standard)) nil) (deftest reader-macro-conflict.3 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) 'A+B+C 'A)) nil) (deftest reader-macro-conflict.4 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) :standard 'sharp-paren)) t) (deftest reader-macro-conflict.5 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) 'A 'A-dispatch)) t) (deftest reader-macro-conflict.6 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) 'A-dispatch 'A)) t) (deftest reader-macro-conflict.7 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) 'A-dispatch 'A-dispatch-as-X)) t) (deftest reader-macro-conflict.8 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) 'A 'A)) nil) (deftest reader-macro-conflict.9 (signals-condition-p 'reader-macro-conflict (merge-readtables-into (make-readtable) 'A-dispatch 'A-dispatch)) nil) (deftest readtable-does-not-exist.1 (signals-condition-p 'readtable-does-not-exist (ensure-readtable 'does-not-exist)) t) (deftest readtable-does-already-exist.1 (signals-condition-p 'readtable-does-already-exist (make-readtable 'A)) t) (deftest readtable-does-already-exist.2 (signals-condition-p 'readtable-does-already-exist (make-readtable 'A)) t) (deftest readtable-does-already-exist.3 (let ((rt (make-readtable 'does-not-exist :merge '(:standard A B)))) (declare (ignore rt)) (unwind-protect (read-with-readtable (continue-condition 'readtable-does-already-exist (make-readtable 'does-not-exist :merge '(:standard A C))) "(A B C)") (unregister-readtable 'does-not-exist))) (:a B :c)) (deftest defreadtable.1 (unwind-protect (signals-condition-p 'reader-macro-conflict (eval `(defreadtable does-not-exist (:merge A A-as-X)))) (unregister-readtable 'does-not-exist)) t) (deftest defreadtable.2 (unwind-protect (signals-condition-p 't (eval `(defreadtable does-not-exist (:fuse A A-as-X)))) (unregister-readtable 'does-not-exist)) nil) abcl-src-1.9.0/contrib/pom.xml0100644 0000000 0000000 00000003731 14242627550 014726 0ustar000000000 0000000 4.0.0 org.sonatype.oss oss-parent 6 org.abcl abcl-contrib 1.9.0 jar Armed Bear Common Lisp (ABCL) Contribs Extra packages--contribs--for ABCL http://abcl.org GNU General Public License with Classpath exception http://www.gnu.org/software/classpath/license.html repo scm:svn:http://abcl.org/svn/trunk/abcl scm:svn:svn+ssh://abcl.org/project/armedbear/svn http://abcl.org/trac/browser/trunk/abcl/contrib ehu Erik Huelsmann ehuels (at) gmail (dot) com easyE Mark Evenson evenson (at) panix (dot) com V-ille Ville Voutilainen ville.voutilainen (at) gmail (dot) com astalla Alessio Stalla alessiostalla (at) gmail (dot) com rudi Rudi Schlatte rudi (at) constantly (dot) at abcl-src-1.9.0/contrib/quicklisp/quicklisp-abcl.asd0100644 0000000 0000000 00000000573 14242627550 021012 0ustar000000000 0000000 ;;;; -*- Mode: LISP -*- (defsystem quicklisp-abcl :description "Load Quicklisp, installing from network if necessary." :long-name "" :version "0.6.0" :components ((:file "quicklisp-abcl")) :perform (load-op :after (o c) (uiop:symbol-call :quicklisp-abcl 'ensure-installation))) abcl-src-1.9.0/contrib/quicklisp/quicklisp-abcl.lisp0100644 0000000 0000000 00000007020 14202767264 021207 0ustar000000000 0000000 (in-package :cl-user) (defpackage quicklisp-abcl (:nicknames :quicklisp-abcl) (:use :cl :asdf) (:export #:quicklisp/boot/fasls #:ensure-installation #:*quicklisp-parent-dir*)) (in-package :quicklisp-abcl) ;;;; ;;;; 1. (ABCL) Download setup.lisp if necessary from the network, ;;;; running the Quicklisp setup routine ;;;; ;;;; 2. Ensure that we cache the and use the fasl for ;;;; (merge-pathnames "setup.lisp" *quicklisp-parent-dir* ;;;; (defvar *quicklisp-parent-dir* (user-homedir-pathname) "Pathname reference to the parent directory of the local Quicklisp installation") (defun quicklisp/boot/fasls (&key (remove nil)) "Enumerate all Quicklisp fasls, including the one we shim for the loader" ;;; TODO: ensure that this works for other implementations (let* ((setup-base (merge-pathnames "quicklisp/setup" *quicklisp-parent-dir*)) (setup-source (make-pathname :defaults setup-base :type "lisp")) (setup-fasl (make-pathname :defaults setup-base :type "abcl")) (asdf-output-root (when (ignore-errors (asdf:find-system :quicklisp)) (asdf:apply-output-translations (asdf:system-source-directory (asdf:find-system :quicklisp)))))) (let ((all-fasls (append (list setup-fasl) (when asdf-output-root (directory (merge-pathnames "**/*" asdf-output-root)))))) (when remove (format *load-verbose* "~&;;quicklisp-abcl: deleting ~{~a ~}~%" all-fasls) (mapcar #'delete-file all-fasls)) (values all-fasls setup-base setup-source setup-fasl)))) ;;; After we have loaded this system, ensure Quicklisp is loaded (defun ensure-installation () (when (find :quicklisp *features*) (return-from ensure-installation)) (multiple-value-bind (fasls setup-base setup-source setup-fasl) (quicklisp/boot/fasls) (if (probe-file setup-source) ;; First try loading the Quicklisp setup as a compiled fasl if it exists (if (probe-file setup-fasl) (handler-case (load setup-fasl) ;; The fasl may be invalid (i.e. between abcl versions); if so, load source, and recompile (error (e) (format *load-verbose* "~&Failed to load Quicklisp setup fasl ~%~t~a~%because:~%~t~a~%" setup-fasl e) (when setup-source (format *load-verbose* "Removing Quicklisp setup fasl and recompiling...") (quicklisp/boot/fasls :remove t) (load setup-source) (compile-file setup-source :output-file setup-fasl)))) ;; compilation only succeeds after Quicklisp has been fully loaded (when (probe-file setup-source) (load setup-source) (compile-file setup-source :output-file setup-fasl))) ;;; Otherwise download Quicklisp and run its installation sequence (progn (handler-case (load "https://beta.quicklisp.org/quicklisp.lisp") (error (e) (warn "Using insecure transport for remote installation of Quicklisp:~&~A~&." e) (load "http://beta.quicklisp.org/quicklisp.lisp"))) (uiop:symbol-call :quicklisp-quickstart '#:install :path (merge-pathnames "quicklisp/" *quicklisp-parent-dir*)))))) abcl-src-1.9.0/doc/asdf/asdf.aux0100644 0000000 0000000 00000063635 14242630067 015075 0ustar000000000 0000000 @xrdef{Introduction-title}{Introduction} @xrdef{Introduction-snt}{Chapter@tie 1} @xrdef{Introduction-pg}{1} @xrdef{Quick start summary-title}{Quick start summary} @xrdef{Quick start summary-snt}{Chapter@tie 2} @xrdef{Quick start summary-pg}{2} @xrdef{Loading ASDF-title}{Loading ASDF} @xrdef{Loading ASDF-snt}{Chapter@tie 3} @xrdef{Loading a pre-installed ASDF-title}{Loading a pre-installed ASDF} @xrdef{Loading a pre-installed ASDF-snt}{Section@tie 3.1} @xrdef{Checking whether ASDF is loaded-title}{Checking whether ASDF is loaded} @xrdef{Checking whether ASDF is loaded-snt}{Section@tie 3.2} @xrdef{Upgrading ASDF-title}{Upgrading ASDF} @xrdef{Upgrading ASDF-snt}{Section@tie 3.3} @xrdef{Loading ASDF-pg}{3} @xrdef{Loading a pre-installed ASDF-pg}{3} @xrdef{Checking whether ASDF is loaded-pg}{3} @xrdef{Replacing your implementation's ASDF-title}{Replacing your implementation's ASDF} @xrdef{Replacing your implementation's ASDF-snt}{Section@tie 3.4} @xrdef{Loading ASDF from source-title}{Loading ASDF from source} @xrdef{Loading ASDF from source-snt}{Section@tie 3.5} @xrdef{Upgrading ASDF-pg}{4} @xrdef{Replacing your implementation's ASDF-pg}{4} @xrdef{Loading ASDF from source-pg}{4} @xrdef{Configuring ASDF-title}{Configuring ASDF} @xrdef{Configuring ASDF-snt}{Chapter@tie 4} @xrdef{Configuring ASDF to find your systems-title}{Configuring ASDF to find your systems} @xrdef{Configuring ASDF to find your systems-snt}{Section@tie 4.1} @xrdef{Configuring ASDF-pg}{6} @xrdef{Configuring ASDF to find your systems-pg}{6} @xrdef{Configuring ASDF to find your systems --- old style-title}{Configuring ASDF to find your systems --- old style} @xrdef{Configuring ASDF to find your systems --- old style-snt}{Section@tie 4.2} @xrdef{Configuring ASDF to find your systems --- old style-pg}{7} @xrdef{Configuring where ASDF stores object files-title}{Configuring where ASDF stores object files} @xrdef{Configuring where ASDF stores object files-snt}{Section@tie 4.3} @xrdef{Configuring where ASDF stores object files-pg}{8} @xrdef{Resetting the ASDF configuration-title}{Resetting the ASDF configuration} @xrdef{Resetting the ASDF configuration-snt}{Section@tie 4.4} @xrdef{Resetting the ASDF configuration-pg}{9} @xrdef{Using ASDF-title}{Using ASDF} @xrdef{Using ASDF-snt}{Chapter@tie 5} @xrdef{Loading a system-title}{Loading a system} @xrdef{Loading a system-snt}{Section@tie 5.1} @xrdef{Convenience Functions-title}{Convenience Functions} @xrdef{Convenience Functions-snt}{Section@tie 5.2} @xrdef{Using ASDF-pg}{10} @xrdef{Loading a system-pg}{10} @xrdef{Convenience Functions-pg}{10} @xrdef{Moving on-title}{Moving on} @xrdef{Moving on-snt}{Section@tie 5.3} @xrdef{Moving on-pg}{12} @xrdef{Defining systems with defsystem-title}{Defining systems with defsystem} @xrdef{Defining systems with defsystem-snt}{Chapter@tie 6} @xrdef{The defsystem form-title}{The defsystem form} @xrdef{The defsystem form-snt}{Section@tie 6.1} @xrdef{Defining systems with defsystem-pg}{13} @xrdef{The defsystem form-pg}{13} @xrdef{A more involved example-title}{A more involved example} @xrdef{A more involved example-snt}{Section@tie 6.2} @xrdef{A more involved example-pg}{14} @xrdef{The defsystem grammar-title}{The defsystem grammar} @xrdef{The defsystem grammar-snt}{Section@tie 6.3} @xrdef{rule-system-definition{}-title}{The defsystem grammar} @xrdef{rule-system-definition{}-snt}{} @xrdef{rule-system-designator{}-title}{The defsystem grammar} @xrdef{rule-system-designator{}-snt}{} @xrdef{rule-simple-component-name{}-title}{The defsystem grammar} @xrdef{rule-simple-component-name{}-snt}{} @xrdef{rule-complex-component-name{}-title}{The defsystem grammar} @xrdef{rule-complex-component-name{}-snt}{} @xrdef{rule-system-option{}-title}{The defsystem grammar} @xrdef{rule-system-option{}-snt}{} @xrdef{The defsystem grammar-pg}{16} @xrdef{rule-system-definition{}-pg}{16} @xrdef{rule-system-designator{}-pg}{16} @xrdef{rule-simple-component-name{}-pg}{16} @xrdef{rule-complex-component-name{}-pg}{16} @xrdef{rule-system-option{}-pg}{16} @xrdef{rule-system-option/asdf3{}-title}{The defsystem grammar} @xrdef{rule-system-option/asdf3{}-snt}{} @xrdef{rule-source-control{}-title}{The defsystem grammar} @xrdef{rule-source-control{}-snt}{} @xrdef{rule-module-option{}-title}{The defsystem grammar} @xrdef{rule-module-option{}-snt}{} @xrdef{rule-option{}-title}{The defsystem grammar} @xrdef{rule-option{}-snt}{} @xrdef{rule-person-or-persons{}-title}{The defsystem grammar} @xrdef{rule-person-or-persons{}-snt}{} @xrdef{rule-system-list{}-title}{The defsystem grammar} @xrdef{rule-system-list{}-snt}{} @xrdef{rule-component-list{}-title}{The defsystem grammar} @xrdef{rule-component-list{}-snt}{} @xrdef{rule-component-def{}-title}{The defsystem grammar} @xrdef{rule-component-def{}-snt}{} @xrdef{rule-component-type{}-title}{The defsystem grammar} @xrdef{rule-component-type{}-snt}{} @xrdef{rule-other-component-type{}-title}{The defsystem grammar} @xrdef{rule-other-component-type{}-snt}{} @xrdef{rule-system-option/asdf3{}-pg}{17} @xrdef{rule-source-control{}-pg}{17} @xrdef{rule-module-option{}-pg}{17} @xrdef{rule-option{}-pg}{17} @xrdef{rule-person-or-persons{}-pg}{17} @xrdef{rule-system-list{}-pg}{17} @xrdef{rule-component-list{}-pg}{17} @xrdef{rule-component-def{}-pg}{17} @xrdef{rule-component-type{}-pg}{17} @xrdef{rule-other-component-type{}-pg}{17} @xrdef{rule-dependency-def{}-title}{The defsystem grammar} @xrdef{rule-dependency-def{}-snt}{} @xrdef{rule-dependency{}-title}{The defsystem grammar} @xrdef{rule-dependency{}-snt}{} @xrdef{rule-requirement{}-title}{The defsystem grammar} @xrdef{rule-requirement{}-snt}{} @xrdef{rule-dependent-op{}-title}{The defsystem grammar} @xrdef{rule-dependent-op{}-snt}{} @xrdef{rule-required-op{}-title}{The defsystem grammar} @xrdef{rule-required-op{}-snt}{} @xrdef{rule-pathname-specifier{}-title}{The defsystem grammar} @xrdef{rule-pathname-specifier{}-snt}{} @xrdef{rule-version-specifier{}-title}{The defsystem grammar} @xrdef{rule-version-specifier{}-snt}{} @xrdef{rule-line-specifier{}-title}{The defsystem grammar} @xrdef{rule-line-specifier{}-snt}{} @xrdef{rule-form-specifier{}-title}{The defsystem grammar} @xrdef{rule-form-specifier{}-snt}{} @xrdef{rule-method-form{}-title}{The defsystem grammar} @xrdef{rule-method-form{}-snt}{} @xrdef{rule-qual{}-title}{The defsystem grammar} @xrdef{rule-qual{}-snt}{} @xrdef{rule-method-qualifier{}-title}{The defsystem grammar} @xrdef{rule-method-qualifier{}-snt}{} @xrdef{rule-feature-expression{}-title}{The defsystem grammar} @xrdef{rule-feature-expression{}-snt}{} @xrdef{rule-operation-name{}-title}{The defsystem grammar} @xrdef{rule-operation-name{}-snt}{} @xrdef{Simple component names-title}{Simple component names (@code {simple-component-name})} @xrdef{Simple component names-snt}{} @xrdef{rule-dependency-def{}-pg}{18} @xrdef{rule-dependency{}-pg}{18} @xrdef{rule-requirement{}-pg}{18} @xrdef{rule-dependent-op{}-pg}{18} @xrdef{rule-required-op{}-pg}{18} @xrdef{rule-pathname-specifier{}-pg}{18} @xrdef{rule-version-specifier{}-pg}{18} @xrdef{rule-line-specifier{}-pg}{18} @xrdef{rule-form-specifier{}-pg}{18} @xrdef{rule-method-form{}-pg}{18} @xrdef{rule-qual{}-pg}{18} @xrdef{rule-method-qualifier{}-pg}{18} @xrdef{rule-feature-expression{}-pg}{18} @xrdef{rule-operation-name{}-pg}{18} @xrdef{Simple component names-pg}{18} @xrdef{Complex component names-title}{Complex component names} @xrdef{Complex component names-snt}{} @xrdef{Component types-title}{Component types} @xrdef{Component types-snt}{} @xrdef{System class names-title}{System class names} @xrdef{System class names-snt}{} @xrdef{Complex component names-pg}{19} @xrdef{Component types-pg}{19} @xrdef{System class names-pg}{19} @xrdef{Build-operation-title}{Build-operation} @xrdef{Build-operation-snt}{} @xrdef{Pathname specifiers-title}{Pathname specifiers} @xrdef{Pathname specifiers-snt}{} @xrdef{Build-operation-pg}{20} @xrdef{Pathname specifiers-pg}{20} @xrdef{Version specifiers-title}{Version specifiers} @xrdef{Version specifiers-snt}{} @xrdef{Version specifiers-pg}{21} @xrdef{Feature dependencies-title}{Feature dependencies} @xrdef{Feature dependencies-snt}{} @xrdef{Using logical pathnames-title}{Using logical pathnames} @xrdef{Using logical pathnames-snt}{} @xrdef{Feature dependencies-pg}{22} @xrdef{Using logical pathnames-pg}{22} @xrdef{if-feature option-title}{if-feature option} @xrdef{if-feature option-snt}{} @xrdef{Entry point-title}{Entry point} @xrdef{Entry point-snt}{} @xrdef{feature requirement-title}{feature requirement} @xrdef{feature requirement-snt}{} @xrdef{Other code in .asd files-title}{Other code in .asd files} @xrdef{Other code in .asd files-snt}{Section@tie 6.4} @xrdef{if-feature option-pg}{24} @xrdef{Entry point-pg}{24} @xrdef{feature requirement-pg}{24} @xrdef{Other code in .asd files-pg}{24} @xrdef{The package-inferred-system extension-title}{The package-inferred-system extension} @xrdef{The package-inferred-system extension-snt}{Section@tie 6.5} @xrdef{The package-inferred-system extension-pg}{25} @xrdef{The object model of ASDF-title}{The Object model of ASDF} @xrdef{The object model of ASDF-snt}{Chapter@tie 7} @xrdef{Operations-title}{Operations} @xrdef{Operations-snt}{Section@tie 7.1} @xrdef{The object model of ASDF-pg}{28} @xrdef{Operations-pg}{28} @xrdef{operate-title}{Operations} @xrdef{operate-snt}{} @xrdef{make-operation-title}{Operations} @xrdef{make-operation-snt}{} @xrdef{operate-pg}{29} @xrdef{make-operation-pg}{29} @xrdef{Predefined operations of ASDF-title}{Predefined operations of ASDF} @xrdef{Predefined operations of ASDF-snt}{Section@tie 7.1.1} @xrdef{test-op-title}{Predefined operations of ASDF} @xrdef{test-op-snt}{} @xrdef{Predefined operations of ASDF-pg}{30} @xrdef{test-op-pg}{30} @xrdef{Creating new operations-title}{Creating new operations} @xrdef{Creating new operations-snt}{Section@tie 7.1.2} @xrdef{Creating new operations-pg}{33} @xrdef{Components-title}{Components} @xrdef{Components-snt}{Section@tie 7.2} @xrdef{Components-pg}{34} @xrdef{System names-title}{Components} @xrdef{System names-snt}{} @xrdef{System names-pg}{35} @xrdef{Common attributes of components-title}{Common attributes of components} @xrdef{Common attributes of components-snt}{Section@tie 7.2.1} @xrdef{required-features-title}{Required features} @xrdef{required-features-snt}{} @xrdef{Common attributes of components-pg}{37} @xrdef{required-features-pg}{37} @xrdef{Pre-defined subclasses of component-title}{Pre-defined subclasses of component} @xrdef{Pre-defined subclasses of component-snt}{Section@tie 7.2.2} @xrdef{Pre-defined subclasses of component-pg}{40} @xrdef{Creating new component types-title}{Creating new component types} @xrdef{Creating new component types-snt}{Section@tie 7.2.3} @xrdef{Dependencies-title}{Dependencies} @xrdef{Dependencies-snt}{Section@tie 7.3} @xrdef{Creating new component types-pg}{41} @xrdef{Dependencies-pg}{41} @xrdef{Functions-title}{Functions} @xrdef{Functions-snt}{Section@tie 7.4} @xrdef{Parsing system definitions-title}{Parsing system definitions} @xrdef{Parsing system definitions-snt}{Section@tie 7.5} @xrdef{Functions-pg}{42} @xrdef{Parsing system definitions-pg}{42} @xrdef{Controlling where ASDF searches for systems-title}{Controlling where ASDF searches for systems} @xrdef{Controlling where ASDF searches for systems-snt}{Chapter@tie 8} @xrdef{Configurations-title}{Configurations} @xrdef{Configurations-snt}{Section@tie 8.1} @xrdef{Controlling where ASDF searches for systems-pg}{44} @xrdef{Configurations-pg}{44} @xrdef{Truenames and other dangers-title}{Truenames and other dangers} @xrdef{Truenames and other dangers-snt}{Section@tie 8.2} @xrdef{XDG base directory-title}{XDG base directory} @xrdef{XDG base directory-snt}{Section@tie 8.3} @xrdef{Backward Compatibility-title}{Backward Compatibility} @xrdef{Backward Compatibility-snt}{Section@tie 8.4} @xrdef{Truenames and other dangers-pg}{45} @xrdef{XDG base directory-pg}{45} @xrdef{Backward Compatibility-pg}{45} @xrdef{Configuration DSL-title}{Configuration DSL} @xrdef{Configuration DSL-snt}{Section@tie 8.5} @xrdef{Configuration DSL-pg}{46} @xrdef{Configuration Directories-title}{Configuration Directories} @xrdef{Configuration Directories-snt}{Section@tie 8.6} @xrdef{The here directive-title}{The :here directive} @xrdef{The here directive-snt}{Section@tie 8.6.1} @xrdef{Configuration Directories-pg}{48} @xrdef{Shell-friendly syntax for configuration-title}{Shell-friendly syntax for configuration} @xrdef{Shell-friendly syntax for configuration-snt}{Section@tie 8.7} @xrdef{Search Algorithm-title}{Search Algorithm} @xrdef{Search Algorithm-snt}{Section@tie 8.8} @xrdef{The here directive-pg}{49} @xrdef{Shell-friendly syntax for configuration-pg}{49} @xrdef{Caching Results-title}{Caching Results} @xrdef{Caching Results-snt}{Section@tie 8.9} @xrdef{Search Algorithm-pg}{50} @xrdef{Caching Results-pg}{50} @xrdef{Configuration API-title}{Configuration API} @xrdef{Configuration API-snt}{Section@tie 8.10} @xrdef{Configuration API-pg}{51} @xrdef{Introspection-title}{Introspection} @xrdef{Introspection-snt}{Section@tie 8.11} @xrdef{*source-registry-parameter* variable-title}{*source-registry-parameter* variable} @xrdef{*source-registry-parameter* variable-snt}{Section@tie 8.11.1} @xrdef{Information about system dependencies-title}{Information about system dependencies} @xrdef{Information about system dependencies-snt}{Section@tie 8.11.2} @xrdef{Status-title}{Status} @xrdef{Status-snt}{Section@tie 8.12} @xrdef{Rejected ideas-title}{Rejected ideas} @xrdef{Rejected ideas-snt}{Section@tie 8.13} @xrdef{Introspection-pg}{52} @xrdef{*source-registry-parameter* variable-pg}{52} @xrdef{Information about system dependencies-pg}{52} @xrdef{Status-pg}{52} @xrdef{Rejected ideas-pg}{52} @xrdef{TODO-title}{TODO} @xrdef{TODO-snt}{Section@tie 8.14} @xrdef{Credits for the source-registry-title}{Credits for the source-registry} @xrdef{Credits for the source-registry-snt}{Section@tie 8.15} @xrdef{TODO-pg}{53} @xrdef{Credits for the source-registry-pg}{53} @xrdef{Controlling where ASDF saves compiled files-title}{Controlling where ASDF saves compiled files} @xrdef{Controlling where ASDF saves compiled files-snt}{Chapter@tie 9} @xrdef{Output Configurations-title}{Configurations} @xrdef{Output Configurations-snt}{Section@tie 9.1} @xrdef{Controlling where ASDF saves compiled files-pg}{54} @xrdef{Output Configurations-pg}{54} @xrdef{Output Backward Compatibility-title}{Backward Compatibility} @xrdef{Output Backward Compatibility-snt}{Section@tie 9.2} @xrdef{Output Configuration DSL-title}{Configuration DSL} @xrdef{Output Configuration DSL-snt}{Section@tie 9.3} @xrdef{Output Backward Compatibility-pg}{55} @xrdef{Output Configuration DSL-pg}{56} @xrdef{Output Configuration Directories-title}{Configuration Directories} @xrdef{Output Configuration Directories-snt}{Section@tie 9.4} @xrdef{Output Shell-friendly syntax for configuration-title}{Shell-friendly syntax for configuration} @xrdef{Output Shell-friendly syntax for configuration-snt}{Section@tie 9.5} @xrdef{Semantics of Output Translations-title}{Semantics of Output Translations} @xrdef{Semantics of Output Translations-snt}{Section@tie 9.6} @xrdef{Output Configuration Directories-pg}{58} @xrdef{Output Shell-friendly syntax for configuration-pg}{58} @xrdef{Output Caching Results-title}{Caching Results} @xrdef{Output Caching Results-snt}{Section@tie 9.7} @xrdef{Output location API-title}{Output location API} @xrdef{Output location API-snt}{Section@tie 9.8} @xrdef{Semantics of Output Translations-pg}{59} @xrdef{Output Caching Results-pg}{59} @xrdef{Output location API-pg}{59} @xrdef{Credits for output translations-title}{Credits for output translations} @xrdef{Credits for output translations-snt}{Section@tie 9.9} @xrdef{Credits for output translations-pg}{60} @xrdef{Error handling-title}{Error handling} @xrdef{Error handling-snt}{Chapter@tie 10} @xrdef{Error handling-pg}{61} @xrdef{Miscellaneous additional functionality-title}{Miscellaneous additional functionality} @xrdef{Miscellaneous additional functionality-snt}{Chapter@tie 11} @xrdef{Controlling file compilation-title}{Controlling file compilation} @xrdef{Controlling file compilation-snt}{Section@tie 11.1} @xrdef{Controlling source file character encoding-title}{Controlling source file character encoding} @xrdef{Controlling source file character encoding-snt}{Section@tie 11.2} @xrdef{Miscellaneous additional functionality-pg}{62} @xrdef{Controlling file compilation-pg}{62} @xrdef{Controlling source file character encoding-pg}{63} @xrdef{Miscellaneous Functions-title}{Miscellaneous Functions} @xrdef{Miscellaneous Functions-snt}{Section@tie 11.3} @xrdef{system-relative-pathname-title}{Miscellaneous Functions} @xrdef{system-relative-pathname-snt}{} @xrdef{Miscellaneous Functions-pg}{64} @xrdef{system-relative-pathname-pg}{64} @xrdef{Some Utility Functions-title}{Some Utility Functions} @xrdef{Some Utility Functions-snt}{Section@tie 11.4} @xrdef{Some Utility Functions-pg}{66} @xrdef{Getting the latest version-title}{Getting the latest version} @xrdef{Getting the latest version-snt}{Chapter@tie 12} @xrdef{Getting the latest version-pg}{70} @xrdef{FAQ-title}{FAQ} @xrdef{FAQ-snt}{Chapter@tie 13} @xrdef{Where do I report a bug?-title}{``Where do I report a bug?''} @xrdef{Where do I report a bug?-snt}{Section@tie 13.1} @xrdef{Mailing list-title}{Mailing list} @xrdef{Mailing list-snt}{Section@tie 13.2} @xrdef{What has changed between ASDF 1 ASDF 2 and ASDF 3?-title}{``What has changed between ASDF 1, ASDF 2, and ASDF 3?''} @xrdef{What has changed between ASDF 1 ASDF 2 and ASDF 3?-snt}{Section@tie 13.3} @xrdef{What are ASDF 1 2 3?-title}{What are ASDF 1, ASDF 2, and ASDF 3?} @xrdef{What are ASDF 1 2 3?-snt}{Section@tie 13.3.1} @xrdef{FAQ-pg}{71} @xrdef{Where do I report a bug?-pg}{71} @xrdef{Mailing list-pg}{71} @xrdef{What has changed between ASDF 1 ASDF 2 and ASDF 3?-pg}{71} @xrdef{What are ASDF 1 2 3?-pg}{71} @xrdef{How do I detect the ASDF version?-title}{How do I detect the ASDF version?} @xrdef{How do I detect the ASDF version?-snt}{Section@tie 13.3.2} @xrdef{ASDF can portably name files in subdirectories-title}{ASDF can portably name files in subdirectories} @xrdef{ASDF can portably name files in subdirectories-snt}{Section@tie 13.3.3} @xrdef{How do I detect the ASDF version?-pg}{72} @xrdef{ASDF can portably name files in subdirectories-pg}{72} @xrdef{Output translations-title}{Output translations} @xrdef{Output translations-snt}{Section@tie 13.3.4} @xrdef{Source Registry Configuration-title}{Source Registry Configuration} @xrdef{Source Registry Configuration-snt}{Section@tie 13.3.5} @xrdef{Usual operations are made easier to the user-title}{Usual operations are made easier to the user} @xrdef{Usual operations are made easier to the user-snt}{Section@tie 13.3.6} @xrdef{Output translations-pg}{73} @xrdef{Source Registry Configuration-pg}{73} @xrdef{Many bugs have been fixed-title}{Many bugs have been fixed} @xrdef{Many bugs have been fixed-snt}{Section@tie 13.3.7} @xrdef{ASDF itself is versioned-title}{ASDF itself is versioned} @xrdef{ASDF itself is versioned-snt}{Section@tie 13.3.8} @xrdef{ASDF can be upgraded-title}{ASDF can be upgraded} @xrdef{ASDF can be upgraded-snt}{Section@tie 13.3.9} @xrdef{Usual operations are made easier to the user-pg}{74} @xrdef{Many bugs have been fixed-pg}{74} @xrdef{ASDF itself is versioned-pg}{74} @xrdef{ASDF can be upgraded-pg}{74} @xrdef{Decoupled release cycle-title}{Decoupled release cycle} @xrdef{Decoupled release cycle-snt}{Section@tie 13.3.10} @xrdef{Pitfalls of the transition to ASDF 2-title}{Pitfalls of the transition to ASDF 2} @xrdef{Pitfalls of the transition to ASDF 2-snt}{Section@tie 13.3.11} @xrdef{Decoupled release cycle-pg}{75} @xrdef{Pitfalls of the transition to ASDF 2-pg}{75} @xrdef{Pitfalls of the upgrade to ASDF 3-title}{Pitfalls of the upgrade to ASDF 3} @xrdef{Pitfalls of the upgrade to ASDF 3-snt}{Section@tie 13.3.12} @xrdef{Pitfalls of the upgrade to ASDF 3-pg}{76} @xrdef{reinitializeASDFAfterUpgrade-title}{Pitfalls of the upgrade to ASDF 3} @xrdef{reinitializeASDFAfterUpgrade-snt}{} @xrdef{What happened to the bundle operations-title}{What happened to the bundle operations?} @xrdef{What happened to the bundle operations-snt}{Section@tie 13.3.13} @xrdef{reinitializeASDFAfterUpgrade-pg}{77} @xrdef{What happened to the bundle operations-pg}{77} @xrdef{Issues with installing the proper version of ASDF-title}{Issues with installing the proper version of ASDF} @xrdef{Issues with installing the proper version of ASDF-snt}{Section@tie 13.4} @xrdef{My Common Lisp implementation comes with an outdated version of ASDF. What to do?-title}{``My Common Lisp implementation comes with an outdated version of ASDF. What to do?''} @xrdef{My Common Lisp implementation comes with an outdated version of ASDF. What to do?-snt}{Section@tie 13.4.1} @xrdef{I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?-title}{``I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?''} @xrdef{I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?-snt}{Section@tie 13.4.2} @xrdef{Issues with installing the proper version of ASDF-pg}{78} @xrdef{My Common Lisp implementation comes with an outdated version of ASDF. What to do?-pg}{78} @xrdef{I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?-pg}{78} @xrdef{After upgrading ASDF-title}{After upgrading ASDF, ASDF (and Quicklisp) can't find my systems} @xrdef{After upgrading ASDF-snt}{Section@tie 13.4.3} @xrdef{Issues with configuring ASDF-title}{Issues with configuring ASDF} @xrdef{Issues with configuring ASDF-snt}{Section@tie 13.5} @xrdef{How can I customize where fasl files are stored?-title}{``How can I customize where fasl files are stored?''} @xrdef{How can I customize where fasl files are stored?-snt}{Section@tie 13.5.1} @xrdef{After upgrading ASDF-pg}{79} @xrdef{Issues with configuring ASDF-pg}{79} @xrdef{How can I wholly disable the compiler output cache?-title}{``How can I wholly disable the compiler output cache?''} @xrdef{How can I wholly disable the compiler output cache?-snt}{Section@tie 13.5.2} @xrdef{How can I debug problems finding ASDF systems-title}{How can I debug problems finding ASDF systems?} @xrdef{How can I debug problems finding ASDF systems-snt}{Section@tie 13.5.3} @xrdef{How can I customize where fasl files are stored?-pg}{80} @xrdef{How can I wholly disable the compiler output cache?-pg}{80} @xrdef{How can I debug problems finding ASDF systems-pg}{80} @xrdef{Issues with using and extending ASDF to define systems-title}{Issues with using and extending ASDF to define systems} @xrdef{Issues with using and extending ASDF to define systems-snt}{Section@tie 13.6} @xrdef{How can I cater for unit-testing in my system?-title}{``How can I cater for unit-testing in my system?''} @xrdef{How can I cater for unit-testing in my system?-snt}{Section@tie 13.6.1} @xrdef{How can I cater for documentation generation in my system?-title}{``How can I cater for documentation generation in my system?''} @xrdef{How can I cater for documentation generation in my system?-snt}{Section@tie 13.6.2} @xrdef{How can I maintain non-Lisp (e.g. C) source files?-title}{``How can I maintain non-Lisp (e.g. C) source files?''} @xrdef{How can I maintain non-Lisp (e.g. C) source files?-snt}{Section@tie 13.6.3} @xrdef{report-bugs-title}{``How can I maintain non-Lisp (e.g. C) source files?''} @xrdef{report-bugs-snt}{} @xrdef{I want to put my module's files at the top level. How do I do this?-title}{``I want to put my module's files at the top level. How do I do this?''} @xrdef{I want to put my module's files at the top level. How do I do this?-snt}{Section@tie 13.6.4} @xrdef{Issues with using and extending ASDF to define systems-pg}{81} @xrdef{How can I cater for unit-testing in my system?-pg}{81} @xrdef{How can I cater for documentation generation in my system?-pg}{81} @xrdef{How can I maintain non-Lisp (e.g. C) source files?-pg}{81} @xrdef{report-bugs-pg}{81} @xrdef{I want to put my module's files at the top level. How do I do this?-pg}{81} @xrdef{How do I create a system definition where all the source files have a .cl extension?-title}{How do I create a system definition where all the source files have a .cl extension?} @xrdef{How do I create a system definition where all the source files have a .cl extension?-snt}{Section@tie 13.6.5} @xrdef{How do I create a system definition where all the source files have a .cl extension?-pg}{82} @xrdef{How do I mark a source file to be loaded only and not compiled?-title}{How do I mark a source file to be loaded only and not compiled?} @xrdef{How do I mark a source file to be loaded only and not compiled?-snt}{Section@tie 13.6.6} @xrdef{How do I work with readtables?-title}{How do I work with readtables?} @xrdef{How do I work with readtables?-snt}{Section@tie 13.6.7} @xrdef{How do I mark a source file to be loaded only and not compiled?-pg}{83} @xrdef{How do I work with readtables?-pg}{83} @xrdef{How can I capture ASDF's output?-title}{How can I capture ASDF's output?} @xrdef{How can I capture ASDF's output?-snt}{Section@tie 13.6.8} @xrdef{LOAD-PATHNAME has a weird value-title}{*LOAD-PATHNAME* and *LOAD-TRUENAME* have weird values, help!} @xrdef{LOAD-PATHNAME has a weird value-snt}{Section@tie 13.6.9} @xrdef{How can I capture ASDF's output?-pg}{84} @xrdef{ASDF development FAQs-title}{ASDF development FAQs} @xrdef{ASDF development FAQs-snt}{Section@tie 13.7} @xrdef{How do I run the tests interactively in a REPL?-title}{How do I run the tests interactively in a REPL?} @xrdef{How do I run the tests interactively in a REPL?-snt}{Section@tie 13.7.1} @xrdef{LOAD-PATHNAME has a weird value-pg}{85} @xrdef{ASDF development FAQs-pg}{85} @xrdef{How do I run the tests interactively in a REPL?-pg}{85} @xrdef{Ongoing Work-title}{Ongoing Work} @xrdef{Ongoing Work-snt}{} @xrdef{Ongoing Work-pg}{86} @xrdef{Bibliography-title}{Bibliography} @xrdef{Bibliography-snt}{} @xrdef{Bibliography-pg}{87} @xrdef{Concept Index-title}{Concept Index} @xrdef{Concept Index-snt}{} @xrdef{Concept Index-pg}{89} @xrdef{Function and Macro Index-title}{Function and Macro Index} @xrdef{Function and Macro Index-snt}{} @xrdef{Function and Macro Index-pg}{91} @xrdef{Variable Index-title}{Variable Index} @xrdef{Variable Index-snt}{} @xrdef{Variable Index-pg}{92} @xrdef{Class and Type Index-title}{Class and Type Index} @xrdef{Class and Type Index-snt}{} @xrdef{Class and Type Index-pg}{93} abcl-src-1.9.0/doc/asdf/asdf.cp0100644 0000000 0000000 00000007533 14242630067 014675 0ustar000000000 0000000 \entry{ASDF-related features}{1}{ASDF-related features} \entry{Testing for ASDF}{1}{Testing for ASDF} \entry{ASDF versions}{1}{ASDF versions} \entry{:asdf}{1}{:asdf} \entry{:asdf2}{1}{:asdf2} \entry{:asdf3}{1}{:asdf3} \entry{build-operation}{11}{build-operation} \entry{asdf-user}{13}{asdf-user} \entry{:version}{14}{:version} \entry{DEFSYSTEM grammar}{16}{DEFSYSTEM grammar} \entry{:defsystem-depends-on}{19}{:defsystem-depends-on} \entry{:build-operation}{20}{:build-operation} \entry{:weakly-depends-on}{20}{:weakly-depends-on} \entry{pathname specifiers}{20}{pathname specifiers} \entry{version specifiers}{21}{version specifiers} \entry{:version}{21}{:version} \entry{:require dependencies}{22}{:require dependencies} \entry{:feature dependencies}{22}{:feature dependencies} \entry{logical pathnames}{22}{logical pathnames} \entry{serial dependencies}{23}{serial dependencies} \entry{:if-feature component option}{24}{:if-feature component option} \entry{:entry-point}{24}{:entry-point} \entry{Package inferred systems}{25}{Package inferred systems} \entry{Packages, inferring dependencies from}{25}{Packages, inferring dependencies from} \entry{One package per file systems}{25}{One package per file systems} \entry{operation}{28}{operation} \entry{immutable systems}{29}{immutable systems} \entry{component}{34}{component} \entry{system}{34}{system} \entry{system designator}{34}{system designator} \entry{component designator}{34}{component designator} \entry{ASDF-USER package}{35}{ASDF-USER package} \entry{System names}{35}{System names} \entry{Primary system name}{35}{Primary system name} \entry{:version}{37}{:version} \entry{Parsing system definitions}{42}{Parsing system definitions} \entry{Extending ASDF's defsystem parser}{42}{Extending ASDF's defsystem parser} \entry{:inherit-configuration source config directive}{46}{:inherit-configuration source config directive} \entry{inherit-configuration source config directive}{46}{inherit-configuration source config directive} \entry{:ignore-invalid-entries source config directive}{46}{:ignore-invalid-entries source config directive} \entry{ignore-invalid-entries source config directive}{46}{ignore-invalid-entries source config directive} \entry{:directory source config directive}{46}{:directory source config directive} \entry{directory source config directive}{46}{directory source config directive} \entry{:tree source config directive}{46}{:tree source config directive} \entry{tree source config directive}{46}{tree source config directive} \entry{:exclude source config directive}{46}{:exclude source config directive} \entry{exclude source config directive}{46}{exclude source config directive} \entry{:also-exclude source config directive}{46}{:also-exclude source config directive} \entry{also-exclude source config directive}{46}{also-exclude source config directive} \entry{:include source config directive}{46}{:include source config directive} \entry{include source config directive}{46}{include source config directive} \entry{:default-registry source config directive}{46}{:default-registry source config directive} \entry{default-registry source config directive}{46}{default-registry source config directive} \entry{asdf-output-translations}{54}{asdf-output-translations} \entry{ASDF-BINARY-LOCATIONS compatibility}{55}{ASDF-BINARY-LOCATIONS compatibility} \entry{:around-compile}{62}{:around-compile} \entry{around-compile keyword}{62}{around-compile keyword} \entry{compile-check keyword}{62}{compile-check keyword} \entry{:compile-check}{62}{:compile-check} \entry{immutable systems}{66}{immutable systems} \entry{bug tracker}{71}{bug tracker} \entry{gitlab}{71}{gitlab} \entry{launchpad}{71}{launchpad} \entry{mailing list}{71}{mailing list} \entry{*features*}{72}{*features*} \entry{Quicklisp}{79}{Quicklisp} \entry{readtables}{83}{readtables} \entry{ASDF output}{84}{ASDF output} \entry{Capturing ASDF output}{84}{Capturing ASDF output} abcl-src-1.9.0/doc/asdf/asdf.cps0100644 0000000 0000000 00000004724 14242630067 015057 0ustar000000000 0000000 \initial {*} \entry{*features*}{72} \initial {:} \entry{:also-exclude source config directive}{46} \entry{:around-compile}{62} \entry{:asdf}{1} \entry{:asdf2}{1} \entry{:asdf3}{1} \entry{:build-operation}{20} \entry{:compile-check}{62} \entry{:default-registry source config directive}{46} \entry{:defsystem-depends-on}{19} \entry{:directory source config directive}{46} \entry{:entry-point}{24} \entry{:exclude source config directive}{46} \entry{:feature dependencies}{22} \entry{:if-feature component option}{24} \entry{:ignore-invalid-entries source config directive}{46} \entry{:include source config directive}{46} \entry{:inherit-configuration source config directive}{46} \entry{:require dependencies}{22} \entry{:tree source config directive}{46} \entry{:version}{14, 21, 37} \entry{:weakly-depends-on}{20} \initial {A} \entry{also-exclude source config directive}{46} \entry{around-compile keyword}{62} \entry{asdf-output-translations}{54} \entry{asdf-user}{13} \entry{ASDF output}{84} \entry{ASDF versions}{1} \entry{ASDF-BINARY-LOCATIONS compatibility}{55} \entry{ASDF-related features}{1} \entry{ASDF-USER package}{35} \initial {B} \entry{bug tracker}{71} \entry{build-operation}{11} \initial {C} \entry{Capturing ASDF output}{84} \entry{compile-check keyword}{62} \entry{component}{34} \entry{component designator}{34} \initial {D} \entry{default-registry source config directive}{46} \entry{DEFSYSTEM grammar}{16} \entry{directory source config directive}{46} \initial {E} \entry{exclude source config directive}{46} \entry{Extending ASDF's defsystem parser}{42} \initial {G} \entry{gitlab}{71} \initial {I} \entry{ignore-invalid-entries source config directive}{46} \entry{immutable systems}{29, 66} \entry{include source config directive}{46} \entry{inherit-configuration source config directive}{46} \initial {L} \entry{launchpad}{71} \entry{logical pathnames}{22} \initial {M} \entry{mailing list}{71} \initial {O} \entry{One package per file systems}{25} \entry{operation}{28} \initial {P} \entry{Package inferred systems}{25} \entry{Packages, inferring dependencies from}{25} \entry{Parsing system definitions}{42} \entry{pathname specifiers}{20} \entry{Primary system name}{35} \initial {Q} \entry{Quicklisp}{79} \initial {R} \entry{readtables}{83} \initial {S} \entry{serial dependencies}{23} \entry{system}{34} \entry{system designator}{34} \entry{System names}{35} \initial {T} \entry{Testing for ASDF}{1} \entry{tree source config directive}{46} \initial {V} \entry{version specifiers}{21} abcl-src-1.9.0/doc/asdf/asdf.fn0100644 0000000 0000000 00000010120 14242630067 014660 0ustar000000000 0000000 \entry{clear-output-translations}{8}{\code {clear-output-translations}} \entry{clear-configuration}{9}{\code {clear-configuration}} \entry{operate}{10}{\code {operate}} \entry{oos}{10}{\code {oos}} \entry{load-system}{10}{\code {load-system}} \entry{compile-system}{10}{\code {compile-system}} \entry{test-system}{11}{\code {test-system}} \entry{make}{11}{\code {make}} \entry{require-system}{11}{\code {require-system}} \entry{already-loaded-systems}{11}{\code {already-loaded-systems}} \entry{defsystem}{13}{\code {defsystem}} \entry{load-asd}{13}{\code {load-asd}} \entry{defsystem}{14}{\code {defsystem}} \entry{defsystem}{16}{\code {defsystem}} \entry{package-inferred-system}{25}{\code {package-inferred-system}} \entry{register-system-packages}{26}{\code {register-system-packages}} \entry{define-package}{26}{\code {define-package}} \entry{uiop:define-package}{26}{\code {uiop:define-package}} \entry{operate}{29}{\code {operate}} \entry{oos}{29}{\code {oos}} \entry{register-immutable-system}{29}{\code {register-immutable-system}} \entry{traverse}{29}{\code {traverse}} \entry{make-operation}{29}{\code {make-operation}} \entry{perform}{33}{\code {perform}} \entry{output-files}{33}{\code {output-files}} \entry{component-depends-on}{33}{\code {component-depends-on}} \entry{coerce-name}{34}{\code {coerce-name}} \entry{find-component}{34}{\code {find-component}} \entry{input-files}{34}{\code {input-files}} \entry{input-files}{34}{\code {input-files}} \entry{operation-done-p}{34}{\code {operation-done-p}} \entry{find-system}{35}{\code {find-system}} \entry{primary-system-name}{35}{\code {primary-system-name}} \entry{primary-system-name}{36}{\code {primary-system-name}} \entry{locate-system}{36}{\code {locate-system}} \entry{find-component}{37}{\code {find-component}} \entry{coerce-name}{37}{\code {coerce-name}} \entry{coerce-name}{37}{\code {coerce-name}} \entry{version-satisfies}{37}{\code {version-satisfies}} \entry{component-pathname}{39}{\code {component-pathname}} \entry{version-satisfies}{42}{\code {version-satisfies}} \entry{parse-component-form}{42}{\code {parse-component-form}} \entry{compute-component-children}{42}{\code {compute-component-children}} \entry{class-for-type}{43}{\code {class-for-type}} \entry{initialize-source-registry}{51}{\code {initialize-source-registry}} \entry{clear-source-registry}{51}{\code {clear-source-registry}} \entry{ensure-source-registry}{51}{\code {ensure-source-registry}} \entry{system-defsystem-depends-on}{52}{\code {system-defsystem-depends-on}} \entry{system-depends-on}{52}{\code {system-depends-on}} \entry{system-weakly-depends-on}{52}{\code {system-weakly-depends-on}} \entry{enable-asdf-binary-locations-compatibility}{55}{\code {enable-asdf-binary-locations-compatibility}} \entry{initialize-output-translations}{59}{\code {initialize-output-translations}} \entry{disable-output-translations}{59}{\code {disable-output-translations}} \entry{clear-output-translations}{59}{\code {clear-output-translations}} \entry{ensure-output-translations}{60}{\code {ensure-output-translations}} \entry{apply-output-translations}{60}{\code {apply-output-translations}} \entry{compile-file*}{62}{\code {compile-file*}} \entry{system-relative-pathname}{64}{\code {system-relative-pathname}} \entry{system-source-directory}{65}{\code {system-source-directory}} \entry{clear-system}{65}{\code {clear-system}} \entry{register-preloaded-system}{65}{\code {register-preloaded-system}} \entry{register-immutable-system}{66}{\code {register-immutable-system}} \entry{run-shell-command}{66}{\code {run-shell-command}} \entry{parse-unix-namestring}{66}{\code {parse-unix-namestring}} \entry{merge-pathnames*}{67}{\code {merge-pathnames*}} \entry{subpathname}{67}{\code {subpathname}} \entry{subpathname*}{68}{\code {subpathname*}} \entry{run-program}{68}{\code {run-program}} \entry{slurp-input-stream}{69}{\code {slurp-input-stream}} \entry{asdf-version}{72}{\code {asdf-version}} \entry{source-file-type}{76}{\code {source-file-type}} \entry{file-type}{76}{\code {file-type}} \entry{flatten-source-registry}{80}{\code {flatten-source-registry}} \entry{system-relative-pathname}{85}{\code {system-relative-pathname}} abcl-src-1.9.0/doc/asdf/asdf.fns0100644 0000000 0000000 00000005013 14242630067 015050 0ustar000000000 0000000 \initial {A} \entry{\code {already-loaded-systems}}{11} \entry{\code {apply-output-translations}}{60} \entry{\code {asdf-version}}{72} \initial {C} \entry{\code {class-for-type}}{43} \entry{\code {clear-configuration}}{9} \entry{\code {clear-output-translations}}{8, 59} \entry{\code {clear-source-registry}}{51} \entry{\code {clear-system}}{65} \entry{\code {coerce-name}}{34, 37} \entry{\code {compile-file*}}{62} \entry{\code {compile-system}}{10} \entry{\code {component-depends-on}}{33} \entry{\code {component-pathname}}{39} \entry{\code {compute-component-children}}{42} \initial {D} \entry{\code {define-package}}{26} \entry{\code {defsystem}}{13, 14, 16} \entry{\code {disable-output-translations}}{59} \initial {E} \entry{\code {enable-asdf-binary-locations-compatibility}}{55} \entry{\code {ensure-output-translations}}{60} \entry{\code {ensure-source-registry}}{51} \initial {F} \entry{\code {file-type}}{76} \entry{\code {find-component}}{34, 37} \entry{\code {find-system}}{35} \entry{\code {flatten-source-registry}}{80} \initial {I} \entry{\code {initialize-output-translations}}{59} \entry{\code {initialize-source-registry}}{51} \entry{\code {input-files}}{34} \initial {L} \entry{\code {load-asd}}{13} \entry{\code {load-system}}{10} \entry{\code {locate-system}}{36} \initial {M} \entry{\code {make}}{11} \entry{\code {make-operation}}{29} \entry{\code {merge-pathnames*}}{67} \initial {O} \entry{\code {oos}}{10, 29} \entry{\code {operate}}{10, 29} \entry{\code {operation-done-p}}{34} \entry{\code {output-files}}{33} \initial {P} \entry{\code {package-inferred-system}}{25} \entry{\code {parse-component-form}}{42} \entry{\code {parse-unix-namestring}}{66} \entry{\code {perform}}{33} \entry{\code {primary-system-name}}{35, 36} \initial {R} \entry{\code {register-immutable-system}}{29, 66} \entry{\code {register-preloaded-system}}{65} \entry{\code {register-system-packages}}{26} \entry{\code {require-system}}{11} \entry{\code {run-program}}{68} \entry{\code {run-shell-command}}{66} \initial {S} \entry{\code {slurp-input-stream}}{69} \entry{\code {source-file-type}}{76} \entry{\code {subpathname}}{67} \entry{\code {subpathname*}}{68} \entry{\code {system-defsystem-depends-on}}{52} \entry{\code {system-depends-on}}{52} \entry{\code {system-relative-pathname}}{64, 85} \entry{\code {system-source-directory}}{65} \entry{\code {system-weakly-depends-on}}{52} \initial {T} \entry{\code {test-system}}{11} \entry{\code {traverse}}{29} \initial {U} \entry{\code {uiop:define-package}}{26} \initial {V} \entry{\code {version-satisfies}}{37, 42} abcl-src-1.9.0/doc/asdf/asdf.log0100644 0000000 0000000 00000033673 14242630067 015060 0ustar000000000 0000000 This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/MacPorts 2022.62882_0) (preloaded format=pdfetex 2022.4.24) 23 MAY 2022 08:56 entering extended mode restricted \write18 enabled. file:line:error style messages enabled. %&-line parsing enabled. **\input ./asdf.texinfo \input ./asdf.texinfo \input ./asdf.texinfo (./asdf.texinfo (/opt/local/share/texmf/tex/texinfo/texinfo.tex Loading texinfo [version 2021-04-25.21]: \outerhsize=\dimen16 \outervsize=\dimen17 \topandbottommargin=\dimen18 \bindingoffset=\dimen19 \normaloffset=\dimen20 \txipagewidth=\dimen21 \txipageheight=\dimen22 \defaultoutput=\toks13 \headlinebox=\box16 \footlinebox=\box17 \savedtopmark=\toks14 \margin=\insert252 \EMsimple=\toks15 \groupbox=\box18 \groupinvalidhelp=\toks16 \mil=\dimen23 \exdentamount=\skip18 \inmarginspacing=\skip19 \centerpenalty=\count27 pdf, \tempnum=\count28 \lnkcount=\count29 \filename=\toks17 \filenamelength=\count30 \pgn=\count31 \toksA=\toks18 \toksB=\toks19 \toksC=\toks20 \toksD=\toks21 \boxA=\box19 \boxB=\box20 \countA=\count32 \pagecount=\count33 \romancount=\count34 \arabiccount=\count35 \nopdfimagehelp=\toks22 fonts, \textleading=\dimen24 \sffam=\fam8 \fontdepth=\count36 glyphs, \errorbox=\box21 page headings, \titlepagetopglue=\skip20 \titlepagebottomglue=\skip21 \evenheadline=\toks23 \oddheadline=\toks24 \evenchapheadline=\toks25 \oddchapheadline=\toks26 \evenfootline=\toks27 \oddfootline=\toks28 tables, \tableindent=\dimen25 \itemindent=\dimen26 \itemmargin=\dimen27 \itemmax=\dimen28 \itemno=\count37 \colcount=\count38 \everytab=\toks29 conditionals, \doignorecount=\count39 indexing, \dummybox=\box22 \whatsitskip=\skip22 \whatsitpenalty=\count40 \entryrightmargin=\dimen29 \thinshrinkable=\skip23 \partialpage=\box23 \doublecolumnhsize=\dimen30 \balancedcolumns=\box24 sectioning, \unnumberedno=\count41 \chapno=\count42 \secno=\count43 \subsecno=\count44 \subsubsecno=\count45 \appendixno=\count46 \absseclevel=\count47 \secbase=\count48 \chapheadingskip=\skip24 \secheadingskip=\skip25 \subsecheadingskip=\skip26 toc, \tocfile=\write0 \contentsrightmargin=\skip27 \savepageno=\count49 \lastnegativepageno=\count50 \tocindent=\dimen31 environments, \lispnarrowing=\skip28 \envskipamount=\skip29 \lskip=\skip30 \rskip=\skip31 \circthick=\dimen32 \cartouter=\dimen33 \cartinner=\dimen34 \normbskip=\skip32 \normpskip=\skip33 \normlskip=\skip34 \nonfillparindent=\dimen35 \tabw=\dimen36 \verbbox=\box25 defuns, \defbodyindent=\skip35 \defargsindent=\skip36 \deflastargmargin=\skip37 \defunpenalty=\count51 \parencount=\count52 \brackcount=\count53 macros, \paramno=\count54 \macname=\toks30 cross references, \auxfile=\write1 \savesfregister=\count55 \toprefbox=\box26 \printedrefnamebox=\box27 \infofilenamebox=\box28 \printedmanualbox=\box29 insertions, \footnoteno=\count56 \SAVEfootins=\box30 \SAVEmargin=\box31 (/opt/local/share/texmf/tex/generic/epsf/epsf.tex This is `epsf.tex' v2.7.4 <14 February 2011> \epsffilein=\read1 \epsfframemargin=\dimen37 \epsfframethickness=\dimen38 \epsfrsize=\dimen39 \epsftmp=\dimen40 \epsftsize=\dimen41 \epsfxsize=\dimen42 \epsfysize=\dimen43 \pspoints=\dimen44 ) \noepsfhelp=\toks31 localization, \nolanghelp=\toks32 \countUTFx=\count57 \countUTFy=\count58 \countUTFz=\count59 formatting, \defaultparindent=\dimen45 and turning on texinfo input format.) [1{/opt/local/var/db/texmf/fonts/map/pdf tex/updmap/pdftex.map}] [2] (/Users/evenson/work/abcl.easye.git/doc/asdf/asdf.toc [-1] [-2] [-3]) [-4] (/Users/evenson/work/abcl.easye.git/doc/asdf/asdf.toc) (/Users/evenson/work/abcl.easye.git/doc/asdf/asdf.toc) Chapter 1 \openout0 = `asdf.toc'. (/Users/evenson/work/abcl.easye.git/doc/asdf/asdf.aux) \openout1 = `asdf.aux'. @cpindfile=@write2 \openout2 = `asdf.cp'. Writing index file asdf.cp @vrindfile=@write3 \openout3 = `asdf.vr'. Writing index file asdf.vr Chapter 2 [1] Chapter 3 [2] [3] Chapter 4 [4] [5] [6] [7] @fnindfile=@write4 \openout4 = `asdf.fn'. Writing index file asdf.fn [8] Chapter 5 [9] [10] Chapter 6 [11] [12] [13] [14] [15] [16] [17] Overfull \hbox (49.43388pt too wide) in paragraph at lines 1516--1516 [] @texttt | ( :feature feature-expression dependency-def ) # s ee [][][Feature| @hbox(7.60416+2.43333)x433.62 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@penalty 10000 .@glue 5.74869 .@penalty 10000 .etc. Overfull \hbox (26.43913pt too wide) in paragraph at lines 1531--1531 [] @texttt | ( :read-file-form pathname-specifier form-speci fier? )[] | @hbox(7.60416+2.43333)x433.62 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@penalty 10000 .@glue 5.74869 .@penalty 10000 .etc. Overfull \hbox (26.43913pt too wide) in paragraph at lines 1532--1532 [] @texttt | ( :read-file-line pathname-specifier line-speci fier? )[] | @hbox(7.60416+2.43333)x433.62 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@penalty 10000 .@glue 5.74869 .@penalty 10000 .etc. [18] [19] [20] Underfull \hbox (badness 10000) in paragraph at lines 1784--1801 @texttt (:read-file-form [:at ])[]@te xtrm , or @hbox(7.60416+2.43333)x433.62, glue set 19.30852 .@texttt ( .@texttt : .@texttt r .@texttt e .@texttt a .etc. [21] [22] [23] [24] [25] [26] Chapter 7 [27] @tpindfile=@write5 \openout5 = `asdf.tp'. Writing index file asdf.tp [28] [29] [30] Underfull \hbox (badness 7099) in paragraph at lines 2517--2521 []@textrm NB: @texttt compile-bundle-op[]@textrm , @texttt monolithic-compile- bundle-op[]@textrm , @texttt load-bundle-op[]@textrm , @hbox(7.48248+2.43333)x433.62, glue set 4.14162 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@textrm N .@textrm B .@textrm : .etc. Underfull \hbox (badness 10000) in paragraph at lines 2517--2521 @texttt monolithic-load-bundle-op[]@textrm , @texttt deliver-asd-op[]@textrm , @texttt monolithic-deliver-asd-op[] @hbox(6.69167+2.43333)x433.62, glue set 5.13167 .@glue(@leftskip) 28.90755 .@texttt m .@texttt o .@texttt n .@texttt o .etc. Underfull \hbox (badness 10000) in paragraph at lines 2517--2521 @textrm were re-spec-tively called @texttt fasl-op[]@textrm , @texttt monolith ic-fasl-op[]@textrm , @texttt load-fasl-op[]@textrm , @hbox(7.60416+2.43333)x433.62, glue set 5.93544 .@glue(@leftskip) 28.90755 .@textrm w .@kern-0.30418 .@textrm e .@textrm r .etc. [31] Underfull \hbox (badness 7256) in paragraph at lines 2522--2527 []@textrm Once you have cre-ated a fasl with @texttt compile-bundle-op[]@textr m , you can use @hbox(7.60416+2.43333)x433.62, glue set 4.17503 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@textrm O .@textrm n .@textrm c .etc. [32] Overfull \hbox (8.98228pt too wide) in paragraph at lines 2608--2612 []@textrm ASDF it-self is de-liv-ered as a sin-gle source file this way, us-in g @texttt monolithic-concatenate-| @hbox(7.60416+2.12917)x433.62, glue set - 1.0 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@textrm A .@textrm S .@textrm D .etc. [33] [34] [35] [36] [37] [38] [39] [40] Overfull \hbox (32.18782pt too wide) in paragraph at lines 3305--3305 [] @texttt (parse-unix-namestring (format nil "~(~A~)/" (asdf:implementation -type)))[] | @hbox(7.60416+2.43333)x433.62 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@penalty 10000 .@glue 5.74869 .@penalty 10000 .etc. [41] [42] Chapter 8 [43] Underfull \hbox (badness 10000) in paragraph at lines 3498--3505 @texttt CONFIG_DIRS/common-lisp/source-registry.conf[] @textrm (which de-fault s to @hbox(8.2125+2.73749)x433.62, glue set 12.58492 .@glue(@leftskip) 21.68121 .@texttt C .@texttt O .@texttt N .@texttt F .etc. Underfull \hbox (badness 7397) in paragraph at lines 3506--3513 []@textrm The source reg-istry will be con-fig-ured from user con-fig-u-ra-tio n di-rec-tory @hbox(7.60416+2.12917)x433.62, glue set 4.20035 .@glue(@leftskip) 21.68121 .@hbox(7.05666+0.0)x0.0, glue set - 15.74411fil ..@glue 0.0 plus 1.0fil minus 1.0fil ..@textrm 5 ..@textrm . ..@kern 7.22743 .@textrm T .@textrm h .@textrm e .etc. Underfull \hbox (badness 7308) in paragraph at lines 3506--3513 @texttt $XDG_CONFIG_DIRS/common-lisp/source-registry.conf.d/[] @textrm (which de-faults to @hbox(8.2125+2.73749)x433.62, glue set 4.18498 .@glue(@leftskip) 21.68121 .@texttt $ .@texttt X .@texttt D .@texttt G .etc. Underfull \hbox (badness 10000) in paragraph at lines 3514--3523 @texttt $XDG_DATA_HOME/common-lisp/systems/[] @textrm (no re-cur-sion, link fa rm) @texttt $XDG_ @hbox(8.2125+2.73749)x433.62, glue set 5.96278 .@glue(@leftskip) 21.68121 .@texttt $ .@texttt X .@texttt D .@texttt G .etc. Underfull \hbox (badness 10000) in paragraph at lines 3524--3529 []@textrm The source reg-istry will be con-fig-ured from sys-tem con-fig-u-ra- tion file @hbox(7.60416+2.12917)x433.62, glue set 5.16516 .@glue(@leftskip) 21.68121 .@hbox(7.05666+0.0)x0.0, glue set - 15.74411fil ..@glue 0.0 plus 1.0fil minus 1.0fil ..@textrm 7 ..@textrm . ..@kern 7.22743 .@textrm T .@textrm h .@textrm e .etc. [44] [45] [46] Overfull \hbox (20.69044pt too wide) in paragraph at lines 3736--3736 [] @texttt ;; magic, for output-translations source only: paths that are re lative[] | @hbox(6.69167+2.43333)x433.62 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@penalty 10000 .@glue 5.74869 .@penalty 10000 .etc. [47] Underfull \hbox (badness 10000) in paragraph at lines 3780--3787 @textrm bian pack-ages or some fu-ture ver-sion of @texttt clbuild[] @textrm ma y then in-clude files @hbox(7.60416+2.12917)x433.62, glue set 4.6091 .@textrm b .@textrm i .@textrm a .@textrm n .@glue 3.65 plus 1.825 minus 1.21666 .etc. Underfull \hbox (badness 10000) in paragraph at lines 3780--3787 @textrm such as @texttt /etc/common-lisp/source-registry.conf.d/10-foo.conf[] @ textrm or @hbox(7.60416+2.43333)x433.62, glue set 16.23393 .@textrm s .@textrm u .@textrm c .@kern-0.30418 .@textrm h .etc. Underfull \hbox (badness 10000) in paragraph at lines 3780--3787 @texttt ~/.config/common-lisp/source-registry.conf.d/10-foo.conf[] @textrm to e as-ily and @hbox(7.60416+2.43333)x433.62, glue set 8.5562 .@texttt ~ .@texttt / .@texttt . .@texttt c .@texttt o .etc. [48] [49] [50] [51] [52] Chapter 9 [53] Underfull \hbox (badness 10000) in paragraph at lines 4242--4247 []@textrm The source reg-istry will be con-fig-ured from sys-tem con-fig-u-ra- tion file @hbox(7.60416+2.12917)x433.62, glue set 5.16516 .@glue(@leftskip) 21.68121 .@hbox(7.05666+0.0)x0.0, glue set - 15.74411fil ..@glue 0.0 plus 1.0fil minus 1.0fil ..@textrm 6 ..@textrm . ..@kern 7.22743 .@textrm T .@textrm h .@textrm e .etc. [54] [55] [56] [57] [58] [59] Chapter 10 [60] Chapter 11 [61] [62] [63] [64] [65] [66] [67] [68] Chapter 12 [69] Overfull \hbox (2.31348pt too wide) in paragraph at lines 5296--5298 []@textrm You may get the ASDF source repos-i-tory us-ing git: @textttsl git cl one https://gitlab.common-| @hbox(7.60416+2.43333)x433.62, glue set - 1.0 .@hbox(0.0+0.0)x15.0 .@textrm Y .@kern-0.91252 .@textrm o .@textrm u .etc. Chapter 13 [70] [71] [72] [73] [74] [75] Underfull \hbox (badness 10000) in paragraph at lines 5752--5768 @texttt (defmethod source-file-type ((component cl-source-file) (system (eql @hbox(7.60416+2.43333)x433.62 .@glue(@leftskip) 21.68121 .@texttt ( .@texttt d .@texttt e .@texttt f .etc. [76] [77] [78] [79] Overfull \hbox (26.43913pt too wide) in paragraph at lines 6103--6103 []@texttt ~/.config/common-lisp/asdf-output-translations.conf.d/99-disable-cac he.conf[] | @hbox(7.60416+2.43333)x433.62 .@glue(@leftskip) 28.90755 .@hbox(0.0+0.0)x0.0 .@texttt ~ .@texttt / .@texttt . .etc. [80] [81] [82] [83] [84] (Ongoing Work) [85] (Bibliography) [86] Underfull \hbox (badness 10000) in paragraph at lines 6562--6586 @texttt microsoft. com/ en-us/ research/ uploads/ prod/ 2018/ 03/ buil d-systems-final. @hbox(7.60416+2.43333)x433.62 .@glue(@leftskip) 21.68121 .@texttt m .@texttt i .@texttt c .@texttt r .etc. [87] (Concept Index) [88] (/Users/evenson/work/abcl.easye.git/doc/asdf/asdf.cps [89]) (Function and Macro Index) [90] (/Users/evenson/work/abcl.easye.git/doc/asdf/asdf.fns) (Variable Index) [91] (/Users/evenson/work/abcl.easye.git/doc/asdf/asdf.vrs) (Class and Type Index) [92] (/Users/evenson/work/abcl.easye.git/doc/asdf/asdf.tps) [93] ) Here is how much of TeX's memory you used: 4101 strings out of 494594 55970 string characters out of 6148502 131641 words of memory out of 5000000 5367 multiletter control sequences out of 15000+600000 34203 words of font info for 119 fonts, out of 8000000 for 9000 1453 hyphenation exceptions out of 8191 14i,6n,17p,649b,749s stack positions out of 10000i,1000n,20000p,200000b,200000s Output written on asdf.pdf (99 pages, 531170 bytes). PDF statistics: 1695 PDF objects out of 1728 (max. 8388607) 1557 compressed objects within 16 object streams 259 named destinations out of 1000 (max. 500000) 1141 words of extra memory for PDF output out of 10000 (max. 10000000) abcl-src-1.9.0/doc/asdf/asdf.pdf0100644 0000000 0000000 00003503446 14242630067 015053 0ustar000000000 0000000 %PDF-1.5 %���� 1 0 obj << /Length 587 /Filter /FlateDecode >> stream x�mTM��@��+z&���?tBL$��d4��*�.�<��_���f�W�_wի�r��c;���`G�U�O�V�&�������ʮ[v���6�W�7��T��vb��uYt/N�.��5������=�S�> stream x�mTM��@��+z&���?tBL0��d4��*�.�<̿�~U��f�W�_u���v��c;Z����̫����MfG��}� I�]/��ޭ�mޯ�o⣩����0^'��^�x]f�kn{��EK{*ʇu�pg�6;�ލ$4��;��gZ8, ���M[T�P�RJG�eWxm����E�7��� ��"/���7������j;{Y��ʋ"1�t�m�|��o�ir��I ɑc�׺>[Tқ�En�n#����b������BS��EV嶭��m���z��s���g����)g��R��133w� xA�b��;��aGL6K&�0+�}&�"?��(Ҧ�a/ �c�,�!�����-f��3��*I�x �{�a����sIC%��hS���7��}�H�=ŤIY��(��jŧ �Z����4{��SO��5���Z ��e�kxvK��Ǭ����@2a�> stream x�mS�n�0��+�$z���"����aKU��^C<�H�DN8�����V{H����=��؏S`�J� m}u%���E Y]^/`�w���o����:1L���V݋omy��U���T� ����v���DM^ug{��ǂ� �pmU�7�^���X[�����{=1�+kܽ�8��@ia�����_^|Ә���\��Xq,Ɵ>�v�F�^���p�=�!9����4g��B˥0p���ދ ��s#�P~k@hZ+vQ�ڦ(��A,�R��f�5�Ħ�q8>K��_���X N�H���3$�Ǟ�{<�0��*�5c�~�P��ʯ���5W�42^!�0^#�rq�xƘ�E�3�x�� � �z�)c�gl1B��Ұ��?�Xq�!�NA��W��A*d�1��)iȧΰ��О� �9璆NVf���k��V�a��UJ����?%͚5ػb�TW�=ј��������5��2�f�&p2pj�V^��cH�Mc�VYxLS7�E=��1�j� �g�� endstream endobj 6 0 obj << /Length 260 /Filter /FlateDecode >> stream xڍ�?O�0�w�������� ����$�MD�~{�"�� �GO��A�BJ"��݁��:�Bn~�,����Ȥ��3Sei���]TހѪp�A�%&W�*����|�YW�BR��j�v���t��C���F;�s?⹾�9�ʇ�=*,ov���!?% ����7TJ5Fm����M��Z��}fuPGY��J�Ph�"�9������G8"ލ��,��v:&��@��S��4�)*�OT!Й�Y8c> endstream endobj 14 0 obj << /Length 1542 /Filter /FlateDecode >> stream xڵW�o�F�_a�� f�0po�� � ��Fm��c*�D�/��8���*UU$����|�fv���b���45�r�ÍN��y�Drw#��e����j�@�Y��n�s�]�tO �-�3��f�� � ~W�]� U�v�C~�r���o �ʺ.����(鹊��2����Y�yk����Cֱl��Ȓm�.�e��ߤ�������p�Te���K]=��AF�7�?�_ OU�����/��.�F;�N4a�����T��jٶ�FO�#1���� &�y[4-��0آn(T�NC�À!���M�� b������&��y?�^���Թ��~/�R���}i>��k�R��ڱh��_ź:�aI}�f�㏶k����k��TL��Y�����S�҄�F)���J �:��l>D�ʴz�.����O�\G�蓁���4�F�x>��nUS�́�S�6�Y�"@K�-r"-Cׅj���f��,𒘖r��� #z�=lS"��*�Q-ܠS[ղGU�ӄ!3�>�B8�o�ve�B@��2�~��������?�\Q�]�0%h�Ȭ�i�����}�u�l ��B7���X_��lR����߲`�cDc���o0V���5j Y��Q��XH���O�{�9ʿ�as(�7��(�7QvE]Ke��e������*� @�m�k�O�5Fhu�!�49_�0u�p#E�C�9�� �=��{z���u���J�=�${��( ⬤��� �R�<��<��ײ�U��CV�T �D]�1:D����z�p�e���/e� ���q����`<�OM!͞���"�P=Ǜr�.ՕC�}���()~9=�[�]�̦l���3�s���ű�P�1=Ԯ�w���J*���2��D��9�nP�V��Ÿ���Gtd�V���]u����k�+�#��n�lO���V3jo��T#��*���l��Z�^N@�(�q/U,t����HF�7�S�' �/ �S����'�j�.�(}��v�!Tw�����L�˱pH��� 7m��8��튌4��������F7�SՄ��E�^^���o�}�mc+i<Ͼ�����R”�V Z���K8 f,ő�K�0�4�3_��>~�X��K�({dQ> stream x��[s۸���)�V�A(q#Ⱦ�&M��v����>p%�V��K��z�����$ko[�ID���+��xpp���f�RԲf�ڽ����jf.���l�2pE~{���9�� �U�g�3�� ���z���f�ϋ?����o�T��2�̙R��n”��E���O�~��������a��x>��eT��4�e5QM��È�Ĵ�K� �����p�-���v5mdc��q�� `\#!oU����ja^꣯~��Gm������D=������.z�{�C��6j};���C�m�Ҋ��E�F�XZ��ݬ/ w�� ������.M���1��?�����^��؄��0io}QZZ�E�hkD�u�χn��_�����}�i���'��4qdа� $#D�8�(�L�aq�{<���a��8oQ˱Fj��*���y�^��f����|����Q]N�V^n�� 0��H�n������H3�xj x&fM � WO�����Hz�X��ʃD,Ho��Ղ4�&6�t-�ѼL�j���W�Ѽn%��:IS������)���b(*!��ʑoIT`����GE��5w�PK�7WC�t�YD^W���j��=,�p36Ai��%�"�Y�5��F���I#��!�a1����Ͷ[y��T�:�&?mv7�~'g^��ԩ��o�2�DN�J��T�3����^�>�"�=LV�_���WB�Y�}��ms9v��Q���ɇ7�:���,�豽�'��艭L�����Hޛ/1!�����/�=��0�����B�������.N�BtaJ�P�D0]7%:�M� VcT �<�������1L�P���a��ǻq�wcn��}1��@`�� �ȕPY�ʒ&PK\S��A����;lm��S���mr"�!��Ӳ������^�5�d��&�}-Jz_��C�l�y[?]�j�#vXV�a�mEx�i����_�j27T �>��+U�L'�9�MOA ��%���o�v�4��%=o6����<��~����uo� ���Ѕ��K���%ۛP |t �Ƞ6 HSq�w���jͨ������P���j� ��x�L��������A6z�����F�Y�+��ڮ�;�N� ��|?�bR\7�y29T-jD�ZW��tt�-R��|z<���S������Q�ܜ�ySjǐ� f/�C�IL���D�~��[D*�f��z�뙲/���X~�i3]��u�'���}���\�c�W��'������p�<P�W?'ڙ�Q$�&M��k;V���0��BP��y��qJk ����?v:ITW?�EMG�|LQ���˕:��v���8�P���Z���?wj�.ɜZ��瑫8i3�;�@E������m�����R�J�F_�����Щs�iz(�cљpU�� Q/A��+�@] QQ��i��)�8@�G�EҸ��w�aHϹ�@������u(>!��Ol%N�0u5>EM�����[�T��a�>L��w7�����p��H�n�~�xe�����I�X�ON��եjP�5-U����~�R6�S�rԴ����3����^24�܌�0]mhQ�J� p04l����h�l-k�}6G��P(!�DF�N�u5EMO���,�> ���oe�PB��s�!���5�@���%�"�3\�D5V%AO��'�t���jۍ�C �4�q|f ��L�C���%z"33�D5=%AGne��ۀOm�y�}Tk��~=��1#�4�/�d�q� $& / s�`�������i�^���Kͷ���zy���?T��J�y��QV��P�Bx���c��z�j����+��W���������3�Q���yPj�(K!��R�k�%��f���Y� •,�����������ל��0�6jC�ϭѴ����%��^B)�5�LW�T��(1�Z��peY���Kè���A����ϟC���%*�����%8ILWU��DQ��*& �ӥ��� �-*� A�{ ��v�� ]/A@��'������7��<�έ5�7��t;���~��dV ԯ i�y����v6��^�&v0C LWSS���T�E��O]��0��p�Yu[��:��|S_�����4�@X����&�w����&�eL`����ä%������6� hZ���2��2zl�� �vbI�\LT�St���d��/`��R����Y���lWD{�7n�����X�n{x�S�U�gx��'Q:x�d�����'�@� endstream endobj 128 0 obj << /Length 2589 /Filter /FlateDecode >> stream x��]s�6���+t)uF(�I�wi�t����Ğ���� Z�mne�KQM�� ����I�M�5'��c����C�Y���Y��r�I)����Uf��׳�����6n��A���#�f��J:���I*I�K�����Y���/�~��w��!%�ȏhRZ��(f����|�T��K�eټ�Z^�Uwh�Œs>��u�n��Q߿Q��^�%���.?��|xQG��?������N �$�:`S]�2�{zSc �e�Օ��4L�T�5�)�0��]�b޵�Kw��~�k��1�ʜ�J=Y��� ܜKH܂p�#��!u{�`M�[�I�U�[aq;J\m��C�ַu�6�se� �E�*7�Xx�p���<8]�I3��E1SyFd!<’󶻩ہ���d���H'+�*�گ�+�ʨ���8P9�OD%/����`��!�B�|�t _���K�Dpϗ�|]�X��Ղ���Rͫ�z�l�궭������o�������e��d�x~sd�z;bX��p���&���t��'��QA�P��,�^,�o�4�?�I�y.�o/K����W�p�V�Nu�� �wW����7��4+B �8�X������Ddʏ�ǜ��AxdTOo:8YD�$RH���~���0׬����b�c��Fщ /I� �1<��ź�M0c8�`B4�XbuM�5]�+��(�����NO u_�l�[�#:\�J��� :w�椀)���=� �"I��\�Y��nO��I(QY@�$���%P�� ��� 9���d����P�;�XR�p���5Σ��t )����dN���29���͘�]G���@t�ƾ��R,Z �,���!<�6B�AM��dAx�<�~��4��CΪ��m.]�����-�QIJLO��=�M��v������<����5���T��vB�ۄ��u��ߪ�:Z=�*]�lJ;_k��aY�!�B���t k��g�3�e2d��x_\@fWe��[�<���s�F�"����~�s,5�؁�4�C�n��^R�j:�D�t��C��Y�]��l�Q�:��珸'�@�D���QHݞ(X���Dd,$J��A��%2Rɉ�����(k7g��1b*�WD����)Pӭ؅R�ɀ)6�8/O����K��jS���ɖ���{|�^꟟��/e�)��c8dy8� �q��rP�[.9�-��ֲu6����n�z��mډA#���'9'ŅN,c8�E葠Q.p�� P�m$�ڥ_Y�O�vuѢ�i;�[8��GC�,$�C�� ASğv��֛~G�]��a�N5�SJ��H,�.Bq$C�(�E"��9��(�B܊�]?�U��ώ�{]�P=�y��`��l�Ԁ����)UBŵ� �a� �kP:�|�/� N���]a��~�m\C��6��$*�nj��L��f~��U��coL���\�Z�_��p�"ӯ�����HKUQ �G~����^�v������Q�$��m�h�?�\�SfW�Ep���?���;��/���[�K�Ϻs �Y��"z���?밦GO��e��s�苾�iu��gW��ֵp��t1_W[=�\����O����� h�;�Xn�p���C�)F�n@Mύ�i����/��q���e��-#M[��]{�:�d���ףl�9S�t��]�� �p��.P���r�r��r ��g��o��v=ַ�� ��4��N4� �S��'�*��1�)46N��jz�t�'��Iƫ�!m���5�Dq6u[<�������z-T�/��� ��|e��� ���΅��w��<�6�0� ����GC�>��a;NԐ � V肛�������`پ�j~�g�:^J ��TJ}r��l@��0y+��H�'X�%"�K�)ϓ����z�Y^餳]o��>�p�Y�1�5lӘn��= U��ϷG(��=,c8�AhI�����(JJZ8 �w���9m��}�j�/��\����[�JR2>��]+�s ��!�/�g�H]���:�(_���k7����)�6]��P��nQ���WO�/,xc8^A<�����qiZ5��yU߯��_��DW�iu���Yc����a��2z���5����0ƈP��j�_�7H����d���J�����Q�=�Z����! 2z��5��~�� 1N�H�_'~���U�l��fߵ�˻��n�n�2�� )�U�T��:��-�ͧz|�����1�5ㄯ8]�+��|��^��W�s�^��3W5t���o���#���>Cu�1�&����� �� ��h|�"u{OaM7[Ђ]wxO���]�����:�z��П�B�:�Et � qI ��5���Q�ӏ�M�G ��rM�ͺ�k��P9���:�]X��p����w8]��鹓���w Pw�{���m41J"�9��>�� Œ9�Cd����W� u ���'S�M�:�����ζ?�r1����I�M��"�E졦�vIψ��%Oo 1�� ���` endstream endobj 189 0 obj << /Length 2834 /Filter /FlateDecode >> stream x��]s�6���+<{Syf����dҦ�f���6��b��Dۜ�DI5��_|��&�g2I��$އ��hxV���8Ơ&�l�}R����y���O�����A�7�O�~A��@]�����B���߻ܜ�{�u��.���K�S�BMy"*�$���:y�F�>���շ����<}���/�����[����~��������̡�����vcB� ��W�2�~+�c��y�Z�oR�q�rtɄ0y�O5�.�"�\���3��D�!��(ն�'ڇ^Ê��f5��m�(���*���ծ�c3w�ζ��O������|a�� B�σ���i�1���c�``�/���?�B�V��2�M���q�L �E�f}���o��ͨ�a"���J�t}7�/�bDB�%�� ��!)���0-�9�Bc)��T��a�jz���0�x?�X«����<���{?�_֖R���_�הE�*��|e5=_�H\�H��nl��0v��8��#h�k���^����'���(>e����LJ�c2Y��P��뛶�/�$)�Mg��vj������w5���k�P�@��'ۇ�0��W���� �$�A��� ��1@�1`�v�ӻ�d\�����Ϸ�ټ�<x56��O'�Pp@�,G��QK�X�st�N�:JG���#���sCVSGwc�I�o�,�~�S`9���s�s}I�?|rc�*o ρB��LW�����UP�j������ �:Hs���2��d����Ï�ಞ�µ��� �N�U����j:������jc���ɠds9�I����PGV�}�WK�xXK��ڸ� <ˁq���R��`9�<�S**;��ʖ��G����F&�j��q�̿0��sR������D6�k��0�Ax�2}��A@v�T�F�h'� �`���KӮ��W�b#^�Ə�[� �n�ZV� -�n(� �`����=$�ܳ�|�G�+9Pk�'�V�Nfв����;��;��҇]uL�m���%<�v�� ��t��G�'������s^uӺ��f��Ɍ=�F&+���7��������j��.��Xa@�37ѽ�-�ݗ�L�^;C���L�u�G��`�\�����,�b�xk�up�ŲA��V��k���4�ܦF�)�U�i^�cä6���f���b� �W��Ҍ�zn휣ݭ�䖯6�>W�<Ԫj�u�X��/�9�C��^��]�jz�)�������>ZZ�B�Gm��^x�Ke��Җm�Rz|t��H�aP&��� zr��'�-ٽ��/�y^v�@D�!������2�5�$�)�EW�D5H����!D�Q� "� ~�γid*8ߴ�LL�i6��n�q��Qf� ���*���6Bi��ϰey�L?˴}��Ֆ�b^�]U[C_����)����1��'�d�pSC���� <�Ձ���^ZF��Ҙ�7���Os`}tiLb�q�^8��1���(F��j��kz|H �X�q�WM��k�N1(�L�0z��gVSM�h,Eq ϡb�@�LW����(b(����u���QU��j�U!5���yW�zo���;�V�غ*��ow�[[ȗ?��^k��=b��2d� �{E�j �#?5ㄽ��6�S;�,�1��~4i�kT��6�m�u y��&����c S#�h+"��nz��#��e��g�_���z���-G��϶A�����a�_�������L��C3�`����Lڢ�����M;�k�x~���� ��$n�*�Q�)�F�&+�~ �y���e�B]�}V�y�j*��������ou�R����t�lꞶ:���I��{ ��7��ʈ @��[VO�箹м �e�?޹���Vpy�w�C9)��7��k�R��� �t5YM�a����<�����0E��=�y��m���m���;��(�O�X/��a���ͥl�W_j���1lR]l(��6f5���"p`#���_d�u����Q�MNf�3&��e����w>�L�3"R��.%e ϑ�� �LW�����`��)�$���� �t��'��SF��T�����,�9RB����jR���(( �N��蹀���c�懶��E��V2L1c����%<�L�_��2]�LV�3SQPa�* ��v=�o���P+�L�ު�u��1Q�s���I ۮ��,�9@B�x�Q�B] HV�k(_q������{;޸gm�h��ݯ&�\ Ld��U%�;o��8��\#��g�>h��ۅ���w� ��\�2��Ҧ���珥($��Hnک�o��;hzݨR&��� z��ס��dহ�sɝ���It6��mܦɣ�gb��j� d�B{��.�9�6�<�b���1���TfF�⣫!�������[fz���&������7.�@��p�F�Jp��v�Ϝ�p?���6I��Kx�۰�y�O�jo�����9�&�� ��[g��tk'�[��m[��!�qx=l���h�gR�5�Ӑg(;j��a?o������`޺.���`3$v�����,>�*DL�ūHAx3�ìLWc��������y� 0{��6�kD�p7~���e�FI!D�ѦA���7���t3�{��]� �B WO�q�xH�>�iIGu��e�%:� ʰ���� � endstream endobj 9 0 obj << /Type /ObjStm /N 100 /First 836 /Length 2337 /Filter /FlateDecode >> stream xڵ[]o\�}�_����\������pQ���~pm�qkK�$���rd%��������K�3C��!-���zIĉ�%�T�&��jOT���'��'*�� �TQ�6?TBmEEi���*ണ��ji�*���U���RC���R�x��U� qO�� ���$D +�pOl�i�G� ;�+6NmTq9�����H���F����:%��6Z�z@Q#��[�j�@m ���ZGyK�����{xe�V&4��6>���\*59����� �q_��7T����`*z����hn*p��� lE�N����^{9 �`(x��2�m�uD °�Z0�ۨ� M#K�:�a �`����a �~����������2=4� ��F���'��Q��C2��N2jh�-���������.�����8�puy{qy{������������ˋ��Ӌ�\�z�⻫ӳ����^�P��`۩طߞ�-=x���.6��Gt��>����뫗O.n�3��Q:>���6=���2j�#>ö��//���lL�:��1����������X�֗��ٳ��,�!R��>}F�'��y{��������O���4}������/�޾�����7���������@p|q��_�_��۷o~3��Ӎ��b���p�� ���V���?�1>"�%>+�ξ����b_���>:�����Q�|�|���N�,u�Q'J�(D���^���� m���QŘ�{J�x��R�5�b�� �5�Գ����mR�e,T`�BkY��ʆ�Z�t���tW:&xt��j=O�ё�#�t�s1ٕ�<�IG-��t�� �f-���.8���YJ]�a�#�h�d�1�}W�&y�^ɭ� ����|6cs41������Ճ��L�|l����R\v�\���[�l�||R�ZΞ �z�b0N�c˒;�}����O;z���k���Dћ���.$p�BQ�����RЌs9b*���1��IW�孀i��0��La@�2����t�\��gE^�~~�$_��М,�S7o �U|�T�SZӜo�����b��Cf�$���O��Ԣ��ʇ%�7��܂x_�s�P�4w?.u��I�����i��|H"���S��/���G� ��9TZćA=��n#��u�#���DW5c��W8sl��8ߕ�x4׆ޱ�ol3�|�3��@v���附���c�VK�|����_�c~�� �S�N����͗jtS��H�_����Q�D��O�>Q�D��O�!6�g(��Ɠ���)��xZM>�#}���!㓘�����a��_H��l�ɚ�Vd|���c۠\�o*2� ��z���'H�4EB� /J  Y��Lz�E7��E�� !c�#^�}cD��)F� B�7�l_C-�ߐ�i_:F��p��w�CBf�1����!�S��\7�x^4�2����i#%�Eۡf��P������v�-�M[��g�;�a�*�l���mN��w��8��}�0�;,PU6��E��F�`#��8ؐ}��i�,��d3��\0�c,n7�U�*r�z������'�1G!�}7�,�'�%����3_��Iǒ�Z���j�8p���iC�n��N�k��0��q��V���R�sH�l�@��R��' �x��}��ç��qxt�O�*�Xᓆx�؎�|��)����$�<�R��qF�ա𜧫���q��B<����U|��%Nn*25k��9c�b�H������gqtC6�9��|F�75��>^�Sn�B;&$�� |�3�{I�' �T�;/~� 迸�E�����%-�[Z״(�iQ\Ԣ��Dq������HrW.�4 --TU���4x��`�i�i�i�i�i�i�i�Y�Y�Y�Y�Y�Y�Y�Y�Y�Y�y�y��4J��v�Z`7�I�����L D����d�A��3�{quG�H��\Z%cC������o��]�"���\���*e��[h�ȥ��|ȥ���G�Lcv�oQ2���t��ćd�ھ|�d���rK���2:�<�#�%w=������I��� endstream endobj 236 0 obj << /Length 2102 /Filter /FlateDecode >> stream x��]s�6���+�{�S���&���&��M���E� Zd,N(RCRq��~ !��'�|u2�P�^���C�E"���H c _lv���l{��/�u��� \;�?�����L�H\��^P��h�<_��,߮�8�����q$�P���<� �����̴����&I�|��/��c�<�/�,/�K���<�V��P�|��$�s����b-ǃT��PnV�/�Te���Pj���{=ԫ����N�^���u��N ��Y��.�2���=h|/�y���ѫٓ!�y� v��P��T��Np`��N� 7&��[�4�Օ�'4aB$�d�r NG����i��N�pU�[�¦�&����Y6���Kfü�!bf6�)<��k��8����MQ)K�tB@�+�ɓF�+�GVk*���r��fW���o_m����κ�&.H*�Yf�}�����s-� }�|��+��l Y�NOf-��, j����L�k���j�Tյ>��.���y��X�iv���kSs���ގ5�1�b�7������0��rÝ�q��A�� B��qî�A'���`��m���]��3��i�R�`����z �]n�?�b���C��s��'Nw�'�9�����O\�8��/�Ō#�i���i��TYv���܏�����yd.-֣)<�;_�z�;x��!Ȁ��G�ef#M������~�]?zV��֗-�]�|�i��E8g.8ֹ)<�;���t炚�s�.�9Ρ;:w���z�\�dr��aW�j�>��ƌtY�E;�&�r��p*rF��-9ﶼ ����n@�� �0� '<@�� �� kZ�(�b��c �e�A�4��M�~&k�j.�%X� !�G�0�Uosh7��Փ �L�>���:5���rg��T���TPst*�{�E��S%�L����Er�G�w�N����*�ws�DnO} �o��U�V��1���\��F�Xc�.=�C%�+�r�-J@HD�<��@6Q!��t���#�J��$ӹ-�md6m!-���n���ӂ���YU��wc�5�%��x����z��˃�)� ����j����m�i.t���(�G�9���4Q�O4�g���gPs�"�s�L���e�C�o�;�\.���ϭU��)���2M�L���?j����H?w��]#B�E� ���6J���،�Ul�5-���u���,��+�n��$cō�2��jD�w6��e��ہ�f�bA��C ��x@��@jʽ�P��F�a�ڏP��A�P���v^�B��F#*�/��W��6G]8��2�����iK�9�8���|��<Ei ���9�!�L����R�;P�)" $�Q�ޑ���h��Vٛ�xG�����eVV����0I��X��n,d`�Y� >�0�E����_&*�W���WPs\�Pr�S<�;�������U���)H����x�63M��l͢$�J*˿Cљ�ul�j��Y��L�G ����/��[WNx� ���s\D�*.š�!�����[���Z^h�f?���m_�� ��� ��ddy�ү���Cb1����DZ�CO��OH���r������.x�C=5/u�]t}7>�R-Ң�6}iږ��ϪL����������`���N_w�wct�;g*=�E�� r��`�"%(�H���>����l��@F���*�aRa��O����'{7� q��q�t��S���>c��A5"� "��m�Oh+X��)5]�ʋ�l.�l�]a(��9N�~Ь������t,5Sx��>μ��i���%5����>p�ԛb���΋?=��!�����Ɉ`��,.|�Dj[F�ڊ̆_��gj�9��H��d$~�6ms���g��a3+�O�!�ݩ��p���pP[9,��?���r8kK�B:� ��U�஼�9��e ��'���8푗���ʔ�b��ʺ�F*8v�G C��D����' ��ER��(8�C`A���� endstream endobj 197 0 obj << /Type /ObjStm /N 100 /First 889 /Length 1961 /Filter /FlateDecode >> stream xڵYێ7}�W�m�Sd����` $����z��Hm[�F=�z���&�u݀Gd�R�nd���{e��AY�?QB�;���\0���B�hIŌ��*B�56-l� �� �EN�Fe��^��(SY0�B�p��&��Z��Y�aF�)��-l�`Mx�A �f]�]I�Ϡ�(��(%녪�L`!�b�@N��z,�L�6Et��W�I;�! �$#t��lhI9C��������r�<��A��E� lp")٤�HJ I��r")�U�@c�o�1"V�zK8���ȭ�Q((I��H*��")�'�kب`�>�X��T Q8�� ^�p�����c$ѨG'I'���!�!D�ZS! :� L̍�X���8쀎l�q��[L ,L0e4Y:IE�5��"Ё�"���e$��,������NF`��D)z�S�sF,B��U��Ƅ)x��nF���)P�pa�F��[�ӂa�d��x�ɚ��HF�í`�$��0�aŭT� 3%��FI,N�$Gv���b����Q��}�-���~���O���a��[��i�-���u��:v�q�}�]F{��pj �^�����Z��}Ӫ��.���?,��[1�6P�wV'80���΋GA{x@��AS� ���e���w:5 �#�4������=&�Yǐ�� A���p1�`�0O7M���@�s�9�*��v/L�1&�D��8"��A�h��d�ͥt���Kvs�����h���h��q*<��7 ���m&<�NE��m�\�윶��+#Y-Q����΁�ųFK���l���0�D7 b2d��8��x �I�b����q�LLt�"n(g_�1�üp}��p��?�MJ� Q �I���c����q�٤y�l�&���׵��q^> stream xڥVMs�6��W�hT���d&��Lf:�'N?��$$��H�����-AJrI��� ޾]�],��f�)3E�"�GŒaJ &8f�d"��f�bYGL�O�$,��LF�LE�I+���<���5S1�"8�G�iN� �<��dK� a� ��E�8f��m��b��<�`1��b�8`��XLqb���Xf��)˙�X�`&�0����,����R��0k�=a �{�Y"��(�o��3� ,�X&��v�?!6�# b�A����'L��Zp hF(&���5���~�s��#����8F�HC hV1� 5D�mi, C`s��L#&a��� I5B&��"p�� V�9e �� H�hM�眖�}��R(9�Ց� �#*I��Aʥ _�RJZB���H{��R����Nj�f�R#{�����H���01��P�8�t4R%)�BH#a��"Â�r� KiQ� -�W'`N��Б 5����,p8�|(�������A� E��vv�m���[4OM�������:�/go߲�;v���V��kv!�%{�nvq�����2m��9��Mѹɪ��*]��K��]C����C�w�sZ����L�NJ �9O�����v�ɬH�� ��Cs�qeޙU��F�`�a�|^m\�����~/�^�|���NF�����»�,I�c��������;�qi���>bWfޝ`�����E��YZ�p�ob�L�yr��� �j[g.��:�C �|M՝���/����͑���˶�R��|��P�Aֵ��iW�5�wh���S���\���B���f�I�����}�pu������c�J*���5ǼU��;�k��%�Z��������k�r>�l8Y�0������/]�; �B:;��F��:/ݏ��}�: 3=��O��ƮC��m[��m�"��L�G~� ��8_=�8Ƕ�Z�qx�qB�3����T3P}�����6Z���$ �`~P����*&Uڕ���O6�юQv���L�3t�ٖ�A��_�Z����/IH�^DM�4�lU���=7��ƥu� /�z��{�4�?H�Z�����~>7n����>��2�����i���8t�s�#�?�?��Cڄ��(�7�S�<�:���F�#�����?�·=����*��� ���3���w�{q�24���g�ܛ���n�b���2�k�S٦���F����j�+Ѯh�%6ٮ����xa,g������m����/�����#)����g:{�ɹ��_nMie endstream endobj 512 0 obj << /Type /ObjStm /N 100 /First 871 /Length 1701 /Filter /FlateDecode >> stream x��X�r�6}�W��I&n�əL:nܤ�I�I�L_���,6�hx��~}� M��L;��E�ݳg/X���3�I.Wx(���g�L��ē3Wxxz�UO�\Zn��Cr!n���eB &�`Ba](�AW �y ��<�{�)'��cJҼdʇ�0��� �/�BJ��3� ) ؓ> 9�a# �N��h�qx$��@�� w�P!.@}���g7�\�_~{p�K�S�@� !��thZR� ����X� >�Z���>X�|�Ƞ�E2�"���� ��C�QH��/w��E�\R�#��p9-�4�-W0�� Zr���@��_(8�Һ@V�I!Ѯ/!#�p@B� ����h��)�]y�JZ��w�B�ᒺ�TN�j!��!�����Rx�RTB�@����hd%܅B� ��#��'>>�T��  袣��sP�*p�ljR�QY��0-d��X(hz�X� z>��|ԡB��U� �d��o�b�S����h]��Xbw�œ����z��&-����/ً ��m��d/Nٓgu�V�>��eZ7���&��\7�z��񜫨J�e���W���'VΊUY�Q �hY� ꛺�9���E��8յ1�@��͋&jZ�e����oF'��&:�������s#܍&�+��MMp��Zw��Ch0fKO픔�,K�K��^�S<�8}�DW�Í�|�fƧ�Ր�dB�m6&Q@]��mեК�3w@��(�vU�A�7�X�Y�؈�_�ˈ&N/���կ<)�P2e5��A��k�e�+�Ivc �h��ڈ�ж��5�.:��&��<�+��%����:'r���(F����G]�Y��n:%+�!�'�� ���[����㳥'v~�*����$�g�Cs�ʼn��F�ߕ�T��r���:��{ 0���*l����3�cTVT��|�x�(�"��y6&�� ���u���3��r�a����ơ���� �K� �z���Q}c�ak���tߖyg�sӵ�h%&xou�X���H꺫�+]�C�KSs�'6ޜ|��c�׉�_�!���{F?�ޔU�ϲ����|�:S��hG6���h�S֦���~Qc�Nm3_\��q��k�����/�h�sb��Cp�o?߉����J�}��_Oh���S���wr���7����m�X�Q�X�%� "��݆(�|��]��N�n��݃��Qe���|��r1�����8�����~� ��5���h{wE%��Դ��%��uel�8̎�[���]�ms��f1;e�~�I�����:�.:i=���~���qi��\VD����LOu\�{A�t�P�s�&���Lߧ�*ʲ�5Ϧ�+Ǵ�\�L ���z��|6Sq�����&n[��lq{��e��<���q��uk�uڬMc��h��X�ME(���������?k�m�s#�.�7z�b�5>F�|�z�M��6��Id?�w���}HM�r87�/��N׳�|�u�at���������tmνz]�Y2�}��%bC �k��|?Y���Uu[�׷�_�X&�4��� Om#> stream xڍ�r��>_�[��!M�k�4ىS��JU2N���EAc>��/��� 4Eq�.�h���7�6!��MnR���d�����0�Ͽ~PB��?���Ç��8ި0��\m�X%Al���~������}����(��w���7Gf�F�A�b�G�PIf��;͏����n��ƾ���ݟ˱�Zd)2�eA���?�r�~�������ƭ�V��^��6 ���ʴq'��6�^QVu5n��{�f�C�i�U�"G6�#2q��!9v��y�x��"{�&�~� 4c�N���9��ռ<8m��Sϖ��j�y�P� ���uh��J*V̜�@T�u��ޯ]Ӑ��V!g������x�e���{A���]���*��Z�"�Q��=����g��v�Z���� �\�D�Z���8��(�Z�c�;ѭپ-b"���x��e"�s.cJ2"M�J�@_=�@x�{t"�Α�Hq�/�+ �ca �V��ģS���a1W�u-��i�=;���7&���wg\� `[{a�w\ j�v�Q�&��[a���J�X2%m~=��B$�X�G�`D��\��ϳH:��4O�jo�����: MLY��SG��&K��I ��A��2`OͲFb�zp�W��x�- ��ޡ(��1ԕF�c�zp��y���� �S��[���2�p�`Ge���1=Gq+^�[����b��� m���)aJ@[<�Ky����;%'��;�$a�p����I\�>F�>�㼃�L�;�!�)��"�eg��ǔ�`zH%.2�H�.Ap5д�+ى� 9=!�����jN�m�Ҭ��E��Ċ�EA�ڟ�m�4Bͪ!0W�d�Y� ��(�Q��*M(�C�����c�"��J̰P�埿���5�y��*�Q��z'y�F�9jF�`K��T�,���r��(���d�Txӟ@D���Q�!�)I,���02JX�⨶E�� OgE+�(�R��v`�{^�]� ��Llt�}[�V�)�R�I�̼i-��g�k�Z0��������Sh�Wq^\�����x�;@?R"���]�O<��z�( ��7�6A��o������K����dM��R��j�� -�2%�.D��?�k>��a�� �X�h�x��i$�^�S�Q�����v'^ʟLJ�h�A{��l92�qՠ��c�f"�ܸS0�ʻ����I���Ƒ��ļeh��g�k�^0}5��N{+^��P��I&@t҈Ic\�T��A[����կ=�U�6et�!�1 �d�p��s������s��� �x�2�� �>u3�B+�����r������u�����n_M9W(��4�T-4y5�?^]��P�@'�<�`��D�S]�d6����:����v3���6"Ҍc��v�x���+��W8E�d�յ���*S����"[P���{�r��Ӝ<�j���1�W��"�qLf�-&��*�u� qK� �ݙz�=�J.�iHAdٵ؋RQ���)(os�hƽ����� 2��(��� ^�PQ(����8�! �N8.{�G�s/t�s�\�fSe* �$ր��/�_���S5�<��c�\s�B�-�lh�<��OO0�}��v�(����A��dݞ��8��l�_���-n ^5��_���'>`N#0�N�-����`�k�;I&���G:HhC�0���m �{�{!'��;7�@�:��5C�S�R���a�'��?0�X5�1b�c�k���0^7�JU6��U�Ό�gOM瞊�7�J`� g ��F}jF��*M,��+�8�>��].�a�+�����!7M�(��)����z�]0%����� �-����f�,���y�A�&y!R�/.GNGY����a�$s�+F0 p������lº(NJ}�~q��=�̏)��d��gM��`�w����؊�C��a�7�?(|~b�=��)�n�� �����3Lpr�̳5��O����ٶ*���\�F���SH3�X�[���˲v#f�0Q�Q�7& ��o=& �?#_ �%�y���q>�KkǻS�az'���x���)���p>�L���\��i��;p߀!$|g!t9ڞ濄*��4�+y��1<&�Hռ�b��(�}�E��z29��LN՘�N�:��Y`s���"�a�Zx���F�[�`(��D�06C~��6n`�b��3��A���/�# �J�C�+ ���D� ,����݊w��0���c|��I�TZ��O�0R���h��sO�-����ڬ���`F�(�&d� ���ʔ��$�!�K(-�~�;c�k�#h��[Ԉ5<70F�O�o�ݮ�PS~B��<&��^�Q��Y�m8���<�Nc��R{[� һ"vr��}r�(I���)%����� �5�0�W7�HpX C�^hP�3�󣐴�+�7B����g�W4P�<�`W�#�s�OX����-V����Q5�e�j�sJ��Z���<��`]��M�0�S3K,�{�f���,�b2���� o꓈�)�J�O�7��K&�x5�N\��T5�(��0���$3^�V�(<����jΆ�֧����4, endstream endobj 811 0 obj << /Length 1856 /Filter /FlateDecode >> stream x��XKs�6��Whr)5�ē`n�Sw���8''F�,��GI:_�ۻ�$���ا�fD\b��o?��2��Y��r)Y��l�y����vF��ý\ ��@���7WZ�xƊ����Lsô҇�����D̿]�����DZ��Ԉ�'*��� ����U�K��ڈ�yʓ�z1�"���2�Iחm���M�>�aWF �`A���²��S~�xN���r� �d$u=�2���R&ͮ\R���S%>�������gt���T"u�j2��}W5+��s�'��;����\�dw�R�S��়��A���z{�u��n�-˵ʿf:k��붢�-���- ��p�?f�TI�\���tG��'���8� ,E��k�`]���C�:KJz�բ��pO}i�z�;�����!�x1\.�=��?h����B���� �\��hI�f�zC�U_�M�����^�e8���[��,˂8i������y����?� j0��j��B&a? L���LJ�t A�����u�𥳐,��7��<�=f�7o��1HO���d"�?iu�>c�tR���TME�)h([e�t��� �j `QZ�U�/p��0Zw��k�jI݇u$|�Ck��`��z�B�d2�^]�f�T]�'C�%�ŀ��+�ع�������|�4� �>ՠ�CF\Qy�ع�\V���ҳ�Lj͓%`Ǣߵu�� ����4˄ n��b��lv۴���b �� 3���{����d�s!����-�L`�C\*�1Y#��� ���f�(��n {9��O-��ɼ|�|h� �A��ﳒ�����hJH��mN�>`�ua� � ��}���㶻'�i���EBf����,鱮�����|D�9���|�&�M� ��Lk���,��@<���I�G>��T�.���H��8(97�X���o)����ݹ`쐁06Ȏ���NqΜ�� r9�J1��y H���M&}�f���f%�P��c/�_�20V�9gF��"��* 8���2lX.��y �D4A��ȓ��QzL[8��i�*@ ����WNұpO9���PM��/��U��(lcuU%<;��i�-8F3m�-!H���L�L�q�d\�"�� |s��RM���W���S����I�7x��&>�+R�rW)H� �x�u���@pwǏn���],� �G�$`�(j����Y8���%� 4����a���T,J��Ts p2�qO��_X��6|c��!�s ��TM�>-"0�+؇�P�`%� s7Xv��Z�mC\țG :z�����{�sӄ������qN!s/9/km �d���b��l����@� Ȣ�*��U���Z338�����N�13�trvz�|�����S�6���}NS�ST�e��7�sr� �$f�<;�� ��c�>��9������KWŏ������2���=����3w5�=��p��_:sa�C.`w��&|��cA E��1�H�%l���s{K��@8��� O�����"~8���"�"o�~�� }����HD��go�{ endstream endobj 824 0 obj << /Length 2691 /Filter /FlateDecode >> stream xڕko���{~�p_BK�._�"q�4��ڞ}h�4hi%�HI�Q܏6��0�����y�(\�.�`�h�g&]�v�Zm� ~��*�% .G�o�_��}-��ς,\\oQ���zz���O�}���ջ�P��w���'G�j&� #�GSqj�Pw�2����lzu�.���R'�{s����o|mb��ÝL�'i,����Y�9���c��eQ�]^�v�K��@�z���Q\�Z���k���,�Q�DG��L�p �{䅮�J� CtAE�8wE~!����U�p~ �+>��A4��C��ё����v�� ��9�S�9��,E���CVm��+���p����̧�ݳ�ݾ�;  `tE�7o���{~)�UyXۉ�W��I���H�������o=�1���� C� ���ʫ�hAط,R}��C�V{���Z��۽n�f�7ʀ�iN�3R6�OT�7�j����,b?KtJ� �.����給b0o0��R~��u?�Ȕݠ *��:��(�TB{Nx��7�? ��Dͷ�뎱� ��X v��t���2������N5AJa�7(�\��38�@����%/�Z�qpJ9�����eB��n:^�*$�j�5�!� `��e'��'I�)�pɈr�d}褠�����W"��>��#YYC=������ڃ�|شTh���xm�q�n�ų���֛��,����g\ ����T`€Y�����8��*��"�r2�C^�Œʆ7u)V�~jvBejZ���[zt��5*q.��B����O�Q�`�g�M�/����g���{Y���� ��xׯ~��7G��H&�e`���7��ͷ�|.A~�;�+4#� �x��q�X�A���w*r���O����J'M������s��}j��|����TSTF!�Q�P���]�͎�������V���%J����2:#K�X�y�a�3մFG������i� \�L�� k�t؇���W���y n�Mȟ�� �r͆8���o$Mo轖�i\�E�R��| \��|*1$~�U�� N�fԅL�.�t+ �s���T���h�2 �J*Jc]�k-h��b.�^ZjU���'(4��5������Def�M#~AI��l l?��ױIg��D S̀N�����i�F ���; ��2�TTYfp��f��sMb�� JXP���QɬD���~+���.�ЎPR�^e:���-����04ӥ�A� JNu�R�*���\�zD��d�\�̽�%�Zh�T��h˸��b���'�k��8K��w����D��fcIS?����k%]<��h)~��W��MScj�9M����Շ%��<�Qz�k2#���M'5�@�!!{>Ģ����ҰL���7ԛ!ZI��Ӱ���Z�����q3�=�Jo���={�^���C=�y���^S�L�����W8�O3q��A�8��A�`����`�����( �D=Ґ �J�~ί�M�ޭ�ra4M8O/B3��~ |Z���hH�� endstream endobj 836 0 obj << /Length 2997 /Filter /FlateDecode >> stream xڝYK�����Wl�bl�bx�&��F�d���JR�Xb�� j�9䷧_x�P�J񀙞Ơ��_7�U?u��W�1Afӫ��YH�fsŃ�7ϔ����O8�{�zEW* �0SWwӭO��m~�\s�c<��ڷ6���yQ�7L|u���k_'V%�������� _���Nѐ�L�T_)k�-Nm��e�L`��(��o�M�K�D,rz68����h��4:���u��džg��P���_�����HW^^5./����Ը��,\�ˬ\3��^�rR�~�0�L/;&���X��^�r�w�� ?Q����Y*<�*��|1�k_ᗕ�{�[�Qx.b������R����$n����"$�=1����Fف��c+��;W0��g�P| �o� ���<4�C�=iv�t8 �-S�}��UE_A��9O����P� |���C�mA�H�*?�J� ��Oj���-ڧ�s�`I��_�_��%�w�����:pR��<�+�"����Y�t��+�vys�����kT�֭q�ϼm'����\ފM��Q�mJ����%+�'�O�dr���� �ޯ������a��Z*L�T%�6���LL�:w�N��W�ҁ ͅ��s����u�)�q��l�&��(�ާ�l�0@fkBN� =� �ǣS /�A�؎Q�h�x!>����|�a{� �=ݔ�1� ӷa$����I��e�F�3q-�p����1�{�L(��@� F�d�� �^'}�E�����h�&���]���;w�j~�S�F%�9��Y;��{\��nHY>��\h��!yDi�)Zg��u,1�`&{���ոd�iD6�_�Lh��fࣆ�%:�Q���z�r �z�Ū&���»uXp�1��?Oi�$���~�U�՘�j�uU?ny-�\uAT+���rB��Pd^6 ��cs��EF�!d��p��X?%��.#���iX.eO���� �,�"��#\�:6���'Ƌ��� ��܄�8h;��I�f����lJ[{!z�L&ɮ"ڪ �s���>���5�[��������bW����t�m?�#��}P�I�p� Z�K����H��"� 9��[�H������Ǻ��.���6�S� a���&�uӝB�rKb+�d�����z��ފ�D�_��;�$�H�0�@��Qϣ0�)X9�M�ΕS7C.I$�:���"d�TU � �� Mo$���+@����ݸ�$5 ��a�|��{���6Aj�nrh����uS:S���)aox:p������/dP���fƌ��ʛat3�~�����>������z(ngއ��������2T��@��<{��s� �ҟ�g���C��8l��nv�?��go��5��@<Ƥއ_H)�/��HB��E(-^���V��C��S1��:1uZ<0��$Q��s�N��Fg�)����ЂX��[<7(�Uj�pp��C��S�2iV��&0q/P��6m�dj����]�Y1S�g *��tT������{�z5螝 o���m]�N���ft��5��p#���$^q�<|}����=B�n&=����rq]I� Ω4ԓ�#NQ�F(�8���$\�|�-O��a��me�0|A�OsI�M�4nIvKu��.�ہ|$�?��v��E+wh�J���/8��&�L��)S�"���q�;E����VaubV8�l_0;�m��c��a>�4��3}p�)�hw��0J��5�"�U���'��U�ZN�� �dh� �c1mF�J����;' ��9� �ɩ���7�r���J�@��2&�HG��6�W]�z+_ ���T�*M�x :�PXSU5�����������:��N��$8�!��yl����d_�#j�͔5�F����p�p�1�� d9&�9z�z_9#u��dh�#W-[�U��y� ��4P��6s���6�|�Ia��П<����� L�x��m�ڗ��t�����N����u+p�?��� �8�Y�T�u�b0#��DAxIA=�?r/u��[�%�����-6� �"�>��$�ۘ�L�J���Ph:^�?nZ���ڨ���΃�Ch�8�=(���hpH�r���Mȳ�-.O�Яŀ�Vb~�=Jy}�\�?I� ��y���8�1k������{�rN���=��*͂~�X��g{4��{���ի ��D?ܐ4CC�zIxf �3C=%�;���O���o��ؑ�A�0=��ov���U������� L�����?6��!��?�-‚'��R�e�N�,�������fC9�K���i;����'�w���g�A���5��/5R ��ݎA6�$ i2�4�� ;�������~�}�g.�%l l����z��(��}��T_F%P��%�g)m꿒�t� endstream endobj 842 0 obj << /Length 330 /Filter /FlateDecode >> stream xڍ��n�0E�|��F������J����]�E $XM��8���5"���b3���32��d��+P~F���-��CDyMț"J�BJpNr ��T��� �6냫m�c�-bĹ�Of]��64�_�1J3N3(��1�/N�"M��#/g��c�x�V��Y�~tu���kB�:!]W��hˡk냏��i�3�;V^�I��3���d5���|D�RL�:E;?�H� F��Q�������}�t��s�{�}%� �/]�S��P�ܡ]$I��w��'(V^Q�n_��w�1|�M�K�Ra�K 3K]Z�H� ��{����x����� endstream endobj 850 0 obj << /Length 3441 /Filter /FlateDecode >> stream xڝZY���~ׯ0<h��l�~�%+�� v��1d?p��f9䚇�}�oO]�c�� ���꫺����6!�S�4�8c��&���YH��fÍ����=0�g�߼{v�:�6* �0U�w�M�� �Ѹ޻|�~�~}���oߍ EZ���`�Do� ��,n ��(cy7��G�޾l�_Beo���ov{�틷�^�Q. ��i`\� ��%f۴�� ն�:�ڜ{�(����?d]�=��Jxu�sj�Jf|�����][�=R���p��OLi�^G��O���n�K!�`��m��i�X>�޶;:��9��:Nj�͔ T��f�t�������s��g-Mf��W��mDE֕P6�pƈ!C���!T�����Nl篓���Rdp[���J1P�!�2rt� � 3�4fWg���rH�c�SO@{����ldX�9�5mI������&2n?~�߯�4���@}�&S�J�~G��3��)�ad�$*� m�|��ƹyS�s=2��C��s���%�M��$�V@�]�7���ϩ�� PX�XglSō�z<��1��6Ut�x�d� �D�qb��v /i�4<�P`��)�!���ҸX�N�����0Z�Q߿��P�/#��ln}���(X ���q?����\.:i�3��$�=j'��H���Ij �A#4��,�^�|5uM�̴��h=P ��n@ "Y?%E�[�GR(c���{6����C~.N|p[�c��Ԍ�k[d�=� �'gv�̓(nZ��Y$��l;P��*�L ")�XVm��e� lJ~=B��ɳ� R���1��ʦ�?{�}[ܔ]�����~�6d��*%�?I�j�9�e*��q��shK��9�(f�o�q�I���$���#��'�1�OZF� �<��IWsN8m�cM`�<偘{?c_�@�E�9'4��/m� ��(B��"w��� � �#� ���Z�!h0"��'G�S�a��K1�#L�xcL�䩤�s�g�+b�\tLZ���c� �Zw�.�����%�� 9���7#�EI �-r�=Bp6xƹ�y]��O�n��zX/�!�O$ztw���,D>π��cy���FK!� �z�8t�1�9��kvF���kIcBP�Zd1$�(����T��Y�8 ��Z�n���Y�E!er!�T�*��5zF��#Y"��^�񪏉� v��'JjEL��R2�H��rb���Ž ����0r �D�>���BR>�- ���-�q0��"t�`�㜯1�Oȓ�$�d�Pށb�?ϙʵLh��WA�X��v0���s�� DH�P|� ��"�͆|��0�u�\!Vl���������+2��:s���+�գ� m��s����a��|����L��E��3P��V VC.���W}[Q�{��W�R� �U�/ɵ.0 ��?p�?�� DK�;��-�l�(�l����A����q'�1��彧�� �-�`���== }�Z9���^���� R3 �\�١� �$�L4����Qx���`���R�w�t*�'�����l��5�� ����@3�� ���.@<�Q)rn�$��7g�>�)��ZBbʜ��Sc�Roᜁ�&h� ������u�6B�4�`�VF!�x�k�ɁP90�G>�"/u�y��G���FA��J1���;��iӷ0�@ )�&a��8�lJ����J@���V���%`%�U�����g���e��cݍ��4t_G�F��d��Q��:�B��xdN���OaQ?�g:�',@�i�m&#�+����v"�2���P7 �B"4'E�z��l�ŀ�L�ŧ��<��e9f%3��|��A�R�Q�}F��':�aͷ�:q� i�Rڃgs�IEn���٩M:�z���4I����s��ǎ ������{.��:�ȫ���!���#�F�� U�$\����k����~��_/_�y���^�{�Ŋ�G�;�DO��xB��W܍4ߥ�"��E3�߯^�ݽ���� ����e�> R�j����)��:�\lW!a�4���n_��U���}��A�c`�:�uV��g���ѩ�S��$���xS�:j�$�������W/,�������Ӱ��h)Q�^5@�������L؆v��� I�p���ea�m]���^ؓ�Q��¢��J��\RM�{�V��A����J�K�.�G�Π�|8I�F/>�E݁|�> stream x��ZYs7~��>�N����T*.9�W�G����ȱ4��;3���_C�"u��� ����n|� � �8sB2G�a���IC����Iδ�(3R���b��cJ| v��`Ab��Lp�N�"P�2�H���6��9���VX��j��'�DŽ r�4fyp����A�1�h&���C%�+�5+����D�P�0�hg;�� �+�?ؿ��u ��%(�hI�΁��q�b+H���,<(;�΃��� ��X"� �)A[�),�<�4��A1e��GCY�N�Ly�$��p�$ �Pq��2-�c��-�1Fcq�5����Ӵ7� �A��=�yn���I�耖�Л����&=���N,&)I ��P��a9����~��� {f� ��uX�ä��=�����$d��A��,M����`���PQd�� }� �-��!hV$V��+|�-g�`|6t�&��%]:�8�҃}ǂ�#Q@�;Z4D�a���a�!ҀQ�ip@��� ���r�Z �V��㚏� ��߸8�Qe�ԇUq�R�C9��ؽ�zw�������ɣ�O?��k6��>��p�=|޶�"N;-�c*gm?9���(>w���N�c�bi�G���Ms��K1ʻ����c1����h�~�2=9[�}�x�������F|���줘tyW�q�Q1)���vlߝ�-wq�����O���e;����Ev�Q�w�"�z֌�d�U�^���4/�9R<�'�®��n�ݓz<���9�h�i�q�&�ի�SQ��{������i|����^�}-M5,#.����Y+��pz\4iTU-q�"o���Qu~�[����ٸ�dN��ァ +,4x�U���^��:[²I�7�O��6�r�_d�[��N�αZw���8�m�ڊ^_ �׳j��,� ,�uN1�lZ7]��a��jo�a��V�a�7����X9���ռ�4��p�䖸>�f�lɝ�^�:���R����U_��������o��y�,�{��Ӣl��?�լH+�pa�Kf���yv�e~�.j����o� �������������}p݀[n3�,#�o���\>�J=[��(��g�^\i��[����Q݇��QI �v��zZVe}����4�B���_�ɨ�F�=����i�Z�ڼ��d4�^�/�QS��y��?󦜟�%J���{��]Z��l�J��!�8R�ʏ��r�w-�����p�H��Ƽ&v�,�e�����R�J� 2���h0a�L�v&�����zb���8"�Y�������K��le�j�;��v����| ��͸hO�=1>��[�mf�HY�2� T{�!�@F�3�0l��J��Y9�@�vyM�����$�ژ��F��,;��s �Y�ЅL8)+oڥh~����'�M&�do�،�˥�Ç�z��� �E�ݎ+�Q" �)����a-��oɔr<�1�N�EQ]��A¾����E�����<����š�2a#C椽������8?�fAj���K��ː��_�[p�f�y����?�������UHF��9ޑ ����Up�vt�2��_s�)/�� b��E��I� ��̆��pVV� ��t�B�4�׿�à���̪��]��c#C{�0�����Y_�[�� �DA��j���"^����Ut\r/�*���f@NY �@�5Vj����s۷�~��v�����Npa$�&@�0�I�+E������ P5p�z�1��A��L�p��Pȇ�h�\z=C�KT�AC�?[�PKࠀ/�������? �(����&�\|_�F4���$ #D4U��_� kB(���pth�Z����f4"�@��8X����ߋ�H����23������7c�@��DP1�B����2%��1ฉ/�QNa��,n� ~��q�M��j&ܚ�C?����ܠ�knP�M�`�$��$���2���/��n����+��it��I��/U�~1��Q����+O�Uq~g�nD�F�T��w��CA����7�LXzF��#W}{+�A��>Y\+ny9�!��pB2 ̲�)��m�u����dX u�a2&Aa�y�%��Eק���\V��fqM��I ���K��9�P�b��XR݌j����A��)�"�;&K�H��:=�·�s� [!��k�����)��= ��GP5��T� � �'8i��#8����uF?���*��wϨ 6���~�SR}��XPYŤN�a J'� gWI �A�I�U��ҷ�yh�I��v�᮷�UJ"�S�#�Lѯl���ɯ��-ce�A�����Ij ᠾ\����-�G�*� �%���9�=�i\1)TP�'�BWenF� �P�ȑ��4N�t!�!�o �Z�����ox����8���Z0�E�y /,ᛰw;U����aT=���dt|��i�Ϡ�7>�nY�C`��-6�x�W���*���\��t��ź�jt��k�Td-]ک��X�\ɯp�d�~,�9]�� �i�n����-r endstream endobj 860 0 obj << /Length 3494 /Filter /FlateDecode >> stream xڭَ����_!�e9���>�&�����A�� ���J�$Ƥ���,�����# ����%7���,�X�Ef�ͮ~�h{�p�߽�.�p����q���ȢLnӭ�����S~��.�Z��]hL�o�?G��my���gM�>܅*NeػO�x�����X�o�!_@RJ)�M�!�a<��T4WDTʠ��PhT��� }ޗ�����68������L��UI��Η�8��yl��K�Z���DŽ���xV�� ۓ}d�7 �]�tiP���3���C��W�I-d̷�9��w}[�Ꞛ���q2]ic�el@+_�m �R�k�9�U�]���KR�N^��z@N��ל�F��x�CW6 �D����]��H�;�-���H��(�O�\ZY��>�*��y�-v�{�$�~b�#RMm$kq%�1��<�6�\�{���d���@���Oɘw������T�r �`�Td�N4 �4s��#��� :��8����$� �׮�FΟ�AM����{���_���FO�r��x���w�6��*aA����5]��h����с�'R,Bo�� ��]���䤚4�vy��&Y��wD���#�J���������{��!�`�#����jw, "6�?q&�u����AQ+�ֱ4��D�L����Dc��L �l��'�K�}�A[[�w�"���֨pvC�k·�[�H(+���0ҙ��\���ܜ��M�wk�.#��fu���K�iߴ�kH��X �� �ˆ�eN&���o3Tk� e��(���轝 �J28�$�}S���!Ky�%q��3J.y(������Sm��}Y�-p�@�C8\tv����Ak��tdO����:v]���A��`gG� ��芞� �li�Dz#�h��n���O`Uޭ�J�tԵ���|�����cFN%f�)Z̛1 P��: �x�M;����_�`~���C����r��Up�����f�=�l���n�ڐ�(G�b�k�+!4s=V�6�֘ !JB!ʶ*ޮQ��B&�M$ʾ�f���f�JZNݽ� md�(,譍��i l�`_��:��΋���>ѩ$���HtE�\��T�dOxw����M�ہu��]F�2V"K�M ��H�C��hs�)a����b��a�����ȓl(pG��b{� �c���k�=������O@�8J� 9X�� �e*@����2,��,;sn;W`V;6'�3 �pl9|Ha�ُ�J �Ll��sy�A�(hU��Ņ�u��&����K7���|���M�njHhn�pƞNE��L�HɅ�Qe��r0� � X��1<����3s[�*�"��Ǥ��t����!T�l����32#�5� J9�bu�^<�7�R@�5�im��<@���V���;{p"8D0RC�(��h��p�t�-��Y��(�kwZ#�R�Iw�}�L����?��HH��2&K�tY���#���Pkx�����B�$<�2V��U�U9�`/9��ݪ��U�G*�8i�v����ۦ�[j���C?�=�Z�� ���ሪ��[.������n�������W���H�P'��Š�hh�g h:���Ri�F���K?�ki9M���\k,�)���({��ނ����ޛ�*�{�-L; q Q5D�x(��z�����m�N��m?ߢsſE���)!G��,�b� Z�?�|Ǭ�8�/��|���:���������R%b�Yڟ���;l�@|"���>L8��Y�LA j��*�j q{�Q������j1t��u)� ��y�v}�!q��|��H �_ţ�"��Cq:f���������9�:;D��Z��59ױ����rKs���%-h���� K�kz��?�=q����� '�Հu� H~C�vں���l2���&bw#�B��ꐙ] �5��A�芖�>�%U* ט�6�rE��C����?���\�\Ł� $�W|J�d�CQ�T�$:� ��Ku,�kU�ن�b�#���R�;.�5}����\����%+���m H�k�5/��C���b�i�Q��o9���J���O_ ��|Pb)BQ_z�oCw;i�C~�z�v�Z ���!�t�~t�S���pV׏>�B6$Z�]]nѴ=U�L�BX��5$�嶬(��O�&�6Z>f�4b&���]��av��Fǚ�A���dV:�^P%�řH�?UK��?��?%�)Њn.����0�DdV��kIO~�V_|�"��A�2�#��@�>~�6{�Ā�'��7ҠlT��We!���/��G3���M�� ��#@G�"��$s'���Е�������pm}�;���\��9��P$�������`�ߖ��1���� ��#���&�u徠j(��$K,$PX���drc_0�@���$���w*���\���l c'� "�Q�s ���v? 09���SgŒ��7�` �U�C���g2�ݛ�$�I��o^���㍵6n&&���u����gz�b������ >��x��4�8Z�y��  �;��|rɝ��0%�ͫ�NE 1�̈́��£�G�+.6�3��_��P endstream endobj 868 0 obj << /Length 3346 /Filter /FlateDecode >> stream xڍYK�ܸ��W4�V/ܴ(�z8��w8���z�$p|�H�i�j�W�<;9䷧�E�ѣY��R�,��z��b��wE�˄`��w��Y��ݎ?���|`<,8��y��R;�".���\��}�ޜ�ˠ��A�����*zӵ����{��yt�Oe��?����4���n���Ǜik�$�(#r~EHKx*wi.�$}��Eԁ�IG���|i�K�e*j�����r���Mp܍���>ɢ�E�@ `:�����N ��K�!Y, 8������l�#$�e* \�n��OY�O|�N�Y��?�W��]���ځ��I%&A�gw�IΊlw��qEO޵t�^=��_��ݴf0ec�[��$�Kb�ԈO�nlj�����^5QPgnp욦ç��� Q{�zS�9�Aڌ�IP��{��hzXJ%*z�?>2w'�WgC��hO������\��w�n��l��3v�� �^�w�AΥ\�H�CJ�D��iL{G3�'mथ�`�JݟtK�Z]����_CM��~�Y�Ϡy�2o����4 1�/{�Fe3�A ]Қ~F&�?�Apr%R��tG��,\W�D���K(~C��hV�[8Vt�<�}�W�� vl�B�r���R��������#ޢ��>��M������k�r&b�M �_�^���*f2�O�;��Tdk���&��0�r�ֺ����d��x#�� ���żLO3�bZ�֎�8t���*���Y뾥W�z \^2tS\��)� ��X;� @,=���<ғ��9D�� P��-Ѕ���p����.F[��}w^��$4AZ`���B�H3�޸�}1U�8��a��O�K��"��n����p�X:�ⓡ:c<��Pm����.����.F��6��@���֋��2~�|%U��d ���|�W�[��p�<��l��8U~bm�n�a� r�@�Z��n�%-�g��VR��k��ʦ��J�N:���Ҡ>���� 8���K��L�Sεڄ��l38�Q���X��9u8�8a��+���V�M0�L�4l�D���q�%�� �V@7A΍D� E�U$G��择��Ō+�<� ў3�d+�� o|n)'�k�_$k[W��la�O��V����,��0�9 ��U��3(d⧳ڍ��g���eΐ>�`8�F�����k�n3���S�B�Q�t�l��f��k5Ԑ�{+��4&d���XX½��Q*]�=�LW�����1�u8� ���-T�"�O�{7 �\@�����҄�i�U�e O:��i"������o_�E�GF������ȿ��!�Ma�����j},�,��!���u����^]����RU{B�j_ �������;����u���H�n�g���)/�-�cM�� H�ñ�t$ %@��UH���ﬡ��-���[���"'�՚�^σE���fri_2`PEº��U)�l7֯���8��ő�Գ��]�v�qR<%�����@������am\A�H�y4�<����R� ��.�4p'f�H�/7#$�AC��gO�����C�5y˝��F��t8W�D����z���3����v��*l}�iXXw��=*�dP����j�a�}@2:�K�f~u,m����'k�C�t52�&eZP@K�Y�Tc�����`�|��*��Jk�"�v���$�j�cY�� !$H1�W8���C�=� B�� m�b���b��#�3� �$�� )���y8�ЩVp� ��H��ɛq2��rk5o���*�� �`Xk[��/Wo��b2+\`� X���̪e�!�ʙ2��/����HY�%� � ��o7��a���̿^t��%*���Y������u3ٽa��.�]���L`�o��ˀ�^�\�;�J^�C1,R�K i�&�o�%p�[9������/�zE�jJ��%?Ż�`L���q�����݇g�͖�8D�f;^d,IŪɚ�rV� ���qH�����*�p���L�R�P����BPV�+��sᬿ�������W‚��)���vv��ޙʢwõL�������Tr���R_��r� ��'P;s�ך �@y�\}{qm�4u�V���ܻ¯��"���Dv��9T �8Ȉ�uX� ka3!���#���Tx��P�֯:���pY �M�ի�sG *� -YcBS8'�)�&غ� ���Dx@q\C&�g�aa� ��L���7�c�~k T� ����@Z��$ut��(i�A.ݵ���E���� ?X�Z,m��9� 8������~k/��8̍X> stream xڝWK��4�ﯘ�T�X���YX *pH6�!�kfLl�����ӭ���ā@mպ�R��ni�.�?�+�]�$�T���^Ş;�vD���J�s�.N���zq��;�2.���x��ڽc7g�;3�$I���GJ���v��B�������pW�o�|w��dZ�����w?]}��N��J��8)b�j���D���Xg��,g�R� f�v[�#R�9|�Yw����M]U��Fb[�51��f���n����\m;��n�E‚~��:�L ��07�HP �H�H)�q�w�#������1u�N�9���m{������G<��u�[0(U %Ø��u������8h������M�hc/sv�y�m�?!�Q{�޳0�8� (��%��4f��(+�/{��ȽN% �Y��8/�v�T�}dj�����M���vj� A���ZL�����K�PJH��8�� �W��u�$�sI������B��r�������ҷ2�9i�,ȥ��1� ��Ql}��}B4*�L6|>^�rxLT&��@�,xQJR��Bk��������>OCC���2 k�ƺ��˒ �̯gJA ��� 2f����U(�`FGՇ}��V��s�NP��xI%�zR lG��?���O�Wz<��0E���v�8")u��D�'�9ZV�'�f)T.!� �����DŽHj/���ֵ )`��PzɅ�)�w�p8uJ���e�z�DA2����!�8��?�N�ۮ��`Fr94���h��IU-a#��`"�֣��9�vr��"7�nlh�0�^@p�ܝ���\��2f3���3v+�B�[���/���� ]�s������<�#�{t��ó���]�3!f���4\������������$O��dh����&q@R��� �p1��r���q���i��o�+ㄫX���q��F�E d1 @@i^�⡝�ZoYQ�����5e���b.��8[6TB���j�R���i�헴��1�9�n��y�[Oζ�Ńn� �,$XH#�P�7��&�?���"�؏G��'!�� i����e ]�G�o����3�=�������������|3���Ufh}������u�����”�)A��j�7@�(1���l1ˠe��8��Hy�ȶ4�&_z��.4��(���.cWO��{[١�SH��ui�S����^7(��e�+aǭ`s�,��1X$��,/[(x���l� � �����鮟���x � ��R.&<� o��/�&�y������~+ endstream endobj 878 0 obj << /Length 2897 /Filter /FlateDecode >> stream xڭYYo�H~ϯ�� X\�E6󖙝,v�=0�`��䁖Z��%�8��[G7�r<@`�j����j����M��dJŹ�7�Û���� ~��������p�t��OI�'�����!b���ͧH$��w{��ݰ���["�=��Y,�Ѹ'�*�:J�vf�6��~���a�V���}��{<�Աҩę ��c��� ��a�QS�D��(��;w�;�bs�a1��B���ޭ�2��LY ��yĿk��F����Ɖ�g���USl��I�{b����Ms8�����**wL���u]ў�Y0�~[�y쾬Lթ�Ih��,D������w��ȣ]���s��s�uk��b мy��v�Ͽ��;�ȯ��ʞ�؊lTS�����"0�� z\ 0�����j�uu���<+wp5 ܃:���x�ιKw��\��*�R� ��� �B(].Jg��6x>��%>���Y��?W��ސ$6z��::�4�� ��4:�c��yp� ���+� �ߐ�r��Nt�1D!"�_P�Xf���x;(.ͦi�I��.�D&b���'6�����T�n�3R��ɊMY��ܐb �:#�91uS�L�� T�a���ͩs�!HeK!w=0]d�����J��)�����}�r@�S@���妨�^����o�/B<# ��U�B�{+���\v�����P5O�]��ݢ�4�~;�i���x�n��;��*`s�d��UG~�B^Dws�@i�6��Дq�Z`��5�t ��T�E����:qA�#�����.�F�����c�Ÿb����o�PB�g�ӳ�o�p i�O��=&6a�c�A�G*��X���CݴTN�24g��M2������'K��F�iEÍ���T��(���f����y2&-t��)�����T�Z�5�1�D�q��,��bO]�J�I��>g�ۨ;�}q_9~�Bi�P�G(<���@۱M�B���N���1t��l�ʋ��A�jP�xt�c�ﯭ�{�����O��+�eF/�\�`6P��,�;��;��~ vͩ�ƴ��\_�aؤd�کA�L~ ��d$%o�d�s��P0��C�+*DB�D���9i�Z�*��׸Ǯ'E���� ��ݕ[���71&�㔙C)�S����0�q� *�1��cٿ89�4m�W�%Z��cD��gQ���/�o���,c����+f�<��^l湂��wYo�*�G�(z>�����|�$KdC�2qjV�m8%� dv�wx��X�丌�!�h)����)��,B�~����%0�;B'k���ؒ _�:����?Ƀ�&!�}����Sz`FǃC��G�Ih.��7A >��J!v��T�`z)�i�v�����m� ��d 6nG����̦h�w]��qe���*�Ic�8Kl���� LM6ʼ����X�Hy���Ĕj�����,���a��-�K�W,�S1!�`��$˒(���<�O��S�]���ё,�sA��Dg���j�����0���@+G �<�ޖ�_ -9���:�'�*��U��4#'�i�Y[r�oY�4��G�� /�e ���������C@wyaX���j��n}��b��s�ʠdL��y%#���;�z-���6ʼnB <�g�[0��E>���J�҇��1;��\�%Km��K�!���^s�]\�D8'�W�ؿ ��c�N];���]�/� ڐ��5�c��RFe��?Tę]�hL"?�ڵ�i;�������AsDk.�3$t�=q� �n���1��Z!%Ӂ����RU���$4����:#�>ϋL�~�̌�@)����.x���$5h{�-1�_X� �H��\����n��_�ׇ[��b �ա}��_��x����΢*��¨�����Yt��Ss@8?�K�]�g�+��Y~�z�� W%Lm�nj�˨!R���`M(�㤲�f���B���a�'c��`��t�r���^�@�*��)��~��]A�In^�� �������g� xv��}�u�F��]p��hM�w*"�ַ��c�k�1O^\�b�0dOe�*�����DX!���>����,0ϼ ��)w�n�����u^z��o��z���M���~�G|�L���D�8����f��U�z8���AC�Ps�;���T��_�^ʃ�v�K�U*d�� ��ԃ)����0�5iW�Z��AMB����fK7m26:�X�� ���VL�I/��_�׹V]���Ҝ�=�Y�\�RƵ&�l9��rLl������M����u��hQF���8��"�o�B��� ��<*�g<VIz��O2*&��Nm�Ƅ��xp>� t��!�/*f���6:�e0O��|��&-iq�� ����7s������1-�y]LO}L[��w(�ً ia���$�1=�������NGx���6krLCRPu�嘶�hn�"m�ꢹ?��w�!�3��4O ��^����!�;�͋������T��w��f����io���s�V)]r�/��L�� endstream endobj 883 0 obj << /Length 3247 /Filter /FlateDecode >> stream xڵْܶ�]_1��[%2�A��,�(;��X�'[�!f��r�C�u��Ӎn�Qڵ���4@� 4��Ɗ] ��.�w�RQ��nz;hw���O�>�b��|y����$�N�Q�bw}Xnu]�~ ^��`��P)$_\�Z'��}����7_}s�,OT �����}}=�H�D��҄0�٥FGBi��i è��{{���X�E�#͕4����=�j&�c�Y��@+թ��/��q� !�ڞW��~���9��4�������!p���2Yd� �=݁�V� =Z(T$���"(`o�`ߞ�Um�k,tm{��k ] �k���Vt�7�5��x���x��P��·�}�~���?�Nv�hv_ G�J��J�w�%Bb����4J�ĝ�IUL��,rt�~�M��c7g��d;Ҥ�, �;����+a��{����΀1�&ES��iq�{$w2��;� K;%s'�g�l�8`q&����H ��E' J5 ������"B� X� x���g; �+'�ϥI�Tj��s��v�)lϛ,Q�r��@^� -6��΢$U+�dU��!I�L�C"�K����f�$:��_�����'��3@g�H6��� ���N�K�LG:O<2�9����:�C�ڇ�`���f��{����:x��HLm�H ��Ni��R#�J�1)V�"�É�- E�5ÿ<���m��h< �=[����Uk@T��3�{ �SA؃�sy\�"���,�u@���e�9�4�l��i$����ƞJF ��zO2]����Oc�껪�ۉ��f�=���$J�Z�;q��Vt���hQD|c�e�y%I�K�_��>�'�;�S'�T�%U2�"��'R���rӅ��<��e ?wv˴U ~�c��"h�)��c�(�,]k�W-�@2��k �8�i��8�>B����d&���ƍ��� �VRo���"��K9%^2B���b��QaS��r&��l� �^& ���8n�C�ѷ<�;��JҠ����tB�8 >Bi�X4A7 |?d�ts b����R�� ~/[w(�W��3�ˊ T�����CFy>�AH�d�]��#��Z��ƥ*(���v=M�EC�������Em�L�8$�d���>��l7S�y Y��;�Pu���,�"�B�@C_���,�,�T�fN;F������,kO�jO���hu:�vr+ȇ��.TI�N�0n�k#��coe��|Q�:[4�D��/_�z��������Z-&��?�<��� ���g^~�ݛ�����G�B�z;qA� ���9�(���q�9,Pb��j�m}�u�s��i���2RY�4�H�(�'�Z:�R?8��u+��Ba�+�]���Eh;���J��M�G�;�mg���6���k��,R��D7�o�-�PCz�� � w�T�;�D}�c�; �]\k �k� �l���d �e�JZ�s �mTEM_V W,���R�4u�~o����}{�,� �c�,J�$S�Q�M�:��~�\�� :�D�L2u^W�F�sמ���� �/��ٲ<u�a�. �mဋe��xe8_]D-o��ٷ�˱���d�0Xw�p�ނ� S�<���}� p�UZ��=�M����^D|���h#��dZIWc�����AD ]C�`C��<3}*�S�gw���/6/#�:I�r�ϊ���|>8��7�8�yLA�\<�< ��W!��R���w�}#]��)�D��<��b���r~�H�;+q�A�5!��X���#�s"�_��ѷ!��m"����cﮨ�߃�l�I��ލ���t���"P\E��"\ lX�;�s;U=Ȍ��r��\�w8k�Θ��#���f���s���/,���$��;�ͮ5�U�C��^�p�|-��� �H�U�رW�J�z���)d�=��H�㉱�t���.)��0(��c�dBg���p z��9�[ G�������%��no_Oҋ�I�:W��8�l�'�^�̯�0*zZ���#�����#eKON;� Og����u�>�����������+.��LV��sG������r��TsT8≮�(`�G�0��ݖo��(��O5O�H4$��)yv�r�u!�a\��'s�0��.��N�y��c��+�ry��>`8����w_a8:�=�e���>����p��#��,��O(en�4eOkԃ��F���/R& ����ܻ�H�\�dOx%K]��xSe4��M�ei�!Jf�I(.��x��ʓ�񬡩�sOc��;�be����3�����u��'6��lpSwSWHм�#�my��V��ۛ}e����c1�d�5(���0�&�Ty�>�o�H�߷�x��Ʈa2 ʏ�����j��`у8�S���^|уR�~7�� ��X�>��q9:��]�ɿM�<��"��;ÿ��w%�A�����!�vB�6ֻ7��M��e;%Oܟ��/䪝"w&�Sp XWI��릘��) ��tA{&h��b�}�c*Rn�´b�(�:#��m�/��2ݖ�\��(NA�뿁@��`�� endstream endobj 889 0 obj << /Length 437 /Filter /FlateDecode >> stream xڍR˒�0��+tC���z9�ޖ}PE�̉݃�� [JI !��QR^�P��zf4�mQTŏ��B[��F��~�T �^�/64���Xu�o7��D�*������W����uڑ�s�� )����� P�_�I����2��~�<�ׅ���T�:���c�����ei�N�� �&KN Y3��[����[����.ڧMIY6�*��Q~]c5M H|&l��X�ut���465����G���y�&���샞�C�*?��� �a�Η1iƢB ��>�����P<�ds��K*�֬L�xT��j�i5y��1���!�xe� ����:wv�c� �4�C��}�L� �4��/�^����J=���O���†Kޜ�%�D��1�n���lA���> stream xڥYY���~ׯ��K8�Ȱ�l� ����&y���%{f��Z�OUW�\rv����/VW��U�ع����.�<'��]zy������?x'�� ���?ݿ���J���n,v�ǝ��a�>��d o����w�())�x%�|qg$w"t�P>� \��ϧ낽�i}�?��/�򴷽PY�s��KC���=�(�G�A�ρ��Љ"|��sϳҽ �srmuM �n�:��2�4:W{�=�ķڊ�F�����oe�0��‘���3_��.�+��-2��I�zJ�w|�He��钂�?�=4�_t�64������&g��y!F���\9*b�lst��Dt_� ����ڋ�|?�4��s�٤�z���>|�u3v����=CL�s�*� I����[�?rDq@L��a*E��2����=�M>V�$/����U�Yc�|�$�*��%q�״�wL��DSj;�O�Q��*at�������r��&�cr�*��BIˏ.IZW �������K�F�7���=�)��q섁���э�� 'Ųju��gW]ۇ�>9��D�M�+'��wAX �x� ����z�_��p8���,����ű�1�Eb�� M��]$�C��}'�ž�脫��r���R���6�� +�֚�0y��h\�A i�NF�0 L7�aUD�7��/�m��b�M���_��5MֵI.��ޠERk, @��L�� �PΒ� +�Dq�����32� �M�( w�u����׽�� �p-Dy��W�@q@�4U��6��WA������֤\ex�B�����~�3��D��,fA�`O���cU?��O�ܚ��ףt6@��� Ɏ@���mz3���p��U��jn����|���hn�ʏ��c,�ƒx�H'F�B]EP'�p�5�~��*���k���<�tc�4�2^�0+Fˆ.� ��ws�q��A\�y�m�A&��pS��{��:�~oz�� ��XQ���.�NJ�wCG��1̘��"���6Tl�(��M�c��Έq�]m�� 3�}��ͫ�=`9�gn���`h��p�JY��<�4�#��q��c��#�Bh��<E��q VzoR9xJ��P�17�� �����z� �r��< #�[p�&uK��i�J/Nƚ�j�[�'�1�hS��'#H���%b�ߘ���pR«p�� �%ÉV�%V28�8�h������D�R�7@X��z�� �9��z���|x���-Tzֵ6 �/y�&�"�V��uI�7�F�S�SW`#���+-m�/X5�$��gzj @g������P�l�H��<��x)/���5��ϴ`Jp�"�M2��t+�����&Mcy�r�.���iܠEӐ_�����= ��!'�u��|c6���[,�B!�!�{�%}��� >�kZ� m/v�����Ck��S��|Çp�����siڞ_�3풨y�O��C���2���Eu��{�*xI�d؇��F� ��_axI�����#���zC*\�Ga%a?��n.G�-�A�ck�N��E�Ѵ@�4�'[ e��Z�!�&=�����h� �����r�2l�N�/z�I�MO[/&8�7f�G�kC���[���`[��}}`��%���|����D������������� � ����`i� endstream endobj 899 0 obj << /Length 1985 /Filter /FlateDecode >> stream xڝ�r�6�>_��K�!��Ԟ6�f��dߒ`�P�- ��O7�(��'���@����.�lW��R��Ϊ]s�����~G�����y��混>���;�&uZ���aI���}w�g���X��8���{�{ʲ^���?>�V�FZs7ݰ�Yd�P�jK,&; *>d sH��H��neRՂ���B���W��x�i�+�d �>��{�U��]/���l@Sģ� |�L��%H�R_$� ���:!�����y�Qc�� ȳ���=b?:wu���j!PDZ�������찺��Hz�4=�9��1(N�*K`<�"�}�G����!8S�O4Șb����h���׵�f܊����$��}4,^,��q��|,xb�j2r���w5֚��5�Cy>�Ӗ�G�)b���|!�Ř^@X^��s� �<��'�+��:��g�t��p��"B��䅦��k���B�F]7�`���I� �G����X��4*o�8�-�|y�'u ��{=\�Z��N�3�D�%$���,��\r�j)��A�� �^�v�% ��z�^���b���|yoy煘�:C�㥆W�_��>�v �a�0c�2�|��ރ'���}�j��Z���n��(3O�m&t�^�k��󰅾������Zie2ȧk+�[���dϓu������|�36�`���h�l���g�g5\�{��^\'���B������m�Π|3���=����۫�Uc3��U�:�R��ʬYp�u�4P��{� ��Re�kI��� �w��E�+t��X�CɗË��;�=��B��C�BM��:TdWL�0��� �rK@ơ1���H� æC!�$p$�� �[ji�?�Q-(�$�\���jJ%B9�lJ[. 9vnН��z�h��ۂ^���������̳> stream x��M�۸��_a�y�$E}MO��H�E��\�4�E�Ց%�$�d�}��#eɦ3�E�R ������M���'V%_�I�JU�6�W����+Z���W���� �}��i��������m������h�u�$I�ݬc���'�o.T[���?< ����X�;\��2[z��E)��D��r��W?�N�R��u���=S � x���B1�(�͑蹜B� v8A����@R2�$�f0}��r !M����z-��i e�;=����Z�S�p��7�����k�"2����o��6ĜHK���S�wU�%�Y!'���V�-���3�8����;��'�bľ�e��2OV�H�H kk���-|$A���<+X���i�u�gM=BdKy ��ӜI>Zot�-쒕e����z��H��,+T��Ǻ��D�r�a�U�%�Ӫ�W�Pd�*˳ A�G�z�"��Bxy��UN���H7����X������8�=�M���P 훑>�����vchY�o1�ލz��-�"��+� W��T2(KI։�V=-w���GΣzK[�H���$ս�h I���>,�}A�<��� ���>���~��}қ �,�J :j�;�G�����8wK���.~�I�U�����&� �a�;}�<\ۍ�o<�� ��>ԓ���{� #CZF�؅�XdL���V�F{3�h���.Ftkk�=�4��{]��4� �����x眥�%��9b�=� �wl���[8�}Xc��H����+�G%�RK7�q<�x[[SJe �K9V؉��i����� qd�����m��^#�������`zR�5r7zk�5H1�D ���!�6�@)�eqF kN�8�=�Z�7�wۺ�� ���� 1��Bv�q��f��J�K8�Yp\p�(o�N��v~4�J4��l�Å��,Xq�6)���j�x ���\��[���4�5��;�o%S��8͗�V��V\�aar���g�"�e��B���TP}Y��&��>X�&�T��2����jVᔷq5/}8$�?��oG3�u�b��U��m�;� sJ�1���|w���`$b�(! ��%�*W�2YPSS�y���l����^�%߯��� �;����1y���2"�!��*Gz���R]�����:�-}?};�O�X�ˢ�c��-P��b�� K�왞�C�3�@�x���� c��XB�Ϸ$N6o��}��{�y��-���g����cȰ���P��"_%gJ����x@�s��b��49�!�Cg��� UBg��T�� Ns0��W*��Tp����T&C��dI�B��3ҝ�\�2 %1� �����0LUr������DY��8�(� �AϞ���g�sJ�1!�P�^�Π�J���v���>Cz95ɩZ ӷ�4i�Ǖj*�M3���ݧ�>|q �ת�^xu��R=�3��#=��݁,�OT���:���G 閞uU�hk� �?�*g� _��Z��SL*K����=���]�䎬~���c�V��c�lzKu�9x�p X����h�B6��l�a�u�6uk�@�@������Rᅸ�O� m]=��p�������8ԚMH���j!r�X�Zh>�Ȑ���2jG׍C7M O��9@��GSrgy� ��u�MHAX����1UBI�7�:�"e��fm��p_�$�9oi�"<�?�Ea�t�l����0�?.��)*�z]?"t`<����s; q9���ã�z��:dД�`�ۻ�c+���h��~2 M�Y5�'�ђ,��4K�Il�;��/���g�'�ۃߣ�0�����B�>�;;�uTW�g3Y:S�M�o�#j<�J��@�U��i8�ne�S��5Uմ��{c�U�Y�Nt�q`g{l]����!�M=���yˀ'��O]�!Դ�>����b,�Lz�%I�i���O��U� �v~؏�S$�]M� �,�����n���y?��`�lwA�r5��+�Xd'�CS� ��68=KRP��-æ#�C-���㻢��0v`���^s�����0� ƅxa��ix���6�N��"���`kA� �r�b��V'͢ j!CS���'��d��%'�Baou2�geJ�E�E� �]۳��n��:�(��H� ���ߠ��Sw���湏�oz*�����;��sW� ��L���<�I�#/� endstream endobj 915 0 obj << /Length 3279 /Filter /FlateDecode >> stream xڝZ[o�6~ϯ�� �)���>tӴHѴݵ�E�̓�(؊��d�xl<w�m)�<��ﹳi�/ߜS&"͇]ہ�IL֨$5�c��1����Άm�qOV⎈Z���/$Z���1U��'��8�%j^��V�ՙ֨S[O��uyX������q�]��F���ظ�����Y?��GDZ$a��8�^z��aX��fI��D�d�<�n�&��s��&.b�e�*��Jb�����|��/J{�t�h�������jK��'���67J#��>�v�nWv��ٯޕ����c7j�He�Y�:Wଞ8��'� ;^T.���)e�#��(�FΌ֗-�K�0"�zۢΠ�n]㺲���I��m�Ol,MY����I�-���s0�޶B�?���4��{����Ќ���� ��_R�X�*2��,8��E�c��ΗV����Q�&���ni9P�L�H�� ��R�Ѫ�G��W��&S������Q�����`X� yx��[���1G�����]���b��E�� �$JY���)��Y�Fc`�Y��0Q�LE g~3�ƅQQ�"R˱�Ft��f�l�(�C侱Q5��.if ��eZ~R��Y� ]�F] �:r��ܢ���!̡V^|�ܡ�1;ۑ��#f���r�q����'e�(�E�>YG�{�9.����K��anM@$zA���%�y�r�M�p��A%B���X�-����F��ݹ-GMq҄��<�=�����Xkqb�"�yhܾ�>�W��j�!;$|Y���/� � Z�%+q=�Wwd �`]���J@�'A>'<;;�S�==��Q+C�M�h��J���"�R�z��Uf�qj������p��n�${�%���� @g9c?|E���-�F^�x�Yֲ�|�Ł��J����7�-����e�c��Rxzk6�9h�<}[ M?�w���}�]�Rfq�nu��))xˋvb��H=�:��|ÜǛ�����5Og�_��j��|`�5�#��Xm�����f�^��v_oX�c���+�5��a�]W5����I�)��ޠ7�6�7B dzЎM5����r��x�oô3 O/��p�\d�Iʀ]2�r�GǞ��_��π�˃�X��Ɏ�\���-�?c�&�Z��3del�$PA$��lҢS��j�$`ה��ӕ]]�}Z#�y�H!�t~d��cED�q^x�-8��D�Jr;=��`�кN��*;�H����L5��Ψ3�>-�4�H�"���Ͽp˗:����y5@�x)Y!�I(XP�(Jʠ纤(��� �^�H��8��Z�4f�+?��`��wҒ{ �4�ᛣ�1�H&��/�y!��ߋ�\��YW�lq���DU��^¸2/p�����nŴ�w��Xڭ��l�9�2�����l���o��o�W��z�����\?wP�X��y�ˀ<��8�����:S����|W5�� �]_D�c����P� ��ѝ�M9�2��4��w��c~�:��QHa� N��x��@T�v�������4t?�8�l �˗��g��dZc*Ap�H�4PY��@}�� �7�gP�b벧P"�����F��_C�!k��O7g�xb���4�D7�C ��i'��W��(�.{��l�' ��us ��V��E����K3Q ��^����.\�*@�Qa(NJ����|��8Щ[��D���kآCEΎ򈻲+A�|���mCq_��%*U�i��r��ȆrC�I������4G���xDJ%�$5W���TƁa 78M��R�Y �J [��&���T�n*N-����'�[�d �㼾�m�}�d���fd �EyP�#��%<�@b���m\3�T��ut�S�65�?xR���Ҭp�6��<履�^_p�W�î_��)q�0%6�a��u�j�F-��,�?."���xe,� ����-m=K��s�E@i�����Z�� ~�N>i������x��I��2�h��}���88����=Q��PG����EO��"�|;�DeY6K�� �.@7aY��|� ��4��C>-b��������!Y*����k�I��!%?Ԣ�%��ջ�źs%7�-|�����������=%&٤����\qZ���Dž�tvzPE3��O��ǂ��f�V���9_���1��b���X 2�R>Z.m���e�)gHd3�<��kQ�8��/0�U���1v��l`�w�F�O����!&��ؐ\��� zY!<���'!�d��{<�RX޶��|�y<��w�̧��ڕT�tn�~�h��3�B�yxFu.x��j��4js�|�Aa[��̂TL)橊�L)e��|m=�|��'U�=���:�J�B�k�� �py4��>��n]�do�B��q� �i�ܧ1}��y����7=ޔ�.e��K�A�͛ C't�-ق�$R�ܮ�E5�X<0�3����C�Mnj"=�S�L )8�����LJeݷ�:ԗf�2,/� 2���Myf��_ (��� X|$�\I*9#�_'Ϛ����7�$2O��u-�o� �@!�C-0���R��g�u�ecT3��&λ��{��ڢ�8iZ�k�2/���l�ׁj�ԮG6&B�*X�t�K�ТRnA�ܩR��^A�WJM��1����~�-4E���]����L�� �@%�;��v]#������e� endstream endobj 929 0 obj << /Length 1057 /Filter /FlateDecode >> stream xڥWIo�6��W��nKF\��Cۙ��[&F�mMdQ�I ̏/%R�Z�`�����#�<_�!/����KOw~�Z<3���;dq@������1<���O���E�2�i�בU��[@ل[@i��ȿ���yy0��"?I3y�ձ�M��fg P�1ޠh�����Ӯ�(��F����ph;�)��� c �Ɓ�[}4�<�q�Z\@�+^f�ҬA�K�ئuD ƇӂI���?�x�2@0��>��[(ى�ؼ�$I:�/V?�Ә���P[F�lLW�ҡ���Thk��g����c;l<�Ͽ�I�܌P2KJt�鍦v�S�4� g����:�a���O�}��u�J� *^3�we�O��+�����=�ٞ,�:��\p�^� t b��jew�Һ�j;eq�K�X^���nȼL����͈��?�Y�ά��ʦ�Ց�a� �$w�m �GZr��(��{'�֖��P�^��^��n���S �a��k�>U����T�����.%.'t%������[��w Q|2VQHz� t�/ŹN9HE�jQ���-��7^˾���J�r-�*��j=5��+O��5��f�N�I��].��j�`wQ�D���O�g����4��� �$t�yz�<�b{�F���Ԉ#�]?6��lED�ח�+���:���Zs�����Z�cz��%Rq�D����S?����S�:g��'�Q�cenw��ӯӰ�˴�{➅� ���'٥��5M�-h�NU쬎����;Y7���ɅN�X*��o:;Q�3��~]�s��{E\}�����L���i/j�b:q� � ����B�Έ��� ���僓s�;&�1�)��`ϙ:wo ;ځ�K���y���[BiGf��i�����o�G�2^}�^��D��Qd�ג޼ �FvU ��e�֛��y:��e Ÿ��$��o�sE�.阛��_�|n_�����>i*ߑ�a�&4{E�;ʝס�#�@u�����w�͊�e�,n��э��4�xE*�S)�mu�:Q`����w  endstream endobj 946 0 obj << /Length 1464 /Filter /FlateDecode >> stream xڥXˎ�6��WS����z Ph��E]$Y�m �DE�g�"�K��˴ǃ� Q���O^ �<��U�BJQ̢ծ�����R��~���Н �ܽy��+�؋�j���ڤ����,�;ެ]J�<�]�|���ìʫ��oOm��V�<�]&G�I�^��]B�?o~�{����H]"ϹS�G(ZC�2E_toܝ(kQ�s�S�� �w~T��TnE�nOn��z�;����/ �6r��A����Rh���[CZ����ϯ�K�4U���G��)�3�i�E�*��H�,o��<�-O�L�m��Wi�J+�h��k1�;��� Ϋ��^㟲|�Y��AS�}<�5��W�hR�?�+�x� ���� >��>B������s��M�<��b�<鎍v�~q�׺�m� ��Fd��"qp3x�F�f7�p���BU$��zh_F!F���Q쇆C1��@���w^�'�G�.��œ����1ƃ����;�-���Տ �K^}���={��K�5���\������=?��_��2����2 b>��R�G a�s�V��<���Py��Qo�=�|6�'����!o�����h��\Q�m��^]��yI���R��8 Dbc�=��أ�MK����0�֧QM�UԼI:aCY���޸����y�`r��$Z{��ıЎ��O�B �d�}���E��Y�wT:$��b��T��WjzRtp�A_٩�x��$�΂je�un!���_ި����D8���ܑ����G+CBT�[�cڌ��%Do�:K�W��쳮�,�$�gYɡX��(?�du���rL +cH����")�i��v����C]��: �݊�dF"�v- e���=����rA'��0/A��r����77�����F�Ub��.��7��� :��Q�����z�K�D�RIYU����d�5� +��� :o}�7V@X���ۓB�$D B�#�L��8�!�N��N��r���SC���M��4��!-e������JP�v�}'!<��X��j,{��K"G6zkxvj�ס>uD3b �U�H����m!�c�dr��^U��dP��O`qg���;3��3Z��>��<;5�{<9�'�tz�p]yCy��?yI 3H��-+��[҂(��c�4C�R� (��Lz��-�C����F����%>8��� �1߸�5�P�D�,�XgE�{���?���� N=��mֵ>��d���[�.1�}|��;9(�k�0�a��o)N�9ȴ��\ endstream endobj 853 0 obj << /Type /ObjStm /N 100 /First 879 /Length 2182 /Filter /FlateDecode >> stream x��ZKs���W���` ��rm�E�l*.˕ʮ���L�Րڵ��~=3���F�����4�`7��~a�|PF%��[�S!*���+6Ϥ�[���䬢�6�*%�'+2�LR E�E�Eߔ�UĜ���98E)�� 6��x!��J�o����.�Ii�aSV6d|�!Vt�@��X��+���(��2��f)�r6�I$�<�8�1���$ ��a�Nb�N�B&�d����!;��+op����' ���F�Iyg����庌�8������ ���CHH��%��O���ldS�m��c2A �j�la%'��� y� ��)$����gca��'��\�e�?Ab�l�� ��8s��v � V� '�X �b;�2�G2i����m��)A-G@HƁ#��a��#Q��4��y�.b�� 6�1O2��s�!f�Hx�$�ˆ8��4f"9�h���഑�A��<9�3�*o���8��vy�7��{_��U���.Û`'ٔE�� 4y�r2}w[�髲�6����/�f����d���E��8��0��-���ڤŪ���A�AG��!FнR/_�镚��zW�����l�,?��x3�?��������� ~����it�h� ��4S>)�_�rSW�U'�o���������F�bV�?k_W�)�����Q{D)x�� �������}���z�����g�� ���j�a$ U#X��]B��(�����&b7����O�p�]G$n� |(َ�%>�헂��M]ͯ hVM�\\����F}�7Л��b2]�f�$�c��d]���b݄�f��b9{]}n�X��0͛Y����[���kp�<#�H�i�_;��v����C}�!b�3�*��ꔴDS8�h�^~��;=�gS5�Y� y�C;��/�Q����~U����"rF�ȍ��2���+�1�7Uݢ����ОgU��R��FbFF�Z�7��%���,p@�5ADQ&�m�=)���v5�wB>X{ys�*n���fY�Z?�=Z��6"Q�y��P�h$�?Z2�������OR+,�N;�E�����ߖ�O�\���]d��^J �FU�4#EÔ������ψ�4�#���D����X��M��r>��D���?8ܧ�p��p�0��0��A���f8J �X�I��_� 3�nn]� �E�GA��X�:8��b C����IK��]|�bo�,m^>F�#� "�Bk�Gh���к����Ux@H�SZ� >�����Ny�s2 �3i���!�`C��1��Z�ˢ�7���+璹�p���4�����ߣA _i�]G� �{1��� �ArG0H4�,r2��ά<�;��m���Yg)��46�z�|mB�€�C��T� r<����r��n �C�%�4�NG˽��c�=`|���1.�Ш�R�s��<�1C���៟ �|�<��3D?2���m��]��u��˔��kR�m1_^/�p�l�-0�&x���p1؂�@�q��;�FkI0��ΰ[h;Ec4?Rý�T�2�X�nnf��ZM�Gf�`Y���|�����3<��&�X��"��X���aX���+�{��!w��|����Nu��F�=`sǚfL�E���y4O�.��7���!���,�>���)� w��k�clt3ʄ�M�R��r��v9���T����Z�f���}΅�. ȼ�W {��n�S�uY�#�%7�e}�]��΅Ɏ�NGtAH�:!�4��俻�b�o#>��ྯ�NSp�zB�޼YŜ��f~R����᪢*aE�����W*[i���7�>j�8-5�G�K��s�8�C�{��!�c$�~*�Z�d��T&��=أ���TŤ�د�z�%�N��kt���d{T3ʻ݁A�vA�����: �i,��?��z��i��:�|5[���-N^9��Bu/u7�񩙟��o妾��ղ����/i��N��������9�V��ҹ �����+��Q�ڛ��#?��t��`B?:H6��.fm���ߞ!��p��v�.�{�=�hWD���� �6m= d�>�.�9B�t�-Kd�,7aRQ�f|��e1���]6�-�EQΗgxPs �,�Pi�`��A �?�p���1��#<��sQޡ���3 endstream endobj 968 0 obj << /Length 2967 /Filter /FlateDecode >> stream xڝZm�۸��_a�Ke R��R�)�MZ�ܡ�����֖�Blː�n��;�R/�M��k��ș��3�P���U���RI�����*���Ê���+��b�Of�t���,[�4)�R��vӥG��y��u����w�X�,����B������~��==<6�[:��;YǢ�RF�\���o�>�y�2)_(:����"�0�Wy��4)p{=�eݯc��@�\� ��@-0QM� 炾��-uV�Φ����?0_D���n�k4�߷ ��� ��6�=���5uV��,jz?���R�`>U0�`,T"2ү���C|��5�2�I.��,��v�ؠ��aM:RT��-������#N��ǡM�� h*�4��2P�7PuW�Ն�u]h�BFM��֧���]遆j�^Q_����*fHeAjl��V<����z#S#�?�a[��é�.d0]$��'Å�/��=A��$�m���$��� }}�q�_.e�!aa���E� �_d��s�s�'�_�D�����&�Ӷ��M�ռ=��w�'[�oh��i�fj~���HF��s�pDǠ�� ���_��LC]F����V;x��f������%�/KIc���A��j�K���O��m6��6�B>���s��D���߂^'���wLޯSpG3 �gO��|59GG3*�u�[�x� t=�����C=�����;�j�uDL|aSy�z{�Z�֭��ƒ��ő�;9_y��?��P �,16p lV�sU�� �T)�F���7������F'Į�9\�~�,h���������� ~�<��"�u��Vn�=>5⃕ ~�����HZxnܼ�o��g��-ms��-��|6�M��*Dͪ#�M�*=ɂ2+m�ˬ��ZI�I��4��#�)�= �U&Y� ����|De�C ��<1>@�����ю6��f�}��ݷ4��8m�4�=�S��å����d! G7�sh������2��1[� �3ƺ̮�m7��V�2��Ҫ����N�P8勺��B W�b Y����kꢊT 5;��p{����J�f��-�Zd?��R :��S����L���^y�%ٗ��mK9���\��A��@��Y���b Y�G�8I5�n^�i�-)f|P��� �F� -Ai� ؾ������!"�c�ay�@k<=�π#�D�N4����7��}o�9���e����z�V���O�Q�t;Z�KT�3���H�f��u�0��[�;�i �Qxײ*���݇�}Pj�_�ه����J?��l�.�ٱ`�L��r:Ԯ�/&��9ȁ���Q40�nKc���tm�>5ϲ%/J��9�I$(X�S��-3�,f� %���w��a�Kh�c�|�����w�o>�����m��� �@�i=Adú�]���Ox��"b1�?��,���Q 2�,�xs&�ְ�� dl=e����~�] 8u�O[�F5���� ���H�0�k�9g{&6�+{�����{ɗ�"O�tQ<�u.a��x����3�� Zӧ��nER���g2����{���b����~������� d-�|y��wE2ǻ�j34�@�r�b?8𥫩��� �aN�� �q�80k6oR��*��m����W���G�dž�� ��J~�鏏�������t�cHpL���� ��'�r��o��;��F��'�oN L6�b��{H����,���w�W�L��D�P����ϙ�� �tY֣�+w�l�ӌ�F��5zM�"KY$F���o�u�^��wYФ(͉��;G�&|�HT������������I��,������ Zwh�R1���-��b���~Bp{^ޚ�M�����šh/�~�N�Ve&�����W�����?��%B���>���#�4�L�%�ā;v�I=��a����Oc� �/��(j��{Ad�D�W:��A$�$���"��5�. endstream endobj 974 0 obj << /Length 3313 /Filter /FlateDecode >> stream xڥZKs����P9���y�9��)��b�|�}�HPD�\���ӯ@j��+�g�����������M��d�ą�o6�w �v7\��?�)鷆��Y�o�޽��܍J�")���n>������}y�n�6�D���Z}W��(�������P{�<��K6�V;��Z�Bk�d���?�}7J�~����˲�����,{Suۀ,��j�.7ѩkWk�G���m�Z�"��V��|�7������=��#mt��<��rˡ-�\*e����#��>l;jV*�PC� 3��!<9�4�ȾBe�������>Q�[9�d�}��� tN@!��u���Mcg��TGߜ��vݞ`"U]Iz�.5��gq�z�2A�t�K��*��Ӈ{���y �T���I[�� �`]������� �=�<[<ۧ^f� P��+�G�lm:Rl�Odզ�=�Rk�˴)Юr�l''�xM>\��և��y,W���PW�[�����r#�]H ��L᷆Ƈ'P�ձ�Gm=�&xjYlL�{��*4�v�)�EO\�Wյ�bWܤ*��_pd鼞���Ք����F ���߾�&�E�𠫦��Ǐ+�sC��?n��R^~~d��BWP�z�PJ��67ib����ޤ�z�;���)�f�@��ݹ�B+�d�X`���$w/��K���~��=�\M�bʦ���J�;2��D#�Ed�mA�`@i�٫���&�S7��NI? ة�(Z ]��f�VIt �7� �-��c1�&al�2椳�Kn -` �.���x�v�_FfѾ��k�J��j���2C=�dGs�Tܓ�j���c �0 8nf����A��=6�ܲl�:QO� ���s��[h60,����x���M��g��9Q(H�H�?a@�/��̓��>T0��%�B@S�k�-I�Xy �O�.���Ź��4��w��ޒ4�(z�#q��ʼny�f��h$M�[3L#!��G��l�� :zl����.)���v��� �k���@9���$8��V��ŪDbw1�Ǡ"P"SsG1�`��3B��=/`B������ Jz� ܟQAF��T�TLJ�Q;p��)k� ���ՂM.�i�/�؟7�����?�S�ȁ��`Қ ���=�������Y��,�Pq�-h+�������輈�t=������� -�M��P��D��-�ж�r��4��;a��n��&�z���%�ǽ���dMK��q� �|��ư ��}����A�4��ME !����d�/��!�: `�H�@6 �V� `2�s}��:$�I~�l�q~������m���R: Z��}#�9 �Ĕp�qYb�l� $-�,�T����%�6||T��L�m*Ji�4���H�G-�` �i��ۅv��V��X #�6[p���]0��5��y2�������`pq�2w���l���} ����N�4��G� �t����R.Z����$RHPٲ��ra�y[�޴��|q��n%s��d��cyh�=w�g��d�V0�1�8 wb�S5L6�c;���鮭=K�B����Z��A�#?� �(��d������v�n��^!�J�'�ڕ'w܊� �y���1����� �e]� N�[��P(^cT%V&�P�]炢O�̷�@f��`��f���п����K���X�ю'�`���cR �r�Z�3�j��c�m>p�x����O'�Ł?��b�e_�(�<�w��á�6D||*>��adžX����u)8P��[����w���Z�#��|w�n$��vg���(�|���a�d���t��5;�(��~i��k�$��f���pKϽ�aHFz�d�n���Æi�h�H�6�����r�C 7�Lf���R�lk �C�=s��0��z� `>�u���Fr��E��ʬI)󽃿tա��%��s*�D J� uL� ���zC� �?1��b���1g����� ��=����PBI���p* ������D��!A�h��˭�b��(�� �~ m�8#pB.��v���\�/���2}�>=��V�ȩ��~��7�/��3+��q�a=<���1�t�B�q���6E?�L�*/�)��oUK��m���z����0�-\o���t�E���hk�?���=�p.�!�j^:�- <���3bӑ��3���1A��;�\�s� ��L����[L����s>����"ա����� ��  �+�{AY������]�90���á 2E�1�XF�&�\��� t��xB��(���@�f�G�r����y��+��F���|*Nj��b3�yp�?3���v8~:T`���o�@f&�;���B ���U6�W��}_v_-\n�G�)j�9�{��!���?��k�r�B�J����i �A��cs�`;��|Vb�10�5׷�a�8���S���aW/��* ��Kg�� ��荿��C�&�MϢ��>�@�-&‹fd�W!�ߒ�Y�4�,{��dq�.�s=|�4 `�$@����m!�O�� �:N�K�Q;Aa )I:W]�myђ�\V ج���q���ϟ���.����k�@��R5����˪1��q`�I� �� �3=s�̹+�`�ū� ��y�� o���X? �f��Z���Y�,|1)��< ��w�1�ʔS�9��qȔ�j�:`�SV�%�#:�l � �!�pH2���RW@�=�J�H6arK���f,��<�)۫���(�_3g��4~Q�yU-i���� `ݵf��iF�>�Z���ҳ�+IG_�J��j�m�!�M�i�_�/I_����)���ֶx~��lz��*��i`"����X�%���E����Ь�J��6�_>E�gn�7�r�-��_FCh-�R��]ٓ��3E�y����L�0�W�����k� .��8N��V6�a��e�uՕ���c�_ �_\ � endstream endobj 981 0 obj << /Length 3584 /Filter /FlateDecode >> stream xڽk�ܶ��!��,E���5��M�/4N�" Py��U���z���}�EJ�����pD� ��S71�S7e|�'IT���p~t<���|�/�p�������.MoT�q�n��o�z[��|{�.s3ކI���mhL���9V�o�#ç�in�O���#��=�܆��ZZ����O����Q�j���#�'hW��Us�&R�a��1ET����[]�nC��x��x��>�bӿ>�8hg^l��1�����X�SW�M͋m�_����y9��IYU/��������6_󮧆�v�yph�)B�݄� U���{K�e�ݒ/�4�p�kW\O�Jl���"]���C�v諎�P1��Ϧ�k���ɱ ���<�3C�6<ǧje�!˄vQ� �d��2�ù�d�~��������2�Rd�϶9O��| HM �v +D���r.t$+�%k.3����u��(@ŊQ�4��Rqt��Ӟv:��5�n6���G� B�̨<[��+���I��w� ��mM�2+3����V�w��|������Y����<���Y�8�sb�G�����m^���W��{��Lj,:굎��S{��N|P+$� �� �A��C�ta���g��M�3�:�+���=_����'�.ĸ�mQZ����u�=�5�1t�–`h��yb9c���(� u&դ������jvh���;��~�Kf������rh�*]�gC+�QVH�8@�@<�:Yఢ3slU�`{��<5�u�I�"���Y��O� WdO��oH���_��'�N� [�\��(����+�E ��Id���[�p�� �W�x�j����k#91�05��P�,����!gR�'��`�[qjȎh��e�#� �R �ʎG��v8����H,�jn�87���5l�3|Y-�z�kH q0�Ct���F�C�zO~�al�#���ad�ɑBGL>g1ƩuO���\�� ���qx6Ӽp�Dd�;�H:E� _�N�W��[�6]De��f�V��M{�X .&U ���#�v��[ �G �B;O�9�� ���%T&OI=|�،a��݃M"! 8cD�g2a����K�.�u�G����F�d�Q�m0�%�E�����>�l ���XzDt�G��L"��^m�� a �l���d��Z�p�s`:����*�5(Yi�8T��['�^c�ia��[�;������;�ұ�"K�[ڊ Ο��IR�<���Z��)K�-�2bvkI�K�bp�L'k�hO��7�4����b�E�;����T.Ro��y�lk^8k< �j*�'��d P�f��HC��4�On3� ���nG��x[�(io@)���Ųi<@�?���c2��:�WQY��gg~{����+�J�����7R5U�܌=T �O��Q������Q�+C^��G���c8��UȤ�P�n�Q�Gi��y�W�@B�|(ʲy���������-����%��8� ��J!�C ��tP�d�4�=�Oh�d�/)�ղ㚞YY�U�U��^��z)L��OR����26s��m��iA�5�e�����Yۃ�K�Jޚ!�G>�%�����S�`�־�ͭ��#�G-��حn����3��X[��)������@O��vGè�c��M�H�m'n훰'�-�.�~�x�b 7�v�rH%p'_–�⚣�0��"� v��C-O�?�g��7�`�r+QA��c��|_-��ÙG�ʼn� ���Ų� 2�舎&�v��Ն�c칰���dB�(˪��8? H� ��m5��N�Ў���y-�mR�95_jB�'/���A�(~��jǶ.�.�{��* �&�4�W�p D�ck����T���}�W��5gB�yϟ��w�'w]*@���>4$w|� �w^h��1�Ct�1����!6a�s �x[&�ؓC��'%�u���_Qn�aۗ�1�p�d�#�D@���3T� ����8&�az��%�{��� �5�)s@���V:����<~�z�N��ҫC;�z��&�&x5�V&�Y�j�+-i>TX���V����&�"�t���I�$P�$��8��{�_�pb����@а@�=,���v����_j먲������K�����К`�X#kh� ��L�}nKW�B�84� ��DE���q��x�P�EJ�m��*#��htE�8�� ��\;@A�/ť���c�K<obwtt�r1 ��l�cp\C/�X���n����i�}��k(iT1kL\��)?����b�In�N�"E�)�4x�X�ET&N=�PQ�D�#��m���B����{��ً<�c`�|?&GAA�sP��0��K;\�X���>��Q��k�'ˡ��=�z7Ay�~& ��d��� �z���m�D�^p� /0��) �j���T�^f��F���*\���]j)e`(���$��!*�9]� 7V��?����53���o�?�!��& �J<�� ��P���>}Kѷ�"��ג5x�bչ�M�\"�m.JUy���4�F3�49���m�Ղ30�ڐGh%@���߉`~�����K�6�T@�z=�!� ��Ov�U�q����mXjMQ0�!ɭA�u����ܵ�Ԝ�a��@�G:<���d@ ��I���s�sT:�$�P@�}�~�1��Q�z�vMH_�� �a ���Y���dp��qCX� 8,B�f���cb��qu󆛤� !����]�7�'j�a�(!�z*߼�蔶�9���r<6��&U|;G9�c���Sp�n'� 2^� �W��+>M�7K�P�y��il�@���m���V����i�H��HC�(J�q:-�6�������c�k�Ž3�D8n{l:��p����r�,}�a�"Aa�]!ER�z8�yF�gN�8v�L�y �E�=�J���k�|M;h�PiC�y�,ʍ�[��>�+L� m��,�t)�g�g2/�"���j{�'�CjS����(�Ԥ;�v��2�t�K�k]�`Z_v7�#J�B^��Ϟ�7���۔!V���8�ۜ����$d��}ɮBH�_����K����芽�H+8<]C啻�]�.��y�� ���1�_q�c�px��uq�� ������@� �Br��:�jW���`�${�������éU�*َ�P���U�D��������O��� �!_��v�P endstream endobj 989 0 obj << /Length 2847 /Filter /FlateDecode >> stream xڵ]o�6�=��H��E:���<�i��\��C�y����J[I���o�3�(���p8�|�P��B�]��U*e������"4������"b<}�틿�W�* �<̣���%�-�>yo�i��ƗRz��Əc�������;�����=M�ဣ�+��V6~� !|7� ��i �����=-����=�� %�kE ,�87)�G�g��+"u�"|�.�C�,z&�� F�D]����6T��e���D��#Ԩ�~Ef����kށ��� Ͽ��)�?4���G�L���� A�H�a��L[1��G���ĒT���L�l��S��� ��������\k�)��%��d> ' �<1�<3���X�^��QD�]K&Bgl( H� ���wM�5��Ls���p��HĂ�(Cֵ�I�enqH�n3�̄��C��Rp�\pY�Q�ċ"T�̣OW�� �d)СX��4 "�%�����v�( b8�q�-���G("�sW��B�T ��5nD��4*mb� �1�'&�*��25ޙ���'��;��%A_ ��Mv}ߎ���nwa�:��_�|�y���e��e�83�Y�YȭO�FB���8'i����&���O ��h�2+5� �a�� ���)�_��Q�"���"j�Tcl�A_�c ���Q�/»���~����2UĦ�&6�����8��#�\�%�{�5���k�(�R��3�\��a���Ȉ��z�tߏ�8��Z;����J�����g%�@����F���v+�dƑ#��H�'��9��.��;7���:��O����g�Գ����ȯb�q*:(_���M���Ը�J2���eo�i�u}����k�K�F��,M}��bQ�a��kę)E`v��V����V�-bL)�y��K��n�-Z��j�a��p��E� �f*� h�S򂙰 ��a,߸X����t�5O�Pxt*��X��І{��0:�1Ð��N$�/���8�\�`��|��T&ć��1\�u�Ը�!L�4� ��c��~&Q��RT��� e�X��Z�ţ3�������Y��P`o*O��@�7Va0f<��FƸ��&$-�Y���� 0?�u9�Lە�U�{fi�PA�D��J�/�B��B���8��U� � ��xⓈA��#u�H�@����^�����P yQ$�6����7gۼ�7H��\���4F�A�B'����c��o�� �����ԯK周$+��a�k��t�z�������Z��wOf��:�0P��e���W� ńz�#�����g�(�)vq������wRY�=���[.���G[z�`��X0F��Q���<��߮R�qb�x����D���NR}�[O/�P���]�+j�������9�ݿ�q�}�!�-��2��t�;�y����=M#"�����&"�}/���B I��������sj���u�=���{��;�ANSϾ����C�D���x� :S�w�,�6�L�?��m7��1 �(�bȨ}�3�š����<�� 8܍����#{�痡�?�O�Nֆ+U�"5�^wK�Jb�٢���( qaF���섗���G.hBr�5 ��XT���0=�Ѐ{��2��+|O[�o`����� �O�h��y2q+���Zq)�pB]���A��g���/�����հaq L��1>�7��@en�5v|��Z<�|wz�ᗟn޾�������u�Q�<�����}��ŋ�/W��&�G.�94Y���c.g��|L��B�29G�(���m�D(�4.�)��f�3c��I�9�ʹg����ړ_�[�a�+�IJ\h �PyϷ��ʿ� �T ��ȹ�gQM*�@꾷 ��� �~�F�k�F€&��%ʕS����o�ub����c�r[)�n�0SӲӺ�,��r�Q'��v�♈߄\:������F�Ce6Y�m?��EЦ�G:*��'O�T�;o���U�g�P�����4`>��� ��W0���#��{ށ�LI�8w�(�w'��D��E8�H_p�Hf�?^in륵��XY}����p:��A�V����'%�> stream xڭYK�������-��{o�:89d�!΁#������(�x�}�E�ԫ�c$0�*��b���G�zH�?�P'e��uV=4�w i�� ��;%v0<�,�}z���y����Nj��t\��>�=�x6�Ɏ��4M����!���;�S����'��W?ً�Ƌ��(eQk���xP��:���?����O�G�����h�+��$��졨�X�/��#8����QW�0s���3K����[����q�j�so.��щ��<�2���v;j3���<��sF���Ln跃��vG ��A�r*�UΫy~<�,ǁ� ��2�@b�6��6������������<��Gǧ�U�q�!>�� ����+#�8\N#��z�i�q��-�j� m ꣊��*����Y�ⅅHs�����".���aZ�`&�� ��ϱ�K��m`�~��e3\pf��d{s��#���3����䉂��e[F�~ �Bi�;�e��ה[������G_�č��ߛÕZ9 �9���D�9I��@r*W�R��lV��,U�^R��8�t�a�A�5BK ��n��g�h�(�qY������M�$S�?Se4�����䨉�N2 ��=da'�#z6�i�He�׳��Zwr���-��L�-f⡨��og�����37��e��- �`�T6����Y�C�߀���K�AN�S��=����3w� )��i;�5�o�'k��]��� @@�����ܥ4� ��@��y�^��"�azn,'LVf�P7spQ,��o@��f���ܷaF�)L%�ű6�:��ݬj�s�f�*�_@ N3l�foh�� ������{)�P�iIVD�C�;1[A��j�eh ������{��k����<�PD ��'V�*�i�!xm���z�7�-��0_�薞����.#0Jrۆ�Z�eF���\�0�nVa�NA�\ϔT��V �M2J�4��wT�Ҧ`eY��F�H���R����X�4�p�K 7�81�֗�z9�I�t� �~tXK3��[��jBR��)Jh�3���x�2���c'���]8ܤ�x '�`�Ĕ��d�V��~{;�:���0:.�M�f5z��P����K�D˦���;�ӵЦ��i�:�����|�lJP_�� $����y<�����'+�b��Җ��"��� T ���lQ��qb���-�n�p��ge��)�� +���h.>U�n��)L���{�r�c�� K��FQ���3� ��s�BX@���a?����}4^Ơ �z9x1S�J?�I����h`r{(bp-�\��D khpDJ��.P����q [ِ\`iz��:���u��6U�TY�*�y6���蹎u���ʨ� s�*p_��҃�a��@����]"Ն�b��n�,�}+#��iC���r�V�QͲ�Z�JU�E��z8�r,zI����=��M^��QG+6��y����� �ݶ�E�Q� �%����$� =�k�v6+-�XgK�?@H �0�{[U踮�`�  4��Lo� K�:�,�?50v6<h�,�}8�C�W�+������ } �Q�ΪЏ V��8��{v��M��mష���~��00%�/O��~�,��k[[L~y��W���w�-�T��]�ǟ\�jpcx��p� $���x\����*��� e���8�\�2����Z�Rj lOoZ��zc�;,+�Zy�eY�s��/��(�Vz P���X ����`#�Ė����u��qU.���3О�*γ<�`���:�eI���x����KZX�_�,���=��,{�ܰ,׿4���K�$+r� y�I�ճ 4��̗ ͵1 ��S�SH�1���J�+�]���4V#�K˄�im�PQ&�#/Bӡ���_yf6u���iV�k�;�� �5o\:Vӿ�\�g���{ᦤ6��UI��;c��:�Yx)-�?7J���*�-�g�;*u�?S��T��w'�a`�‡��tu��z�ڭ6p��j��#�po'zQ�e��:I� ��`Z� B �|�Z���R�ܮP�����1C��YX��e�k�n��d�� ��Ng.0�v�BՙF�� K� ����j|��ܠL�ʁ2�Cr��x��� � �vq8�'tkCa9j�nk����{�B#YX��kY�!xt�e�I���æ��]���2)V��n\i%e�����n` �S �G3�y�0�4�,>�G3�̩��**����=ʹ^�כ�^R���ow�QZ�qV����Oh9& �V8��?u�m->�9ޯ�$G{�Bef3�O<��E� ј:�֬�f�y�3�"�b���u �.�����g�]���p�g��Ё�x�7��w�@�o��م�}�x�&�9�� ��3���( �Xv�)�~��Mk?��~��s����{�U�0��_c��8[\�n�W9�� }������&`a�w��*V�7V�/�^��G�*��"����8��X�bM�����HU�e��/N ��(�f��[�����F'\|3����$����=Lr�P]�D?_;׸�_����st�+z�u ϓq}�R��ぺ����-�V��s��#��U?�U�g �1�C ����,�� �_��_v�2��R��cyCY�A���X>�Y�?��J endstream endobj 1000 0 obj << /Length 3293 /Filter /FlateDecode >> stream xڕZK�ܶ��Wl9�p!@$}sl+Q*���M�`�@ 1;�f�1ɑ��>��\��0`�tݍ��o��7er���*mq�;�J����p�ǿ���c����ݫ��Ͳ��2)���~9�]}�s��:�����4��׷��Y���%Ѷm�{���O|j��lT�=��ƺ4�D���z��W��MeƼPt�|$��+� ��n\a�N-���赞�(���v���U{�k�ٳ2�ȿ���ƹ���2���ml����?/�}w�u�r]�d*IuX�5�Qu9��mu����QG^=�{�T�Ϻ������Q��[��*�4 ��zk�8-�*��MI���g/J��i���i���=�ڍ�,�.��*w����$Y2t��ȭ�j���cw��e����g.���j�a�֞�R哌�Gm��Y� ���N��0I�RtѦej%��nƮ�]���̼;v��Rz�x��Q�}�.��s�ؑ��jl�vG�����SLX����"c�y�m�9C��x����yug�pKeg����x�i^�!Ԯ� ��I�nA���cǿ�Ӯ�?�0�YHݟ��a�:�o����2-]rX!~�rl�wZ��e8�?�eӱ3��Ob׵1r�CJ����|An، � K�;^j����C׊ ^���:􀞩�/ͱV�q^��ݞi�Af\nM1��:n,n1ü�n.��.*����Z�Guߝ�j�T�'�.w\Rs�p��A{�־� QtnXe2r$���o3���t�7��[�a��vp�֙�Ne�y�L�J�<�|:4|'�C8X���\,�4DF2�$�0���z��9�^�Z�^�o ���[���1�P!�#�� �ӽGO�~�;Y�iW����eJ4q����� �Lty���<�]����E�c6NUۜ/G�=sɐ���́KNj�z�:�ݤ�X�}C�$�]@�v;4��G�� !j�r��w����X�Sr�~�J�48��HQq��q�T}�~�axR���������������t�=�aa ��[k��C�5�۽�_��C� 6t��j�5�����l�f�6p1�ɸ��7�DSQ����t l���S���QT���2�* 4&�����Ň�B�M�639�D����[li�U���û`��e������†���X��s.gB�x ����~7O0/��@�̸���e�<��V! �{>p�҆� O��x"�x�t�Y�v#*���8����_ ��s7N^�Z�d:�JfD=$1�/�?��+Q6��w��g��K?�p��e��;a�ws(��5��Y�O���0a�aP�ŀ�d�hg/5�\�ڬ�c����O�$�c`1f�*�|hp�}������j���I�kW(����]��`��Es��M��?�Xc�E ���BNnpl #�X�rϿ e�1�`BՆ���(� �9�r$N���a�t��4��/���#� ë��������jEz�2�[�¼ oo��� �'ґG��yX�'�s`���9���}9��}#���������_.���_�HP�2��q�ս\Vi~-�6�!7���yN��/�7d����P�ID*R�iD�i��h��mj���,l>�!�K�D�c32X���)�� ��ݜ3�t����Y�S f�1y+q���w�k��1NV,�'��-A��kp�4tQZSd�[�B8C��z�^%�gl;@(c(�<�͔�Jܔ�� 1h��SY�L>Q%A--UZ�k��ߌ2�8�a_���fnW�!�<����@�P��d�:` �t �1p����2�lhM(� �E�s���Fj�2^�x��F� �/lC��"��O�?�Φ=�4��uǏ��i�! 1]�eم}Y! �m��p�z��� bI�p��z 8��s�Gq��;7;N]qa�� ;/Q]�U[��&'C�.WB��E�^m�n���W����T5�W�ۮLL���Mك\�HZ��T���L\?�O��LM��ڒ�"�0L8q�,�TK�w7R�����B�^P�ᴨ�7�� ��_"g�(W�u��,;⊧��0�!CD�����d��w��I�ͭ�:��@��lŨ�N�s%�'���!�2�U���|��3"-�c�X� ��so���)���>�0g���2�4I_T��L̬jB�*̌Up�*�Z`&t�ATL�3�*����FR��@Hz�tc�$Tw�`�W�� ?��� ��J+�7��?8�Ǎ�kI�[�R蔌���<�_E��l�&�����x�����'�p�a�k�T0r���\��B��HB�x�σ�U)'�y �="��a�����b-���;ldD��S�p��:2�wSl��%�Pݎ�ߵ�u�> ���l��t�|)�ͥzز�Be�zt*˞�m�웶���A�BZ1]4�����5.M�r�ӿL�����ד�]ҋ+��9#��5�L^'���3L,�]�c3^F`bY*G��*����� ��\m��| ,͘�#p�P�,�!����Q(!�N���O�ػQ���u������w9֬{�(}�����M� ��V��5����f���%��� �P�@G��j��r/���-�H���,O9vYKA�Q�1cw�~ђ�W��f��7�:�"��O�V��B+)��j���U���:�T�`_���\�$�e ʹ[�G�D �9:<:�� ��l�������rlwm��.?hfe��˿O�6'���Ж�e����MU�܋�EK�,��+�a���`$[\?aV�oJ��$���$�zz��.vݏMߵ�F�4��:z�{`�����3\�a��ڴvO2R��\�{Ƽ~a� ����Z endstream endobj 1006 0 obj << /Length 2228 /Filter /FlateDecode >> stream xڕYK��6��W�fK�L�����8�֤�ɖ�Kj� ͰL�Z��D�~������&�ݍ�?t7d���_�*�cV�|U6o";�=����o�[��p�����$Y�Q�W��T�v��w��Y{ݭ�8���~J�?�?".�������1�y��gl�`��4�y!�D�����7��E��4W���\2K��a�E�Ӿ��(x֝�!��m\�lk������U{0����`��e�4����y-��=Qg����-���ű��\��zj���`��03���� �W�QB3���v&jy�'����<�����j��T�# �L0��Ә�Q �����-��,R��įB*�����TNW�<�L�ĐÞ�vdKr�`i2�}g�8{{�mר����;��SO�?�$j᠝?�r X�����R�8�3oݺ�D�=Ӝ%�����Fp����/������U}Kߝ��h���L��ќ�s{�w�~�k�J��s��(;�D��<ة� x� �I`�N�f�ѢHY1B���?$HX�N��8��{��1�B���3��+�u�`�������-BO���>���&�H컶��w_~���i�ƌ���ke*,Eg�OQ�$N�p��:LRl]kJ&��*�1��aB=�( һ�Ǹ8K���`���)�…�/��z�����)"�-5��i�d���`Ԝ���7�K�L{�!Z s_�Ib-�(�tU���^/ߵ���c�>u�i�.��"�8��u��uh5� z�]�}*k( ������c��d��ńѝv&v�PVډ�;i�w�R�����9ܛ�Dz`"�� 0� �,�)� T DǸC�Q�r9�x�� �h�m��`h��ھ]�&ͧQ�T��{��"�}�*�,����&� &�b_0�@x�|lM��]t�v�����t�)���"y�"�h�A5�Im��)j���,��p{�j&R����Q,�kYH9'ZM|�a�i 1Ć=M�Z�P���hwV�p���W�g8.N��ck���0c0-Hq_�ʸt�|v�|�,�$�����3L�,*f ��Os_H��[#�t���d�!��'cIp�β|h *o�f�H@eY�F�ڶs� �wzOns,�v؂�:'��p˻�&���R`��S�m��6�xSAl�\����@�6]&��m��|t>��6Ƀ��(,�&r�LΊBx0�sXW�K��9�FЮ�q5�`�#�-fQ6�;m7��ې��Z���Q6M�YL� �4�q\ G.��i7�+7P��U^bp�l`�KUפf�y��oO6@�rf���`��幘]�K &f�K�%�򘉌_؜�p�Y����J���L�]���υ؞�a9��;��n�^�S���G��΋WTr��K{e�B��| �59@�1rI�`Ò����k�x��E�@�)�bB�A6���~\a�Y���x)eA����$�B�Z����=�o6�@85aYkȗ�h�;{�4��l��mi������[O�4\� ��͗d��(���� ������[��0�W�zJR�~�sf��� �õا1H�7�/�Lz�А}��*5�b���Ʌ�P�KP����~qe�}O�����H�V�gtW��=�)[Q��n�����%�B��<��,J9<l@o�7�Uns{��7ܦk'�Evlc�sB�@���"�9��Q��h-/�=(�b�$EP���[x3V�,�rƣ��9� (�1(�Y��_u��r�c�^���)�E4�В������@yO���푞u�����Ӌ�e�T��9 ������_*0�K9�����5B8�d2��?��������Ǝ|T6>`χߺ���ipO�O_�>��������O?}~��w��tx��濅�{g��Q�OԽ��︛:����ig �l ����۱;[�-<�P��g<��8uGw�3���쉁ko�R�����3�� u;e�!�mT];�.�̈́�M��2Z^o�N�l8~8��,�a�A�b �Mÿ�6}��2���U�a�+�U��w�#ߛ��+΀�*l?j��c[���z��ڍZq�T��ʔлrʸ��J�sboy���3f�QO��*P�9������� �S���=��E���ƁJ˺��7��۟�n9��ȖU��"��Q��x�fw��!�va�w6��ܸ�V �6�B_i_Ѽe��'�d�� endstream endobj 1010 0 obj << /Length 2419 /Filter /FlateDecode >> stream xڭYKs���P�N�"$H]RN�M�c�K��Eb4�8��$��t�Ɂd9��Zh�����o��o��FK� ��T�O���7����?q7/���b�_�?�~I���")���~��}}�s��Cy�̰���Qv���J���ׄ����>���9��yn��TT�=��b^!"��~����g�R!>�:μ�=[��eʊ��d�b\*��]����?�.n��������1���~��Z;�5I9��I[ ŊN��f�?��n ���`�Q��P�|�o�;�� ���H�/ P��8Qg�G�N>�y�!���l�rG �q��f�������j�}���͢�;v� �� ��{�`��6��J�^��q*�����M�7�`��Y@@�\r�E;ؕ m+���H����C�оb/����m�=�]��3��rx��2�L�Ʀ���;���4h���c���,�OO�{�VwB�!�n���M�B�ʩ�;��c�j� ��.;wj[{"�#���HY�0�W`�jm^��߂G{TnWٓ��2&��Kt0� p:��nƠ2\�+��|����kˎ��l[SS{Be�|Q�k�;��=�R��j��-�dI�7t#NO��Wj�b�?ԃ{��[�����t�"C�+��e%�"�ܢ�Ə�gak�����R�7���8{�$v@�3�y�n�g�9�u�K�� ?c�0Y��Ul�Z� �sT�h�����.t@�"/l��|k��CVFWL�|��W�؇��ɂ���3��;��g<7mK�q*��� �$���Xk��9Lt.�op ��c�J��|��sӟ� x5��>t.�|��Z�(2�^t�Ӊ0��$ mu�SH?xQG pƓ�q�7n��$�Lh�R)<�^�x��y2D� 1h��t�sI��8��%�}@%I��#�ް�L3%=#w��!v�����9�X��M��ؼ|d�Xq�fW�=�8P`۫�@�R�����^������6.�36f��u�c�)�(S ˷qdvu�b�{K�lF�Lݗ����BfQ�s�gq���c^J [wa�)��p�@rH�RІ��� s�.��T�o��YK����] \��Ʈα�4>�m3����H%����qk{H���Դ�#� \�lA�]=4����^���#h��ػi$^�5��J���*�� ۢ؄8 �IY� ׷>�ƙ ��һ�V���x��g�uZ:�A{�8K�loxs��x]�(����|�D������r�T� �x�r�:xU�r��W� �.�BY�vS=��E�Xf^�������� �.�9�P�&���OrGb��@�ii�mံZ�j a�ILJ�X��a��|C�5�_�s��SR��Ks�`D �R!~��K_ �׷E�hƕXZ��'�œ�I`{y2k��r���o8m=��-���d��D�H���j3u'�ֺ;H�e�z�D�}���z�ǎ4L �GP��r[0�w�d"ɛ���&��]�鞆t/W6S�]�@t��]��$#S��-a���Z6E �����2�hj��)���M/�12r��Va��z� Q� yЖ�R��DaE�?��J�H� �t�D���'�2�rYE_0��]u�^���(�;����U�_ľ�����W��Wq���� ��� L��� �I �#�����;i�o� �*�[�����6�}7�������J~,�}T*R DY ���F��/T�c�a=�P.���V���!+�@^l��-�R���w�S� ����bF��te�v�b��RX�,t'SM�jLgL���+8�� #x��6\}Bo�e:(��7Ҍ=�C�A��Zğ`�$��z#�?��B������q���.����8s)������I7΢^�,�s�7�=�ҿr����LeW�?�0F����������_���wK�[ɷG\�V c ŒWe4��H޿�.H�%+���8��WbՒ%�@�Ċe'�ڿ1��g��X�T`�X:3���%@(}����ȕT��D��\�l�e�h�-2D[(�Lq�y�4o������� ��ۼsa�^�l�E��[�ȱ�^�`�S�m{�܅�m_֎r0!��0��X�����r, �������Ji��ƾ�KwSs��w��F��^�@�.��� ��0 ��0$�U�����A����(�2l��i���~ �r����1�\2�P~��\~Դ!��<����):���)�L��6c�F�Q>I�IZ�,z<��M���"1� �q ��=�m�W�! ��3,.�t��[q� 抅X�c�X4�g�oH�Ƀ[Y��� ��Q���R���9��Q���i�FՃm���,��@�[S���X ������d��{ݥs��O��.؉Z>������� endstream endobj 1014 0 obj << /Length 739 /Filter /FlateDecode >> stream xڝUKo�0 ��W�EjՒ%'έ[�;���jˉQ��d�m��G=�:[� C���>�_2�R���H�e�Ⴍ��[��To#/|�� �0�!�o�W�G$�EZ�hS�]m������:N�,C�:N��Rޤ��M����a4���ؘ���d�o��RD��������3#N�?R�ȿs�W ��y�㡋� �� ��v���t�2� %�s$�D7�� �� 5�=e���I����ֲ�WF���(��.{х��Z���?����]+Mi=�nC�`��(K(R}LP�. $��X���<��D�y��E�a�}���6I�U�GeYR��9t�t�%R{��V�a�pY�ˋ��+/ل�e�Du� �K���ſ����,'$>�-�,njA�I�Ih�M�S�A��b 9�hm� m�D�`��QU��ڥ��e ā��p^¹��^{��Y"3���7[�?�fV��Zy���N�� �P���}Qre$���K�ڸ-��_L+]\C�m�,0ǹWT߆��U)�x�)-`�l����n� ��� �����+���z�&O6�0Xkv\�RA{ٛdf��D%H�c�*����GP���a�6�)zh��k��`E>�Y��s��U�iTo;uf�^�b�Ѥ�m��OPܳ�G���fk7_i�?���l�]^V�o�p/��������w���MN|���Ѳ4JNV7�9��d�2{3O1�>o��Sn)��/=����j96�������( endstream endobj 1020 0 obj << /Length 3554 /Filter /FlateDecode >> stream xڝْ���]_���U"�9p%O�%vT���*?�~��C^@ph�|}� ���ڪ�=3=}w�]�.��Rc��fw��F��7~�� %p[�� _߿���8�SQ�G���?��J���P���_�m~�����b���H��93�w* ��-� X%� ��|\��Ɖ�7[��fkR��l��v����� ���~s��߿El�/7�i� �A`[�GA��w��c��2Z�y������6]��N��C?mt��3����S���]3�?��fkM�n���P��~p��z�n� c��FxeB+�BA�%V�H�-|��u�P6uσénG���Pu�i�����dǦ浌Mσ�����O��ܧ��}�P� �fhh�]S�D��6~iYw���cW�Ϯ둫Y0wӠ��y�vO��OD�e3�T�d�ِ�o7ܥ��T��ʽ�H����XV���p(�dH'!Ȣ���~l��M7����� KP�weQ��q&�t���۷?��R��]W��C�5R�rȆ,���a�Q���+v���J�'h�a�ܨ�+@de=� @���+Z/7������o�����Ԏ9�_�TV�9�Qu{���B�f��R'K�t�'Ub< ;Xܶo�Eև]��dL�n��Q%�LC�yϷG�􂇎O�%��'`��ʪ�R %���'�(@�)�ة� M6q���U���0�P"�+�#{YV7<��L��t�"��,���=qS\6c��ى�*UafӅ��G�}u�����%a�� L���9���]�m�a�38v���f��.!B�Kހ�xpװ %�82�O� ���e8���$ �,��玣��!��l��(A��gO����Qh)6�;0D���?mQvز�hb�Oi !P�m�?��,��r�ʶpe�os� ��ف�d�X�c�uC������XV� (d��&ˋ��`�dTC�o�![βV�Li����рg>ް˰(T��Ѷ s��c�Ƀ�d�8�~�#�ꆿ�uj�u� �\��- �z�}��KM������ ���d�Ih{+�R�FKbZiRT_�X�%�(� ����<��� I���E˧�o�. ��'1a8�Y�D����d1)v�(d\�Y��������lZ3J�l���P��K�>����0.��Ϧ�74���q�[Ҟ��rnzT0��3���߲�ap~� �6�RY�_�S�{P�?k.��1�1�9�g���p��72_��"lK��b� �0��bx��r��vf�I�(���jA��{�O�"���֊޼{��;��ۀ[i)E��=$����� R���L ����ҡ�@�6l)�R��ɳ��8_�\��J=֗���}j+ zA�?�OS�֐v���G���X0艛/kI<�0q#�C4��C�LV��e���hP9����]Ka�&}�����@CL��g��,���X&,����f���P�~6�6F���A��u��*�<��8g7e���4^�#0��9� 2ߍ�М�� �~���Óhü�����/�Q�@# ��H]9T\Y~�l�~<�J�K��@�2%��"*�zc��L� q{J ���a�I�0�ӥ&a"�W�8CB����2��|d�O�I�"#'/:�t5�a����D):���A��f������L���C���/��^�yIc�'�aJؠ�z�D��(F��5�Y����P�Ϝ2S9iF%ν�� 1�̹�w�~����<��~!���\����G�&$� ���'���yP$�`A��Ě�b�����K(�z�+*�y�(7#gW�up5��]�f�d�Y �g�87#���"@�ԁ�3X��R�Dar�Q��� �<�I����:e��I���ȥ,R��p#�zB�RkH}���íP�tm��78O��|] �Be͢����'�ck���,�� �ڑ(BVB�S|�é>�x&�ۊ��'�"�e�����65CF�(�����+>��w�X��a6�i�D���,�3.V :$���0篘�Ę�-0%��!��׀X���%�wiy�����u,g� C�v��en����yU<�������j$�ؙ��s��'#�?�ڤ� ��>q�6⇊[�PT�K����� �zB�9��^� 1� �͋�à ���R��� ~炠� {I�q�!�1��y��(0�H緃�#��������+:��4�K�3st�8�50t p��Q�� ���u~�C\Ojbm�p��� 9�X��sNڑ��F�s�f�J%��'%���p�0�VJ4�� ��0��E��J�s|%�)sO� �F��XxwA] ����f��f`C:����[�򃔅Q���8 endstream endobj 1027 0 obj << /Length 3233 /Filter /FlateDecode >> stream xڭZ[o�~�_a�!+�"JyK�&H�$@�@�<�#ڣ�dH�u��{.�n�YO�€E�y��9��.���L�R������!��������C��%01Y����ß�7�.KE������r������_�����D)����'Z����q�/����w���vГ��#����D����{����=�d��;Y�����{��g���8�d��Q}�ZdJ�i����nߵ��ñj�{���>���#�tx��.��oi�[W��r��\*!K;%�݋뫱z�[br̊B�����"�n�qSj! �������ec�&RH��{�\Y*���ۋ�pF�y߸�d�v�G�?u�fa�K�%�f���5����i�v����f��A)�,.4b� �i���R�Q\��4��j�N܁�5B�B~�_|�˿�&mF�8���PjU���+�Xp�%]�0�`�L�ؙz�]�,�B�F-�`G� ��﩯vC��Vc�#��0���>|�#��Ku��_�w|B`d��1�L >�4{0�7 w_3���WjҔ`����uG����������IJ��,��T}I| Q�5[)�b=4L�9���yb4-,1D" ��fU4��2��b��3�����QP3�|2\�Ņ��.YL��U�,5�. *8Vf:xWƂ1ؕ�lf*Y"���bd ^�5�{8�GU��2�_|���+�L������8�(e���z|�uqC�C���FM-vo���0��oZ�� *-w���I�ji떴;QuP����(�Gk���VO���WCT] p��*k�&�恭�:q@�>�F���;l@!a�4�V��w�|��,&G��� 6����d��~��z#����/�ʂɥ��M���ls���:�˟��oh��x�w�֮�7���VU��#�Mθ�Μf��C���+�s|n "�W��i���w�"���|*7.�w�z���&̧h�+��FhCg���#���v2���e�/\���Ƙ�K� =' _2z@z��\v5l(t}�ܴ�ѿ�!rg9��Ib��Bg��v���������ǧh0�@8�)S�xaRV��HǼf?���f�:�$6�,tFڲ��(�h 0�|�\����ؠ}��&� ��{� �:Э�&��.�o�?I��� Vf��w�ʲ�X)�� "owNJ\�Q�9�&��橹�ji@_�-�6s���k3#�8�Tj�|N��E����v����8�-xڮ��D��i���@�tX�T�mb�hk����j�Y:�dk8Eұ�t�3�&zQ@�B��8�{8g&����*Dl���ư�V�)�YH]�"α^��/���Y�k�">Ѫ$���s/.C����w|{���Kx0��i���g��dTE�Ɏt:�wܷ@�wIQi�u��M� ���� :��E�A�0� Zk�y\ᵄ��bv��w�r���]����a��&9����� �W �iS�%�� R���4ƾ)��-]��t��ҕ��ȿ��[� $��=�q �[7f���� �1�[��{aC ��̕2؆ ���o V%��y�6��yF�@�$�c��a��&1�K$�y�vn��_0�t!#|c/��tvne� �� �@(�r��#'� �H��/\���g��%� �];D|4�d����� Zio�>]�R�92<��S� V�|x^z�͗ܢ �Oݚ�C��ۡ1,h�o�y>r� ����k�� �(N��������s'��^�j�U� =�[$�bU��A�yb��$��bke�o�-��^^?�Ty����4ް�}���.4Ny(��m� ��#��:̥��d4^��*o s�=�4� ovAc`��c���q8 x��KG��-])�'B�ae8t�c��S-�:&X_��H���z����-F|�|�w ���IV�٧�w?A�<)�|�T�¯��i�Ή���cw~yo@����d�_��iNT ;�����\���^D�|y]$�"��\�c���͆��4�E�d�L�1�kf8�sh������C2��t����X%Z���WYg��:ݍk,8�����fJ�@�L�k���E5�WӾ)c�ê �ѻ�� �i?��i�� t�GjnI��xY�9�*��=a����W��d1=R_�.Jg���@qs`�ʳ_k��|�u��� {w9�^�IGt Hyy˅�Z32�X�� ��̓7��Q��?8�[bW�p$�H�b!'���7c_}v=���4�oB���Nֵ+�d���Ep�6���`)Zp�Wn���s�$V�]��X ��#�%(��n������d%@ӵf?�-R�X�*����!�v /m繐��o޿�*?��3��Ϋ�L1��T����~ ���/��?��Z�~&|��Pqc�_��r4��V7�B ��,z*Ƅ_���?�����4��bE���_���-+�>����qʷ�8|�JeD.7�Eӏ�Bu�uU~�1�{'���G(M� endstream endobj 1033 0 obj << /Length 2648 /Filter /FlateDecode >> stream xڭZK���ﯘ��* !���y8��T2�l84bL�c>vkʕ��n4@�4��ńd��n��kh�C������T����.�����n��w<�m�q������}���Y�����\�q��c��c�2�~��Rf��f�����?�Ml"K�[l‰{WMCH� /*�v;֧@t}�����b9�E��_խ�P���,�cn���X�ۻ�r�Z��� �W�����VS��էYb{���2��C��xu���U}XΫ�۽v}�pO����c�pZՓ��*�+ I�G�)��ͫaH�. }̜w/����F��g��b-���(��z��: ����uE��a(c���BI��E�Hf��̊Y�g׺��Q������e[n�� ������> ��o<�1b]��J]���N�F�(�y[�5�r?��)ys9S,���rg��v�Aƒ&�"g����_�O�`�9+� f�V?�� ���YkA>�v�ޮ;�� V�d\��]��G�F��d"���/[f`�)�7C�jWc�c�0*t��ֵ�#�<��B�L%U���s�5ۡ����`'��kXY����ymb�I�*8Z@�XW�`�[�|p���=l��J��5�o|��f�Æ=�j���X���ڽkw��9U?|]�#Eix�ӫ�K�&H���ݓ7����\� ���5�m�x���V��S�?!�k2x�f���BK[ty�)p+X��u�x{YÙ�3Y�қ���θ�� �s��� �ػ$|:��KX��Y=�9�� ��k�M�N}8>����74PP��@�W���L�۾�ׁ앣���@>� �o��9��EHCܑJX����\.�����0�5Ud�>��O��_�ћ�hnP�h�%�D������+)T!�T�G�ȋf�� ��y�$��ΉL�)u�?�㣒Ud=}A ����r��oi�<�}_f��y��s��N�$�Tε���#��c$`�ZR��U,2*�7m P��^����: ��+��p }�5�Qܚ�LY!�����!|�@& �TB�/�o�u��*!���s[E��_��@�}Odj���}`8���*z���ë:Yi�H7^���u� )^�\x�U����'K�g� �!����{F��t0-�� I�b )�AƢ��BZ%(K��M��4��CRe�`�3�+g�=��Ӱ��L�-���7�n�O.n��ݪ��-&�R.@����}2�J� 6U�hy��ι4᫞h��{��n`R5sdV̀e��K�Yy�����'8�� Ț���L`b7�7���V"%��wA����B  Ô4� yP�V�mA�~�/#��o,L\*s�+�Fo{�F �F_�FH�l7~"�ٴ�C�n(�=��R���(�W����7��NxC6�V �H/�0c�j����W��A�3>" �D��NO��sN��9��Ύ�/F� ��T$|ӻ_�z�ǠV�P��ܭd�����<��S �3e�[�����, �+��|đ�?DT�;�^�vQe��l��:�WM������,��K�R�����^ /� "TZ�P��#��!��VH��"�j0K�5�c$VtYM��v~t� U�Zk�r|� *�!�% ��Aqp�ӣw3�8��������I����J��������4���ot�����W��-�����ŗX`�B�"ޡ��H����YD7�aQ�� _�ݡ��1��X��]'8�V����耐~�+�yMzX:���� ���=x�m"��+:��$Y���r9����}4��B���$F��.Z��������z r���cc����y���R�! �[���n��vH ����YۺI� �:��� z��U��5�;�ٹ�y����̯�c��Q�b��e�|*Ժ�7~�̙03��� /�)�`���a:�����]��K7k��Cl�a&~�'�e��o���Ҫy��, MW3 �e��8��L�뒉�.F0��F���p/`�@x���qn�]��^�(.ܝ�xp��@a���> stream x���n�6�p�C�"Ҋzؒ{� E�hs��c�6��h葬��3��,y�m�E��04�=$�b�O��p��� O�ٺ�-����� �t>�#ʗ�/ަ�L�A�bv���.f�W;��T3��8�����$�w�S�xw3�Ӆ��\x�޺#|e�~�y�*il6�����oaFDy��b���׋7׃zi=���C�Ȃl�Ȓ@� ٲշs�Jՠ(ӡQy�zJ2̬�[[T#;mꖦ C��a�Fu}SR�v��e�h��B��G��qۯתe~�q��oT��S}"%���3��!�δ�d��鲴Lq��n�x����PB����a��Y��T�o���hP aR���g��v��!d� ���I4��Y%ȬD��c���0��e���]Ӣ�q�ɺ@�w��(|Kc]����a��i*LG+;� e�Y7�:Zz�%�w;�FG�x�������"T��E�d<�u�ٗ�Y"��8>�!+��@(v;H��j/!��*�y+�$|�y�8w���S�9��K�up+��LY���HR��T�kcS��u��lM]�G�؋I��u�0�e���a�ɢ ~���e�M#+���t��4턶P\�u��5��x�hJ}���0�m�\*��gYA$�&�Ɓ25�o����<Ώ��`u.��,X��4��4,Ԇ�;W�]n���r��D�J׾i ���G�w�2 '��1�0%ܟ���(��$���B��0���$�{2a���@HZC�$k���U�� �'��`L.�J�PZX"�6%p��{&~#�N�bDi<��5�X���mT��8á�����jpG�o��R�lKt0�N�9�i�DC�~}������Ǜ�d�;�7�, �A�����0 D���/��+V.:�\e�P"��cf#]��~��S��eӲ�X��_5}�q�}0��� l6p��׏�R��o�k{�)bA�.ʼnM�����#��4���/΂0 ��� ���w�+��c�8a 31W��r�|kS�u����.�s>_ݚ�rOV�ڔΡ����`eid�L�F6>V�Ӆ…���e[<�}�(v���͇ �{��|�@=P�Ӆ�Jn����7f �=b�K�H \��Xz�����}%�%͜4�W�u��P�[Ț��7z˒P-��P�x�(y�D��ה����@��i;��� ��׉+9�,��=�}*}%�Gr���������3��T4�kF�8������}� �6�G�#�)y>ܫ��CT�� �UD�W �ȶ�I�d�E�>Y�Op��J];�k�I-ak� UP��;}�~�6��S��.4� � �4B�x��_��^�s �`s��VO��d:�{"+|�A�1�8r�M"�Zmx�]�Ю?���$ȓ�P%Q8� a���r�r��X۽@=*�٪��-/�ɝ(O�����8OO:J��|Y�#��{X�Ӫ��q�]k�#eC�i�[(�X�h�K��7��b_$����M2�֞�"ZDv%B�I P���}GH(�3�E� �T<���Ò�����M�B�� D��(ց��+n�yz�Cc�% ?�%���� ȱ��-\ �8�Ea4���c��IJ ��UNlc�US�B�TG,:RJ��O� ���9���b�4Cq�D�D%�5&v;�����*فp���)�;ط!�7�b�0�~���;X��ݎ��P�J����? �u}|*�]�8si.�%�ѣb� ]��g��<�������["��:$����h��k%o�a T����Ut��,tG�(h�.�\�8T#= ����#"m endstream endobj 1041 0 obj << /Length 3334 /Filter /FlateDecode >> stream xڥZY�ܸ~���KԀ�ER��!����8�:H�l4j���j�������Kj�G�c�*�Ū��� ៺�»D� 3�]qzRo�xǕ���y>L�g3�}���7�ީ0��Lݽ;�I������{��|�����|c�������η���NyУ����S���ۻ��́�o~�� ��(�<����O�~x7m�F�g�g~� J�Az�&P��Y���=. 3��L*��0M*�ӹ���0�{(��|��R�8?y�FU�A�d�SS7U�����T~� �8�j���$S8f�^��&%w�ҁ��v��5��ӗw�:��R~p��w�߾m$�W8�i�~|#9�b O;]ע@�H{���$ͮ��4V]h,� ���H����3I��q���6vc`/��G��6^9� dU�����{~�`�I�|�$�uQzi�Z���5� M�8㡬���Aͪ��/ 6��t���t��C��c@<� p!@ w�iU�^��I���c%����:�������},��{a�{�ˋ]�x�Ip�v�3g�|(�$8p٥��ky���L�?� �b�� �A�/<���hO|:�=�&\^p�1�?6e��U�5u0͌�qbV��*Le�/\n��1ǣ��IWѺ�w{i�R��`U��\ժT��4����WQ�o��Z_Kk�ܪh�gc�:�N����K׻Ӻ�&A�N��Õ8'��v(.�ʚ˜�'da�wN=����a ) y�*]���2�H�>������ �� D�{W%���.�Ka_�->7�֦1���<���Ľ-�}��e����P^K��d�v9-�ٰ�ʭ ,k��Yjaki�9*`L֮,���K�L%>�j�P�9n̮φ�� pJ5Nd1��Jj���{���|���A�n��n�N���Khý;�4�ke���e�,��뤾.����,�{ϛ��p��99n��@��J�h�|b�Is>��z/3.s.@v��@V�ߪmsYs�;����*46 �e�l�r�&M��e1�I���"���\a��3-�ƽ�@ ~�\:��Έ�wu,�i汎�Q��7ׁSM�)��a��,�3�F3���6��.Yp����-]�`�:�Yʡ� �X�ԉ���d��&�� �f��*�ސ��w�r�"�_NǍqJ~>We���2���|�`Du� 8KG�ۃl��1$<����$JО!�{�lP�n�9 η������H��lN1����+O����t�z�1TW�*��\�E ry5l�s��e�����:�p2Z�'pK�#P�,������"}�_�O#9D�Y"y�����*�' �5��M�8���:d-%���.`C��@��-D���|Z��-hS��'/���'N���/Z-dhw�����ml�Q,�ߺG4ė��P�: \�=x�6c'����`�� ���n�8�n��Cۜ���|y�����["�\�7߭c^d�������O[Q��5�k���B�df�kv2Y2�>�b�sr�Ȇ�j�ћ З7���15cfV�п<\�g��t˹J���tM !�5Ƽ�`+�O9|�&mY�p���vGeag)����_uuc��*�횺�2͙�~��CĕLkܻ䟁-��jv���<�Jfv^E`�� q �<���=7s�t��x蘭��`��<��d�C]Kl��^h@��66g�zA��Q� 9�%��cnf� �W?h��lj���F��;~*���(�oL i�„� rYs�:�CK����x?;�ɗ �1�I�(�u، ���1�3�>����OM[�}!�ea����{Z��H�'�=_*�� ϼoK�5F�a' �͇��z�2�@iR��&�����VPW�����}�my�\��L鵍��vGf!���)��7�� HC8S��s���f�̚i;���b���M��a��r�y�L΅�%c�L�W!cn�Y�ɫ�&3�5Ae�Ɓr �d�P�Z����J�K?��8 u� ��8�ه�3P��^�<���*Z��cA��t��F) #j\�}��ˇI�6v@<�ڊ�ۨ˯�w��'c.k'N&B��T��6��n��9�QJ"&+y`��k1U�=�})xf(�:��X��n����3V��n;��v��k�]�m7, �X�e��eh��iT n$:��K�[���Fv[nS`��>Uն�*5��p���e��`��� آJ��}�Up�kt4��ln{�*�؊恿1Ӽ��y�ɚok��L���T �ʞ)^l'��)� �g3K0�9�����s ������Ϣ[��0u�b��~�Y00�*U�K����gA�i�Ŭ9P��&�s.(�S��R�)��j_��Dr�R�c� ��Q�(���طB���ڡ�.F�.��B�)Q��8[�U�ӰUp�����^@n��g�3��8��� �{ h^�l���u��U{� �h�^�C���C�Ei�Iѯx�&���؟�JXac��]V�cwW�V%# ԵЬ�SzZ���Ha�۴��B�\�Y�)&J$&�*�a�r�t^��l�Ul �x;; �vi��vA�g��{̋��6p���)��)b� %����|��3ɭ�n~�9�}(�����W��G(���U��bWBF�hDe��^� �GQ�E@L���E�}�L��N@�Q���7sO�u4����{RW����$��Q�f�!���Z�m0�j{q�*�;���� F�&�y����O�[ ���I:�cѸ5����`>���$֎iu�,���s)Y�����-^�G������%��1-��Y�����Y "�^G:�zeQ@a> stream x��YK����P�b�j ��[��)�b'�R� ���H��ϿO����zS��@<��F��-���Oo�x�'�*m��_��4ڟ6���_�hY������?=����4��X�q�7�9������su]��%I��;k����x����.͢�lu#:ڏ<~�;SD��ww������0�Mi�$����7y��|�=p�'.b�\�&�d�U:�|���c��ƺkF`c��Z�ijp�.�yg�{�]��F���n�~�v�U6.N��v:Q:��/]�5�x���/<[��MW���O��˵n��?ߘ��]�>���%����^�x)�߬S�b) pU��,�Q�`ix�b�j����ꞻ�Й���X�䀌Dcb2�4hxjFZ �I{#���ׇ�T��T�D��SU�@��$Y�ab�{3�����ipǩ���q aTL����]"U?u�6h�@Z�ٞ2@�::5N>��� 6�����]�� ���L�ˡ��?T�l`�<�x��)4���Foy�'/���r����k�V ��l\s����L�hc8T�T� ȍ�f�`��p�_А�yzOh���3�&$���M+��O�~��h�rc�B��dUY&TY�oz�9����řZ�����=w!�x�T��Z�!��8��^m��$0l`�����k��W�&��ʔ��M�+�=W�(C���f����I ��ԞD5�_�Q^�ʑ��$*���������xsa6�.�ݴ��IU�� �A�l�oz�Ė�Q랸�֜��Xa�m;�m�j���,?n�O�3� ��Չ�_������o����ߝ�{��������ѓG���o���|9㎣O���^����G���c^�>� [I��9���ωhLZ��A�ھF�xژ�8�(3�ü��D���<�Z�5����Z.s�W��j�j��^�b�6������K݊�ήww�o&e��� ą�$y�ԱV��u��f�[e�'�&O��$d��$x��<�[t�<�(��(��T#;�װ���B�f׸��)�wG^��r�wQU��F�a�F5U���ںY�Z��1����DZ��ԣB �^^�g#k��J^��\��Kܶ�5i�d�t��!P����n �z� �ʓbA �V<8��T%Eq_x���\�pR�l~��4N#�N��"� �+\;L�l�V~���S~T����;K�偱��+����h%�\T~� �X��i�(��]��ĒT�".`�0�E�_�&>?MB���E����j��� T� �Ch��� �$9���Ny(��> stream xڝZYo��~�_!�Ŕ�d�d7�mo����^�Z� �r�C���SW�Q^9X`��������(u�?uS�7y�F�.n�󻘤�� ?���wJ���1\���ݻ�~4�F�Q�����p�K���^F�߆i��w���&�;9|�� M|�UHTP�,?w�aR��{w�����GhQI�������~���g�����/���A h47Y�#�j>��X�(:[�UI��b�Uu�K׺v ����v��ڨJ�"����~�3�"I9*l5�0���4^H/�?�ƺ�\��A����~p�I,�����E��-����d��M���4R�7 '��ۃk�� ��b�q�n���e�.Ԧ[�q+]�x�;�n��(����#��a'M�H�c�2)��?��=�}��jW xB�Ԡ� Q�`��������� J�j���ui���c�"jy��[�m�8~_]�����Nu��':V,ף��&�lӄ��} � S{' �8�Rum|��,0��y�B���P�����J�`�[>��|�&����-G[7S�dާ��������+ҼU5�4� ��qð��7��X�\ [��49|ʷN��2(�/G%�6ﷵ���� {�-b����x�q��FGv��[cG���aP�����w8��K�v� "���E��/ }��uoa_�ϰ:F��4+��i�=ڊ�����CzOȖ����B\�n� ��F ����g-sX���mCAo���l~It��qliS}�����@�����$(ݓ��F|������yX�aj\#fY�V&�+��������5מ,^ܢ��"�h��r\|%�\5S\ʗ��2�����끽e*��3�^4� ɝ �� �c�}?7_x�&��✑���g"l#dC ��֞ b�aD/�,Ȫ��#�2���Qp;�0Z���N��J�J<Ž��<������7v�� )ⵁ �b�+��#1"*��r���́��c7�=������ �ΕEE�!�u�^�-SQ���3�\�(�K��һ���8�u��&*�5$��ٳ�a��N�Ff���[K%T����>֏�ߥ�4m؅&$�2�E: TnA����jR����e�+��HW�8�Cϝr5� F�%����o�I`l�Of��9��x���DNZ� ��_&";���'$*��l�Ǻ=�3�~�[��9�����3½�Q�ʭNt�b���l τ�t&z"����3, ԃ�puA܆G�G,�9��ʑ�������//C&x�\�������6� �MR�UcO�˔�4�4�;R���d�������r�]�8 ��䋎���ܼ�,se�[����Tu��\�`� 5IT��u)i2w��2/Ez)��������8B�&��-w� �jjl/���~�ѝ/����{S�H-�����0KQ��D(�$�Osȕ���{d\�"B&C��,�`3!P�� ����^���ra�v7_Jth�D 2�G0I��-�ք�J�w��4.�b#I� ��u=���>���~���ւ�2�H������2����kxY�s�+0��GŜ<�H6�o^�G'"�cyp��(�R�O���Q.|�NV�[���<�h��rѼɭC5�#%�z����B���!L���[b"m�%+�j�z8���%�l���Г���T��x��,�h��1p���`r� �>�{( Yy��֐q��������g�F;����ʏ�pb8B���_��\3 ?vUK�c�؞�� ĩb.=�_>�����R�)�������� ��T���� 8ߥ�A�>��8\�(�Z9�8`盪fb�] ���䙇��H#H;! nP��BlX\��E=** X�q��ٕ�zA�yC�K���6`*f������� yX�<��=����3�|N��(20���D���p@�ke$Y%K�i��)A �:����]&�P[ni�ʥ��e�oЙI"�\��kN���`S���!<�.��L���׳+IM6nr0��c�dc�Ue{Zn��P��ڥ����� �"K�e+��5F��C��ڶ��վΚ�tX��JQy�xk��4���J ��c�M��'?�*4�t���{kR*�I ���!��p�疃1> <�;�֪k0�Ѣ���q�����Q�Ѓ[�0����Y��"�/��� �ie�S�`+� ��!9����^�"��־�GyRl�|�2n]n�ƒ��u�����Iow9���HÞw�L<������B-��ϸ�y_���+j�P �� ���E��eE ��- ����S�1K� V7WXd��' �y|Bc��9��Rc��_PU&��- ��N󙉴�"b��&���S"HT���f�僻P1-�ow�>:���C�-f(&���h��Tv�����LeI�9�����M���B�[&�Ÿ� ��dE�� ���)�N�n7�naqz�"� ��**M��,� &T�%����[�7N|-�ŗ�ױD�@1�����_}�Lbe�U4�t��N���L��=��n)�c��F�� �~�/�.���`��F�������P��[K��O�R���������k�5���. ���KU����r��s�C'd0���,��.�t.F�G ���8 ���I�w��C0V��KJ�������?,+����Ez��PFj���R��6�>sdx�92~d�e�<��t���k#ɛ�xw`1��|�����RX��/���i��Cl�����kLU�?,���ǩ2�d�� � L�WE��[c ��%>YmX�\g�q�������t�/���� �g,q��'Y) .+�(J���Tx�����j q��M��uUmkWT�K_�>����̓R�W�r�(T�[>�� �\ {��U�J���m� endstream endobj 965 0 obj << /Type /ObjStm /N 100 /First 905 /Length 1879 /Filter /FlateDecode >> stream x��YM�7��W�L�U�" �5&�0b/����L�2�=��,��W-٣�GZ�${Q�����*��� �&rbv��"�3���TG���Q+�z\ul8`Xìj�,x'�f8'���Ra���\Ѝf|���D����+�gfWYg5Gd� =b%���I\)��i���EfB�����0c����\ �J4 �W)�\aNI���(�a�%B�Z`qFC��0�0q ��dB8ehId�T��U�H���q0m*;��DxJ� �1U80���P��y<�)�����E�<6s��b2���h���d� L�7ľ4J5tr� \��X��$Jև�I�3���U��e��0G�瀒R6�[���u�[] �^�r,}���m�\�3��I�'�ה�-l,h�� � s�Bo� ��j֪NcPk�$6S�� p��06)��*�Ldv��}��X:#@*=(�e< �o�W ���U����h��9D]s��0V6t�DP2C�3���6{�� :�G��l��� �V ���g�W�]�r�������.��������wߝ���3by'�xS}��)��J�85��Փ��K�3�l��g� �ԫ�aG �uX?$oQ2�C��L{~��ڵ{���/�Y����c/���pۼ ��-Q���0�����|Ӭ�;7�����6���1o�mб������Ȧ]�ax/p6�����W��]�p�O?6W����7�.�����o�!f��Xgqh�k5?�6c8���3���(� � ��,�u�֕���X����`���L_������0�;g{��b[�=�D�������u��ò�u6٭���FFxo�\�N�'ˡ� ����N����޸�����������5�i/����.�����k�5��V논穯,�#�k��)����y��{�Ӕq,�W9�\;Qz�gՕ-�ƒ��Cr����hl�цde2�j� �<_���d��/DG��w���-�u�iy�����b�K��i�3 �r9�Lc�D�9� �HQ/(t(e�V2e�T�)bd-a��{�F�M���b��-y,o�ly�Q�J�ͻN�o$�̨/C�j%v`�@+�)�HR77]k˴X�W�����޺��{���v��`�e5s����+*^���Y��W}Ҽjn�� )t��+�-���I���Tf�4Kx�#�s�Gu���ê���r��`)���E�1�26�⠘�9�m{����QYx�����l�4�.�;�q�Zt��0�2bR^��6�]�&��Q�?�o2�n�yjf�=c���w�S������ߖ�W϶1����V9~�NM�����3jW��?��؞J�{|:��!���l��>�6�E_<>��o^]L� �]1j��pl�H�g>�0ˏ�v�RwkJ�g��Q�gi����B \q�H�g�"�*!=#���Dm�i ����_q���L�_� ���5|ֱ�Qz�q�Ԃ+����L�C�ҿ�7�9�#�x;"�=vБ��_�[Mͺ�k���7�>m�R�*���Fl��'�6 ���?�/���IJa��8��e+�������e�i���������A��3�*Ot �P:V��&�z�yR��v��]wS�H�|HƍN��H�%#��F��J;,��!���(���]�s�Z�W7�_�g_v��.���J�� ���X��r�*����es}�h����io�b&O�����.��y�=�I��]#-N����q�����a�2���Q|> stream xڵZI�����W�������\d�v9�-�W��I� ����m�(�$'�R�����[��z�M��Mn�$ �ov�g!�v� 7~��Y$�|���f~}���wi�� �hs{�ou�߼��9���t[?I/{���J�ۓ��w[?����ȃ��� �n�~�{{S�w{��Wo���Dq{I�}w��g��:��8��{���_D�*��)��P{}�k�>̼���� #�]�+�=� '������}�~ ���8\Ɓ�yu�U��am�_�j��N����L���mw6���h�r.��Ir�N�8���剋'Y���΃S`��W� ��6~�Q*�h@iH����L�ۃ�r08�l��b��'����n�v�GyEo�I]Y�p \���n� |k��v|��C>��d�"�� �+������CH���z��L�Z)P�u� ,��9��((����&�=�cSp� ߋ0�@'�Ӛ���0���I��T�� ��<�k�ȩ;�[͝é�uG%ɝ@r%2� $�>�2����"i$�G֏(ʂ0UW��f�j�d�����p� Ӱjv���@�C5��ՙc��M�;���eo[m3ݢ�+���#�4�X.�eB(Қ�4���@Z�u!B�d���{�֋(L�(Wv��FN��0y؅��%��17��E��o G�>1�L"��k% �M=E���@��<���X�d�r��(gvW�y#n��Y����a���(E �e���&9�r�Qq�I����n�'���T��{79G0�4��Ǿ��f��9�N�3�"]Z�?"�����'��t��i�I�@�_;H�J�$�um�_x�amW���(f�Fk���* r�ʅ��]BKI"f}<��.x�_P�:Οf��%��j��M�3AƮ陒��xG�sJy?��i�<�ƭ�(���"nڱ٣�ŚbH���M�2�Ƚ���+�ygμ�U���G�A[֭�����Y�����+�/X��A�B'ᦪ׎�� �t˞��4{��Ol_�Z��t(�������( �eݛ��Q��2�m�UD }�p�>I����{B��b�׵.���jL.�IE�)�u��)�� ��jsv�;��/F�:���0�BϞ;�tU� �ޔ������W���TC�Z�I��)\��P�"C�ȋܻ�� CwbD�޻I��P�|!9�7hX�ULF�b�+<�l �[��f7ȂCמy� ��Ԓ{'���L�?,q4�|4�!�8@pe%.?T5�LM�$(��$��;�2N$rƁL?փ 5���x��r�4HJu[�ɚ����`�<�J�`�;Am]�x�����+���Kaq�:�T|�'��2�x��쮫�;�j��!��y�J/��1��\EO>�G�ןڱ�[���}]�AmT�� �T�TtU�@`j_W�Tv��sQ�Zn� ��\�B=�@����z[�NM� �eB n��?( g��r>��3��fõr��~�Hp��J=�挶��_H��;fN�m�%8@ ib3S��˥k/?�`�+�� n��`~�홲�מ�� �0�= ��:Wu١+�[uwe�k�\�b��0�S��s�;Ϟ����3��j��w�� C���t?䁙,����g;����6��Xj߹���J���Tۀ;q �s*�c#�":�"Q�8p���I8p.��z�;q �g ����9��3�*��v�\�d�d{K��{�x7�o��\����1�*��F|���N���+�W[io�US $������ �D�#�$w�w7v�Q*��Oϐ^B�����ɟ��Ֆ�"H���<���|mv�Ⱦ67Z7J���숝<�9O)?�u2�:�'���mbSh��6=6.�V7]���=����J��ÚF�?Ur%ޮz���!��ӛ��೚dl�0��>���0�'Ő+�r`�*���W�T�T��#B�N�.��c�܏��Fd*]վ�|�J���V�%3| ��ػ:W|c��mw4o�6ȿ�ؕ�X{����"�g�8&�~�.���@�y�Y�MDՋz���?��|�:FC�n� C2���Z+0��1�ϭ���RP#_H���`@�����r �p�ڔ={����'��A�(�"ggO�$ќ@�Y��~����7���ӝ�@M�C6�Џ��T��hrX9HeA8)�TeY�%��*����.�g��k�i� 6��p��Lu. ��{�*���jg�r�?�m:ּF�w}���;|��+z��1��2> bz+f�Ś� rhF��=���n>̪t�� ����2�=�0pk*�-�.y�P��7bN1�ј�w�@��9E4�������;�����B���X�I�ʖf�.�atz!����=��_>����\΂�D̓ endstream endobj 1059 0 obj << /Length 3561 /Filter /FlateDecode >> stream xڥZێ��}߯l�1V�����Ilc I����D�hkD����|}NU5�K��1X���]�U�NU����O�d�MbL���f��*����F �}�J�qk \�F�����W�ݨ8��L����S�oo~X�}��ڢ�]cV��۵�nu�/���k�W?ߪZ�j�J�Su���j[�^������� =Jgze��O�߼��ߞ��J9h� �(�F�Om��Y���Y� �Z�-��tn��� �m%m���X�c!��[��·����C!C��M[<5aڣ4�Rm�0��9o��V� 9 ���a���Q�t� zڂN R����Ah���5R �-۲�� �J�C�[)J�^��b<���/��,"ܭ�V_ݦ�Y�}S���"o�# �N�i��`��d�J�.+�~�y��C�K=?���d��'Q�M�Z��K۲,�w��ĠqdP.��� h�k��*�I���vU��6���5�5�ح��!bWmΗ�Ҡi��Yf4��O$�%�WGhG�^6^/�GK�16���!��vg\���o'�������8������|��Ͽ_8>o�aµ���& E>?�G��v��3������zY>��r=�,����;���5n��M+9�����T�ZU7l�1��$���me#�s��&��� `$�)�a�[�y� >�":�C��M�_l�o��zm3��D��d���ɽ$N��C�aN�I�WН?*G7���hɥ*�tX���Oy'0��C����v}<��[6>pw>nXyN�jzoO0��۷a;k��7��X�7���a��DJu��║>>E�{�J �$�Cs.?�R�����_��1�j�b�E*������������� �^W��˝B��F��*߆�}XbS�u�tj�-�����"�˛��9ɩ�,�Cg47�๑��(�9?�Js�Pm/c��yC#R���<����`�&���|I'L�t@�S��%,��qW@���p���i�f bo|�%&�Ql�_���!vi�,�P��hػ�x��$ou�_rm ����m�������&x��m����mF+npX�}p">�uTap���$K���0Pۉ��#��DȔ�#��/��"�����m Xv��J'h{*��S��=B����s[=�mI�P� �`"7�$�n�@%I6U���e�RS!% m )�[!�7�X ����%��a6WHS�a���Pg����jR)~?�M�v��G۰H�d�):�)T衃*�eR��0�P�n}I���Oz �c�b��]yܮ{�@t����j�M >=\$N6l������]&8����BHrx֨���$!��co��uu|<|�ƺ�Ps��T0H�)�$��� �N��� 3���:? ����3PK����R�?ΧS�n�^���zE��3�����뭴��2?�,�X�@�o��"EȘE���~�8�s�j��p� `�4����至�WJ�(8�%w���3��N𦨏9�"����AkC<#�9:#V�;����0��J:���� V���R��wl�-�[مX ����@�)��-ʪ@�D����邸HtOm a��8�R������b���L�i�<,�GKR�m?\j��zZ�z`��/��v�un�A�ݟV�CE������ʦ�,����.�4�M4�>���@k�Y)g{<G#3�S%�̃+$}_:�82��a��P�ݰˮ~a��ޖ�0r ��^�*�Mӑ��QIS���A� �>E�h���ſ��u�;Ci�;b����`Z7� %MTj�~,�Tn��\!�ι���Ag�uiH���>zݙ����%�8�����j�g:��a�D��.;��9e"�e����4ʲ�T�đU��l��|<�mU�P��2Lq���dա(c����e�z7��Ⱥ\}�E6��K�� �]}`dT4F��ՉV:������"Rh��Q�>nO�����ć�5�g}9�"� ������KWd�H'��U��b�%)�i��O���¤:����]p�0S2s�my��= ��Y�t���%�S��I�P��\H)D�:c�0�(�NҚ<|�k��AE E����s,>�z#c� �4��u�Xb�ZR7�B@�}��Z�\s -gɬ��ɨ�1-�AYt:���F:��lM�2�DZ�H5�.RY ���(K�L` _��Xѓ�[�,D� �f�x�N�vwA=�g`��<�m��1�Eh ]����Ai�Б�sā�3���i�����.�����w�ݰ�� �7����[p�|h#�O���9~��#���g��.����?�o��^AN�#�`dXNc*pz��e�h#�����M��K�ct�^G��T��e�2!Ie�$��]Zt�B�L��4��� �UVn�a� 9Y���]�!�H���5o�K � ��q��9Ħǔ(�f��Ce=�˻�� �F~���V����S���j���S ��U�cT�T�٨�5#u���h5� �Ay�g��7) ��+�&�V����P�>������XL�f\\�����r]��%!&�0`���9��� lkJ�>�����ؑ�X�����I���^�r�6�a� AO�f.{H�'�/��Fl��%Pp-���Oh��+�Yd�@e��T�vЯ ��)V�*�6�g��b�'����1]��)�1����-����-����� @�\��\��3I�=�� �X �E#B���e�(����#Rù�pC��h=v�T�K��E ����G,������UGnxr,�0D���'w'[j��eݵ��3�+���8I�^�>U�z&��gDƘ�.p���r��CY�1�z�-e��D���-����WɎ�!�HK ���qb6�6���������A|�ҁ+H���Ή��G�������JE�>��\!ų�&���9����%��8�����,�b��yB�~&�3CLE���v�࿝r���#��.��Ԥ���������� �h~�h���@�E-C$�U7eE#���S�7 � '�L���� >�L�=����BVQ�W��f��W����I´E��e#�C����2L>��r Ϋ���G������5?�[+���! �׻�)�Q�CMl�:��Ƈ�f����0玟�8���T�;��K�� �G�MӃ��WdLt��?š��Ռ�KޛË�(��nD���u8]5> stream xڵZ�s�~��B�<��Z0�yo��$i&q��Li���P�BR����.v�2d����A$���o?,,!��E.��"���z�!���ӂ~��d��&�y�pw� �,���a3�X�|�懾l�+�u`>.WQے���\�I�� �E��w�r�Ҡ(kzo6���/��/Re*�f���{ԋ��r(ya!RE��h����:�����l&�$M`d+sh��9v��ڕ,>9I���Y���a�*��2���o������@��4d2�@&"�� �n�w������ݦiD�7>�$�A���Q �^�t�E�Ƌ��B�$d�g�RY�E��l�w�X7yQv��.b�É04����e���~�W���y\�D]��)��8�6վX��ݡٗ�~4��!�B�ao�U�M�-|�D"��0Iݾ��q%��U�A�y��Nf�xFW�0� *n��� z��a6-=e�qP��<��e�q߻�{n����& ��w�T�92���>�eR�:)Ye���hpI���xVA.�qM:sXM��( ��#ʿ���o����좺��Fw��h�j�D�l�f禰��%ʨ�� E� �G� >� �� �e_�~��x�R�8zrZ�d�D:ϱ��>o��Gt4^�we�qB����Kx�q���&2a_�%�����$ٻ{�y��%"��t"D�®o��蒱 l���u��$�lj��E4�C�����s���SI#��e�.W�� x+�e�4P@+أ�o�{i�^�Y�NWߖ+�l���fQ]SFh@��M�._}P��^�Q�^� ������4蘘��׮/w���]HDg|jv;8+A2�z���#���F�l��0��{���Ԉĕ~���9�s�P�s`>Gc%�edoX��k�U���8��xf��=ƹ�3)8"������lw�æ�e���d�K)����������鼐V��Q/�����n֪�� `�,�u��o�}W�Fs�`���{[=�d�� ;c ��[f��W[��K2+�|ՙ�1X��4��cO��� �ѽ۶*��`��"� � s��8T��PpN�8ј��P���9aN����V��;��KEq\�����*l�;��}��^��0Lff��h� g�杯�M[ �)<��a˪/���f�v��N��zk�R���n-a��TfD �~��I�&➒��T���Vuy�Vi[���}�u���Tx�u)!R�j�/h}:��o`J'nD�)9*�@��_����( !YT�g��(��������E鵛o"��釃ǩѩ����ضo�&�(��K��d��4�6Ǻ�`� ����4�eI/9� �6C�6��� &b��T��`x��kz�a��>,ç�K�;�v�(��;���C�PH鳘�l�����&gn/߄[���Jf����Wq�� J��+^��Ih3m��O���OO�O��B��ו�/,� �Fi�-�|ȓS{��sv�-]&<���n� ���B$��j�G��?�e[���2��Ƨr"kj}7��5#�I�U���T����DM �ZZ4�ɺ�U�6~��*�����h�7� h��fu�ue�^9��$��[G(P�,�K!�y��D��e6�|*�ߎ���g<G���*�n +Vq��]��v9_�:r+0C�Ӥ���UsA(�;��F�bs?/\bȧ�x^DZ�e��x�6��x�{��cR���uCpq�Wk�;Rp���G��,<�����c 4��ڟTL_�z-]�7ˊ̱���a��6��� -� �Ϯ���^h\:��Y���@�(�."-�������Q;��t�N�^㯽�9���2����ޘ'x̅����kNO��-��n� M��Ж�;�$���6�L���m�2�F|�5Y�c� ��]�X�s����l�؟�1����<}AϮ��!�'�@Z��Ʉ���&�M`��F ��M��Ƕ����ɧ͋�{XI|%�[����^� -�c<ɚ!ر�}�>�D6^�~�go� �k˼@&�sX;#���a/�,�_�ǂh����9���u��d3���^� �Ǝ�i��l0d � ��1P!0q�Q����������@����: 6}" :e��s �˾ �M�.�g�e�w Y�#;U]�/~t��?�u�� endstream endobj 1071 0 obj << /Length 2348 /Filter /FlateDecode >> stream xڥY[���~�_����CQ�&�d{7md+Rf��~��z/ ����=�V4��w�hԢ���\�s�&���l2�����tS��D�7���_�2υ��d�o��E���2? 6��V��g��!? �ۺa:����:r� �m�(v~�P��~l��J����o������ T��0����7yً��J9p���SA�x:�7q�� �,�7o�]�<�I���G�ݾ���HE�M��W.���H��-��j�� �b/�DC�7 Q��s�o����aB_��2��AhP9*ae u8T=��өk�b *;0Ŏ �\V5�ݵy�e��x���4�pȇ�V�\Y%/�f��5(N�7�(`1d� ��q����`��F�`pd�E~���/�j ����#�Bn���������4}��p�g���&�KT �'v�8TO�mO����YD^º��<���.�[t���m�};6G��3�Z�E+j���,�kn���ѷ�0=� �8�2@J†(i�NNZу?7��^]���H#�O�Qo;��y��i�MU�]�Ec�S����T����+�2��� �;Á�`�s�Q�꯳`�� N��VN�I��!�w٣�X{�J�YDFj����F�h��x��G[��1 ��!���O�AFhegH ���*���XLdz�w�Q���kw��n�|f?� *󧺹����ܙUE FE�P�q�����Eq:���<6�ψ5i�������{q�?��`{�\�3�2H�r�Lߏ��=���y���GYп�!_d�~!�ԋ|eE���:��_vN�y���/q>�BT�jBbq���4Y6�������$<�`��}^���~|�ho� ���'T��Ļĵ��\!�`�{���s��)�j��g���V5�񤝺�K�H��巈Uخ�� ��B��W�ib9L�H8�����n�w� �<��e�鈕&,�ضэC��#\WE5ԯ�6C_�'�t��_i� a�3��zŭ�Lyq�ᶊ�^���Է�!H'�\�����V.'��e���O��x�D��6�t9��U����\G Up�����Ћ�� ! $ F�&��J~��dk<e�IJgU$�tZ�\أ�'�t�O\}��z��֑p���s��z`��T�Q��6�*}��j�!��]�J *��XX:� G� >��%�'�Vj�;�4qFq<[bQcqy��TP�&�œ8�MQ�/c٥HWT�R. �QʔF@KE^�,��x���Ne@&��@������m0��r Z�0�墀69�µ"uz.��[&����~\�u�d���2�1҃��%��)]R� �����Uc��m�Oh�����U\��N%��,�����:��3װ�A��1+{�����\%������P<�$��r8<��p���$eÖ[����$��� t,a�I�d��b(�a��Q���� �;;۝L_��.7��^����_o-�<�v�^2�"��*�J&��/0�ܔ��؞��hD0#^Y�Xv���g&����K�rޛ� Dy 5Be�5���I�e��i�y�jw w Z�)� �4�8�D����[W ���d%\�hx��*���8�z�[3?������F�Dc�2���+B�J��Y� ך1��4fl��y��W�W�$����$ t�k��P��"�1���R���4��'5\�q�b�h��$\��2sv#g!l�C�å[�mk�rɨ���B���KV���sc��(:��"7�F�dqg!�����H�Ec���;���͏��R�aOt(��C��w���/�%%�_�������El �S/�WwU���E��cj��;ұ| 7��4v��4N[.�)n�x�Iᖗ.�϶���}ێ�\}���&s!�_�L����ݷuM��t3�L��-�p�gD^�esw�IV�K(������[q�*G��ʑ�N�3���S��fg� �!�c��ž��IL5+g0���ҙ�����A�&a��j��V�ޔ���+�Vo���ۉ���L3��V�� o��-�X;E{��Js�j�@p������af����=u�)\�/Y�6k��� ��X�$�����Law]SX:SǾ�G���R 7�؈�1#�k#_�B��=#C/��Q��L���B������_�FZg�}�:S��C�����oG����b/��-)�ym��6��������0>)�F�%���$0��讕�w�7=j���A���>T���\ �Ww��ˤl:e�q��,�Z,���ݓ�����.4!Q�GW���7S W�=��8 e9�7���v0w���Á�T endstream endobj 1076 0 obj << /Length 2351 /Filter /FlateDecode >> stream xڭXYo�8~ϯhx"-R��2�d�Af7HF $�n�-�u�2 e���,֚�'��"Fst.�>��f��+|d�hD�EeI��l��� �����x�j{�r���1�L�Ƿx�4hv���h�zګ ֈ������~�f^U�E��N,L;$����!8YV"�,R��8Pv��D�џqX�'�������V����󝆂����Af�g.����={���ZY��2���Zqx�,|�Q��D� ��_�;�� ��O����g���V�,`"sz�^cw��adL�k��vS*�s����� 0Φ��7nk+�N�)���M�5o��CG.���y���JQ���y6li�������~�]`�2B�9�$�+����rlUU����T�`Q��A<���Hd$"��q�^�u�?ժ�[jQ��։���-�^�ԑ�3�;L5�dT�|���n����6k���J ������&��,D��ʌ� ������fm����a�z��"d!� pX������֓�J��������2Xק����^�B8��Ek��3a&^���~A�P��2t6�.�+ ��p.�x*�L.�(T�{�أ�M8��\P�u{�Nۅ��QƤL���gӏ��y��R���t�f)�t�w鵕��d#k��֞�����f#K͡�"5R�l!#eߜ�RӉT^سq,�4�?:E���M3{^p���"qniMM�i�$t���.[��`*Z��+��&�����=-��{���6)[ � �n� 70�.P}S)�@l�#��^Mwa]v���r#)E2)$th1�������} �+�O_Mc��������=����.h���/?��G<\[%�q���*���Uk��*�Ja$Y��|��α�z/��`O$I��W��=�mu��n�� ��K�D���l� �"6G�gK�'Tj�s�SN�%�؜eQ$��HC�M�u�ٮξl��C�-����7ʂ��K���u| ��� 3ɹ���C2����,����,�_�}�O�=�;�ȃJO�X��a|ڀ�rTzA�K �l�G�Ե5�È9�!��,~��&\�ځG��2/gc9xPx��n�X���?|�����ߧ���pX2�z��hR��3������[�rq�[��U{>^�Ew��5W�����,6O�w�P�z�ly�\Z:��f��T�C��g���� ���_����•��S��= endstream endobj 1082 0 obj << /Length 2700 /Filter /FlateDecode >> stream xڭَ����_!��r�C�����x�`�M�]O��zĖĘ"����}�j��p��&`�Guuu�U�7�ś2��Z�����ED��~Ã_��"���n_��]�n�H�QonwKT���c��`O��oB�u��� �I�ۃㅿ�݄i��&`%�#���0)��5<�v�}��w�'e�����^����K���@�G)�M�U/��d�Q�6��\%*Vқ�ؾ;U@y?�n@b��܊s�i�(n������w��`�ܝƺkm��&6@��* ��� ��n����4 �n�p8σ�a�1�2,F�i�۽�׹�O�v��G���#�w�矢�4n�I�3�� �BNVU=�;v�G��+��Ә_1��6���W��Dw������zV![5��;2��u-t��P���}��{K4�1������}X����g��$� ���Δ�=2%��*��y݄��O8�w�m�ӃE�|�t��$���ݩ�[w�����*H �: nyz��a�0�9� �=�2dN���#��r$�4SB܀U2=X�-���8P�!Ϗ� �����P{m� o,q�^�Vl��p`[! Өt��u%���-ߎ��Ma%V�-��®�4?Ei�J��4���V����u��7�ւ4���i�f�I)�e��) �����m[���5 s�?9�q�~�2��<���{���XEê�,V9x� 7���n�C��pP4[^9��Ul7�v�L=�ي�ێ��u+G �����&JIG��du���iHdI�#m�s6 ,�_�*�w��8�qw�=K:aU���� ���m��t��@�5d}1Bh���ȩ�Z (�!R&ʽ��ê��fr�GS�ʳ�Հ��lƪ�v�D����F��<�;;�!8C 5�G2��I9��iPJ���A��G)�#�5�9���&E�� �d���/V��E���UyÚũM?8��=����^]���|��ˌWHG����@ѧ( �O�8c[��\��G����5�I�^��6*RR����(��n��/ N8n�~�`jp��c�A\͏�Ch�� ��P`A�䒰�:9��~������՞SvpB;�\�sϑ�Ho�U���l�c΢�����2P�F ��Ƌ�5H듾�΂����� ��ʊ�t)a�!���~ ��)������4!��K��S+�kxP��� yǮ:��nQ����� �Sɦ��˥E��P."�l�hV%�ԍ��\q�"�)P�� ��TJ�8�^(�06�^12�dC�tzI(F��c���t_M9�jݜeP4O�s"��l�A�U�n�Z/�)x�$���y�^U�zP�v�܌�\D� ��: ���kL�uV[tԇ���QA=�f��G���U]���;su�� ��ޗ�|�erC����SSo둼&*n�5�ݹ���%s�� L|����' L�Z�����-�]�S��u��r�*=�oi�`+eш!KH��HЅ�94Q�d�����0��j���9 ��,5x�o��y=�9]��[�LQ��[wP��{�����Ԭ[�@-S� �]��t~Op���r�~���+Ϳk��}��T� ���J���)[�:����H�3��oPw�r*��3�V8e�Q<���-WH�S�B����l�8�$�,%��F���<��5��&1�J� �=t�_���o����]�*���dރ�k۬���ʤ����@�2*�x�4�H �%����!��Ɂ�>U�`����ɹES�V�!���A�.B�e'�|��Д�ƒr։��N��D�6,5r���X 0��8�V���z��`������6�%[m'�֜�1͟���nau� <}���V-�R' s:�D�(m] B��t�����,n�⦕�.W�<�.�a2��P&�H���晃=lc?�_8��Ra� ��\0�|`qq%���JB�I�"�%��M ��#�%��^U�j��"�{)���P:�S���x�[���j��h�u��n]�%��y���8Օ�+'b�To�$�N�u�L9'�S�9/5`���e*^�(J�'�D�����"Bm�j�34^����W���W7����IX�����+U����#�~����bؗ��uOCWRc��P�p�jM&�:'^���5����/]S��޵��͹�\k��Ua�(=;ߛ09Ve�D������L_����ef=. v�(C#������1��$'X�9������N�`��������V.�;��L9�~R����fp�����>އ� M��!��j'�fV �� ��\��V²�͔fE�8�� .r��׆����k��QF��5��{����B9+��or��^ endstream endobj 1086 0 obj << /Length 2571 /Filter /FlateDecode >> stream xڍYK�� ���Kԩ�,Rԫo�u�J��V�q�́#��e��������=���T�H��.�?���]EA��]q~Zj����?��N0�������w�|�;y����q)�����xҗ�t{?�"/=�}�b��d���i�lj��^x@^1���}�y��������ヌ!s�)����_���qR/��+�@�/"Dd�$S����So�Q^�Ҩ� �£��{ìǖ�N���_���{ގ��Js�c=�]�N�TGf"��Է�'�`ޕ�q�L9ֳ.�����=l��Lo-#i*�$"&k��Z���[��__��v%/�=�g� mHF&w =!v�$ R�K� Qi ��Czq���ĥ1�24��|������w ����w�!��n( ^,� �"Z��Vb(X"�ް�D�}�!�y@ӝ�Fi>�B5����Ŷ���[��dp�pnY�=�7�U?L|�M�ڤN�ٻP��D �Ix^�{=+[T���K"Wf81�zFVîq" .�8�����(wB�,IBk���GA���R����� �� Q��p����ۂҷgnU(�98D���a;�r���cS ?��@9�a�&Z�O&��n���(cp���U�����Wщ"�v��L1�ݕ�YɎ�~�����7���Y�,�m\7���Jd޿�Y��đh�4��S��ll�T�]�L�OM��8�;<#씌`�P@�y��DC���Tl+A%x?����U�.���g�7�:�t�1�q��ɧ�>�H�~+�:6�T%�H��(�@nKh&�g-vKꔛ��db���z�r�+t��Gj��p�li���M&7Lw-h������3�l�� �) Tt�gð$�!� \:� [6 R�[����r Gցf�F����S�EO���Л��;�o�4�a���.���h�B��;>SrČ�$��u���n�*��X5�j7�_�)(�b��_���Hs��_�����}U���3}O��oqFd]�7��}2�"E�=�c��˼�n(�!`�b�gZ ��t�+P��r(�;��Jh���!Y�>[�r�P� p�Ԁr�9pwd8�(���.���W�������?����>td��秋�+ ��g��ç�u���2�s��)�#������dr�0�B�!��oO�3���u�� �Q�Ly:/(�"D 5 Syk1+"��]{>�� ����l]l2�df:Oˣ�M�EY���]���i_B��-YTj��:��Jw�%"��X�n�b�r&MV�q��N�@�%v��7�� �����2p=�g��aIoS�]�����5�>�H�tl&�|�a�ɝש�-�xᦤ�I\�h�� �����|�d��֗j�Z ���p P6J1[P��IJ.�9aZ��� ڌRz����6T�I�c��5�!�:יt���r�MD2+���&owׂ�B[ ]ޔjN�Rъ��9Q�� `�� н �[� ����� �`\R����}�]�Z$�|Z�fw@��eց��j�CZDa��@Jn �$Ln2��@*��� �k܎*T�%Ya�&���d������42��A�ܧ�HM�E*^+p,�� c5sXM�&j�-;�M���j‰ �Vy��ec5�f�f�v�$��|���pt��/��� �P��δ#O��Į�~������ ?� �ǝ�����Y�΁k�����_�R�c 6n����0�� l��XN�e�T� �n�:L ����9��E5<�-�kǎ�t~G���m� endstream endobj 1092 0 obj << /Length 3117 /Filter /FlateDecode >> stream xڝَ��}����q%���<���A��A�����Ş���::v=��tZ� lSd�XU������D��Lz8]�4�>x𯿾 �@����w�=��ʂ,<ܟ�����W��ֻ��GQ�%�}c�wq<񏇣oc��c��L�z��6G_�^�*�n���Ň���J�3�}���oo���ȳZ���|��85*� 3�_r$.K���x�0�孫�@p�Y�3�������է��4�������z++W�R]�d�U�����q��x�#�p)+D|thS#5�ף��a?�Th��k�t>��T���#�����&E�=����cy�� �2PscLmޗM��!A��va�Cr@��R�:�T������l ��c��`��aF�,a�t�a���=�ӏl��0���u׼�QU/�D '���wWW�#2�*`��1 �v�]ᶺ�y��6��1��Q55h�#M�/%Ȱ��E���� �J�١��./���Y]�p�5W�_�����jr2)J�s�h�̘b1���X���NT��M'ʠ�j��1���>ѥ��7J���)j���{�Iv#?���Z��;�&?��h����hN��[� C �G�=�܄��N���E�wi*_���Jo��t:�Ԁ��� ̤�����,��֨4�C0U�lX�=�m� >��ծ-O�q�� �Wq��X�p�a(��/�1�O��O �j�J&]�y��>Wlš2�y�Ԁ����W�.� ���G�҉��GC_���*���N��������(S��Y�;�g*��?z�1htO\���=�?�n��%����" 4huO�J-9N��yBBG*�b��)�˻╎ݯ}��z �O岔�V$ 윝�Y�3��8wZ &� ��\�M��c� �s:�vCL��IB[�1 E`�dw�޺�Z*����9s�!Dx��f3`�:��rB��oS�<���;�0i��U��a �y��Q�O)�P٤�o����n� p����+�F+LzS����1���P�$Z�o��k;�Q2���b�B�5��̱�1�]j-x�%�2o�s��k���Y. ��V� ԗ���돃Уٴ<}�Fe��FN@���������\������(�^��k2Q�l<�:�Y�"��x�d�fJv!������V��l��j%q���K4�ӔNZ ~Ĺm��L��`�L��}!�`���oPr��o�{'��NX�I��$�1+:�ےk�T%�+��ȵ�����W�gyt�*K�U�_:�a����k�t�w���(� ��?|�\��<����tݺ����zY���\���7Z�a~�_���[�sh�d%�X��� ��2.q�U����w��l�T�0��%� � �Nt��r�� ;������mϢ��Oe���d��pN�^���=^T�� �&��Ą�_:�o=H�gJ�z�j#om�BQT��4�2LP�j�K�″�1Z��,��O��pN7�4��chɧ��=�����]*L�񤣻LS�ũ}‹y�8��@�[>�y�r�j"]q�����aTv�g2�2@�h ��d�v��I( ^f�J�Dt�`��҂hŕ:�w�T;W�F�_��p�lX��Z5�u}�j�(��5��2�VA0w6�����#f[������+�{��G �N�}�����I\g��\MB�h$+�V�F�e+Rx/���ەcL���v��:~3A�@��ld0˨��z�d�B7:9E~?qǰ�3�Y�)�O4��^%9�H�� �ۼ�1�[7�,7��y��0�� �N�MU�.���!iP�i�z�� ����7hk�t��@L� T9_|�%rd� �-�X��pF�K�}����#6Bq���b�1#,{A�%�^�( ����sg��nA(����ڬ[?�ʭ�#ɢ4A�ǂ"ok��v�S*ɉ���밪��\[��u���m�������kȩ7�dRbYV9����+ұ�f�Jg���5��[��q4��8��c�F��b���_� �>��'2�]�.���*2I�=�/3� �p�<�J�O�����h�%N�5 ��b��3�\�V��,l(/80eMr�� x�U��z7$�7U��]�g��')s�G-�B�u���%�oJK*k�Ak�����/���KcU5�%���ۤ�����n�j�>rZ�2Ӡ���/�9���ѱ� UI��_�I��?X������a��"��=$�hs[:�d�+��~��h����m3H}?����X���L箛�u��|X)���ڝ��W�r��dd|d�yI����9�Lq�w0p�����^4 �tֵ��S'Y���(x�F��cӓ��%��6f����f�*͙���]��=e�Y���Q�gW��}���s��kf�a߶��1��_6�2��ƙ������n�ʤ�Só�/J���D0Y,�Sw\��T ʉ��f���٫-22�,���m0��{_�8Vi��t~����N�맲��5x�}͗�ݷ߭� �J��1�1Xao��_���=�]L��z����9�� �{N&NU<7�g��~f��޴t�Q���0`��g�x�pi��_iJ��uuy��Ft8ǜ�����y ��O#��T��9zO' P�=e�D���`���xS�rї��'i`yZ��ћ�c�_���#����� endstream endobj 1096 0 obj << /Length 1246 /Filter /FlateDecode >> stream xڕWMϛF���½a�lw�e����M�*j��RI��m1 '���;��`x��V>�1��<3?�)�&��*�T��W��^޾|�\ ���_w��HӍ�����sQ���}��Tv�鷱�2���Ri�;Zx�i�:�{+"XQ5�����I�MM�큞����vDR$��ۏ�?~�M�I����?pD����+&�"_ޚ��7Lɓ��Gmڜ �V�-X~���7 �|�)wܽv�=��^�Ы3�3����s�6��م��`�Jǣ�F��Cۇ���x�2 ��${3Pr��o���x����w��l�7� �j�}�������Iq<���lF�I6�i��_�$� H�i�q笸��YP p'�I�TI[�;�" z�Ӌ�P�d�^ �.��Ve]�ܙ/�1���iW�LQ��ݘ�8W�W��E�QDž��0e�\�T���J��a(�{S�C^&~�c������0�k!R��)܏{s(/�����Q(��)�%�Ӥ�"}�L�4ƁI�_,�M�~8�pOB k�<��[�ir������ ��]� endstream endobj 1102 0 obj << /Length 2371 /Filter /FlateDecode >> stream xڝ�n�F�}�B�@f�}�ț���z��,l�" �e�H��|�C�}����Di<=��꺻�����" ��,Q�b�}���qA���︃��A��|w�A�X$|�\/4� ��2[��)u���_�n�=&-�I"��X,x�� iWa�������wS��{m]E^>^�2����Ԇ���?Ш1i�B؍ihe]�n�iͶA���bR�ɂ.�:!c�{�\=��ͫҝ�� ��q���^���E�U�~��]�n���ն�/�(3w��@x�� �0df�Y�5p�@ ″ ? o��*�N'"�64��c޴�+Ͷ�p�&��;Sm�Hx���.��B�;@������t���8D+H�%F~WV�X ����jr�5 c�^2�2�E��<��J2���0[S� -���z�@eզ_�W~���'X䴍Z�թpũ~ ԩ~J}8�����͉�rW�����<�V_2Lz��v��4* �d~X��@�1( N�i�BT��.��jt�Z@�[��C^�Q���5S�aL��V ������k8*�;���ʡõޱpb^p7o ;^^�-�2���}�1n4վ^p&�]M/A��z������z�BJ�]���@�1��M!Ĉh��b1�Z|���L\=DJac��ZS71}~�9����% w飡�qX��s�7��A��C��u��� ����������ɻ ��U�8��.�y���( ��_������ ��re��D{w-m a &y۠ ����������t����v��?�M�̇�c.�������5jVu�k/im��[�IA%���M�E�K7�j�"�D]�����?8֣��;�yQк3-`�m���+�����.p�Ӆ�^Z�z�ˎ��c�~~w�p� Q�ț��A�d��zN�"��dAu@�����~��:��v �i�k�C4�_Y��������Ɲ��.M�4�X[� �H�,�����R��0Q#��=����B���Mmna��vHV?t��d9Ĭ�:3��S���bb�]�iR B~������vz����� ���X$��:�L�ñ�!��f��`e���q�_k�LM�+da9ф�m�؂���=�91�[���D�s��#���FP��|a���'�$��-Ve� ��eBFL��'� �|YW�:�� �!1GcPT���6�?KӗB�^]Ǟ��zy����~��:�n<ݒ�>J(���; Wmo bȞ\G�y�/��N���9��!��zc�=����Y�}����'9� 3Z�!LT4������m�X���ՙ�-���Z�����*��g��J�`��������{ʁ-�R���S=��aһ�%���2K�t�j��D��Bm6��-P=kg�)�hCu���M(m�s�]=1�D�H�Kp�4;�d�&Ɉ'jHF8�aʾ�!�؜ġ�u9 �xeg9 �\N����9���.E�b�T�ߗ��(���؄��9<��lA0�l���;�d��P�� ?h��e�*7���5w�B�o��oRة�(�81�י���a2i ޫ ǣ. �He8�U���w���gG0I��'�鑮���Duo�}v >�5O��ݻ,?�`B-��{�����`�3tml���. Nl�'y �ܗ- ���{"� ��$�־��瓚����T�����6��m�ns� �V�54Y2� ���m>�gu1�f�py�v���y��Wb�¡`aԇt'2EU�POv.��PNr��|�E�� �,��k�A�$��X�͖ЊRr�.$HC���O���SP�U�9��T��Ru-�9��X� ��U�>m� u�x�� �߾��F��lM �ÐyOىð�hO" 9 ���c�)I��R�/�%., �v��:;��.g�3�C�@�d��B@�u8�|�v8F�Qơ�P�^�q �ODƻ\ַI�Q�� ��}�N��p��cf\|,�>*!� {�Eo���VC�( �hUA|��U R:��j���@�������?�k�.M��> stream xڥYY���~ׯ�ʋA���}(O�')YJY��)�������+�R���k@p��6�ڪ堧�3������*��� ��8�ˤ�������~��Y(|k`\�8��yv�6M���/�2����E��W�x�v�0h�Z�q�/V�$I�W]�� o�]Әv˓�;m5_~|�G��ke+����6���c?�=P�8 b/IW����ٛ�i�i=�X���s�A��UV$~'|�7���2���o� �U��IB�=�T]�k&�Ѫ�tm�T#�]�y4����I��8X}g��_�D��И� N) e�ר��u�G��a�'�����5�GW�;�;5�����V�X�y3�2��������i�2?KK��˺6ȡ�H�x���(��n���`����{�FC���[���6VWCg m-���ZE�w�[~�Y�8t{UѢ4*�m g�TY��:��`ՠ�pOd������Ȣ� ��L5-�^^'�����^+�ž�I����Q�����n �������l��.��m��I��{T�Y.���iy7�2��[���橧ښl��V�V۞%�{n���H@��6�ok5�M G�ݭ��� � ��D�fk�v�)+:�~�o�^� 2P��3�������qW��Z��ͷ �G����ڻ7?������,0K�nb�<�ёT`7l^q�a��_�B���ԍ��zU2S��Z���Y,��ԓ$2Z��M#�f@��� ����a�A�<��? U�}�C�~��H�0����?0�]@\��7�$dpO\�'(qw���5���g<���1GM�[En�٪���'�ﻁҪ�e$Yr��諣����� �Unf'/�L{ʦ=2�=�c/�,5�T�%������d���%�8�r�� �b! �@��5Y�I:�+5(~a�v����Xg<������ƕ�U��s�/��g���T(f�N�@IA(�Kk��<ɘW���gt)�����PQ�Y��΃�^�ع��-u�p7 ������l���5$_����wv{��&�������� ��k�~��Oܿ���b�$�2��� :��ɰ)� � !���h7R�90ic��IUۛ�P(�BM���خuw�'k S�%:��FHO��_�qHs�9Y��T[+S���� =�:S-4�h�������J!���� r�玲O� ��X�1|$Q�a�߹e+8�\ �}u�B-(/R^�T04;H�L�G�N���_�'��é��D@O�tE Q��x��]��;�]�P��(M@�k����*n��*�1B��1�=� �n�n��x )��L�br��?���l�Q�б`�T� <+||ڠV,��n �p2/��A���B��3Ӥ�Ԏ/Z ��p�J��ϋ��O����;�a�/e@i���m�s�7��K�4I����%Y�'���{{���,��+r��r\��Lg�DE�_f��ظ��R�к[��� ���0�4T����dn�w�\Wp��Cf�������!�.����O'��WP1q�s�.��R��L*�ez��R!v4-���䬱�N�w~�r��k�)�ڏ0�>#O� Ƥ�.T ��8Υ����H{@���;f�}F�]�&>��F����3�›��xs�bʤ��{g�3O<�a����=�0���%_�$EJ�كq̆�0��ļR��{�&c�̜�@F��S�IZJ<����L�N��f�9_O�+M+�H`ҹ������g姻�] ���7��AEN|�e*���\n���TЍ�;\C�1ӧ�oq�����󚳕/"u�5 )��h3�A�S.���-�$����������O+z.z��<:�O���E�y��� ��a�)��[��ε�8=�č5%�9c&V:� ��q���9��%I�ÚZ�Z��%8��|e��nC�~e�a/�7�:���},�$�AK�/���G|H�RĊ�"���W}�ar?Ȧ��\�uh���6��`f����e�l�w<*�V5SKw��CxΧ(( F8�vQ*���#�X�(+?}�u Y>�����Yo�D|�d珧��kϊ�\����� �Z�%���R�r.��cv�g��k��+[���L��OE$29 ��H��d�ÿ�����C�oϥ��mR���!�r?.˧��1Y D��W���a� endstream endobj 1110 0 obj << /Length 1306 /Filter /FlateDecode >> stream xڭW]s�8}ϯ�mM'���:�@ I�II�N;�}Pl4�-*ɡ����%�8$�vx����{%�� ?�7�{�g ��egv9��=�X\�9z� ͣ�Vg^Aϱ��=tz����U��טl�V`�7=�3�Q�����м`4MI�V�� fX5���+�� ���� �j.�LO���:^`{�?�����l�����J����rlf�� �-��s� S�T��\"������ ��;��ѻ炡�dxM�`�wzcӢX���v�H�*k}�T� 0�}�}����C߰�q=��X6����CV"itB���jd8�7('�85/����| ���{�3-��^Q� ��3W&����ڮxNH����ܮ[�em�?�����X�D6��8�� "�)������¼��Nߒ -���T�-V�-oǘӬ�M�Ɋ������V�;#�����|���A� endstream endobj 1113 0 obj << /Length 1570 /Filter /FlateDecode >> stream xڭX�o�6���~8Z5!�@�i?p4�2Q�A:�i7M&1]����4�o�sl�$ �7MT�?����k7,�ٍ�ո�t́�o�� +�J7 �X�_؊�B�@�޻h}�v�e�����EV^���9ޢ=����t:����p�nsL�v��)��0����S,�����r� #� �-froM��J�;�jw�V���^���|�z���v��f ʗv��v�v��7z}Ǵ;�4m��?MG ��d�G��l��w�rr?y�Ч�n�~�4�<7�� $v�uG���#��q{�9���S>�a�3FI�-��M�X~~�j���[R�sBӲ��ٱ���"@�S��&SI��F���c?D�P����^��6Tz����[�h��/��'�5��Ǐ�;�^ڬ�0��b��6F;�v���Xٖ��O���r2��0x�b��Xt�4��>�|K�_��G4`7� t܉�j���!�o!'�C>�R%w�˜q�Tq8�D�%�P�αdu �ʄ �r�r}�ۓ�Q+F��T�27ju�G�.�fg����a�Z�Z!ڒg[����D,�G��etz�m�>��S *pGEZ�O�j� �``nb���xO��1A��/�7rŶpXQ��<�� A�'���,B<$���ؐf;QN��/��l���HH`:��ՕV��c¥֠�XU)E��'ŌDςΗ�O����p�n� �T���PB6\ �)~3��tl41�u�E��Ȋ<�Bp���p�ٱ\���H�}ѫQdP� �6��ѩ����w�b�q0��d���S�cƪ�LL�EUo3�LP�䀟1UZ�$� )E����9'�������t�9w�Pn �r$N"��qe(=�O$� �����0e�5���G�g�6��W����w����ug�:�go^B� �*"_�$� _�(����*�N't-�08#8�ڪ��[T((J�4Dy�TD��y5i�z�������p�7��5PS��B��4�A��Ug��i�.��h��}��F�� ;KY��[I+]b~=4 ܅�zG;�OY�"�����8��.gg�I[r���]j�LC_�P�g���� 0�C�E�|.�s��;� ���kk'� !HB}� �(k�U�F��y�������6{v�a�`\�k���Ð۷S�R7�����ۼ�9���Mۺ-��{���'�W4jK��(�eR<�>>}���^��Bձ����s���=E��}���(��!V��2+��8�PQ�C�*ΰ�А�J����Wѐ7 ��L�o��&T�5��� endstream endobj 1117 0 obj << /Length 2257 /Filter /FlateDecode >> stream xڭY�o�8�_a��*Y���^rM��C�-R����h��y�%�>��p���f�C�r�kX�(r����7Cןx��O�$�]��$ۿ�h��N���7>�9 �H�u�f�!�&��.��?YnN�Z�'����C���#���73' �����鴩�<���,>�T��������Z�*Cٝ��ڦ�x�X7j���<1 ��?�{s�쬍����B������}7��I���/Bs���LJ�?���h�T?�}7��M��w�@�r��'e�ֺRYSVG�z�ͮ�{^��y�\w�T��fbu$-+��������������<˶9��7�,j4�,�l��B��~���L�J�6B%{T��ڃm�H6P�ի,w|��8�����S��V:�߾ܿ�T�Z�s]���Ns<(+�GO1b�������_?.�������_�h�ɜ0����'U�ښ[2&���(��mޜ��y��!���x���]�y�w/�j]d��P��C�ú?����5-�I���FUy�O2�Z�g�%[6:WP���)C���@�����C�c_V �����hI�LY�&�� �4.��rm�;.�N ��2�N'������Pf����yB�F ��!@ �f; 0@�b��y��5���/{7� E�F+��dd�Q�4�� ��g�V87����Eu��ѣ�Y�r4��#�pcѹ�h�-�(Zy�&k��dc�M��`K`������(9=-|+D��-IF��b�^�C��JW�Y�����H48�URϽ���/���.7 F���BI�kL �j���9�em����WY��r�C ��sF�+-Q���Џ���f��[�L�l\���in�6m�x� ��6��f�4D� �]�f���������� �%g"� �s�y��� M�Q_p�nmWC=A�;b�"q=�Ac��쇕�]�}�ٔ��:/�� �K�x�@S$b��7�0C,܅���#���B�����#�1.d�9{�C��\V9Ӳ��������'2r7jh�J]����I�w?t��7�јx�I*�T���)uF?�Q����N��R��C0�E���\m��i�jU�������#~���^QK�;� �ZO�� �y��� �_�<� ��m������������!����k���J�d�ef�Fq��ɼ�J�� �7=�f��⫩t8���`S�2�1��?%J{�e���ȯ��;�~#����{��u�P endstream endobj 1120 0 obj << /Length 2551 /Filter /FlateDecode >> stream xڵYߏܶ~�_q�K��W+���>�} I�;#4E��x+���B��|��;�J�3�v�� jH�Ùo�r�E?qQF��a���Ed����~|!x�nW#��~��!M/D�Q).���S]7޴�qR�f+� �W�m�������E0�C��~O��5__��[I`T5�8�U���ͤ 2�d���\����z�6��o���b_E|!d��x_Y��B&��"�B�٦Y\� �h�'�+�E��U=�O)��=�S�a&%MyݺQ�zT J�0֎��=s�8,E��K��P�R�W�A��{uk��4)�����m��������wj��zFu�F�iH6�< �:��$��~���}Ӱ, ح E*Hũ���{�� ���d#��i�&=�$Ga��O�@�#�n7[��<�q��Vƨ&�Z�ܛ�ee��L��y�js�(y�� <���Iڪ�Q I�v�4�p���#Kۍp�6�ù�@��7�;��F}��7�y"����Z'��!��"�#��'Um %B�28�� �X�튂͙f�?a��D��F����Ӿ��Q}҆g�ӺH��=�����z�����m`����0[�%�pBDf)#���Q��>Zx�+�����ގ�F�t�᪡y+�Y'�̴ék��p���y��-8���t�U�q�o裡�д�x��{p�aF8�U��IaA��=[}�H�K���րv6|#�z+�28ҮFc�� �ځ��ʐĨ�$�# 8ģ��jn�c a%��5���["lV�~��:��Ep������?�SdYp� �,]��'���ž0v� �8Ʀ�FI�26��F �,d�9"�gT4�M�8~���]� �����d��U�P_�ކc�D�"{B��n̗���ַ�ht���s�jjgN���SI",�y�3Y�\-���G�F��Q��i��a��M�����Ϧ[)�H�<g��O �� @ߝ��P�C�i7qbE ��~ķ����[T��|��P��t��d6�c:$5�!�����CK�e��*t��\�$6�Q�(�՞�(�!�ʔ998��`5���6�<Ƀ��1�oIY��Fe�R�Q8}��a �T�8��|�Y^�'`P�-m���[�N_���]���wy�q�#y���e��lv������-Us���MJ�fړ�]�� u$ /q��~��!�ֻ�(r�8�����`�s������1�+0��Z��P+v��u�R��qWÎ�a����ϧ9P�H��&[�DT-��=�1�q�2y8��q�>Lm��"sl�$�m��5׋(��`G!g0d&r[*�������\`|Q�j�U������zj �&�v��e[�� |�w(�Jx�(�,2"��D���*����YP�-����h�,��S.ȗ�F�e��Q3qk��T"Ccuh<��祖�-�1���:ϜjH�6wy(b�F���{4�v���[���r�h��_���4UW�z�#�d"����t��n!yoDH�Y̷p���]��6\���w�$��&�<�¤�������L��_���[�21���L_5rh� �K�Oz�_P�f��=V�2$T ���7������7�~�������߽h� c.e�M�hC���G潁$=d�Y{����V8�ye����9Y/�%���� 7�Hb�N�H�7mq�n"��ɻs���._�}�8H�U W�2-���U������:,N�9����zW0h�w.��X�q�(�E�H(�������/ˀӜ�{o�&�W�"���74�D\��'�[T�n����&��#"�N\���{���Ch�4vj\_޼��׏�W^��j��+sf�9Xg��I���#����L>1�r���z1=?�@soT�a�\��%�PeJ�v\�.x��VB�-C׎���0.�Pߪ�`�vs=t�,Hk81���ןIr�ü���7TZ-�QZ?��i����I�įl�$a�������5ꠙ d!�8)���� {�;Q Q��\v���9t���o�o�l�s�>Go�}�^:��W�.�@7�_���q�\�t���ND&�`�y�C�p��ހ���p�5���k�����>���p�KB�Į2���Z��w; &˱� �� ~�g'��!=���{]��� ~����p%��mgG\�F�<�zq�RS���h���y̪��� ���q�ȳ<C��S@�7݇j+��Ց�I��C_+�E�\�`^���rD����N���R��O�=����x�N���Z5s��d����O�9� endstream endobj 1126 0 obj << /Length 3161 /Filter /FlateDecode >> stream xڕZKs�6��W�rY*� �O�^���b��V%9P$f�e9!9��_��u$��l�t�����n�S7yp�j��QvS�^ �72��������n�����7?�� �<����~��}u���X�G����^vw����{׵�a�}�4u{��ǣ� �~��'�"o0E_�hY�w�]zFs"��q��8����_���O��a��l�_Yx�"_GIh�J��W:�2?���I�}$��W�*���;ui�m]_���Z ���r_�VFZKze1��b�Hy���m�� �5�3Es0�B�Y��������e����p鋱��a��>�кM��Y;��1(�s�} � �N�z ��?�v�-N浬Tuo��.�#g羻��Bi��T�[{B_��g2HAy-�����_aC)��=�O…"�IM� �*���6��K*���&$\��,7�\��~`�Bp��KYS �#���,v=2�� HT �u��.f�`8[2� �a�"3�3�����$@]kd0)��`��I|�L2�I�[&}8��>؍OLx3�����e�E��Z��sɌ�h$3F�� ���U�#B�6��Ùeb�>`*� �ϻ^sz��'��M/nwp)�G�l{�'u�l��r�[#�r���EH�� u������M�`�@?)XƤ/ؐȄ�>�^6pbU���d�j ���/};Ȅ���\�G8����`�mן�f�����I�E G�iٝ�L-��h\{�b9�ñ�G3�2kL{�l��k����0XAp9A�JPzS|r;�Ǝ��@��:����xQ?r�(#�9��@�h@��d�U��Fn�.m�y�c�S7�AF�@i���a�%Wr�#t�F�l(?Mb�������"�/���%4�/��f�%&�% 뭚s% 6�8q��FbS���ĺ ��=4�)������X��䗴�!���œ�����lW��me᯷t�Ƣ�|��4�r"�(�L��e�A6���O˳�l�����>�$�#��5����>p�dVE����=��-"?��o����D��?��~�l�a��f����,6�Zk%��j=UrV�4�]|��,� $�����:���\6� �!���L�2Xؔ�O!m«8��(,&�8'q��8�`A��� ݣ�N2#N�T����T㿜 ��B�uIv�F��Pw�I�qY��#�N���w��,11�� l�;��~?�̈́+� ��A�\�[|' L ��#��0��c�Q�L[I`9-�GҀ*�sq �J0X��_zTW�[޷��n�B=:�8N,�I)�~>�T�"8�� 9�K-1]T�,V�&^e��?���зf����@v��}��s���S��}{�͖[q���`���D�Q9�/�jw���v7t��4��(�O; �,�ߊ!�8�s�P�~��2�C;yn�8��n�^ y��}����Ap��K�m�V����,R���Nt% �E� �{��S�� �eO^ן/7.o[���,[�n�DW~bMي%qbIV�mbcO,ĒL���;+q�u�a��b����?�"&gZ�m\��o>�SD_���Y��a��Le7:��$�_i��n��qE�ޔ���^�Q��t������ec {-k�,oQ�zM8��~���H��� �Q�* � /$9uд��Ǿ8��)U6 ����d�r�� i���� .�~�q/�]�Q�<�m�F�i�RNZ�c밄dj� fH�=RP�\F{���l��K�!�䝑�N9c�mGk���jR��y4�%��N��^�m�?k&����n����Q�� �4k����n���]���$*��~�b���VW�D���A�í��� �s_���LI0�5HM�� et�����ùl�N/u6�T�N:�YeGr����4r�u��4� <�4�*�jw����ҫ�̦N�M]�#k��昜�2-��KB깩\8�V�� g����tߥP�'X̢,)��E�.=�a�`��h���I4k�D� ��I��ҴcO�S�fbVA�ᤚ�q�Ճ ݿ_�-u���9�|�].�$ w����(ͯ��=.�:ii�*�*a}`29&W��d'�;~���s�>u��^n?0�[�� dۃ��>�҃���ʸ��_L�K��z"J)�<�h* ��J�0�����N� �����n�CS��{}�\��^�_�6�ܻ3�$��_�z}�I IBM�-���,5�m�Ci4ws��U�`�0����݀�Q�.��_y���#_��N{�q�@z�>�U���dȪ@��eO�g9�G-�&��r”�ǭI��rB:� ����7�N�� �s��޾^t�@\����[XaiN\��%���q� P��T?\��)L0Bar��8�e���Ǯk�7�S�:�,�=vn�+e�q�i��fs�W�:�:#�)��H�H�m� ���"���I���>1�}�)bP�Ƭ> ����r�6R���� a6O endstream endobj 1130 0 obj << /Length 3017 /Filter /FlateDecode >> stream xڥk�۸�{~�-�VD�z�}ʳ�!-�dQ\��\��u�%C��l}�EI�u�� ����{��*�?uUDW��aa���YD��O�o����g/�%ɕ��"*���v~����K�zo��k�WZ� ��zeL�n��8���������޵����߼C����q���m���c׻�*�D:H����?={{;R���w> 1/ߕ��+�M���w�nWv}���z���sN�N� �/k�:��~o{�6e��}�>^�:�WI������~OLxm;`� n`Xy?�[�� a.��C� �<:���*΂���Nhh��9牂]���� < U”3�m�s7���gI��mD(t",�+�O���5���+���;y���P�x��X�a�����DId����i�5C�v+/ XUK�Pi�4����V�eaQxlj�Ko�=��8�@ �0i,�?� ���n]�� ����1lejz$Q����-���98��i����{ T�*�`ˆ�� ��q)~\�b-� J��X`0������_��p�˖A殠��,�A�Sae-�l˺�C��]{��VN=تb6f�p��w�n^���)S9��������vT��G�\*0ΩIL�������ݰ�`����j��`�� �3`����� ohy��ʂ���E��*J���q擮��E[ `ep��4?7۞� �Yd�A��-�wC_6�����ݱ*�sU�%[u O�J ��R�����#+^�QYI|*zF��$߮瑈xI�k ~;�V�B�Iq*(�`�Sh<�ʣ��A�GԺ�A��c�'e�$C� ��e��8�mf��$7��.�'N=9�E��$82�^'I� Q���]YDC�o��_')h����,�(<�a�0�o�nW9���²剪� ��5F���/��m�N��� /�u���^�G �ʉ��3��+ä}j�,H�pRch�3VĪ*:<� 7mmǩ��۶G����<�lmB�0!��Z{�]��j����&�e�ORcXo�8\�' �_b^I�*�4���@�9X �8p�z��P9u f�Uۖ�x�^"&�,��>��l�z�!��q�'�SÀ08s=9v'�M=��2���|YY��4�S�'ȱ�Y�%���M���y \���].����*>i�� �|ɋD��D���Ե˟�o��J���p��YF�)x�6:x����M��� ����m�0;폿����aG���f��5�O��m�c�3̾HTjI� ���#/�~\*�3=1Y�'��� �@S��j�R؄���,lI�������,����Bk0SΌʹ)���Z��0ME���S�{� �)�k�E& ����E.vb�7�4�ӰMP���D1�#SQ���vF�Pw޻a\"�cxv`rZlJ�B���ȯ �pd��\���%掾[�r���;��ճn�k���Ns3��E�[^�у��Yn�'a�SY{��Ȝ�~x�P�̓��:p[�Ya�w"�anL����X6�ሽ+b5|3H1)&�k7B��f�6<� @F0�;�y�m����T�� Xg @�Y�[�ب퇶^��������A���JV���~a�G3�^h�T�\�����F��+2`���� x|�(LxK�Zg���.�(ѓ+S����O�<�C۞�$* �s�hK��,h|a�0v�Z9��M(w���Wn}|B�X�>R��|�H��*��ru7�ߗ�&:��)T����qRJ�G6ce?1���7�ި�Jn}�x����~;���(t:K쀑� ��-� ������?����'F��ō?L����|�=�2J����ސ�Qt}�J��(-0��)�y��l�ױy�-yEʣ�(�mYoV��K�qX���r8%��9 `�d�T[�/`J:����2r�S�q�2��5��]�?M,�f������ �ͩ֙ �j����8���_���,�~�C���eog�;7� �a9��a�/tD�o���-��T ��T���P����fi9��Q?�(gl�޷3� /ř endstream endobj 1134 0 obj << /Length 2525 /Filter /FlateDecode >> stream xڭYK���ﯘ�BmY4I|�O�M6Y�ʇ���*� I�P� $wV���(Q�g�)�6@���&���/�+��\��L����*"������?^�·������~��]�eT�w����뻟�ws��l�RA�f�MS��MR��۶��<�t�����{��4�q���s����y���ґ t�����W����I��k!��i���56G�H����q���L �3��ONf���(N��3c�'���߇�xe?gMn��L��y���V����w6B^;)�� >J�B5��Ama��2��p�����|j���3��2�keI��lB����6��������}3�ί](2�q���_l���@�D�-�� Jz�����9�@/�Pq�B��~��x���[��P��\=f��dM�0)s��ϑ�@ĵ���+��`�]3[cMQ���1\ �th*4�A>�������Ŭ�M� ����_���R&:�yD1�&�U�3�� C;d��.NC�f JJ�0��`�� 0�mT��=��0��E�� #Ѐ�"�\ve��78ڞ�3G q�5����&C�k�Ck�t�����;�7�'�.�m �>���r4�� R?mt��������A�2����K(䀙��V}�&��Q���1<�ȒU���/���ړ�c�* 3��”UO k� �$%�k�؊cF �J�� �������4�m,O�o��0z��G���x�_�P��gg{ �t��HI��~���w��� S���C?�5�;� /I� >z���U��$jv�b�е]V��ӛ�n-(G�^��za3sB\V�C�ǿt������:�?�4Ġ��p�XI�%��J�^�!O��qr�q�c `��B8��-�� �O2���?$��T����20^��v��a� jٱc�K��;^DW 9�wT �‡�WX�|,H�4��P�"�^�F���t�;�?�4{B�BT?�wۛ���������(��sh' |�� 6Re���4���,� ~��a��ᦁ"���`��"��4�@����ׅQ��U0�<�@�\/�`��/�^(E��s�r�a^���G����E ����<�h�N4�� ��T� ���tSDPϗl>��L�"f�.&]2��T�Z���*�"̲�a#I�#����91��`�{t<�WJ;N��Z���Z�c�_���|��F������X��� �� Cq�c�f82�O�B �#�|� Э�0�����������)�E�'f��������Ȍk�PQ&�l\3Ի7�+ۍδs�Z�o�҅Q�.:I�_h�l��<�`��c�I�y�������f4�GU�e�|4��S:�ӉCi���f�PGq������G�Qp�B� 6qP5����`|��$���&�bށi��+)����9_)�o �1�~���N�����A� A�0�W�e����×���kJg�YiC��i�i�P�E�C��Rzv)�%�G����!��7��8�� � ��W�6>�|ة����5$��#!�*��/���|*#�����jh�����_�T��jBh�N�7d �^F���eQ�/ �jŶ�q]��?����~)�.+%x��z���#�S3JNlF1c59g��$��#{��Th��+��DWC�X�3&s���Q؆�%)��W; ��� ��� Nn�u�������� ����e��]o+��@�!dǿu�k��D1O ���� |`�c��tB�A�r� :���8�і��B��$�Xg�vM`�2�K�Z 9��>�䉷Vk}��q�; �&�8���=��g�ϖ��d��H��iX�/��� sV%�gō$_�������a��k/�_ Ȇ� ��@�:@$�k&�C Q�������z0A��={�'u��L�՜����\ ��Y̘����kA�$y�i�\��Ljs��6�f��e���`@��1.'DF;V��.X����?!<�Y��І�|{W?%`xwQ+��$=�W��Za��%N�/�@U\�%�p惃�X��W`2b�C��v��_w�Z�2�����R�n���Dq���̿Z��j���c�?;��)��d�#@�Ụjd86TZ0 F��M=�������� ?����w?~+!����y�K���T���+SJ L}}7i�������|�sN endstream endobj 1056 0 obj << /Type /ObjStm /N 100 /First 951 /Length 2109 /Filter /FlateDecode >> stream x��ZKo���W�-����]� ��+(X  � v��@KC�0�afF���߯zH���8����ⰺ��_U�X+��Z�$��?�H���p�41�9�D69^ ��OAx��ފ4Z$' K�e�t�:A� ��e)Y�LJ5� ��}��(X��Xa��T^`�Q̦�׼��0dX�`AAs���z�6a�bq|��RP�ļEH¤�&�{� k5�l^�/��"ܓ�c��j .<�>�/�Fvf�p]vP�����!^�((��Z�� >�hP��,��� p�e�`R��Lb'$�k��q�4�ZAFtlS����ם��@9x��h8�Ů���#X���KS8o���.�8������n ���c]LY��ɲ����:+�6`G �neF� 瀆O� ��lԇS�լ����W��cs6Kx����Us���)g�a)�������Is"jl���*AY^h�:��D �M��`9�� ���ip�-B�� �$|���������h�*r�:�"����G��FD".ȉ�r� v ��j"< � ����� ���y3�~��)���쾘L.�M�nj.I�z��L���|�n��������b�S���� ��f!V��dƷ�u i[`�#q3��ǽm3�d���S���c��<��TVwE�JW7��m#>m��j�N��)��k.xi��V�y#������RL/���*�6���0�b��UU�]�_�X�O���^�� h�U�R|�-�]�鯿�X$�Qb��\�<DŽ�Ep�x�fͮ�^���rr;!�i�%# pr� i�4�ivKI��L��]�����}�!��Wb�&��4ܩ#��e�>�K|�y/�ɾ�Rz� ��A��w�>A���'%�[}rO�~lQ@�$+��Ei�+�G(tŻY󰞭reԛ�v1_U���/��F��e������8-C�N��Qt���̘-��!ʄ�k(J4�a�<��1a��\g�D�n�S�հ_&�7.��*9��4"��؜Fc�D��^:�q 9��냴�vFs1�����Y]n�.Dj$(}��!0�Egx�i���Ø@��A�4cL�}�x�'`L����1�>�&��<�&�=��Nb0�T㲘/֋�}V#��������+����Tq�ٿz�����YT#r%�r%n�H�'��6���b��� �%��Z���;�V�{\�-鱽)8�0�4Ƚ���aɰ�d� ��s�Ĭ��8(��0�ƨ���픀I ��{nr�Z!�徚�V��Xb�I���Y ,s�W���~M}C��E���|`���C&�g�yF�t�ɡ�}�yo��R �0w0��P�it#t ��HA�ڢ���x�8�|��>�Y9�(:(�^��T�?��U�ìi�ŧǦ�����m�ڔkǓz=�����=;%�e����M�]��~���4��o����Y�>�۬��rQo�h���n�~\Lu�X���_�_��I��7Z:�����]4�%�����γ���Ŏ�>q���9j��΢� S_(L���U��Cۿ��*���)���l��4��KyI<� ���or( `��' c�T�r�{(�9���˫ fŬ�}had^V{��q �������!{`���]78�|���j?�'���[ 0P�h���2�?�a8W7��ݬ���*����ܔYV��O�fU���\,gh%�|hVˑMm{\�͖�� Y��l������6C91OS��ɪC&��41�g�~�)�<�Ƒ��f��:�jJu$m ��&��k�<�pԃ;�p���v��ۮͨV4܎��n�}���*LP����m:�Y�Lfm��#�$�&�V�4��ǟI�9���ዜ�߮��R��O��J"���1_)��"���� ���Bc�Q����*&��.���`l���s�y��I�1=�탘���|�6�N(�>G$����o��&���ô����Y��R�-�u�Y�n�#�X��ͲXA���]�Š�;K�N���.�Z�ݓ}]�ڴ�UGL(0bG�WSȞ����N��GL�H��9Ϩ�d8<ˈ4�F��DI�ԃ�8H�{���oh endstream endobj 1139 0 obj << /Length 1880 /Filter /FlateDecode >> stream xڝX�o�8�޿��\T����r���5��v��@��Á�h�W= �J����;�!U�U��Eф"��� �,b��,V�̲hŪE�=���-hq��'�� �0<�|�~��M�/�8Zūd�ޞ�Z7�߂W{~0B-�,˂�j2���~�V�QC��~G���B Z^߿~�+h�U��{��l;(wt�Ft��dy�y�����'7�I� ��"sq#�����*hΜ�z�v��·[� ���glF��D�B����O�v��🢩������?��6���b��5!�������7*�{�I�dmlJ�H��5W�e��P�Nk��9H-�dW$��8)g�-����YMV � E��6bvk�q@�q��eGD"<�N� '�N=� ��Fōj��HN��w J��ѧ$r�zR.2��8��xӄ�qP�=� �55��,a�V�wFJGYYx"+�� �����<�#4��3!g��{)����6y�W����B�QQf����l�J��4�W �X���������^����ql��x�fz��4J��_I���ƃE�Ak���4S�a���:���o�lF�@����'{ �)-0�o�b��3�f� ��qK�*v�v�4+����~��O5}p7�*ė:���� �l�X�h�Q# 2:��� 4�a�p9 vtC�N�\y>�8��]ڋ� ��K� 44�{�Z+�&rDE@藶;%�:����z�/����d/;޺�/-�㶅�����`Sl���dw;�W�4u���M$�6��.�Eg�҃�ߙS�s�r`ˍx ���v�Ԏ�J��Q ��sC+�Q�i����e�[�����rs�RӨ�Y�eׇ������w7�o��_��o�~w3��,�yF�9�K�"�R�o�/_��o�>DZH�a�i�T�b;���!�f����J��_� *_�p���,kDC}9�OXq���Ӻ����εvV�Z]5b���L�lm�"�W��?h�,,s�|E���z�cۭ!;��y�ͣrjL/������� Ę1���x�˯��a+��3' 9I�����|׈�j .Ž��Ÿ��#�D�X�a����<��M��G�F?���l:���&�q�H���F;� �A���o����n��*�uGR�O�����g�� �7����2CH�2��90;��)u9(�YE�*%� r t(�`�l߿���l<��}׍kb� ǩT?^��4{�D# �U�;l+�x� =���s�Q|��&�O�9̩R��� ŵ�{#ZI�s���(^�g�����HBl�c#8=I���kўJ7nt��N�1�WF����9I��.�����>� ���DS���5���b0Coli �-w=m��K��MR�I�e0�4�,h��\�9V]�C���T�UE�)�pqu7�S����xm����ٻR�b�^��N�]��QvB;�|���;�D�J��� ux'z�;�a���I��0�W�tUY���?�x������r��.�����!C�A�.���AĪ�#�����qVO�L�KŦ��?�����7F����4NbZ��U\^e}�0��ހ?�M� endstream endobj 1146 0 obj << /Length 2776 /Filter /FlateDecode >> stream x��Y[oܺ~ϯ T X�(R��47� HҬ�� PVZ�P��G��q��;�j)��M�€E��p� �� �O8Y�$R��J���Y��ݭC��o� ��ѳ8�v���u9"� ��։��i�� �ƍ������^]�+Ea��["�ٞi��E�pO�*N�/���š��mVR�C��u�ܮ<�D����Jj>_�|M�>G�;�W�HR����,��S T Cp���A#a�YD{��7�0uw0O��߃�����n�?��lVa��P�pwyO����׺��m��b�6-9�g��<�e��u��ʉ�,�)J.3�Gq�j���K'�f�dz�������q��@��k �H�m���G�c=Tpv��Ԑ�z�D �<�)eן��-~��;f������p�6�����$1�k]�} _�4�H�����mP��x��z=�6��@�EՕ���*m��a����j�Q�nEn�U�>ؗۊ%���A �?�q�>a�M��_,-�8K O��_������Ĺ�ju�6��SR���Rx��Q��[�+ ��l��).d-� 4��� ���a� �~c ��h�@��S��8��O6E����y��j�'>��G������G��[~ʦ׻�������BL��갆� =w:��S��%�&�����N{����\~��pÃ�&���׻ ��w�7Ԩ˼�VLe�k=P��:�����u�X8���� ��E�l�,2N��&$�N�v���f�Z`��)\�C`Ijy�W#HJ�� v�r_WM^��� %����?�zZྫ����fS���>��-Ơ�&��.�v!oZUW�-x�L����~G�Bø�ߜ7D��gL���dtT,�{�F��C)Al��J��l��쇎 GӮS�%;JI�P���!��몡���e��5����`���R��S,L ��b���p��˛�f]J{ Î��,�-�Y8�סk��8c�|����N�T��b,c0*���eE ����������@�l��Q����`�]�4�#j�d����>;�^�K�/1|��S�ɖ0��b�MBȂ�ue��� �D�����7����L��@Dd8ƁuL��ƪ��h�~PT|]��2UA�)�tT� |�_�n�b_(�狒�v���/����̌*�����!?s:��i�� �Le��1��O��p{�™�j����j9�p�1�jMy4� �u�e ��wO V��& ��-��ęQi�>7 �� �@*t��p�B"r*�{�M����'t�X2F�(X��!q,g���)Y�0&�h ����|ȫ�V5�󲠅��;� 'h�}�#R7m����-.�-%�1-P\S�d�W���;�L�����B՘l� �sIW�V�@��2�yH�y�����PW�+����B G���~�@D���%�Ih,E~=��LR >5�@�8��y��6bVE���x/�#�1]P��7���]L�eQB�D�F��Q��᧱rd���O�(��,��5[t�@��>7��c=6Q�6m�������с*�M��V���I�!���9�c��컪kSp�� �RZ*�d��2o�X~y����߮�p���-Nf)����w�ϯ�޿[/UPI��x,����0����M>KC�����L��}R�He�U���ʐB*��s.0튊$��qIYY�Q��� TFK���3��߿{}���˫��ˍ~�������f�.iS��O�q[ ]VL��E���V�S�n�s�=��Ē����V�?'"��~�����m�%������2H�Dck4~d?����q�X��2>�G�#y4+�T��dlͽa���<��K��~q�����-j� 7���x��E�cR�&�)@�,��-��!�S�; tOK?hjĨ� #,to4�PA+?�C�?ceHh��qa������.'�K}7��p+�9R2��Ap�����(�p �ăL�(�ģcuM�X[��]��K�7 {ya�,�}_ePKea�����i��{\'��~!�b�����[R+�N/�:]5�ќ>�W|�i�dj�;} �N��{�7�~�X�7W��R�푪�,~��J;(r�&OՂ��Y�K��lQz| P�Ҥ~D���*�/�ou��u,�T<^*�:�釄7�O?_t \�DPMyR�~�Im�T�O꒸=�}Q��Eg@iR?���z�/M���Ί4������/6�U��3"� ���Cn�b_B�lQ @Zv�q0v|�}��t!�:~,{�#g��}ٰ�9.St��%�(d��z9F:�ЁZ�]z)�!q_;~(��Afބa�����=<q�M����_��GUlY��o����7��6}��r�le��5��/oDޕ��@Aݳ�Iß����Ʉ/�s����)����2K�{ʹG,÷v���Nַ����'N*��<7�/����Y���~��}Ӏ����T�WB(P��_V�((�$���D�4���޶y��1��7��s endstream endobj 1152 0 obj << /Length 2849 /Filter /FlateDecode >> stream xڭYK�ܸ ��Wt�!�L�d��^����S��8��T�����bO+VKQ�q�� �W�f�v��jD�I���l� �Ol�p�FQ��l�;> ]o{���o&X�A&�����7q�a�������S����>u���(��W�R�����d�umSUe}G��j�|��l)�j���R׮9���$�1��!eq���է۟��t;�9��+�C�?�N� F�&�T "E*�k:�������w|�va����z��8]��S�����z;�ï� J�^���=���{em;�ZweS��*�Ě}�V���I���4��35c�l[]Q�â���t͋v����t�n���m��9�u YKAj:y!X�j�ñ4�Y��gjm[�.l���q{׸� �z��sNι��������`�a�q?�3��5O~��h3�ܮV�ZUC��;�b�z���������?�sp1��P�^j�ll���8M�zw���^˪�- ?�`��R�BR�kum'_�pom���7�A�F�f&� Do��ג�2�'�T"Q�g9?�%Y2�'�{! ����-�_�pu<�&����4�p�y $���WY�f�i�������:c�BÓd�I`sY�\n����V�e�,�N��eah�-��gÂzws���N7it[�E��Ai����I[I�[�� B!�� n���Z�g:N?J�@���Civ|�+��I����8�ڔ�ޜБ�e�0 nֶ�ƁHG��Ǧ��Ҟ�]S��J�Y5���� �A����M�����Q�]�W��w�GS��eŤ��2'@���� �@$�".�(�F�5l � ^�LM��/;}���K�*�DA�04��׷�ZA��p�<�u��# ��<������] ��G.i�0��Z��G�}׷�!��;�MwxBb�yI*�����@< /��םw��Wy�y���$ 8��Ir"��u��EI�f��y��h�Q��D?�1���am�< B�D�I�b�3/`w-TTdj�1�֎9E�B���e ���@ۘ0E VY�Lנ�I�R@� ߕ�8�}U��S��z[`V�!5p vjl`�‘- ��@�"����iM�T �;�M�2 b�z3!�*� �{h�����Mr�����ԎX��M��X��T��8T�ۺ��#μ=�(�99��b/���#/�����c�_�Ur��f'Ī��|��3�o؝�%hy�jZ�G���a�v�� 퐏`Oז�����~]�S�#͸+�`?����Yؕ%��e. .p��+��Dr��ɵ9|�t�?`vX ���$Z_w+��l���2&=�w�;��n�n��f�6-F � ��v�H�V�bl�wn��l��k.c{n��n�9ڽ�9X kL�T�%� S�q���4�b,r�}�!���)T �7��|B)�ۑ+Q\oɠqg�_��Ў�����"!&�J���yj�N(� ��Ȑ1��;�o�6�wS �Ӥ���%����K޶���2���[Һ���ye�M��d2�!׏����Ϭ���7|C�+���n9\�8w��W�<�] T~Q�f�t^qfHmU_q��5ܑ� ��O>@�O5�?��+��]�w��BӇOOǫ��B�rA�(?'���D�Mr(cYkvf�wE(��@�T�}�R�&#}��݌*�^hi�DK� J��7�[?�C��J0��>��Hc��/����R?V ��Ze�)��&�!:� ͣU�!H���gAr�~���< �W��@S3��Z��XL�9�0�5�U��#�w<�-1��A3� #9���S�q���H�3� �,�J��R�k��c�e�(�~��M�^ �!���O#s}(\��߰�zh_�'��|yk׮.�q6���QXxD (���Zc�J�'2 @OM� u/��p�(������B��>�����7,2L"��E3F�7�-N>��G㊀�R-�Wp%� @ॸ��~G�"5'��c����{��4_:S[�EI��+��/� �E<�t���t�n#�'թ�O� ����k׌}��uU4Y�P�i��)7//O�&CwگsXȧ����! M4�Ӎf�F7�ʛ�R3�W�,7�a�T�J�$�-�Hf� /���D�WoaCW���9�[o=�&964�iQK�|q�1-T��yA�81�� �rc��q�8O��̓q���͏-4?��� �n��zs�6���ܞ���eŃ%yj�{�NW���b�-/���~��BЈ\}`�o��ï���Hv�����(�6N��������Ϯ�_v��e�ט��#7� �(�)ZA�:/I( �|� ����;����q2`���0��� e�ƫKz��8�k���M�s1���5��T�J�|m�?�vM� endstream endobj 1156 0 obj << /Length 1279 /Filter /FlateDecode >> stream xڝW]o�8}��mA� ��@����\�PA��j�>���I��N)R��}��I��R�8�̙����X��Υ�#o� � ��%��,�/l��� ��������2G���q�Tu���l��A�3\���=���� �zΰ�N�m���(����y] ��7�R9�t�ɥ?-�K�'��n��� ~\L���8�28��StC�c{�� �`虶���F��3��#"H69 �� ���ޮ�&E�C{dڎb�{6R������@��������'9��oq��b���N�Ҽ��y��(6p�v93M ܴ ��٦5�a=�q�7����л��e��b�ꊓ��݉|pC1:2&��I�*(�2�b�� ���=b[9z��=&�|S��ne� ������q�\~x���A>�|$|� ��3B� �Aj֌�J�����y9 f����|��|k��v��v����ߦ��4M���.���Zv+�%�:y8�u��b�s�m4pp�b��S���8f����,��o��P�gh�tR�}G �����*(3��6��2|!K'h�\0�|���V6�(�3Z@~l��|� �%(��@�%-��B 8f0ӻa�b�7$��RFͭƺ�0�F�������� � ;9�3�6 ǘ�)�;n|����.��,T��B��cZp�M���y����U��j!��ug�4#ܟ�!���D�:W6�@����3���N'�3����=k��W�������~%�$:nJ �a�-P�" i�K���J�ꡞ�-Z�o A�3F����\.�g�����6����T�^Y/2n���$�>�(�P��7��S��|��Ŋ>]���K(� |:�� �F�N:H�Sȶ�Q�{�-�������X����fIw2"���&��U�RT��f�MA�ƶb���L��V\�o��(�[%mn�6�:��J�Z%�Q��f�� ������9�7�ǧ�|:>��)6PS}�Y5�&xZm��J����EC�!]c�{8!e_�~������>�W���S.U�|��=����~��=�6Qc!Z����� endstream endobj 1160 0 obj << /Length 2614 /Filter /FlateDecode >> stream xڝk��6�{~��|�v/��A��O�$-r���d�Cq=�\�^�"K>=v����)Q��k�F�pH�{��p��pU�,�E!����* h�����^��D��������I� QE�zعG=lW����ձ��DZW�o|)�]S�D�׷MU��/��u�yx����8�^�����6��XVz˨���p)��$����_}��a�9��?�b^r��܅�2��4�"�%���7�7��������?������?�����C��d4�0�M�����@v�%� ���5�G/�r��~Vՠzd�}�_e� ��/A�����Xi�b1ۧ��[Q3��9'�^���}�z~磝���*�ikn��g�����1X����-�O {�O��4\_�y�=�)YǍ��ld/<T�l��'��i!�Z{hfW��pS�m�Vo��-�9���� nv �T[����[6�P��ɹt�2�C� B�r!C��@�e�W���ѥ��By���`*�XZ�݈����4�[i�5N�����G�(i�^E$����݊�%��@��` i��|�K�̝�f �y,�sk�O�)wHc*� Fj�?�������4F~�� 4:F0T���g �2I��� �9����T.���Z<�%������M��ޏ�5��ݣj�[�S]�͒4����4���� Qt�`��,Pa��T��/;���k_�7 \\�x��9���|K�M��yZ��j ��xC��<̯z��c�[ݕO���W`����R�#+`�d��� �Gpk����e�(�L�yd�����r\�+��2�6&)���g���R\1fJb��@dř�[�_� t��MSz^a:]Ͳ�/Atlɸ��/�W=�xa</ ��yv�فz~(d�U��z�=�����d6~����IvFH�!jAsa�� �FC\�["�(s���wN�U1�$��"��u�JB�qAy�R����m'����,����,��yh��D�(�-��i�����Qa�1>2ȓ���xN� ���-����hd<*��5mތ��a�̍���H���2 #��n9�{���b��Q���~�/*�_�{�(5�а���!U��&� `�^q ﵽ�Ut�5'r�"k ��D����\�������D`�7��l�cI�e�_�\pm��ʺf7�Tɖ>'{�B������� �F/���X��*&�R=��ƞ���_1%�3k��d\�<���JH�R��O�4��J���9A��� $׃dm�돑�BT��̓8Xr�.q�\��,E�&Zˀ��� 7�X�픁�c`��A�8����d:>�]m 6�*s2�1[0�H �LꧦW��M(B�d����C �/J@�0�B '�e8�����U�~�c r!�)��roY*-�϶��x� L?�� �P��dY�Q3<���Vwb�R���.:�?C�\eִ�N<"%V�g(���-Ϫ� �A��I��kwB�;OxsX=�Ѳ G?.4q�T$b�����`b��B��n`��"#��5U��(�� �pC/�R�ԑ9�B�}�,���:W�o)�"L� �k0T�n������W͆��|��0|,��?-���B�v�á�v�\ot A���ܯ�����\�C��s�팕+�pP�no�6n ����ɶ���X8ʩ��Q;�Sx���'�v�5�_/�0Q�N x-Ц���}��P���k����(�.l�h��X;Ί�7��6��CǗ�N�e�vh���D�P�$9woC֮����a-Q� �3|�m76�܅�tt�/)�gy8ȯVx�h�[W�y���W�Y��j�^��zZ��]�/E2�83�Ϙ��2�[r?� �j�Q$�������b("2Y1B:��]��8B�1���0ί^g*�5��M�#�D��I�B(x��V�������uYo�a��0���D(z�cl��0O\���9 �ET;z:.�s���1������m[ O�7eM��]�}|*�Rd�<�QN�Jf�}�,��i9!�Q1�ɱΜ> stream xڭZ[o�6~ϯ0��r�EQ%w_�I�Ȣ���.��<���H��&����}ύ��5M7X�P$uxx��9��៾�� g����b��l�x�����J˾l\Mv�����W�^�Pea�/�SR�����7������d�W�8������Ҡo��*�G^|�m���wo��Qt9n��������PVņ����%mRk�^�r��W���m�����O�N�1��I+mb���τ��lk��$ʴ綬�ze�Z7��|<�y_6���Q�\���>�}��ZE6 ������<芼]_E.��Bÿm�>��lz*{���ҁ�r?��$�^!g+��*1 �Җ*Q�kb�$��m�<"nL₺����_nL�e=۟Ǫ*z�)�]�]��V66�]Q�*�d�J��H-�?�T�{5پ��S�'� ,f��ӛ���_�YV&��HV�)�G1i��CG�2 ؒu*5���W��KzB���f��n3z�b���ȩX�����I��ݢ�G*��u�P+��v��׻b���dj�e��1���Ehy�t&�(N�3m�����\��Kg�F�:��Q��$���$�Mّ�^�p�����n a��o�3�lh>����l ����0� �:��@�M"�,7[��pem��%�t��8R� ��n����bd�e�s��ᥧ]�Ƴw|��go�m~�z~(;qt��G��(�3��b��;�p ��� =U���ڿT��%Ӻ���o��å�z�?T�z Cg�q@��D�i�S&N"R?�5��e�f��L���(x�"�;�-!��M[�ҩ!���L&q� �̈́M�%t�� %�S����7�3Q��!S��Z(��S�PO�Ȃ:t��� �p�*�cO*�A='�Ϙ ���9�b��,�iH���o󺫆$ �TJ�ӡ��rvp�m��1;��?����ᩬ*q��=]�J�Ņ�5�l׷r���$KN#�(�(��lR� |A�]�V Q� �[o�0{����x��Sl2=�\�����Q0ϐ�Q.�=`$�a ]�H`#a$�n�V!NՂ�.V�Vi��a�_�.�%����� �1�U�!ƨCx(�ڎƾb�1{0�tFRk�ȓ,@�KB�8�{�$!1c�H�2Y<w����S��\��_��-��zCQ �&��D���]��Q�O�'o� $R0���w�x��r�}[<�y-g�~���XH�֌�g��\F���1��h{�-�AGmG� A,��0T�d���e�9c�Q8hb���!i�tͧ�B�`T��fs&~�>���2F��������f�@n0K�6�-;u�qF��'`'e�G1��8���Bq0`��y�c�g���>��y���!����M�XR�І.%�P_���.�-bvP��9�~��B��6$Fǀ�R}�Y0�u��#1s�׈dWo����땤:��M��7�;������� �C�W� {�#U��s������~pu:R1ƀ�#P3E;�p 9|0/_�σ�d�)�Sucz�M2�3������67v���3�G����KW� `㩦� �`��� �Cy>_l�-�[at1Ce33Hy�2,ԣ�]<ːw�B,�z�r\�@�y�ۛ�џT\��6�I�e��ۑ��j����=����+���g��ξ�}�"��@ɡmHs�����և�m�����' ��E:֝������������_s������~s���!��v� n;�XeRw�Ie�w,|sy���v��<�՛��p? �-���҈��/ҩ�e��z�0��q���0��1�Z :�fR�~���۳������v6������;_�H�򯽽��z*�X������sM �Ƿ��m���E�k�������d���w�b���%�o�����^|�k�Rz\�-��O��VǶ �}��He��M ݺ+��`̧� 1�H�nb i�1��1�:-�8Na���8–�C�9���c�ak��p�ꇼl;y�ȇN�� {5�ů �a*?���� ����H�4 Z( ��i�V���ƍXpZ�͠�I3w�N>|�8L���n*��q�I�^?��G�tA�v|2�É�����?AdRE�P�vDB\�� ��<�a�C��z�c���4����/��g�Y+�+���F� z�����V�y��15��ďe�a��M !k%�������p]�Q>-� 1�E|`��Z�Ev� <2>��r��I9AV�����u6�$�̣���W���\�N��-�����<��=�)j9�e8�9�Z��D��^�/a6��F���)�.f��99гh�Y�y��y� c9�������Jj��,xO�w^T��*p��癴�V�\��8N�B'���EZt�f£3�~v��ڜ�6p7Qd:am�3?V ����AUl��< �V���%��T���� ��k�}�\!�7�u��K� "U9Q�+��m ����yK5�W(h��ċ�9u׋o����A�[�·����˳���/@N����4E�P���d�Dw�ô|D&����7ង3�f`b;��Ӵ��9@e���/]�hH�6��e�L�Q�0���`�X�*s� !*.>]��뇉o0fQ0�)��ρ�L��/�OD>�*L��#��ih�`V�>��Q��(�Ƚ������0��M����"�h��͍ ���2��(�_�� endstream endobj 1168 0 obj << /Length 2513 /Filter /FlateDecode >> stream xڭˎ�6�>_��B�Z��u&3�,v�AOv����h�I4(iz���zQ�mM0X ��b�X�w��.��pW�<��2)vU�& �=�x���7���������?��. �2(���qM����{Q�Q��!�c��nH��{g�}Tx�5m��'^|}�V����p�x�B���O �LwnZ]3�A����E{i����o�?�<�Q�C̻��.L�8�"�]V$~'|�����4��O�y�ujz�>�����<�̑�?O�yy��/Ϫ~h�ؘ~@�o �K?�D��E�Y��4��̓�?�l�ABh�̀�C�i�t�[X�BO1N� �M�1���� �x� ����VU�#���U�:�bsz!m�}Ł�� ��#^��+ҝb?L�J�yI�.���۶�D8�_ckm� IxVW��rp��b�L~�N��m,�4=XW3�L�� ��ɐ�����a*,��R �~Aaህ�#9[�rO����i��έ�4{�r�>�b<'*���L���X^�q ��rjͳjُj}T�H;��̼Lؖ�A��'��(r�#����{�2a�*��G=�BP �#h���_ q �KZU��"3 t4�(ac�5� ����%��rܠ��뭤Bn��)���&$��9�����m4p2Mf��L�� \dB�nl8��}QuȠf|�%�f�����b�Q,-OJ�����y/L���lD�^H"#OX��qP0�+Q �  �$��R��"�c6͒\b�G_�� ��J�Qu-��r� �&>i�vw��f%l���<�!ɉ{���;L�d�챐E�q�R����a��a�W'0��?�3�֌�n�<�5H��o�_ ����@�!B�V������"�a�q`0 �A� �i_Y1�~=�|� �E�銾D2*2V�����Q���b 6EB��ͽ׵���Ԍc�J�i�7�#�jȘ�A��ᖧ��/XJ��9�+���y0���J}��F����'MA(�dxJY0�d5��P�$�u�8����$}@Bђ�a�di�/�ZFrJ�*�2���%�ffFF��9B)����0Y�&j��&�Mۺx�*�$> ��Ը,�����\�$���Vt ?* G�oڭâ�j> S5�H�^t �E���Cj�Rʊ����?y�D������"4��������ӿ�x�p� �a��L0Yj ~J��\%�உŎ�]��!U�� ޜc�$~]�F��A���ǽ���1�GL1��?åC�r�5��YJLa\geca�Ȕ�`}i*=o����M�M=�j��/Kq��׌K�':��.W\:�8M��/�u3`���ymą_lWq�U���9)�1íI����?=�)6v⍩b�=�����i)��B}+;�b]m�:���Y��&[���=$���i���� ��_�������� v��{�EL��L�� �uu5�mDi�qYx�"p�SцS~��\⋂��w_՞���rLa �0�c:�L�Sn�� g'� �Y��uaF���X"�8���Fx�����Z# �c3 fCa��U�9�eʾѓ��·���W6�xT�^=ugc6BH�Q� v���T�<�δ���¹��uC^b1Y�����?)�Õ�Εޥ� ��Σ�����E��dFy�O �5���z#d�D/�Q#��׺�00��E)�����凧M�_yO��kB'�ӝ�"j�-K�< .ܞ&?PQ�_y�1���1���З�X|sv��?"� �K��ݖa endstream endobj 1172 0 obj << /Length 1475 /Filter /FlateDecode >> stream xڝWKs�6��W��R3!�A=�v���v:�nI�Ih)RCRM��� R���n�3�.���lA�-4](!�Ί��pC�i�[���� �t)�#ʻ��W��\0J4�l�ڎE�6�����;�,S!D��^�Y&���Z�"隺,]�Ï���������~�%����ţu}8��n��eY�?1QH��t�~����j�Yr�B�<�3�e ��E^d�� -|�zY��T�;f����cDK�=c*��I��V�i}ꎧ.�S����md�cf�$�X��E}���D�⯿}���a���'J�k4)��I��.����G����+��n��(N�����o��ol�[W�Ι��e7�]'�o�KUw��i�5{{���n�M�Qi�Zp���]]�5�RNt1��Y�(F�| ��d�w-^��Cv\���Y0X�a�6%BH�'�u�5���:{8v��jd��(�1� v��A�e65?(!719�-�"�AHI�Z������x,�/&'"�SO/�,Y}�3��`D���p��I�)��ź�|v� S6xR�� ��ߖu���`x��ᤞ�������(���9��J�c�^\:�Q��pͦ�{6�'�1ɉ�D� C�� ���b$�'ω�z��̙�#�A�u����� �SO}�r�@&$�P��rѤ��x�(_��=���o����x���T�I�t����������^�8ӄӫ�iOX��A����& (���㐓���P}1jF�"�� ��HJ�������sV0�_����� X�P1�l�r��0pL����hs���œI¥��r���[a��2�7n��ڰ�Yߴ]"�*<���.R!�}�&h��eDdyh�0�p0As�C�LeΓ�&�~�U�ΠF���f���*M�C� �C ����֠-�61�ޘ8�3����;l����r�� *E$��}}8�N{t�]ς�$��4�\�KC4�6�w�{�Du]��Y��U@((����5�1�'�2?��H�)C`X����|�L�\��c�� �9%\�ː�ti� hNX|N�< �Sf���mݮµ�X��2z�k �2��`�՗ /�����F����P�2����mo]���U��Oۺ�E�p �C��^ �,�d�� q�"��-�g��&ndSX^��Ը��A��^��7R�I�b]�6}�UL�'�����ȹ"�ЗQZ<�l��9>'���cx��Tٖ��+=U$+����S� � endstream endobj 1175 0 obj << /Length 793 /Filter /FlateDecode >> stream xڍUMo�@��Wp�(l�����M��R����്�����3̂C�HQ�Û����"��'��G�R,�.*�W|�vۈ�D�K�0}V�au��ޘHp��\D�Md�`NU�u�3�"���zu�����ol����t2��h� SY��P�� �����.IE�um��*��h�u�lq��Li+�9s�NL�-b��tO�zX�D΄� ��&Iu�ŷ����ˡ�C�гjʶ� O��o?��T���n��j��E�� e����ն)B\�c��u���ԣ���xrq� �ۗ�+& Oc�k���:��ҵ�,��/���,�Sx� ʷC�J ��<�r��mK�SׂHc�� ߠ~x�(şb����� ���cW�,2W�Уll2U�$Z�$u�ī��=�+:���pzI�Hv��*��c�^�P/9�w�=/�.�c�w�!p�:��@�d�4r*3ʹT8�r9�Y��?��CU�}�҆ؠ���S�P��!�\����N�WF�%Ҿ���wO�QL N���u� ,���*#�ޘ i)�BQ9�ɯAN�9�I���X�Q�h=>�������u�I�GJF5dA�χO�׻��O����pɜ���m/L$�\�6Ѧ��c����(fݼ��"tm����0� ��ZmgÎE������"� 6_/��OX�O�� �h��&� ����j=A��H���?��@;y�d�qL�5}�QRZfς�u�,�US��%,@�g��} ��*{��fm��e�e� �M�� P�%��b���qf�k endstream endobj 1179 0 obj << /Length 3112 /Filter /FlateDecode >> stream xڕZY��6~����<�JY "���{��Jf+�}�HH�ENҶ��/���^'���h��u��.�ꮈ�vqI~W��E4�����gJ�@�]P���͛4�SQXD���?ܥJ���T��ݿ�Lo�s��g��O;�Z��#��ə��S�P�4�3��,OB'|�R�m�����V�ۨ��McZۍn��wi`���5 �c[r�6� .������q���y��&: �l��:��g?lt�7�> ���p�`�0��" �����+Qpb\�=p�l���<>>6Ҿ����H�H@� ���u �>w5�:�60p�;g��2���H�0I�m���"L�u�����v��7ҹ�K��.�ߓ�yN���pY��8����aUފ)��YkQߤ-/���ɖk[��s�� ����" ��&��G�.v�mr��b��Ӌ<�iPxe��C<�vBl�Ǎe `8J#%j��3g��Z�h��?=y*�5�dy���[t1�XM��\ۉU&z `��g��O&z^%`���d��d��Ѵ�cL����� S������.�O ����c�5BDb0C�&���Ο���0��4�`?Aނ�T H �_r�,�pL�!��ɲ��:9Pv��E��\2:�� �t�u �Nߟ��RaY���S�'ۗ�N�5��YLH�:��*��w�O�^�Z0:4� 4c�#ZGV,Kj�@����y[Z^%�'_��� d$����L�����)�Q��8���`�^�sw�+qx��gA ��D�@:؞ǫQ�4��_܏uS�`��IF��}>0!���8�us��F&d;ط>ۛ!��}� �Xir�cߍC�D�-k� �Jy�/ߡ���K<=�5�L��zRL8l���W��C=��~��f���JR�� 6 d�����y�E^�?}_W��W\b X�\`���l0b����HO���������tY�sB�U)_:t~���k�ؘ�D5}kq� N�&^���I9_%�F}��Q���2Q �N�p�Y�!f�B�#N��"�a ��F��{�F a��r��5gQ4|H)E`��`�S� ����ѣu�ξn��RP,�����_c�J(֭b�, u2�z��og�t�`� r��Ke�}BBg �~O�d��S�đ��`��ka� �tTL���td���g:G�9��j�۹6/�^��]0�N��?` �[9X�MX�-SCw2՞�.����f�T�9��ݮ�0���-�v0�� ��q�����ǩ��ۑ`S�9穣m1`�:����v<���?z����'k�MU��-b z ��$��!,��ܽ�p�T;��C�p��Ej��{m'����9���pV�[1�C&( v@q������^�̳�V=��X#'�Yf��q��x��� @����Mc �Wƒ������ .��E�Sm��/V��W��3Ry;�~wT� Z.���DZ��&�l,-Ȃ�I����X�*����� ������^p���wܠRV����O��m�A槂�ԤqZ��w(�S}uX�pܖC�cX�������SÅ P�ɏ���Z�&���c��0�t���̽�@������m�_�&+f�28����9(� &��W�I �L������M��Y|�T��R�N ��w���'s���T���57�MOQD�\$_�NFVx���q�*����F c&)��i�Hɷ'�ʘF�G�a۳�lu)�i*BS�+آ�K���;w��p��F�¯k���t�؀�\O��Ɣ�����N詉B����Ӛl�f�c˒�V�����m`83\0��̕��ʩ�'&�{���UO�����6�|�kOC)B�a�!���GY+U�c$����ffń$�<�.n�נI`7%���15 �>�v�� endstream endobj 1182 0 obj << /Length 3596 /Filter /FlateDecode >> stream xڝZ[�۶~��ؙ>�J-� ���Mǝf�i6㇦X ZѦH /v6�����R�6���ܿs u�O��]�uX���<����{��ƿ��Jɼ=L�/f~w��/�'ɝ��"*���q�����?�ۓ� ���ցRov{c����/]]�Ƶc�c�p���ml��DZ)��vq<��*5q�z�������t�$�_x~����<�S&�&���47�҆ P*�w�$���m��*�������%Aߎ]��K�L-���lgK��\S��R��ּ�"T����vo���s5����O��[q�׸� ��|��Om�����[��2H[vM����� ؝v}�Ǽu�$ �����K��l1�����V$G3�|���O���ea�Z��*���T���jb kg 6b���!��?�c}����/c�;��{:ge�m��>�$��h�l8�Jv���5h�,8�p�Ϣ"xV#%��������qQc3S���(�(�xƒ�� P�QT=�V��uՀD��k�ܚ���N���gYm�eB���w�PՑ;���٤�k��@��X��dC$��� ���"�O��=��Gm�����pβ����alb�jMUo�c�B�����~��UY ��iCx���upM_=���i�v`.�m�S�/�JT��ګ�"L��O2�n������X�G��O˼���D<� c=TgPB:7���B�8H8Ӗ��,ԅ��w��|�U:�s��!�k�+��u(6i�� Q���{T6TϙL8]C�σ=W����hm��|=�OK[׫���ߤ��BMBǍ�a�%��'М�G��d�h�n ��J��л��ꂶ6c����}��[������Jz9��Hc��D$6&"�m�����V�DW�&�����{�,�?qo����-Ψ8 �l� ���9v.�2ڪ11(v�5�&��w�'жqVKEf������ܛ�������"��-�$���y����ҟ U"�%ݢ4K����K�����K* q0RӶ��l����I�4[i4Y�v���QpSX �n1�>��׹a�y�8�`lc�<��m������8�) �<+�����6Y�d�,�}�Bu���0a��WQB'W���m�����~ɽ�'�5��C/�DI$1��v�;�NM1A|��c��I���5^"����2Z����J�X����~pD%�9�-����{� � � Ϡ7p �z b�#�ogTDZ�uy�/���� ��2v}�ݞ�޶���U��\ay���٦��0Em��\+'G��A���:_jwK��5��s��8t���A�g29��B��؁pW�L��c_����B�F�����YK �ͷt��T/������0�!��=��m���K�e���뀵a��N����욳��9AD8���F���$�H�e�ŷr�ܞ�_�M�Q^:�k�>��sƙZ� ��t> ���<�+�Ǧ��m��ޮ���7�m3�M�j�b�p�����I�aN�~U05�-�� @��~p��N4�9��fK����|�b&�B���,V\��b ��‚�K6�n��X�}���Ī�/U!5a4C��c�y���MC����E?������H:YNڱ����ϱ�Q�*���I΢ey>���в2�L����2~Ԡ~(���^z�Ճ�<}E���]�U`���g@o�0Nr5�u?�ÝP��S�s/c/_�¿F�XNf�k��q?"�n{B�2�o��B��xδ�|hrr�Wj�6D�!��*� 1.�+�-�.�~"�7�K���;�E�:�Ξ".^f�-�o�<:�ۉ�e�㋿�`��au�ƫ;(�?K�757��� �c�,a�k�g�:U���d���+I� ��I^vs �hlAy*�P$ �xY�LM���f6��%[j�~��Y~dV� ������و|�v~��8��� ���%^+yKb%��65��xUL��>��Nnѽ<1��|z@pW�B�(L� 1����"�G�� pN�?�EZG*}- �G���pO�z�i� h~�x�g�)�bH� � �E�$���$�Ň/ �����8�e��[aTĊ�É!�Oa��gu�'���UnGYc��DH�v��Q0��Ar��a�U�HNN���.�s���tI��چ���Z��Gl�ѥ���D#ۋ5�eoU�!� ��ݦ?�Dd���͋ L͊U:!���^3�U���� �-@Z����8nl�C���W���-����&��Ѵ%���HFi�B�s2u���5$ ��!�/ꖲ=�(|���]�Z��XV���G��Y�llkt!O��|ؚ꺙�eJ����wf�����$�x|"̯:��S�"�V5Sg1a�����OF�� ��A�?6����b��퇭�Yڞ�>&�%4X����<�j�K��2#� l��q�z������~w��*�73�W��<_��,I\�n* �������A�� oO��S�x�(�����Xa]3�\�>8��Ŗ�1 _�9���6����4�9T�q�!h7�é��y��D����S8m�G?[_nCL�,��9��$����u�Y�> stream xڥَ���}�b��,g��^����q�#l?pDJ"�"�ڱ�>u5 �=���������B���,�J� 2�^moB�v�+n���%�|���f~{����(�Ra������η�-�~����ǡ�}c���͵om��X�����lO=��EQ U��5���f��j�֩w��Ulu�����ۿ����V��+�Ǚ/_ Nm��� �͵���;5զ�f�%Bbo�h��.��{�r��l�f��2�G�Ǯ=ҎeW��S뽇��&<�,^,���ah���t7�2��~ �)����xp��vpPl0��\�HK���L�"��vUM?�͆���9��,P������wE�we^�y���� ld��N��J�8��(0a�c��N��q����T���D�w���-�6Ȭ_n?�)7�^��e�l�f�(���X�6�7���D�v�c�Q���%,�*�� g8��U�W~ApƷ���aߞ��0;�Ǻ�T2ԋ�l��v��Z�HE_��I�0��tlmґ�y_�qH'��F�Auك��Q�}j��,���=����X�>�Cga���Ad�0G*E��Ʀm�ݩ�a8&�j�"̨ܒ��d��m� I�{��6?��ڍm�j�� lPaf��m.�G�T���0���7Jq��4갉aI~�Kl���E��v��� ��)C����Ln���x�aO�!��4p�H����nQ�����❺-M��Ey�H_�Q��|s^ ����>g� Ä��1/��ww-b1(�.6Ѭ�0v|��&kc2���fIE�z{0l�Չ�VN9v� �bg�'�i��1VkZ�;�0z*у�h)���~ � 92�KU82<8,X[�"��B`�,���B<{M9��G�&!"l��o��P�X�U��y��l�^^ةC��I�HK�;�jܪ@��ܐ�1`���!dH��r D��V�4��$%����-0r��&/3��#�g���K+�ᔝ�_�#���I��n�0{e��Bg��>>j���5�T�F���BOI~���Ė��x�L�Q�pt��ȡ�S�N�Rf�F�~��+xl�4wg@�]�`V�io���"' �o�9-ѱ@k`u��ʹK����lzd瓾�?���ښ8HM��ng;�_#h���[P�;g>33�۳���3!Έ�xn�?�(�eS�>�.����%N_��j�Q��İjX�qʒ#�W}S`��ጸ�� ��/�i��-g37� t������VWE���#���Sz�����QϰS?�:If�\�:�~Xe�I���;Gd1� ����C>����_W�t&I��7՘ H@� v��s��I��6 ua.��h�$� h�Kk1� �������]�*5���gBC>�9�k�gL*P���e�F�b/����Q��I�'��PR�� ?lIѤ��P�( ��� t-����B@ IC|!?��`?�fί@+?�P�!��v+��A"������e׃��hAۮ=�Z٫<�L-�V�J5c� ����وڢ�aK_W(\�Z.+k�er��DZ�[���a4��M�s��򟤔*Z ~wp V3'�K��d',_��y}�ɘX&&}�T�\��u�ɉg�VsE��1d�taʥ�8L��6��q�7�_UH�w� {��f�`aG>� G,�����4d�l�n�ɽd���X��K&�p�`s4��R��d�?`o!��S�Vl��I$V��� ^��5`U�=����QkD����#0�6��P5A����pb��� �!�� �+�0,�E�� JF����8��*��� �l�gV=#BTA���1�&��K��o���TW���q���4 �x����a�4��%(3��2���܌f�n/�p�X���SE7�GsV�y��>�nK�?i}�Š���Y-�-���t(t�#3H1` ^�r].@(6p)Q;�-V��桌��!��U� c�'�:�*v���n�)ٜ����|�cu~��oC4����D�@�r�-o:�i# �]���A<����*�4"~Y��uћ�/�cL����Y�م��PȶxH�6؃G:���EV>�?�>iN��ڴ}5�ݙ���+�X�V��C����n�?�Ε٥r^l�9��&�@�rʜ�ue~ ���@x���p 7۟M_)0_n:�U�y� ��<����3�na�+�E�o&�K��᢮ r���q�ձ�Ɗ������PN�5�!"1��S��S�C^ Na9G'i� `O��O�.�5DG����n�]�R�e,�#TZJ G��u�yy r �֛� Ո��9n8�y#M���N���df^[`K)]���8��RJ�$Z�v5�΢ ��W<~d�k������%:Y��N�{_�]9B���q2�-,��]>���)���晸t8�ss������O:���'U�|+- ��lȽ_�/�y�� 0zy�Q��^tSEx�t)�� ��$�KWr�#{,='�"�rM����H��H�������E>`���,���% ��w���mϣM~���eɲ�H�g����,q����{�[J�C��*�zB("�R3 �-?���B���J�0��*<���y+�f���Ѹ�R��=揙s^� ��� �`��.�$[�sa��K{i���' q���d�K�1%�g�1Ei�Fa1K�pB� r}���~$�1���K ����\�����D����[����2v��0��� ��a�7��<>^Pk�*�i����^X5��I ���Ɠ0J�~D�!��ֿOAYi1�2����Ą�K������l�TEq��r)cMK���ª�������o2*�P�O�۱�4�R[ڃ��I�g�wT..���o�r�b[n'�����-� �sa��1@�h��^�ν�񤋒͂�˄?���� ���r��T�|�q.��.�+) �������.�]��3��O@�ka7�v'W��'��]m6��>C�x>6��nZA�4�$O�FgAb��V�+~��A�&`).�.`��f5�����>B�9:��TB��<�zuY���2���A �����Д�z|�^�WY�N_��QA8E�����(�R^}^�R�Pg��Z �9����]R.��L)凔�σ"�=D�D�����)J����~G1o��{JՑf�b��_0��л'3U�FǣLlڲ�<���)�fzY>Y���ԢT�Oՙ��R\h^��d��V(Xn���xߑ.hq.�������N\�hR V���ϣ{��DC<��S�b� endstream endobj 1192 0 obj << /Length 3218 /Filter /FlateDecode >> stream xڥYY���~ׯ8��D�͛z�8q� {�d?�rzf:"���ߧ.^�\YI��N�W�W'�!�?u(�C�A���y�hw9p㧿�RB������ë7?��A�A���p^o�p:������`��DZ��ۣ�$��w�W��uk���>��`]�k�Ƕ��Q�=}�%Q�e��ׇ�����|�4����H�P��CV$��~û�T�^g��k�Iz��nz���1<�8�Z�ϝkxp���ч�T��C�|G�?��i��Cz7v�̜lg��uOr~{B>��|*��>����p�G��$�MA��p,bω`�g��j�w�dk�DE��%��YX�1�?+S�0 u:��[�r��� �wU��nU'�o:s1����7���y��~��Mgn����7�ս�vy�Z/�H0�� �A�Q����=�W0uTޯ�SUP�i�+��h�pZ#�b!� �ye�^��2(Tt��dz{i5,ڻ��"��h��?���@&Q�-��n�XQ��:�R�hO�g4�6�]�c�{执zW�6�I�@J@� �텇��L�Be��#�3A�V�gbS|�_B��x�(��z�V�i=�l?t�q�Ih���H���i���4�+��I�Pw�W�,��eޏ��t�iL'��t�w�7{�We���*l�G�y6�`��yH|}�v?V(��2�k�i��4Y�������#Pf޿� ���jD�ѕ��� �� �E�E<���b|ф<lĞh6(���Z:O �\��)'+#�&:����Ry�(�� .��_���Η�v����*͞�C&DŽ��`��P����w ?��2��3�� WI�o��M�BA��.�l]#8�A5l��E�h��l�#�L���&�ȫƮ3-�o�����賊 ���'��*��z K�T�' #�H~�Q�*�X�85�lp�e\�����q& � $D$'�յFN$�C'scOОz�#t�� +���q���#�7��6�}�r�*�RCQ?�M�33��E�6୒CJAR�P�T"B�� ���a � �4˙�n@1���K�Ez����.9Hl`dD �����y*����@ȢO<���C/�'l-+ҕ�Q���k��T�f{�XF^��Y���y���8D^iz�H6`|�A-TN0Бqx�%/*;�L��-9L\��4��Y�[V��!�� 8�Lo�L��*s�R�G �Kp�p?����cQ����p�B�^<]�{��G1�؆�z� ��+q�]L ��y��?�3��y�p׮��Ly�'�GH��~� П5���H���4*̔0Zh8H��u�ol��z�6�=���)�S�5���1��ً�0��s]�Z��]k�P]z� �(�Z��mmh��in�s0�Ŵ��P#4�����b�B�lśN��d�w""pa�V����q$��<���D<�~�0����p�.���D���d(�bA� t��/����BD��&1��,� Q� �/� ��I�� �<ڏ���h��r��r�=�a�d8VC� q ��XP|8D�Q��o$�kVG��@����ZV��e�����a[lAR��w�*̃0�6��KP� I�����3�JKx��c݋>K�����a� {G吙,��8����g6* ��g{�%›�H�n\�,���o?.2��;��|��B�� E#IT� $��+�V��'� D�)�f��A?���c��E{���{�[Q�Ŭhw@}V�-5���/�P��a�*�A��5��^�f.Q�e�P@� �H�V� X1khh �j׻���4/�Rb��������@��R& ����R,&-���E�l�i��M�ˊ}�ARl����z� R�d�8JΉ q�ѶP���5�5*�B���GﻳMd̬�1��B��n�����ĕH�IA{��`�a�;�]�ٱ��h��T�SZ�#�˹ւ���@���'*��q�Oa�u F���D���`n}���1!� ���V�ؽ��l`4K����+S0��~���H�a��p5 -��#��[����5 b���} ��v.��ʑ�a��Gai��A�~F@K�-zV��4�T=�W��Hyv*q��\���k�e����)�>�I�c��.�a�j8�i��x�Sw�j,���ǤԵ�}�A���KI >Z�6�}�jX��^ʽi�*Q���(k���MTg�]Bd�,�h6��VR���N�}-Mq��U�����I�X�6�#H~�m�3*H�|U/ݳ�1���ۅk��W[�_wX�x�x����8��0RH)�gS�=�_QsP�LՇ�_����o������C꺾��̲���0 ��M} �j� yI%�"%�'Ѣ ة�X����%d6t@�V'�( �$[��ݟ��$� ��7E����`>-�CJ�%%��v�=C��J1 �wFDw�����e}�n�����Q�9�5�l�z^�] endstream endobj 1196 0 obj << /Length 3051 /Filter /FlateDecode >> stream xڭYY���~ׯX���"�f�t�d��(2�,�����!�!'lһ��SW�Q��������ꫯz�M?uS�7��A�7��YH��� ~��3%�|�F�x��o��F�A����^궾��{y*/����Sꇃlj����i۲3�d����fl��l�~�����x�r���4�B/M�������,VER~�_�T�7iJ�|����u፧r�Rst-ԕ{p �=�ќ���.-W�v0e�ĕ�|U��gpN����{۾�M�����j���J����k��9���kF��nj�����T��7ݱ�%jt[d�CӢ���̹l��}��R�:��M��OX�'�JXv�k�E��B��s՚r�-���o��� L���kF<��=T6�{j*��ě_���׃��!%�ۏ I,�W���Of�Ќ�~�I:�Q�VG4�K�#u� 澁�S�� �K�¥-+�4:I��PpJ%��ۛC�=�m0��-��I�j�u&�9��=��|���5[��*��&nnW�E��c��_薟�ޕ��t�����I�hʨI.��(+W ��z#�ΎQg������F� �~/�a�)�H���>q�[�\|�e)#�:xy�u��=��"��� Ж�D BgE���Ǒ<�|!#���zR��K�nD�F<��0r��"�,��v�*cd�b�PW���H�"��N���}-W^��PK"F�D�,sc� c1�52�p a�"48���P�x��,�]�,R��NT�&�Y��V���qׄ���q��~:�4���n��e~�jv�ۑB�"P����ݮEg�� k��R`�/f(�}+ �p^+8�i{�'p ��mE�m+]���B�v�-�4������k�����;4V�8Bh;~C���z���?�䰉W=�?4" ���{�qǯMW���%�i(��D� �ݳ�+�o��$`o�e, ����=~�pΜQ /0�#�D��40�뭴F��I��'�ss?H�I�~��������<|^����fRB�ep�`� y���,Ѱql���S�l�A�,S�u|��"����g����zY �!�2����G�t&٘���lX�f,r�B�;�����Ǒ{�q�(ʅ`���G�;ʷ�j3;�Ѐ�Z���5_c�2s��k.����ҿ�[�FA��i�X~q������Dn�5�~�ۿ�8�c� ��#Jy1g� �_��^� ����f�U��Ki�-����`Z��@��l��<���j�GJyiY dj7D��,� ��D��?<�!�l����.{Q��䙺��y�s�L1r�D�Ǯd�����T2eI���E~���'.�-q�s��s�d1���Q����{3��ؠ���Q �C`���l�r�<�@ 1� /߽ ^�A?�~.cN���Ezv��L���|���?�f�Ҙ�p�����ۋ.#�ˋx��ɦ��ma� ��aR%Ԝ*5�9�5�����Ŏ�\��(:%qp#���WŁ�S�}��1=HR���bd��>��u{G�<�? ���9�㔻�����!b��������=�9��a� ��48�<�) d�����q�e*� ��s�����W�^��p��A���%� �=��{r§��B�w�B��_������9?Rb�?3��Io��9��;�1�:&I�qY��W�c9�������x�l1ڐn��tv�_7pOc?Ȳ��KΏ�~�~��:��r����6:})l����f �W�?��[ι�J�)�-��HE���ӷ��O恓������A|��* 4OG�����{� endstream endobj 1199 0 obj << /Length 3305 /Filter /FlateDecode >> stream xڝZݏ���b���Q$%��6M�m��yH򠵵k%�������� g�好��ba��!��OR�%�'�\r�+%��w�û��vOwT��?�I�C�x��o�����;��8yw��$u���%���x�n+�")?lb�M��ߖu]4e{쩭��j�����c���jؤ6:mb��4��|�������~bˤ��c�7 ��.�ZH�i �k�?�o+#�UF�� ��z�M�c_��{�72*�0L���ێ4�@þdͮ��S�<�t�~(�6N��?����dQی��س [K����DG�IT ���mS��t싇���g ]YC� ��M�Űo�CًMl��~l�P�+y����h��#(Ė|Jbt" �0�&��� l�v�X��&�W��W�]��q[y�H�~1��˞�4j$<Ђ}_����� �wǂ�����Z@��mN穬����#Ū�> �t���C�~m��/�DFE�#^�,b������Y�3��D��Ұ?��������2G#~�î�)���ϟ?��z�LX��QZ��"�j��>�LD��[/v���d���h���O\��<:�с��-r�/wp@Z:`z��W��N���������B�t��9L�� k�5��Yb�3��A�pwm��#\��|*���<?Q8RR$�Ǻ�Q:������C�]i�2�X�Ju�k"u��S�<_�m�5��3$�P"�Ba�ʂ��b��{�`,s)�$]a��`] 1F���i�%��Za���9Qծܶ�Q/�"�9-[C�D�#Bi;�M���HY�� Vd�Dn�(��W0k߄�&���`K�3��y�]Օۡ�N�/#�����Mg*�9�>�\T}P�i%l��S_fq->��㎨��>�X���j�ز{���}����=��512�dL-?>2n�I:n�?y&t�A ��8 J�gZԇy��@�a_ӵ>�:dٴ�e��2�J�J�9�`v �;���̲]��i�39�;;n������%|�s��5�@ҎT��^���!�T�C� ��$�۠#�E��[Hue� ��M���Q���ԼsP�6����<<�#<:B0p�����B�h�雖΍�^*��KE]�lu{a�eΰI����F)JS�.H8�0����ߖ����5�(� �t�G�u8��DV� ׋�3t�K�M�4�����u h�l��w��,��a�I�gz �,�ROG�?Cp�"�Ą}5���E�4�ET�y��T�LZ9�3p*�Y ~&ː��*��=; �(m��n�X\bʎ�`p��'��[K�˾�����X��3��R�_Ԋ��5o��fm��_(i��tO �A :g��^�B�Ƀ��K�h��-5G`�8[Bٓ���4���q7�|�,�XY�Iz�\�8��sD�)r����~�(Dv>��f� ��Ю�Tm��ra���d��Oe�Wm�AS�nIX`��%y�`(��B>�|��C�u���|^ �Ox9 ��{%n P� bY?RyI 5I�P�C @��MF�k0����|�;�� �̗:��))+IENT�b�r�몠Y�4���MՉг{r��ID�>�ل#�OK\z��f�p3j��/y*W�r��>�fV2��� ��m�����RqW��}76l��#�nTg9���Q ��0����#0g�ާ(��x���8p��C ��C_���b�4����k����u�c� �C������ʯ�I8׆�f[�% G4@G����N�W�9%ҭe��%zO�e{�$��I��I~V���{*'��A�; [3)���@�_*=$f� �>���[X��nή��rї\�XR�� r��o�0�AG��YS�� iJ����Д��}>��>EOm�Vf}�ݴ��ˤ�P��,����+�;�.�HH�!���������~q<��t��=�bW��9*W����OF�� �]�� tK�ҳ�µdm<Yb�|ILL�����&����;;{s������qC�FS��K�~Ea��X�ڨ�3BYu�ӷ ��,��%n��W�ȵ�k� �[��P&}�w�%��^�J�V���)=��6�l�2��p�<�,ωU>��~����g�{��Ǒ4*;�oŰ�ݸ�9��ߏd��H@ ʆ�Ф��6\�Z �� 󇗢b��l+���@��ܞ��� _�����}��_,ugBS�cdH�:/���v�u-_�z�������l�����V����H)H�X ��,����f��o�b��7�xQ�xe��"t�!21�^�sf�ܩ@n��>/����d��"��2�|���t��_|�O8�4�u�-�dpą�'��t�� V�a:'���Of����hV�1JN�[�j�qS�ɺ��c�����J鳀�vSsJ�����^Owe�� �.jh2~�}u��'y!���B���}����|u��]���,�3������.�����Mn�FU[�������>Q��Z�xkU���ݱpv��<;@�8xCtc�f��!��ם��ɀ�<���hFŀ_�K���pt��KE��#��P��`��Q��x��'�O��W����$ M��r��S�B�˵P|8sOV (��r�x>)GCY Q }M�nF �Μ *�<���YA�0�?�Y]��w� ]� �pv�8���* �ɜ��%�`�h�Whf_�aB/ח�����s����1GwZ���]{.��a$_|�`W�������o�1$'���l�1��~G��'�DCߋX�� ��6&��錏�L�� H�.���ˎ�B��y*w��S�������a$Za��صS�M��1�cb���L7�������:�uV�x���B'�vB�;'k�1_���ܫ&*a�����^�$z�֯1�&&���ײ����+5�>K<�2'���KS�����j&���K�9����6��e��@y��|�}5��Ɗt~A�>��B�T��������G��4? �A�e>����9�(��J��C˟�"�t��j�'����f���9��;.(л5l��h ����d�J�_���Vu%h�O����Z��8�,\���.�q���QU4��������\4�u endstream endobj 1204 0 obj << /Length 3331 /Filter /FlateDecode >> stream xڝZYo�F~���S2c�������YxË�,��") �r�C���VuU��ul��i�YwU-yß���Tk���<��]owE�����yL���?\���gk�d,�8�W׷�V�����y��}���I�f����x,ں�+����-��};�%}7�^e���H&V�]�����כ�3YV�Wҏ3_`��0�^%�Rb������1A{��)��ɕ�"�V��HgneLk���\���8�oyzN�b�����S�w^K���W��J_$��>����]�Y86�����ׇ����,U���q��a�f�F�T$*����q�0eD��斶55n��^x_�%V��<�}�kE"���mR����J��)?��>�b������ܢYL��} ��q�ʭHs���Խu|�D���x�S�T��DM))b#����S���/N[��a�YIew:m�e[�]��uT�}�G�X��7o�����.K�۴g�mXA�]ȣ��3���a���F��4FUG�X1i` �Lӊ��1��[��k%�s>�E)miJ'O��L #�נ^�^e�U��3���l�q�8h���;'w��d'���]��MY�G��CC,x�P= #υ�F�n����,�6�-�B>��6�9$ds:t3��0ހEYiآVs��EA�k=��M� V��V��%��w�F���t���������KS����^$�c_'�Aa峏�p�C����y�II�9M&.�b�p�&D��;~�3�%�d1]/�7L�X�y��Q�X^�Ns�fݦY��z�b�q�Ϝ���6�g �3�YC�K�' w��U�PV?�& [')%W00L%F�C0;]� �: JC䌣a%8�0�+;���>�)�J ���nKX6�rc����ȗ��C=�k:����>� ��E���X�}����^;'��K�׶�e��"���_���J�-L�8[������Q���N�#�Y��~c>h4�,��mkTy ���v:_Žcۀs�te�ӀI�#��~�'c�b�#����]��p?�8����`1�5���AU������yW�-���%濚��eV$�h��!/AI͸]_����\�����}srƍA��1�%GW�А}���p�H��� A�E�aGZ�J�KZ)�Ua�wm�����M��1'.�ŵ��:*�`�!z�Y�ևy˭&���e䖤���z�R[��uX ~)6������N�T��$�H��b,��B �d�e��\��8�ha�r3G�8�ӵ�=���O��Mv v����j�%zb�Y��.)_=su�x�=Us⧹�Li�5O��v�-Z�g�e{��|��,9H�ց Buj̅\�@.n�K����1P2(����늺貍���s�'_�煃 >²+W��53��ڡ�M�\$�KOt ��l�*��Df��0#֥=�OR�p�Y`�0�,��)_Dѧ�S9;#��q��ɄYt{ߝ�ѿj=� A߉���LsNW1x�#sa�} Bǐ�_��^�����nk�K�������N?��^� �φ�H��3W\@S������_ϛU#�t)�0���x�gWP��`d�/�[��vK��/E�gT��\r� Gw���I'����='���7�N���Z�r����̵ޖF������׈j��JZj��9��`�+@Ou��*��ȉ�LU3:i=���U���Ipx��匵��RIӕf��2��t���38��Άﻆ@WK ����f�MV���,S��>�2�'� ��,z� ��`KœPWSI�?#��/���K�e����2��u�Z�M�4r������.<��� �£��.��r���ј�����E�����ۢN��&cP��Q�y'��E>�.΃�p�}7�裠w��hܑu�# ��6l��OA'!���$��/�ɵ�ף�?��C� E��$$����X�o%|-L_<��DбY�U&��b� ��4�w��)����?d����|Ḷ�g[+��������:��K�8�: endstream endobj 1208 0 obj << /Length 2586 /Filter /FlateDecode >> stream x��ZKo�����!p(@d�M6���:���c���-N��� 9�#���S�U͗9YE���v�Q�zUݐ��៸*�+�$Q��W��M�Vۇ+|���t!�3������RW"���Ww��Qw���?̹��u�$I ���0MU�uՕ�x4�m����nW�US�#��C]Ҽ�e<_�"Ked��Ow~���(����#�'"��,O#�����U�kP�����Y`�J{�q�MM���|�' b5���h�?&�1V�m�Ʃ~|�Γ���_����o`_м��E��y��X�p�p�C4(�$�d��\�vy$r4�#���W_|��t +$��9V?�6��Uw��NU�/E� W=�MkCT� ;08{��2���K3t�������t�P��yh�i��,�R=� ( ��nz���, �S��('-U{��Lӝ�����h8��C ��Y�0� ,�>U� q��%�A&(��h�G�/��#�<��퇿� ���gG���!3?��u�fOϾz"14� ��1$H �hR ��e�ѭ�`T8|gi��mT+O�ϟiig�"�T1� �^L6{:�r��γ[��YeE��� ����v��V*J�� ��#�%�9D�BkrS�'Bԛ�n}L�/�He2��<��M�3�H9����48M���~7��:M�c ��=#������  F(���ֶ5�-���ZZ��vF`�6蚡--�a�e0�B��, N��D�#�r8��9�]%JEBC�H0�&?��g����+�B)�0%����C{��<�&��\�?BO� ���Hi� -Np+��AX>o[^DY�2�%I��g���"}����R�4�Վf.)�G�(N���a4p�s�ia�rb7�����l�3����܋�,g� yx�W� ��"0%�a Rmx~DA�vG� )!�T��o[��?�"%���Y�}o:��,K>HW�4)����N��H5�Z�G|�ޒ��t����d�To�TF�+Շ�G ��dQ3Y<��eSs��n�~�$`�3P0O%����s�G[�����L� �f���JY�qrg�0����ʸkm����Cgq@���X9͑_C��g��`m����x�3o��,�V5k�AQuLټ�6�+BFJf*��%{_J*�H0�P=���^��m%��Bﳎ?]2�c��Y� �v<�LvǏ�-�U=&t��":�J(���ؑNx�3��YPS�h��"�ccT���$�S�UE�(�9LQ�_�44�ԯ�:�y�NJH�9Lcj��;�meC�\DR�S r����gC�+�B �s[�;�)�֧�+��`M��8�,(:�%��4�?Z4���9�K6��Kh�꥗=#�� �@��_�(� W�_6�kq ������2�H�v3J��� �إe���vnͼ=��,����&�����%���$E��(�}J�u��N�y��*J������� oiB�h�(��/o�I���+o��aqsw��rœ�F2j@p�ZH�J �����v�"�w%ߨ�������w���(�Ѫ�/�(�!����|�D���Q�����(-�J��@��-�JD������&4p��s�+h�S�r�>l͊�w�p��$\�9��jjj_&1��G�+�FH5��Π>�����IkO DS ߊ�n�(!J�ԤUsvQx>֛G<�>��R�5�u59��M�V-e�]�IPb��h����$��l�j�YH�u���B ��UC?��q#�E+N��Y45�]�f�N�p���2P��l�M�c����ek��U{���_RG�t�)����0�,"�'{�>ol�/�wV=�̱�\����SuB����+�R�*MFA��K��S!�T0�ߢW��=�P��".q�B\�HL���r���Ɯ���k�:�����83n5�;�V�Q)pJ^�(eV2p3=}��q�05 �w���,V�� ��Tg�!U�f���[S���S�l!���VIT�M�� j`jl���;,/q~ ��T�Q���­�<$��+�l����(w��I��uc��1Z�G�8xG+5����� ߮p��V�Z6-���ˣ��2�5��@f��w����I�'��#�����B�E������ht]���<���_H��+I^� �xze^|��N�ڲ�wyK��/*<�e0�(<�H�Ϙ2\�:[��MCS�?���sy"�}:�ޛ]W�3�3�{K_��J������ /m!��F��k���pt&d��.X$/�B@�o',�p�����ƙ+8sC?��> stream xڍV�n�6}�W�Z �ś.�S ')ZE�})���y�~�$�ɒ>�f�2ZF��5U�B��r�� Y���vΌ�U�k���FcPN[��������F���5�N�{�;�C&��ag���.��X��W�XTe��j��Y����`��"�9�e �CŽ�N�נ�Ж��ͬ�Χ�p���wz��{����cv�p���h_�ш�8{\��T��7��A+D� �*)FH����a�����x���a�Y~��F"��K*��1�{4���)������U����vE�?��d�`��[xtx�xo�7�5Ј����������Z�@.1��)���/हg@�9���P�b5� �͌2�� ]��cwG¿ :,���JeE�ɤ2��.�]���~z��% �����s�������D��/�^�gIB�w04���T,w�v �h�*��Ow��\�4}H��i����;eB���׊Y a;� �÷�*�Z�OGT�TU �J����L'EG�W�s�4L���c��4���uLy,�*�Mx��&>�C�����[��.dD��j1FG�Wz9O��˔����L�� endstream endobj 1223 0 obj << /Length 2764 /Filter /FlateDecode >> stream xڍYK�ܶ��WL�"�K� ���Q�(�e'��t�|�13�9��U��~| ��ڪ�h4�F?�ƈ]b���D� �����,$j{�q��?� ���?����gw��x'� 3�{��B�u\��G/������?ޏ�b)��$rެ�ʝH)�ׄ]�4 ��x9��~���z/d��+��7��@EZ�<8L��ݴ@��O j� ��ٴf�$������?[s�����gB���p��/��R/���!�F^����ޗ�����N�v�6?�e����L�Ħ���\.M�Wew j�?���;�}�߿|�ֵ�CF��ia*ѷ��g�|�z~��P:չ��˻;�I���nl���.����̼+�w����t�3�TZ�;� S��1�����D�6������wk>���U_���^��LB�"��y����- n�o��OL�+[�F��0O;�c�9��.�"WQ�C}8_�bv*�R�� �Q����.�T�<槎ٟ����IK�~�R�@t%��F"9v�f/��CSwMUyO�Fҵm�w���CϔK^�'s15����:���ZBC��Y��7�1tS7!�j�� ��ChR���OG4�����h��-�K� u7p?��{t`����lz�<��5����8q�v{eg�rƇV�bHL9�Ήf�0�:-t�ew��lj�yCgw�� ZfQt�~a>�5U��K^V%.r�oP���OavƬmKB4���� ��1.����7�k-���,��Љ��sH���7�e�q=��o������m�R�j�Z��s�����Bi�:l%._fV� !�ec������MӍ�8k�u<��~ C^�5Gn9[ao���:y�AB �Y �SI��Р�sq�i[p��6dd¹��7S�ͺ��7�Z�淜6��T,�v�"� �' �(ԏ�;����7B�Z��!4����T��e}�*��u��)�cs7)`��(�3%���o���.�SQ�az�Ej��� �w |���y}›'$ Ĝ��Ϙ�Gؚ�'^�)�R�KV:H`W��̖̱r�m�右f��S9:u��U&�h��e�AOBZ �ˆ��79��P��r�"Ġ)�8=�T ��7���?3'LW�t�A�>��vM~$f��C�8쀸��Τ�����9�pG$Vnr����Ԋ��Tܜi��#��^W�����f�'�TCa��Y�(%�`j�*ہ�l����pl��" �~����r�Ƭ�cd�x�'���йI}���@� �Cb>�[�S�Z �[�fo����*I��*I��Б���`���� ;���8�I��C�%/ ���5��L}(ɐ�NJD�B�[�Qi�J��V) �R�F�ڒ�9��G��+�)����.}� a'.&����Y� ��������9q�zae��2B�� ��ư0���.Mk���Jܶ�ՠ�2@��xO6$2-z����u!��6�Y��`>�Hn��B�<��J�c�B��锐Vn�ә�G ��`�1x��Y�]or��'`��D����r��\0�_�S�\�4s5��u0��� b��;t�۠piH��PF=E^ND���@ x�k!�f�q2��X�0%������Q <�@�Kw�m9��#�n =�XDo�[��С� �^)\�Y�f�Z�:T�@���[6mij�Tbē��GkN; �>���^,V��Һ(f�HOV���l`:/�����M[f.w Eq�?��2�i-�Ù*�Q�878�W4���^I��涞�@!�� E ��т����_ %�pί=�e� c��ύui���ȶ+ͬ|*+� ����N�i�ǎ���V��:�V��zU�����b�"ws�&��O�o��@ �.W0�{.�zk�(�5 e�)r�^���$F�%K��ɮY�is��8��L�Z�DZGڑ<~Dn����+��haTB&����0�o�A�8 ��,��Tr:=BY��좀�&"[�Ӛg�����/������걞9��8�i��8�Õ��抨�z�v}ι �Jx���1E���,!-��l� ��1;�C�+Ou�+8<�.G�fwV#�P¦hH��� � ��3>`�μ��� K�ʋ��D���^ �`���í����U�4rZe�b����&+�ۅ;n�V��Jd�#V�J�$Y�~'f�Lm�9�Fh2��:��g�22��G ����0�c�+BDq�O�A��jw�g|��k������B|5����SR��& 5���t�e���3#������*)bKJF��(�1Gc;+ �/�o}5�2n��q(��&ޯ����ӎ<���UP�ӱu�^��<�K����� :ζ/H�L�}�o  ')�N$[fEQXl��i��A��H �ڦ�����tV����ΐ0 =L�G��B(�0qI?B�Xny� �&to�H"T����*�ΰ�3�2�_�i�t���M\ šLݓ��'�L�����3��}��X���f�3�� �On�7F/�f��u2Y��$W��c��INF�t�H��4Sp�ˬBz'�i���M�Wc:�=vl⪯�k4o�y��$̃�cgz�G���� c�;�#�a<�� ����o|G ��v�m endstream endobj 1135 0 obj << /Type /ObjStm /N 100 /First 956 /Length 2010 /Filter /FlateDecode >> stream x��Z�o7~�_���C(��!Yŵ�p@ q�6�E^��ɻ�$�����P�X��j����A�,wH�|3����;e��>ዄ`�|P����(�F�T�� )��(F!��$����M#VY�d8��� �>� ��n�8т9�8a�g���=˗ �&'a'��I~d�S�& .H J�P$rA�,�x�BfE�|!��"X����Q�Lb)�J 0���r9�[&��Z,��W� $I�`�|p"G��A��~���c#bl!~�����(��P�-+����9�e=� ,m.�T�ٍ(�2����F@��|Jh� ��k��"<� IT7�'�� ����2|���<��C'P0b(*�� ,U4�_1�Lj�p J����I� f���9 ۢ&Pd:���[pk.P��D��IJg^�EPbKg0ntad9N�I�K�7^�� *�h< Š��zź���.KL�a c�"´#6 �x��T��0aL\�Y%SdrA%gJ[Tɳ��H��Kߤ��6��xkTʞG�_��M�R�_�� LX��ĸ���l��:�R� ��Y���F�w�fzY��G5~��B�?T_V���d�_�+���T���0}U��J���}�l�j�����j6����>%�L�}�D�z���5�u�`���8$��M[F㟚�U�Xg>ɤS��\���L:ʒ4QK��<������vV���.���������n2����!�_Wu�����/�F�7�c�������F����?b �k��8��^3�}��ŭ��{[3�Skb���f0E��"6�m���%|K�?��[>��F-�h��7� �i�<�����C�`���E3����`�{[-*!~�|s!��j���VK���Ei��\Uw�m9]N��:#� Tk�~g���� �j `>���8}��������BN���ټ�*���^KGR�p�4"��KJK���v,���43D�ωz=�yXLV��1�\�& �q�����F�"yml:(��m5���^̪�j�u�Z�j�e�צ�B��uIg�z.i��g8a<�p%���0�3Z���Q}+eKm@��C{��=��d:Fx*zG]�0�c��:��8��6�%�c� �Ny����crK:�) ���;c:�J���֛����s�ΡGx�����.n��i���+>-�.F��F�c��_Z�e$�heC�Z�2��&�O�8 ��e����.���=�d�9J���8pU��8vA���nr���cG�}��Nh� k<����8�ެ���|��*��<�q��d�=�� �x�B�ɺ�7��X�w�R�'�C ¹��\���J�@�rtч�-� ��h� ;��h�.k�SO��[T(�������i�lǽԞԤ�'��#a��l�c��NUR�;E����~��x|3[�'�5J���~5�-�u]�Ɠ��u�zU��� %���� ����#Kh��d�h���u;U�I�zd`3(-nB�I�O��MV��䮔d��j:��U���W�.�a��Y�� ��&ҩ��s+dw}�!���%,������s�mHν����9 ����w��٠�!x�`4�P�rt�v� *�|��W)���WJ.��*%7c/@�t@)�T<�2~�H�V���=�j[^.;Kb��� A'gxK��\ ��C�������Y��� v�Y�]�6ro�Z�<���`���͙$Y >S!l�ɍ��qU�#�:u�L���(�)���S��S�mo{y/o�օ�{c�BmKj�ܾj}ޝ~��`a5�x��gu��l�|�zT�l�&�y������oB��e��x��P� ���%G���$Q��&�r�)^�v�Q������A��uN�7!�ۄ0U�;�0�}ez3{�yV���nR�E�Y}ݬwBW�o�|�&v��ɟ��[�*����P���\m��S�v��fB�d endstream endobj 1231 0 obj << /Length 2654 /Filter /FlateDecode >> stream xڝْ���]_�R�s��KJq��RI�"�K����(��c���� ��6.� s����=M� ��d�&1&�l�ٝ߄��7<���7J�|�g����]mTda�6��9����'��S~�\���1�2����w�UJy�:��[af����/��x���x]��+�B�o�B �v�6P�2u����יg�Ӹ�kZw��V��u�zh�3�t��F��6��{��v*�j�QF�˫���A�úB�<�y��n�W�Չ�� ���������� T�l �(m;j,�`��� �v<�[�^�������D�x$Wr�bR<%%����`&��C�fЁ�����0iE�0���Ѐ�H���Z�vU�8F��m��wu�{׸�%o:F}X�ww������EGA B�1�Xk�ǭ��zk4�$��5?��un��;9�}0z��@��� ߼4��� )K<��̈�xc�ҷ'�/�Ǩ �1�%|�vX��h��tc�t�FL��w�w}��wkH�,X���D{���(���<{*�J���g��6b/,��ԫ|�A6��|ډ����8�f�Z���*FqČ���=��ve��!b�&��9Eg�ϋ/hPv"�PL�`8�ri��$���b^a��W�P�䏊0L ߤ����\7�=0��/��܂�A��.k�XB�&&"Zƪl Qx� ����x�- ��"��)E`ؠ���#CǕ��t �W��� 9؝��� s ����[��н"`��u�o�(���om���V�rϣ`a�w����a����K\�$YQ���t몝�ꆿ��|�0�iei Ut �O�v�kJa�����s<�������_�v24����m:a��G�':�۸�� Ž�d�ծ����E7Z��z�l���<���u�U�$�හtF\�Kv�@J'�����$��}�ď�IJ��A�=C&(*ɠmqꥢ�e�5Mݬ�FR�~_0��3�XH��`��j��h�"�c�<r���� �Y9���I���y͢M��d�����������1�� �� 䝚�ܟIO`�6���M Z�1�*Z.�ڻ�Y�N@�lτ n���z<1Ig��$q$XB�ȋ�����G�3W�����g����`��!4���q�Y>��TW�Ӣ;(��Lʢl�0���HT��jJ�a5�@I�l��}��;�J���X*I�&� ���0�=������PT{���R�U �C�(�h���c%����.�����P��c^�l�Y��ܖZusE ��a��F"���C2Y-i��N}��؇T��aN�ud5�WDD��ƕ��Y"9�S���9^/��K9����_�gyq��]�F:��#��yK�M0):iܢ'<���u��M��!��o��h��s�FJ�|q�� X���A�-�#�gB&P@ !�Y� �������_�Mˣ�l��g�ńf�͌j���y��g�k}�+��_i��� ����H �H?�SI�Ί'�wA������� 2C~�)�-)�D�S_�7P�v5���+z��C��zJ���'�*h�Wq�ky�����\c2�X�i����Ⱦ����k�Z^�x�cx=�S��@�r��&ۣ������綣 N� �xx !�xt��O����M4��aFT?}~(����[�!k�^'Ah�!��)�r�u�he�� ^�d=��6r��rP������tQ���2p�h� ���-�dY�EWek=����U�Փ��:�DD�ٵ���\ǡG��ɯ}� K�u�]��\D•;���pW��S���h$�@x6��h�ށOK��y��� endstream endobj 1239 0 obj << /Length 2924 /Filter /FlateDecode >> stream xڥYK��6��WL%�P�!�H���덓l%;�x�R)� I�P�BRϿ�~���H�t�h4�F���`p��/����4��L�/�� ������|�">� �?�_|�.�/���,���LE]��;}�M�r�(r����U*vޭ� pެµ��3��4Z}��׋ﮇ��0|澐��%k�����tl'��]Ӷ�MuϽ��*�;���ka����`O9����M֑�25���0uDN����Dy"[wFd�;�s�jV.�mnIz! 3��� L��I� ������+�3j�ׅ��߬��D�r*����2G���9�9.�cJ�ԛcW65wu]��mk4�}^� Ps��6ZV��ԋ"�̛�|��:!�ё���i�Sr#t���ܙ��H�=��_��iZ���m 竷"Q�@��]��v:�4y��(�vpG ��o�Gm����Ѐ���N���~W����L����]�˞��X�`�h@,F���A�Z`>=4�muY�N�`�|0��T�zi�]$��T��?Xnw¾��BO<6����s��xS���(�U�Z�tm�c'�T�"]qs�s�=^��'1Ճ�fI�ӣ���K��"��F*}��۝�/�T(����dʙxI��l�؛vk\ko�K�0G��K���xP���7��G�K"�14�v�'�OC3w�+����n4�j�����; {ĐA�ơ�9�-���q�z�#�� �yN6~@��!� x*�鹳�>�I h��p��;Ǯ�^�H�X�d���P�y)�# O������WKfk���j�w?� �<���<6�WӋ���3��ꧫ�|��'���ׯ޿��������}�����_ a�`�zC?�‰� JHÉ�s�І�ܵ%��G����K��b�a��K{ 2o4����FY�%Yz���Q&ѿ>������=4:��� ����i �1D�B�F&�B)B/�;R!�C����Y�"�"�S8� �5�i ��P��ٖ���1�y�m_��J��R��m9Esly8�������plc9����R��O���p�-�0�#>�����PN�ĂP������Gr��N���T(-��=�|�u�)������O�şd�i��][�'v}*t�o߭� �aX�ɂT$��� �C�)��й“��M8UN�꺫4�n�i|���f�o@JjU�� ��1�?��`B9b?6��>lQ^��v� ��&�[ē(�ऑ�f����u{o3a�zo��5�X�O��u���x�oj�*�� yq�6U�s '�6�l�DWn�!��-�3��Y�D�F�( z�3�v<2V"8� �<˻�l7DЃ�a8�� ���)+릀���)�L����Z �/82�S��%�i=K��(]o v�0t\��DM,{ BB�@-gO�`�C�$u;�q� ��.J }ӖFDP�������}�p��HA��y�t��(^�%@�]��, `}��PiaBV�nR�ល�%����;%<= ��X�1��=�M�����!�����o�H���R��<,7�n{&<��4�K ��L���9���e�ʄV��b�̠ g� ���{�.�=��J���R2��$,C ז��r|щ�4��Pb�s�� $G3���l��L�����q���=ȣ4����ua�<�^G_�D���G�f<%B1/Z��Q%��z"cY��l�%���`��]�vM莇�ԕ ����`��u�E� �" ��^>�����G� �u����)?�mX�$�w�l�)��>%)h�=*�=�A���Rt&:�ti�/�����Q ��n�g��r?q�S��d&��g�I̙��(��_̶���{oύ�4e�����J SlQ���<����Θ�R&����|>c̟��P\Z�P1Fd�g�e��N���6�/PWV蹠�&Vo(��Ac�}9b0�%XPhF/���=6���d6* -+�8���+S[!sγ�| !l��c��Ma*����xg㋸�R!tC�0`�+3lZ7Dz�'ЇQ�zǼ)XDa��TH��ݲr(�� xq���CS�L��<������+�\7=�N��d���J�o#�^׀%����Q�ž��75��4�#�䨁[z��N�{���c�͑��SO�*���(��;�h�� "BV8.c#�%�2?Zá�r�o W%�$~�4�d��R&q�E�.�ǀ��������Ď�1xf��N�`�:)O��A.���R�8��G.�W|S�S��5@�Ϣl���=�8���/��}���[��!e���<��R�Y\a���m$�<��'&ĔM i��^�7��H�'�� �� ��1" �Ɍ�8 �Z�cpnʂI�����6��h�{��ᤛĴ�;��^�F��'��Cg�?�H���p�Eal�"�,R �c f� ����� b},�� 6��VSSx�� !���.1���������c���{z��mdb!�1�++׌�QۖEad�(��1�.@�߰�܉��ݍ����c�&~C_���������D��ohvD�����׉}��vG�l����ܣ��Y,؈Đ�Z��'I�Mkl�3t�`!5?�!i ��L|�܎��90�Lk�6h��mhph���� ����enj7��JR��!RJ/��s�*�T���z|:y�� 8^��9�3��w�����������{@`���K���(lj! �eENۄ0r�X-��X s5SϪ��o��9dϔ���i�06қfc �E绎I����-�Y�d���= X��x�-)~l��N+q���j�4�B?zn�6r?R� �y���������!�$�u�:��T���Z���z"r,�p��P?�� endstream endobj 1244 0 obj << /Length 3005 /Filter /FlateDecode >> stream xڭɒܶ����raW��u�l�唝EG�8)qH�%6��2���� ${Ėe�JU������� ���ʃ�4 �<ʮ�㳀����|�L ��+̗7���:��T��A��n�n���x���i4�n�����}���R�{�ә�/X �(��h�ߛ�={u3_k��t!�'�e�J�~� aI�*��0X �d���� @��I2?�(��{����8�<�]�c���($%k�4�-�L�/ACux�u���4m��ړx��{~�:@T[,�$��,s�1ɩ���j晟��@*V�V�]��0��5�R��@��6E�<����[��0�(w���d�4oP��N�ý�:/�$��0�x�(�q$�>3�U�� սiDzQ�։�GR��M���(EH�p�,d/X����r>�Bp��$��!� ,����-vC�8��O��z��Xp*�c���u��"jҡ�6�B�f���~�څ��wf��2���M��{��D�y����i���;�a���Ʌ�L�a�'tXP#ėG��ӝ���؅ʻ�?An�&���/��>��s1E"� �e�t��x����ޱ��0Lf8SD��<�y��L���"�=���lRD L�@1�$:����=݌�O�y�m ��c7��n޼�$��Wo޾BP���D�v�������ӏ��Ѥ3��q?�kF��������Ŀd��Yx@2�9L4�tzv��!�8Q�:[�)�� [�b�M�C�4��z*�і8�XᣭL[Z#�< ����n�kʮ�M9�kʙ�Sߝ�;�?( �Q��0����%����N#Zgb��7Hp��d�ՠ��E���9�������X�JH�3�#\�!s"�m��i[.�N}Zy�����g��5��C�WU��҆7̮V��l ���w�eT5 �4[<Ŗ|T�?�0>�\*�`!�ߠF0߁�;*OTȚ���6�� �M��)�9��iP���; ���9Q�%ND؟^ 4w�>�(������ŕ��*�-.����j�b�;0�]��B�FA/�| 1E�D��t �X��E�L yC#���� ��NS��p�ԌN��99��{ ��&��9b�ܲix6L'�$rS����AKB��_�Y�ތx���+s�D���{`,0�F��k����ɞvddz��:�9�x���Q;9hf'�5��(����oX̽��/v�?93���qG�G!&��{�-RԝfG�^�j����ŦzH b �Y�M��;��jڋU~�Gq����юs9y���%I<��;6}�����m���1���)�ka����3Q�|�g�i~�K�( đ]�t����U<���(m#@�'sr@�=�A�AaiAkr � �S�u[`��+su���?D�]#n�o�;�V\ ҥM'`b&�M��Y!Aj�}��:����Y�* �\�0�f����� �k�+�m��r�7��[� ���&�15��6Lv4Q�Hi���:`�K��6<�z��fs���+���!H)Tc�j��2��i�C��_���I 7�/43s� ��l?�d &������0��%)�% s!7Ry�@��HN�[4c̾�E�\m��q��?{�Y��z�ȸ�7��Q���B��>�E�_�Vޮ 5�4���L&MAI�@� ���qtI���/���q t����3���e�Tw͓V�5}����>�����@Z�#4W��m��x����Rm���F�s7��%��@�������n��Z|BϬ@�Æ��l�؍D��ͅ��'�6?ۼ@��T#m�\�X�#�冪��?����˹5M�� �M'�¹����q��#�{Q0W|�0�̇8d�ٻ&��7��8}eg0�߁����`V�v��_��$pd[�kN}8~�MEqK�m��J���*p�:%�9�(���9�������5����z;_�RFr�Y�3n�A��;���-�j�������qΕ,N��$`�`���0>v.� �]?��� ���xrq�қt|�C M��K�s�ҫ�O: T�m��0խ��6jI�X��q�gw��G�~*l+�!q� )�SO��w�\����������Ř>��,����y���ǨȽ��Q����7�hyg�`���ZK_yp�٫`>�,5��0�B ��]"H�}\�/�� ;�����5��>3�R&��G�F�FG�gr�z̘Y�?�;��9��?�c�m����O�W~}���g��3?���I��;�߬���s�~�SP��$� �8�-bEV9���,��J珥f0�G��(���k~}�Օ�k|�ڈ#����A���y�J�\]`za_��~��W���r8X��{�~ff�&�����1c��F�a�I��Ů*��4�Ͼ����`� ~�cO"��EK�O��S�E?�0'�<�ԁ �f7���.Z�%����`c2?����F �����SA�.�h��^3��N��(���M�t!E9ex��I+^p�5^J㻛��ځd�;�ڽ���T�w ���b�B��o%�r�@�,=�n� z����b�/�[Ha6������u�����o�i ���@���1����2�Ty?Zl�� ��<��)':�o��C endstream endobj 1249 0 obj << /Length 3157 /Filter /FlateDecode >> stream xڝYK�����Wlه�� /���Q�*N��r�lf�!�h �����k@���*��y��t�`r�/���"M�J�7�㋘������ۋD�01\̼���m��$qT�Urs�[nu_��|w0���0M� I_oB����&I���F���a(���l���?^��~>.S� �™�3��:JR͌��h=r�dy`��t{��,{��� ��3��2��d�n��2<�㩥;�9���6a~g�����!3rkk�?�1�x��k<�� �4J2�]N�������w���Yp4��b��?���eZ�cz3�n6I�K��0 �S;BW�y<4ۍ*�����q�O]m�3<\7� �s�����/��;����@��qiQ�5�;�@2�a�n�65�f�Q�Y�wS���n7"�"��O "�]?X9r� Z�Om���G��y�z��� ��(�A׏L�� �xJ�͙�z���������L�'�XW�w���0��V����,��ڛ�߿��Κq���2� �p�,* ��O���_-� �xʃ�1���-��L����Z͖��*�r~���FX�q����g���~8�x��cd�<4�,��P��t�"�`�6����mh%�K��z��*��U‚<�iS�@p�i~8a x]Ѯ�4��J��@�R���;�56�`�n��� �q�a�s_ H� ��i[�ֽ�< ��.�d�(�hۿG�qp��k�э�姸�6�f$Dpl��Y�{��":�����2�=���}A럸�f��َ�d�ev�d�|BA���1�A��Γ�^�C�7J�:1�������� �j>�f���hmGO��m�n��:18\��� F��B�*��n� �ZdȀe����i�Z���+�m�(OS���E�Dž_W�0��O =ޝ} tA���MTqn�6��bK ́s����o<� � :�"_���p-�� ���T����؀��(�a�0,�@���h)���s���&Y�g���Z�<�U�6;���DwhN�2�NP�!^�� ����+ M;s�S/��A�E��8�q�V�(��njg����g��5"����r��(b���x ����e���7$,��}�B"8�B"H�0SA���+%��$~��KB�z�^����qF�:�1FC�#��^�-'��v: � Kd@�k���6�4��|/E��r��$6ť"��l�� ��h�C-�8�w�x7r)�3"����G��{���ĿP?�q�"+w.2�1�y�k$a($4+� Z�\��W��������i>W��ʊ �$���#c(���x9eV��RP�������xL��p�Ca���m?}ף���qG�u���.c2Iŋ�J�5%*ʁ��Ao��DJ#_�! ��Ap�j�3O�h^:Mļp�h$�Rd��ih��a �o�^B!�` :��W ��XP�Z���(�}��_�,昁�����ɭ@��QJ=�'����?��w���h�)�̃d�@��� ��tP4��O_�k ������yo�u�B�`���I���J=S����������W5`.I���/I��>4�B� ����x�!�x�8ߏ-��-�zմ���T�D���[�Fb��ͯ�'N5���ZNI��X���$�u���p1}ENכc�VH���}O֓�]�������uT�Z4Z3p�U��}��3bYY���ВG9G��艹�J� �ӱ9���D��B[?��{�u)I��ZгaVIM�&��~�2�ve�Ȯ F�@�>���$��1ΉVw;��^\BϗW����ej�(���2 �O���;yYwZWy��P�y�iS�P�u$��ڗx���hyA�a� �0eh����p�������2��٧N1\E�@DoB����-�% �dæ <7M��e=�'0�����at�L��z��i�s��l _P$�=�� ���T��`W��Sۋ���]��^S�4*���d�q�a�5�FZe���t�=b~v���bכ^�=pR1 ���J�o)����?H���\�����7��֧��3��;+�H�x ��yΝ��p1}͝]m*0 [w��?�c�ty0��s^=�U�ܽ���>W�T�8�BE�J�QF���?r����&�|�m�Y�}��'ʐ ���Uɢ��*#hQV��wݍ�ʺu;3#e�H`����%���6Ny ���%p<� �\w���`o��ۭ°OF!r(B���RB:�#W�p����ƣ���'��,.����CQi癋d��Y[+}���S���?�^�V&�E���+PS�ą�����k�Gi���L�9]�z���s ֋���%>{ά?\O�m��a���M��Nw���pB��)&�Pye�Ux�P�4���.�� |5�;�V���W�\Ʃ�C���lN�q7�L9�V���^�����N;���%�vUW��俕�gq����ߞV�5��1�s�_��.;�Y)��N.�����s���^*0�ra8������n��l�g|� ��`���>^R^��#�s3���H����70?��1��Պ\U��J�m�*� p��sU�,=?v �$���F� �RИ�UU�7�g��q�c2�1�[���k����8�Z���n%e�n�>���̻�%��A$S���6�H�w�~!�|����ª2���2��G�b�W�?`f�Yu�,f>���h(@�ô���tu�?ɨo�}����d�ĝ�����Y��N�؊,/1���.��| ZK)D��.�@8k�͸ef��y�,��\����ٿyQ뮁��֯�=_�|��e�|C��Ɣ�M3�7�_�5��j|��s4J�BS&W� �?�*+��r]FŒ���`��X�,� h�B���x���B4T̗t0kk����� �N���U.��m�����,�� endstream endobj 1255 0 obj << /Length 3097 /Filter /FlateDecode >> stream xڭێ��}�b�}X�����)i�E��I�A��E��ʒCJ3;���e٣�� C��!yxx�Lnb�%7u|S*�Yu�=�� j�7����_$�b�����ş���MGu\'7w��Rw��O�_�i�v*��D�ބY�o6I�_l�*�7 �u�e����/�������3�B�OF�MQeQ�2�m�LNo´H��?�3�R5b? Nʹ�&L�i�m*�'���*.�Ri�@��s�ǣ9jf���^�ތ���o:t�d�:�zo�h�%��,}q�4��*+�ڰ?ӭ���ĩ7�*��N��0QQ����Bnj�-�?X���� =��pM��{�ɍ���������,�;8�,��Z� �C����s<0%2��[lח�m!��Ґi錱.~��I�k�8��}����e"���ջf�F�^� �C�s�d��6�����[n�1〷�����֧5��:���…�\�J�R��״2�VYp?�Ђp}���IGU:����X����QG�ȯw2��^(,��;4]L-Y�w��(M�y��u*؋4� ����,�3�B�2�3� A9%�OKPXw)��x��Q������JJ�q�@3��Ɍ�Kk#�AF�u#��A�r��ɺ����������tD�Gu��REEZ{�|��I�6�:�TTfg�ٳ��Ty)Tw�h`�N|8���b��'$W Gu�P� h+�Gds���`��0&�ȖD�I@w�TQZW�0&�ډWN�--?��en;�*a9'k�O�N?�]�;��n:�1; �d�����C�^�f<��Q� ��ӫv��\̭�.����lD�J�k������r)ӎͻ "�ځW4 R�)������k��NÖ4{S�����W���fe�m�P�è(8�jdV���A8��x��.F^Y�����P��;t-�G�2;�?��r vFk��`��k�%^?CH�sp_�Q?�C�#3F n�e(�g���y/���5��� �y@D�d�qb��� ^�� �b² ��~�&�qg��f¢(�/�@,��o���[i�&���4kΰU��w���v�v��a�t�PAq�U@P�_��(cEʘ��Y��L�PF���l�ĭ��d;N ^F�ĀGE����ac�<��r1K���� &�OF-% �m�9��G��P��wDP��M����ǃ�q�z������h~��1�a����U@�T��Mt<7=�ġ;Gh�ƽ��L��l����~Խ(8twv8r��^�kt��̛�C?��G;4�W� ��5�Ul��&2�HF�gJ��I<g+���#� U�?��(:ߟ��W,|D؅��͐Tʄ� �Q��Y;@�b�K/���Cq�$E�%�N,� :�i ���A1��K��3�ǧ���A�)�S�����>�/s��%����ݺ��X�p��j7 >#�3���Vo��.r+���NO��$��\�%H���[�L���f�5��<�Ǽ��g ��T�P )�^����?"0�L��x�p\7{mQX<2 ��� \�1 ��{{y��I^�"�dmԍtf��Σ�U-+V��-܃sk��Zz���� e�(g�U��ef�i3ƭe��^ ;�p$o.��+FZ`:g���Z?����Y�]j[��}&��r��d���w�>����o]�7@W +���UT�0T��HO9��#*�E"KK��U�K� �鴷M+*1���nl��#���%���ҔL��C1��f1�v�9���!d���8U�Y2`)�(����>�U���Gn��G�դ�X���Y���!�e_��2���*�'�����Yb��r��$e-����,L����� �}� �!��l#�l#���5#�>Jς�p���/Ѕ$��qg8Gqhrl����~�F�� ��4݊�vz�0�� ���� �eozF" ߹2Ƙ��`Sb{�&EoК�w���IT-%:T9� M(0A���V;�� f�&`�7B��) ]n3�';I~�� �y�E��h�����G�[o��Jĝ�B �D`����� d�%�( �o��b �� ��4�F�j&��@ڷ�WO� ��X��Ͼ�B3J�%KDh�w't�֍��z��O�7W� OBnl/s��ǓBΚm'���/$��9so:3.F!�M��>��+р��E^�� y��r���"!�Y)��"�_3�;��Ď!�w��P�"�H�rn�����i�دO٭�C@��I�0XЙz��4�)���O�����h�3_9U_8���VC���\g�~~���3?��޲���Ǩ�|Ɓ�m��{y�ja5i/=r�����6��� �f+-���S�^�0Q�Q�۰ JU ��a qHK�D��p8�p4.a��H�<6�T�-'�ښ�@�y�s[I��f����Z*/�.o�ީ* �c-�M����E�w��.��l����FS�n_J� $E�ˏ��B W�"Sq�a�,OI��n�V� U�A�}57�VwT�1Ϲ+�� �������3�%2�]�b@�] �A.tK�?e�p�Q���� ��3B�z*���k:v!��𦗒�{�>��R*O<��t��0��bm1������~�q\,�<�ʋ�C0�5�y��/ �j�gQ��E �U�Qy.�sd��Z�)> stream xڭk�۶���~0/c����tR7N�i�&�L2��N�N�)Q!Ȼ��w_�(�m�f���.��U jU��R�6�j���l�b��/�)��1�a�����7y�RiR��Z�n�[�nV?F�w�8��&�ZGJ����ɣ77J��󛬊����6&*˛�o���ۉ\�e�!_�����\0V�b�**�(m���RED���������߹�M��etB��E4�{�q���=CC�2�xԵ,��pk��Mw��n�럿�������� �<��kO)LQH �G�7�|��f-�����Һ���2�;���f��K ���7�(ޗH��e�l“Ԑ��Z�&}��];�d��T���Z��%�!��/x� �O��6(�5���� E�X Yu�rH]t�̐Z�-7-�-���I����x���،B9�v-�R��F�& �J;w]�ɨ�ڶ*>T�x��P�_oJ' �ĹN ����{�\P���"[>+�\Z���8�s�+?�#:�{ c���Y���6+�u�>t����}����\�GT\z�\%9�z�9�i�~��y�G�X��~B�����*�����s�U��N(a��a��i�����НAM8W�s�J3����5"p��ȨO<���%fi�PS�����4:I�r�;�V�+U:*��%��w�_ ;�w��p�Pb�HW��E���/ �V�p�r�5B`�\À�3�6\N5!L� _��t�|Lj����vܗ�H/� �KV~¾��&���JW�<6�)���ipqk�,Y��UR];?(��HL�?gt[p�Te����$��>�}�?��1Ctdzge�� �z�rs��-rq~��f��!��m���4�f;~B���Ωiv���g �cۜo��I���1i�eF�I�7��r7sO���+�'��ZGh�aCY�'�t���H��l���a`!3��"3P������"���O>>K�.��A=��E����|�Ū��%��X���K����\��]�֋zL��TO�9Y_V�7�0�0��~�ۆc� �5z��@_�2Q�T}9� Xb5%L%����?��U>5p�P$LP��R�o�"9 �@�겮�'�&Er���s9���:^�� 4��t�5p؝?������7�ʽ܏Z���ri�S�p�<���_���������d��#�kτ����{m0\����W�� Y��X��:K�bJ-�6�|�f��R �w���[Jw�����XXqw 9�/S�\�O����"?���60�It]� k�R5�]�}� g��O�u�TE��������lU%uy4�|0�X'UZO�7�C�� ���D�oM ��! �� �k���� ��}��ч��� 7��}c�5i5c.+�$O�齔���է��9?������q@mZQ1 n�P�:���P�����8�D�ˉ�46w����x>�d��Ҟ���U3#�oef^�L�> ��o�MѪ endstream endobj 1268 0 obj << /Length 2793 /Filter /FlateDecode >> stream xڭ]sܶ�ݿ�&/�͈,�_�CFv�Z�M#e2;ԑ��G^�aW����DY����[,��b��T�~j���4���d���EH�~�b�翽PB��?�|}��/o�x�� s����ouS�>xov�a���E���Wkߘ�{�VJy�k�y���07�K���7��;.���|!�ӌ%� Td���ƪ(�t��óaI2_b� �4]Q��AO�6Q`��v-o��w ��������m�MsϨ0�Z��X�e%�ܢb�XRI$��GCy�W�f��$�S{�q�'c�+k%����璎a�A����a�SO�6[t���Pi1b���T�}�����_gƃ[��ۻ����I�" 4�y�M`��#�³�lKR�u���QI5��~s�~�.�(k[��~���J�f��*]t�,B ��g� "�7#��F!j�_O 7��T�g ������ ����x��*��两!� ~f���J�L;�G\O�<`��5v_�-ɤ����G�~9��<��%S��0�t��2���/ߒ��g� 7u�驵!S����?�LdX"Uf�R�j�����Q�;������5��3mT%�6fS<�m�ڟ�/h�|ӣ���O?� 5���%Q}�D�@/����ɔSb[v�p�_wUkSj��Sw���D.)|�E�h�]"��?�o�G�y���nѢu��� �/��8���pѐ�+������ߖ�������!}�+F ������+ `�?�.mu��8&�F�g��<���qc ��#� o @�~�XO����*G��I�+�kr9K��[H X��L; �~�BX>_���m.dR\��I�1�qH�w���s�z x�a�}f�t�k(�)Z�q��$P�@<�:jY��8H�Y�"�� :̊�n��㌟�a2[0aOwO �A�:h�/& �Ӂ1Mu�h�>}�-��vN�ڠ��\� ��"�7�HefL�\���XYb��� [���S�>���u��K����g��@2=�Z��d�4�� e�� A9%�7�������Z�R� endstream endobj 1275 0 obj << /Length 3083 /Filter /FlateDecode >> stream xڵko���� #_*^UE=��.�W��9(�4��N+m�����΋��������pH�-u���*��L�H���ED��ኁ������<�W�/��ژ+�ET���{��mu�s���<����i�����%� ^_+����q|���H� +���ˋ?��ۙ8~湐� � ��*͓P�����w /���MMpeu��ǃ,���������[�"��>�m[������n<�=�x��8���\���ؗ�p� �������?����vn�N�PfP���6*�U��.�4��q7�e;4�Xw��J�P���i�duU$ad�Jb&�g��M�q�F�I�i�K��ǯ��n=jR�&Ҏ����mqJ� %�^��~d�T5��:Rz@��a�`�: �~�k��rփ�X7 �u�o�J8������qf&Y�+(H�l�N�a����z8m]π��&����=I�#�'���d������9�N��w�S�ȢD'��wu[�O��<0��gpVm� ,5S�s�(x�|�6����e�G�����x��e�������7���!#uD&ǒ���Գ'�+قo������m�#�o��<��.�u�S����i�}jV�K/�a>[�rE7��6|���K�@����]���X,�bT0�3v�N��a��į3p�&�(̣��p�Cޛ�L�(������)�*L]�( u�V�7mem�W09Y�6�&��XV�^�O����i�fJǖ��ID � n�bR?0�#��0�v��t�eV�����Vr�;'�f����C��g/?��i �_#A�ms�0�H�f莲�ͱ�{�G��`랩���[���uS蓄艡c �X�������Z'�(@L�SK�Qzq�r���� �_�\8���=��n\u�l���u&���u~ �.t�@����(�;p{]/L�����/$���H[���Lx@o��Y�%�&�Y���#b2R���� 5 q�5䵄]"��㩱Gy��C�.5.��0����ă��d��i$��d��,� �5Y�� ���Z����M��C���tk�L���p�����g+�ɣ0{��0q���^��~/p����b�l(%��PZ�]^]���W_U:K��Th��j��8�ɯc�K���*����x���2��:�|�4����u.�t'% �'Y� ��Q$�b�h�n� C��R|�-� $~8��������ܘ�7��&��3�� zh�KnD�Y��]Oy.�����{F� ����$�T&�?��jG�7��'"�~�xvL�Ŀ!����R�%��Q����#t�n�B��@~{E�g�ap)� /�����1A�`�ٻ��%���u��쪵.B�N��e�٘�I��_SMZ��N�Zm�A�q���m�"�\�����F�|/�|:��N� �X_>�����i�$�Y{�C-epXgI��+�q�ڍ�wX��B붦�>�����7���9X��i���F[b�Ӝ�ԩ��Vh#���<"�_�����2�:�ۗ�p���c��vC/�p�Š�X�J�b��Œfd�x�b]���Ǚ/�7�3TBwL8o� F��T�jN8}��1�P��}D�`6 5ć��/.������.����d՘u &�G��O؞ M&4H��#W �6W jQAOz�G\)Յ�-CHX�R������l)[p����J�^��^󠟤G�$��I�#N�i�(�,�L�e�~�5fxY02B��b^� î�l�.������?�_�1����Z)�k��3 �EҚ�*5F�۩��}���a������ G��v�����1ؤ�z�)��z����)HcM��RR.8�ﻻF�W���9}�� �;~@{�m�n��}�4��> �S� �?��2 ˜ ����S|�Eh~ ����~�|`�=<;�9����픁�����wC���2V2��Zn8 |��~j<�Dj �7<��u!��ۙd�Rc�`�%$&����_�R��w��z�s�Q�;ȷ�j*��)�w�;�n���i7v����XD��Ϸ�e�l}m� =4K �n�Չ7a����wPJ�<,��-���#�l��gl�s� @x�$�lQ�L>E1���C��6ږߝ1I���w�X��o�����I4���؂K����3�.ZEmW��8�б)�^�y/A:QE��te���P���R�YK �<)�.I �F��QC8�Z���B���y�m`K�c1@ݕ����Ӛ ���js��M�Ͽҡ�B`iv���g%N\�A�\K��'8�����P�����u�9�k}� �� ������.��} Y�&׭��=\�/����x���1��ѫjꂭ�+*��#��f�y�$O���`;�)�@M�p��?J�]�ʖ�'�U�ѫ �BL�Xz�Z�y��գ����0L���#�}�:�jHa�� � endstream endobj 1282 0 obj << /Length 2855 /Filter /FlateDecode >> stream xڝYm�����_!�)�䑻Kry@�i�� �$�?%A�Wk�T���A{gvf)RG�΁q߸;3;�� �U�h���T� Sz�=> �h�_Q���D�·��d��7O�^��* �,̢�f7�jS�~�=�޴k_J�E�z�+{/�Qy/�B{?�T�)��p���_O�����x$]��aZ�"�@�hDRa0�ڏ�� �k?�o�Rx�@Q{ۼ��+�]��O����rs�w�~ #U��:����ZS|���R^ �( )����\J! �@fj�$I���p����k����]e�P�/�65^S�6UU�{�t�C������]� ?��LnQ���T�#�2�)h���s��=o�K��P���#�w���rS��G�|e�H4�2 D�s��(T���C�S���O���Z�]���;���J^~�^o�I���6�*S��$S�E&�4V��� _�o�:o�����}��ݒ�E"^�{�9q����A�La�����&�Ȼ��;l��wp��4"�E�m�Xp��K�8�ow3<~4��m]��5�#)��S�hhAMH��U��:S���)!#|c�b�*��i"`�� %� �i��������#ط�H��t� e��F �j����Z��fS�l\�r�l򂳨]���E��ʫ��wԷr�Z�g���[4�H�`3��&M�����Oy��]T��,��,R6J��@N�:��-�Cdw ��;�� ���Ί�h,��d"Vx�F�r�Q! |A��gXPPi2c=?���Gu��8SS��8�{ʼ�@N�;�|{h:�T�8�9���-fZ�F�~c7�Ѝ]G�aW~��v�""^�d!I�h����Ȁ��*!����o*�� |c�ʆ4�#���k �l��q��A�U�L�ymH�+��L�t��1Й�4� ��u ��ޟ�+#ohy�v�9�Bt��s�<��ݹ�^ t�g����D.b�?��W���w�� (?6�_����snǮ ��%l����|zͲ��yJ������p����2v�w!�ϩ���V*����)U�i �W�Y���8�"oB u��aV*���p4�!���r �)ʢ~� ��%�b�^�t��i�rȍCg�e;qh�����C��e?nv�Ȅ���V��˚��T dRj�h�\�Ỹ;�sni�9{ö- C���z����B�IPgk>�_#�S9w0d xBZ[:Ӗ��ҥ���O1��y��E��J3�n;���\�j��c�\�B�����l��b �x)� �{��˾�+�(�B34�ک1<��b�t�c�Ac����2�T4�,�p"3�,�9̲3�Y�s )��%�؂�����:����6����9α�m�pJ��A����v�5�V����A���M���' T㪦]��2��tk>-o^#�bz.�Æ=軺��H_����omd��^Ww��"��id"�_��xjڞ����7�6?��������?�ؼz���_����EQj8b�Fo7���Cb�z�i���ܧA�?C��;�,����!y�C�FQJ9����C�h� L����������2J��e�:tc���?{�|(i �s< ��*�#��)b:��c� J/H4c����I@�4���7��C%6�h,�w<��t����I�l��^4' �ov��X��I��X��c��<�n��хW4�i�K](H�)�0������]���R.���҃�$�NĜ�I��Ah��*:��(a���C�r_�$S�Ɯ�6�l�,re�Dx� eU�ƒ�S-f��m���w_ ��$�xo��B�]��aOM0SP�cw�}�YP;�K]z�}��'8Tt��e,��=���H�'7� 5���y <� ڹk D�+�[�q&�4NA�����;�T�c�Ҍ�,�Fb��Q���b�IQ�E2�E�54�6����x�.�5��păoF ������.Ќ��' g&�ȸ�D"�괠wjHsV#�����(�u2�0J �`ni !J4���mM (YAҿ/;��U�RUq.�M�i��� X�20X�>P&v����h�rS��o��]�+ �l�d��2q��\��'.9&j3��0A�D{���5���U,\G�0���-�G�+����^ K@��� �!DG_�[�O�/�r�1��L� (&�t�������e��=���B�p� W��h9Y8�۱��v@�;§�i�L�K����-�V�P#�8�E�ƚ �>g Mm�:%�A�+�q�6�Z��^�X�D��bж�FL5���%SHuGg���`�+&{� XK[ p�j� �̣�ܭ0�!8���BX�e����_���д�ig,O�����l �vx� ED���v���9����m�d��U!1�k��0n�@�����h5q��h�O�::���%j�9����H=���d���W���=��_�L�r���jT�ͅx���P�B��dҭ~���Mg`#���.\�rV%�S��H�l`_��������F���w�o�#����Ʈ��]�<����=r6���4��XVlM7T=[������f��ӧ݀E��!�M{Y{�����+�5�&?����3��"K��AJԛڿwB��?�KX endstream endobj 1292 0 obj << /Length 2260 /Filter /FlateDecode >> stream xڥˎ��>_a�edd�z�e�;Ig'H�d��=��AmѶ0�����%ߞ*)K���A�h�L��z��"��� S�Ey��ek�����{Mۦ��[���2}�J�6�f-�`�6?Gqd�>WMJ�d,Gi���� ����D��?�M_� I������bf��jv���6Cݛ_�Dp,vN�8�� W,��{�7�?'j����~*��p�xL�''Apm�!�f̓<��)}�� 'LH�۪)�:q���M{8�MXW�HKaS4�lS���л����ڱ����e�yƩ�ID ���uͬb�CM ���*� ~e`����'q Ͷ���)z�1��^4t��� �����q���}����~�-���U�v����~|o����;��� ڭ�� ��ӭ"�p�a�蕶�q�:O�/ mV�.�#�膑U3��R%� F1�sgO`��o|2�*i�^�{�Ca `�>F@����QY��-�[j��^]Ʉ��]��ĩ�jz}0'�$�����_$,�󓔌���!�1>l�RX/Ǎu��oʔn[ ࠰GGz�+w谖�X8�^�]�wԤ��E_�r.84�|����"(�h�IڲL��� ������)�k�Rq��*y7��� I�p�E�����պ��ǽ�zF�l0�1F9'���=�� u�j���}:M5�a�Q�:8�;;��&�./��c���&�<�U��G�2w��,SN�I��B(q��-��5л0���.W*j�N����Dh��Q� ;>}{S��� ��,���g�k̓�p�� �8|��N7���>�њ֎4�Lz���8�ȓ����PtU;��#����`����֋)y�.8��Ŏ��Z������7�l7_q��2���%�[e˪�M{�*e�JV2�X �7��a�t �d�.͉�r"\?��0g;rӨ�̌��3�*�Uz�'\X�8��Y�v8A_JDgD�9OE�XMFO&�!ȡ�q��õ������a�lLj�G[h��S�E���ύO g2W>�6�m�D �t~�J��"%O��]�~��K��L���# �D͍lͩ��Ҿ�E���q�/���r��{3��{�D��Ss~��]���zFZ's���>^J:~��W�����+%��׾-�P�h}��'�af�L�����<�k���ZΠE\�i�N�'���e�A�n;'�{d�=f�V�73��5��(4�tDd�$�D�p����.S.E.�1鰽aH��h���w課� z��WB-Jz���[a:F�ñ��ͨ�ݢK��L!Y�#0� ��!��d�!���-���s�@���l���R~���#��Z�?�ñ�$��ם;f_Sz�K)h���5C]8Z��j���x+ X�ˆ�C4n�Ƶf֎��� �w#>5*4�W�w@���� -@�>���b@�p�{.fR�)��z��~{g���Nkc���f5��L�G0A�6�4A���ph�=��Ka4Q�zg����$p,�݌��V#�c����V��e|rnzE���o��Q7� �S��24#<��{N�C��j�m�g�%�]��V�d'h���y����WԹ�!��"�Q��՝� endstream endobj 1227 0 obj << /Type /ObjStm /N 100 /First 943 /Length 2338 /Filter /FlateDecode >> stream x��Zmo�6��_�o��!߆/�Ei9���-�e�����-�V��~�=CY�;g�J�= �(qH��2�/�0� m����5�^��7� O'LTxFa�-~���J8ϣ�Eɜ��y�I"&��{�O/RL��V�[6��,���E�QB;�kXLK�{ l�ē����,Xu̾�H�C�gxDx�,�,�K�v;���4Yɴi����708 �`��j�L>TP�(��^��c�k+V��yU�TgŷX�Z�k�0��Y���n5��p�o�i]~���)�A;$]^�+�f%og+Yc� ��O�gn�϶�~+�N֕W{tG誇J�{� ���jt� ���u�¹��/�vs:�ć�@7��=c����񀿈[]|��zf��^�o�������۶]��\�Y�S-U����D�~{$#l�֠�MJ=6X��'�mؓ>���S�;~F-�+H��ѐ"k�����^;XU��n�rV��bU_\�ժ�jG�aHF���"�&��!��|���lя��hv��5����+��!����H��� 0Fg"�՞�拪츼�|M�d_SJ }�̑*���o�V[��϶��YL��ls�����s~4�L�n�g� \hɷn(�d�|��lR��mH�բSQz���z���Ũ��)D�2��p��ȝ~�'`i��1P�'x�O�R%�O�R���/���z��_��~�4���Z'm��GN�B>)Η ��3����vcm�ݬ�0 �x T4]��c��B�jUM+xdqͲZ�l([xs�b�)8]�w�3l�P���^������S���_$Y,*��|\�5�y�8���eW�����E1/�ټ\�h��uS���������_���d��D`9�d����sp���*� $��3�v�}>6VϬ{�@|o�V���j����d_��,#� �"+��9��xk�������v�Ϸ l8�����x�����P7�1�;�YU�f��S��|w�c��IΣ6�p5�� s�( a��S�'t�� G@!W��x-�f&�����a: �O� cL~!a3N&�J?`B ��* Ąd�B����K� rS� endstream endobj 1301 0 obj << /Length 2164 /Filter /FlateDecode >> stream xڵ]�۸�=��p"#J�>��4��Rwmo�>������dI�l���3R����Z���p�g����Mm�$a��7���b�� ��+��B g�������"*���8gu��#xRm��]�$I���](� >�8���]����B� �w���ӫ��u2��R.��,� ���8ݤ�`<$�O����ݱ����`ۅ}�����Dɲ8ۄ�\OS\X��<�.���Owm�-�D�qbBؖ0���+����K)�eL.��ؒ�C�ϸ�g������'��3��I462������gS ��;�q�yq;��免]i��Y8��':Q4m_6��hwh�����~��3ϊVd,hf3cMև��$�!m��=a��f��N.�啥E%̓ Oa�Q ��1+��_`*Ǒ:��!�Kbh�Pۤ�O��;�zM���<�[��5�X�hT��+��m�[H�+�����8q�_$��!�t�k��tr�lnjo9�z�2�c7�vĒ%��c������0�8�Rq+Nx�0��qRA�X �Z���)]i �M-vl�$S��F�J�(��/1��}C�xI�\��(.��&>�'�y�����bpf����(Z��kN<��Z]c��N�����T,�E%FL��xQ�}����q�y�&��e!���X��T�9#¸W JoC/9�P�� �Ԏ9 �5A����~A� ��V��7Y�� 2����g�ZwU_/Ӭ�)���j�ݓY��8g�2=���R�/]S5���s� �D���9�I����>TĶOX2U��Z��E=j��0���� endstream endobj 1305 0 obj << /Length 2352 /Filter /FlateDecode >> stream xڭX[��6~ϯ0���H+�yYdӦIQ������A��11��RR&��=7ʲG٤����C�<�}GjŸڔ�&��L�M}|Ҩ}�0�^(���_p�����ߦ�F�A�js�_nu�l~���Ө�֏��S���O��{�UJy��Q����2I�"��~�������(�J���`�R0����dE�8a�~ Ӱ��SU?Vz ������WC����Qw��;�j��@p���^V�M�[��������� '`R�A(k�b��t��ȋ�vW���O���޴:�ոx���a����/�`)D�q���_��0���2�8r^��{*$i�\,����tf�����o`�o���V���Giㅳ��}��cK:o���'�ԕ��6�8��Vy#���s��m{4���NN���8(`�N�y��<�Z$��Ň�����US;�` ���P�G~���_� o�׼���g��X�^�����쀤~��gd��o�O/->8��x|<��P�3C��m�y`n����8���- K UҺr$�Ns ��a��ʢnN]�L�_$LM�d�y�zR�]��e����B��c]ɑ��0*��%z��&L{���{��i\ڌ�g���"r���R&N-�<��C5� �A�fJ���(+��t� `�ؓ~-k�=���Yo~�1{�o�}$xeM?����5�Daɦ�Ϧ/@�=^<���4�&""�j�XT�h��|%*n�疣+R %���.b [�l�8H����;nk�͚�L�An�����4�9�5*5��&5�U��ƨ�Z� < ��3������lػ*������j� %�I�~?�[���Q�FOӃy�P�85���XZ��a��yI�8��/Sù#�W}��N��#[wc�g2H��mQO�j^�B�ةg�;�EE�����_S�慖|+w^ �G�n�]�㉙�i�a���ߡA��p7AF����-s���$��E���f1�2����I=��^�6" �$���j!���e�]3�(�d.\1��p�� . ���e��_�'{qwTƸS�+�� ʭ�vV˷k��)@��1c��2�|g+��80�j�v�2>8N s�$TdD���j�#VNr�p��aam0�`��rz+Kc!�{r�x�õL��ԁ�����5M��ǝ� M�qE_Pi��̺?i˥F����S�j �[� �G �GH��\��/.�� 7�u�j��k1X١� ���qPe���q�]๥�"�d�8v �v�$�B�}%XT�X��ǫ䑬˒�G"�3K=�X�Fw�c��!\�� �� �Q��m�K/�/05��w���}?#��3���pEv�l%.>�Dh�K�$�`F4V�A�2�4/Y-���?M��Ȋ������4bD�n#� �)�t��G��+�a�0|������_T�8GҔ1Ќ��Y>h�3�;����\�;��O�t�9��L���] �G�RvZ}`'Α,���M;/�o(0������D�i]�yVl�X��2}1��E)�� �>�[�\s���_G OX0�X]��\�`+W�-;ɧ�t'�&K� :��t�)�*_���O]�"0�q�����@�]"��@ƪ�! �@��6�#��@�c�-����Q��� P@ o #s���%�$`���݇��u� �� endstream endobj 1310 0 obj << /Length 2531 /Filter /FlateDecode >> stream xڵYێܸ}�W4�mD����%�u�����!��A#����^Q==��9Ţ(�Gc{�]�P�Y�SUl� �Ol�`�E�_���:� ������?����7����7�d#� ����o����{��P���(��"��yq�l���owa����"��y����?�z�����W�E�OK�`9^&�4�}�,�O����k%D觠���"BҁĽ��P����_�ֲ���L>������ꮵ� F����l�ܲlU{g����v8H&��hWm�zz(ۺ�k�T�͡���#- �'"_$,6��rKCxV;Od~.�X����"ٖ�d�^��דh�|0];�U��'�`mW nOV u<5�h�T�k�#cb�e9�Rw��S卛��x[ug�Ns(����̢Zj�T��qr�u{�K�� mڻ_�č��˞c ��R�,����3v��K�`;-ׄ�s��1��Gv�+���d��+��^�侗�5.ܷ�(�Wo�3#��E5 ��m���)m�^[�iiî��O�m��\�J�>�ܤA�G�����ތ�a/��w��Q�0 ��7o.��_5��[9�1��i�Ǵ��Y�����߆�[g�k�C�i�I ��$���ļ��|7I��Aj#��J#u����X��KlD�����z(o�x�H5�W&����P�=��m;�.oU-y��1s s7��^Uf�߁�NF��|����g=��g��Q���Y��E��9vg��b�0�۝�� L�߶5/� ���bqr�I�G�v{�^�3)���Gf��XM;J�摩�j<^YyF~k���b�M�d���0�u~�$�����I�[�t�<#WۺkGTڻ6��[ �ZOXtp'��6G �<�� ������SS9���6N%�{YuGa͏��:�gz0QK �(9Zc/�: c?����[���s��k�) ?DZ��CGԒ�j큣А��6�Fs.�?C��;dMe&���suȒ+J��D��S⦖���kȝ��3� i�؏N��_�A���Z�'�����(i����y0���gu�K�m�ؒ�@l �TL �������Dy��"O`8W���ӏ�P>���0dY���c�x $R�� �6��F��g~�/�?��\�0ɷ���q�)=P�T� �� ���0�.j8�=�?�:K�Y��_�^��Ӵ��>�c�*� ��0�<�fC�aj�>���( ��RB��33���ԤV�64�w�#/���i�a6�����:D>`���-�֢H�℧YqZ�F���(�#%L/���Ƌ��Q���*W�<�4YN��w�qm/cQ8h;J�e��H�0�5= I��I10�^��np�Q��d��dž�����hԁ-#�L�%ԏ�e���]u�4y�Q@{e�JԢ���W#2 ��� "�˃� y�ni�U�ͦb��k���Ai��㬣���\���z5U[n��<21����=+'��:DN�{�����If���Fo��³�y��?��y�'��d�j!o%O&_� r3�,�D���0;��y�����0��0JL�Dr�=��܏\��iK��xϫ}�ǭ�������wsJ���y�f����a���=�V#����E3Z@������2��j ��blݫy,H?��Mc�*�K�-wS�O�:��_�W{q��~>u�i������xq.HōR���e� ! bӥDp�k��`�]+^��ie� ��`���q�<�5�Q��S�轢Q���U�y�:՜%?>Z*j9��=S�u$��EKT��*�~�:�v�w��5t�0,:��.�^�Z�Kz�I��T���ټ4^45%+{�h[\�`��m�@8���ZXL���_�s{!fz V���V� �^Z��+e�YL�/� �Ef�����9����d I`C�Ђ7›��|A�e�������2L2��lR��.�37�5�)��gx4�r���iw��H�$E�}�@�Q�2?��k����|���V��v�$@�y��U�0���E�������e��d�v��T�0҅�|������7[�����(5���T����șk���8!{�ܐ��Xd�C{�kmt�1�\�����������]c��}�j���>��@\? *_��Z�I��;L~�aX�i�S�������S��QJ��v{��`h�04vOȨM��|�Ul��I�\�$��[�4��f�#W�������]�:��|t�Ԓ���l�c��y�0��E��^�e?���$���A�M�0t����׿Z��/�����LV����f�%C` ��4�y:�� ��z���o4���p:�n����䟓�����|���$�0HL�|�;6�槪��Z�����K���-���5����v:�z=�$�>�MY��!\�0m�~?[d�&�L(�/D��1��9��dX�Њ-�Ss�-�j��b�pR����|��������,]��o�`E1�~$�[�h��К���Z��h���g�������L��� endstream endobj 1314 0 obj << /Length 2346 /Filter /FlateDecode >> stream xڕYKs����Wp}H@����)9+�Ji�^���9 �!��A���!�=��3AQڸ\Ẹ��_?F�.����H����t���\�*w ��흧�l ��(?��]~����:��y����պX���략=�K;� ��vF֧��y���O�_`����J���w���|��� )_�� /p\�L g��&Z0؊�liG�o�g�� |��G��2 @�,�֟�\�t� ��bMA��PzH���#�n�\���r�p� �8���� \Hw�V)5çeX�xw���O�Z�V�'m^Ѡ����0��R4�>q �u j|Wv-�2+K NӚ��g�:����؉���n (�Qs����i�d~by�+� �fL�^��!�^�̿�^�ACۡ�:���Nj<"D��w���b�o,��j=�D�v:1Ȝ�Xq��g��eG�����b�.YU=kAә�׉F�џ��w�� �%򑸗 �w���'������ym��9�@��ܙds��=C-Oq‘oI^!R+g�� ��{N��w4�LDeO���� ��N*��e�lA��1�"��y�p +9��t�g��y/��2 ,�,�R09R ����J���B@}����؞Y�9�~Ȣ�w���" <LJ��]�E��) 2z�F}YsL"4=�yC#�7 ⡲��gNEs�?+, �u!�d�q���|�8Xڨ��i��Ӳ~߰Z/*\f����6f��wR�M�. L� �F-0M��-F�Eq�W�D tYQ "ך湨 r�с�u���I��خ� �sLj$)�P@��U�<�� %�p��A JY��I#�Z)6���c��z�!ֵ@Ǯ��C�LA���L:���jC8��|���3��BllNn�&�:�Y$�ܛ����,`2�&�ÂF[)j���ʂj��D�i��`��A�B"�i�4ߎ�h1�Q�� ��(o�o���qW�=�j�l8�������JC���)���Nx�rz�zN���z�6'ZSʹg��������F��T^�&3L�Y�O;�� a��K�-��I���0�>��] �N��<bV���G t� ީlÒ��^J�2��GFd_|y������_�y��o��Ttm�XB��;ao1��N@l��Qe�������_83�[Y�L�t�U��Z�� GhOd�� ,�/�܈j[�Zk�e���8�My�C�@.�Ha9CP2��\J�1d`�a9�,�#41�����^ u�.Z^\L����-�g8�g��f��t.��ų�Nm��� Z���?�~�PBp�G��C\��Lae&����Ǜ\���@��q�#} A,�~4~���}7�EQ�{��8�%��%Y�����ňs�/�4B��Z ���ˤ���4�����S.� %oN�:�7# ��\�~�������5��jtAwړ�j����� �]�];��KU�~(;��2�'J~4Ps(s��V�#�:c]�ck���Q��*�9�����$<�m�L��%��o�?�џ���bO9���J��h��}Qʓ{_����hɕ ��c�9sQ�{}`U�-�~di�n5ɠ䂎'?��!��Fs�x�`��l�xh[!�.�s��{:f�h��$�mS�%����i��@�l(`uQ�w���r�#z+7W�x+�V-�َ���h+;��lۛ���f3B{Tm⢦���M5{4yI� t��MM�|�2W��Kp�&��++d> stream xڍ�OO�0���=�D ��n���%�ăz`�62�K�L��mi�m��p� }�>������@� �I&@�1Kǯz|��8�A[a|��+fɂs�S$S�A�c��IU���,z/�f�w'Nȕ�N��S�sD0g��Re�!L��[����(�9�/�dP�#����aqùE$���s�²ke�ψظw�v0~G��j��l�F�o�(��PX�����Є6f��씈���I=Q��_�N2��To)f]�j����Qtj��G.5�F���6ʐ��8C8�q� *`�Ӏ�����M�1�1��*"9܍q�!��cW�qw�/���啰"D32*���RL��[��Y�� Ǒ���y��0��Iʡ^_�0Aɳ�h&�%��/;o8Ҡ�� f��6 endstream endobj 1331 0 obj << /Length 3504 /Filter /FlateDecode >> stream xڭZݓ۶�_��K���" ~�O�cg�I2��N;������"Y������~:J��9��=p,��b����%���MoJ!�:�6��EL��a���/�c��|����]�o�8��:�|�Iɬ�GJҨ����^��Q۰������iئU��O۰L���;7��GN�s=�o�u�A����~E�0���C���m��y|���u��؇;���Ƨ8M�y ��D�A�0Q�',�i&� ȖI�C�M�`R��&����K�,E�f�ʨ�Q�Fi��n[e��7K�_ *�|��ѭ��I��o��(-ŦU���3w��;�V����E錧i������;͒��Ֆ�8�� v8LQ3�w�g�3�*i��n�A�v7����yv���Q��e�� *���� �����IZE%�h�P��3����}ű�Gl�s��O "���|�Y�hQ���*�,�M���Gƪ[�f�{����#wޝ4�.�Lwä���6D�宽�N ���R� ��h4�� ��WFvކyY�>|��.. �m5Z�pw��}5 �m݇�,��[��<�~�=��~�x�< �: ,R�J!e<�2�]���|�V�9����`,l�� DV'i������H�w$8v�j�� ���p=��Y��.�u+�|\c���)�ʷ$/�t�Y�����cȀ�S+{h�V#S�&g �X����D��I��2H�Eiy�ԍ,FO ,^' ���Ϟ��9.ƃ %�[J��|e ���|y�"�M5�M����1��^��ڀ 8b6蘚��ثփ�Y; ����}0PQTNh���"�(j�ݗ:p�4��n8�Fv��u&�Ν2�jpH�g��'�ң����yTA�ˏZu`�� �bá_˪B?� ����^�3�e⠝�*�Ŕ #��JhLy�M �� r ��9F;`��Dz��/%��DYG�dj��q����2�1Q�9��9);�l�sI�F ���S� �ج���O(I*���� ��C���� ��p�K�3��E*�PFp�x7���$��<�EʡZ��Rn��+ndw� ���kV�A���V�yi ��7��R�9���a5Y����5���m햒��H��0G0�z��1��ɻ��2�����ZTP ��vb�A�CL�#�u�Vq����r���Us���Mx y��еg��f >���H��S=�\���!��(��)�6�,|�6|ϙ5$vb��)�)2���HΘ�CE�����4�!lč� g��q�O�l�_�c�9�ƫ�H��3h�CP�Hp�.�����t9mA��|!����͂��|Z���u�e%Ͼ�x�p��V��,zU��x�ޗ�ie��˜��>H�v8�����i\Eu!6"/!p<'���+�s �qrYtQ:�2� � �K� � ���^~��F�W�Vw���_������#�O�J�y %�ԅ�8��8��(�dp�Xyp�����W�$�c��V���>��-�ez� P�Yf��Ek �r'�ĺp��Ϯ:�N=�I��|\�8�ae5B,�a�c�Y�{UZl�a�fBL霜����f�w��8�*.r~:��<�xLA� �|f�3P��ř�m�'. I/0�o'��@��)2U`�e����$ �j0q����G��hه�#��q0��%�䀽��-�mj9�)/������'�# �TܤU�u�� {�p��;�������+��_'=;?��� �$* ���Ё��� WOg����%��91T�>X~&���`nmr �6�[�� �8�zr&F��@�i0X�����(\ �ޕD�_H�.��� )��A >��?:��$��p|}mt{T�9�"2�e構�!a�7̏%�h�S�� ����;ptw�'����j��VP�U^��vn��3�>mY�>,�]����$�R�0Þ�A�z7�5$]v��;���m�]�ϡ��B�͂�t' �@A�v�8��X���F ��Y3(ޓ�b�d��zR�Lt�w)0��8�0j��c���.0;�1ϳx�¦4��^��cb�3���?������>Jٛ��e�v������4 � QK�Q_�Ҳ�7D�Ǩ5��7+���l����'�r�XQL��_���8��ӗ�Ҹ���4�w����^e���*w`.�1�?>�=y��Ӯ�]��;Qq-H�`����W&�4�"�T�3�i쐾t��p���0f�4�<�F:^*E�:ie�a3�R䏆�Hoa���!����z6p�#N�R$��W���+F��wÑ)��T�\7Q��?攖l��($6�-|]}�X�.�e#ִ��$\�Y �I�4���������J��Y��!T�"�Qf0�ݓ��.�T�_'QN%F�\mV]��sr{�5�Q\�^6'W�u%��u����@�� �fP�����s� ���+�;�ˢ���Ww���J���C�_+��~*ĕ�n]j���� Rv��tM5"�#�_)��~F5� �x���k�j��F jO������ ̈́{G`��;��2��=e��d�߲�R97t_��x0|������������?�HU��OX���O��f���)�di],�?���0)��C�z�O�D�SL�v�/rI�]������(��܋��.Pޚ�vV.�Y�k�����Z�9I��HI]�pս0� q�g:���;!�� ��ڧ%M.�$�9�f���:�p��V��,zU�4��H�j�9�)Ө���`�ى�����������gBZ�QQ՛:�D��9�7��YhM�$�r�qɵ���&�xd��7�\l�(4�r�x��XS��M���x����I�)�����3�m1 endstream endobj 1345 0 obj << /Length 2465 /Filter /FlateDecode >> stream xڝXms�6��_���3&D� H����;�v���^;�M&! g��Hʎ���.�i���g `��Ͼ����,�%Q�2����]`���&W�x������x�n�!�g<`Y���b9�jQ����Mi��V�Wa�m���y&Bΐ? �4E껳��8 �S"�|&�ODJ��x&S�x$��/O��}�y�$P�`��kU�7��t�|��we �68O%�xΤL���_ �����]��eS��U߯�����B�w����K�u?��G���k~3�l���Z�w�V�ݶ�u5i0N�F�W����M��N8�s��' P�r2G�tp�R4��M֏�eSdLf�������p^��LH�4^t��VS��rl���� �����F�(^�� �h�g C�M6��̦�W�q�#������7�f�Ms[j>?_�X?�r�d�N��g�Mzy��������V?�]槺���9�����W��i���BY�V.�h�[�����'-1-ᨈ�jS�P�=�a"���%�4�t��%�,�?xp��Yg, ^���G�S���t�����;�U� ]l櫦�ݼ����n;�>x�Y�ç����.����E�N��Wn10���/�( X��",��Ǫ-4��{��@d����2�F�6KdM$��J����n�woi��#�E �=[0+���7ծhD��r�X��ö�*f�v'#��OX�a���8 <��a^n ��T� s�LA���]���4�N�c������� Vw�5]������=W�NV�KJ.8~ �`*��`�d�Wu�ロ�}�(�]6�-���V`���_�xh�$�E��G��<\(��C���Z��љ��j��2�,�Ā��A�G�C��Ɨ�ͱ� b��ճ���h�v�^A�Qq�K۪��&�ٶ.4�?M-�'s�"�إ�ӳ�\/�.�����b'��8�&w Y�*�J�����]V�&"�}��� 6c�A�ڡ�b/�/��GM-7X�'�w���j]��-m���l7�U8�'�gY������s��!����b����%�=�k KY�w�5Z�N�I��@>���8�ׄ��6��CS��Ҝ�N.>������دm1�N��A����p(�� �վ�������P~:h�ю�����:H�Tw6����|���H�n�jт�-8:��A�e�7g�g�#ԃ��'m�,�/Jل"��Y$ ��Z���F|V �W�T�v� [��F�5L[Ôl �Q���taMNi��]��&k�:4���:u�D0���}[�� "p��E��)G��?��+K�4�jnnL�������_�/N�ӯG8��C"�覤_(��oT,&T,bv�%��:���-LM�{]�`�7��kJ�6j@�sy���zG�8&���i" ��o׆`8��� G�/Ԇ�~mX�&g���q2��9�Ҳ�o� 'kC".�D����!gQ"Y��v ��G�߮ #�D$o��/�/zP�\2?���I ���<&t|:� �0v؟O���% �$�jo������qh�o���Πr8�h- X�J̫������ ���6���z��e����#�h�8n(p�`K��U��Ɗ�������k������7c�^�K�S�z���a,��w��g�P��}�f������y���|�q��q�:���[�N�/��l�֪�)c`�LY�ŗ�Ƙ$��X�_Cc�e��Lj,���tV�U�;_[�.�L��#�bJ��[���t4?����3�F��_�.���5hM�>�� Z���V�qb|�H�Zt�� T�=��^��q��i�nu7��(~��z1�u:olAܥ�L��-�M׶}D��Oz?�8y�d�-�\M&l̅������ا�~�6;�c��Fceݘ�S�pִ�s�����\�<(x�Ԝ6���8e �$> C��~�6��� endstream endobj 1422 0 obj << /Length 3411 /Filter /FlateDecode >> stream x��Ks7�����������-�#�$Nl�!��Z)S�H�t�o���$����U9D������hx�S��HX2� ���. ����a��[�`�rdYP�,kJj�9�s�Z�׻m���ҍ53#�Hݨ;��B��c1N�0�ԣ�OC*G�e��i�l���n� ��%�i7���:�c�����NJr(@��!@J�6@�&2��o����.ُ�D�8�/N� ����dA�C��R9AA�A� [ � H�ә��5�F<�P�4� �?sp��p�'V8DBA�F�ҋ���FB����y}�ړ_��_=���t��Տo�ڵ����~k��C��3#1�>r�%|l�M�p���(�W�r�kA���1�a���Й"�[���qÉ�_�e�*n��{3�"�{�4�9�4���A �a �K�18��z����z�w�ڵ��̸ӌ}��wK�#ج��p�&.�p΢d#�}���9�a:�[Ԥ�۝_20#%�k��؍f���m��O,A�&F�.�s0���xbl��!�Jʦm�Ү�����/�A��2,��F�R�0z�rD��mA�iifo��Z���kS�+?sy���t~�O�Q^���-�9����0�B*G�e��&���$��3��PS𵬹7��_�|'s�o�jxZ���-�Z�|m&��)���^p��5{�X+ņ�)66&s86RL�}�r����� ��� �q������v=d����m(ག�;Y�lS7�hq����~G��ςRS�q����Y�'w9վ#������C�|��|vN��`�I�{㔘�L#n��Ub~D������v �j/h*)ZdZd�Thᒞg�_������FO_s�櫫��]��wj�?ѿ?�dCL]J�q�bA1B��܏������~�M�~��Ν�� SŌ�ʿ%�d�J�Nա:P�7�B������F������d�VZ]�2wY�nb� 6�HUK��QJ����v���r3H5��3;���o�P���ʣ��|�.=���a�}b�y�U�<&s�GꝆey�T�E ۨ]����w�l������-0�}�D�#7�����E� ��+o�Z��©��:ṖU#� +1/�a5�� �L���๔��Fh��K%1��B�T�TJ���mMj���Օu�n;� �ki3+��q����${���*����`\M�G~=x������Z*8N6�d���� �㶠���q�,�(I��\�Y�H��79Y��W]0�f�oi��_�-Z��?� J�a��"6&�.\��˜3Dc�[Cn�_���vt�性q�����Ζ�֝�q��cj��|�����}Э~�I�:\QC���9:��P�!U++�4�.�|�r}ٟϗa����4���Un/�)�Ds?�$ ��SXܓ9�;u>ˎ�����"�RpS&����W�~���~�[��n�qJ.n�0X�ӧ�97ަ�L�T]�(��i�񭟓{���W�.�$~ �߿6njO� �����pboQQZ��[T�M�K��Pb�6c;!r����wI1t �UD1���l�f��LP��c�p��N�,6<&s8> stream x��Z[o[7~��������mH��b��,�m6(��c[�,iu����J��Z�-YJ�i��pn���X�Fe�1*El����s�,h�Y�'���Q�� DP�Ĥ��x&���I�DY&8�ba�U�V����r�0g0g�� ˎe�p�2 7}�Y)�D��H�ЃK 0'Q��'~�+cX�kb�e��"*�Y��,�E���:壬�S���#ч�GYu�@��r��S�g� ]te�W.�cEFPl�p%v�XT�P c����f��"L�ɕYT�x�s�N�6����s"�a����ʇ�7�XL�n6�g.TV��+��8������Y0��t(2� :d/��U�qbDJ��*�!���pV^��*�/@�l����TƒJ.������ �:-���S,6 �R*>��S��D`�M�M�Ly"�,�UfWƒ��.� d`�9&�;�\")���G��Ɩ�s�"Z�Ӹ�Q�p*�Ix�\Ï��<+��DV2�,�ɚ� �׽�UӍN�f�ͺvڻl���Ϛ�t�op�1�9[ �����ټ���b�o�zr3�V���n�|�+�_J}�ui(�d#-��%0���d(,Z�@c�wZ��`~�8+ʟ#�JI��qw����I9L�6 h����� ?�b^Q�|1�B?Zw �܎ J��Ö���F�I��P�wAJg����b�{?�&z<�hv���(4+e�8{("�2���e1��!c9h[NYX{#*Emv(��PC�n��k� � �6�KQa8���� M�zu\�)X:�/�c��)p!�j<:-!"@�7�/� �=���O[T���g�:#�(��MY�r��(Hɢ�UK1�B���b<�_�#��?�Og]I�I�fyV�<���c :F��&`�R���� ���7�>����jo�[N��=G���5ȫ#.�[�9t��VŚ~}�bM�{Ϗ�@[�'���/�A��>H�}�}8k�Y[��Z�+��J0��$��!*�uF��s��Q�~�|_ �R�'��g�I;��Y� -s[�^��|(�·#3���B]�\���Y��pUs\Lh�~%�3kB�c�#S]Ѭ�oD�j@�fv�*�\�]��=��a#D3�6�_sԗfAMkEb/ �Ț�E�Tu6�FԫhE�fuL� �����ɰ�-��= '�gq�O���;}�le���j����;��шA�r�Mh����$(.��3y��8�g�h�ܗp�����M�r0Z��_ݴ����/�)$���}��$�qR�˯�d �{����`_0�D���� ���]ω|='��x��S!_����WT*��9TΡr�s��C�*�P9��9Vαr��s��c�+�X9��9VΩrN�s��S�*�T9��9UΩrN�s��s�+�\9��9WιrΕs��W����%[ ���W�W"T"V"U�r�����m�:�~��D���=�ΰ !� �rF���w������HgK���Q�L�29Hf4���Ȍ {��*3䣈��$�t�F��gsi�H2�i�@-nd�����P�iЮ�Mrzy�Y��/Q ��ְׂ6췻3Hf�y�HT������-3`��uHf`@9��I[O�]���`#5��t��e�*oD�&���kYy�6�Q��'G�,���ME`�#�x\��B֦"�����\Ѐ&Z�4I15���t �� mFtG�>i�x�V>���g���7[*�c�����2Q}���K2�@��Zf��d�x �!io6��I��QwlGF*�F&�.v��3r�-n����P(�r�t ��h��z>�L��kЖ���.h�$�ݸM ɻ�|�M|pK�r �R�����O_c����������!�.������� ��A[b��4iK�i��7"m� ��$h�e����"@g��7:����oB�:�w��I�*0DN��2)hGtԲgQ�"m��Z�&o��[��w��� endstream endobj 1428 0 obj << /Length 639 /Filter /FlateDecode >> stream x��WM��0��W�����[�R��.�e�CD�RCV�V��ބ�_*����<�M�=� )~�ؔhΩ���U�~[�H���i� 0�!�e����RjS ${�ʶ�!z(s�T� �<�\n�\2�4��}Y}�N�%c�y4�Q"�� ŚD���[����E��}�x�f�P��h`) 2I����b��<ں��8a6r�|���1� ZS�L�}�M�����.���o/恁6��N�4T`]��yF'=x�Q��Ðm�1[MSfC�=z�M��Bk���c��c]��J����<0�_�P����^���ŬW˜O^Y`n��,� /��ñ���+7���h � �z���S�W*T�3|^�~�c>)���(x��S��x�٣�Sg���h�zzŜ|�Bp��;�/��c>9`�|9=p\K���!�H� žAF�A��u�y�ր �����lR�-�f8偦�2�tJ�W&=�Nz�S�!�R��xHʮ6��큻^3OXW�u����u���{ ›a[T.���q3P�����v����j#O5��c�Nz� /C�EjR�0�V���N�AZ�q~ ��(��\Վ��+����yy�&� e���W�罰A=�악�a�{{���K��JG� endstream endobj 1504 0 obj << /Length 3369 /Filter /FlateDecode >> stream x��]�����W�r7�X�Sd���)�H��)z�kf��خd����R)Q�|�b�3c#@������7š���CW�\U�#����M���yX�~���� XD��}����J��%1�����+I)�>�����?��������CI�1�d9��lE+¨������r��}�Έ����i{ؿ+x%߮���������n���~��8A�P�+�(�PV�W�K���>�ӕ&F)'���7E��ֻ�^o���a��7E�Ԟ��֋D_��$R ���k_�+hE�?���������c�"���0�.P �E�ȱ( i�.t�f*R2�U��3� ��2�%�w<��t<��S�޷�ug�;�I��saa�O��4�Ø℩ĄS0%�3L]�R���n���j����lM�ϺR}�/@���:` ��������Dy�kC$7��!�����5�ۭ۶�?4���X���4�L�f�֐J��i�(�F�q��R9X#UN)�q ��uS���ۇs��9sS����|�]F�C:.e��.��9פ�~bE ��� ���b�Ȯ�X3�/@7�KUY��A.��GQ�HR�{B=��Pۀ"�}��pR��ش �CӲ(<-� K؃8�����̃v����=���]]4�ö=5O�a=u�z� ��?5��)��=Ry��(��1FJ:����m�x�>qX��bJ��)H�g��J�B'r����_?fƁ�7�v�yE���u?��R��GQx�{��R��?ᔇ�iI9)�B���^��?r��<�;Q�ٻ,I�B�tx��b�{�q��4u�~R� ��cM��,,�1�gJ�%Ry��(g׌������֌7��v_��y�i�p[3��Q�lz���ak��J�@k��k$�i����y�pC�'�I%ի$�&��L�Q ���h]D�s�I���i�窊p.��>zY9)���*R8̀��"�Gg�H�0^TN�\�c�}E^��?2X��ʡ"�ʳ��m[\I_������ �� �m"�Ȋ��? ��3����#�&�r������������z�� ����������������/�D >�lȇ�n{z�.{J��Э��@����a���G��-Ry�Q�<��Tio��]����:<���3��A*|���"F� ��؋=�� n ���)��Ő��D9�@���W�$���s4B���m�����IcS�^Ί�A����08�B*���i�gBֽ�Ty3�zd:`[�x-�e`��AD�� b�cx �f��I��3�p0��� {hH��̉�����Ru�e��'eE����l�g�!6A���#M��`������=�oD���T�1C����-��X\c8�+N���H�X���PÉd^�;�f�ߞ����g�TB0�?w�Т�qg��\Q8H+�\X@*Z�rZ���D�rF�r{���XX>c8�'�<@*|�Y�J�����H�����V5��1�AL$3� >�)>H��*��<���p�j��[�l77 7D��6-D�Ȏ'���1v���6^��pʃ��51�(�6��6��C�`�M�-�d���V�hp�>-�O��S�>UH�c4�;�=�p�w";�6��,)])�H���� �zX���|��O��DVF�����֬%e�����h-/U�]D�3��Eojw��#U���Sʼne:o�E(�7ztMq8���}Ww:g㳄e=�ì��3�e�Su��3X�c8�7N���|q��o���(���~������N��Ҍ"��ޅ�77\�����C�]D�3�EcLY�:*9R9D/*�E��*�ˑ¡�, 'E.4�Hծ⤊نQ��;W�-����� B���jY�gk�1�~ e��(��� �i�����$��d}���~�����[�R�ַC�bs�Ni_�� d�w ���ɞ�=:�8U�7Q���:�~_Z����������a�1��R?N��O�!a� �J��v�_�(����ijx��ߧU/b�60�N�.�X�pk��[m�ÊT���Z-�@_W���ߎ�?4�����!��ѱ�p`���;T N�L�+J1��~���A�=5��t� �ן ��O�e7����D*�e�Su��<;U�T;b��7.mên�h�x+�k�16GL*��"U�9ż9��P���=6���U���G1�V��3�a~�9���)�$y�#ja~�S�|K�i��S>��`�%�H`W�Y��,�(�DŽ�� �4��Z&��M�}|<�ܻDਐb���OKC�c_~�6�ѡc8�P�Ѓ�PʣC��"/8'<8tI8)r��ũ:�&��F�I ���M=���;�<ӻ�CB��!E� �I�Tv �Tel��g��;�4e�{:?���!iۣgwC(D�?#�����Ʋ� ��H%�yR�Ј��mn7�9W�u�ศ��{���Z� L��{�_)n�{�8�5t�ݎ�M���a���0����Y�8Ug�D1o),�j4A�������72̯>�D2�:�0��`Ɏ�0�8��RՑM�Ct���?�+j����ͱ菘���ε������� ~ ����|v;���'��*]RR��|�K �_�v\� ���]�+6N��M�|��v��ύ���=u�~;c��>� �p�"�sZH���b��$�ә ����.�!qX�c8�?f��!U�D1��* W~��O����ou+�/�Ґ<�$Xc8�#N����!U�D1�CbJ���)\�0:�Kv ���i��T�D1OV"�E,�lSwo$�X/\K�$T�/_�ªsx�Bv.dOR����S����"���ƒ���"��鳋�HUg�D1o@��M���~�m�����e�� O��5�ü�������W���Ŵm���׿�����r�����3bI��0�8m@ӎSu��� 5��0p{�Z"9��i����|k��� G�WB��"9R��J���մ��-��Oͺ� �����~�$$k�1�E�(���l�(M�P� #ҿ�����p���%��N:��mJ 蜑Ҡ��(��c6C��z�@/��8�~��(��7���8���ܶ�f�ݽ�ӵaZ�z{}�h,�4�\<�(�a�� ��<���C/�N \8G�$�f��1 endstream endobj 1424 0 obj << /Type /ObjStm /N 100 /First 1002 /Length 2299 /Filter /FlateDecode >> stream x��ZM�����1�p�*V ��%K�$������j8�ޯ�͙1ԽH�l�����i��U,�Y�[ )dn9��>�@$>��l>(��� �������>����,<�r��%6�, �����!�G%dq�����>CC��g����(�>���9�e���9��gdP�g@��`$�-�I #��LS�I�� ��%p��!���40@�o���\5p��G-����زKA�[%�W�Q -��38�b.^� �S(�U]��$q.A�:2'T��4HWp��"�ߔ+ք��[�-)H��YG���k�R�oZJP�>C���ǂ���.�R5�ŋ��N���������.��`�+8�D����a��^J�R��c�PD��y��O�Q�����I}��Ps���J����/1F�l�S-�j{L��WK5����PۂRCK�?�B���Z �ɿ� 6(F�I,wS�ߖЬ�>l��.�ih�9��[��7�b\[�{���W|N�\ �D}�+�H����uX_�T;�Ω�V��~�w��w���[!vT����Fs�ʢ����Z�y�������܆��ww��7�7�x�����nN��?�x�޹;H�oN��~| �Z��G͢�:�E.�Ĥx����E8� �o��އ���. _}u��P2EW��El �> �%b�7��N��6I��Bo��Y|I���ΗKd�C�Mѝ��V��c�J�0�N'nC�l4�-q���.�XS��<���H���>;D�����GlE�i1ù™FD�MNj�d�.�|:�bޢy�s�R��x�Y��s]��@���qM�[�� �r��"�F��,j��I{����x4� >>T>r�x�hH����cH&�)�_]� ���:��rL��4�Si�ʗSZ�rE�=�/����������k��� ���e[�4��j���O��h;��,}2�o�g��}���M�pa�u6�"�l���^�w(�2����_��Q2�p�����_���{�d�PW���Wȧm�L�����O��?���$����pz{��cx�{�����ۛ��@r{����w0�����o?-�]��w�?����_M)�k�ͽ����XTj����O �O/5ׁ���A��hy��_��ЫhTԃ#�W-Qu{ ��g1g�B� �3'r�&rHq�$DZtgNd�㱜�#R�3%��$������EJ��y/'L#Lf�|�T� �mkl���w�����ѥ8Cz��M�_:�S�I� ?"��7?"�K?�iu �ǀƀ�`�������kx��� �2��@.� �2��@.� �2�e �@��,Y� d�2�e �@ց�Y�d�:�u �@ց��� d�6�m �@��l�� �:��@���:��@���:��@n� �6��@n� �6��@n��Ȓ��i�S��W��"��.Yr��Q"镣6ħmעi%����4?w��]Y���(����y�sc}C�G�&�=��pJ������z!(�{R2,)M%�ԏ��m'�u�f�� Ji�8�QT�VN�s�FJ1���N����*�]N� �R6'��r"��E��ΜCΧ8m'�k4�ZϤ)��n'y���e=��c���q��C ��'�9�D�;��Tq �ǚ.�E������'�O$*1˕n�+�C�6Μ��.QU%t��#?3%'AA����J����q�T���@�y�K8s�.�I�I.��9T��N��^r!n~<͇��K���Ē��v.$2���&�pR�l��� ��t����Ҹ= ղ��P1��y�霭B�5��*$�>����9�|�sR�$?Ϲ�dT�mw"O�["�R�֓9r�9��d��3�e��7�f�Y� �=3�g�|�^�"Ѯ"YF�ܹ(�e�I]f�$��H6�)��X�*J,;wȳ�/�[�]bJ�����:�� YO Q���!���g$Eo"[� ��W�!WN+e��@E����t�c�� @��_�!Vs�Y9��� ����,#�?�\d��߫���88{o�>�,�A�-���Z��^*axYn�P�����V]�Ί�����Ί��z�\��Z�^�o�;c�MrQ�I^��Umn|lg J��6��7��C���l�/������л�3e�5ڧ��N�pۛx��s :��jp��O��2F�_�'K��v�cTfu7q�ے���r$n�?���R���*E�cs �3��k7�ێO�I�?��)��#,�o;����%'� r����&mj ��r��؆�s�m����"]O��D�ҚVQ��M�9ڡ�B�л �78l�'���.�� endstream endobj 1526 0 obj << /Length 1147 /Filter /FlateDecode >> stream x��[o�6���+t�#+���yh�u�"QvS �bӱ0[$�k����9l��t(к�+���|�D�(��0�@Ee�ܝ��O�Ǡ�p��jt��@�}t��5c �  �u����V���� _��tvu#1�=-K��S� �����+.)D��v�\(zgI����v�&]�O�=ԗRH(�� ��" a���E-$(�Pq^Y42�!S��-uZd�d�1ɋ�ss�\&9�J��TW\^$P������`� \N"�$�H�bԪ�@^qƒ,�CV�5s�"�ӹQw� Y977P"�m\�O����e8sV�X�:7��`�5�$� �պ�=%[ ��_q�=d<�M�1�2K�"� ���.^W�������ݩ�ϑ3u?�.���,�P@��-���,M���D��4P��cw�ܟoн��p�G��s8O�f�C�ڞ�����-@nR]�'�i�=��>�mY I��T֎Xۻ�u w�:� sv O�6֩�,V�$���k�Q�£�#�_ó�z* )F]����j0�ϋb2d�s���511�Մ �Q��D��5XvO`���f�� ($}^��B�D㋸���VNĞ�-�� 1�������x��~�^�|e�kvr�t���]�Ƿ�wjws�-���m�xl;C�B(2�n��g�"i����ݔ������q�8�@o��i�Oq�I㝶p�L��c܅�I�w/w�υ��s�{�<�M�J��S�h���J�X�3s�X��Ƀ9���(��9��R�g�����ʭ��J��[h ��'��07G�S��U��|V�!���J��㹣�*0�������}��L�=�.�u$�\;�� �������eulgg�$Lء�N��>_h�� �7Z� E3_�� c��v�t�pL�> stream x��[Mo�6���1j��"{ܶ[�hѢͭ������lo����dR�(5)�i�1���O|�i8#Ҭ���,�j!�����{C����W�7�~����� \D�o��|�N��Qb�e��m�#��u��~����ϫ�|{Տ�8GB��L�+VΔl1�Ui# ���fy8\.D�.�����ե`/�Ž��_4��~�]5���vR!5o�\P"�C��Դ> ��(Xe�պ��a�S��z��\�Z ).����;�i����y�h�ǔ�p7�W� V�� �����I?���MM ��h�g� ы(�S�G̤Cv���քr�E��� �%J�JYN� �™�fww��4��ە{qf�hnܨV� �S�k�ΥRuM$�s���E>;�cF���8aN*$��.#'Cv�_@��{���C�����"�l�ҦҚh-ƞ��mo��f�~V�����&o`&91������U`���T��+� OPʭ�f�@�m�2U��V�G�d�!� C8l�XAA3��{3$�3HE��n�ݶ�3^��k���0� O%�C8�Xn@O��{O$�OW��>A�����)�V�`H>?k�|C8,_Ld!��{��l)�!���� �U�Y�����*+�v��z�}���4���eV�!f��D"�ʲ�� Y�,����e��3�%9�>ENӖt�K��d=�-�L����X{��V�a�D�e�`l�1l>= MX�����G}���f�es�.�g,ƭ���t�A^���o�!v����8�� r��Hb�_���-����|5$,1��u*/�^rQSB-�h��A�����D.J��.�����G��6���R���I0G%C����mu �s �7�6�h5�Q >�-W�����<� ��(,�G��99��E�d�ry�F.���Yf�Ƚ����m��62����?���=����j��F� �� ��>9К"Oh5��U�iE��V�����&~*XM�pX����&8�^�y�I��1�է��������=���+� S �*$r/`�<P�ao�0[�+Wͩs���5 �b�1������wM�Ƚ?�?�+���/�Ym���s� $�g +��_���˝ �{;��+�*-�ܟ�� h�\o������n�aӜ{�G���6�Ҏ?�������'�J���4wx ��KG6i�dk�'�\�z�lw�����bt��O�RAjg�O�9 i���k2]�; p�� b^״(�' S1�Z��a]�Te�鯷<����'��C ��u�Y�C�E�t�|ܻ��� Y2�3Z��5���; 4Z{ �%��+��)a��^n�"�~n{ ��ʭ段A*:D�����kU�A�r&py5�pj3j�K(���G�� ���b��a�����P9�"�)ך��twD�ܩ�����rw�2wG�`���nr��K���܍�WN�,�n$jg�1o=��k@��F����^� V�!V6�9c�VYj�l��WV�a?R6���.�5�p���A�$~2XI�pX���fáv�$�yI�"B��$�6髸�<'Xe�pX٘f�fáv�&�ye�{ gceg66�� �g�]��px�I)��(�a/ �Cά�8��z%�d�RR��v�K��s�R����m��ՃQA�A��Q8,��)u8�N�1+��¥ ���P���z��pH�p��Ѥ�<"Q[S�<�F��4F��i�j���.�?]*��>�;�{>� 9���7�������>�ϒ��f�<�w[��9���Pr���B[f�=�c�/�t���v�I�(7DQ�b��������N�y�0A*{~�*��1�:[$#Q;��|r��.���������_����|����� �rG�aB �=����&E̦Q;'�� ��kh�=%X]�hXֈc@Ud'�.��D�CO�������|w?���b]0��6�e�?3A�vFH��@"·�C:�w��:w�D�gآ�� �Y"�1�p�+>�p���y%A�g ����>������#?5 c�2��N�e��C�|��u w5��E�Ū�]oץ��=�l�~'��a�H��pP�y�����"�W� ����j86�#|j����0���1�t�BEYD�V�O5 endstream endobj 1506 0 obj << /Type /ObjStm /N 100 /First 996 /Length 2744 /Filter /FlateDecode >> stream x��ZK�����1�pȪb�v ���CAG^F m ɀ���U���k�low� h�>�c�����)���sș��@Ԍ(�Ň4H���-hU#z� �KJ�u'r�)� I3�j� J�10��� ��i̯h4��Z�g��j*��J΁�Q(K���j)ևMsMF�h��@j�)���8����끺�W(N&_�8���f�ā���t���EOa�B@U�'�j�T�`�F� �|^"d��J6|�A���T�;s��lK�J}E ��Wh�nlw�s��+Z(����R���PE]��Ci�0�B�l+��&�"A������Р� CjPW�A����l�\��p)9h/PaM��]8��|��J���T%���jjUCU6��;;�bV�jw��G�� Cn�K?�- �#;�XV�o�^} ���ŗ���۟߇W���⻿�ޜ~��7��Y�V[o yw���׷�F���?�~��w_��<Ԧ(Dj'���wo�� �2&�����ۏ�7 �"�I�I�$x2�2 ���'�<9��L�3M΋�^�z#�J�#�*����PP�B�P����C}��Q��A)+&\#��li'̬��~�$���u� 2�h�� �1[�,]"��jS����yⱪ��:DOZ1Q�DT��s�N�5G+PWH� ���w2ZT��6B*�zo�+dI����E�^IS�a"�*gL)��\6ڝ�m8��T*�e�ֽ��c�ۗ�q�zﱡg�3��Q�(嘹Z�i"�͢� _���Nuw1�D�r�du��f/8xE�� )������}��yC� )*QH��I�����a!U��R4����r�g�ó��Y��,�xR< )��O�<9��,��L�29��,��L�29��,��L�er.�s����\&�29�ɹL�er.��N�:9�䬓�N�:9�䬓�N�:9�ɹ�G�kA�Ĕ6�n�0�C��,\K-(΅ki��s��Ὢ��9�����s�;Ē���A��,'�Ux�&�7r*�d��۝ t�b̺�a��;y۫؁.7�2"E�U���b��2�HZ�VZC!ɇ�특���^v+5EAZ1k���X9s���ū��t����̦��2bĵgI{�ɸ��|�-�e����n9i� �nUm�c�vŜr>���yRG�O�&ĥ����Yܘ�r�k.�Yq �g9�\��[�.e#'bD�th^�B�7�H��1��|�����f��/�(��0!�.L��~�1�G� �,��ϲ5K�c*��v��;�U���V����;_g\��I��8�G�׊-������������z�+����ngX�7���%-��'�Xi�C�I����n0�Kd�c��j3D��6� E�Ӊi2>���N�q��h)�X5���s� �'�G> ���m�5��� �b���p���W��N��ޏ���b7�C޵L Wk7����|��m�c�h���1�n�0zP��hƞqjޯ�SA�W�9Mm��^����= �^�����������n�����4�1�0&�F��EqN�B �� ���7����[%:sY��ܟ=f����h��F��� �O��F�'��p�h=��kk7�м����d�[顊�����b �hw�er;쪙�a�x �����g��G[ԃS���k�\�B�97�c��a��n��3Ǹ$D!����G�ud0ho���U���6�q����k����W:G?����}�k[��s����{���7! ��ۤЖ,���mi��Y 7�b�V*��P^���څ;�#��߃�}M+�E��WAImT�a�vz��͸B��ǁ<���Vh>���L�տ�Z��h7q���;���F�|GO�3���wؖ���3GhZ�َP�ɧ\�_�K�ٞz5�P���u���<�7��mD��%;�h��r�8�#(">{������}�h��:�a�`�c�@�����y��Wz\��dc���v���G��C;��v�i�v���G�𓗋�R���+[���6�����.�}�i��|��@3���1��ޛ�s��xO�[�le=vf~n�E�k�v����'�X�F/Ώ�zb���\�j{/�,pZ�﵃�Ohs:�ZOn��fuQ�B���tM�xMp.8^��&��K endstream endobj 1594 0 obj << /Length1 1760 /Length2 10813 /Length3 0 /Length 11924 /Filter /FlateDecode >> stream xڍ�T��6,ݡt�P���)� 1��twKJ��t#" ��tw��{�s����Z߷f-���5�Q�k�JZB߀�0VN6!���'������� ��N ���1��邜]�P�?��A�'���)N�Pr�8��|B��B.�B��2n`K� @ �rA���:z:��m`Om��`28�Y�JHڃ��@ ���d��hhA�`��J0���`�B�����l�.lPgk1F�;f�����@��� T-�AoƆNж��mׂZ��-�A�' 9��[�Y�!o���� '��xZ��\��`G� � �{E��e�NY��Rjor�����O� >�'��7k�uw��X�,�~/a��Ȯ�vr)���dB����rpp��q@N�І�wymOG�_ο�O�x9BVOK�|�V��/t/ 7�� ��������` �o@�`��T2����O�� �q))����� ������xj������e�-����G��� ���O������!�?�`�w-U�kA���ܘ�����������1�w����w 9W�/7�_����� ��'�����'�@�d��z��E+�X��Of�$Ikȿ�"�Y��a@����]�� `�:����`����ߓ��vO/�'B��=��[�:�������pv��D��'� ��|R�%��/ �������r>+�3�������6��x���A�v�#�'d�o���ga��D��R�w̓��� ��o���B!O����{_v�? '����O����#��f�|��� `����>��������^����I!��? ������������`����p�>���|��?�멯�_�n�������K�O��� y���3SP�p�mUP�U�$�;����ݺ^#�׌s�� 6J2�̀%� ��o��� ����^��5(�M�ͷ�wf�c���?G {G v%�{(��Y�%6�u���ڔ�>8� `���]�w�{T��� �L�kl|�{�qW6��e�_�5 xhi��-e�:��`a��G����F���A���A7X�i���WlS����%Ʀ�gޙ6a��e �Q��$T�wK���#�~�� �vQ�Ű]=�!c ���e9��h��CE�ܹ�щ�~V*�s��ً��Kcç�M>���v@I�$pݐ勾��Tu���\7�R��T�-:P�6���,��ѯ/��(�ףs�X�Wo!D��w�Z��\tx��.�1G1�+����=� c�T��%���߮��8� o��˸���P�I�9�H�וh�U^����f�$ ��5֣��壥N���+_�x7 �dĄ�&��tM��rrdzq�2���%�+��:a�.�1��Л�PTʑ�� �~�1�a!�� �Q�R���� ���]Ŕϱz�uMf��H����.]w��� +�Pf�C44k'�ݱ"߮� ��B�J/�;f��QI{��$�u�R��Y׏��s>��ZfBpb�Cu4���d�� �r\G���RC�&nKN�������b�絒E�r�����S ��d��i�n��;��x ��wg� �⸤n���~��6�`�Bt����dw �Z��on|�Su�ͅrK~��atc���l���;��d�!�&���D�>��!eT(���Ը bn��� u�hvV$�c�좝t���HC�6���|�����Y�l�2�/N)C^a߇“Ft�ӟ�YU�͗� ������[E[���F���,Y�r\m�n�5+���M��v!���ᳬ���k���������8�Q;�4d�Ҷ �Y�HA�D�P��f�4��g��m���81�$�=>߳]��cN�$�RQ��"��\W����F�I���:�8��P��=Iڻ����eP�]*�j���p���;K�e�%�����^���ֿ9����Y<��5��D�(/�{�Kz=����f�SB�@S#=��OƫMnm����2ݵ�,���Tf�$NY�x��Ʃh.��0�V�������[�b��6 �@�r_J��v��? ��ʋ�"M��x�xj�V��R8?�~tSq��z O��)�B�d)�9��f�'G��}ɶfy��a�u���~�L�VU ����J�7�K]ܕRǐ�X��� �/S>���rc\�K�IR�?��b������4\9���FZ�F�]/˹f)rBKO�h(N���MO��#!���<6pwk6�_猲v��َ�.�o|dž3����%%}�@�4=�2H#b�+a�Ǐ��� �e1� l[9��9a���\�t-���26��7�6�M1� a�)�DA"�&� �Y�W����$*�$���٦5���w�!i�q�TC��Ʌo�����������#!A}�c1��y"/�uf���]��c����GN���F ljE� �N3�z�֞ 0xH}�J��%�%Uo_��N�A��}��m!�؈c��{-����Eψ�;IG�"�����Xg�z�y�=�&a����~�QS_{&��bjr3k�P�qq� �:�T���]g�V.)jP|ㄑ;��FJQf�>�)�/;\(�)�T�PE��Ī�9���D+�a�A��]"(AW�E��^^?Ndy�r�l�C�]�(V�`���_$��n��N�hqg�\� sSU�� �x3��ʐk�ܛ����^�,�[�e�~!�L�/~r�NKg��� =����l�e�� � �ʸEצ�\�?Q�hG�����;3����`F��U����ڀ/���������T�>D~CfwQKv˳���w�a��S��ܸ ��q�=��IMia: �Vv���Ӂ�B�����\ �!�D���Y� ���Bzo�ڧ>ײ&�����^! E �~/~`��w�?<�IZ���ˣ�&<��(���*n��°LF��~w��3��^��|�/���cs��&ok��%Y9�Ϡ�?5ҏR��n�_&q���,g~|��4�#�i�b��t�&L���Ͱ��첼Y�0�94�=7�Ql��Ϟ�� ���/*�Q�"(���0�䔶q`����qw�ݑ5�%7�����^ږ�w+b~�| ����xL�����F j��6EDN��R���}���2�z"����Y�e��J�#����{j@�|��x�J|a��ߐ��+N��æ5�k��|���������_�J� �R:��IDY�oIwBu���O䅙^��5�I�% 2a�o����� �5 �R`�(ᝉ�T��������P�J�H!��T��w�#Ѱ�e5���|bPg���f��ce��w�a�k������bL��誄�i0� �C�5�,)������t� }����Ņ%���q�>��Sz�b~��h!�� ��^_�ܙ��i��C-�� LO�μ�qZ� �3��@�W�Gn���%v���- ?�k�ͭ�� '&�0 �J��)�^� 6��q�� /�EH���9����[��5׺���(�I<������������\4L{ ��� w`"f�r��PZ*w�l!����ahS�E9~C�Dk�Y�lr9�<��V ���#'׵Ә3�Y]� �����uı��6��� �jU���|b[�zִo.b��%N�:N����b4`���~}�wo %; &��:�����?ۯ��G��dZ�#�S0LG��_b&^���!C$^R~W]��L��Y@�H6��m�[b��z�`�OF q�� F9�KtI�/ݤ��B N����f��Qe�}�6C�r��H Rx�1�9r���V2d'Qī}'�����ܢ�瀖0rVD4k�_�I�/2秣��M�6�=A��պt�Jj�4�S�v�Gz� 8�Y�����j�%��^s�\���ͅ�/I���/��Y�48'6��`���z���&!������I��M� o��>�EȜ1vuu\�C��Q`�/�ے\�J*��P!����QDE�4��k��ѓE0��W�L�u ,< ��'ZX�ܼ���F�jq�y{u �����J�y?tʮ����q�(rc��4U �Mn�����=T��G �k�0�xZ@��C$U����伅AT���F����դ�B�������+*���~Up�L�~��#�s&|)���8�U�,� �nј�Q4iFz�����Զq) ���K��#n�8 ���w�ap�2�F �nd΍��Z�*��� �_#!��3�Q�9���Ҏa�Jz�a������R׾1�T/���E����/Z�� ¤��AP��t ��_�F O����S�Ll�D�?#��e%�L�U�0��ׇ��@p,��Ce�h0�B�e�� ����U�n(�P�8#��޷kV�W%�,��UE��|�L��&0D�"L�4�������׶^�ޔ��E�hy7/�.��:֜�N@p r�3wC��{jc��nQh��7�`�0UDM6��l�{�� I��Q���M �s�Pil r��=���lwb�fA68��n̝��k:�'��Xy}S �a��N��M�txhu��wuf�9E:��ā@R��v,�,z�IqW��r�;��:w�i�slrr �o�H35�?����3�t�����S\"8}��U��G�`������lך�R�eoފ�mH�b|2#�/R3�6� kvK�Z��0 �ߚ���m��ߖ# ��[� �`8>pWG�c9������<������J\�'�{�!��W���%�����-����g�L�R�J������^EY,)i����*'��+�kd����6a�@��}�W���;X�X��Z&�\n��x���e���J&&��#u�����T%g�o�y� �0;���v�;eYëN��}y���Ř)�KOƴ��s�.ˣ�~���������ڬ&�W���"��m����t�!֛pi��ʫa���'yx����O0��Z�~�!^��<ɹb��CY�}�4�@V�GR�3� ��F D� ����ye!��O�[>���Q�[�x�H��n �f���3�h�Ow�3�&��W�X�5cv(m ������6R'J�N�����D-ٚ/����[$E��W)�;s�B���>�=�$�^2��}M����]-~f����N.Ô�0� ����X�? ��Vk�*b���u��Z�J��Y�ۍ�b̶�(�?�n�ߎ�����[��_�b0�U׏cChz��jј.�k�8F���#��wL wCgϢw��0��6L�C��W$%c�Wh���R �׼�؄$?�U��E(=��Qπ�7P�L���Ԕ�$ɶ~���̉7�I���W]`�L#����9�5�ѫ���� G�:�5�+�U2�F/�ROjYL+QAT�뙺���}"+�͡eE�cLU�ˋoA�Ѻ��_����^�dR �ii!��U����s�cM�V��5Y�k�H����!+L��;=nU9���'���(ꃻ`y�oԾ�,��}�t��4�nt%1�R�e�B�F�e7����fƮxC�5����%��z�4�62�{$u� ?κ� ��K@���ꄳ�߻�9K�{X�z�o�y�1Bm��(w����<쒓����e,]�9�C�7^������2ۮ�r�����k��#��|Qx�m�ޥѽ�p�Ѳ:Oo�:>��p� 9���cƌ�u���8� �' ���)w(N�Ae�:l�khx���]R�GF��(k�i����S�e�Ux R����r*�8c%x��c���a��T��q�jȇ�!�,�m��p�.:Co�p����<� x�F�'h�-�)����mj�Q��y����L�؂NkTt��7�qt�nPvV�� } ���n9���65���n���y�|O|).�*�q�FpzYQ��%�v5B^a�˖���d�#Z�K�w�T�B ���_��S$2:�/�L^y��gF��G֕e��6d?����-�6�OR���z՝dw ��-��n�=������9J|��ܙy���m�2b��Rҙ��.=>s!�B�F�����*���b����x���VҦ3-n�5�3�E�}��&Z�Hp�a�����_x� 6o{�u����f���/�?&�?��� �B��AXڬ�g��h�"A;̱�%�|�ɏtZV��6���h���Dŭ����A���\ ����W���ލr�� A�"�(?�癕�$���i�Uh��ց*Z]�6�U�R�\0��^L`[��\/�M0M���������̆u �kО�mG�o(*��ng�l8�p�Ǯ+_yA�� ��;~H�Gȱ�+#E�g�l�z�B]����,�E�Iָew�Έ9��p{�H���SE��޴��1�H����M�x�p�,m�q�� �#ҙ3Xe�ޫ�OV�J�=���" �k�uN� ���m �=^eXfc�xY"�(-�3��7��r�#��"AN*���6����hf�Oյ$Oם�e>��o�L2)�����P�q��]N�r^��wQC�׻c���#b�9���)~�h8���D�T#k+]�OX"gڸq*(�,��F��x�5D�Fb~#X���M��1p�xk޼#c=.b�F�� ��>|L4R��V��Ɉ�gs�w���ya��k^�^�) 8S-t�� ^s'$�+��+�z����#H�IA��^��t��V����>�������{��o�(����������l�'���ONFm �z����EI"ԝ�w<��P4�q�*�c�"3�W>'6�D? nt67��"�tG�,�5.n5����}�x��?3��#�r,�+A�ז����Y�|� �y1N��s�j�O������M����P�(��I�b3 �]������a��P�-1y�T���� ��a�W�Aݞ�w}z�bk|3"c�Kz� r7 �}زa4r��,��M6<�&CiJQ�E��D������\��N��)�c�l�=U;���E �����;�N�-�B�Q�[O�+e����� 8$��`u�#/sg�<�uMoJ�|�Z{�ʞ5{��P���-w����9:%g�C�}[9m� ^V�3�%��T#�J�K�v�������t��.���JpM%e�0Dw��,cc�x��-Γ�����?��i�U�cz.�S(� ���tG��Nv��yt����ʭOx�D�k�Y���e�4�^�O!� �K1��Hz ��򽣎Az�أ���x�W򂨔��k����'�.m�}͢���Xt����9+V���U=�9�11�N�|�к�q��:ͬ&^6�--��Z�������@� �C'Vy2{�dg�&a�2ᛦwq4#��w*æ~���2�ϩ_X��b+SaƢn�dž��WX} #4#���3J��nv�W%��Y'�K0o���v���GkEZMS݌7���t�s�ٹ�Y��P3a:6J?c����Ua2�c�O��v#ۓ�+,_��R��(s���L��j��� ��(�1}��n7/��}tJA%�j�C�O�8D�q��DU*V�ϘQ��!x�����x�֪�63�E-�1b��5ۂ�90�����_LxU���K��5_���~�N��E���oc]���؎o�T1}&.�k�> �(4Z*����xB/qO��x��,��IoB.�m�aVIe)Arb����T����� 'Xq�4����m����țu�e,��KwHzFO���Q�Cz$JZ/�&�9%���]�b�`'2"悑����K������[��)U~��b��>��S�� {��<�� ؖy2���H���� ��fg]`8�x�g��zַ�����dT��;��Y�Hyr8�IdPݑs��8��6 痁�->�yR!c�����>��*���b�U�iO��R�b��9s�/� �BVJ3r;�_�?aT]�[ׅG ��W�� S?/�f���Y�4z��� r̲������ ��oy���fp! �9^l�R�YZ��!�h`��NI�\��,���x�]�Y�=O��[^�r��kq�a����� �6Mq�l�f�F���/�U�#|���wOH� ��!�M,'��g������ �I�n�/�L^#�X@4�׍" A�E =B�+�SnL�Ԡ;͡[i�ƕX���pj����9\SCd�4��a�E:�eLI+���A��H��r�O��Q��ɇ���y��/9�B�[�9� Qa�)�AfN')~xn�,"�� ��"|ZOW}�m糔r����c�(��E�G�\����[(��s�p��_��g:�AM7������J��w�9‚��k���V��u�����vr�9A��Xe�0����� ߁�ڰ�z���cB���)6����F���"8�(�!��r��)���(�ۉ�L���')>S���^��{�+���4k�&a7s��X[C A� �s&1��IEŘ����KH�׬�I1j����#X���MVv�Q :���<��k%��U��GMg��;���=�^�*������oHZ��"�Bɳ���B/��vQ��5|��X��X-%��=����(.<Ω�����r���@�YD��*���{P�7d7�o}9� f�TF{��b�v3�$�V�CW'����M�oP3�f4�Db0�E����Vw7�u�Iڢ�C�܏�7���].h�Vr����X�x8��{E�Wf�~�v+!@8 �q�����.�(B����Ϊ_��7b�l�m��$L �SҶ�/���TRUɺ2���m,$��|IR׃��BxC �B������[���|��p�%S֣⬟B�@��E5�T���!}G���p�v"\~L��U�)�,U|��}� {c�V/���y~Yh�|݁b�1��?w� M�����.�1�\JmvJ� l�>C�"7Y�*~ss����+ڽj�6����� �lU��hT�H�$Z� �W�K� �fw���j3 ���Y��c�/ȏ}����:/U^T�~�l�B͌�K �Zѷʧ⟕��:㼚lZ�&��iz�5��_���ΐ����C��M�M�h��M��|D�U��� _͛y�t.�zN��jڏ��j�&��o��;�=9q3�F��j%���T��zx����( z���k'�?ϸ"Z֫�L0ל�̟��I�;}�|x��^ 7`�:����GM��6�j�����+���0�}��yi�h/�%k��Ǔ����Ge�Tλ�ly��0U�gƼ08a��E��vL,����s*eƬ)�݌�k��ϖM�t��O��%��aս�mj�g�g��k��"����#��[�V�����ht��7�N���s ?��;��c�����'�_����\��We�i�Tw���L��F�{��.�,cGʎs;��K� VZ҉�66���X9 �����H�A��׆Q�+��� �P�Q!����|�?i��߹1�k�|�m���'8�7��� Gy���H���Ⱥ�^EH~E��p���W�{��Ļe(�H�@e��ю�`���I��Ω���\��^��du'3� rs<)r�'��v�.s��P�L�����ޭ�#Q ��~����v}�i�q�ܵf�y�W��g#�R�u��)����?�� ?�2���R�-t�nM 6�]�fp���H�#��*���*�~�*{���O���ˎ���[�Ƌw���Eت*ʖu�Q��['�`�.��џ����h�ƛ{�\�5�8�$1��E�>�C/���{���cp�~��%3(���]�0.Gt-�Oj��&�(y"`������( �!/��^c8� ^�0��z�� S���s`-GYZ�����������*�a_��˔]��na��#��MP ���XF{%�:n�^�����]ľ�ZW�nj�K]5� �a�0����B��$v�P���qg$_l�r��5�,���X��`�l��X��i�]8�6t�jZ�+v�P(V͵���N:����|xY��e����AɞK�e]6vO���9�rlz0�۷*fS�w{�#54C�%�Ss��"��ҭ�x�1�u�L�٣w�Xף��!�& Y;.�3�����^{ϫ�_ђ&�7]�{㳷vZ;�殩p )�R��OA�_Sc�3 ��>��9��Zm�B�ܽ��K�-���iq���p�/�p��N�;ڠt�E*G�^�}�8�<.�`r��Yl�0K��O^�=qg���DZ+h�x*�������n]�mhDY�+�گ��,; �Y��+�������T]dwJ �b"��dB�`_�\욬�;�#w-S��|ׯ���q��2�e�����n��u���sQT���4+�7�P�LvU8�m�ؖN=M�GN�yy2�QE��(�����h!n endstream endobj 1596 0 obj << /Length1 2509 /Length2 18183 /Length3 0 /Length 19632 /Filter /FlateDecode >> stream xڌ�P\�� C��apw���|������Cpw� �݃qKG� �w�� �l���/2����Ն��=����$#����� �daa���� w ��{؃�V��%����eog0���4A� y9]AgG��ן��EH��SKg�1����;:D 2�C��h��e��+�察?�C6��l�����3˩��+�������v�/FNv#'+����������8�@������Wlf���\O�-��?;@���o,E;��4�]������������o���������"I���4���聶�6���l��3� � ����Z�NW������d���[���K�����;�T�����u�G��ס�X�A�vN�=Z��,,�G�.k��� ���@���ߔ`;ӿ���� ttz �@V����� 9GS���[ `f�9C\��|fv�HM���,���`����b��Y�7�0K���Y̒�+�Y�7b0K�F�f���O�7��S�� �#H>�$��oɧ�A��F�|j��Y�7����Aj��� �h�F�Z��E��_��t�싥��o���o)��_� љ��@&�o��$������ ̦@H��� ������AB�lM�N���!�C&o��#�X�?� ��wX����y��۹8��11�B��N��������"��B*��B���B���Bh��vV%�#sB\���C���w1g��QC����������6 ��4r��G��?�r@��� �@������/�r����;�_B;g������a�����L�g�?����B<�+�U��T��@��� 1w��@~;@:��fv�p�1i�nv8@�u�B&�������A��H� �������KH$O��?���Qf��a��� �9�_����d���hg�lU�yW+�֍qoRp�rO+���kű����ښ����7")#�1�v%h~�_%y�:ik|֞�����h��:�ׁ�<�;4Ut"�0H�HĨ�~����[3�� �G�2���M���m@ʽa���x���~ ��c�,c�F�^@��3#1�;��ϛ9�ܩ�z$��1��^:[l�� ���lN�:��0?1�g��DSe�J?�ɆF}2#6Xl�B:pԑ����Mm������΄ƙ��P��٨�v�c�5p��>�"9�t<�zFU�t �v>Uf ��O�y��F��0�0u�k��`h��w��1���}�2�q��n���������))0B����S!�i(�r�(�i.?��i���P5拵�۲��WrV�u��=�h/��9'&A«���Q^m-9��/���fb3��d���cr��lj���'�٢Ƙ�� Ёv���5�@`QjD5ak��uɭ21�d�L�l8�i��i���L��Y���[�zu��\\��5��]+��7�i|��G� �k�z�X ]�@a�;Y�P�#> A�b���T�� �,������&�t�g����H������w����Ċi4g������>���A����1�p�+SUn�-G��0S�(�^�1�z3�o��Bl;t��3_���H+/�bQ�8;,>���ާ<eP���J��;��t�S�n��;��ߛ]�b7� �=�W #�;H��'��gpL���q ]��� i21t"��39��g6@��{>����g����s�P�ɷT�=bR�+�Z��-��������Җ������wNG'�����.8�.>`$PF�6T*���|�w�r�G��G�d&��������4�⋰�>q�UՋ �L3J��O��gV���\l��$��剠�:h����zip�$V���lO�#��V�4��oC�*@�[�ҧ��Z�>��'(_�n�("!�mc7��n��'l��dMqƚԾ�y�U�T�������|_u���E��V��J��"_`7GQ�\���l��k�v��rMI<�}�A��1�/<փ�� �N�m:pD���̽�����/��=|�%���|Ӗ&8�VOb lߌ�9���� �5 �ڪ���z6��\R0B,݊�"5�5R>��A�,*���[�O�JiN�����I�� z��@/� wO`��E@�AڷڠbZC��� �/-,/^�T.#�a0��||�]g�m����d6+�c]J���A!���� �� �eh��xxr[����Lfi8W�ۄ�{�O�����4C�w�ix K�L9 6�9��:8�H�.P�Ų�k%����Vt�`�-��k�c㷧�k��z\��k������Q��~��&�U����˲N�1߆/6?�VFbv�f�M�1���2`A�Z��GS���x�ˮ��NQ��Y<��nj�A�"�'y��@��_�uV�1�O�q��֊�qza�c��2-G��"����a��/�3U7NU�B�"Ol�-������V���q���=���Op`�.z��w��U�; �G]�</��{OUf��#4FĎ�R�� �~S��ER9�쒺���@�!���){Q�ŅH����{U��W�D7F2z���b�ٶ�tA�j�{9:�W�5ΰ�#��]�_���' � �tL�.�,�R�����O� 6�w�`>e�I���([]����\ϝ�f�B���_����"M���� p�(�CVG�t*i<�q�7JUX�/�&�Α�C�9�=������򺼌/��s5�}��I<���=e?E�"���1����W��:��ԟ-�ױ5���T�Y��ܤ�u��� ʀGq=��7j���*1� َf�R%�z��a)�+�8�!�iqp復5���2��x� ���C��i�)���Z��S=~=�%W��*r^�+�P!Z❦Bv���U�,��B�`F�{�D��8��r{82��4ye�MOc�O�:�&��>/���x��rfJl���;[��F���F�K��_n�� �jE�G��� �P;�V�����L c2�}σKR� =�M���oMG��e&�NaI�w��|p�����!���Z�wQ 8t��p��g�fWf���%�ȅP��v��� Ҽ5��cg����z]xYp�ɪ��E'�'� �JSq���$����A�Ա��~�:���쇡c���?9�+��G�'哨a�"M��)�Z�e��)V�&8��\͏������[��c�j����_���vSPR��w�MSy����/��5�C@��Fw�5[�&AB����l��%�_7�hЪE��W �%��+���0�+�#��U2���y�<@kۤ(F��7�lM�y񗬙�*Ve����[&�<�yh�IJ��R�F$ֳOc���:-� z[��ඡ/f dk�쾅5�7����}U�cv������[�T"Y�f���}�.����ت�����(^�4T��!�~|c�=��/?�^�z^��,��N/� O3�e5\jgص%^�H�o�Od�:4�<�~�ÛU�7�.��V<��\u�e�U� ��V��b�1ůr2´ �512�� ���Ը��1�j̲�Fe��M�%?�(;�W �J_�ɬ��:��`� ��%j�g/�?��~�3ç�"���H�}�� ̎ٻ�Ν����m� ��*R0|�|�� y$eĥ/ʸ��9iS��a� �|�W�gd���@q�(�M;!����7V �KT��d���)��l_�yWU��P� $��$�ڥ"v�j�_rR�n�"��=����Sӹ.�{^��MӮ��~�����`փ��4�����P J��M�,=�}�ݜ>M��*��%���Hxkm�+$ooW*w1�}=�P�M�A'�>��J�T��f�Yǵ������qh���XF᳟���W'��R>j��(��v(K��.��nYO5iP�������l�ے|d�6�DŦ�<�3� G��:9�0�vR�%�4��Y�g5/������$YL�い�� ^�s7�8� �+�i��'�֐2��7�A�-�Ƅ)c& �8u���#�N���~��� ���r������Υ��u?f���(/%� �1�s�7�� |�����[[���:�� m�࿵lyk�}��d'i8�ab�S1k>�lT��u g��-3�kF�7 �ST����s�NJ���f=Iןߵ��{�mΐ(��t��1NC��|�1Ő�q�� �m���=���(��Ih�)��Z �����02<��F��|�t�N�VI,e B(>劍�gѹ��?���^�X�BC;s�d�jB����Eh�A%�*=$�W��5��|nC��d|%�1��kV���=��Db����pk�}ΣP�1uL��y�˷;ްm�l���3K�:�U(1�����c���Ә|�@.�GEhyRP��'���{f/��>����K7�˻� G�50O�3�?;�͔ �ZN�{�� ���θ ��jyY,O���0G�d�[4���>�ʆy"�8�F.4��^��C,�h��̒�rуR�������TT��_� �2�H��H�?D�vV}�wZNF�2 \\ ��2�/��/�U�kߎ� B\7mW�6��[A ��@�"�r}e +�΢+<뚹���?Ww��M� ��U���S�U��qi�J����^Q[ �s����~���T�^Wn*��:����H�m���wm� �V ` 3[�RU)� ت�h5<�3�C�J _��0"�������) ���D�P/�0�X�z (Nޣ`6.إ4Qm �w����^f��bc�D��)���gg�6��P����� �J\d��ӿ,��5�!�!CǛ⩽�����U���S�Lb���x���DP2�_`�$}F�,ĝ���r�O/����� �`|�S��/��:��}�@JsST��x��C9����<��K蛂�Q��Ђ�4������P��Aն�nah/=��hތ/6�g�-�~r�"�G-,-�Ǹi����ha�Ϛ ���z��*���U{)�x�Ŀ��N��:}��o$�@� ���Y�P��1LGs�'&�$PR���P�s�n� ���A�.���=�>%$��8�z> ��T��q�sS.�g�[3��4[GPW��� ���`�x�����\�c�+�\΀s�q�� ��A(�愨P���}�n>�XT������a�.ۗ2����}�k��H�r�dw����L_��� ��H�(G���|D[Y�av�sa��;>�f��ට-��{��.��b� ���c��{l��k#�C���x���L0�Dl�����Lת�c�Ϻ�����B޷�o9���R�"a�3*���զ7�O�V%��&�9�)�a���H����C� �����^m`z�ۓ �3���#ks�)�f��.� 5��,&¹◕��~m�kM������C�yJ՜>,�f'+��<̺ �^�V��̍nE�����ODS�=�j��7a��mӖ����x����0<̵�Q)��z���+ H�h�'d��xԁy^�Q���P�7p��_���ʢ����+��G���I$ZZ�"�]���뻰�Uc&Wfi�^ �;��mj ϱ�Zi�=�FR-d,�k�u쐮;qJ]�X}�)٫,g�����+ mƱ��{g��J�۬�� �� �Bd���}x*�He84� ӻ�᲋I?��_�=l#���%���1��f�X��ޟ[[7# ���)�5W��H��OY�sd _1�X���<�]X�d���<��>Ԅ;��jI�� �(�hܤe �׸����mO��� �<���\���2����IA.�!t��}��;�d�|L0'��wTU�+M��P�oy�|道]�|�_K�4�H/H=0�s/����S���;��YJd9_��1���"�<�i�=E�����U��n��} ��'*��f����������Ш�����Z�~>�(|��x�2m�)OT�EZO�Nn�~+�!sl߇�N�WK���i�TK���ރ��q�km89��z�3��FG\ �20�H��� �[��m~&_�8q��5�@�O���n��W�'�A������mS>�� �M���du>���s�Gb�RX��7�]�����&mT�ْWo�����#���u�| Sl��q��#�6g�u�N�g\���#�o��l1:�O�sh蕈ِK���3��iO���"�PS�8�a��i�m2 tmpZ�'C���p�aI� |���j�q���e&����C�InVsu�O�4��-?�QV��״12�+� c/�7ǣj�ڛ�����Q=U6�BO�;-^�.ۄO˘���>�5�i�m�����&���I=�#T�Z��}�� '��Y�%4���6z�Зa�_w>^_��7|�)�*�5�)�,��@fL�2rR�<�y/ �1i�',Ǘg�$�|#�=���:S %r���O�`<���/�W=��<�q)�`�϶J�m>���Ⱥ�?��Sg:bR��d�:�j���h�x��D}|�(���S���Vuu����� ��PϺ�"���*�Ԗ2#(ßE���8_��.�ь�L��Xt�+�Ջ�L*T�s��Xl�}{� <ʊ��I "b��)Bp;�1�t�9�UyEݩ j(�&�"��Cw04�aXq���^����|;�>x�`���;(�m�^LcO��j'PP���Vb�.��TB�9,�����A�H�.�N� 'B��p��������9Ѩ@�ڇ��0] ϖNd������w��4M�ԗ����xxw$���ꃧ����a��?a�=+�mM?%�]���5G�J�(2�vG����ƿ�1�D�[��9�����RHy�YFY�t~L2�9�9�����76!������C��\���4�����*ɸT�X2��:����%���u�&ۘ߿(��)o�z�W�2��n���&�c� �h��<)�����%1: ��r=0x��/�q�.��4�h�����ij��.�X��6Tg�f���� HX����+����Hr6��V�) �T� ��_/X�l%���,������5�7􌻰�kl]��?���ߚ�h2����+�)���V�_Jd�u�H�@W��� �!_=�`�6���3�̠��5*�Ţ'Ē(�ԣAl@�?⡸x�cL@�-�Hk�@ ��[}�A���Iy鹑$���e{�3�|���Y�fl�8 �dž)���Ɂ���mOӂV���N�ܴ䢱2{�n�@$c�}U�z��Ӗ念 �����1��G) �%��* -)p�FŬ�Wz��t/:O�I� �����Z�E�,���tAA!ެ�GJ��a���0o�]�|Ĝ�qp(�c�G�@�D"�Y���|2�͢��K^X8��*�饭�+>)H��"R�k���cU����#-:�]�Y��N6+�Dc����C�<���$����x��D/�[B�� �XΝnrKwhl��j��(�$n����&�Ǵy&-����;��m� ��f���A�!�[����2G1��3nD<���WWA��&B�̫'��8��>U7��L�K�SkwPGM_�=xO�.=�z�i���������t��m�)`5��14c�1�lUHnC&����Ȑi6�o� ���E�����!�V̩����rsF�͆�P�.�p���bه��,NTҍD��b��f-K���'�Q� �A�˧a��-V����MWm[`%�� �OQd+�d=F�]���8+�����/�>��$'�w��C÷��B�;׊t$1�5t��|aQ�$٬� 񋌋��+���1�~%����� �FKW"��\�M��ym�+�� �vIŸia'����;��:�����=m�E�D����m��ԍ��JU�:*�����J" �V�E��8��oӿ����+ ���8o>�dY[y�]m�&����P�W��Woj1�OE�x��` *"��P���E�`�d����`^�y^�_0�s���fE�O��q&��'I J�;u5{PG�՛+I�Q�5g�ĥ��;�^ �p��#9M���a��A����(:��5���'��i�`)��ң�������(e0t�pU������k���T�Yg�>�ո��-���kAۛFb���Lݤ�Gd�}%�p*���p��Se'{l�����3&�Y��SFb_�a�=R�U���`X� 鼦���]�������i��wq��ׇ1-җ��[x�U|��u1�S(-"ٗ���:�ڊB?$q��UV ��%�eldL쮵����9&<�W�t����J�J�y}�F�g�]�����Rۋ��#���̇�k�4�ܫ �PfP�(��qP54�:��uwa�2�]�Ҡ`;O0A��A��4@z��8�� ���;�`o:�{��;5�=����K�������铠C*�#���^"�'|���R�:n|�Ę���$� ��� a~8?^+��T]� |�!['a����*<���!��2��У���\ KA>c��g| �C9w�z����A�� �h9�T�e]��9� �����$�&>U�a�Z��9oY�w��7`h��z��K�����_� �?��>�*���"YY�Y�0MY~]�!�uy0o��b��.� �ڿ���z���E�;㱤q,�T�b����i?��n3W<;�n�v(:B:�3��֞�c1���\�E��d ��o��mz�J�(%��j7� eG%n���3r����f')�~��R��g�qs�u;[����=)/[��`ҋL�[4�x���%*k�����"y����(�0 ��I�h�}�C�י�tf�����I`\b��v�hR����K3ͷ�9r�9�i�)Y�z�>w�>�>s� hZ~]���U57�eY�T ���F�C�D�t0�y��[6�yb� ܄����T�s�!UϦ8�v'��0t��U���� � m�=���{8��el�Y�g�(��z����_#���o^���(bu��8.5;Z*��F;7�>�^}�o��9sG��dŏf���~K�dM�j �i�N |�#���X�)z7�Q�ϏAۨ�x%�(d� _ '�2^ڮ`��#�f�X��HKʠ�&F9.v�|#�J����b"Y����������n�?����d��H�c꽐��?�^��k �!v^mu̺-onӗNG�#��!�Ҭ�8�xO+b%��lf7�J�D^�{U��S�Jc����j;zt��,T��LR��͈��rma1���bX��>}�D%A�.��G��G+<��ֆ7�}*�x�v����]��^8M ���K*f q��IT�L͍FuB.���ڿ8x$�#Sg@��je��&"��_�C���YI�91��'8�r�����_�h;s�GE�m�D�{��R7P> ��
*Y���$�a;�=V�5){���3L�ҍ]�ת�(k���`�JW5�|�珅i�FJc �U�����uX��Ff��Tݶ�u0P��d��w�M>��uqB8qd��Fh9�~���K��#���=��4*+���8����D�w._/����O tw�����΋�3�ev��ܔx���q*�J+]�zDx���E��E(O�5�R�#�:�2�W3�@^��a��I�K��a\ ��\�A�L�l�c�')�� f�\]�>��$���y����TY�q�3�S�jA��[�ˎ��!" R��ZE��,��&�[��~���*�˵��1Vv>�x"��>��.&�a,F����NQ?���;���qy���0�SY� "�� �$����;��g�,����;�Mé�����F� ��R7{(��mҡpؖ#��Z!��m�"�c ��9���Z��7����B%���1�W��v�^I��o���Ϯ������_�P��̊�󕬹׋�ao[�:���潁�0�|{�g���u��������RH�����`?|K��}� r`�\��tA�A/@�:#�zI�p�b�J�9Hĝ'���z�F�6�#ֽ�̫��)�*Iu��C-�r��������m����1̲b\BS������ �w��(�oK7�p�Ӎ��"��z)P�!w��.'c��d�U���t��S�\�[�o�ގW�6�|b��:+���e��^ȏ�I��̮ȖPm�+�%�3]�kV�x��Hh~I8b^!t�{�py���q��~��,�jʒ+$-���a����"`=|�כ[��= #��qC���~�E�y���Y*�z�R\��6K �(��8M5/$�DSZ}Wx��/�H�<�X�Q�L;�{���N��nG�H��m��`��O_�a�/n�ȕ�>����s��&�hw��~�3��H%�+��$������cQ�g[�K6�;wtgM�T��my65-z%����VK� ��cr���4qP`i���Z��*r�+��/��(�x�J��ȟ^ a"{�����<�c|�D��������g����0��SRS:��y\���tQ�ǽ���N�j"�qz���5��UzǬw�QV������XC�'�ũUg��BsO9~��Tj�& ��^�M���7�!�oG�h$��:L����B�C�5��w����?�]"�2�ݿnO0z)$���L^u�f��I6rbj�?i� 3���r� e���/'^4u��|����"� ';ϙ��V���fU�E��7�E �ò DgZOdhV�D��i����1��Q���߇� 7�AHsƗ��@[q�w�����V�p� R�q�o��8gg�tp�{�4Y�x��:tÈșXTp�j1���h$�=f�5^�X-�ܢ��%�/�#hir˛ ß���$�cD ~ �e�<B�$�]����� �Q�� X�o��u ;43�oR_�L�S]j�O:�آ�J��+F.����}�f���}�28�Hn���+��$��ɸ* ��°�I�TtWI F�ܝ(�{���*����Ö@��6,54���m�y�bP� �^�.�G�I֟�C�?��ݕ�*�H�2��.�"TQ���?es�4›��[�����y���n�>���,�� ���h�˝����om[�Q/IrÝ�壨 nm���&Lx�]ʂ˰�*d$��0��7�|��B$k�Y�١��I5����I�J���׎~!fֵ��;h8Ł��B�:>¸Y�EFq_�q!M�x�l/�-7?��[D�|���>����r�b� ��N�Kg����E�L8C����W�?Or�)?&�u}uoO?jm��� �#�R�*�*��[H�K&���0��t�@_+U���T e������qG;wE�J�w��)���"�P��9�#~4XX�^�� d� S��(,b���s�L?S�g٦^��خ�F(�!뽄��^�����cٍ�^����o2�Cd��GF&v�c����b�ِ;��<�|�d�/�(�.!����XZ���-f`�����@��mN��� E�b.��eY�S�;������� Ɨ9��_�l����_�%�/�.��h�P7�8�/>��D��A�]W����ş����@�@t�I��7@���� ������Px�z�2S�ٴܘb ٖ�����涙}U%U�~�xQ��%q�ݠ. |�AW�㚝`�d�˟o��z�lH�`��DI���A�RBZH���j�1�oj6BI�g^����$��}{�yTW��ݰ�t9�����rA�ܐ� �L}�C�(wB]σ���<�֊��Wh��(f�qDe e(�� �3�䍏dk�{���ʖc;B|�)���|@�C�o�zV��O �sc���Ug�T� �G-��@z��m�%̛�-��}xDP]��9�\]���W�+a\�c��+����W蚥Q`�++������7A�S�����93� Њ5�|'�N������y���W#��Я6���#DZ�΄n�1��q:fO�!)�m�����$�c;��릙�x�3ν��w��l΍ea�Ț0���o���#f�u+�p���_iI��$\��H&�՘��M�|���iOOI�7[WY}���G� �IϠ;���]Ƶ���bp�6#[��ʾ��W���Д�f^ w�S��,*�bJ _�e�l�nf8�ʃ�å���x}X+���$Y���T�*Z�ҧ�M����/� ̤s$a �Ps�O>Ij �Di̇����)͋c�Z6:$[zU�����^s3N�1��R���wzž��>��3q�T� ��K{�0����MF4���P��ܴ`[�/�ɹY|���� ����`�i1NK��z�'�^۟�&%�|�����O+�����Q����Y�����S��lU��Rs��L��6��왍� �to����Z�c��t`��!����˚��~����E���쪑�))t4A�f3غ�E�Cu]�a�-�b�sM�����X|���f�q V1�侎��/�u��>�3�UcQ�6A ��4�/��_��}h�@�Y�|��Df�RF�j�X���$z%��0��-�@9M�pַ ��t~��rIA5�l;AQ�|�t]o��1�c���f>�S~ā�y<-���j��%���`���F��V9VݷG�T�� �m>���,4���:����4�� ln�~�P�I�,K�U�z])���� ����i��Q6UEsR�~��}ZvJ�$.w1���r�/3�^]az��}�\�TR�1j���qK�����Q�9�y�Is.m|�Z9��<� �Y|�O��5v���@�����t;2~���ޒ������p��z�JZ7���5�z� Ē!�S�o�� �>�l�EFӦ�`Ħ䍕n���r�|{F���R7�V1����MO�&~I��Ix�g(�F�R0���l=��t�)��'�D�b�'�Z�� ��<���0������������ɭ ���PyHj{D�}v��q�HsLl��h� ý���d����0�9��6�Rew���T�n&„�Uu�f.��5��^m���_\V�cjz�\\�!�]��~r�4�1*ݢ�be NS����ēz* ��������,z,uKݯ7b�g�l �a�sb���+�U4P�e���#ծ9Sɝ�H�c���?�� {�i���6}�����?Z�g~z�(Q�f1�Y`h2p��b/xHդOy"b��^��?�d��Y� �Vr���ǡ���bF�l�F{5Y[w��*�9���"^�� >,�l�6��;��� �����7�D�Eno����:�����v�vK2��Û�2��5}ډ����8�!:��#��4��7^W� ���18=���������V>��1������}"��Q���{�/���,�/�� Jʮ|۠�П�e� �ZT!$8��YE��p��XM$<�?e���Gcb�P��� �v�t��7� �6*���v@~�=�X��'5v������j�.a����7�%N����o� ���q=:�t���,���q i��+�]���J&��u��n�"�q�F�/�5����&�[�F�j�8nT�@*'���;����q18����l7��He������Sq��9��/�V�9�[av�PV:��50�?2�-��k�]����P|��U4��I9E$�4�<0�8_ �$˰�{P���3 �A) ^�`�/Cd�[Z(j1@��4e'Q����T%��2�k����g�1X��ףW�b5cZC�xI���G�hL�g#�>�j�4�� �|�����q��ƫ���*,*��"�NF�H�r�Tqjl��M��x�3?�������峀�v��#�� �!� x�R3/��|�&��S^����Z�n�Y-9i��m�ي�:A��Ptm��� ��Շ��U �O&. ����OiB>6���h�BO�%S�0{�'�-+�bd��ʖőb�лŕL'��'A��ᄘZA2i�؜o =�xޚ���;�<����q/��y7�%%5_�o�Ylؓ��tهo�Y�������c�����>]�n�g��Z �<�u��[�0�~�?���|� 5��q�/��%c3gdl�� �"w������:Jy;���?���ީ�wy7�]��Ѷ2�b=Z������$Q��?� ��\��&ln�=Hg��k ^�Uc�R��h��Z���CV��m$J5>�LY�dfS���nt�51�@`���ߔ��r�d��D��*I-������r�ӭi����+a�� 5FV�՚�fN��_c��CT6��]�q����7�����H��*'\7�󁛚����Z��D���B�V���� ��6@�{F2�� �@oOb�OLC`��s ��?�VR��9#�61�_�'��-_�h�_� �����[�R�sqC����@�k������d4bw�Q(d!^"�qZt��v ��tWFo��M�hM�B��ֹ�e�)��p 5^�(���sd��d��������2I�eWv1�w�}�A.�Zl�>ޛ&�5�b�<���岡�6��Dͽs$EO�a��9ֲX���/���$@歎q����B����=��%p����$���j;z 9G�ݢ�ސFm�$��8�N(�!qi\=��4��Z�dF�k�B 4���R=��O�K�8�� ���l��IS$b�p��y�Vj��m4��������'�V,,���U-kI��œ�f%��r�� =E �`� ��:�C~ԧ��^y����] �%›�)Z :��UiB���b�&I���W=� A��O#F� �wT �7r{dR {[N+�Q���_Q> ��8ׁj��7Ռ���nzaK�!�SZ�m�3}c�h]l�]3��h�y�q\n�)N�~W/�j�ʡu&�X��W�W ��k@�hv���r�_��s�wp�� �|.Km�KE��.1��{ /۲�F�%I��&� ��pb��]S��y��A_��Le�79�4hRe�Kn����Ō kE~y�K)��<���N�����v�%"C�i��4��y����&��{�'�?Y�F���_��RS����dZ4�M��?�s"�|o��Fd�E�|��.e�'�� � xx��j�x*ڂ@įy䵖B�Œ� ��A���ڠ�z����,��vg��� �^8���܂��R��A/ ��x3��9P�q+.���3�Y��gz��r:���c���=I`��ڋ�I}D�4=̡� ��[�����q��{�����b����V��u�d�H�;���f2v� |o\RiX�����K��mں6.���^t�#�J�E;�<���T�0JZ����u{�)�!���}w�AZ�[8�W� ��{���h�f��Ȟ�������oӣ4=3�X�Džtʀ�G�c�7�`%�䖬�ªo]�m�f��x�\Ë�K8�Hv ���|t&�%G���W�Q��D�<�c��ut���]��m)��1�E���Vw�K�"�)J3�; �',�= k 8����vK!@�m����a��r44�V�=\�#�)��㵿�w��v�q`����Lq���(���%#�:�u��-A��V�-Ga6��2fB�C|� ���JS���jm?hs���#�$�����C��1�[֍OT�P���$�l�9�C=N*�� �^Tn�+Cl�PzP�a��ͦ��(.�8p؁�[�D�a�����!= 6��-b�� @c3*u�˄9�Q�jM��#a��IV��� |�G��=�=����)��_ �\F �M���_�%�CL B/+X9����!��;?�;�#��XW��5}�r�Q�&�� [�>���O��c�X�������L���m�0���(f���yCK��Cq1�&�\\�%�U���t�bj��t�ՊKȠ�(v|$���~�u�����i�kwu6�N�8����y�-��HJI�j{&��~��|�Y���X� ��(�3���-�� ��iϝH�Q��uʧ* W ڟjz�̩L�����x7�Wc0b�\O�-�t 9�'gv0�)J�� B�� %m���Ո����&!̅A.��{����a:q'e�P�v���Ch�'D��׺�U\6p %�R(��J��=Q��ffњ�f��FYK���<oT��B�Vq endstream endobj 1598 0 obj << /Length1 1398 /Length2 5888 /Length3 0 /Length 6843 /Filter /FlateDecode >> stream xڍwT��6�� RD�JD`�Ih"��^U@I�P���� �)�7�*��(U@��t�"EE�E�u�s�����]Y+yg���3���}��DH ������8!�0H����A 1aH��m���������,���� �t���B��]�`1 XR|K��@���0�@U��j��p,�[��� q�<��P> ���[��܁J�p  A� 8G�+!#�4AAp��?B��:�phiOOOa�+V�q��z"p�@c8��À�-�!��?� �����o� �� ����  Gb .�H$d�h� �p�o��o� ���������}��� �BQ�h��t�#\�@u]a�NA�΁,��� \ v���!@u%# �����P �� c.�=���!\���ru�#qX�y}� J�wo�?�uF�<�>K�$��� �;Z� �ps�k���T���8�Hꖘ���{AE��z�ῌ�s5�?4 �'��C�� ?,��a��~>�i����0��; ��G'����e��1/�%�@?0t���ɚ�0 ���o�����ik� �i�_Fee��GHL($*�A�R�[���?�B��_-�= x�^�E�]�����>�?��ԅy��t+�J��������G��(�+���"uw�_v�߀��qE�x�A��#���� ���Z���pw�o�BX%���B`qa��o=����� 8��o��֛�/�  7Da���_6–A� �,���M,a�p�y.� K��:ԐP�|�D%$� � � I}��5���~�("�D�.@B�~@{p>h )��0�\�Gl�;CH����˿���C�(�L�Sup�A�����,�f��Q�����.�a��x���I�g��`��Nm��nٳ�}�j8j����8�W8�b���.�&��q��4=�HV�.]��"2d��m�T�9t�p���U��1����D��vH�~k{eI�.#�m�/��qMv���;L�|r}�m���Ω#�z�������띦�d���p�;W(�NM��MU���|:��Ϝb��tz;�+����s|���[�K[�7x�o9�&�G������� ʩ����H�TvIC�|�>ּ# ��z����vX����h���Ow�-�w����z�r��K_��_�x؇7�U�L��&��ɷ�g����5��2j!j)���b*_4};�9����"���H���»{>x�Ӽ��Ve�I��(d }4~�f�7����&X�M-4�*Z�麰�[�`���*�+÷�J|��@�(% ��~���$��Y6���{��8FT����h'��m7��H �Q}��?� N�еx�g�Wė�${򺨈�'�~�7�h��*�N���Ǜ�z}Z����o�-� ܗ��%.(�8� ]��}D����7h-�qt���NSN�H���K-%r�·�~���s`e�Δ��a�j�qfw����]�ͼ`��a?y��'�Wf������5�=u�A_pb�&Lt��3Z�Eو������w������I�[��V���9�\&k۵6ej?��ڶ:��=�{�y7hj�rJ�^}�����J�#�ICH�?z������} �x����"�7_�^EoϷ����+j����qI��|�z�2�CM�a��=~�+x?�.>�;���B�"n�L��~��~��{��)04I7r��E]�h��z��<���K����f͑%�����+�t��H�c��%�u`z*팋���t<�z''#K���t ��F}� L�cg�r�Ş,����2��� ���v@ߝ�ۋ}E�G������L.՚�~�E}3�LY��]π7mD�(#�W��^11zm����[�����y+`� 8��k1W�H��`�8"p!�����g����PdaO|�Ln��-&텇�T��}�W�:U�V;�Fx^�c��������~Vx��Ze�$����2��Z�_,��SQ?� �7�J����S"Œ����-g����S�o��w�e?iލ����A��_���Wg�� �:�����N����SAcg�3Ւ>�x���a��\�������p�ѳ�jJޢ�2���F�f�*h�շ�2*D��k<ꖼQ���!���E �L1�ȯ�-�6;�!�t����KrJ�A3�q1�"��<��� �֍}� ��ӽk~���;ٖ �'Fy�Q���w��uc[���ę�T�e,��\�L5�z�ç��p�����ә��1�A_k`�u�� +�)pF��'�%Qc� �X*,r�X�gH���;u|"WQk��Gb���^n��ހjO�����"5��GSvI� ?�Vy����;�K�ʯ6y�Jb�]LJ��Мm��P����!�G/�3$$ג?=`�Z@���^��ҞY�X��Ql������r��g����mVB�nD3_����h�a��b�؍$���2�����J8�aڗ3��38��(�3�&�t��<3F]C�����k�*�+&z{c��1�I���t���×/-����tӢ#Ku]j5�kk�w+�F�z�\�@d�)�ڤn����(Y[���9��n/�G&FWc��+��ږL����$���K�|�f>���R��x�f"H�~�DA�=�4�5����pQ�B�;܋\�M�X�o_V)ۙ��*�3ǚ2܎�Rk".�0p�LMS���^a� �$��Ia�/8yM+2Z�@���*��a+s^����mF ���mw���ܹ�����=�z��j����7g����([���f �Z�˻��L�1���dUOǛ,H�С���dyA��J����zK��h(i��c�� �$U�̼{�-ǶSr/�Ȍ�:}��: �w6�D?~���ر�� ynK��6��9��i@C�q�gU�jP0��|9�mR֢���(+E��i��1�� ���/�W�f2�BjC,�! ��v�f�$�*�~�Ml��E��M��p�� ���,c-�����pP��܊Z�bEs����yLM�t/��|)|u�p`�fT�b�cχ'�~��kB?����X[��_lv��I�Q��&�"B�����Lc���y�˷�YG+ [� {��R� \��[���ĮT��׎�n.n��r>?�h�j�u:�#�QH�9��WbiX�.�J�Z���h�����Vpi���2�/���܀S�O� ���>������Ɇ&%L�8�,�̑� %�2s�?~�M���PJ��.=��f��A��H���5�$`�U�Ƴ��fPR�IŐ���K��#7�d.=x�U{���Ȟs�R�A�{^\m������<�L��uB Ɵ�O3�"B���c{UR��- �GM��oX�i��ns����`���o���=�u�����䀗ʬ�_��.���k���R)� f�K��1^��H�gn��+�'�ю�?;�_�����ʜƊ��~;U��X�S�'㳻k�$��6�=���b���Q�y�V��Nؼ�+-G5�����B�xk �4�ݏ�������3��7� �.���wYRV����'�MfƁ��$��7�����o�B�}[��暿��]�����x�|ԡ������%RM�`�����9�� ed���sד��n�1_:��Z�r�D� ��<�ƾ��w�=�:��)�C�*���������[��!箶m���B���*+S�T���p47��|(�e`ϫ�;V�u�Hx�o� ����C/:�xkL��}�܅��J�L�m�C��[���L[�>�5Kg5T��E�x N��Au?&u�2�U:[C�39��3��֌ ���|��(%��h�q�X+�Ƨ�fOJ݂H���ms1���JTe fR�=]�X~4��!�Zឋs��"�H`{@�8.�!��.��1x�����U���:�A7�K�,Dg'�դ[=����ՠ�T 9�rZ�k��=���$��3�ڜ�_�%�����t,�IѬ�ɼ�3�%����jb�.��ڸX(�v�����[g��T]F��Y������[��(G�옊`�N�8*6�:��[z�k��\J�]�;�t�?�s�������U��֊�������$���39;�&�G��T|g;�VY���=�Te���7� 2N �%��_�ivM�}ݫR��tS�U-���(�t)Fq=v�ʆ��9r��,ݤĤq8�+�R�}�y�d�v�I�9M�9L��e�3.jL=x����e�A�VsE8�.�U\��+J�����N��p���{��cW��z�%�n��P(�/����z��u�9��˴�I8�d��|9����.ҨI�E6+]rg �')���C����XQ-xߧ��~�܌�����'�aNʓ�R ! ���UI_�űY>��VM�h#w�(��o9K���Ӳ��)�@@ ��n�K!a�,S4�X��"ϊ��˯��F�����'�D��X�����w�o�oj��90��a{` ��L/�L9�I���`��5U��-з�ݼ��e{�/xQ��ez�_������n�7<4mt��������o�nz�C�� ��A9�*�6��������'s�&�lxE��+T ե��Skz�.�޿���8�U��%��ha�������誹ȶu�F ~��@�[ϥ����L��nsIz-�q�����e���qCѫ\�<^��3�e~F9_\4� t8D�riج�}��5o�$*�'�?���x����"T�1UsH����-�~^+%�U{�p������#Ywq���&aP���⤉��%�������Ųv�Th4��av�gja`�6�]\����+��3ݏGw�sK��t4l��jn��v�EA���=d-[StjZ�~��^����fZ���P3�����#mq7��%-���N&F�C�A�x,6f��D_Z�I>�_׊�(�f��F���'Q� ���ԋ�=�|����O{�xJ���_�uN+�3s�0�j?oՠj�O�޳�*� �����2]���Z� d��+_�?xD9\�WT"ܱeu��WKX�����a���C>�OS��z��x��'H0%��/� ~Ƞ7W� g����Uxk��WB=�p:6��h�n?9G�$9%j����J ���tn�[���(k���:�b�\�a�1�=R�Z߭մ)y x�e��+,�t�;c"�[��d4�i���m���35�D�cF��5�A����H���%DQtD!�|�� �� =����Nݔ#��0z�#�qЦ��-/�/��h�rC�~6����~;��G5ֺF��M��z��I���B��g#�WOU�˙i.&?�p�����g6���сJV-L�t��8�<\�]�p�_����Ĭ�o��s��&,y��x���VF� �G���ͼ/ ��9X���h�%�k����������?R+���3y������5�;����)��y���0\�A����=)d��-�*��D/�Rd�L�}T1��6����S�I�"w����V$A�v��3�/�QQ������ |� � �嚟\��8Ҋ��A��+}�h�����Pnչ�[�|2}u�^c(h��>�H�\�I-u�f�f[`�9��£x���UCαw�6z5tz0#K��iֲ����x̯�0��H���3������8M�xmL}���Gv endstream endobj 1600 0 obj << /Length1 1398 /Length2 5888 /Length3 0 /Length 6843 /Filter /FlateDecode >> stream xڍuT���6("LAB�a��0��$�[����ml�A�D@�;%���$DAB:D���3���~�{�����}?�}�����;NV=C~E(���F��AB������ a�������0�������mp>�a�H4J�!�c``ަ ���hP���ĥA�BB@a!!���h�4P삄��h ༏vt� ���ߏ@.7$%%��+��� !`P�C��!`{�!�������K��9J ��� ��h \����!�0, ��� �;���&�!���C�-����{$���C�QP��4T��:�P��Z�|�?� ����O��DHԯ`0�vp�ܑ(8�i�j ��p|@0 ��Ǣ��`0�l��j TU����� � qX,��猂?��Y��vp��pX����������vEy�}�E���?ǀ:; ��N�0u�?� �� �ń$%D$Ł0' � ��Y����� �i�����v��ǀy#ma��'��0�0o����� �Hh�#Q����0��g��1H7���~ �����,� ��Q�����XPMOQ�Ȕ����q*)�݀��" ���$$,��?x�;����b�Q�h|��~��w�.H��G!��'�A� r��t !1!� ����_!�7�����d�w��lo�������H{�?�x,"� ����-��*;�j��\?�3Hs4~e�g��Zk��4v/Diў�����vI� f�&Y���wT<��kG�j�DY������� ic��x� G�_� + �Ʀ�m�1��g��j� 0����D�xQ��t_���T�ո�8���(/A�Z��(iF�5�,]����= '�u%��/ �&5 ��d�� ��Uy���6���F��O�l�2:T �-_�������ܛ� 7��"�B��Ppg�t�<�xGB�����e�R�I�GЕn�l��x%l�_l��q� Շ_�Y�o���z.�Z���\f@���n"1���b+;�4I�j�!#�] .�te& �<������2�?ċB�\�I�Tj��#����$�>嗚 7 4U[��\ݦRO�i�͌%��Z�z��ZT9u��+�^�Br�4)�O�=�_��?���LfԢ��]��c�#U�F ���f���}��d��?������f�|�/s/��s��U{@�R�cs�+a�U:��h�;�����\�,iX ��R�R�l%�ux�1d���"�%q�Mꒆ�|�KYf�f�$�e�7�Q�k.a+;z�� ��TL���;����߮Q��V�z<���D�,2��N�|��N���s=�:l�4�`Pxo-W���b�.�;�h��i�+�>� ?ɅŶ��Sp.��wn�C�e`a�P���J�^!�M$��S��|{���1��K� ����g���wY2��\ �=���̀|��0�Be��������= �~BFǤY �0GF���B�џ���ŖLUT�}N^4�\aAT|����~����4�0�l�3�З�N�e� �n���]/a& ,��^/+�z`[,�;�����_`Dy鲅]s��p�'�J��������Uf����Ԃ)�Ʊ���'�o�P��^&!���`#�q�NOMUyI�+PNq����a�hN�23�A���g�c߭�]�'�>)�ҧ:�M��sͣc`�D%�Lu��%K��:�Z�$n���D� �N��=��^�$c�U�E�� ^q���6Ǝ�]�������9k-�!� �>i�V�@��ے ���U�9](W����R�(o�|@"Δ������9K�̼k�7׾�L��8�>׏�a<�Pb9^{��T�s���^� �VWs[�1�M��M���ؽ|��:���`� @n]�z�(��8�"u��Ƀ�:�L7Hk��1W��^V����a�X �Bּeف�3ň�ВS�(�T:U��O�>y�����i0B�ڍ OEg�Kׁ�T�S�$�<� .���~��us��%Uc���ݝ�1Uѵ�����_���t� J�,j� �]���⃒���p�����7�j]�@���b�pT�E�FN_�t�$�`� ���g�a���I���� ��7r׍0�o�ܸe��a�A�5��YyP��A�})�~�i���w6�s����|_+��3�<�||/Z�.�� �!3����t�d#�d=�?�pKTXX�-���G5�L�7v�p�*rP�٩���N���Y� ┪ů�jvONF)���_�p�!*&|U����a\�[QV oτ�E�\���xA���GrUv�����B=t+�bŭ����H�v��D�f�hc_,!B���������=�e�>�d�j?��nW�ɻ�\��Z���Kk��"����g�%�w �f[0��^ň�|�Su_? (�51�zkE���W����a|f �m-�8R� Jڴ����R3á����D������b�[.���ʖ�E�?h��koA�Xc\��fV����^�,���Ztm^q�MY��{�籨|#���� $��� ��*��߭�SR3�a��20�O���h��{n7�}���Ѩ��D$��q$����)�Ԃ���;G/��9 ���R�ڻ^���� ��*��}<�9��[f�sL��^`-iw�mf��,'<@���{�� ��+����V�v���F�,�(�*Cd�g�),��V�c�W��� 8>��S�) �G�p`V�O*�>&%O�mot� g_�ra:#�2��"Ɨ�� 9���7��c��K��T��ܣ��qa���^�<�k�%��u�mߤ5�z�Cv� �MN� �a���᏿�� ny@������ ��>�=�{����r�Û� �� i�P���J�6F[���Z��իb&�WU=����B�}k--_�=� .�H�F����,`ZzWM<�Y�w�ܵu�Dx��=@5�3�6S�S�qvd�S�K����O��3#|��VH^񁖫.�kk]P�wG���@�j���@I ����:��rg��� /�,�Ox��������M���x���1A@л�8՜�3GvcыV;:4{��f��y�H�p�Q=�Vũ��\�m�Y� peM��2�48#�d6��c-6R���*�����R�%i�sՉ�G�<,�L�/�j��Q�� ��&հ.���B?vF�5��l� ��>�WK��'�bV[�������IK_ic�a�9 ��,Jh�~���$�����3^Õ����h֧�}����������R�Y(��3q��]Laբ�0:�w���R]@g �D��ŭ37AZ�hx*�l�?�T�� �"Q\]�|!�hΖ��kA�ҍ��M$�����C$Q�>���A�%�~�bv�s�#�>��bR_�����7T̿x�EǾ�6 tk@Ԉ�1:c�m$i�9M���U}��-���@�3���?���n��x�{���W�8M ���H�4��,��� �CY<V('�^�u�}��gw2���Ml�T���>�8���=z�����]0�l�F�ڒZR)���-��g��B(V�6�n��e��-�1��N����L�{c#��lc��^��� �o�g�e�ծ~�Й;�d�<ܩ�f�p/#°�y=�܇Kr�ɝ�e�#�c�MZ�_�)Gb��NrZ��x�Y�r@zNM�_��L����*�o\�/i�Pa T+L,�i�N�Uuz6�~ ��,כX_�*�YU�-\&,��X9u{Ջ���Yt�a�)��L|��@!��v3�~�4�Y];�-�=�TL�ڿ ȭ~)�&{%�m}܄4d����Ts��������*�˶�A����[�B=ǯ$�� AO��N��wew\r�m_v?��=����yyU�?3o�$��j�H��I��6�#�d�4d�]+�$���?R}O���е`;��� �ԓN��p)},�츅�����U�G��߃N�i���N3��T���W�$�]5�Yj�c���i�j�|ahZ�蟅��9 l������H&n&H� }� �Mx���Hz��Rk��^i>�p?�����q�u ��y*~=���/��U��ѻ��2_��R�����˘a��G��쬶M����F�6/OnK�?}" Q����|N�eiG4�OپA��S�UxtI^¶5fh�"�s7������*=�|�fJ AȸJ(�/BOrg�h ���5���5Ɍ�jބ������I>���e��,����<�60�)_��aU�.�K/��v=�P���X�1,4���2z�3>o�����$@�*~��K�7}2�Sx�P�8�ý���5��ɝmh1�>mǫ�ܖ�_�g�y�$�Y�_��o(�hJ/���ȼ�=�ʢ�� S ^��Y(�N6oY~�qZ��Z��+"��׊ ;"]Pn�)���l��P��֒I�6�d��j�g���Ǽ`�̜Yߒ�9�e��!��1�����7� �� ��x��A?�P��U�+�ٍ���D�v�/G����?߰?�_�j�_�율��u++<�3� ϕ-'�2ᡟE/�ʌ�TD���3mc* �&|T�-Hyt(u��1�� �6������~L�nY!O�$�q�׹�Z����}n��g�y�d���j��DLK~�d�K��$ߘ���ݙP�� +�sX��I��L��|����9��*���_����t��tV5�<�Iç�l vڭ�� �^3�}<�5�˲�¦� �m! +*�|i#y4̴�~�RP�y'щ�$���1 ���-O�������.:5�ۺ%lM�'ĥ��9E' ���BJW%ej��;�� C/�(__��x����tE�o���i��m�j�z(���R���r��}2������&md��E�/�d���Q <�ê/=�&|�¾k� xp�mT��X�ORc���"�|��$��ܧk�ځ�{��/�:��u�֊���n]^{���� �=�Td~@� $1˙jR�)\u�.�8�Q�k �k������'�*ES��#�\�W�� ���{��b�� ��.�4+ &���6w�j��> stream xڍtT���.��� C "0��twH��0  13C HKJ*��t�t#�t� )�������{׺w�Z�|{�g�w�w?������+g ��(�a(^>�@AKKM ���$P�#䯛���@B�0��P@@@(�O����0���#@@ �PB@T����E����P�� H��'jk���W� ..��w:@� ���A0�eqœ9��`(���\�v(��?���;� �G�Js?�CQv��$���� r������``E����mP� �q8B��� �� ���j�g�X�������]�o��BP��d wr�<�0[� ��Q��Cy�@0�_@�#������ + �w� ������xH0�B�!���F��Us�J0k���B���O���1����g�0�;��a�Y����ՙ�uq��)��`\$���BP�����0��x����7�t�� �rc&��r�;l0C@|�6���������E" ���Q+�-F��7�揍Y>�0b�'�����C/k8���?������S�4P��3�c��p���8�WP��D1/>�,� ��m��\5� ��]�=��e�� ���n�?�i�1�����r3��y�s�w���⿪��X�� )�::�s���a����/�ZWFZp�`� }��Z-�5��鿣j(F r0[ �y�����P�2�b� E���p�����0�. ��q�d��� ��� 1��!1jC�^�/���?�P���ֿ�'(�B @�$��c,��F���������(L 3��� ��f1�3f7p�_~���"��Ss��� �@< `�� 8�Q�}EP�I��;�ڐ$�^҉� �P�3"T�҈�r�~zڌF��t���3�my������^�J�*O�#^f� [f����#�x�cF� �:��' �L]X�w#n��X�v�sPx߫蘊w��SUn�nn-�KӤe7�Yy����5X�Aw/s�):p5�,,Q;�UC���$ν��RO_�e�ݶu���}��(J�G���„�Fs��/2?�m�PyY�ܒݶ�*\�N8��>�Cn���w�̨��$���T�{���';[�=�l�(�@�!0�"���QJ?`u�2�/X^HC� �բ�#f�"���.o� �ywU\ ���@���4�eڟvA�Se|�[)\���������'F3wb�qd�N��F}�֠�5�,��(�#�N�Ul��`vk,m�ь�H�0Z��ݻ�_0+>�ʬ�N�����@P��ف'oo��RWH�Ͳh��E�'B� yߘ�k����붲j����r��������ճ����8L�o��6e7:���=)��h���rh�ԧ'��0, ��7�͔�a�q��ݶQ.�:��2*��H����%�A� y�o��E�Vd+x��E�G �����I�ve� �lyE���i��s蒥ƍ��8D'�nLv>�9���QPFF}��B���I� =��`��b�[����U�|����(?L�J��P=T����tM �)��0�y �y7{��K�j��n����yzC��P���fE�g NC �)���vFϕ�Q�;݅��[��� �=M������� ԛN���9�vy��"�V��`̖�#�,Z&����8E�������}�冷QO�� -��V�E\�����ȮX��{���8ͪ��7��M���S�g���t�ǡd ��(�5�����&twm�x� ���X�'+�JɣC �d�����Y�;�ƹm@F��!7 w��y��)Fy~���� �d!��$gd��NZ��XP�W܏؞B���LƷ�S�y�:���Dvj����q��c�/I/}�D��`wֱc���$��;=�X7���\]�8��%A�t|� �>;�5m Q����??-z����+}�R�*�^pzmx�̳����!��xE�V�m�2ӊR���5h���Z���`��]���0����C8�B�XK���w����SP=�ͣ�6�B�R���O�LV�Y�E�nkD �����z��>��rLIs�T�KX��� i|O�XI�z�&lC��ڷ�g��X�Oʂ��g�'[C��C�s& w��?a��I�ܧ ��� W�EM�:���&���4���9R#;�~�W�I8aF��� ��J�*��סs�n��cij�?UK�C�Jn���;�.����ѭ� ���w�ga�˕Y��w.�$��{enj��+��ɣgnMȖ �7�6\*=*�A��k�y�_�c�KӟG|���#p�*GpiK�/p�IB6˾&������g�7q1�� ���̗�~�z\��| ;�$.�ĵ2T��X����l�+Tk��6K ʉ��ظI�#�P�7m\���<��x.|~I "�y��` �ϼ8�� ��+G9�,KN�)�1���&D�f }��~p1���.��缒1����B�� =e�l���lm���oώ�^N�xn��� <:.���z�/�� ����V R�����)�Y0���������Z�*��˯��y%�̈�����M���3��lW+*)F ��c=�V�f=�[0���uo)c|qe,X5.��ϞL+�KA��Wϖ�xw��m�8 �5����s7.�q,�Z�ո� 4�@OUl���!c���'aI���ۂ�8��POe�D*3%�A;�����g��iM޺GI5''xҌx�#����Ď�}�-�^�?dQ#��%x,x:��dJ,{�4� ��V#J��9-u�g$h7��Û,l�Y������<�n$g�@��Wd|����W-\�P�:; b:8W��~�ycO�L�m����A����ߢ�=>*�˝'![0@OS�@y���L�g�J^u�B�t��|P_=B�M6ơ�:FO{%s�Q��1����݋1�U�3׃��C]��%��yT�R~S��˩�|�بj��Ewߜx�A�"���F���N��X�JU��,)1�s�9 �����K( c�dB���Mo[�U� &6,?�Pq�khp�n�u�Wo�6����2�m0�z����0�E�t�(8�M�f��K7�5�s��Y� |{������P+���ڴ��ƂN�u� �&՗�v� U����i�2���7���qd{s�/�^�W�� 侲O�,�jgaLX~)�2e$`yL��;o�X/*ŦnZ�T,������_��"F[��|8W&4D�I��a�3�S�z���.4�nr2�c�x'��oٝ¿�r�<�:q���+�.h$��8�*��T7�؜|+�R<_ �00�o�Į�?*-�z�vSm��ȃ�1^�tS�tw"�V?�H����_ϔ��s�_ &?�Y��S��L�� ��9ڇ�;�R�P)39� JH&�������l7_y_�=t��K -Ȓ,�u~k��p�S��h��RWk5������!)�F���m���_p�ʩ�m��T��H�X]���o�Q(`�ŝ�l?��I�~� H/��L�Y��� �0��͓O��C�<��v����x�R����"AF��RS��#��Z��`����8�H��H���=~�tQ���b��!9����B��]������� � E�5�'m`��d|�[&G��﬽��n4l���|�� � �DG��ҕ� ��S}��}�� kI����W ߭���~$�"!���NWƅ1�[5���� Q^Sj��_kd��X�ʡ5�ղ_���}�d� D�4��M/jֲv씮�b��bl���sy`/���hWT���~W_~�0o"���K�㳮qx���3�C�h5�_k_�����+�������sj�WЂ��|~^Fkd��nB˝�x\�|m� ��g�o�W�LH�f(Q���!X����2�r�qjZ��Aߧr�M��~91"��XZ)"��'즶�(Ir.���P9� ����.�6M?%��G"[!�Vɕ��Ғ�HN�ow �oR_@�7|x�j(AٔyZbE� ��._:tϯc�/����r+/�m����6�ﬕ)�[rS�hwXWK��r���*��w�r�a��ƛ�(����U�S�Yʟ�R�g0����P���e~꿀J�G�tb�7���� ˞X��1��y����&pMO���6�tx�Ʉ�t��Ͷ\���ȥ�$����i48�N���j�a7gUR��Շލ��7�q�O���<ˎ����,���f��(���r�c�`\����6|i�8�6`��>�r%X�U0$r|� �]J�e��q�;�M��6%���ړ�����e��$ 5��'��R~%�g��xi���T�4�b�޴?�a�G���\�D�G�pV��ȉ@���ݧ���x���ͥ��^O"��H$��g@�K3�aO}D���L����=��|OA���/5��*wv�?JT�o�D�~2Y"����� N{Ps7��>�̹���JPַ7Ӊt-B�`3�/NA����v⁧9�=�?{���K�P�e|sL���3��rwz(���\ ��>�'�˖�����O+JÜ �6 ��.��'v䰐*�Ԫ͓Koݸ=���revy�������>.$|N2��r!"�b�~J���G����J�t�cD]0�@�z��� <7�+�S���O�X��-�۴ө���buz��[��M��]�I�&$O.N�GQem㸻b>�L�7JV�%k���q���T�.�p|��׹J4��tfI���-�i|���Л�� �J�?�'���`U��+�5�ܥ2(���#O��q�e�ͥ�9i�7�ȑ�����&C�N���}�Q�;c�j.g"�V���j���-e�UN��o�k@�] o<ț�����Y㼏�-x�ɾ�zBh0[���XA��7�ND_�����Bv5> �|���{1�H��$�)����Q��K�����k�Z2��u����6��0��ҽ��#�?S��h-���`�K�Y������TQ��@�݃�z��>/����T�e��� J6J���u�U���R_�]�)Үb;ùC׻�[�G�b����܊���3�]nGo9 T<�xrz�.�=o0�?��֋ -q�nߦ��.>��w4�h��U��A�F�깞;�dž�����K�Y�j��Y�f5o���"�A�����VΟ�%����/FU%W$\7F�s/W{��sܨ��/�i<�BFk���������)q�b��H�����,�t)�GF�c�P���R�˨lN6J&�Ӥ;4@á�\�J�s�;�V�(�&j�kIz�Y���*<\Qsx� �뫜+��$F�V~ ���feD�=�a�� <��9����Ǝ�D���V�{��?�ѧ29�u�����j�j�'̓]�Qu���jL�(:=|��(rjE���E�T){Qr��~QT�CݷV� ���?� �91�&����9w���v/Yliz�W�؇&���n���Cx����z�si5H���.��-|���.&Z|���Ⱥ?�<���V�p>�$p���˖��&N~���ee���/��և�5_���(���6�t�%Ӝ���� �WUz��M�q�:w��4q���F�f�_p"9��ұ�RV�h�5��/霃����I��9UMu1�}���JOT�^��#LO�i KiP���e��x��� �Ċ'��3�:Ӟ�f���j�˭�^�L!ŏ'��kw�ؽ�6��d�-��e&߭Dj���i�U����R����$R}.�C���*V��&�#»��'�ϻ<�z����4�-�`�Q�5�Oʑ�$�m};�Y�V�c���C���*+r�d]F%��5).܀jw��{��3��+ߴ���P�M���d�������4�q�)xy���~o �l���}�{�)Ӕ��?-��>j��?Nb���Z2�&(3��炟�z�+G�)Q��Df󺈓��PM?�=��pY�v�GW~���Dbl�o�e�(Q�g��"CVVɖ��K0]��k+��M�|*_i)�f4�l��jP�F6�Z� Od9�bB]��b[�fx���2�3J�tI3&c���kIq.��=�o���������t3z�\�7�~0��-��s���ޘ�iB����f��p.���LM����a�+i}4<��HY�u/L�a��ud`3U׎%�p��!*��̭g5_�[�f�9�x�+r�ʙ��p+�É�*�N:�2���Oݿ014��:A� endstream endobj 1604 0 obj << /Length1 2792 /Length2 24000 /Length3 0 /Length 25555 /Filter /FlateDecode >> stream xڌ�P\i�-�w�@�܂���w�nA���܂�����������^սE�ں���wNCE���(l�`�p�1�2��D�UXY,,�L,,l�TTjV [�?fD* �����=���@c�&f ��;�d\m��ַ��\�,,6�� tp���Y��2�@D*QGOg+ K���|К�Xyx��J���L���� K�����-@��� ��O Z~Kȑ����ݝ��΅���B���n��]��n@3��� �v��'cB��YZ��mWu0�;`���)����jot��T����@�����`��+�����U����dcSS;Gc{O+{ ���-�(!��1���~ۺ8��݌�l�M�17H+���3�����#ȅ����׈̿ʀ�,no&�`g�� ��'f� 4�ݓ��wp����[ٛ����ՑY����(-�O؄��f8YXX�x�@'��Ԓ�Wy5OG�_N�_f��ގ�s�@_+s �����rv�z���/Bde�Y��&@ +{����f���|��V]��X,�~������������ΗYNMZ[S�������8x�9X�l�,�_"���o%c�h��+mo����-xM������s9�����V-@�[�z,�,��_���R�+��OῪ��D�� I���������q�Y�z��+|������j����@3+W����/�����k�r����)Y�L-�V��v�_�������b��`��򁯖� �����_. ���������ٯ+���`��l�>d0�x�����/���@�x<_���3�}� `�e��0��F\f�߈�,�����E\,f�߈�,����~#v��o�`����\d#0���E�7sQ���\�E�`.J����o������F`.j����o����h�F`.Z�������E�7���X��Ʀ`��k��3vk����w���o�����~Y��~�����}��u�������3���kk��'����-X����~����Lf�? ��o�`�1�ӕ�W#������60G�~����2y����Q�������� Z�Q�CN�_��75�_���_���tX���]X8�Y���7a�,,=-��D�m0bo��>t�? ���|<�~n3��� N�?������ 8��?n�x����b������������:��v+��S��<��7�r�����W^l�� ����ڰs�v�/E�����x��� f�u�+x�.�Nr�Y�W���b�n'�� �u���ź��G��`V�ۂ�S� Kg�/���G���|�n@03�?T �����{��K��M\� ��w��<�M]�����m �H����nzM�L������o+�����&��4����[\�Q��ʿ�8_ '�w�/n��^ ͓>y4T�}l�Snz�y4�Q�jB����=�����QMh����G���� U��+7�R֭{�������-���H�E㌟�#�� &��Mҧ��aA����`�z�M^]O`f������#�~b���Ye����Z*Qcsi#�$�� }�98F�-��(�7��-o�g֣�?�4�!i��i�-��J%¾���mp��u3+DCԃ�WYX�m�L��S�d��d���m5Yj��h7�N"�����DѶ<�o�~�vZ��a� Ij���h��,x��������n��o��WE�!�6M�46:ü[��+�`~�3�{B��\�W����ǜY>gQ��5� ���3����/�o^L~$���X��} ��No�^��Q��L1����2�z��ŮsΞ�R�qHKvn͔���xZ��|e:�(Uo���U�l�0�qh�ƿO$0����lw���X�g�A���=T�?jM�+(;�U�/��E1ER8*�fc����HMč̮.MSM�~c�-�ѝ�HZ��&oN�[v���Ϝ��X^'A��n�U�[U��--���(�/� ��-�ugτ"D�j�9^��3�Cd?�6(�mK� 8��|��)ж1�d3~�+�������������ĕi�=��þA �vl��C)@n!͗e�БE�k���bD�Cl�O�`�UE'��`)��g�1�Vb�`�>� �ʠ�3������APwzs�~~[�H�1�9�v05-5Ew�\8�*1c�N.��~�J�S����?�3���4f���?�����>兿i��n��r���rV�J�|MMEEڻ~�w\��H��Y�tZ/�=��9X�^_�Fn� ��P�ަ4��:˺��?���B��Jŭ��V�M�^{�L?�7%��[q:��kl��P�p#�M3��n̩8�^��ӳmAȲ��\^�N>S��d0���� ~���m'�9ө?���@�:>]m\[�iQ����Or@��8TTGD2����-j�,MH'�"˄FR�[i%JJۇ���z�8�U�6��I�P�m/!<��� 5�E�I����A�W���%l]�^ˮ�)Y'߾Imz���݁R<���c��ʻ����t�?Gn��N-2A��� 7�F�.�a��[⶛)���D��r����G��4������溛-bw,��[Ê ?�h_����&�m~�Z�[��=��;u!��DEy����7�}|�>��M���f�GK���i�MELj2+�����+���6�>r��}�.�:ͩ�R��R�E*���Wo�Rາ�V�ͯ:�m[���ٲyI4��TE䘷��p�9��D3���ܤ��y�lC��h��ze/K� ��2���ޥ�G�i�y e"��A��A�kz"Ic�8��sS~��_qV�Aˍ1(�^H�� �9B�4��ݓ�"e�M^~fT�[�iIڮ��k$R�,�m�]1y��`fVC$ZS��wG��3̢j߂C���r�� &n=n^K�ħ^��t��9�1?�[�||C�a-�P �ދK�r5��+���;D�C�����{��G��v���!1)׳�ߘ�Ex�(q��EKEY�@EfB7߸!Fm>NF�V@fM�}m۟�������E��T�χ�[]�3{.�x8��-E\y��ߓ���э�U�Җ��_#�"*n���c����E��7,���ҵ>�����s �;{�� ϡ�'���4F�$(���w� �y�}.W��u�B���_ ^k.S�q�c�z!mSN�i�`U�/�*�|�"W�����|#���Ĝo�Y�\������A$�h�J ��Ӯ�����Q`n�*��w�FY��rxz���C]缴�>�n�#m'�os�,1r^�ͬ�G��K�a Hu�Ë��� ���)4�H��AHe�a4�U��͗�/m��踺�[�,��ӑ+ ��i&�;j�:�h��?L��0��'@��e�"��& !V�d�ME,�Qx�-+Q��pj`�f��a����H���>��q�z6dC��c(������b�vG�%k2�,g;�c�쎞�s{��7)M�7.W�i�&B�1��H�d����x��L�tjOH�Y��VM�-\���(���ˇ'Ө���`֣�b!�4�O��޽g��J��7�����H�fX%�U6�13���d3<,��E����N-H�d�S�v�� �-�����o��$��V�-H�Lc�kc���\r�]t� ����R���: ����}tw�t^~��V���L�N8܇�#��������6�I K�k�'^^H�& 27(�O� �z���hİD�U��,�f� x����i� �WҖ,��#��D�S8�� �,����2FK�x�%F)�3��_L��c�� �3N��b"�6S����tyy��MRټmub9��|j�9�3��ئ�W�Q]oݻ� iS!U)�D��Wͱ�0@7{n,�t�b� ��"�� �Ra2O�� ޳ z� S����LF䟧�֘�}�W�~��n�K&b��И˻��M�ji�?�>^���kw�|2@򛜡��%�j=�P�z���"5������X5|�!f]��-��_��r�m�F��?g �*��릣��gBq�����%�~��)�L�C�l4!��iϣa�!� (�fF����}l��^�5�H�f=}X�$۪~̾�P�8�ρ/O>v4�5@�O\�HpE4�5u��l�|O���?�~Ot�v���P � ʢ۶�:�jU �Z�-3*�v�h}v��,q�]�b�� ];�� �N��ѣ�V?r�m� A��0�_�)�ɓ�OAm���]�L�`�]��L�-.�{��k��)�����#�O6�*LiWOn4~�vL�4C�bM�s�����\q�9��WӢ�K���j j�%]9 %��nk�X��@̑�Hϫ��OW9�*YK�C �}a�͋,x,)_���:��3�5o�����,��u�=h�ٔvv:��n.���a�Z�ױ��y�2vr8��팾�Z��7�Ӽ �J� N��|�X���n�Ѹ(���r}�Gw���^u�G6� �KM��X�r�ݢ?�V1Pw�#�ȩ7�'�4m�K�5:�\A�t�i���%Ie���:��H�g�&�O�-O%:��';]#��_X���~���B�� A�����L/��V��̿%:f��{02>����C �-G7o����N���И�9�k��\�8��z�b�_��k��o�����Wp)[�]��Y�ߠz��۾�)���H�����>"ud�����}"k$0��F�a��s���ߥ�]��Ϧ�ǰ7�8�O�k�L̃��[��2�>��#4{�]X�[ oF}v���K���Һ�\�/*��� �gq���N�M��3�7�ԡ����T��Q'9�C՗d�����7y���\��t=�)R��3��� s��y����3����{/�\���lx��.cͿ~�^yz�ǚ��?,HD�c�_#k�$#��ʅ�6�MRO����z�5���� 2}�v菆&x�yL��D��-ʷnU��j�a �erI/��;�� Fh�o:�>H��iH�M3�����H>�0�:Uw��_CZFv����鐔x�����o���i���B��t���F��͡�/39�/�׀�Gb2S>I��Zh�c���}x=j}�}�H��OP�_c�|�^��O4�^OP ǨeաJ����>�L�A�&�F�KAh��W��u�H�N�}Q�~M�IWf�3�󠨏"e� U�-�6�8Z�����1 d+�y���A�_��,H�~��^��g�~��Њ���=*��Π@��˪0\�RA�]�\jr�r����Ь� ގ� ��V�K% ]���4� �y��X�e���w5(:�Wc�$���O H�: ��8�����7H�H�T^k�:&�Oٛ��kgAG���k�F�x� �<�?B�g�D�h���~ �BS�F+��G���x-��ۯa��/8���F��w�F��{��]}ޫ��uS�9��\n��ʷ:�ϡ�h��y_����N-���8M�YS�5�/�Z�9�"�}ivq@al�E����� /�Q��]t��9�r� ���%7U�����g^4e�\�!�~=}����%@3��ݬn6�Q���w\�R�s\��y|��;4؟�Vkֱ�4���p�����g�A�YRH�������ϟ� &?�)U�..�k���/�3���Z�D8RhZQ�� � l���(��s���w�]���M�B�nx�ڪ7��Hwؒ�]:��ȸ�`l2��Nm�<��j<�$>a3iQ"#�P_DFk�[/����h�O�_d9� ��2�,i�n)E � I�v�v-��}?a��R�j�+'9����g��������O� [ϤĄ�?c��Wn�^� mi�F��7xX��k/�|��Y���X�k�{�}Rx�!uo{���oU�/� 7�p��j���j��y *��7��O��o���z�J ��vf�v� ��vd��E���@����M̯�U��5�Qt뱲(�6�R"&,���%�����H�R`��%�q�.7�n�,��f=!E�ؕ�׷�6Q-uqE�Qj�3!�2}��/�{ՠ��0 ����5�����i�O��_d���Ew_'FRKY���L �]�M�w�&E�mY��2�*G*qk�x +��Y� ����`KKM>[R�1VYώ�6�fl�(]����rN����6��_(2�yU��ʳUH6Ǟ��Gz���$@v�1����S��撈���'�� �0������58z���3�c�kl]D��|Pu����A�c�(�1�o����8 Mo�{�8(��$*a���g�ֿ�rѡ�v�!�daK�^���6ٚ7$�/q��������k� 4S/E}�^�b�H{��ֆ��p��1���Xy�=��E_A�����D�t��PO/ڟ��[�[A�Ԅ�G��-O�P�������G? ��~�5H��;�\x@0���=m��"8&�Жi�E��bMQ+8�P0�6K-�� �q9�t��?�T��|Mh�$M�P��3]��l�j���f��s8�d=j��N��M�2�K��y� �rG�:&M����5���%2q�$p�����^�ݫ� �4Ӝ7+��Cڡ�c�Ra�烲o� ��q�ՙ� �X�ӕt/d�� �.e�c��Jo �F��6���@��*����m��JY*;ei�F���_�}l�h�k��t��F?�� S��#^�A��S�㏈�_�Mw�RyM�����úҘ��^��+^��F���� �G s�R�Ev�Bg�?z���/�q��f�&��vș����Vp2��0�A���|9��[Tj�5�����9� �Q�ў ҝ� ��lX ��^t�$8�Q1:�&�Y�m�ѯa�x�u?��lENT��[y!�� ����&� B�m}�8���� �}&�$�� MǼA �Q�tS�%�y;��&��� 3�sY�+��N�����i����)p�l��j ��Q��rH��fɟ?8����n7��mGP&����،�]4�9�X�Gvr��ˬV��x ;?]?�̇0�e�������D!)�)u]�h��]��}�7Tst��&�rM�6��<������م� �md.^=� �/�<����I{��\��z� b*uɨ?����Q����o8��m-���Ձ1d` s��g�Y���Cq��Q�ƣ����;��V����K�~�N�M�D�Kѝe�Q���v,�|������CY�R�� ٌzU�^�C�m|�tD۶����zZ*��|��m��ZP��J{�LV[&�^ �i+yiw���QKKAۡ:�0f~Nk2d��������-$o�\h)g3�p5k��κ��(����_�(�r�u�,Kʹw:>2t���f�(�KҶP�AJ����w�6�#"�T�p�j3\�};,X�'߲ݕߚ_8T��*�F��f�73F�u���;�|�BTU>۴��Eq���NLM��E�!$ں��™�9;Օ#���w6sj�M8�%����C8� 5# �*��pf�u�M$��m]�c'�K�+~�P� {τ�o�o�����j�k�y#�[_꺺��WW<�ږ$��K��#�8�LC��:�����L-�Q!�G�m����K��hÖ-�7�S�މ �f���J�s��ƿ�V��xǣ�$o����H��2��1�z]�ڪv�������븜� �WoG�Ϸ֍�o��b�褈]����X�>��+��n�d��*ŕ�]�kh�>b.-t��=O�:�O�o���U�S ]��˗]v��/~� w�"1�o?�bl� �<5�����}Þ���wo�B��{��@�V$�tO��,D�~��V7�[��.�" d��P]�.��7K������"]�}�Պ�+n��,o�7o�G���W8~Jg�2CN/�"�d�&�GÃ��M.h��$��uA�Q��g'��a��Au�������1���\*cmA�������/�a�~\v�.?���#w�q� �r@���>8�$�O'�o�� JH� ��x� W��X����D�T@��0ןT�T��"��\��Fd���N�)��%]To3f�&Kݙ.� %ea���[ޤ�@��}|ڤQ����ԏwi�� �QQ��~�L�C�[��� 2 ܩ����D"��'��xf�ԝun�̆���5,\08\p��*�����֓���L[�Z�J�:����k]��8s�g<0��hj35#+R�@��A�`UFI &s@Fp������Nl��[XÙ�����_iu8ֽ�C��vM�7"�`���'L�:���H��ǯ #�'�;v>��B��-���}���ٽWE���z>��e�h�z�c��rsb8 m�(A�%�"��7�{O�N�+zk F���.�#�2Q�ֵz�� ����!g=5���`}n>b�o��u�]�50�i��b`0�H�}y��}k�lR!"����> On��յX��;hk�����f`V �q Yw����$�|��]��QP�l+��KV�m��MX�2��RM�W�; <�@�ط��C?�K��������B�����ivc-i�%��?�P���v;���F��U��k�=i�z!�e���Ih9>hi�F.�I-�=��8!��{��g�ﱄ�OC�n�O�UJXTcV��q�HSwf��g�E�a�v�N 7G]����7��Q鑯*���Ay��UTG��� ꛔ-�Ğ�\��'Y��q�\��H�8*�^ȡ=G��Q���i;��%ti�1�A5�� �;�⸳F�F\�oV��z�B� U�\�\r��W�?:�� ��d��ߠn�^y3�Hw�S@�Qu��S�����s�Z[�5�{E�o ��9��36�e8ǃ&��3�B���<?'u��a�1��I8���K�b!P.�U���Gg|_�QL �m�d�XrE��B����D�0>�A�O���@+k�3��4UĆ8�?�J�>;�o�>�����8����$���T >�t,"#�Ik�:�AI�ˢJ���_��]��I3����K~+��L�+���� �)���)�|�uխO�w8�¥ �X�XC��(S�z(���'w��c%�I9��oerTʀph,Ɔ�h��k?'R�+�3��{�L+޲����jSƸ���I��#�j]=C�z�!��Z��΍���Q����]��5�&�ϲf�[lN"� ��D�fb�e��Y�ǃϚ�����L�b���E���ߌ��c� ��� `�����:� �a �u3�-L}E������H ��؀z��>^éњB����Q��K�)EB���lYo��ų#~�����z�֡0�>���^K�E�;^��y��U��S�H�ؾP���^�XY�e������ �6��h�\�0���H:� �����Z�k��D���2f��)������=�̛��i�J��8�x�5���|������d�79kd� ~��mPTߩ�U��x�:���m�T� *��X�ڊ��If-�Wz�i^&-:b;�`}��@ӓ-��w'��8O/%n����d�qI�L�����R�dO��n������?�����v�u�3��EI�z�����?�Q��� S�T�ω��gM��V8ܘJ���˞�RqU�͸��I�2p���p�(��r���-��[����g����a��94\���cV�~ 3��,�N�P�#�Q�q(O��� z>�!]�����0������fC =QV\0j�e��+�gW��1t !�QfQ���n��vZ��y��D���m��^c?]�`!V��1-bm�k�H5���͈�J��I�{��'_c���gd΅��#ab���Xpt�#+��Ei��xS�dU�������l{�=Ow�c��}8��kN��\Dy�f��p)�_8U�����������#�u��.�P�QhWD`�8�7�s�_��}��9Vſ��~���F��–�G"V ��ɾ��L�S� Zt����TۮO�Z��c�����^ �ו&5آ,xL���{�Y����,Qx 'a3?�<�'j���ƝE��i��)�c�S]q�#�ӣ�/��#��"J8��Y�:�$��u�C F4uɕ��/BVYa�3d�2ɐ�L���@��~"pH։)���s��wi'��d~��c��8�ߨ�\a���^PI�a�>�О�U��l�.cs=��l/'q�a e�'�5��A� 4��� �ԥ�;�HJ����r��1���c#= ���e�̨$S�d�!��j�b��嘙�b8�a�ө�4�Nb��~_�c��þ�!���^�����Ɂ7 �C����}��34��E�GM BQ�d��9GL k ����5����)mE��ұVX��&>̣Y�5d7�gUL���M������6�i϶۰�����(�֫��d2e^�E&{�[}k'O ���2>�̫�c�b�����8���eV�K��w�x�aa���`�[w�Ѡ1� !�3��?�$�q|c!�C#�c�_��� �@$bs�i�Y�:—\m0l��J�eT#�䉗P��]a����yߝ�f�zu3B_����}�� ]����4#iǽ|p � ���Ӹ{��� t@�붏#���c��i-_;U6+�ѯ�L�:� k�J� 2�MV)/\gϹ!� ��׍p�����cuc ע�j�����{� ej{:f�/�S�a���=Ur^ J���г㙾t3���H�yvM)�ߟH�.t�/���q4���)6�B�Kd�A���s�����/w��"#�6(Nf�ʐ> B�_�acȀ����c��/U��ު�u�%��-�Ͱ~Z�|��X���-���u5 '�Ep�� f���-��l�T�Ln]I����\n>���Dw5���N�Ғ�� =*ʸ�C����eJ7'����Rλڦ��WG}G�B��P�E�$�����re�3O~V�h;ip;�Kgj#I��)�n�lI���Odx��rB��vB�g1+��9M������!_SC�!�p�=�F��L��j<�u��:�dW�l`U�u�Ȫ���vrȝ��!hB\w�ܕ|V��]��R+@��㸧p�����N�o��Έ���Tu�@�2�x]�B��!�W�]���۬)�rʞ8:W�MG:�Z����;����2�Cr�U DF�-U�h�D�A�Dq�-�*��'d���ΰ�dq{�<��i#0vV~�앒�n ���Y۝D07_Jl��}�������!���7]�>ӹx��5`��ž�;�ZL0�V r� Lfc��#]*տ̗ ��ǐR ����']���3N� ���tÿ����)\�Ds�Q�CΣӗX���JR5�qp ��3;���Z��.0�V�(�.b��V>!��0�=�� �]��}�+�1�� ���H�9�$C|[�4�S)8��V������0 �C�᪋�H��N���P�HLx���[���M[��H���V�CV&�O���=A�Y�� ��1�� \7���e �9GV���<׆<�j�l �i�#�����A:�]��|c�3�$�Y������i�i]~��O�����7�����j�7�Wn_��&��yT�}�!�y����q-�9Tߍ��n�����N��،Ww���inBQ�����8�3��M���@��1��E�οіT�6������� 6�Z^�7X/�kE]C���3�0���'� h+?He�� a�7}�����y5�`�)��#��{�;QU�5�t#�� ��@q%�*�OK�2+�v�:�؁bhT� �Z�N�SK O���.�Y�=a,Ȉ$��59����=��;���2���"�7W>��+�*��QC_.!E�xL�i��p���U�7����Ș��c�:WH�� �y����c��AQo����|9p������G1 ���ǭ�������7�˟u�&�"��L�e�\���B�o,��X� ���ţ�>2 '����zn1￉}~��3���0���` YS�)]Vw��>o��jb/�n�'���'��(�u�ș�_>�N��D!&"�j���K,KO^e �c(�_����jP� ��گ�I��!�%��� ~��Հ6����}o��y�� SL�����S��4�߀f'�)�fv�}wCb�9�� �c@_�p�@d���4� �q�GV����B}5r֫e= 5�:܅��2��_�r7���b�\�qV*9."�W�W���Y.��7lҴd�b�� �d�0V��D��b����2�ϯl.�Է3���blq�UN����#ׂ�!��0T�< ^6Mbws͐rjc2R�Q�!�;, )��z9�� %�T� ��~�-��s̀�$�1�/���6j��E~,'��5� 0��Pզ��3�������.(^5�Uɞ�W��X55�M]B�D.E7������G������Y��t��[Ck�8W���(�*Ѻw�`dYz�;,Uk������w[Κ�k,d��>7�����uhU��L��n"�Uy|����jKCZ������b��Z�ҹt����C"r��:��7����W�;#a�ݕ<�\_k�ZH l<���"b Ɏ��j>v�k 6 �AH�- �����=~c8�q�����i��6�����ĽQZG�"�꬇����ett�������c��*գ���b5�_e��Q� +��p;O��7�Հ������ڞ�L*/�=����T�U`�y+��Lz���S`����D�;q5+zks�-.�e��p�VT�@��6����2�})�ֈm��U�3��Uy5n�1������ p.�"*��l��~������Te�խ�ӗ��q��� A�������%�. ���G�8��ڭ���mFF��d����J�]]3ft�z�� ��ʛЮ���?��M��'��� ���G��Սu KȄ��3�n�a9ٺ��;K�gc$$�����S`|��>uj�͊8��ڵ�\$�_��~V�*m���z��u`� M�%b�����}^~������T]��5����P<��)K�j����c� �5���6� � Uݾ��9�;i+�0��1�*�sVX��E�S�*��% 9��=~JO/�0�Q�fi�Y� �>]PLr�;��~`��c�I���WM���� �!ު�ͻf�a�_"�jNv��GI����ms� T�o{m�b9�J#���m�gX91W�bP9���c=( �t2:O|��4a�S�+m��s���݆��}�{zN";��#4�1�tʔ�.�����s,�u�����D�h�9~��6i�� ]�CK[��W���y)�\��ʅ���A���ims|��.tK-���C�s � �#Ikᮙ�H��gF�k��0\bM�����pG� `:�]�A)�aл`رȦ޼ 6�5�b�+,�(@���K}z��xy��L��<0��6=�/^��rW͒{$Uo���tC�K���4����Υ�q~��f����D��F9�� ̿�b���w�e̹֧V�#�]�E�~�4��3Ɓ�g3"���%�����c���� (j� Z��c�M��/ m��������m����g�nj�_>~B������m���#�@�WގbJ4�*I�S�%8.a���?��J�S�y|���x�NJ ��܃�.����=;����Kã�����~!@��V���%Zbht��?�{�6��M7뚝��p��b�6H��9 �|v���ݧ���� E�o�ɉXR�X��[$�}�� ��Rr�����x�r�E���'����.��h }�T�ɗ�$��0>����8Q��f�m$#b���o���n'2� �F��������r�;��ì�\��t�H��&*k�Pn�A�`J��B���IW�9܀:�4�ė�T��c�: ��<��F ��@xN�̄��kl�D}�)zt��]�s�2��I4�;{ 틲�x�i�/�})PC^��˰k~��������\p��=X5�؟�w�%^+��я$�k �Jc)��D��q�|KN��#�l�D���#-��̦�E�\� ̡���sW�<L �@�;�Pf�ʐ� ]r� �P��ѻ�A1�I� �?����E� O��(Q+� �ɗ]�p�yt����������Z�ID�> TUX����cY��:�ђ���+������k=@ z�X���*��jF�j��!��k���haލv��] ���\����a 5���Y�<ԍ�r@�@p4O��J�� P�6���J{V��,�H���m��B�u5"\�(�:~�b?�u�% RmZ�&�L �0�wƫ<j^R8�ta �B��k�L���sU����^��g���g>�V�R�3 �i��R��������EO�[�Hp��zz���<�u�/ʶn ��n�i暍*x��Ejt`��u��j9[��P��:ˁ���M�UZ������c"+�Z�예~���ck)��O���ej��-���W�(�x.�%�.���Gf�����=lZ������ �4�f���촍S�7F&}1e Z���K�(�횿4�g�Eؿ˝s��qWi�t��r��3ӽ �j{j�x�1�S&Y�Sov����!ݡ����^�q�����\�� 4�I��|��T��;D^WY������VR #�h�g����wES��5)�{^�m�<�l��ONUA�Y+:��2�z.��J���6;�=���#_ZƢH�[܉74N��Z7�qy� x��������j(�����x� s�Tg$��/���&�qE5�ZL� "���R�y�d� 36$�q�n?ߊ����vl��v��WCbh� �zN��Gяd�9�~(n�W���%�^�=k�thH���Y{!���>�{?3��!�~�C+�p.8�_yi�q`�R���9m卛E���-�X���p�����ZLw�Z�JuuGp=2�U��OG&'d.��8R�D\90 �lhV��DE���Y����*��1a��;y��<*~�;f����������b~�(�S�l���L���"^4�|�\�v�t��2��>����!Ȝ����b:��Ú�-��,�9�j�;� w�^|6��f5�z�{@�}j��l�)?bi�<����p����^H���J���~��L�JHfp/�4E�r��o ��B�[�(zo�n�pT��7���m�~��p�M��n���c TW�y����gpH�\NO���T�s��bh�ޙ\���� �Kn30I��[��q�������Is��2�S��~�����u�5�T緕�=�1 C<"����p��aC3��H���ۧ>���"����Hd�+����N߰6���ekhx��Yd�c�K�8��ud���� �dKpr{H�v�KF�2��+r�a�~/'X"3�_4 �( �8�+���F��J3�Ц�F�&?� ���^���l�N>w\/=/dqa�6���z��F���*fDT4����~�-�������e �O��?P�Q�)j� #��q������R ��Т��I�ta�i�v0��!�SaE�M��]�j��)�IK���\�(! �;�5����F�}� �ɱ����Н�'���� ��˴E�Z|,z/e����Hz>�89)�7I5s��A����WDM�՘�D|o��k����k�p�C7i�ic��8����>��a�5�p��R�x���4�a�c6masDT��m� �HM,7���3p�؁q��!�8E��z�Y5�zNzR�n9�?nI6o��z�J.��8�n���gRd�J�����PI�S���=�� ��|%��¯�����R�s�� ui5=�>=Y�mof�$���o��&O����BDؽ�o��_��߬��xi�Q����+��^c�G=I��wX�U����\��� �{7�u��Pw�����Y��} �?g���c�-�������t���ّ��� �����L!�-2��MztD��՟�o�<���;�r�P�&��0��S.H�̉P���G�L���h���?nt�Ym��l�i�fk[^� JVb{��I!���|f� O�JCa-T�YC`�����`��:��"`��_}����vq����#� �>JcD��ɓm��nࣨ?]��TĞdʼn�4��i5�a�̚2ħY!�s�hƆh^�&���ޞ�o�O��}�!7�/Pc�w,��C���x� ��<(.�f����'�]�8���6��&��\G;������+�z ؿ>��'���Y�{Qz]��u����� ��%�L��� �󊙩J���J]���`�_Z�"�1��4$PG��t�V\2娐�.I�(FCpO2�L��Hx6�aD�>P9!�&�r%\H'��r%�O}} l������G��ȔC埥�>y�Tus3Hf�������d�����ڿ]���f* qp&h����*p���I�$×y��9UAJ�7O��!� >J@a���\�L�r)o�Jb��Bd����HE�{j���*W�y�Oh�f�W�� �/�v�y�[Z N̪��c�����v��\#\a���\l��2��LR��!�~>����f�,>�\}*]��1HV?w�X)�PQ!�.�MR�&��֒�����.��� ��N#)<�t�ӛ�9[F�*� ���?�r�OI�j�kᖒ�͑,�U���sf>3���++���K�>�(�����i��C�Q��� c�u� �\(V ���.��2�GkHH�O��AD��_.Uвjt`eD�U���iRq�u��< �eع=6yl���:���H�+�.w� ����.j�E��En������*N������R"f"- ���P�J�rT� =A��N���A*/!^��A�Rp�v���>��`��a-��H�bc��Ñ�<ǫ���f]��8���P/s��}u�0��|d���?~:���p�2���[��{��sf?zto �ι�>�����Rj�+��p� ?��[s%D�],52q*�~�0��9^T��=��;H6h�d82o��J�� ���F4�Q��<���v�$T3-�a� ��Aݶ$�� �_���b�93����,WVhy��?rBd[7�n �nQt/�k;�� �a:�AwŢE��Q�t�\�B���e�N�`U�^�ܯZ^ m���_?� �m@J���=8��9�:��8K���C̘Ď�ȋ[�����(���e���,L^�I��´Y�J=�@#��V]�<�L���H����� ��|�wҚD���"�t�e�W�����yy���>smȵP1�����7�k�(m#›?���l�b��E;` C�m�v<�_ �r�s�'#�� ״ �]����k�\��ص.���DS�j;�~NF{D�#.���ޔKy_�ؑw���j�v�0��z)o5���Ҵ��F�q�� w���㝬w�+���{5Z���Ӫ�a���"���d�mx*��7N���#BvxqO�q�(@"�ml�b��N�rr�ꅸ���FkrfX�V��S lq\ch���n@gҮA{�U�ښ�O[��{�&�n_��L��Q�U��b{ŋ�7��980�i #2��0K�1�s>UW�������������n؃h���aeͳ_T��� Un��8���R�rJ�d;4E�j21���+j���Da� @ӿh�ɓ_�V�Q F��6gf����pj�+�_��/K%O�M�7�Z��I-�Co?c<:A~�u�a �O�w�j(78&�E�eՎd��MAYG�kEr���_�*�N�F%bd�����V�=j�v̑�� y����##���Њ#�?m*w.�w>f>n�W���D@�U39!�zX� z9y�9�Yg��-6(f){�72�KU���G��{/�Y�bƉ9Y�+�[�� ��#�d � �`'��QHM鈅��M�@yN��6J��)�ß�A��Js� d�f�^�[����5H����׬��~���V'���C�����L`5���X/9a�"4Z��\}��s���nD�kT��Ȅ49�M��2���"�I�j��9�C���C�`xh�M[���rwx3�Ra���*cnv���q�>b+x1��O���u%�o /�DK�&�X�+���q�B�,PE�(t�����"TK�ݡ�¸L�G�o��ɽ,i�����"�n�#a0n��v}b�sX Z*g�6R�w��Ro}4hh�!�Rè��ܱѿ�cZΣ;���OeAC��z`�����{� �r�0Q���y;o˭r����i&d�jf�{�8��}��9�}�����;��F��hRjV�D�Aߟ�6%��-H�0>quz���1�ARt�4��'J�;�O� %��P\~'�4蘹nϦ |���v���{�G똕��vεx��,�d�}M�-ƫ�D�"��@�a�iW�eO켝/Y�̔$����Ԋ�dDFm��|-~D ���_��U�|ag�k{���4�(�'���qx���%���nX�!Xw�=��V!�!��`�Ӫ���%�O�R�5RML��fU׷���:��tz��w���w8�!;]�x�ԮXqmhQFK)�ay��x���/����:��$�L��=���b��mS��?���0w�)�BL_ъ�䊬�_��󤒑�lh�w�PQ�����k��bn��X���eN�T�����J[8Q40��KO��T�Á+�[���;��&����6��)������\-u���D�-$lH��M���<�J�V��? Ck���F��c�eI�3������ӄܷa����������_����?���mD�]��B��%XP�)K*uޛ�=��)�� ���܁ j6>����7��q1h��re�5��Lj�q����+4T�qa��n0q�ؔ����A'>���-�n�����-t��������2/�7�^*�M�U����� �*�i�I.� _Q}~Ս�}����|��h�V����0&��P���lJ,g�ZA΍�]�ԛZ\�-����k_Q�2 @�ڲn9Gr->)㔇t=7D��%$�t�x[���P��-��j�ɘ��bb3_�CSH� 2�r5�:2)�_@���:��.Z`d{�V|+ɵlͳxk� G�W�{e�sK M+��<,\I:7�`zy����j���7^T��\ ��ZQ����:�2���x,���9 ]���{^b�)!i�88rጁ8wX2�I1��+F?%fl���t��X�8(h�GB��#��|�[�r'��t3;�����эmq ,�Wڨ\kD�?Eu,��\�E��LlԩlM�dn�ű}�y�h�A}��1��A�r��( )m@!C�#��f380�����&�9�R_Hw+���t\�I�Q�-�-L��F�'x!}#������� t05W�ղ�V����"�]�v�i_�V� �v��`�>��Wn�W��Ԛi7��x�`��J<�i��4�B�dԿ�uH�x��Q�B:q�7�7)T�����iq�[�8g����UJ�vi/�aCqͧ4��u�y�d�ŶS��4�cs��dX����A�}��f�m��WR�{�_��T<@�T:�a������رoW�W'��uE�[=֠������G>��f0���!볆o ��v�+�?���R�q> ���\�3���g�eGq5�*=��l�e��,9iJ����e��D���q��;�г<`���N� L2>���Ŏ}�<:+z����w�3�C����2}�Y��O���0�����7L �0�P��ӘZ�Yw=������Ӯp�̡���V/n�� Y(���6�?T��]�U�/6u�S%��≆�rz�Qv\ͮv ������Fs2|�?��$ۏ�W�ɛ�iG���ǥ_�n���'i��`Ǹ�d�9@�H.���(�wA��h��iG!C�����Z��' ��Y��Q�� q�Pa��҃�y��/v��EhNW���[�|��Y`��f��׈���J��t����h#/!��Z ��o�I�]$;�"��2H'C�3PE�8rtT�<%�0��Yg ]Nf=���[�ť���d��zy۳Q�\��{��7��17NL� ;��&�@���I�k���u��}��K���x�#E2��UR�& �gM�v��7���9��3%9ê��H��A��K-ߜt,��d0$�z�� �V鐲�c�U6)Uڈ��$ �nY� ���_>����> stream xڍyT�k�6%1 �4 % 34HwwK 0�3C�PR������"����ҩ��4ߨ�=�;������Yk�{_;��}�{=k ;��!�����Dx��A�@Em1 $� �ٍ`�n�?(����C"$��^� �FcJo��6��q���`QI��$�$�c���*A|a@m~���+"��'�7�P] ��E�1��c� ��h�`~��������� ��G��!�� �s�uU�����y���/C������ vh�߉C�*��@��������{{�{��~U(�+ ����H8�����O � �G�z��ﶺ"�~ԟ�# ����wc��������9A��" HL�z�������C+��`t��(w�;�]4�E�(/�/��� F�oſ% t��{�N0���h��GFw��|B �z�^Y���D��c�����F<� �[������ŀ|�" ,(C/��E�+ �?��G$P�O��S�O¾u�����;��X(���[�D@����7������+�����������o-�/�����an��|��Fs_�����B���6���o��7=�'����:�����P�n�k��`�� ��B�A��ҡ���}ix���[EͿ�TF�#~M���(�� �[��D�(0z ��� �G ��.@ty�@G�'�W?E���04e��@ }<��%���a�����`����'�Y�Ј���d�}<=ѣ��L�J�#���P�=`zi?ҥ*��R�ΏomXz�}�4��5���sN����6+|��D>u����2�� �j��/�)Y��"��&���Z3`j����W[�ս �|Fr�AWA&]�1�5�s=|ĉ��)N�zT��{�f?FM�鯿�$�,����8��a�8{��� j\o>|n�}���1�&�$@���B�Ţ�ӳ����F�^4l4� ���?�C)l�iP}A���[�� }���R �\&� �%�����f^wZ���N�0��U���I{�~�[Z�%��q :��%�EM2���U��_�S<�y~gY46L���VZ��#�i���/�� ��MZs��m&��*��5!��pF:�<�c�lfXig@3L�B������!�Wú�� ���U�u> p����37�A-O��s�����f�W�m,�}�{���6�a�?^��3�$#dO��'Lc�����&3Qt�3`�[�(���6a��lj-n�}�jʚi��-i7�j��CE�]'L��u�V�O;�h�R�K:��m�p�"L��dw���Tb�;�5���eobն#��S�ܘ �����t��EA��q�lGC�ހQ�nS�g� ��7�7�|�(�����㟤+�X:�mf��w-5--|�9��ΉO�}^�3[rM�S�l�a���  Lq̮=��* �æ�>|��LO���O����� ��!�0�`�ٖ�T�k�X�<�?��Uz+��ݺ�U@Ф���������Ͻ}�� �;�&�&�[��OAԶ��FZ�#̓U}��Z�>Ї�Ԝ�f��c*|W��9E�c��a�W���T�V�g*���1�W���84��y��>!�?��U־%� '"�h��/o��[2��TO�o '��'a^��ph׏���|Y�ؕ�t٧J�P�δ.��O�����rK���wv�l�_3��M��B�,Ud����P<:��W�a�2#11ҹ���5.��V�Y��ᕹ��`�й���K�����A��c�n��M�טGw_m��F�H���?�����z�@L(�պ�C���5�'x����?.څ+eb���4h����r�8�*�i�z�jO}O�B�K+�FK\�a�m��5 �͋ �B�l6H����Kʌ*�<� a�FcwQV�ex45c��$���ں��K�n�2������k������]>7E^���> V���/���zQ s/��]䞆�|h�P8���Xe����Rmbf��im����D�u����y�ľN=�Y-'a����+�Yh$�YB��_� ��UD���;C��s\!�~c6;W�Q�/ 3}���$�C�`���gěu Fy�Z+`�r��㼢�6/��wF�&M{ 6 �d1|��0fz�����-z�*�Rc`I�����ӭ 3�}\[ɨZ��қp�����>dn֪�:�LS�r[����^��q��E�$Oӿñ;׎~�A�������WtMvum �.�ۈ�ʮ|������T>���4����4�.�sRb�Qd6� ���H˰�sfח,�1�h�=7�X5 �Ϗݯv��w�h�;$2gLT�5�&�m��IGg����r��]�O�d��c������V�8��o�|��H.�w3��@:�Y�P�;c;T��t|��N$7��t�g��"�U{ӂ7.o�5��՜�sS���)Gʵ֣C���Z�|}����&2g�I�x"�[mr3�p~�(�t�2w7�B��mK�ok>���Ě9k�/�S���[��RD�v6�Yȟ Uln �b{���T�0�ɧ��<1U��" �7� �M�X�).���(��c�>��T���V,㵎7�s\�{ Ti.Wr��_"r^�IZ�Ro}:�%C�1��FxrT�fn;�I^P�C�Lv����� ����d3�Rw�Ӄ_9�@~I7��5���(1w����q�M�5>sS�5ٺ���`1|$ez�Iƿ%\�4��ٚ}��p�����tО�l�N�X�SS�>�"��JRz+�A���E�@�6����9���d~P*�������y�"�5�R��8����0�� ��/D�>�SS��Pv򽌟b JzJt?tx��{m&�q���VNY7�8u��o��5��S�����I_�20#aeh(:˗(� �a�R�j�L⇭�ʶLjR �y����ϑ�>>W?n<ɻ��L��� "d��<�>H�Tf��H�O���p�:��F�@��sg_қc���;a�|2T�z�<�~0�5/�B�3�2u;-��0�MI�q��e�Y�!�������h �^�(��X��a�t���X��f����=��G�aJH�gY�A��6lA�;&ݙm�LG{���>�/���j�Y�޴G���Q��*�m�,H�͞�3� )�|�ATMjjIr��Ώ5��8�"**���R�w�1Wj���� x}ߊ=&Q���]o����=�������0� ^�7D�V�O�sdz��ae��o&C��|��4޹�)�P�%��5�MŴn09k?���m�{��Rm+ ���õ�T��� 3Qkdة��X���ǭ:�4���e�Q�M�2[Tq������C��ċ�� ��\Ŭ>�Ђ͹E�Mn�|R8no0� cp�c�P��z0���T+����棫��vbiR�ؓ-�FV�78Hm����g��q4����O �8�0k��$�˩�dx��5��-(���xQr��9�r��K�d��9R�+6>z�l��T����Dn�>�E_��2�?1E����{-���ܴ1H�`�M�u���2���ӻ %�O�b!׀uO=s��z�.G�;9SB�Тl}Q�gx>���̵����C�̵xY��_�F N^5�ˆ�ȍJ}#��˖�uG�X�j�k7�M����6E��жm�6�8Ab� �ձ�*��z�K�h���n798��c�?��9��/��0�S��Gp%���6�4x̨q�my���:3Pw��(M�j6�'p���P�ƺ�(Zү��C����\zUJ�i[�s Wm�87��5V�\m�4%Q�mKc��x<9]�VF���mz��C~Bvͯ;�7_LgH�g�͛Z�"J����'Ϳ�0xJY��a� �]� 8'��q���_e�Qu���U�dUoi�Ý�f�#� ��c���� j0~�e��H���=-�{����1�u �TMek�����+�9U���Q�������»��8ě�S_��R�0J�H��_�H��sL*�Y�I]�"���)�>=�H�Z��b$s���L0[�t0�:�a6 �zRb��A�& ��n��U��ɿ0�B���3BEޤ-��I�vN�����{�v,�1��;F+�����}�J���;Up�ӷ����N�&|;N��G�Ҷ�CX�o��N��o Q��:-e���\R���Ca����yz�Y-��y�r�������C��x�u�5� �uL�}�7Pkf�{EؗG<�6��#���򭘝jE��F�$@��jۃ�� w��;1��zo^H��lq�Գ����3.~+�KF~���!�u�K��m�� �{oʸn>��A/Bz!޴�w��S��tȖn�4QW"�0��y*y� �w�����؋'{����v�w��8�Џ�˅ac�Zy�� z*�JO�b����,[�L��z� �^� ���[�7g9K�{�>����/=_��� �Ig�Բx** ��&�N"�����NGU�eʁ3RvU���À���e:�*�7�M����Y�����(�F���w%���^MW08��$'�ou���Jم+y�gհ��v����'�9����{fZ ! W���IBO *�n�0�]���N^u)Z��KJ���H`�Ʌ�P s��4!E]+\��I�3�f���p��ݕ2MBP�w���mn[�b|I��X���+�IA�k:��}?�n1�.����J�X����h YG��$e��-�i�)}A�YM1;���P��Z�[T�T�d�O�Լ��KG ��x"�h ��p?��w� � U��M��aL��w؅ �fGCJ��&)lwRLk]ʚ�u�ۙV1�� g��R�.�����|8f�Dr����]Уh����:�9�>�\G�U�q ���s��ӭp.�����态K�i����ͬ�����ܔ�M|O�Da<�;�3��+\zG?Ϊ�z[���}?z�ڡ��F��ֶ%�����Q"��H�V*ڸ���v�Z�-�'��M�A�¦�HW^t _v`ëN.a#��@�'�� ���1�9�v��b,�=�4�^��o� δ�h�v'-(�7j%bF�Ε@�}�(ǡU�_L��Uq]`<�!␹N �R�~{N�^��ƴ��nD�б���7�$g�ʎ�/ �h�-�M�fv,n�p���"*�A��3VY��$0�N@��&���o�{Ne3����F���r�������W8•���b�����+v���+Iưv����gK7B�t��ߤ��Z���U#�'���v);�ɚ���N!�5�J0<�|�/�=!�h�Mxz�l' Cs��uu(ᒐ���[��C�6�8�W�c���E�7�����t�x�� }�8Nd�����Vw�W��m�2�Өz��&�����,{����W���6 $#Z��b]�'WS�Qb���1�}"k�/�+��C��h�a��(&^.� Ks�'�54+&}+c55~-��D+������:�e��V_S������Lj�#��8�0L��F�2��퀈����A����m��F�7}`�y��H�Gl���m*v{�n����O�������g�bT�78���M/b��d�>S02y�C�V:kN���lX����i�E� �?���{��t��r�k5)��<W3�Q ��wr\��чБ�<�~��q;A+�}�� #l�� ���@>շ�3:�n��&����oTJxŎ���;���M�#�$T��Q�rX���N�q?��Kom9u�kO��5�)Z/�&a�xC�nc�R*�X�7�UX���Q� R��%ƅ^�Pn�Q�;��O�E����a����!ؕ��+��[n ��)KCB�|�n��T��#��`M`��ދ�6��j?��M��ۣ�"S�iWw6Y>�䦄����?X�5~���J"+`�)�m59� �v�5�up��&zjO�Q�ŗ�i�������C�.�S�R�l�8G���������ᄅ���$֫H���i����˙�����#�<)�K��_3*�U�eF��ˮ ?*� �Pk����W�UE7�� y������մDZ��G^2~�:0���r�^�#����|��#y��G"��)˾�v���r�(��ťb�3�@�Rt�Bw�U�nI��oG}&LԤ�2��[S�و��sj΋z���¯��K� t�8\��iF ;��� k�k�O��p�,n݃��,z�Љ�����5��A��y[�`8Kb�z~>����G�J�mo�\H�qx�������Z��a���b����+H�Toj�q��;������G=9�Ajs;�振����#,'6pq���F>�q~�l��1�+9��M��w����1OP�����?U������Ѿ> ��C�����J��/����+ѩ|DV��l8�Zu*���� �V��q�L�8҇&�9�-Y=\�8̸�=��Z^�a{v 1�`i ����\���� �eu[�5��uM��[�[�oH�toh2VW�P����Ȩr��vt%��N��o��HF }��wed��zYC��\�{5����nF�/�>�w�a�(ܜ<�&dG���m��������[b� �S�1��K��N��͆�Z<�K6�.+��R &�����ˮo �v�Z19"��(��eI�[&��� ~`�ey�B�0�m�$�������A*�ƞ|� ���� �=�m2�)۠y�` ����I^FZ�R�bɅ$� �gp�&ֻ�-�֗�}�N?��M��F^����,�?�’��_�s��:�e=5���gft��na/��=��]UP��!S� Ɓ]1� ����QNo�{EB4�5���!+3�kF�:D�l�n�]o�!R��(x����I�odg��Y �͖V�㨽R�0�,��_���� gv�^:�IZ6w�? �1��i�7�5ۏ�^�����vV��+H�#�K|��wJ�ᖀږ����A�Wi.i�O%���I�Z+�.f<�=Bk�ԟ�~�us m�x�=6�8>�1���} endstream endobj 1608 0 obj << /Length1 2520 /Length2 20222 /Length3 0 /Length 21668 /Filter /FlateDecode >> stream xڌ�t]k�.ܨa��Z�m4�m'+���v��Fc5�m4ll7N�����v����8gd��yݺn=ϜdD �t�&vF@1;[g:&zFn������������L������L ��dag����#��$1t�����\�L,&vn&nFF3##���9rD ]-L��);[����������3����T&..ڿ��6@G cC[����9��hlh P�3�:{�+%����=7���������-�����t:�M�����*�� �bn���X������ �-���N [�#� P����m�6��ۀ������?޿Y���lhllgcoh�aak0����d�ݝi��&� ���@����ֆF ��7� * A���:'cG {g'z' ��2�j������� ��� �w~"�@cP�=���������Ϧ�&��K0q�gP��ppJ���$��#3:�9��@��؜�wp{�_J��bP�>^�v�SP @ S �����+����������� `ba� 0�Y����M�Ơ�;Z��A��`����']�n���Z{�1�k� �Ҫ�b4�_����;���� @���`bdap�|�E���?Y0��5�p��,�K�����O���A�w,9;���\�������������m��(�������X[�������h m,�=���3h�e�@'�����>��@ ����t6�A[3��6��I��h�`�ll����-W�}��-l� vN�/#��ҁN����p��_* ����R�������bfc::z��F Bl/&�14����z[;g� T������<�� ��E#v���`��8 "�A����� �1�� f���`���@���]����A v�?�.�_� bW��@��]��+�A��?���bW��@��]� di�_� �3t폅�����J����� zӘ:����W������g�_� flg Z��r���������&1���(�"�� �#(m�?�7��c����#�o����?�A&f�������ꬹ��9�� ��? (%�@PO��A%[���a�2�j�� �j ::�Ѓ���� ���_jP1�Ԡ`�����F����� ��4j���%���gt��.v�@#�Eda���wP�5����b&&��?:�j�ӟ�ANN@�/�o��?�� �z�� *� �vfp6w�cԠ~8�����_�@�h\�Ay��c�@�� c���5��O3A�<��S��3vq����w������4�[^�3� �� j���u�۝�4K������kٱ��:��*#`��`�p��(�� ��qs=thK�b���~���n+����d��`]?>,����������D3X�Y�� '�Bڽ[��{]ُ���]Ž*vi���h�(��9�\��y,���t�0Ԩ�Hs��fQ�'���i�|N�Y ��6�c�=׾�0;ua�bka�Cܢ�M�{ �Ha.z��,�7�f�M]�C�?`�Ze�i��[�:������ ��@�I�)m���H,�^ժ��\�b�?�0Zk���mj����5S��� J����6���݅���] �v>^p�ER�r��[��E���UxtL]��&��쇺�m��/��ϫ�D���C��K�ӎ.'Rs�Q�b�+��R����� .���M)x�;��w�+�{bdB�14[m����P� ����OX�r���F]!AOնߋ��G҇�>��C8Ԅ>]���h���i e�����"$C�,�P���+~� ����Ļ�i5Ċ*��Z��dp�Ex&")B5� h����a"C\o�tD·|�$e��ֵ ���a{οF�M�GvM��2'��� ��nUl�^��$n2rFEU����jK o<� ֧1W��L��b�����tR��p#�o�NYC�5�*>�zu/�~��KLO���qH�Z�{�E^@��,�_���{J\���?Kc�a<ɲ!�q�夞 �� f|�ٿ���` �D+�"��F}%��0hm[Mt����W>������}u���A-�@������Cj04�F�����dO�+D�糸���t�N1PS[����S�1�0ڐf*v{X M��9���" bsWiP���o?:�ʖ�(�%�ȡzP����w}�鶾p{�z�#�n�}N1�S4[�f��s���·���L2���"�]mXcHr�h£�jt�I(�7Hz@M��6:��ǘ��-�)2L�r}���F�18���o�fó��gh���XAԹ##� ���B���%-r��l�2�f���k�b�͏���K��������y}�u� z�1�,()6��S�o�� �#���y�j. ��f��ew�v���Q���R����r/p(g2�����y���VU^�鬀{r��wmΓ��)> �l�\q�ZKR��W=ـ���7��3� юB?���ȧ��h�T���A⽝۟}�+�5c%���r.ZZ���H2J���Wm������#�<���7�@�Ն�`��J�'pd�5�`�V��2ٗe=�[3�͒��{�ON��U�:��yG`�UYx�M�6�R�r�m�71�tܤ\a'��U_�R~9Xq��E�"��kr��o%��o�.Ӝ~dD�46�x�,�*�f�/}#�xz��#Ef�s��A�bS�E�O�R�n4sg�&��J��ᔚDz�m�pZ'�L�~�D�2-Y�����r���f�/����r l �b?lx�;~���d#�0�iƀux���OS���^��|��� ړ����4�ĦؑYX�&��p����Ғ�{�/K+��Z#��~�9�:��9�]���rs` ��ꑅ$����5�ߏ8�S��7,&�c]��\��Z}n�ao�g�R���"�;k6�S��zGf9�7��a#���U������Yǻ{j=f�� ��?8����K,-'݅�T����1��e��&�a �q&�� ;�@q�˜�=��[߆vZ�]�Ʒ����q׾$��6[�~��p�↗�u�@�r�Ĝk�� �Nz�uʏ�S��q�7��O���/<�񽍅�,�(_��[I�W��S����Ho�C�Tf�M\"�h\ ����\9L�<�<{>�W�h�L������d��i��z_ �i z�SRn�s�ƌ���:6��-^s^Y� ^hɄ��UI�ⓖ�O���QمN ��������R�q�u?�p��vŵ��7���fnAK���X�6Ԣ��*0�Xs�ZG3�� ���������ۈ�*�%n��a����3r��1JMz�[�N5��H���2�F?����f��j��f�3,�TK�lK������6u�R�������r�M��6����A�c�s��̜�A���;|wQ�Ȟ�Zvd����l���^���Hw����Wk�<4�}GR�鱩���*A���+����hU?�7��t��s3���F��o�6�v���Yh��;�B?� nv���4�l��k� -L&��P�䘲���ǻy�"�ٲ��1�o�O���?��� 7��� ��P]u$���l1>�1�f�e�؛Y���e ����ł�����]y{:�$��l���Բ���� �ѯvحz�W.����|tΨ[����VnO�8���'"ة�&�#�������B��UlX�վ�k~�������W�E��ea=�q�!�[��tt�Qz,��rzv�M�HO���z+��,����A�Sm_���F *y��^�C�z;] ��B#vb_�K�>�'������!�D^9>U��_8)?}�A+�d$�jZ���wϠ�'��+3Q�ύ7���*��AXs�k�Ɂ�H�C�v�aK�o��� ��L�V����L vB_T�G�~��-����Q-�i����m�X<���CI3�P���,<:��a�î`X�*�W� 5��n��7�'�B��c6���a�����2����w�� �'���Nvl��}t /w�}�X��j8}�Z3�~�&��3¯51�al6}d�@�;o��.�{q����ncz#Q��`p������W����R��D|����a �l}�/ª��`��Q��S턨j�?�!r�%(�M�n�!�Cs=T��{�E[q ���0U�Wx�Q*b�Ǔ2�-V�T����Kqz�:#�:�7ێ�!��d�h"&��m������F��Y�e���+�@UP�K��Cԁ�oB�;_ˁe�AǗ���h�9g(QE�ߠC�D��S�/ O��i\|�h�Ҟ�3�mq"��<�[��`j�����臛����R1k�oj���œ�� ���,����ꕹ&u�)�I�ڡ�Iƿ]ܿ���&2oNKK����}����ƧWXQƉQ�������|;�D'�_)��&j�C� t(���j$!G�Y���������r��B�;g�n�Ý�\[�qæ{��H�<�>���ޏ�&�I�*!T��2F�4��г��e6m��ɯ܇)� ��,�m�1ۿ~����xd�����&��4��RaS����2��U,R�dx��x�a��=A=���g��F��K�����mѢ���>z/�mC�;���?�6��+1��ٽi�}�{�<�\m�@ԯXtu�Y{��GD�殝����F�����C"�hXl�L��6Aj8ɳ@h��^J�ֿ�Tdo K�)6�,���儈CGH�����6����x�*���ϕ?LJEԓqCC�L�x]e�S�c.q�t����f*<�2ƙWr�J]�8t���{c����%~�i��ݪ�_黰���oB�������ľ%�3\���XTC�3�B;��v�[G��0U�"������8n߾ʥ�P����3=u�@lU�sAx؋E|����D��٠v��,#�J5�����t[wN ϸF�T��~>�-�I�/�@��sK?����#fI �ϥ1�<�$&��/U�pc�Y M����ʪ[�ºe7�Uo����׃ a{�;��"���<~y>DR�n2�g��,�� ��E”Zд�� -�`�.�Ϟ6�] ��tQ� ��>��|c%��n2�'��Udҷ���  �^��5@{-� d�ݭ��6�1���i���yo� �0��"�E\�DGA��Xk��GnͰ<��u���UZ-ٜJ��}:�� T��:�h(]je7v�%�{�hs�CecۊV���n��丹f�NH���u���T��U7�q�Ɛ�u�z]��Y�&��3�c�u�D[3����ٝ����D� a��* �$X_�&�#,��(���k ��P��4 D?�'�pp�im�^)�����������L�����1̶��v���fklU��$!�y�T1��C����I���ID] �7ٹx����*0�`,�Z`��|���#�������ZD0>�]s�8�".Y�7E"1o�_����k~EMG hu��I��Ɛ��T���� g��A�����a&��S�;���sL��A)*]�Č���QԒ�)U��z��D��Ř�j �i�QZ�Ϩ��+�q��!�<0BQ���bF�b�U��7����� ��� ��2���xꞀ�Av�):��g[�pv�!c5%]N<�4�*��� Ƙ��:��b� ġ*M���Jn�H��ʠme�v��4Gt-��L_5�V�c"N�n�,:�F��j핣ޗw ���8p�@pq����*�zy �@���{ȷ(/���l����,�;I#>�K��YL��T�.Y~ѐ.�4G$a�������e|���W�]r�@�ڵl%��O�(�)T�f��k��FB &�Uۅz31��DH����6K�RD�5Լ�5 ʵ�C=��dǸ|4�(�l= 2����t}'�+z��}N��;1�%' ���ݳOh����M�z!���6I�F)���>�GH���1/P���3%4��I��-��>��3JTrxR��x����g� ���L���F�B����� ���b9K���U7�/~�h�%�]<�VJ�R:�ˀy�� M�{ _K>�2{,���a,���Kߞ��|Q�/�H���'{��s�ө���-V��q��Y��Pm�<�E�z��-I� ���,���\ �OC`�Q�����Y��y}��lb���?�,/ ��*i�vh�Rr^0i�x�{��@a�� kp���Xz�R~��|V0$+i��UW����.��|Ϲ�a�� ,;b"�m�Ru+>�W �T�|�u��L��aS�e ��J�+�rrnI��F�N�s��*뺞�tfċa�{��yK��G���iʷ�lj�0j�v�Ƥp�>���bڈ0�+��޺��b�ܚ��b"���ddItu!Z+����h$�*�>,��(}�?�@|f������~��$� ��t��OҾ(���~R���':"C[Q���s:C,����+��$�:���d �d!z�4��f��i�ڶlw6N�� H����� ��V�x��i��._��%�Z�n�wI�w�cD(�� o���Z�V��4*c1�5�es�^)� �f9u���O��;�����<�J�R��&�����Z[6yFGp�P+�wS�f�J�TU����7+U6�-՛���[2l6�t���⡸�[D�����SjHW�r~V�Z�T]�g!a��_%�S<��>&9��� ��,-f��lQ�&�n��2�¹�0:����l*A�8��2����t��(�~���\�HM� ��X�-�n�cK��KU� �~)�C��M��a�Kg�q����"^��F�G�� ��A:=?�GJ���#�ȹ5�Ra�i�N�����6,�5��q �y�[ s�o�����Jo�S�6����������׻`m�+��l�QE�_!�# �\�RwV4v�@ߘ��n�LK�l8$⟼��31����E���r-3��d�� U#Wo�L���o��U���}b�^�&-���j��$��(w$Zj;���]������4s���������.��#����țc����}lz�Z��������k�X��`�x�Ybo �w|l���_dgx���.�bf65X�Xܻ�����=x���@J䂱�"�%Xqݼ�u��0�|А����E�Q�]��@���H�)�Qk ���u��*-�����zd:p^�.��-��Lk�F�F'�O��4�$R����U���o&�)s� r���I/��1���U֬_�}�b�2y�������c��n�@����-�^@ICX�҂�F���}�����O�� p� H��d��� �2h�<�����r��&��2|B|$�ρ,+� zs��i����BaO��¹�h�`���r�`��scW��(��.r�$�� �cn� o#��o�ǖ��Mh|���luIO1I�{=<����I�׫M*����Cd'�:K1����˚�s����b�7վ┃���'�]��n�.I�j��QS ���)�w^�������b2l#���4� �.ߩ�ab�� n7����Nh�Y*��8y�9����~�����\����[�2�~/��;�2���Þ��_�n���H�a@����ȡ ��fZ9;J�w��xG������1$�m뉎`E�����z���"n��9���2L��k������ oS��J��N��H`�P)�z�S�����x�B�,�j����z�hx����I�^�wCw�d�T)�ssc�?懶�c�kb�ͫ�0XI� �o���"�b�CFܒ��)�ړj�*��k�8��dU E|�b���6�!�����?0�&{�D��O}�hD�%g�t`<4O�VB�;��:����p���eş�G� ����"�8� x��_�W���\�����'k4�v\���{J��FT�!�J���~���͎/`�#>C]XToi���O&�P��.7�����u���W�N�M�\��X�{��&�\xU�L?!����(�(>�OVg�.\k#����W�f�$"�<$�{'��� ����:d$0e|L6����W�k8̟��"��{]�jQ���L f��$��!��E<9�(Qi�6�3����2+z��~I\D�,j�9���LSX�7f ��C_x\�uU��~!�a^���������t�4� ԑ�I:��E�B�jT��-f�R��t�:?/��NE{���uDB��mo��|���Ǻ8J)^�j�:�h�e]j���@Wמ�-~���Q%V/�����s`R.���-���cV;W2���-S^���M?U�JN� ܳk{��&=|����Yڗ�M��z�A��ݘ[��_���U��\��%�P���t����'*t���)E �s����;���q�;��>>0*�p{����#r��ä+�"��q��>�n�l�2����_K��&=ʅ֘��y!?�ŕb�,��f��) �ծC!����x��C7|ȕ�Y���\�FNE����PX�6o}ϥ2x��҇Bdl{o���£�S���w�P�|XeH[����Qh�:�<�w�YJ0�Y/�)���Z�m������,Ϗ��oc��OQғ����TWЭz'�l)O<[��{2�:�����t�����F y���m ���*�Nܷde���og7�h�vL��g��Ґ.-=�<�*��8e60�g�T2�]N%��w�oQ�k"�������B���[Tg�0�E�=�>?��yχ�b�6tk�OԎmY�dI��^H�ry���@� ��w��l@����rY&Әǯ�S���:� �^�~k���M�_O�塩.�=�{�u+M�8�,Q;ъ�`���tb��G�zFk�t�.�)�Ď�V8hPFO���QP���5i �{�Fבy,V���K��>���33�HQ�N��P;jd��Z����K�N��)�������6�����gw��߾ZĐ���%4��a�<��U1�#\�����o:VUk�*�\i����@��t��2D�����4�u�j���a��C e2���4�:gb��tbk��b�ÂE[b)� AJ B~_? }���m�z���V��G�G����i&��6��p�9Rk)��LZ����\C�p��;�a�ȇ�E>$�eagu-�hh�:��[�=�E��j�H�s[ �&�~�>�H ^��� ��{P5x;���+�k0�_90����;D��K��,킫?��9���\�h�$����=3D�ݞ�� _ �&�-_�p s�f��s���P6 �^��s�>ߊ�`���谧�x$�zG z���3F��u�]�>��z9q�#G�TYv�/4yu B��Â�f0����S��aY���*�'�m�jx�\�-KpT�d�d���O2�z����k���ث�7ubO^�w #Z�H�ɱ�Rp:;K-�a*��Nb�1�٫ ������f�6�bZ���l�_���+Ӧ!l�ݹ{���F;Yh�q��Ð\��B�*��FCqSl������H�JE�h�׹N� �Cz����B5r��`�#I�`.LJO����X��W��1ɷ,�;� �ҟ����Ll�$�Ml�^5y��Z�j����z� �Bْ�vG��ŭ™y� c �/̫ɰ���6��_:�vb����^'��I�*횆MXHy������п��C�����Q�w� n�rc|�����S(6ӯ0���K�;Q\9����Q�TmF,Cq&L �|�J���h��5:���+p� ��ew)�L)���.�u*�� ��D�t������.%�z�`��k�\��Hz�2嶬N|GM�������{�ӎ�����d]z5�,��L�� W��z�N�r���Ġ��v]�hL��=�w�<�C룡|�:\��i��Ќ�f7Ӣ&�ڣ���Ti1!X��Q���@�4r��kp\�Ū��O ��73��,�ꉦ7�s�Ըj�FU������U/~O�Zu̖�t�� �l4 jJ�/�h�PmKjbʶbۆ;j�G��dM}�D�A8ga�R�/y/�#^����?�r�} ky�e��*��S%X!�_�VL������/�����/gUܖ�IY�0�g?�c���� iE�aWmIJ��jy����!@N��|�6'v�y<��TSZ������"���E�%S�vdJ�3�� ��Ic��G�P�ōz.�M\��P^�p��_��Z�QT'{�IP� 8��F�,i 6"TC�y{=��ur����9`�'����ˠ����qPsgZJ�!�\<�ĕ q5W鿠ͩ�� u�?A����pQŠ� @5������̵��)i���3��6$�|X!�d���f*`� ��nob�u3Jut\���+�L��[B+����CV��Oe���k�Y�6F0�b�[�v�;܌ɱP\�_����*�pC�<@P�_�� �)A��K\�54����:����$t{��Y��H@J�_��z�m Ah[�p0� �@�ݠ{�T�"R����_��Ǿ;�@p���ilT8џk&i���4`����L8a��2�m�<)��ը�Tg�l���ͪ:q��7t׶I�86|2#�x����!�nۍ��r�`���2��c� � ���:_�������E�iۀ#���/�,*[����m;���N�k��Y� R "xK�Ę f�j�,حO��?��95@�"+� ��N@9����&����C�r�A�NJt*1�E�B��v���g�'a-�(j��҂����3&����}�!n�I�s�dFY�V�R�k@� NG�=ݮ�ũ� �x!WJLg�s2X%��ʣ���}"�b�����]�5�o���9?�1��&J�Wo�tYiM.>K�� !��j��:SUe��4CN��l��:�I�?a������N�畱h�zz�#�4�*P�U���p��k�qr@�h���b?=(�;U�5�`�(�x|�҃V�:uf�֢ڒ�5l����uN�����g�ƅ��ks ��P+���ˏ8�̕u%qt9��-���ҙ|���Fg���|��"��f�i��7lZH�9�e�e�������;h�OJ�1����q�FT���o�,�G�)�\7���a6��h��y���Mz�_���U�:�T�3:* �X|��f�I[��]���~y`��$�B��E�.�����?����tik�k�5�m묦����t,F;��/1|����q�T���u�x��;�gv��A���S5Qt� �kq���-O����5|�����;ע8�T��=o4�D���q��k-H%a���aK3����͕���6�"2[Uz�R�(��T�F��0��̝z$��9�5keE��:��K0[��eM �o�i���� ��=d��l{fpjtڬZ��^v�v�W�H�/ ���\���!���`>�����Y��UiQ�4.�A��*G�ǵ��iQ-2KvT0Ŵ����C���#��}}��9g�k�nv �6�;X�y�,$Vʏ��8\���x,#�f��׽\d���(�TAi�{�e�[��7�f]���� ��b� �a�ch�/�YL�����8�[�f� ���&�oN�)mFxg��й�񎛄aE�p�K��[�c�*j�]qJ�� �V͊��8��[9ܓg�A�� ���2�p�onz�Z&�`����\r�N�W�+�p�`�j�ސCj�3^4����1'�w(��p��}f��s�h*���p=N�`5�� A�gE#J��s�ky�Nw!��|�_2�h���{����}ޜ��b ����Xf��Ġ� = ��.<mgw��D<��w�t�"�*(��$�q�8�U[��u���+�bLb�q�%:��S0�� ���En�-D�,4{�yx�������;_�꺞���P�|��j�.����#� e���O:**?�{���C 9���%׌�IJԃ ��6:�,��'Q�b4�\L���%< ��;[t&�w���m;� =I's���e�r ،����<� �m��JO�㚄��c#��z��f8����q�I�#�1|�GN�b�k�ly��!"�-E�<��5Q��d���i�1}%��!)4�S�p!�5ו�Wgź��������<�le�^fM�9�ꚧ��u�$�����3hF&X���䮗�*aV>�[�K.'8}�f$#�e5� �j���#�_��?W�Z�����m��r,f�.M�Y��l=%��~��)����6= >�]��\-��ӭ�E�������-~1�+r0\�5,n��Ϛe��s����m������:݂jw�J��N�z�N��4���7W�p��T5b辁�9��'j�1��&@���ִ�i�BVJ(A])���$�+�[( ��y^C�$���RV��{���쎁�u�eo�, ���m ��ظ6kP�H�8p�y�@��-����f��0���Y!������G<����qMp�x�1��C,��f-�?�=�&��Q�V_���U����N�_�� �ڂZH�#�f�r! h�mƏ�b�o�O�����)�����u�AR0���3�Q�VE��%dž/P#���e�-ߠ ��N�Ra]a�ƛ��w�db�O�g~� ����5�����w_�3�?�Ȕ�`�}�Z��U�C����^g�@8 ��M-ae���W�rg,V_ӆ�l��i�� }K�>�ʔ�������gsZ�~��H&�����F�������x��a9DOB��X�Ʋ��ON�˜�9�i���|%�2��9���"�䒽�~�wl-wPϞ�����c��<=��3��n����~��r42�%v0j����2��T��� �й��z �u�2�w�n���t�k�֩����l<~'��NK#�r�;�Z�e}ZQ$D���(��g�>��1~�[�O�C��i�)v�9�Sb�wi�B��"Q�6���c�Sҫ}8����H�|�5��)�~���8��p?���f� �ї���Ln��$��0J��V������n��g����dB�����[l.���܅=ܣ.������ߑ� �7Q�������V��C�؞|��vJ�I� l{�[�1:��r<�*�'��Ea;ӻk�F�;����yo�#)��þ W�en2�46Xm�{���������$���߅�Z?0.g���~��Hf��0�2\��4�N+�G+�0ӣ��p�-�6<� s*�'���t�KV�T��%v���8�1P�'2� v��l!�v��#en�����ZĽ�$�!�?tӁy3�6�N^l C��Vb�?αkj\�q�l���v-]���J�9ʞ�B�*�G�,d�Z��r576���oB�j|��D⣅L�j�>T$>d:�kh)�S������� k����r��D�H�Q�AO��wgdh���[�G{ON�"��歿�LQ�획��f4��_�E4��T^�"��E`�JZ���-�iH�ziV5��qz��9h�B�2Y�Y����<^/�[ ��T�Ӛ� ��H�_��_��H�|:�n�4 �'Ί�ҧC�2�t#�q�gKG`m�6�c�A+M���b�c�;veXʓ�E���T���͵A��@G�����or�c�n��cm���W�>u,G$�w7�f�,��(Hq�A���X�F}4}���� ��c�Dz���X��h7t�p7�Q���`��D����������=/���蒐�#�f���1�tG�"��Q���~���+#�W��L�K�#)�]T��Or���cɥ�C�������P��%�$����H��!����?��;��^|f��̣D]SOU�� '�m��Y���L� G�3�*ٴ���^4�4$F�k�*nE�\Ε�'�zp;*mMvcmѼ�i�J�U���'� �ExGu�3�4�y�.��Q�� �n\���I���9 ϟ$��\6 �^�Q�u.���%DI3�#`�)��)��ԗ��TB�Uqn�Ń�$ �.�s�s��"�#��B�VIOu�G:�'fQ����y���YcL%���l�'d��^���� ;����z!��m��>̙�ꅹ�)��5+�Z�+)���i%g����`}�Mt\Ŋ��srVtS+�ב-�<�*�v�&�y!��w3����Ҥ����D�Q!�F���n&���iI�5��f��j�o�V���k-���jC=����3��C��"'^LP��^�%��P����]en�'��x�D�)��>Ƞ¦�t��|�U��>`�!ъ>��eU�����R5�,��lѸX�Y�z \�.�����$�M�LdԿ�X�v�/ ���;�\�44W/���fU�K��.�k�q(/flp֍H����K#d����F�b`� s��VU�I��Kcu�w�F]Aň�����V�I�L����S/^ �v ܱ�)��U����˽R �4t=jLoi��:y�—9j�a}pn���G�d�%�|=��~�8�@�Ď)cb��H��|�uЮ&`!xp��`��!��5&���c��]�k*�f�5ۡv�*�����):� 4�+���~ȇRM\�u��qr�7�q4�� ��u��� ��5�4vE���Ĺ�dఁ���}�� �S`�,��e�A&p5)��E�a��9���%~�yB��P垘UQ�wb-�`�5TVe��ů���/��"K�]���� �#��'憪2,O �_�Ql�S�x<�Ԩ���<" �Xb<������]���͏����zVm��(�Uuq_��볐�2/l��p�nlW�@�ES^ |G~X�s`��C��,Z�xۤ�O�̷w���\tgHU����B;�����P���3R�h�~EM ab��4|ÌQ��w�z��I� ��ؿAz�J� ��m�� *,��A{Y��ر�� [ɆKf�H�s$��C}���e���� �����٢%��d�,[�n����9���#�,nWE:7a3�,�� �sVH�Se�S ��5�gL5Mx���h=<�lX�5�$���j�f�qƓ�N9���4��������3R`'��{F9�蕂���F뱻�4 �B�mD�(PӁ �*R����B5 ���'�!��?ŴM%!��Dы��TĹcZ�- �g)���>E�nL��J�֍d��߭� �j!ݪ��gJ���8�� $��I���@��r����z��'�o^�#Z�~�xPA^�CP%C��ź��y��%[�� �(2`:���]ݸ!�~j ��8��J�J*�,�� %nI v񞧧OG�����-",˴����zϞ����Ys00�Έ>u:J���~�d.���Y�>D6���4����S0>~f� ��G� ��ɉaՍ�� ���%�����Y�#9��r�,��������b��3��B5&�����=0�����,�:i�P�D�q� E�'�jpCU1�,�o���2'@�2�@}���wN_���(�6�?����!Q�&�� upRx(��B��,HJʢ�EA�Pr�k͹�+��]l����/숄~� Y����7����+� Egc>"�����P��/_��Ƽy����Ksk�G�(��D�ڙ�K��B�No�9�F]x)�;�;�j˕|gN�����#�(�L��A⟭o�|�m�$�Q�sX�K)A6o1�+�i5�ӯc#CdfA�\�T�;h�Nj#�6�����̈́�V�.2�4���Phk�S(A�e']� ��* ��s�:��4���[p+��}��?!�)X�t�K��|A�W'��L��]��LY���SbZh�ܦ���p���� � ��J���JO�?��@U �GX"Z�M�~A�y5�w�L*9k�ܞ�u �t��C���6}f�楞�}��a�sR�zD��K/8���hJj��w҃��M2F̌G���ln=ʺL$�СͶ��{�51N��(�� �Kr��m=W�����쾰"Nm�5у��L.�s�('" Z�+"b��,/��fц���;�NKw}� ��:����(f��Y��1��,B�-l�-��^�u����}pY��o k�‡���M,�0حR�q@�� ���m�EY���HA}`�zBE���76��T�=��)����(Q��w���4���Dc1����b1df��0�����(�/��¼1�o���~ǃ ��0<�G��~ج��_͙�Ds�֑M>�B�]��F&T>$!i9r���Q������U�-&'>&��T�-*���M�fÆ���?��#q��_�̤��u�.��#���o�Ay>�”1AeW��0{�U��`{�m=de� �5�_]"d�Y�\#+\�M}+�SV���u8����kR��F���_�ˀ�:k��th ��[���c� �{���������8�O�:����Y���5���:I�nx3��o�l�O��aTc? z�7~C�6�R�#�*�-�����B$��d�d���G?L�,z��s$ƈ�]��vv��`iQ;Z|ǔ��Ѯh5+Og�l��k�N_� ����@��}�e��)6L�##�@���)������Z+!�a�ʍ��p��K�6�I��b��a���$��Tf��iE��N���]E���1�yg��.�G�g[�B�`�%`s�=~bz��"�&�-�)�K��QX�K���l����v��PjRqa�G��0���cZ%��=�� �V�i����b_$3/�We:���ᇈM�ώdq=�ӢB^�9�y/��ڿ�I{N?̑��J&� ��q��9�du鳯gf��-�6�-U����2�:1�AU(}T�S��P�Qˍ{��a��7_И�s𜢆��ũ�PL���ǕCC2�F ���]s����k���z��m^VpJ�����?��/��3":`��&hg$�&�f��㦾��]����dA\�g����*VN�\<�)�2#��q��'�N��{ ���U�v�"R��4J�/��Y��/�@H�ur'��^�T#@��ea�oF��1N2&;�Ü^���!j�K�ځ2��\��);�1���Mu�( %�\"��^���<�eP������t���`����ת�����D��0���Q����� )cv�+Gv��Vexu���pWUf�� �P�T>+y���aC�U��5W m������H��䧜�T_���7���_¶fk�)���w%���������\P�(E9TC� �*?��` �B�q:!ƥ?��zp?[��we�0?i�����2sz'�~k,U� &�\�CAr}J���\�绉I�:����T�@b����c����ꨂ��.Z)�:6W�" .�;DD )l߂P�p7�}��Qb�ל� C7���@l��)ȏ����v��4�2���pDd]p� :�a���:�F>�e"��,$������ IΒ�k�{}*�.��,3��<)UEf�< �?�F��wǜ�V�8K��ͮ��e��&dҿ�Ռ̟�|�P.�?%�n�ErOJ�v�i�t���'s��JD6AT[+f,֢RXi�c���,����>��ʚ|d(�������B�c ���N9<�g�PH�*� k�� GR�8����-+6/�I.؋�=vA��5�U��lW�w������Κ�+��U/~nn����xz�A���C����z�ș�8�D�F��/d�ak���F�LY��?;q/p���+*T{��_�]>�&x*��/yl� �J�Cg���x�-W���)a�2f[��.j ��ʗ0�2k�j�� �j��q�dDc̲?�z�fZH��r���T{��=3AT}γ���-�v�a|����5%�8 �:�r�[�gG�<�\~Q�O0�ئ|���k�y ��&X�k7Z�鷚!���Rs`���%I��:k�cB;�-��-����Qg* endstream endobj 1610 0 obj << /Length1 1991 /Length2 15037 /Length3 0 /Length 16256 /Filter /FlateDecode >> stream xڍ�P]�� �.�-�F�����;ww�������� ����s�������+�`���=G��^�vAF$�H+hdc��v�e�c�K+J12�����Ȕ�-���Ñ���l���`��?l"��Dik�7'K#3���������������=@D��� M�fc t�#��u�731u�8�?� CJ#'';���A+�����5@Z��h�q���%@��� ���?)(xLm���]\\����l�M�(i.f�����h��d����ߥ����L���P�1vtѷ> �f�@k��'k#�=��t���@�h�/�Կ4�7�H���t���+��������6V���nf�&c3K @VL���Ց�om�Q����#^�Y��R����t}���<@�����`hof��@�`f�W����h�����������/}"f�@Ï�����r-�m\�=���ͬ���*��ɖ^���� (!�o· �� ����������������f �������/[[��G@/3c��8}g ��� ����##����`41���'��h�/�q��f�M���c0����'� 3���t�����K�KH IP����:��l\�lLZ&V##3���������[����6�����$;�{(�� ����%c�1�@�?�����`��������o�����:��W������~����Vf�n�f|L����H�|���������@#3'���p���Ak�����ca����A��h$g�hh�����]��u�4���8�����220��ǎZ|�D>&�o�c���XQkC��v��� �oo���q�������F@׿g@Ogm���(� `lc�׽����2� q�E��ؙ�_�A�z��^濈�@/���S�����8?���1dѷ����� ���|��;|܃���?�T�ЇP��"�����G�c����F@F=�>���.�!|�i�����r��AfЛ�?*4�G�GGM�lM��������?��|�?�GmVH���TI��~H��~(��~(��~�p�G� K}�?���)� �?��N�?��N�?z������������o�?�k�do��*��5�1���n��@C��EC��ڀ��Ղx.���L,��7aw0�{�8·�~�<���y�˂���[��L��Mj� :?=S¹0W��!� vi<�Qy�N���$��4����L0/��]��(�h��ҏ�yț+*L/��4��!�MF�Ccsp0#�t�wT ���wJ�:�L���?� �1�� ��Ҁ�m���� �Jޥ��%���J�M���zE���)����S8�+�pgH�M�|���P���>�(E� ����b���$z7��@��E����W�+��{e��� .��[G�&pO����~~, e�*�/�~��k�r������fIa������E����<#%Z�-�C6ѕ�n��R�+|]m���PYD�F�||Ĕ"�Ƅ Df0R���;cʯ�D=c�J����!��:�.ڟY&��3Z%���P�!������m~�M3���N6v���f�խ��[k� ��'Ż�@Uj-�zu'��{�&�N�/�)NJv�nU�M΁�9����B��9���҇R�a� r��[-�O��� |Xf[mY���}�bQ��lp������y���ĥ� �U .PaQ����n(wb3��)��l�͓�Q�>������/���#"�#搅���M�C�o7���i�Tз���\s����FuUn�sb/Z��i鿀��+��1��<����4UdiQ�i�sIG?^LO;Kd����?\"��/Ϊ��� ��J�A-�a��0A^���n�q>G�PP��ȇ;FÉX����B}��������n卝�.��/�0�����'�z�^� 7�X�Rڸ��h��L�O��a�K�CX���Q.2��M���- ���p{�U��F���u�#�"��0s6d����!D�)( ��)spf�)� J�F C)br���!�bk֍���"��=��_��w�a6Y�(D�OBR{��v�#��X �����+$6=���1��y�`]�,��Y��T�K}S[����t\�[~�i��ouB�)�i�%�3�8-?��w�gw�D#� � ;�Mo��D>�g���`�;q����A�i�?���l�����A�/y����a�; �'H��࿻�,��4_u�K� 1C7ucпy��r�E�S����p$7أDgA�Z�5"��9�A��fN"f�U� r�<����qZ2�H�Eք\��m��d�>A�D��>��:�?���\ڵa%Z�K9������O!�M�����|yL�ǜ{~Gl�y�U��v}{��+j\��8{�Ʈkd!'^ ������K]Lҳ�~��3�3���x��+� �%�ek�R�bؑBE�/��2M���8��4�-�Ty ���W+��?�4o)�0{W�ug�T:_i����ƹsN[��>�h=��0�瞗�M#~�UEzut8���� s�\��n�!~4��j ��8���S��Jؿ`qYI7����K_���pW=׭��F���&hZ�y���+�$ԯ�7�,���R�K,�JksɈ�ZnP����1~��E�5Z��f�z��j�tf�(B�m�9� An̯�:O���T<��*V�\�X�p;"�W� ��� Ղ��7�aA�#�XG���i� �:�d���r^!�$>�'�J��M*;�`��=����4���͟�N Nh��Z�ͅ4�%54�%~Yڑb�%���-����NE+G".���=;,Q���%2Bs{�I\Y* �!�D[����k�Ox ���hQG�0�ɧ�^E�Y´�S�H&A-���ep=%\��٨��h�I1�D�ȣ�̒㖪�H��[j�ا�f���_Y(�v�ާ����F�hP�� �i�����D�=�I��CW�e��� q�O��&�8ra�V� ���������"��2}�DdI8�#�w���j����<̺G��|k�H� ��Rx'7��כ�}}�~�U {�8�2\:�&Ӳ�fhF�� $x����#@�$Et�a Gj�e�R[v�Z�WoKǃ��M�ǍbV��������Tæ��^�ƽ(t#�tfЧ����G��O������!d�p����o�j��8�"�C������8-���Tzg�S]�I����9�VL�Z�Z>�8�t��`���g���Q���.-����&N��������C}�g�R.`M1^HH^�ޞy�Rܽ~5<��T��)�g};�<��\Oc�=�f�d����|�6B����F�^f�c��Ћi����e�=<��F`���2�c\���U5{^x��m��`��%��h=� /�˭T�/(P�Nn�g��6� � ���_����cK����8�l�5L��0ȱX8 �u/��)�t������%X��>��Z���,�G�mP<�J8[ ��T��� ��`����Ѯ}f �it�½��0q09���@<� �7yfz;M�%����a������o�-���*Wc_(�5O�;��X5� ����_����h+N�Ha��V��O��n��4؉�eu#�Q�K\�AQ��gA���8�!zl�|]oU�`�JM�Y���bk�m�,ZK�x�y���o�y��/�WP+n����y�!�|r��5�c��q'�m;��X_�yz���-S��Ϣ���8\���u���#Ku�*' �H-�0�w�2��$�����$��5�2ϘQM"��[������"!�˱���O���O���{��й� ��W���t�@bOX��<=W�c���b�/nRJ�}�V�C��^��������Q 5؏ff%N�r�c��M�..�*¬Ts�ȕ~q>�M,9��4"�b6���Iqw���i>����[B�z��9q��������L`���]�-S �Qi�x,؈�z@�#��V �FFdK*��� #�z�0ʸW�5�z���� �CO�JO#%cQ uNꇻ�aGl�>\\��������SoV�(P����0�z�2!�8&�*.� �+Ż���~J��m�|�$Ƅ�� niᕷ=ٗ'�J���Q����Й�Dԧa^�� q�VV�>a {��V#% 1�te� z�1�5Yx��Bˌ�$��Z���w̧O`�n�t��V(U]��ӭP8K�:��h%`��j4�!�l/���ɇ_���~�_��R�p�:����bz�Vz�X�fnߞq;];�|���I)�����~MMw�/`:�-��ބ��͛�(X���*�z����H��l�Y�Av��$�t�;=7׮�k�h���]�zk�����>~�ʨ��(s�Z;B �c&�%��ƀ��\�ذ�+��x���1n^�K��u+ ���tF�lϞL������ ��W��'�E�<)�����s �c(�ٻ�uޛȪ`��񓑢� �,��ual-.�B�{�����hr���uL���TR����>�� w.d�%m�́W��{�]<��MM�t�}�Ŧk�{�Zǖ����Ւ�.��X_��5+R��h����bLWt��*�U�Y�XS*�5��Q[t� �mjW3�6�G�x���Fm�,�v��J�o ��Z��AJ�ɚ �����ø��ڌ�P=��T���s^l/������o�ƗrCZ������B�6Xf��`��@���*vM �@���η��u�8�2�z������K-��%� _ZN�E��,�n{~ �V9]Tx�����vfL���Vj���ÞJ>�Ԍ��._hBP7vNVO�FP5 ��Ps Y+]!��[��Cã�'�a�]����%� ؁ ��v?�:�r��/ۜ �����O�mp��<�U#�,��O�Es��`T��P`�ѳ5��z�y���U�����&����m��&�]���Č�:�Be�%\9,����*Ð�bO6��t��vz�\��%�Qd\Zc��hU:�C�Cv�UMvO��պQ�$@uteo�f�qT�K���u1>ͻFl���!e�V�D�O?7W�cR v��t�� _�`;}J+�cN�DS]�g�ym���oD�}�e�Ni ���`�}������U�il��&J���^�m��聺ve���� �j���n7��<�i=2���Uf|"ہ|�̝��؉ ��c�okTz�3X����3��5�**���)�1Wز�V)z��\]�J��Aa�&�:{� ���CQ��nD((��KƖ��� �����q)p���;1�&�/�vf���>��*~�2r�rt� a_����t�+D�=�ퟕNB˝҆�ҭ`�O�23�@R����<B�����7C{���)w2qs��@�U�5-rq�Y�ӄ�����â}�y�"��+n�i�i\�B��I��/銿��±}* ;���xu����9�����2;�{��Е�y�p�3;f6! ��X[�t��bL@�� y���ǵ-(�h@>_�Q`~���oḞQ9?Ctu�sM~5ÿ͓�ŃCާW��2��=��S�9�N��J~H���G+��6���j�Ʒ���N�{A6�N$?gC����7��6�5s�^��V%!���1wp3o�Ip�?��e�P�-҃��V���_�>�Y:�*�*�duˀ�B����jA�mR��}��,3�}\PTOa�g/�X��BӃ��4r��D��~s�th�}�;)��H4Ȫ��2^�He�C�.�ඛu�� ����ĸb;K�.�ٚ����!a� *��BGF���:�bq�`$�=�/f���0^�@o���L~�0���:��p?��Z�(�5�r�v|��*�T|0��� +9�]�+��P��ҟ���Ss8���^��#�֍�T^h����Ei;]����V I�˱^�w�d���M0�^.#� {� �t�@��Pm�M�H,�sm&л���%�zO�#zm ����wZ �"��N,W^9D���MO��"��q�K�T�s0��m�0f"6<��YB:�����r���[cM�+��)'is�Y�m�L�e#�o, �JS�%Đ���G� Ff�W��.:�����~���!ݘ2��Z��͍��p3B!��폚�Q/gb�j�I��r?�`s��T���Ƈ[lad��0�k�[�b�*>Q���eƸO��L��!��.�VwN/fȶ��V��c��92)|�� 08�KÃ����ι�� V堔`��- ߕk��n��T���m�al��ky�I�4e�5���k���b��\��rNy7S�X?���C��~�)m�` ��Q��ou��j���jO��&o4Y�=����G��������^[a�+SP�l��>��wA}�6����9ۡ�L��yi?���k��v��e��}b��l�n�|{�ԉQ�S��NW�.V\�PmؑG!�Ҵ�eJg,M���������_��=����LW���,R��2X����H �O�`��b��LfgF���wHe”���u�v‹��"�M��Mҗ��<�ڎ�>����T�֟������v��7St�-O��g^vj� �J�b�|b�a9�z��r<�L@ ZFFa*Te^���}�����7�Ssg�\މ�A�&��w�Ϛ[/l�z��>���Tr��A&�\ �)�U�WD�5�5= 2����.UÊ�����WPy(ѝ"�Mw"=�,�&F^����&�8^p{s��=����G���-7R�Y�|$��3m��t�Y�7 J .y��u$x�VX�-�تحB�-H<�Vόgւ�b�=DG�G�,x?=1��'�c ��I˘�S��o�t5%�vp�ζ��?e(QtG�/�)f�R~ޖ�$$d�Pn����Ս[z��Ǘ�/ܾԪ_d$#�� :�;�@Q٪���+�������s��!�K�y0�`\��;�n��Ž�_�����!�{��}��a�ָ�m�b� |p5����qWG�Fw�h��?��މ��� ���:wAA|w����݀N�dV�pO/uߺX�hRp��I��s3wXڷ�7.�T �;��'�b��T���0��kYѸ…� s�>o1�����V2�'P�XIՕ] έ�Z|_�2.��B���h_'t��y49K����%g�]��� n)�����F�S�t*��do�)��䂿6���*�W[�UA���.��r�(�밸�N�_�^�e����3�{~ ����zg�^P�S�/��FOݓLn� '�H,� T2���L��ڣ�����Λ�U�{�xc�!$�נ�6�[�8��Upv0�9��7�,2�D�C߂^�A�T ������{$��Em�ҫ�~[�kV�9��t�vm�(�e�H�Լ�Wh��y�GgLt�g� ���� >p]<�\Y�Q��ZO���k��w��d����y��M�> �� ��Qv7 �_�Ru�L�ceV%,ď� -3�%+)���s��dھ�2=���<�1��� ݶ4�l���M5��>w�Qڞ�Rc��Y,D�M!����w���u]�1�J��k�C[E#q��W��~<��D��=L�m{q�vl��A��>HD�v�r��v�Ʃ!��7�5�4�Z7���iW�];�g��k%����z�� �^<��TF�z�.|��Bh��/��!2�u3)�)x��5�7�c�d~�/�O��O�{���$��N��2�3��(�$��2�!�<���\����J����j�HC�A��v�"!�/��"��IJ�`� n�(�NM­�D�~|+�/�?&����M ��e��T�P�+y�\"�=�x�oC,�l6��ŋ�vd.��֙�i���ဧ �W�5��zěP"���!�2�њ� �o�taBq9�S�݀���})�a��;y=��� F�8_Y!��~؉)��o�>��)��G� Z;x������bv]�m�Y��f�Ό:<����G ���s&���c4�Tm�G�%B�q}?զU(�ځ0�'�n�� s���؛�����f�<�K:;���a�����;�S��6RB�n�^�(�j%��f��w5M������۳�7��p m:�Y���\�d�\�K�{N f�X�NOB��A���+��܎�O�c �s���ث�X��к!(x��dCCA�U�Lie��'��&ihϚ��YI��Ho��RJ� X*��v�1XpR����ޥ��2IՖ_d�䃒����Ҹ�-rg��Cy�$"CI�����i*b}�� ����d�-鈫�.Ҽx>iۮ�KP��K���D��������.=*��>�l+p}[j���LA�2���"s;�n����W�ftA����ɘIs�m��x�b�)�v�.s�Y\C^`� ��I��i���?�=����צHڊ]�~��z_�~o�'�*\�VP|��FWW�=]��N-�k�)�- �� n��-����nVV��p�����(�?g���O�]���EzmE�/��C:�o�zЈ��tj�g�H��E�|Ǘ廕���D�� �'�>��J��x�(݂���%��BxHK�U��{4�y=ҊЯo��'*$f�@�TB��P�OF9�眱�_�v��l�2� ����c-�6:�Ю��9|��V�^�sd���:5�ĝ*{��TA,�-o��Y7 !8@��� QM��j �������z�^_�s��!�w07-���q�<����B�BG�pǔ�bЭH��ԅe�������&��D8)lAs=ͷg�9\K�T�շأFW�_�`?�_o]!����n�X�R�F 7&B�h "�9u����M�J!0mi[g�K㞞l%I�Xн�\�1#��1�M[!y;��a�VMg�|�^ ���)�@�p_�&�[�U�9�� \�3㟿:{�L_̵P��Roo �N�������O���kq�&=����Θ&ZC�`�ŏ�%�S�����0�O��w�(��/�7�Q�.c���Q��f^B'�-&#�_����va��O�q�|���e��(᜸���n���=O�HX&� a�^�+�Eԗ7!qg�+��D!$�M� �m(˗��)~��ѿ�K3��� M�jP�eg�nYNo�T7�S���*R�?�>W3���ȴ�*b��8�������Xz#��%�����v;�ZG]�*!#!L�1�����;�1�L~��S%Y������� ,s����g�~<ל�^n�F[4V߷�m�3aVY{�.�"�fօ��,=ȴ�p����0��'�)f�j���[��^_�b�6g�����z֨l(D�C�7P����_ 9T�X�!{޷�=�άׇ� W�Qt8�u73l�X��M�E/�v=f�[�����r�Sy��B�_�p�/���R�y��T4��I۟�FA���80����Y\�O����^�3���u���S�@���mCz�3��S�Ƭ�Ū^�$� O������_�b8�'��'���V�㩊�1@������� Rm=���э끚r4�ѱ�1]���>p+e҂p���8��~���S1 ��h��Ҡ �Q��O22zHQ/D���5��5��1R�@U�d�<%����f ���h�ʷ�j�j3B7��g� w�o�V���HV��|�U2����J�R! ���>�k�]��î팹�� y5�~.p.۝C��5�;n��JK�5���V���wZ�]<al�e�!)�� �ɮ��z�d� eF��𫿓�汓��犙Z�F”�=�(�v��1� IY��O�Fi���� :��ѷ8��a��/�-� D5�Y\��)��5<����Uu�9U��XBEƸc c��B��Y�9��);�S[�5��L�`6 �F2B[�_����UR�a�{X��s��y�Rv�. �ha|��r�b�=�0���%0����q�h�a�5 u�I�&"�9�]~ҁɀ�D �A+���+�;V��܈��u�b��w-"nW�lX{�_�Y���dz?�:�z� �Q��&����66�,��%���j�;Wh�[��$�gd�ž tq:�T����z|�?N`W ���im���Ō�t�@�Zg+�0+���j q.}��R�6�R-��%ũ}���:�|*��7��NL}{��ԛ��ћ^�,�!GW� [�A����+,�4��K�� �(�Y.8�u ��C��jꠋ�K��Z��3�o�:�ޗЅ6<�K��㘾��"�y�߾�V*��ʂ�!���ŭ��O ػ����IPc���x ���J�g��&�ş$\��{KsA��U�X�9=�+��k_����λ)�r�+�^ X}��.':Q}z��Jt�t��Zk��V�)�z���|H�Si�R���+~,�Y��f�����%��|�%������O�u�N���e��S�/�keȄ⠅k����j~Opfm?���:?��ya���m��֥"�˂[S͙���7�6��z��Hx�Y��vYj?�q���1 �Y��=�^XZ�����de�H�SO:_����`;�u0�h��.K�I�5�A��Y<>�?��ٵ4�:�g�u�Ÿ6�KE�G��N�a�ԕ����$8*\:��5޺�|� 9b���@���`�XI�������ݕ_�Us���xK���h���5�7�Ay��>�N}|�^fC�m�4��)���EzwCʙ�4^�W����6A�ۛ���t}�FUO�3�*���,�aMVy���&E� O�X��0�MR�+�;pGL��LH��?6>���qH]�9��n���U�#uv�o�ls���D������Y��5)�����s�ƃ>p�����ql���u��ͧ��9�fe]i����� "� 4�0a^U'�w�a"��睩�-E�:�����G�dS���]�H����7�CG[#����\K�ͫ�e�h�' Q��7� ?�i uqz��~�Ҥ�n���TRy+(�8�Z�_�&m���e�$�$ج��� ȿ���qtG�y�W1�h�o�H�4��<%~`� Э��}n �tE�,�����J�BF���3�Cң1(�^41���C��W��]��'� �B贪����y�o x�a�> �S��X�� ��;�×��)�}�[p�j�<��K��,�[�mx`��}��ߍ�H ���� �� xEw�<���!��k�lP͝�oQ�p2a�z��������jwb��ѾT�#$��5�E �$���0�)�@0��R��N���Π<��?��1�@����Pl�(�]B�)��m#ױ��W� �������?�Bj�ڭ���ĥ]���`�>C7f��x˄:���b���� ��Z32��8a�,�in����$��%@b�Cէ�����>�M��"|7iuOMɈdE���9�c�J@g`hSÒz�5׍؊�4�A�4�u��"��B���Y�ZZY&�Z�R�o��;� �����;Qf,r�&�� ���"�C�(/a|�O��]3���J<�*�y�-�"����)�� ���=�Y㮭�J5��u\D� w#�OC,9���a�Ew��� ;�nߢJ�5M�Z7_&lϽf��njZL�*��8����]�\����.Hx���CP�����]�^D��=�3�K [�wt�С�C,֨ ��eƦ2c���ku^X�ՇG��b����Vo�H��/C�4��F���sI��B��`Ѝ���nk�ũ�ȩŤ�{�Le=�?|�"�\�jI��Qު=�t{Y �m�ߙ/?I>UM3�yq����GWIJ �r���aF.۫dV�%����� ɵ�\���았�0����m�sf�\c�� \~{�r�eF�y� s�+�8�Oi@�����ƥ;�Q�lޑ_5�A�R�T��)���(��赚1��_��9��'�G��r�!�i�r����Kd�k ���Ps�ʼ!k<�~;��u#+�@} mc��r�V��9*qy�u=��|�t�.�iVo|�=��ճ��aag�����qf*��rI��I+R]'�<�Ϸ�-7���w>�]�-�X��/�w�R�� o �Tϐv���W=^�٬�d��m �����[n �(��{�*� �r8rnQ���ENI&D͉ �}�e2�C_�᯴ƽ�o��j����"˾�0-��$�ض�"�k��Gw���)�>`c�-��7��I�$Y&�7���B���f��� �UM��,���� =��@�͆��f;�T��N.��SD�0}��M.��h�]?�s�-" ���H��#��5B�AP���\����T�nZ'6u˾7&'�P�_�{�����BU3�|���l6��������5!v�˷� ��[�>|�4�9%u%BkJ]K�cR��ip�䄐�~�*ee%憫��7>F}2�A_U#����F�ؖ��7�%=�{��@���)��a�{��²R�e껁(��3����#M��~~d�3X��*v�#��!�?x�>!fE���*��b1���↵P/�S�W�)$�_\��̿(i��P��Ҙ!��2�vя�'1,����uj��_�r�wWG~$|ju���Q;��\2�>m?�cydD;������ B��1o�ܗ93�=ϕ���L1�p���� ��� !Y��ֿ%���!U;k����01����c�V���7m���Pt�"�"�S��^[�җ�㌠�O�Oj[ߜ������h�?F���)b�Z��t����N�����n���ڠ`Y���mF�I�;�b��?�(�l'���\�7�v��J������D��4"�&�C�=&�6����{� gI�b�I �v�����<����A��(n׭����N�H|w���J$��ͪ}Xz�JR�`us<0]^�I�8�(�3ȗN'-�h����&ں��U�] �є�ک �`�,�NB�6�ˢ�w��q„�.�(�8e:�X%Eg� �٣?o�"ü #̧����;06a��Rv�4�H��e$�Lː_+�َ�h�$>~�R��$���4�&5�FB�K{�+��U��է�s K2D4�|� ���f��e1����6L��SQ���TN�LT)����B�|R�0~J~�(]@�2,z�*t� ���S��%���s��SR10��'>O~�gY�����CxlG�}Kb�]1�m[Y��ū�OI�����o#a��)�E�3�'{�����XO�j�B\�l�*<�nUF���H��R�����~���������b��6�3�~�6���If��P�Q}5?��ݹ��:R�_J^\:��<��禎Rԑ�TփF��]'hȉ� �񕛕�f���x'�L����}#f�a�S�8 ����F�Q�2��0��0�O�ȩ 1Ԗ\T�{�@��`�P�*����6 �kϿf� E�� ��2����~�l3ϊjI�X��)���֠�L����Wb͎~��YH��@�AC��He�f?�A���o�1��#e�vP�$Wq����9L�l�)~���6٢��Bb�|� �3R�T�g��=|�xt��� \����ai���;�ǁ#8�^��@U��#�h��ey�9δMEP:b�������v_�Q�J1S��V��T��5�sq�4�wN���� �͇#���� �AU<� U��Hx���p����z���]�eb��$7�8GU�%%����h'�_Z�{_ N�T� ��-U���: ��6�آ�y�Rve�$�N*���K/��d_���H!���]t���Ӕ?��^�k�u�G�zV��ng� �#�x��*+f`�� 9� h����)�"� ��X���!�z7:)�o+�'��$�u�aũ�2|V�T|D���(��=�g]z�s!��l+]���.V�4Y�6���!4������U�o�+���Wu;��Ю$X9/���YB5�)�K�n��CN_�e��Y�"7�w=颣������� ��T9`9��ޠVh��KX����.�ؐ�>O�v� ����v�/gx��RP�:��#�+;���co �Rbդ�$�؊>�LK�}v]eKA�6��s/��KuƖ�rF�'����_���5�F������/�L��>� ����%���ɼ%<�T����~s`��;�x�7]���(o����̬#�H� �)Ǹ]���c�B}���i�>i?�;�DŽd ����mnڏ�w���;K�|Tg�&c~�j�[��h�ɨ`Nf������k!_� ��eAp)�n����T��h9RV�����b�)J�� ��N�<�� ��y� endstream endobj 1612 0 obj << /Length1 1593 /Length2 8838 /Length3 0 /Length 9881 /Filter /FlateDecode >> stream xڍ�T��-��k)ZܭXq+� @����[q�)�w� -^�)nE��݀`{��S������S���l;�8�;������i�e ��� ��3�����0��Ӷ{r�y�v�;��/`�XZ�n��ՑCvr)H��d���f r�qrr  @N��� �oz-OG�N���|�����&@�`+����3� p���|����7���X�-\� k0�o�'3��O�t�0����I{\�ߟ��?�� ���;���向Q0���g���IIA=�l�\6n>N��C����o5 ��28��U�XABV��M����/0�5,�s�B�T 0�-r#N>N�������H��S�o������ YW{�?����?n����'Ѻ�< � �i �� �shU@�`W���*��Ab�$f6!v^�?�`gY��R �ba�b��k��4{0�u��Zl\����{/ �����I��@O���ee P��c����`@O���~B|o��y�y�!d;��xj�`�a�>�'�s��D������wu���\�? 7�����a����>1;� ���!��O��@^���������~g{���?�.C�'6�?�6��{�?���Ӯ��qY�@ ����H�m]H�u�$�;��87/��Y��� �ێz�kћs���9����U�}���f;=N;���ha���vd+� V� �W���ʮ��J]]f<Kk��C��XHY�N�����D?V]U��25�c!��F�>��B�����6թ@�|&1~�L)�w�10�ͷ>�P� ^� ���Q�"��X�n/�s%� �7��^�g���.�C�͝?k�Ӊ�(lN�ɟ��5�=NƇ�(��a61�@f���(u�l� $��E_��mq�0�FB{�S[�5FbI�v/��Ÿчg�_�"c^�Z�0[l)�]6b�"��ʢh��˂w\[� �LFF�m�!d-b��2|��&؄%�zG�i��0O�y�$P��9�*~��Oior�z<�윉��d}�y�=(M�O�|23����9���5$�#���J�~H�@p)�3Tl���4��(�M�h!����~h���/��}�%��_B }H<� � ��V�k \r�������͙-ĬNb�f!�{�Hqy�xU]jKmd�8>vy��2� �����Sk�}�������E'I�c�|8@�y�w�&ٰ��?T�Q`���&.�.ڄ!�ŘZ�&~a�y�"r�'�Td��h�(?��;�F�N�?�#�b�Z�]2xv*�Z�L�s1E�����.�ZrU� s���M��$, ��)7��� dN�9�a%��t}Lv%��\�z)׻�`a���� �3hz_�֊Z.�ֽ��$���ȼ�{�����3�9�x�4GT����s�ES�^�n��B�U���M���L4�3�C����Q�+MF��HXj���6�����Ko�H�a|[��Q&�nW52oy}y*��ЯE�s^�~���pg���b&f���,^}UU����b����}}��[�e�Ȣ�"B&T�$Y������cs@?��ٶ �T���4�4.Vid# ��*s(G{��AWW�Wq��Tr �WP��z�$�� &��Em�K*+�6��K����vZ6 �g���F�7X�9�!Q�H�4E#��3�e��jxÀ�Ѕ��n�9�z�o��~� j�~8�Wl�B�����8g���4�`~��`�=ϒ��9� �~�ҩj��s ��졻E��>��3���s5c��j_ƶ���R*m����B`Z!�0��匳����aL."�b�'�\�;���63@�w e߃z�>g�q����+Pܝ�'z��%���n�_�ؔr�|N��#Ϊ� ���y+����A�uܯ�%�G��ʗ(�־�e�b]7L����C�)c/tނ��yQ��[�=&�R~y;� �����N�[����%���fE���wȮќn9l9�`��G��JO,���Gq�ܬ�K%ܞ0ɨ���ϴ4A��&�ljŻ��$�O'y�W���/<%û�ìfɘ�Z�y�T�� R� u�-!��Y������3=��I_��{�/"�_�w�龗/ȗ7��) �E��_���O����9Nַ��sq휈�0���5$T��^ }��4�P�>�P��b�N��Q�y�j#2�.�ھE(��u��|䷴�$���v��|#Y�iFZ!n,L�oY�f�2�ְ��z��V��e�xK�Z̉X�N��nd�O���!%��QG�OoC�� �CF�Ғ�Ơ��)0}3a�E��lX#y[���ԫ��{W1�}[��� �(�N�kf�Ęf3��e�C��R1L�T���)�� U52-��1WK9�~ws6I���kP�؂/5�� ��BxQk*#�O�Qh"�ù��#yal��H��R��'i2aHί��� ���%���2?7�ק�Q�N��A�M�B2�H� �Ŕp�(&u|��=���x��� ������~�_%T���K*)˘t��R��B�%�\T��D56���&�DY�S��;���}���5��x#�/u5�u~�@���:7�X�� ��B�ו-lbz!;���n�j�.=����6j�F��0�LJq-�CxT[����sD\�NLxg�Ǒ�8db>ë��%T]]o�����}�j-!\�%@�z�L���˜�cv�H�=Bܲ������gPCs>�So�^ e&# ;��ƪ$6N�� rR�E{AM��L0%Zᵬ�Cq ��� �ʚ|�>@pl�>��50���Z��8ψ����և�W�u��#/�eW���a�W�� ĸ��?�jj���������v#X�׀V�� ���_����Bz����������l~��2d�*�/ԀŇ��7��\o+�Ik��hV���y�b��B7r*з�1乢Q��� cw���u��i"g�d@�Ĩz U<���n����-�����ܲO���9��ɠa��v’�wD69&�.Ϛ�ONq=Ď@��M۵-�~��Ν��z"���#�ay���U�I$S����6+�av�P��@����v��8oU=^}Y���ϙv��SW�� �5��-�`��̻�g ��D�es�p�[�x��iM������Sz� ��RL�a\5�Y�B�r�f���Cf˚����l��y���O��C�����|��i�w�{�{k�\@v�C�2X���f�9�~J`��b~´��)[IN3������9��]��sO�aD3W �nAJۘ���ܫ�u��ِ�߲@mO���M 6����[M}d�‰��c뤼��5\����S��� ��GŴ�n��XŽ%�"���Br���F���m�}|��\qH�㢹���p��tq,L��kB�K�'G�Fv\T��I�!�n,���j2���~]�G�;?�Ix���Ğ�Q<�Z�O����Mی��Xί�I�J�.�S�+�Qpr��H$�ƫ�be�|rq�������M�Z$��n��yh�R;c;X"s����c��6C�5O��_��Z|� +_G��%O��!\��)��`���i�X���>�/�D�V�«��ʜxY�f+q�(a�U�c1)�i�}q��=�Foޞ�� *��ͪ1�]�����n��닪���$쿒.��G3�P� l�W���)����2R�WL�N��4��6�܁��¿$x�)��R� �/tu 3.P>G��/� R�Li��i��S. M��(�™4%e&W�9�_�Q�2@�}��Ֆv�(?�eh�w�,Hٗh���M�O�1:�3�H�DB_y�(˖���&�N26~ЗM� �d���� tҶ����y�%��ߖ�S������k^�g��&wb<��qb�5��D��=N�PՕ� e����ς���_����-�Kr�ܞ��xyoA��m�"�\���Efs���/�RVG7[�9[>~U��cdI'�"�:S��tn�‚���0M��RW��K�֡ ����w)�}���~�'/Ur\%_���(�;�95���կ���}s=Q�ۖ}(�V#���°o0����m�#ݖ�?��.߉�۴�����G��l||�� �2tW�?�}�z��9�{m��C�܈6t��?��:mMu hk;���#$�]#Ư�����_F�7�Ŀ T��9 zׇ?��������ˉ�� �{�ד}��hvk����O_����� ����'iU PklP0NU���V5R��թ��F{Uɬ7�AI��+��Wb�Y����\??��ޘ ��}�]�¤#o����H~�/�ZH���ZQ�{��R�?�W� ,N�M��RF"s[��� ��ig$�y�)��"H�a̬Tҡ�A�<�sQY"�R���>rq]�B�C�:���4��aҢ��ж���\<��/8�o`)!!�k(z�j�3 ���I#�^����.�+���[Xҫv��&�0��L"�����Y�S��N�+�!ɖ�4��.@�@����oA\�9��Rt���no��P�ީ?�Ӕ>[��G���Zf�F})s�u��1d�UE�P��T���c'OhA��Ղ� �V��^�8���R�[��ס�X�p��i� �.�-�0��/Tj����K^ �Vz���F � ��<��=�/C� ��ia�߄W.T�ٷi��t7��H�x�޾t� ��Md�Q@��m��{�UAs��QZ�P!?=j�oTg���\K!���b������:��8ͣc��n EMO��l;�- am�q]b���(m1o�x�{�,x��.���(U��������k��7�P�r��Ҥ�<����@i�3(�G��I-�8��i6C�x��۲/vh$����C�R{l[��89²9���B������t7�]�v�I�a����h?�����������韖�v��D���3kȒ��������:�af�]��*螊�+��B3�Ӏ����[ ���P�w_�BS���pN>���JQ���m&��w6:�t������'��y)�E�U)�\<��(N&�D�}�-��G�f�+���H��]b���S;���H[ç�c-�AxT�d�F���5n�E���?�[���r�>$� �"�+���5��;���1\�s\�(����|���w:���:����ثI��@"�lL(�u�j+r��^ �Y7�k��Zo^����@t��i�my���Ԉ��iM�0��kT��^���}=� ��4������}e�Y ���#E��OD!�{[�/��68��I�^ w��t�*D�:��~=��*��:̻+uI��(��Y�����:�X��¯A�֖�q�9pU��q�S�>�5.I���\Az/w�D�$1$�P�] �{?sq���� E�(:�h&���A�ߏ�&�6{�#�, ����6�'��TY���ˑ/������(��Y�;x���;�\!�B�� Oy��q�� D��t����8J0������yL�5v5�˭�םi���rh�I��r��b1bpW<���"��.��RS�U p��q��{Z�~Ԇ�X��y�����4 C�p�g�-���Y�sᄐ+,�O���(���̏�k�P��r>Q[=^-�nX�B����1�:ɇ�P ?�cX�<߰G��ѫ3+�Dž���n�j�ҬN�c[1z�@E4P}76&ˆ�d�!дy�3?k�,�M��3Ϛ�~*�;L__���) _�wh��đjjG,}폸R Qyv���k�a4t*Up��U��{-h�����7Sj���ޛZ|��5�V��W)+�S�cT����&eI�$��~��N=���pMfT�kI�uv[���^�6F��;[�>[��� ���8Ӈ�|��~��=���hl�ЅS-�x:��i���u�I���t���JY^��eƀdRg{���Ѷ��%l! ܈�*� �;�X�O�jlOct�5*Dq��4ϪC�  ݦ� �wJ����F�/q�%gݾ6��A������;���ܞ,�!�_��� �[���+���ؼB�D�Z�Z�~[�d��|����Y&�V�%^?�r%���Υ�4��})�N<~.� �,��&4Yh:�7������R)J�my?� ��3� #�%G��..�\�ݶ<�UG�bg�o6�gB��Ų�ErQ���e�Bȣ��z����ʌ�!�8=ݣ�hs�C�K�0e��~7)�]�N�˧,\5�u�p��.�H�]�i����Q�����*��WNv۹q!Zo���p]�G�^{i��!�ϒ�VgI���Ic��,��0���gS�(� =��iF7��˂�M<�� ��CDE ��ʠ��g�s۾~҃����E�GDF65 ͷ�6˅�H f�r�5��֜��eH��]5{)x:�m{�\3�%ZD��$J��Li�λ��G"xj(�g= J�b��O�i���G?UWZag\x/aw/E�u��=�!_gRr����"���S��4^8)��%�!T��X�c��I���U� "`l�;���=mM�2�Q+�^xO� �V n����sDw� ����j�Klf�B"4莧��>��m\/������J�˨t��X,p�F'�\�[�D^��r���&Iˌ,�"KX�|� _䢰5T0�pOGZ'���B�+s��K��E�S܆d�[���@��0�0hh%�,�+�Ӽ>|s "TGU��L��Vu��F|0��^�A0p�{μm�X�g��D��X`���J�i)J��N�&�y�A�8����|� �2����x]O#�d�4"? ��Y������R*5Z��7��Y��ɋ�ʬg8e (�jES:���xu��Xn�׈�l��y�� #���E�#om��%`��X��6>�~n�L�I}@|�[ɘU$�ƨ5��]��Q������nԨ�0��_�� ���1Spe�_��%��K�j�r�ƴE�cP��W�`l=��K c�<}t���\�J��bp������{6o5�x�F����u�}� �{����D���a�KU�� ɚN�6)���\���^q�~�`�Y���g��W�X�h�c���[;@ve]�0�+>���C��e?A�N�T�dz\FU���L����VsZ���Ś�!=���&��f�B�'�B�c"]��d���_�����2� 8(x�xR�}<��9�`��>%��o�y=��J7e��w�1.^x��ꊶ#��D ���9�,\ݖ�wF����_�%����b,��:=��׉�q�'?R�\>�=�>��z��'_�B�!��`r�۪�RO��D���$}��̕G�=�V\3>�/oL��X 1K1��!f�h�;H�E� [ �:�.�8ӕ,}��H+�t�c�٪ٺ�Gt��l�8�c#��)����K��'�u��aA|C.�F�+���Hw2/W��1�?�o :�h�Ͻ٭^�5�1���M���F��� ���Y9���o���ë$�"�FL-;�=$�|[� �&��w�5w��j=��^b�!�A����s�L;I~j���?�G � endstream endobj 1614 0 obj << /Length1 1979 /Length2 11894 /Length3 0 /Length 13103 /Filter /FlateDecode >> stream xڍveT��-�]ww\�����]�C���4���{pys䞓{���֬53�jWuU��kJREFa;#����3#+ @TNEVU���������OI�j�l ��O�tt������#�4t�� �AT9;[���5����������`ca���Α f�ja�c�����)E��=-�̝A+��/�Ƙ������g8@��halh �3t6ڀV46���[�=�+�{sgg{>ff777&C'&;G3AZ����9@�tt��h oh��9&xJ�����_.;Sg7CG d��0�:��\lM����iY��=��/��_���`eb�'���$���3������������ `ja (H�29�;3 mM� Z;ف� ] -� �@�?�7H+ A=�ݡ����������]2�����&�v66@[g'�?��p�vރ��Glek�f��/6��51��{f5[ ����,� �_�������z�@��؜��ET=�:Y�0���񲷳��Z�X�A?�^N��@��� ���w�#xVV����3�hfa �ov�h�������!+���?��@:3��������f�(&�Q�����q��ع��X�l��.Vn/��)Z�]�o�Ҷ�v޿�m�jv�[4� -�s�ہ ���w]Nc������ ����,�z�ߚ$\���d����1 m,�=��$�� 9;�P��/U���M,\l��+�l a[3��y�8��2[8IX�M-������_f�?�����h�d��Q`dea�h֌�@ljH����Q��U�m��L��96N.�����< HTl��/V�p����3�����u�0�s����rq�$��/� `�q�|r�"��?�����/�0���@Y��A��,���b:��%5����A� ���5hg�c�c��M~��f�o� �l��h��l���!{s���A6�� ���7���7���7*��_D��2�����7*���R@\{Щlk 4�wg8X���5I��AEك���m���~��F������u�dm�d����7b��A}��A}�� A� ��oT�ǟ�Dj��j��������?�@�;�~y�Θ?ز.���F���q���K��ͅ�>�|� �<�U)G�OJ��⨹`��$xh<�x ���H�;t�t��3����|���4SW,�� Ѹ��ǢR���Z�����*�vX~DڇG 0���p G ���O�?��}��`�;�X,�Rd����e���~bTv��/� q�ͅJ�;�]h�r�u�w�=�w|�� ��P������p��,d�/9��#���H����"1���q��;�={7��9�`��4K8S���Bs���9ܥ���\�R4��3]3c��P��Q�C�)�D�4"'͎�B�[����߬�%�>�7��i=�':o!���ʨ����!�zf >��{�O�d�}�^���P��igm5tOޥ^.��3�q�Ӿ�8������f�O(��<�n�#v�d� ��{�F!��*�7�~�7�O�t5+C ��"EFŲ8 o��Ue==�@쟕�i��{+��h��B0N���:x��2Y��2^����7Y�8F� J�1��d�$(]a�G��I_vs�{c��O��֦V}R��cC����Z����mo�_�4 Kӆ c�"�OL+DŽ���S���i��rӽ ����_s�?�\w�{�uD���{�h��\������S��TO�S�z-�)��\�L�A� R%&��1��uDx�@Q�3c�z�}^Aaf��C葌Oy/���ݫ�I��91��s5�u�ZT�38|&�^i�3��"�!]%������F����0K�鵬��(<ډ<�Q�9\״�f�< �Qg|�d}��e,㦮�A�%&����<��@F����_ u%‰R���8���^)�z��߮9�����j[?�g\[� ��ȸ��^]d��J23)Z�s�͑�4+J�Q���6�����R��p��:�i�qz�`��wL�4�����@JOԵv22���,��-٧�b<�w���'�(B�8�@b�N��γ��~<��͇���4��o���x�Y�+����Z?O�<����1!� ����\�5�����b'��]Uu�.�b���6i b�H�V^Jv��e$8��ԡ|OS��в�E��2�O��j���y��+'��� ]��0�������mz�{�lw������~��jY�o����$ O���\��ۓቖ��*��:jl)AB��-T�^��?����Z�T�~f�8x�������`ҹ��+�I6�*cf6r�i�哣�+�sL��_e����I��]��Ib��l���V��eܡ��-��$���u�7$��Y�N�Ԋ�{�B7S��6'���� ��5�&�F��|W�2�#��(m̙�c����MP�� 2}��>�xy�`��.����!�[���'}]j��]�[%�o� ���'9��d�I�"�8��+��*���f���d��q��,�Eί렱�2�Z�,W�E�/�y�YR�4�sFH�)�`F���� �����b�?rX|��pa2+ �_�.��<;���`s$�2KY�����/��/� ք���d��Ĺ!I�Mk���V�q��T'��f�.4y��3kU�;��W�p=*���W��bg��Hľ� Ð���|e�'gk���{�����Fe�Bq5n�N'g������x@�;dO�F��{s��i��&k7�#���56����}��E8 ]�NO�����V.E�t������_��<ȼ���#�Iʕ N�>��^ˍ3�x��p������j�������Z�uO,�����`;j*Шvh]<�����!F�?Ih�:)?�k�fĕr��2Xk݆#�Wl%�C�W�ɬ_�G^[�]m�i�fh � ������Bٽ�8v�T+�B�G�9N���� ��Ո�?~� �����$���]&� /�{|�N�ARN�ʜ��� t��nT�BoM'���m�i@A�{uNXu~�O�q��GH�I�/�O@P�� rK��nw٫= �B%���'����r�~���8�'�UB™3&"�e� "�.+ZW�b��ՋFb���u���5_*�[p�%҉A��α��.H�ߙ.���kϧ��$Y�M�f�O�1�ޯӂ�J�̱���hu��+A��j$](�vT�;���0���3�_�0���9�th>:E�-W�S}��8Z���"`��l���v�e-��VK)�1.����;D�__߬�"���W���'��T�)fS�(H>+^%W���h_�-}�,�F6�l5�O�*eR����������o\�U,$�v�ƈ1E �� ��r7��J�2�|��+@Ā���K�Ē�B�g�T�q���m���P6v�����v�4��U�����M�{��S� �o�W���7��7T�vm.+�G�͘�왛��\�Z?����ف��}��剄[�:��Xp�l\�-�� WZƏ�L�区l&�W�;�ni[��0. +A��x:���M�X� 97u�:m 7�rv�0�� kø�~�������L������/g��q��H�Ȯ3#�U_���5X�N����t��u�]+G�����}�K4q�������x+./(��.w`d��$+���i���KL7���7S��Dž��.[��ʱ�[>��*�]��q/�ܴ�B�,8���$nvA�Qy,���~�ҥӼ�u� S���r;!w^$��Z�Dz�~�[ ��;�Qg��� pz�}������k�s|���3u�W8D��ׅ��R�t�L<�Z��u���HteԮu��9B�J�'���p��`#t#l�^��XN\���@#�� 6t ����q�Y� �c����*�OL����7��'_׿�m}���%�_ Jc[�ޜU�HW#�Z�� ?G7�m��{�k��Y{;)��K+�������c>�Pf3{�y�43�HdT=��^�3��T����g�)Q��1e��Hp�rqmHd���1��w���z��bת�m�w�a�X+��^ a*P]���K��0�ǂn^�X��x�%G��&.L�P�z:��N�MZJ<>�j���Cd���Ogr�aVV�� �� �[�t�MͧQ ��� k�9���圼���s��p� ��|��-�� �����J�aY���7 �< �Na����G� Ɍ�N�>m��{�/��W�S�Zw+�t����-�)�گm"�5F�Rtex� E�\�Y�Q'm�9%®�VKv\�k�o�m����$BB��sH�o�j ��\&�+�~q�}���-���Ȩ�~�r�. �ٵs s�ʶ�Z*����؜6��9n�%� O�F�(�Do)B*}��Y6���h�x�+��d[�'�7>��a���%떛v22���)6e������0��g]37���>��II;��ډOt��L�� C�(j֪)��nsqvظRu�5�=��<9��#>C���V��B��q;��h��;�N;��I���̥���p�M\x$ʖ����c��2��H�b>��۾�v�a������x�����U�;��6�ˆ፰��Ť�9��9d��vv��-y���ĕ���w[�B��v�n�i{Q��.�}�_f-a�hB��ƫ|E�,BU)�`�L�'@��!��VÐ�k��&j2t�D��T��z�H|�y�_�[�Dd ��4�:�#k�6��]�)� d�]*��oV1va�F��t6�n�u�}�:#��B�1�&j%�/'"s��f��0����]Q�#d!���$z'a�� �$'�`��b�/DW���(�/�'�Wɪ�G�t�0�diCym�H�^f01�%ĬF#�K>�i[����V��1�4_��A�7��b������m���3�jl�tZ�m�G�����B Z���& ���n��}�(xHG����8���r�#ћ�1�y�����Ґ6���8%��M���95��RoǷ�B_ۗ�x46(�`O��[ 5�)wx��(��A��=��9��c�3[�b���"ܝ$_%�++a�G]n!~���ۺmi�����H�B�0�(ݳ1d���曰��Z�}�*����G� ː��o��9s��(˛X { \��"D�b�����q�k�D Կ��e��/�'}�wm ���~P�s���Ep~�Fe�'1₞�^)�c�̨� "�\e�A�i`�I�W��ϊ��)HH��U��!C���k��+U��'6\Uə�jOz?"�Z�ۣ3�9N=�W�l��)b}]������M�M�v�b�(�h�dVs��:3�<�!�*e�jlPF���S�M�5H�_��c�ã�h@�:���&1]��B��l�%m0�C��r%c愫;���VZ(�VW������hBzdH�D6F�)�c �@e�Ə����xJ��m�nx)��_�\�bx�]&$G��:�n�=pYLӄ@�ܤwc;=��q�W@b��4�.�L.�8�ل�2�� ��( ����ħ� ��.�S��R Y;D�0��l�O�~�Ś�mwY��U����3��j iu�.���! j��LW����i ����ȱ[�Idؽ�&��".SLR�z����<�ɷ��b�r3�&=7���g�P�}���a�i�������V�Q5�`�|,���o"Qvy�H@4z {@�H���^�|���]��V՟̹�e;�^ �? n�=�0�>�.%�V���F��.*n��gʧ�A�x� �]����-�ވ*2���T��o����HW;��C�}/]��hȸx�[2r�����������N�ѥ P#��}5���JG�;UG��ã�f�� 0j#�#)I6�;.e�0�].��0V=B�SZDz �E}@+-� :�XҙFч� ��Xj����]��:{�8 0��,�����m�g���t�z�P��v1Æag��"�R>k��4}̪m~�]�����pku��u:V׈Ҫ�jK}6p��禾�@���]cz>���g�\��\�Č�gf�ʵO_^fp�Q=��D� �Z�5c?p�O���9M�����V&����m ���K��4�(��=��c��N١R�/�b�`�lH�#J\2�x3�߈ڴPJNY0� ���]/�j�N>���">}��kAW´c<�JU\^��1$�O��@_4F��{:�i�{�����V���RC"����(�S1^����dنs9sb}�V+9�4Wn|��Ц/J�r���k�(g�iP�4���j� ����н$d���$���G}����jP�*�o��}K�႙�i�q���� @���]W���E�H������,`�e�X ~Z� G��g����Z�g����: �U؆�~��ر¬=��18aK����� �&��5~��>o�T/�n�i�R+&��7��t�-Z���@�O� ���=��0����9�NW�M ���Y��O\}��Y��!H��á��`m�q���� ��f΄���1�a�B�**'Q�&����a��+���o:a��42l3�,t���'aS�#i�9�d_Z4�$���ơ���!_Zg�t�KJh4`� T�y�m�T����Jq���W�u�y�5���Ӛ����Ҭp�j.��4Q�TR{��hPţ��:9z��V9���� 8��t�q�@C�G�)ai�WB��#������v߶;ggϐ������!-F�Q*�����;����8 WJ^�>�d���s�� t|�s�R�P8�>+A� ����8lw�gK��I��s��_b�#\1��qnZphu"_֛a�&�Һ�w�헕8S�ɴ[�K)DWKdҕ�g�[�Y����]���� e�j��HO�����_C��p�j׊�x�df��NK�ȶ@�� #�p��t|>D�)��k灵]>�|,d�t�65|� �2����EL��m�m�Dc O?哋�s�� �~p���`��ϧ������/lv�&rG��v~�r�!�?�qN���Ƹ�*b����&� ����oC �s�xe�L��s��馸a*��(֐%1�i�FniC]c.�� Xf>ز�����B�;62%͔)2LD���BP@S@�ӌ����k��$V�L<��W��V�Brg) 7BaI~z��kۆ���Sό �?f��ݐ?V'ԓ�5�12�����}B�V���}t��k0܇�R���:��U}���0� ,TqOi��E�����&_�Ž�3G�� `f�z�Cߢts���x^=Z~,�G'����Q��:g���R섍`��M�p�uv{0���U� K5j�e~=#0��t���R�۶W}Z1LP�4�S�2���-{۵Pѱ�,������uu-�8�����{���Z��CZv���ld�%�a������I��t?���5��D��H��{~���E-�� � ��|1�e��tw��� Fg0��Ȍ2\��s2���7�g�&x��S��;+g�$э^�P)ƽ�7a�:J���j��|֢�Q.c�#�+aVS׭�*O�n�}X@{�O�tE� �7��\��Q����I��μX]���n[��}Q6� ��Jꐑz���d��7���B=� Y�J,hK����U�R� �}�K:��}�1/�ux6���Z��#�?q*iJ���+Z�j]֜������a[�۴ל�ro1��x`�8��N`���%{eܡ?�9R���n�ז �U�R�Z=�ړR�'�*79ѷ���Ӈ�p�(� f�.��۷�UKe,����� ��2褴9�����~H����V�Bݥ�2� ;��M�ɠn��w,tL��]��Q��~��M㔣��<&R��>�E�̃%D�"��X�F�p"�Ώ\zH).��H�(F��F��2w�.{���v�����w[u���L���ﭩ��/���i����bx��̆�ܤ���c��� 6zĎ�8�m�tG+s���&�Cr�\�w���(��M�"��M� �R],��M�C�=�n���nw�E!�A�<�S�� WD���ZŠ_b`Жo����t"��jT�zi��S����Cb�t�2�Q�h��:��Хi���aO�)3�h"��z�,����XuF�%{j,Wc�@�(^���P�(8�7#�G� O<���?�]��)�]4�u�\��~0�k�!X�8"�a {Px(8��G_n�A���^����8K��IByԵe����kun�X�<(1���`��QU_��<[�րuH't��I���%;�W5����'!�x�)|�n��W��/�B���H_.��U�����)>G����^��a��9N�-�F�$P-�ݿ�I�3��و�~&K��&��jU�ֺ�w ��ѧ��Wm"�]�f��ܞ����h�'$K��dK��nw��S��׍H+�?[ >~�w}���.���9Fy�uR��i�Ў���U$���&^���� ��};a�:Ig8CoE��>j��K���G�D���ISd_�f���l�e�sغ�7�O�ЇR��0���+p���l��`��Խ��mpT��!� t$�,ܹ�-�:�vt�>`3HO㌙��ҧ�W �����Ea2,���|ƹw#�z�G!+V(�p��~��9��f�"� ����a��^�^�@�kn�N�Zvt�q K�MvkC-0.S�C�x'�ɽ�#���#O馪^o%�/v��Xܑ����0��X�ihπ�z՟ ���)�h�v��:9�Ӷ�(�ka=FJΥ_߲E��i��))�y:�tu~����:J�I��|;-�� 7�֔��������!\�dk�и�*Y������4R/�*�9G����D��g2�ZC R��p� �U�S�����9V��ՈI i�װt�R����"}�(�T��a%�#��Y�|����q[*5gu/��$�kh�;v��� ;S(��(����'�/@� 7�UJi�"�W~R�Y�0=BY�� �ɓ���0S�p�sA�������^��]a$��X��^o�J��>V�&-���`����z���a1i�j�6D���35V��1�`=�@M r�f�0� �g'+B��{�$��j�Jl����aP*��Y��6��r�uV�'G�Ϸ�I���0]�}��ԦDwP�{6�>�,�@8{�� d�g&��%=�N������r�Ms3J���zu��n�����7Q�+Q-�Z�=��"�,�ԩ��3�?}2!_���-�Ί�s5 >,\�L̰��H�}�� �g���a�Ψ{�W|�"kR�����k�J,� ��xJl�3�4m��z�_l�x��|�r�)��� :Uxm�������@�<"35��1lo!)�0��O*S��vߑ�ɔ�C���0�PL��~Bk��fS �*)��A�KX���A/-'8 �z����F&wT�9'Y��\\��BK���m� W���'��G���b�S|��;� |�f�*�K���ȿR�/�?* xK�*~��(�H}�X�WJ 1���,з�� m���iͨ7�[&�-�O�%e+�Cyѕpkg�yu$�p�w�����½ZJM'����bS�ې�㍌�4�vϡ��6w���7�@�n���X�4��$�b�%�d�Ź'Ÿ|1��j�_p����BU��@&�yl/W5�~-�*|-�Cc���c@Yj��C������"7 G%z��d C�j�`�)�-���� �"��v��⊄�}��Cg!j�ڒ���6�#����֕B6���� H�,{%�4�2��X�p�9Fk��Ld�������ha���ʕQ6Y�<��|�5x$l=�=8��;D�Қ}su�9_�� 9�/P �ͬ�[4$�-������y��ϡ���Ce�Z��{�ʢpT�C#|t���Wݝ=���6�U����`YfΓ���ѻBa��m��ɸ� [^���4���� wy'��R�E��Sx�����L��>S\��c����x N����"K���:�g�M{�hi�� '�'���h[_%A��=Ȧj.ץ\Ǝ����5?�j�n���Ϫ2���b ���n�2 v��]l�A��X���H"��j(�n��6�%o�ѯR�kx��,G��p�MQ����o��RF��x�e_V�Hm�1�#���W�5zݛť�� �Yq"��-�3�aD�Nr ����3�׫��c�Mzғ1L�6��޿�+�<0+� Q����9���� �"��~�rv�&����Iz{�>�t�s�v$B)T�ylz�{�9SȘ ���Ls� endstream endobj 1616 0 obj << /Length1 1401 /Length2 6058 /Length3 0 /Length 7007 /Filter /FlateDecode >> stream xڍwT�[�6R"��C7 ���tw0�3� ]� �ҩH(%]� " %!��)~c�s����Z߷f�g�}��]{_�^�aa��㑵��@��0$?/H����� � /$��¢E�@���B<P8L�?�0eS#Q@ 8 P�t�~ ~Q ����=$����T�0�E���upD���� ��r���ܿ�YW�� 4�HG�+��-�Ѓ�B!H��`�rD"�$�����y��^���47� E:��� b���B��Ƌ��;B�zp{�7�� .P[ � ��A<Tu@OE�r��~����?�������O��DPد`��-�� ��{� �RR�E� �0��'삀���^`� ���:P���� �̇����!�����~�Am�"�N�� �!x?�S�z@lQ�����p�apo��_+{(����v�n|0��'DE�e����A� H $@����#����n�_N��f� ��np7�5$jA���#�^�� ��OǿWx���� �@�0������k��{@}3�~�����7 ���0�࿎�OI�D�X����;���>�?�?�# ���Qaq ��i���?m�G� �����Mu�������;�&E\����A� [ԃ����_!�?�������;R�tq��g� ��`W������H�4�()��j��\ ������*H0J �0��7�P��@촡H[��|�m7��4( � G@�-?�_>��l�Q�E�_.J=�.�������������P\��Qz�����1�� �#Q!j�@����L�@����@�?]��������_Um==PN�/f�Z�k�K���ojn+�T�rV)K�ͳ�{~�5�IO�0��s����͌��r�ve��ړ%�#4�;gC>�Y!s)ʹH4Ş%�=���������hj����DZ"k3L3�$����N���רּUS�M�(:e1w�b�5bsc�E�|�1Xx n �9�0c�jk�X/��b9YX�Ś��F�i�}x�p2�� Z�HTE-�͵8���o�1�!��G�0g�����<-Nx���}:�lI� �Ec���&s�Xs��A$����qV]6��6�Ϊ3�okb.�Y���nCZ�S�h�����9iM���X���{�#�+��=� O�"�p�R��M�����G��4�s�A�I����z� �[&��^�-�p�z��^�&�3c\сi�'%m=�o�D+�Ek{U�Z\�����]�����K-b4'0X����z�#������ᬉ�S:Q����qˋ P�ng�� �"eS?)<�%C2�M@G�H-�]�D���)מjZF!�&g����NHݑk�N�4�dRyd�2M����扅}Y��k�� ��1�t�mb�#M�p� �Gգ�9L Ӹ�^䉁Øi��f�ԇG�����z%�`l恼G�L{?��u���~�d��ٷ���Z*� C��}�C��e0�#�����O�\鶲�LG�nKR�M�z~9ei#�涡hϟ|sa��>�9ݡ��զ���Fǖ�ִ����` �r6el:&c�В�e�S �������@�%�����ӱ��iG��H�C b�����/�V���D�~"��J]��VM�����$Q& �Xs�Wc ?J#�O����Yj1�ۯ�����M�:����'���u+�E�w"&���LB���s�� �0ݰ>$��+j��Dk֡�)�)O*ɮ��Z���b19��+C���������oDX���F̽�GsV�߰�  �}�G�������j�d�"�L^��W��W��/.Zi��!M�9��΅�Md[֮@���&sb}A�pP9ۊ�M,�IΕ�Ss�KJ;w��!\�#-��)%ti�p�FT�'݃@f & %�^�n��›W�.���r���v>K]7��$e%: :��f��Sn����T�����Q}��i�֎�L˱k��z]#7����{A��"�� ��l����8�1`��ڗ��ޏ� >&��~��ʄۡ��ei*P���Z�qՠ*E�y� �F(���A�>�+��uf�j��\��i�{[��� ,�ьk����;GS'�AG���)] ��'ҶW2Ԫ�'(�l��- {w�f4� ǁ�$1_N �a��*�`���Xw�Ma�4!�d8�d�GZ�� '�mu�&��G�% 9N�p��6~j�R���\��剏˜J�h^�S���p����&S��*�>_#��%Ӽタ���JM���[��@(���L�3���Mh����că�;?�#�&�$��O�3�y�j�!��X��Po�ᡘ����C��[<�y���g^!�i�l�3�%�P��>F�i�7�� ~�b�ʩ����>ogNw��v��q<��j|�����+��O����=U� v&c'���ŀ{�]Kg<��9��4���-h�9)>i�'����N/4�5)Pp��e�XQ�~Gb�wؔ���1�g�?Z�G�Q�'K~.YN�ab>�#|X��ͤ��᲎o7�9W����bqנ�G�V��v$uW?�s�qY���|uR�ȑ�O�q�!�����k�܈x�~�?<��O+�^�3�߾���-�F����D��DB6I}�dN��o҉���fm[62���D����f�2K�T�zBLe/<Ɔc{�� �)�!Ea��a�:��7�[xV�aX��{� �[U,�'� ��"���M�*�hI^v7e�2uPg�d!�U�#�y�)�Qz�U6�7����9��/�^��(K88���-�s��A�Yav�¾�^5�`QnW���-eA��h�?�G%.�]���S�� _⁋�9s�n�' �?=s(�o�@�␡��G�e��i�cK�4��8H�!eg3����n.�����i�s����5A�2���{ֱ��]�����S_�6���S����� צ�\���E����̫X�g#|_s�-��2�1g Q�f^��&O�����>O�6�B�2�׵������Ⱥ����Xp��<��Q�j�$]�ښ�Y�$k'?���tWtymш�P��4=�=v|8�Zgq1~��y�.5���m/�p����U��xl��: Y��E���d ��䪆�1������kr0F�� ��m�UϢJ��ٻ�>ŕ8�0AC�͝a,�*��}l�U�0���SX&\������Tss#��-=�{��,^cR2��������2�y�;} 7t��o�Q��%�ـ]ڶ�0�TŜ� U����x1)�vCF �MǘN�2H'Ȼd��ș�K2�N�N�S����M��I-g�q� ����"�8hw��Tge� ���O��Z� 7��!���y���B�C�&���̸,l�Ǘ���wW"�mJ7��uY*_�2 �V#�H�%�#�- ����u~���1�_�rb*s �ro�F�@c�U\�?� ���*���0<�N#୻#�z�+�˄�&��1�?PI�����̔Do�;�M�7z��a��O�(�= ���i�rwٰ��wz ��1�Ax��Ϸ�� �޾�Q��N��=h{�kSx����Fڌ޸���C;���ؓJ�H_���������a 4 ����&�q�����*���;�����֑����j��t�#�c�έЏYYsg���2I/��Z�eD�Y��3/�޼���Q��A�k��d4��uK�|{��dp�:4��&��h.[���׍�M޲@F��Q�4��=�3PK����0z/�$��s��8&�E� 5�bAC�J�g�Z��9���t�h���~��ϵ����G�.V��F��a�|��[2� wMM������-d�7�3C���S�H�,�D���Q�oK�Ǫ�ǻ��Ji�u��K�'Ff�ni��S���J��1%OI�<�-/�kzb�k{����2�� g��=�����P�LA���NA ���c!�7��;Hs�3t^9-�'!���� �9)��X�:�;�;,��I}\�զ���ԶEt����i� v*�͕�>7�NҶC,f�[ŕ�� �!�+E]�����Ŧ�@mX�Fu���vOG�>���b�۫��\�[�-a�#�ݶG.�g��x;Ǜ�7SK��U���)��q�|�\�K:��͏/�c�:Q��$����HI���{���w��?�d�zj��l�to�c~=pt>p)UD�,�~���Qg4&H'��xPnk�1�~�����D!t:j8��tśΪ��J;�t���A��cP ƴ=}<�6�O ���܌~w���%�d1�w��{�o�Ʈ��M�f̤��F��y����UX�+�Zy�n��|��2��ηı�4�<����V9"��V^��Y� �^�돽�'�r�z>��δ���A�%��ޑ��1����!Q�_�DH��^�K�$]���ْ�]��> ZW��W͎ ż�^ ��,!��c��(<��`���� 5 �������G�nEΌ:���S7C�S™��R%<���ܵ������K.{˲0� z���x޻ "�i�"h{���fޣ-h�T� � �� �I>��o��ȝ�9j�����S�ō��dcX~�Uk�?of�-���v��£�1~9�0?Y�.�y�$��Q̟�B���t�z�~1��ó�?Lj��ڬ�;Y���ݸ2����� y�@6�g���`��6�B�o�� `ge�b�l������K շjvL�[̤8�rܼ�e�� �O�V��3�꺣��b��s5Jw���d��vc2B7*�6ψ Hj�{����)����;z��Byt��^_�^N�A9H��~����Cȳ�Q�Xe.��KΕ�!��o��g�aAf+��^��������*h�(>��;� ����X�2 i?��9�RϺ�c;`�v�0A�|{�{�P�� ���ޣב���}�@�,T�_�����R��Z� �Z��[�f�rr�*RG {���5�; ��&�_��&�;�?.`�����O�^�j�㠻Y��3|0�V��]Md[�S�>�]��k$��i�Q4/.�[Ե[�rk���b�W��e�=����%���-�Y�f�P��0����`?ꏚ����̜ީc��~Y���DH]5��� �TY�ȑ�ʪ3�B�o#���N�Qy����H]�^���i������[[\�dٔ>q�]�P�>������>U�tD�0%�FM�4��K�' �a����`��t���|����I�3_w��^�x:|�,�=�s�������^�޵E��]ӎ�ɵ �V�3��'��hg���G��6Lt�vb�igo�U�n� �*�ޤ;��ȾF�z�G��=h�"I�c2����Qؖ���Ȝ� �������5������6�N�[L�Ŏ�:�����Go� �kar�j.�t"���Mޜc�q�TZ7�u�|�b�2K��З;m�C^���I|�>H�U�x�Ҍ}�Q�%�󈔗Ӿ�ʨ-�zc%������\+���K��Ka5���2�&ɷ�N�#̟�E<U�B}��1T�*/���5 >6#�pv��w��5�L��s�o�}�P����p��;W��5T?ox|����8��� _��#`��#���,������C�'�GlG�a��]%��з�a���^��ͅ��:L�#&�f����RcR[� c����GL�\�u+��'��a����N�z�oEk#��z-�n��;��X ��H���Dm�@��K���c����3����(�R��"ҍγq���K��X�W$E˯�ˈq�̂�>v�qr����TX5zS�FZ}����ՙ� endstream endobj 1618 0 obj << /Length1 1406 /Length2 6162 /Length3 0 /Length 7128 /Filter /FlateDecode >> stream xڍx4\�ڶ��F��A���A� c3:�kD���{DoQDI$z'B|��}�9�����o�Z{�s��ݞ�����,�F� v[�*��J�t�,�� PD&`g7��`����w$����;�B۔A(4Phz�B"!1)!q)  J� D�K�A�P;��@� ؕ�>�PG��߷.07@HRR��w8@�����₮�F0���G ��(���������)�pw���xAQ�C�� ��� r��5�;�����0Bأ�@����!p$:�nq���4�z������ �+�_ѿAῃA`0������P���-��F�@p�_@ �@ǃ$��B ��_3 �J��f����G! ~�� u�����#���:�^p��W�P����1�<\M�P7���_����6 �@�o����>�����f� ~�W�=z H���"�C��#Vn�H�i�O�����7���th�B\�&�#�(������;����_Y�W��wG�0�o?�����@a>!���@�U��@k��P3���@�.���@��jP�;��/t_x���T�zC���(�������� ��#��_Ot�_>�����M��.ZC���#�~�MXT rw����� �Ui��Mf���B��3���VH h��#4���?&� ��A�����E���h�f���׿��xC� ��t�����z/�ϣ�+��� }Q�(��~��xYjSn������ϗEL�����]�y?�� ^NS�Ca���+��~?�v�0�!���ӣ��� I[b[r&��^����l��Rx݉�|(� p����ѣ�)�vnc>�`a[E Y<"�#w���0�0��| �;Wl����n�9���.��/]�@��Z�*����W�%w8i��*1G� ���(z�T���J[�����X|��tA[ G���R��'#�u�Y�ܞ�#��l��Dw����j��٫�0Ά2��E`y���Lܺ�7:ӈ��s m���X�'�"�_&�^<~��($l�*���RQL��:lo�x� @A�N�������1|�O��e�œ9~��]�PO��m��j*8��#k��Vb����{2S1T���ˆ;>7~:�0/[��SM�����k��I�1ٜ��&F��m �p��iRb �2�W��b#/dB�eR%��O>L�R6؉'�]�c���:���@P�Z+����]NM��h�v��WE������<ş&�6�O��?�w�yҰ�g�P���5�n�r���aCƛ�����Mo���3� �!5�ְ"XEc�h��R?U��e?H���߽gľ��;������`W� ���?����$���"�U:A�~؄Q���D��D����Y���}#�LNk��`ے�is Yݥ���Y/�Ek-���/��(DU⇧���O��zb�|]�{O�7����CtZp�,G4�X�ό��h_ ���ܩj)C����xO�Rnqv�{���!�.�.�t� �TR��w3[�1O~p��g��Uo�j�a: �bR͵=,����)]X��>�p�1x�� By�����l�2�����<�Q�{Uց��_��]"6H�CK´����X4�ľ�~�c��!�OԴ�tf��aƀ�<׽r�H ���9~�맧 �Ϫ�0���c o�Jz��)T���BiO՚tˢ���O"��!�PSD]���ܝ$���f锜Z�Ᏺ|a��%��X+�7�f�L��x*��a�(;�O����P�t8�S?���m*h\�[c��ez-dQ�i ��:s��EB�$0� � ��k���i���"�� �F-���ww<���-�[~�35k����og��F$�?X���|9�!�3q������ѤDG�n[n5ٕg6Lܓx�F惾2`]�$Y�P7I��@$5��s��}k��Ǡ82�E�;���(>�e��8�v�a�e���K��c�o~��dʎOl�ef�)�o�\��_�E �s*�,��� ��~%of�H��Ӊ�q��~��uu�YO�f�g��� ��#�oI��t��3��Lbq|7,�Eܝ�˦���ӏm!�slM������$`��M����n���5k�,��o�@Dǘ��{ u���F����_S�<�1�� D�2�e�>x�?d��We�׎���O��QX ���EM���M��>eȂߺ.��\���?���閅`�;�#��;�`�̭�R�l|�4]���eY�|���#��=�E�Ò3I�o��<{lJp ���I&���wY \�ow'П�����wK�=L��տ�9�$�L�CGݠ���*M�<8�Hv��ʙ�:0 ��\ʶ�US�ce�,y�|�M{6\d����KS��M�{���8�{�_��8+{?w��4������D.t����!t�~xE��@�Xb����3��q�8�r�2&[[��}��Ǔ��\�S<�\޹` �ԾѶ���[6:#�׏�����䦸���'9�ge(���B;��Zs*l �P����κf ovU�|U �K��\��o�p�kqf�Zx����pu��ֆ;F� ����~�Sv���s+UUX��s ���EOf�}�' �yLoST�q�_/`%��o� V�1Ro��ñ��!Y �J��G)- �E=iM�ˈ�)A0��K�����h<�G8U��j�Qx;� �������}}Hث� S��7x�%|ި�G��up>���X���� ^�����K��<,Dĥ�Y)�˲��R����2��ъ1���_�G��h�h�H"�O���a�k��5q��lL���ZBm��''�n�.\�(a�1"+v���� me6� �� �t�o��☆��I��>��X S����0��b�� i�8WT��8-V��Á�4�j�W�ݢ��Aef��}æ�j�n�7/�+�Ai��v�����g�|��1T�����$W�jU������ �}w�i�1�8�N!���d(O5����i��@{���6�=��3�^�$P��4/�U0�6�ĢB�Co��V��V��FN߅��# ��ܷ�{g�w�f��S�z3>h��kn�}�V��^[H!<��,��rH�ly韍�v���iض��I̖�~p��Ք��Ml��L����~/�Wd��a S\���dF^W� ��n� aQ2�����¤����y�@�o�����-���4�a�jk �+��Б���X?�dc���hO3Q/_S��|cs��0(R�f@��K���� ہ�JA+u�� �S+9@���~^8�6$�"�E�{�]u��+f~���Q(� _�p{=~0L¼�fy�~^ Sda�Ğ�+}���oW���剝���0�p/,�L\��|�������3���@�s5��<����q�����;#)M�4�;UG3S�5�Y�!2w���Yhn1� w� � nzᾍ6�h�_Xx��Kn�����pI�]z)k���%r8$?�&6�a�2UR�z�\�3�L"���]"P �VQiG�@q�>&J���mL�5i����U$7��I`�Q����x]�3\����R�8ƁD�+�<���+��A�+c}���L�t�5�7[ �)`⪠��O|8]v�2M�K���tb��/�np�f����d�c����q��'����j���-(���^��갅1>�s�����e]�����spԹ�G��s��t���C���raUD�A�@�m��O%�j����W��j&����#*��י�ٙ���v5�ؾ9����M �,M�h�����tWf�A��d�/��ض��T��Ƿ�_0'�u�NJ`���Q K�oS�ǻ)pъ���~0ӕ��r�n ����yy��C}�fd| ~�z@?�|$�/W&�B˝;��b4j?D�y�{�%R#�[�k.�s���?�*�7y�^�zjr��ڦ5�[�>e� ��Vp���C��鳴���$�ɹ,4�ba�_��I?�����0��.U��Ū�:��Pr�Z���_�W耡��d-1� 6���i�� G�tr�Gx>��-����2m!=����g g�jZ���uOt�-��5�l�������}���oo�~0��{|��}����Ь&g������۸$!x���J���t��� @�Mq�灤[�G��[]'�Z��rt��E��⟕�Y}�2���$�dN'��1_�� SdN�]bN/���!-��b\�ӄ���:3��x�$3i���u�h��� � ���Lu�z��V�k�T��{m>���8���֣����A�`���|�dq���C�WZ������3&�&n�ouҗ�R�z<;��N����ui�� &�����e7q1Ox?jL�iY��+&e���ߖwC��V�s�,#^WbzKOs�P�Á�d�k�eu��dEM�Uo��c�L�!Y�f��}6?�M�3΋U�RswX3�}K*:����_����$uI�|c^"7}�(�W��� � �$t}@t8^?�Ͷ��3�1��7�H�B,�2��ඡe'�DB��ӽ/�?9C6߶ UQ���`&9��<�%5���; �X�x�y�I+�!���kaO�& �|l�qe `�t��ޯ���@+�S���#刜�h�c����׳%m��t��`�@�.^9�A��(��y�����䶆ꦔ\*e>��Do �O�$��bY��BO\6���ҹ���sؼ�3��c1u U����s�$�vN�s�"���������&Q��vT��*�����v�~}VG�.-�#i������Q��y�>�����H;���p�8��ɒ��V�������['}ɵ�*��n�dŘ�c} �{q'Ҋ��ze�"߻x�ԅz�۰ؚV4���n�l�p!?�'`�`{��8$�_��@�m�g�:HP��|����TM�-&�� ,��bۃ����ڶ*l��L^����b��z�k,�sj�h5������$j�,#B7�{�F�<�k�]��=�1U��ތ�:k|6���O (k�N\�m<AE6Vܴ�;�G�����9�K�%����֎q�Ì� ���G��;S��L���������{��Y���-R�}��E��9�3��Xr�����p ��IG#~�����Xc�w9�j·dJ7>z�~~^��KE�]艮�o�y��LD�cX��E�'�Y�?O~wp�) ��W��ve��9d��vVC��( o�����~���|��5)ïy�TC�F)M�Z KЫ� %^��!��l� ~0M*i�'6S{gx���Y��ڼ���A�5lC%Yv4¿Q�16I��� ��jc�]�,��~3�U-݄���Jn�O���{F��� ��㡏 �kc;��򗶼��zV�j�O�b^G�b毕H������h�#�佬�M3�{,��l� �~��dM� �Yy{`M/�s���Q��'!���g����a�����[�پ>�I3l����3��v� ;������dp|�d��6d/�7}��ݴ��^��~�Ы.=�K;x�h+^c���o=��/�|����o�����cc�F�(�֌�sN��!*�"?���hz�_ZϼJ��=���פ�R�7{)LjX�SO����6>s�A�����D�Z���u[n6�\9,����W��6C�g��N��V��{��a�<�|��� �� X�P4����[v��]��� o�Y� 7xd�@�D/x�.� Kq��Sֶ��f|ڴ�2xMwrPc#�s�;$����y�b�.�=a���}�K��y�~N���Ƿ1�"�ѡAPpS�k�L?JMљ,O6� EͽKf%�20k}�w}:�x�G��G���� �Ra�q��q~~�"~gKf[�<��nf��Ż�->Q��ƊjL�`���HL�*�)P�+xC���/>�ӽ�t��_W՗`J[P{b �o��q똱���� =��NΤ�a�4���/ed=ɼ���F�K�{y���s��*��~�����ب]���"?~y�P�S�'ߝC������O����_��I{i�0b}�C�;D�I�� 7nAk^nm�4�x)�{�V���3����/�9r�EN��(��3�ڏ��E?|��s��Acg3���+U��ӈGKB!MS��`�9~_�@��gKKVX��$�D���8�X��0�H�G�1%R��G � �)Y灀�3�/)�bL�#�m�(���]Kl��t�V凐�x�W��Ӈ���J���9fZ��"/!8 ��k���D�K�e�C�.U�� �̅i��v� q��Ћ�m �”���Ҧ�c\���^�Y���+4�Ĥ����>�tRYx9i" �'6��)�K��v����k3��gVӥ&+�iI�Fi+^���Û��e���'�z[ ـ�W7�'t(��mHXX��ؑ���?���J�^4U�n8j:�/ݥUçJ��)���L�%g7ȧ��y�H�b8������$�:J�)�r�������O=g. ?�y�Վ ��gf��J���-�h��� endstream endobj 1620 0 obj << /Length1 1978 /Length2 15135 /Length3 0 /Length 16353 /Filter /FlateDecode >> stream xڍ�P��� �\���\���[�3� ��w��� �� �A��^�����_ս5U3��ݫW��۽��LY�Q���(i vbdeb��)�˰�XXؙXX����AN�����4�� [0�"��FNo6q#��@[0@����`��e����`ca��O��/@��d P`�ڂ���Tb�v� s ��}���5����|d�s9@��21��,�6o;�Y�lM@@'��IA�o��d�������dd��d�`.H�p9YT��@�)��E#��Ҙ�� ǿj�fN�F@���d;�-q�o��d�Jv@�_��0�>+������D 🋍LLlm��� �9� d (I�39�91���Y;ھ�7r1Y��Y�@RD`���o}�& ;'G&G����H�v�`S1[ �����A@��swg���Z�m]���!3�����v�`��3PF��7�?6s����������L,���@�������oO;[;�ٛ �7� �����h�898�=���_Bde��L��@s��of��_���@n�O,o�� `����'��3�[����+f֐��UQ��[�����nOFvN#' ����������(����_ke�f����};�����w��= t��ͥh�ֹ@�?����������s�����_��������oE�����i� ���ـ����x�\g��)P�}��� ��5� @S������8�M�����Y9�X8���%An@Se����_]�]�y���ʶ��?n��U,,���6d&Vo���[k�������+6�5�c��8�FF�o���8��oSi t����L`[��%�7��3[�?^,�Y�ӟ���,���e���f������eQ�/qs���!η����i��x�r�Co>��-�����gbk�vL���qZ̦�BV3�_�`6�� �?��@[g���i5��I��/r�I�p���{�7�_����_�V����M��?�6���J�v/0�� ߊ��g�X���l 4s�������)������6[��:���*f�ᛲ�f}���/|K��/|S��/|S��/|S���#~���_�V����? k���V�ӟ7�[7�����݀&��s�&|��5�mwU"�����l(��WZ;�.{*�b����� "]3�"�70��J^��qX��׽R#xq��`͌��~b <9�;������5d���6��^ O��2؟��fH�S7U�~�8��i8fB�������fG� l�h����鐡t���@,yp��7�ƹտT� �L%<o���#��[|�(z�q��F'N�o����cQn�CS�>;Vt���(ln���3CWq#7�LXZ�Q��N�rj�"�}w�>$���| ���|~�]�S�����kZb?�֌H�ENOI�9��Ŕ�z{m� ���mb�H�Ǒ�a�#�=����+���l4��|YvI�#�X���)ҍ�)Sf?�r�,���/�l#7E��è��Z��9�ep֩��L�e��iU�9�����v���^C_�f�j�B�O���)]�Vԣ�S'>Xlh;J���nS������OZ����Gk~��YaA��DA� �>1�� #/Ib�9Ӣ��̞��`�m�}�W��%U���3��$�Aoέ��2�k�����>{� e��ƴ���^ECi�N��ه��x��t� C^sB�=#x'ō�A�f�BH��em�[��s%��]��Qe��^�0���K���<�Mk������T,r�L�m���ܽ�y�b�� ��οy�`��;��Y1�zZ0����40d�=�K�w��7k�p :iJS%A�R�l�ƅ����1h�?��o;�]f��/��S8�/��f�7ɝ�\:4�/��s��c�V���$l��g�6Җa���ϭ��l8^�F�DžC>�#�V5ʛ7��EG{!��D[��Q�.S ]�g�B.��/ˇ֗Ǹ�48?5L�"���;�� � o> ��>7��D�7B���<�z�H�@�u~g�5�k�穮t�܄�չ�ԄF=8� �j����+P�+�J��&W�fA����'5���QN[����K�� ��D�h�瓮qע�V�Ka�&��� �$����2�ũ&�@o�Sm>����׈�_��T-F %&=9�G�y'D���$�r����l�k�ff*�с�? aa�������m�Ãi\��������K4�))� �m8 �$FMJD�>aç��b=`�/��v��䧇"=�v�՘ס�ј��׺��9�g����>:�^S�NB�0�S@<�m�|e��z���3 �WQ%+YR�@NCUm����� ���HՁ�d}��� KX,�I?�ũa�UU��(8bL� ��s��\���|v���T��lc]�+"�Tez���<���ݧ��)�(GK����re$s�m�3�Z�9�˛X= ���I�� �� ����<�c'˺��W1��į�X�[��N��#*���S���L�o6O< 2�y���C=�C�#����w�ا�G���u��>��=Dc�+@�* �UVDq�HI�Yo���n�Ӵr�v1^�ȇ������n@�y6UR+HM�A$��q]����ٮ���:�̧_������Gn���~�� ��{����mآGd�K�4�5�ȸ�c��|<�3Ðk��wl���as<�-yi8��q�����+(��{Pg�[l��~��*\�]V�fV�s-Gz�-���>�*�l�.���8���"@�Zśx �]��K�R�&�p�b<�!NDl`J/J�g0�8!h�j=O?�;q~0��yR��������^j������8��!X`/���^�P�-�ofD ���U$��jp�F]�_Xm�?0���J�� ��YP�|��{�(`W��O��~s�S��3��:qe���P����jy5E�nI�5��~2�ynH����XŒyu��bŜ T�� /AnIf1lF��g ���hXS~a��Պ3�M�@>���qN�(���zP�K�l��B�ޑ+���~��Hq�ͦI�B�d��`���wt�#�Ae����s���3*� ��=_Ld�M�9�Xz��S�l��M����΢��?��bULߡ\LA�� �� oԲ�s��wBw������7޳u��ݺ)�wot;2�}Ro ɥu{vt(Z6�nF�Ѭ���{�̢igͷ���~��'wIno��/|DT})����xx�?i{���<:�Zl��-C���,D���븓�9~��:8n�p��0��!�-�Y�b{��c�a:g�?�H�v?���>��It�V׽t�^4��#i��G�'��^v�ri�|Kݖ����ko� �Z�GG}�ㄆO��k����4��P+ߜ���O��'L_a�����ۖ� �K�C�[]�n<8)ovʞ�����4 ��5E�W�T��A!X�PsJ�xt��;� �FH��JJ��u���;��)�L��o�'�{��p��6�_0�N���� ��Ds8c�Őü}n�����r�Fl����N�� O �ԏ!}X5uۣ���[����K�Xw �k�Kw=3i�g}>ETwi�xX�U r:��W�&�S����.��t�k�[V">���!����*���W����H荭�|��I��~$$�d����^�ݑ5��X��r�I�0��EЖ~���l��o��K��B~��@t`��)?Tڨ���*�i�V���i.��̹�DO0����4ߘ�2TW c�-��V9�tSŀj�,2ԝ�%~�|��(Z�pѵ����C��[�`q"yat2�P�h�d� ���'�Uꌽ��a�>1Z��d�W�`�~nzNW=i���v> 򁯤W���x?V`1��8.҃'V?���^ x�fkp����S�� �ҽ��H*�rp�Dg!5��?(���4 ��'V�}0�zZ���,TC lͺ�����_B�^�:%PS��%pR2{W�9 ^]�y�����qp�ﺯ�4���\H��V�L��&m�� ���dZ1��uHq��D��p�n��T��&u~�u��i=dz^�G�%��2�X9 w�0��r^ܻ��� �MԠ}�^R��ِ!*�5 bFMJz{��SP��K�����{x*f#���P�.��-���&�u��vFܳw�� ��$�N�/� ����d�I8�������1a�l;�! �&j�R�[�+1QNW��0�F�V�N;k&�f;ǀ��`Ǚ��ɀ������JN�`�k^z‹Y�+�������Q�萤��m���L�����6~��YB�3_N�I[}��vҕ���zlKE�kC�-;�W�~���sv�_]��0��W/9��Af�C��< [��Ͱ!�V}o��Z�d�eM�9�b���vN���?Y�><�R�WH-&Y�w9��o9�E��5%ɰ�M �l���3B�U� }�����h��2��I�~�Ž�z�at����&�lK�*X`�ܝ�X�ʝ�sZ ��(^�5�+�a��V3Fԓ��i�7[�p�i�q�[�{��`�����yp ����R}���ǸR��\pD�~�H�Aץ�Bn`̊��A�e�<�. V�����xai���;�U�|��.���?{�#AB:���N|��ZJ�n�"Mǥ�d �V����$R����Q�;! �D/S�Ce�~*C0�@�S�:��$��0|�1��CA�(-�ʰ��:Ǭ\&m�6[1.ӏ���A�GmC�g��k�I�o�O���?�]VfjX�A����Y��g0C-'f�Z3��+�4�>>ps �e��q�%�STi~�ғ%�;bd�ПD���}����E�QV?&��7_��ϵ��bw�A�����B����<���G���{d�/�� �Z�/�����T����k ������\Ēf�т��h�3��y�E���A��f�̟r��tM)t��l�\9`q6����L�$rI�| �6U,�K�&� @���,a�l|��c$sI��:�kB����hI�ܼ��$����3���ؽ��������� m��W�1�@�)3.���؁��i(������8�ذ��(�����C��v�54^�p���Ƀ�ۦ��"�Wc���'?yv&JJc�x��l2�2.�Ʀa/�,�j�A�P;~ ���-i�v�ː3�>m ��ݽ�f������'�����#�����"����Oi�|���[����WM���N�Z����G{�ڈ�$�݆;7:;���n++��Z�����~G�h �I���;T̄��#������=[��P�� ����=yGM�+.��x����'�v�����Hyq �<�Iڌ� ��o*ѷ�i����_�;��^� 9`�WFVf�2������gIՍ�={�[A^� ��rY*���9N� + ӯ��Z�������0���W�Զ]*��������Y�ú/�OG�`��1�R�$ViG}�ЃG�*��0�Tw"�=NOM� s�"��Η/������̈́4ςp�,Pz�J�őd��b��-U�V3G�?��V�}�A�j�b&޸�.ǣ����i5��t�� a���<��� ���nJ�R�h�$a+/���y`���o���:�����-�*DB����'ڛSa +�L�_ʸ��Ԝ|ct�&5F,d�L� Ǹv0�j�x��Q�|�;��rޗ���H�%�Ŵ�ev��Ā�_��L��%q��k�v��7�]�әaj���:��y�c�(1������x���C^-�.Bg3��y�Փ�����'y|�3��g�r��$8B�$�* ��ʉ��[�d5����������F���k�'��r焾��/Ģ��槢�ʗ��;�K�@W�F*�� �˗%��ބ�p� X�����A5[��A}d#�0Km��B��E�)A�- ��ּ ���_Cm��I��3��Pk���M5= E�ʄD�^�)�`�K�j�U�Ƣ,'g�s��ܐ�����,�6=�~<�B욅o�!��6��쵏�$*ݞ}9������`���&Eaà�!Q;����.%�9�`�%9�X�Pi��zN.�Lc�LՎ*�D1L������ȣQvt�9��S(�� q�������S'��h A6�jZ�7��q�E�Y�k��v�tg%$l"�6ުχ�<_���-���L��QFh�P�l��.B N�Ҝ8���̴/�a�e��O��Ey8���Yy}ɿ��,ɱ���{�g�fiv)���9Fv3.�]�����v���ޯ�����q*���� �����\�@“��ֵ~knڧ��+J^���A�P#r��&�O(ۺ}�ص�����4j�_B��X f�s{�B5��k�����z� Uכ��i�sO@o�w�'��6���U���b�!Ћw��m�G ��2om�?�a��������!��,�fLҚ� N�]�^��"�nqP+��٫��r�o�= {�Iw�y���>�+ -�C���U�5;�%]����O ��\x"Xiہ`��� ߝ��й�nU'�83�1 ��#�D�r�R�.qe��o���N,8֙���!�� �Vܰ.��B3?-8��U��`� ܛW�C�R���3L}�(}����P�s�|?�P�p��T| w������}�&G���N����$4������8�_���mm�;���S�]�^(��ޱ�8"�G�g� �T1mw�����u�����6�=:���@ }�$��;��%W�� �����r�K�K��b�n!8�1/�����i�ʓ���ٝ�I�q�٭Z���ptѲl@�6 ފ�� I��U���7��$�O�1��hƒ^z��f9���KΞK�� ��������7�m0=��QQ \��uJ[��˖dX��0oaO��8K��I�R��yA[� D�t,���'2���U��ÿYx�.Sj���(�Se (�4�9i�3וs� �L~������~����^��J@r���t�0E��.R��7�� $���T�w����Ϸ9H�M$�!4i��{�tuZ;�+dn�؉�뇛m� J��S� ����tӰ>�&A�kI�'��-�H(�[y�x��q~�.��P�%���ۻ� 4�ո�_eoV32�F���v�V���gږ ���py����� ,e_�M`y~���\ �� ��v�i�"ֈ®���x����a�1d�iW!^� (�r���� |����ȵt�m $�f����Cx���S�"s2�MW�7�D�p2� {�����A�h�A�����d�����3i�]�0���n�6k3���V�ho�av01�ѥ�Fh{�_��jEb�-ݕ��WD~�Rc\�9{��(C��)��m�-9*��e�0r����9�rإ���*|Oשa�5��4�� ](�h��h������� N+m, �w��O��.�J�  NX�$a!��{VR�)��V��lag�|߫ -����Z0>)o�,!d���?E_��W )���6p^�ݼ�L�Z:bC�����aX 렡��}8�K� �c/,�MDb��`�Q#�����y��spMp�|��]���g��r �@{^�^25:�L�f�֟�L����bh}�Ǘ� �]��5�bvȜV�Ȫ�'n��T!��2G#�o��n_m[��ũ���­-�`h(}�Z�Ȑt�3Z$���.6W� ���a����`�7�~\=������rA�%i���r����c�)3qq ����f4�) �̥x��Λ*�H�t}����5�_�������(^�-�B��br�� ������@���R�������&6����es�1�g��w�T��L�����;��[K�����H����ƮΜ��C�J1��z�H�+�o��>?��Oi��lл���D)ؕNp ��� R-�\��.��Zs�X�!!�8tH`�آ��>���@�,z榵���g>@A��D9�y�1"�o"��Y�{e�*0"/:��U��+��Юw ����y$�D��ҏ������F�K��?�eJ��oS�7���[��`v$�9�<��B��cF>3�`Ų���[�0iMyq��m[�q�̊�ڐ��W���T��p���`;�SFB�v��~3|�|[���의�V6Lfϓw�>P W�m�+nX�ٯ ��:}!��j=��� �.�J�l%���, |?�u��(� �7��b%u�/|����:��>�*��s�|j� �P�8ԁz|�����^��B'�*�-ܛ����e2{�84h�Û���L��Fs�?�m�����V�����,`O�~�\�7L시�1R��-M�je,~�9oa��}������.�N/��/�ւ�k~�ּ��Рݍ6�%9�^�O�z~� �x^�%�g�l!� 'C���u kw+"&��?E,�b>h2 �v"� ��>�����j�G��.�h�Q##q����_ _Y�)��D%�)[�qM2bF��� M�~GAl��j&=��y�+�H��BF�(��Oȱ�I���-�J��O���GB$�� h�N���l$��!w���x� �H/�ÛEM[g���,��Jz�t ��Ef�7��d��� �v�; l�+<�nvRw�X�kF̧�Re�-�� �iH`C���I���{�M�F֫��´f}0���k��G��Fn�eu��{�'1[�p���=�:�Qv�R:��C��:���L�,��h��B��`�7��Ck_R���"��e�w'UX� �3K0-G>q���� ��#����brV�Ǯ�����iq� �'�GX���*T��л�pt"�f�g}6w�&�iX�9 L��T�r?w� \�L�oYݛ+���Y���>xW�Uw�!�|��4��P8�c���t��4ms��'�Tf��`�^��>>�<#�)B���6д���`8���I��B�H�.9Z��K��w���W�p�Ź����b�Ch�|ma�$7Dg� �Cգ�Q3�LoT9��N&��|�Z�QOY�����O���_L=��R��ٔ� u3Mk%���v�9��[�����{~���D�зsz,U���=�T�����N�$O�ɀ^c�H�*q/�O|B�{�5 ��2D �y�}b: i�$h�-r`�Psb�Wc* �*�s�O�3�+�}Z�tD���ςR�� �c�qauѾmhW0D�ȅ���(x�X����F�6|<ۿ�I��UM�yo�9Q���B��`b�f19'Xd�2Sm�D��ܯK�� �'� �.�i�*9����˦��yl�$F?���*2�d�1�u�t�N�������y6O�o"��B���z��-0� �/NL�7g�����'��O��4�ik�gn�[{�F����f�L��U_��F֠� 7�IL���ee� �d7} !��XL?<��iǧ{�9��� �Ys�P��j�\��%Gζю��Ip�0��/�v,��!�|;�:.-EPzu��溚��eo(�������n�S���T��T�ΆG�(zڪ�x�ޒ{v~j����l��v�N���!y����0f���i�����ߟ �x��0��$)�;?y:!<�͑�ʤ��m���na���J�X]=&;�s�]���qžk�����"��n�����-���F�&�f�饨�wf�DZ�^�j䁏��Q��Z�&����B��!#��[��9� <�����O6��],��0����$mgu�u���0Y��$�7ɰ���I$�a��3H΄�������'8q�x\-� Ck{��{�/r�ÛT΂���u�X�"M]������P��X��_f����q���2���҉���#5.��d���I�?* f�� .�9)M�5�k�v�$H�i�� �$'���eő��m�v�H��Y��XA=��#� �M̖h��ﴦh�]B_��e� �2޴ �#���z���)G��R�C�1���gi���|u���(M�^3_+nb_�'�p��2���E�#&AI�;�q cxc,�������RA��oB����aO�� �<�@���[:�x���y�{&���J1�L9�)h�*U��,��$Nv���sC�6ND���i�s���o�m�gw ��QH�o�3KֶZ����F�#Θa���}��Byߺ� �9�}�Y*J�����l�M :�Y�[�%�Dެt9�w� ��Iq���Ch��|h�P��S��� �e�L �O�K��I�ݾ����[b�����kU S�"(���Ӌ'�AT���8ڽ6MZs��RO{KUrI{Xٞ���H�ő�]����-~tȃ��Ю�O������R��f�Pc�Z����y�6�� ��0��́�=�Qx����M�~\����]�R[��AﴄX�%Z*)�#0>���>g" ��X�gG���^u}D���l�v�j"V /�w~���Ʈ� �)���)��@!�����2G{��l�6�`�s��E<��2�� ��L9�v��+!���(���8�6�ӵ��=35�G�.������8��m| 7D���LᙡmG��wj�%�xd�qLc�l��=�J�+�Evd�+m�T�� �! n��W�TS�tqZ�����$ V>��Pp<\���҃�@����;�c�~P��4~X��(2am����k[w@,��ii��I�s�F]�d0��%�1�)n~u>�F����DE��|9t�i��;�����C���=G�<9%C<����4��'��:3_�xW��zld�7Ny�Ii��(�!؟��}c���<�~k�`�D�Fnݩ��}O 3�4�7�!Ć���*n��s�L�u�wݢ�y��ƒ��$����,����;t��J�U���2��)պ�Wm��\gp��@��z����ޝ�ⴽ���/_�*H��-@3~c�H,�;f^$3�7�I���-�����udnT��^'��${�s���R>�a���X�lyo4������Ӕ�)^��3eݸgO���)�vT�/V�Z�R�o†�9�I� �q��vk��sx��}���7Ѵ=�d�>m���5m�`v��p2N�ۖ����{�oO�T�t�ce?���X��}��>tZ�+��V�9�蘅�0x�{1A����E���&�ߪ�4��"A�=��Rݐ��8�$��i'����\]j�`����"-�N�d��C���8���ˀ�ol�d�d�8܅H/\��S �HO٧���;O/������r���؇ ��l�؆���}�񉟊��Kt)!�*��]湳9�}��(d�5)���m��_.C�#��i���9 L:JG�R^I�lo�2�w4��в1̚d[ 7��n�5�� үm0t�3*�����ϫ��dΫ ��ʯs��� 4S��^�����[/�Ɖ�Q,�$�OTK��Qcӌ��6���Ɵ�a.��p�ԳB�gr$R�<�VVť��brz����=*t�Mˈ[%��g9��� ���ek�9l��jQ4q�v�%��mH�v�ȗ�� ���������C��K7��"i��RI�5�� ��̌d�y�NѠ������3���L>6¯LK:�P�n]э� �����l�9���;)�W9|�V��h�M�y������j��V�[�+ڕ��x��G�X�com��UaY.oG��/�����#ز�#5�`�s�%v��+�L?[PC�=}b�Uxqs�uy�2ĺ���)$Il�&��e�<��)ׂ��̚�j�{��+��O�߻U��p����R2ø�����ʻAzr����a��{�K���ֿ&e��a� .0\\sn���K}l����Z�e�F�cߋ�����u��i�4ٚ v^�����^Q�n}���TP���0I�H� 3��ho���#3‚)�a�~��M�����UJ>"Nj�-��N��׵O�,$G �����c�Ȧ����h��C�8�s)���5���#�Hp�ߞL#EƖ�rgvC�I�JA�ⴾ,��Ƣ�+ |�A���S�o�c/�O��A6�p�κt� �����P����.-{)��US�+�+/�nk���g��7t�X�'�h�#�O���0d9W��"�{F������Q�9�2���AK�@9:j�^�ڞ7o�̬��+:T�L.f��1��Q������;�lJ� ���o~��(_���e�5�U�!}o�0��p&.��o3J�d(�yI���ߦta��,�2�N�������|�+�X�G�Q����^׈j�S��ߡ@ú�G�-^M�н�o� ����c��D;pu�,��ʧ�E���K����a�u$��`p�,����3S7$~�#O�c�W%����w�u�{e�ƽ��IC.΃�%nUn� "��/�9�ߋ~ ��1 >�1?]_�� �|�<�ԙ��|\��S,+w��'S�+ �*�6��9S�Vcʃ�-�R��e����q %��+��X�^4�!|����:��2[c8�^��E�Oo�n�H���sݬ�&H� Bwn�G�(ejhE����4}����d�k��6�5�ɱ� Aݷ0��f�͗��F�G��/���q"�])�̎�KA�T� ?x3��H��ͪ���{]=e&#�M*�_����*/�q�iO�LE߮:�:3��L�(�Q��z ϻ,���S���~�oi@�4?��D��|6A?!�����3�"RQî0�?h�q�(����/��s��R���ԙ��Ӱ���4��|쮦���i���.�KZh +M��.z��p��(��F�K� ]�KB��ݜpc���lu�P��r�e��,���Ԗ�u�6W˷x��I�$����Sr�0\0���yT�e��J� )��ۏ��L��{Vv)���N�{ߒ(i��%�vF5����|cKuO��� 3^nJ���/�@{��G�a*qE�,(�õS>��e�ۿ�YSQ� ���;��3y�CO~��6�Q_|�tb�<4��쳜 �i�!Ԕ��h��)��zo���x�!�|a��!� ��A�� endstream endobj 1622 0 obj << /Length1 1442 /Length2 6999 /Length3 0 /Length 7977 /Filter /FlateDecode >> stream xڍtT��ڶHH����sE��#���\F���W�rs@�h;#P�5�8�� ��;�_ѿ!Q��a��h'g� ��l��@������0��#������Ð�0�K�ߕ���.�l��0֮Hg,��t�բ��4�����+���(,��W}JHW���{ ��Y����A��6����9 ��.n��_.��ߜ- � ���� ����������E_v���vl.�@�!m��>�;���!�|���OD p�5�B�"Q�g��6���"=3�K��_��\� �F9z����~4L��5�x�t�o�������"�$,�].���F��� ��c�(4 ���c�W�� ������K }�Z�����E�/?��������+��&��.�����������aNHG��.E놽M�������gh5p���[�X�� ȣl/�����#1�'���Z������ר9"Q4��m���/��|Y;\��K]�6!.���*����_s`��0/�˛�D"��r ���J�Qh�ep٣`�v%�u�b���I��F A@�7 ��� @�P����(�����rP����߯ተ&��@[K��W�6|+�����4&�:�:&4^U�u_� V�>=ʉ��o[�>]$�\�u0�-�`���-y{����j��w����F� ����l�P���W���q,7�E��r�i<}CE�������5��m~ҫ����h�ŅH��6ʧ7�(�ˏ�5AY1�r�; ���Ӕ�>��r�t/r)�~s��Y�8}S&�s�(���a`�m�M��{5艃��5�����;{�cB�"O��>�9P]�>��\1�{o��ꠀc\�� �ޞ_Y�;�W��D ߬�����b�,Ȩ"��]t�o��y͈{���۩%�������›l�QMY^v��J����j�?{��E]�[J��ȿ]��5�[��cS(T�>`��c�܏�g�'���Q5�Kz�M��~�(�\�z����9��uf�M������ǵ�+���(U�)t�,Ƕ�(��T4|��?֘����� ��ƼIO3U�֝��)n:�|e�ƅQ��1����t� ����w ,�X�4�}��IN�$'��u�VE���v�h��B��Έ�G�&�%��B�Xl?Si����u�J��0��G��o�w�g_�"�AG6$�$���(�ʇ��_k�V6�7� ��;���T. ��SMӰv��X� ?%�~����ՅŤ2;YE��;C�a�E�����6��������ˌ!���/�A�Rpxy��qY��q]ȥ��L߄%��پ��K0���Z9 �oҙ/d�*���=�l[ �)�����@���g-��d_�2>�Fc��^Nb����m�ɣ52�y�p�MJ%սS_�]&�P�Q�k�c��B�UC��0���g�O��9V ��.�I��4�%�4�K�Kx �6��IYZ9�9Ol�P/e�W��� ��� �&{�ҳGp׌�U(�3iqM)s_¾�����5����y�g�<��9f���50w?1�2��j�j�˒� ��u�E�,�������7S &�J ׺��o��flv��U�\!�f_0��^_� �� �q�� e�-��6 f� � K+d��k���j�"�ˋǚsC�RJ��{�+UW�����Mj����K�^*Π �v�%�s�+,}���:�hc�� 2�{77d���J���ϯ��o���{M��,E�/VR���T�rRב�;Fu���m�wD-�w�����!�B�ͫS � ��r;� S�){ȼ�?�r��u���y���1A�7��:�+�&���fױ�#�-�y����g����vK�:x1�K�7�.mܨ�|��[��-G�.��s=�#���^Q<���r->>Ev��M*���~�٪!U�<�����[�6��5����fC�}l�+Ǥӳs��v��8|�Rl`�������*�N��8�����0�J'N�����J�պ����/�P��+G���3| ���Ѻ 9ڏ57+�w}��aS�f8�UV��ME:oI7� 0���� V~��eA�/$&��擨�Z7���GDM�~/�y8��� b56_�L���gUh9܂�Ť�����ί�w��K�b��]����ľ��l�(�f���5tP;}і/��x�?��i��r�Gr۫��}����o�m����^h��u�!�Ն ^�>>�$!��� r`-,m����R���=�_�p�|�Ǖ�g��@�WS`�>��qu�Dd�O�<�����e]�|�uX�9���b���4o<������v��*� �ۇ:��P�I|�;�E���ez{⽦ۇx�l� �79�I�*g��-h���n�b�jN}|Yi�U�y�r��2O�򄇞�a�d`����mw�b��̑��C$�fQ����-�]%Y��ɟ�O�h�XAE".b ͟� ]S�k���W@�r�I�y�����~BNr�{�!��]-①��F@�V�Dq�C2������W*x�m�Y�=�3Y/���u��xؼ8R��%Z�~B�=���/�>Ϊ؁6҉Bldi�-o���2�����[1�6���!yR?k������&��gWF�FL�=2��?��2j0���4�N:�Å�=<" 98��Ǧ\�f�����̍(�~�n/F� �*��E�j�g��6A�H��,;~:���p��g �u��`��2Y�^Q��������@�����==}H���˛��n�I���?�Hú {����a��Sq}"�jqW*��D�O�ρ��&�g�����8eJ�:Ԁ%Q\���� ��t}�}x��#=�P"�����g2ͮ��K�y�}O�q�X+�.�\�'$�"�|�"G���3H�O��v|y�""ʛ�Lެt�I,��d�'� |7&1]�vM�`%�'.��J��pS�Ɋw��.�qV�s������ǐ Q� � � ՚�(j{0���2�^ǞwC�'��5� ����{)�۳]�[�OO����g�����f4V^%$��4��B�N��΅5���US5��Az�`���x��cY���:�B�kL���uY"��CN4?a%���P_{�;oʃ��gw��~Z����v��׵P��Yp��Im٧�H39��S�����8f����Q�cl^��r��C#o�狳(���tz��m�-�h�P�9̲,���xh�~��Ç ��̩n�`��͇�������J�aH��ͭ��u�q�t��}��XN_S�0ɴ����,�s��Cw{����o84�;�v�~bt�R��KaD�bI���q)"�q_M6���?�j�/ſu�4G���M���"�ļ�����c2Ǎ�5���U\��O�B4<7���}R���*~���$T�2�^T��nm4��k�����N����av�����&�<�ܑ�*M߫��0z�k�W�C񖾍��9 �2�̋�?�N(Q�B�' F)�ݱ����S��h�7�����S�2��-���y�Ҟ��N�|*N���vS7P$�u}��!�W�Y� ��\��Pū=3�x�l�'\�&�o���Ru�쑁�ZF�_�� ��OD�=Ў�Ej.ä+[������,^H����H��!��O��!ܙ�1C�����ޥ� �f��]ٙ�N�K��1���Ͷ�W�S�?ZS3�ut>�2�u�&�'w^6&0jфC�a�͍VU�%KRD�-NЛ� ��z�f(3 �����}���E w;��������ާ�{���z�h�P��KFj���6�&D;D��IBwU�����"�,O�>���I| ��Lb��GyR���e�l(� f������-R� ^9<\#������DAM]��@�~��a�Q�ߓE�-�>�+�.�uo`��olA�t�tաq��㚊���0j��q�fl�W������#�1�z!��-%��K���6R�q�%T�K�(��;�-d+z�F��V�S� z2�cͰ�X�$�Z B��wR�`o��.���Ex us�{��Xl��ݒ��W�!ե8K��#&�i�l�e����Pa�XN0�d;d ԫ��~7�� ���9YJW��T �sW<؛ ���������i��w5a�ҁ��_�Ӷ�U�:uc1)=l��0��#�=Bf�լT��>��<�P� ��Y IrFM�\�V�[+I��ŠAǜ��6��b��Ϲ��;sa3� �� d�=�15 ��z*6Q-5��G&���c�*�h�=��0}D�^u�u���m��Gj�/K봄�BV�犩�w��W��A�_�y&� �t�7»�u缍��������������p,�,W"q2��y��� � �^��Fm���=R�*sr �9�e:�Z'B^�_a�v gv���T���hz6,��{x�<�� ��ä[�,�ς�ًQ����{eB�:���ЯxGb���Tŧ���'7�EKA|I�`�{�.� 2��˺Nf�< �XAZ�5u�sw��XME.�|��kⓃ��CJף���G��~E�߻G���I� (uG� &H��:�K� }@�8[�[e�*k�9!��Zu�X��;ڷ_8��}C��P��r^���Y�G ���+������1�T����B G�����(�Lq&iSZa��N���7��|�U����>S� �.'�)a'�[c?�����L>0�e]�*zP��/���ru���-$�iL�,S���J����(�:�KM&��=9��5�嚓�v`�v��u�N~��j�Tm;r.�H�P�k���̲f�`�+��f�l%��~�x��P�s`,N�Ԗ�U�l��K0�0L-��yB��-r����K��z����0��jM���y�o� ��K|��)��|Im��I�X[�T�ZNք�����#gc4��2�&���t�%-4 =�C����m{����CHG;��.��+�3�Ի [5�02Q������C��+J�D"�jr�l �VޕܣZR��Q��d'��>����P��(W���M����^ ���yՏY��TaZ��"��?<~$�lx9����=&�����Rk�y���GaϨ·��L�_mQ���3����j^�M������iKed|V͎p����s��W��j�B���B��dv�g&SDA�΃�tY�;O ��m�:h�R��.f8�w�R\MV[�N�Í����Ȳx1A�5��wG��F�� {�w���f�wj��w��wY��<���.�͜W���_t�X1�y5�=�aJ� TcR��&)[S��f���8լ�/��y�ɧ�Z]޳׳��Σ��s��,��*�ٶ�~myKL����VkMS ��h�64�J� &�W�{�6ʩCL��z�\`Q����߀�J=�>��m"O��u~y�'�*SÐf�L�����ۻ�3��|�x_��OU2�0��$P��N��զtSqh�$�0���p� n���a�>����Mb���|���={�@s�����I���iy�C��+uM���ߜ_\I�M�U�M����~��� �t;/I�����œv���X�Sv���A���s��H��4�yU�Bp��cC��s��U��t�\m�H$ ś.2&�fڰ�•�9�?T ��4{�\�i�%|p�M�������Q�H��F(�i���k�D���Pjޫ�����.��9���5�����z^��&��R4<�����o٭@��΂V��8�HI(�#k=�&�G}~�]5��ה%5L@�c�3�J�n������q��*/&� ��Ǽ�E�]�G I��1��9��̒�ׅE#�nef����*����[�cD�� �h�^3����������X��Ϻ!��FDx��ec(b�� � W��R#�-���x[���C�~EJ���Q��w���.�c����ص\|��M1��z�ߴ�I���֕�r�m.�wy׸O���̙?~,B݅P n���zm� �͎s�?��r�>�/�T�.j*t�Z=��9H�||Y!|$��7���%H�8��G���ٚ��Xܹ����mǖ�G� �l'sN�(�k��>^�T �o���a:�[F�)�Y}�C����i��ѹ?y7�<s[��x��͈ls������+�|�i�k�����������/��*s�6�����!J�Y'�u�;��A�)xanAW�n�k ��B���t�Ƕ"ܫ�=���k}��6�'2�T6�?O��7)�����1;�k�l+!O�� �o����{���t�����u˫���� A���i ��4q��g����>���c�ӡ��銵�K�L�xcgr�'���oie ��y���ĥ�z��t<{���m�b?#�4�*e:ۨv �2N�f�S�2�#=�|�k�:�&��#|�*կ}��&XEmW�Lƾ+J�Irz���̮˚]h;��W6�E.����0Gi�x@�R׿�p7����w�H�c>#����7k�H$t���`+'��J��or"���Α���#ΑJ�m�~gHӈ�B@�׉u2@��~!���uE��@+�:��c�#�@u�u�=�[_��y?�> stream xڌ�TH� # �� ����epw�����������w���&���9��9��������DA�A���(ng������ �UQaa03�123��QP�X8[�'��P::Y����a!�4t�D �A��v�)k �������������?C;G^����� @� eg t�����p�03w���'�ژ����E��r�� ����� k�l�1Z��-���qA�o��l�������hh��h�h&@Cp�p6(����@���r�6�Rc����[8��P�3uv3t@k c��h��� �b(K��큶��m@��8F������# ۿ����zXؚL-��yqFgwgz����/CCk';�zCWC kC#��_�ą�� ��������ى����W�L�܀�,fk"bgc�uv�����#�Tw�6�������������W&.�L��.@I�l@"��23�3�������tݍ͙~�x��R���r�񲷳����X�A_p^N��@��� ���O� ����`4�����$���A��h��f� �����_��3�����m��3)�+�h�����Jaa;w�;���� ��������׋���?Q��R�����w��*�/`�:�����ח��o���m����l �������Z����y�m�������_z� ��6��X����4�v�I�������Whb�b���Ά�Y�5����N��@ gc�z�o��9���*�9Y�:Y ,���G.c+���jɿT@����Q�����א�rp  =��A�����bM� ���&01��9��@��L��~m)'�I��o� `���L"�7�I�7�0�����L� �I�7b0}���L��;�I�7���F v���.�����E� v��Į��ؕ~#��obW��@�P��@���F�X�#P,�(����_��4���˯C�_�����������ͿrV���&��쬿Ġ��p�����8�� b2��@+� ���� ������K���T#GCc�5���1�?⿧�_�,�������a�W��Jc�/��hlg ��c�%���]�_#���Rl����Y[�3�d�]P�3�C��K��:J���4ֆ��T!��^@������s��db���7�u��4����"�{؛m���,����-���ޱ����; NPa����������g�M��e :A~Dm�bc���6�#$�e�d�;h�O�?V������q؃^ ���v����}�E�j}���Sοdv���TX{k�?���~'� ���:#����Kh� 41�]"Э���?ѱ��#�ot��;Y�uZ�f��cSY@u�ș���}������Ns��8�.����� # (��ီF&gsG�-����� @>\~' ����dl��g���q��v�c�AN��� V�? h�=� �� t�;��\:�.���v��]�����z���@c��y;c� ˚�owUB�n ���f(vտ�0x-9��< A'�T��;�%u��n�Q_�_&~�:n��m�Wl}�~ҏS��m�[����;��#�%`Py������o� �!E������έW½��de4d~Wq��S��d�!J����,E�Q�)�3! -ڹ;���� Z��+�T��I[���k����Z� �S'.9�!�5�����A���WQ���w ��4�`�}��#$���2�h��֎K<��>��L�=�����5��H 8t�nn�_� z��Cao��Ld]c��<��6��\k_K��Lh{k�n��ma�6 ��>�:�`�B\�qwz�Y��W{�XN��ϸ�+������ �A�%� ���6pQ �]W����V����t�h�.���0:\콰��j}�~�ts#���N�(��0Bk$�4�;��,�@J�����ʛ*���#{/�bR�~�U�|L6t��K�$���̌����]��qěY��PÏM���r�84�����j���rB��������G�)��$���no?�@%!��[�6��i��S` ? _V�w �)�H�ꆏ��+�(4u�"ǔ忻.��%�_ҭ"��2�5ӥ��1�>X��&�z�_�RT;n�,��~�e�����5X��ާ=n��g��zޒQ�y<*{y�q���^���]�[�Ќl� ��M�֞fE2ƨ��*"��.zY����h�7������ >�#��vs�IƻB%�7߇��g!mҭo�V)�W��#�����?ۈ���(%̨K��_�Kb����� ��z���%�*�(��������0�E�Fu&�O��L�=�>M�k��R�o���+�’� 6s"�XO��\��mQ����Rf���]�O�4�z�R3w3X�i;ON '-�~�K4�J�h2J�|�]"� ��3��7� (#������d_�D{�N��/>�d� u_�.Z��|�2k��]���,-�c�総t� yg�\]��_����Qip���FT��&��TW'��oc�Y��&�׾�G���͂ۓ[#��$�Đ��q�]����N�� �����v��3��� ;����}�N�犡�� �!Mx#�F��O�H1�M�����#�0q��l-�Y����1b�X���F����$uC�#�<�jx�GwM�s�W�"�w�. �L�N(:�s�-.�剨���c�jF��J_����iTܢ�#S�[���{>D���~�sEv3Q-q��zo��ϴ �����^�c�C��彦Ŀ��n���?�M�q���)���e�- {� �~N3�"�1`�SA��Rp��ī���:*�ӽURJ+�y�W���Cv%t�I'8 |L��:@s��s o!�:�=d(؋p�D .���Q����9,M �7�A��V�E��(�K�H�\.Z�47� ~�N���Q'��PA٤<�KS!Ko� R d���m(����xE(�I�*!�����d8���҈��[9��(���`����&~��u�aI���\���X�Ay��V�,O5Ԏ>��ٴ��V2��7�^�a���r�NH��!^uݏ�9n���y�o�?Q�vl��Au#���H��~Z�4|Em�|}ۓm��v3�����fa @UDd��D��M�&K��Mix�j�TYӉ��[8 �� j�>^F��1i�����]�Ğf���9��vc��Z�"R{�2 M��9��F���>�0����6a��lo�z%.�B;��5T��&@�_u�=Κ0AB0B۝����%�m��#w1��F��X�j|����N��~x �M:�nP2�G|pQ��.���Њ��� ��Y:\�d�5��,cI��� ��xw�O���sbA���3d��'#�U�2R�-���{ԡ�x����~�R`&\g�})�G�Y�H�R�M�^�~������Ů����E!��~s�9���eBk� ⱟx��#�*�r�_)F5��ߐ/��b ��o׉뙤 ��K)Q�sj3�О���GMyh�P��?SC—�T�ˢ�*��������|"}#�M~�(�����+6p �[�*�w� ���BМ��r�I��4�&)���9����Q��/R�ܳ�e�������_���r�b��s�����^UW �/�٥w�QqQ<�k�]�|w�CX/V7RD��<<2���Q����+2���$�_���.6Z�P�E3�x�K��Ab�$$}�`ZF��Ͷ�p���������D���:|-�l�7��Y��+݉5ơ0�YHy707Q��vQ��Ɉz6�)��n͂"�;�ڞ�Y�1�`��9M�� �%�C0LP�|�뵧K^�{�@��>X �:��5�4J��}D$ɓ#(�ܘ�f}TD�#e��W`8���g�4y���S�8 �o#��:Qu���t'�%+T����,͌2?ě�0R��um�(M'`�4 �L�g��Qr%���L@��ӝ~�K�󘱮c��]EcH}�u���2��*�"� �Dy�I�-]�{r ��F�0;GD?�w�� e�T�>��@�{�H$���g��Xi"�r�� �����c��2��#�H�Y�R4��m]#'O��A�� Cu���v:�g���wRD*����0���47�l��''�������=�d:�N�(<�$8�b~-�r�M�^�Q"X�d���6pY{�� �'�/��8lf� �y ��֙s� ��"�?z���Ly�/�*���}{�.oّ܆W���GW�ě�t*��SK��)�����k�D�BS�b$����ʄLJ�K]�nP��/ͨpT� ��G{��q��L�c][%<���oԏ�8�J�w�ʻ��&p������9�>8m<^�b�1]n�D�Z�����|LxΉ�?C�b�N�L�}_١//��̅�6�����Ӄ��q ��?�m���Kj}j��.ha��N9�x�* �� ��ب>��J�Ʒ�l�9����`�[r��$Q%�)R��|�>�(��)�@,�d˟R� wWm���,���m� {��r/}��EA���z3-pQW�.��J6.��1÷��s�����������d���,Qݖ�u���q�G�C\1F�z-Թf�TT}���ug��Pu��J��1�Xy5��G�HH��v!R���]�����Z��AG�d`��s����� 9�G��]�V��cg�:aS@�ђ��B}�8\ز䑓�y���#�|n �A'>�~G��h����Lޖ�s�i����Ol6����%� ��>�� ���V?�z��h���4g��Oe�}�"~����ef����m-�u���:�d� �??>tqHt��Q�c �����aM��KUH��,8��]��W�����ǚB%�g����1����T�M��Ϩ� ^���a(��b����hJBKk���ѷ�� }���0J �`e�������ql�<.�Y�?�z4�FŋV�Y~��bPxy7[.�F�-sB�=����y]�F]5���{�C9�]C4�o� �s�q�M�K���]+90j!�Z�9�����Jt���, ^�JW4� _Rg'ml"�RW���+e�zu�?x�+�wWU�6Ȯ;�; ��F� w��:[��K����k��S���E�AʜHX�{�����6p?aM3�/o����}�TrT ����e�N@�b�͚e�ξ�k��9'����#y����6\�ʎ+-�T�U)NV^P�5�%޷�;�^�1B� -ƀpks��+��!`^�a����y�t��Q�����j�+��$�ܛ��[�C��%)4p��ǩ35t� 9BhS���_�Z�9)?L&����8����r�A�)qO�z)��������LB����ַ�]�J�Oz��,.v׆�f��H<�]S9��i#Q�r�j�g�����}��t�-:�`�7׵o���x��y��x@"� ��/ �0�`p ��,�<��}ŠH/4��@������Rr ]o+��$�T���㛫��<��HЀ��1�8���r�a���(D�'u� ���i���I � B%́#�ț����3�!�c'���O�V ^��Ƭ<��# �/���ED]G]\Q 8���'Ip�k ���QY���t�aA�ϫo��LJ}�ڔ�'�n��b\E���&����s s��n Rc��/!�v)��i'�9�#�_#��(���;���GK�Ծ�o#���a��#PXGJ�rXp�S/�l@PvB�Ti�47�z��<��!�Uj�r�&�.��=av�?o�St�r����V���y���x [�`�1(�~i,U��4t?�$B��Â�o������^�p� %��˶�Ր.�7z� 䗬E�09&{�B���CVV Ȣ�Xj&�����|"�`�����s׈A�M��D"#���n�O�5 �� ��+7�� g.ѹH��/'�;h{;ddo�~�u$�J�&z�I�I��N��5�͙^�}�Sjw D=/�z(F�W~����W��^ѵ�W1����_ת�?� !��}I�ȫ,���vC� ����u�1L�4S���f�a�;߄&B�A� �m�x?0��ǏbR#� �^<-�až�4���O��Q��j��E���o�w�'J���Y�/�eo+�� ��x�-K� LY��>�󲉈��ɣ ������y�1j�yg� ��Av�5���Gf��%��#N>�J�����W�`��"r��X�#������.㩧J��R~�4ד�զu�Q���P��1������50�QG��8����F� )�_�='K�s�N��I8��ӳ�k�̐�����?7��j� ��E�g)���3����`���w�@�*Us�'�2�p����c-1t��b7I�T�x� 6�E|Y��݁��u������dz��ƹM��-�+��6Ǻ���m 1��L7""�.=Z�%i�!��k��츑�kZs�=%�\�芐@���o��������� ��Mu��h8�)��y1﨑G���hA8��xN���M����$Uj (s��ye�!�eh�I�[a:5�S�;ҥ9�>��q�Ѭ�PFʨ�*�"n�p�Ӕך��5��,���k e ���j CK{�݂C�–� ��"���ijI��PBROU������_�p�S��,<��6vM/ũe�7K/Y֫�G,��c�b�{jMxۙY��V�i��O7���������G��N�ש�Q6��0�f/�w'��K��]_QEq����L�x�oU�$��tdž��Qi�l�;�c�4��[ѡО+%�d�h���M~RH�H���Ovѩ��4/Q�%�刪 t�I##�ݦ0ϧ���V(7B8vs�cM�e;�L�W����I�Ka+���:|��Rb�Ɗiz�fyTV.=]��Z��5H/���mSJ�!?��aTWҤl1 �p�S��o�h;w��EQ�� ;|��L^���\_�#���^���H���N�/�ۻ*�=��$�V>���6���c�a�D�"��w�=����A��v�*Z>d?-�Β�սE���,x�\��Zh��z�����k�_,z�KhY��(o(~!������b9oS�<���!����R9����i#r�Fe��`�j_6zMs������ u�[6���/IXW٨@��%�nJ�&,���N�qa̗��&>�B��u% &T�;�ۋ����8)*�̗��Q�{Bv����o��0$��k 8�oG�F�c�\8&��Q�= �S�(�6a�(�;l�~/�-*6Wo��e�RIq�n;�1.�s�h5���s P�Zs���3-��fB��7 Z`ʽu�e�ˊ'��J�u7�I�p)����M��,�XX�;�_Zrrfr��Ør4=�M�� ���X�r:������ŕ�z�@�J�k�Y���#6����vg�N�,�8k�l���124g�4K�~j$���~Dk�qi8�)�/͵�cM7�= O��s� �B\5�&��`f&�:E4�Nvg����y��P��w��V�[0��j� }�����v��Fv�d:N�aD��֍[��(9JAh9���9����|� �n �6��"�X�m<��A��g�A/�|�Rڊ������R����g�|�f#y��%,�`q(�W��� _�x8����j���ua�rm�t{�\���+1���\h_&gr�l�������._��c��4����d�_○2�b�r��_�ÊBB��*�b�K+w���_�M�y�nUj4�A���Â0r�' #��r�:2��"Ivͺ�v����;R���ّ�7�]�P׬� ��3�ظE9�ڙE��ƙ��@e�� GKB� Ç[ֲ�T�k�0��'X�\��F�\��p=Br���+e���\E�S��Ԥ*�;��:�ҁ��,W���[ �T U!a(�{\X �b`��/S�gIF�tZ8� �U��W�)�M|�)���Ǡ��C�%6�cy��{�� =�U��<�Q[� ,�2��37�-���}^Z�X����x�ٺ;�]���3V�v##Z|L�-��u:���H���ia܃��@oѮ�R�qI����x����!�3�3+N���F�臓2�I���q;S����FD��WY�yG��K�o`=�?� N �gN}�1~N��)��m]�j����MޏQ�m>�pL����f^�V� }� `& J"��nB�l#��AZ��ɿ�AEQ�&��D��v����~d�O5�3 �yd��f���O��e`l�xZ�d�>��Rc��� �;�Zv&�ZkYLI>�������Ӏؾ� F*�(q}b�oy��o��;͆'�ޛk��T���DI���p-�0�uҍ-"�0��.���24tw�:��B#X3�hU."�NƐY��'=������*q<5����K��O��|�w�"ֈ~k��C4O^ �7`.�\���lp�gd�dӺ��n���xZ��V������^0�*�?����B_Q0d�#�B���|;Q{M �H�jw�MvR�n�ܱ?�D!� �N�j�^�^܋-/u��ܑA�V;-N$j}�9��Cnۡi�_]v��' ��� ۨ1���4��qOo*���ԜX%p��E�"������*cB�@މ,a��Bf:�%��_�YǓ�?�O���O�eU����MGB9���:�I ��u>9���c?h����ֽL�F�wG�vw����@L`f.�'��nR�6g�[If;#����$I��4�Nx����J��7�����x��5���?��H�.ۗ¹�ܑC�7��h4ܴ����i�@��? B�*-7i��+�l��C�6���c�s_)崙Ae�kMU''_�Aڇc�d�#�R?�z#*���<~A���h��@~���iC�u��-f2�R7���KA�ٕ�U�D鹡Y2�fq5�L�2TM>���hpކ�!�q��x�7��3_��w����Z�w�w{�h"x���ۆ�} �'�<�L#�?�D�^���S��F���Q�a��B�ߕ9���5�x�������j���b}#�Ŗ�9��sͼD��z&`��&D8�l�X��%���L�_:r%�>��]t)��b��ڬ����B��Vݴ� �QW�������~%~�g~�*�=���ɐo_p���|�V�]�J8��[2���^@.C�;���V�e痂y�6�M�c�b��L�~���� ��X�p��6���k7C�kw@Cr����`8k����HUk��G����z�h�&7���ֶ<�����G�֒^�V���v�r�Ӥ�Z�:N�`�x� 8��ǚuL�����w��$��`�x���'z��+����u�I��B�{p�b��h��Iwiua`����v6���>���J����ʹkw�H� ^{9�h�����b�I��!F%�������p���0B��Y�F|C�����G�1X���ِk��� kT^��O��Z�z�+�����ؒ��� zެ�>��z�@� �Ѝ~�l��O�1&�GD:�lK�ݚ.�T�rF'�®2��2���G����ȝƟ_c����7L����7���RMȧ������/LH�M��ى�ű F��m����1d#E�2��;�(̼�n�p��ï��) �>��}�0�?V8k�W{�s�j '�����s0H��N��]��E�I:"fBG��Wc4g;�t4��s���X��ׄ� �h������Ui�5�}��b+�P���=�Qz�q�W�?�,�}<��?S��1���g���˓�'���:�$�@��T��bX�ܕ��œ�T� iƇa�W���߷If�����׷�'�3�(2��8Fw}��r����!Kц�W�3s��]�����^+P\�9�����Y3��ԍ(���P����eM!d�踽�6V�jʜ�����b�$�Ipڮ�+r�}G<�O�� Ѽs˫Y��TnQD6��� Y���9c����C���M!<�\�c��$�u?����oȥ49T��A_ fJm�wS]�g�d5�L�,n��,(�n�%���L"����ݩ􈯽�����a~�PV}�J��]�fb��Ya|�Qp�(��y�&�W���r ,�-^.�� !�q^Ӡ�LΒl%�o � �9r�`{1�A4��h�jzǝ̲�nߜ�����X�eSxP��+��'�C�wU���%:zXR�-I�3���/���A�z���� '�I�+���x��5Ss���Q� ��=Ѵ��:k�bq���������BF�������f_�����X��V*�KW����������4l�[�m݊�o;��M�ֱxc�A�O�}�������v�p�c<�K�a����Y��[y���G�w����<���)���o��V�{�#��=ѝ�&'�R�H���ܙ��uԑA&skQ}�7��5 ���C�ɟ{d��'?4A�~b+-K+}2��+V쩪�}�󱲓R��O�ا#��P�u��V�U��H���$�ly����Td��"J���fT�#,��T�P�$������{3v��h�)=�vP.���V�To(ފ���=.(�\���'@�r���|mΒ`�G%r�FM�J>�k��3N/�w��l�ڼ�,�3O�^� *:2�,z�D�@QSO�{ ֘��& �D�?4����xq�'%8 � E��YF��w@�^I\-V7L�5��A����B�P �� �U4��>��1lW!�Y,ȶ��Q7W.��J��K����S�����C��6D���~K�ķ�ݑ�y�R��qȐ���򥆔t�u?D��� :������H|�S��� L�}(��{(@�a!]m�lD�G����6N�;�\�I��xȥo������~Ê2V�sÝ��yc�*�)��j�܂��<���M]na<���G�$A�`��5���8j���sr�Մ|��T����BR�g28R��"��J�܅�r��HO�L��}�p�ϰv �d���_�RT��2�4Bg����(� >�*��"1�� -�LP6<>�q�7�D����%X؟B�`_�M���i��2��o`6ܘ��`�"EyW�,`^ sO1��.�Z����-eD���pyM����^�:|�ts �v6��K�' fK�:}����z���o�0��&��1_Sc���VwT?�$�e�c���|� �?G���ӭ��%���bHBZ�����׾)���f'��)�&9��9��ऺ�SU9 �^A�"r�nF `��*F,�;J�%|��{���\F�>Q��0 �N��f7;.K�7��Sו�}�Ůb ��D�)�3�mE[9a�|b.�`=���^�+IG�Hh� ���s.N�f!�V<�yF$�-l�:V Ń��~q� �f !vA�K%DT��B� �H�}�Jݶo��z��S�1F�� ՖB��c$���~^�)8,�Қ�c�//�l��T%^��UqPK �Tu(��֦[+���Ǘ�5&�T�X�G��?��se#����U��J� k��|��v%zM�?_B�S�-�)'��d@����2{���t[���`}�,����+\�ʡBk �0$�廏_�(�n��(+�|.r�ޟ.~���X�i�ۙ�B��{�� �wx���-�����$W���z{R�=Q~ljR���wXb ��.��L�����'"�^T�:��e�E��O2��o�8.฼:���i�[Y�&Y?��1�j��������nӉ=��|5 �������E!v�nB�{���f�S���\�������� 8�˜��^��B��"zo�jm��G׻��pCHݡԂ�goX��r8=�zi���(�!��ƙTt(Y��yw��3*��=V��:2$�x��+/b��D�E�L$_���H�t��?rMi>{���3G���5���yV�f��n4�Q>䭺A�.w�{%���r��M�r��IO���ʼc2��mV� �a�: ��N�����܎�5��m!Mf���6�O��p�c�1�_�/*��?�z�$S���_�nL�jܱ��o Uo�պs�Gc\0"_&�i��e��yG*->�G��,�o[#�fd��T��>X��o+�iO&���vf]�xذ�l��V�(�&ʦ���ʮ`ROf'���[�$�i�4�}���k�) ^>ͫ N�_L�cE½ L�G��g{�4�@S��^�(g�g�;��p���s� =��—p�I�y^�oԩ����=#PV" �����l �w��5�ԀM���� 9���n����Zd�hP�B��0��Mk?���S��d�r��b���Ȝ�׾���C��L%L��Z u�ea4�m�(knY�� QJ�@u�*�׈^ ߬��N�Hs�Ѕ?�o�񓍗����ǬA��G�p�w2�Ƿ���u�J>~��T��m�4d�Un���XU��%uL�>௉��Oi9���}���/�d�?�x�W�~ �2�����f�čn��11��ҍ����r|s�2����.�KuT��N��mn���kd����6Ab� ]��_�'�N�`Q�3jtf3��`Z%��X���BǷ���sD~*���g/V�s+y�kZn����/���<-Ig�����e��).2G����c��=Xr}�������Q�\�ȣ�9��Z�t=�Ѫ p���w��ҳ��V ��Xr6�!����9����8ǚ �Ñ-��^�Lհ��f�q��f4ˢ�ʎ�5U��Ȣi&�j�f� ���@n)��xB�n��f�6�܆�5V�x�6����C�����V�K��;�4Xi���7�8�C0����f4�y�J0�_�tb��cp��qЬ��P?������,y}����|����c��T6Ү�:O5��}� 4��ⶼr ����O��I��4������>��� �錏���ަ/������ ��� �*.Y�ˎ3��5�͞�`�`څz��5��R��]�X]��G��2�<���e��z�H:��8�(e�F��2�Gv�H�3,֢Y�Ť��ξQ��>�u�5=I ��LPDJ���ץ�� J�c���ʞ&�������P"�����4��F(��i��ɔx��ӈ�^�d<��/�s�?� W�t���^�9��ҋLa� �b��� �f�l��܏v_�)Ak�9��3�͙h{�h� ��ϴ�PܝAٝ"=8UD؊;���P`J� vz��Gb��M��  �����n��z���_*�����̅�k�W�A֏��o��BŦY�xO���l��~�k ���8q�a��T�-�� �ٓ���:�W�� ⛲������s�AR*{�.0�R��%I���z�c<$KfH(X����E2;��=l��G�1����g�&Yܙ}����b��ge���3JY��?XG�GHK��a�����+��i �!��{�s�yxl��X�ŮxD�Q� � �.Y�+�MیZne.�"�uȢ�ș�� /Nv���ð����:.��>Mr��^� �)��3N��0��aQu���o�6㢈������Tt%?8�,<���G���M�M���u�G�V�<��̴eA��)��@�%e� _G�#���6��EISӡJ QxNj�mMT� ��qGU�:q����C0�Mpsޗ�J�b;�Q���[*�4����F;��Ra����Ӊ���)�� �M] �� =���ը��FXa�,$z �* C�fz0����G�����ߛp� #�=>�y��-����;f_��TN�ۈB���I�s��F��oT�5� -;v_BZ�����`1���O�����k�v����O0z����S!�� ��FG�V,�� �#L���VB�K%�x�h54 lYv������7 d4����j��,�]#VԲ�?]�cy��#�$�s��̟���,/Eq�z!�����p�Me�#ql�v���P�� +y ���]���`9|ı�6���^Dd�k��҆ti�]��J�{Oܪ��_��`�9�v�A��>�N6s~�� dR�Kn �2;?�i@�Pى����~gͬ[1y��[��޺|.�H���|O�M��_�N� �e]���)hڌ��up�£��o�b�y�{8ָ�ت!x͂�'�V�%��w�JiW"��$���L�DŽȇ��y2O핦V���)�O�ҫM;�v��V ʼnf ႺcU�6�۲��fc���p�j�+qқВ�񄼢�3�w,�'�AՁ�!�����5�U�� gFe-S `�2�cZo�^��Iz�k�W�UÙ������gW\?�b�������|��+�lM!UB�9|��ZJ�֐�f�W1�G�t���}�Q ���@�Ƿ�RR*:m)����� ���u��n��R����]hZ�bI�D���J��'J���ﶋKĬd���-C���M*^�?��5Tɶ���k"����I��e�j �Ӓ��(M{�"n�����?����p|���;��E���C�x��?�"�4Di����N� Ϲ�%[b� �h�+���η� �z"J#�]-����Z�$X�{�����@���3���;�d���:�ٖ� ���tun�.��b��/Ef�X)�W�Y��7�7>���á��jK";We��1s��1����F�N�&n�*��%Ơ�/�*}h��R��71a�Hd'X���8KX S�,>g�_��E#bS�~���6<����g��V!�Z� ��� @hio�����X� �+1R�F@e%�U�++�Z�����H���?͸��b"T��"��;�g��D/2��j���o�#��:�:�mj�yR��a���U2��Gr���R ���B��`+� �3 ��@����6���ru3 k)�畫��qp���"a��� �۹�A�i�eCr�P���[�~Hp���!���LUv�������k��F.�~���x(:8 �L��3���H0W����1o�@C�.pc��f�R,3�z$��;SL��*hi+� ��]��l��+��^Iǽ�}��(zaÄ��l��*q�0�LҿoED3������ӺB ��\ЌSO(����J���9���MȎ� *nT�l����c2��p���(�1����D�ܖ� ��}@�A� �=.�V�[��=���v���M� սB_1m7��gdON=�?l/TU{Ç���E�@zG}�2��#M�s&]��\삋�Ž�jH�B{�\ �����oz9>�R���y�]��a! &��)d0�̢�tf�Q��K���xж<]�J �����ck?��� ������]@�9�)��y{!L�'ܕ���s{��PCk�~���+6"c�x��>PIv�X�d������N_mry�.:D�?qdž��t�FaD�>�������Գ�U��m��2P�wH�•����{�3M�'��j��m9uTn�ƀ�����_���z�Ǿ�������x���tW<�>��^+_G}}�͚�+n�'��)��SnSbM�1�9(���4|��b�gG��j����o��\�����|�lݜ"�!���|��V���هn���&,�o>4�(�FF3���z��@인��K0#U��$l�)�ie>����e����s�N�,6��b�W� k�O˯Dـ�I��՛@�k��7ƙ���(�U���l��d_��F�צs�'�C���A/%m0�Â�����:�Ѳ�[���)<�f��L^߅w�K�ԗ��d�=�y2�\ ��ŸB<% �{;"(��x��`�\���$b��'�3L�p��9BGyQ�)l!��R�v�Qަ�"��o G �@j�s���~OgN����1F�V������*3`W�J.#�����H{�J9;zJ`�Ғ�o�X�׸�N�!]v�P8S�*clKH9�j�BF�Rf�ѧR�]b���S ���F�8��;=�)�R��.��5�S4^��@�}l2���o���4�%��J����x�sk nG?n���&�zH��-�?�U948{��CU�O�c�v�-��)|#���~� �$J�3̎i���s��,��|��O�౜��k��n2k�9%pP�<�������bU�i�(� �uRV��Op!?2� n0�K��X�!���nq� �!������z�ZD!l��?�lx�$��H�@NL}�ML����;��8i��T��@��F�-�(` �uj~qծE���.`n}�|�n/��- x�a�5�S#qz`�P�O����M�#Ja��~�z��M}п��������xg�Zs���a����IX(F�������H[�^���}����OV: �rv ���s�r#(����Y�Ni z�q�q��>a G&��Sҩ �����Rg���T��m��X�90" ���CE�����H%� �.P���>���&�<��x �9�K�3I���K�0��Z���W��\�����'Q��r�=���<�@��o�(�F��N�F~�^���~��6��ual�6���j"��7a�=gI})k�UҷC����~3��vDů*^�� )�˩�>9Ї�tEV��)BgǷ���Ӂ]}ʀM�]����%T�n�Q��K�}��;�`�{��o���]��f�p�P{��p7�f���ϻ�Q�"Ar�o��6.R6e�$rȄy����OF�$R��^ �*aX��Mk��#�������N��=��,�nW?��ծtbk�D[N�����d��䇕^�U�{J?����l�� 1� �R-F+��ɦ�2�/��͊m��������/$��qB�� |��-OV�����J�@c��5�q�*��������'�%���'��� ����F �:O���_("�Hj�4�ɛ��](�� �X +�s=��w�M2���$��eG6*i�/��)!�b�h��+���j˦�;� ^R���G<��c�X����� �y������n�2���ۚ4�]�e���M�;�ﰧӤg���u�O�g�YOu�y��%F�5n��'���Iqj}:Q����� Eޡ����v)��c쨊̨Sy1)eS��%�R��Z�j�\���ΉA��ԏW�-��~(����v�I�� 2��|Wη�Rċd�|�̍1�Lc��E��z����N����i+4�͎�}�.%��F��h�1�\�����-ڑq��i�9�p'� ���"q����A�0���֪~�a�& ����šۇ㑒)�%|<TL�O��Kf`{笎SH�� �=��!�t \��QC��P�N��ǂR��CW����Ei�� >���;Ъ���DZS W�:�0̡�q Kg�ʴ�J��$,��:j��գև��h������ü`���ƛ��h�����W�T���.�dM瓒��K`܈E�J8���e�w1,-J1�v.������|~9�r�� �EL���~���X-Ҋf���m,��c!��p��Hm��#k�t(�=�8�L8�`[Q>����K�]f&���l����s�.�$�]�|�_�$����V089���V�rj��K�w �� �ppF��=hWX���K�aF9�S�<�R��7�}�w��{|�eQ��u�8�;A޼h/5�w�����I��4��n�R,k"%�� ��"�'O�����LU��*YI�I��"��m��+I��y�� e�����OC��-y)m���yF�u�[K�1����ݐi��P��z�G��e�0C�����UU���� ��+ص�܌}�����c�: �a��~�G�f!�;�5�tֿ���'Ν�Oe�K��f3�h�ϡ�������5{�a�g��g�� g_$dH@;!z=���P�U��2]9��+n���)�=S��{i &g�d���zt1B�O�K�^W�U��T{Y�6*�9�*0{@��sg���c��R&+�בJҚ7�Sd�e�¡>O�z�q���ߒx���v�S�Q�����p5 L��H�~e�;�Ӝ�=(�"�.+; �Y�� ڢ�=�gc�,H#�FU$K�ֲd��n|���aM���t��"��(���dW]_ܣ�@_�3����,��"��ʑ�T7�~��jU���̋���P��������8$.i�����j�0�rwe����$3V�3� e�X���j�zæD�$�����er;��f3�Ͽ2�=�$ȥ[�Z�A��t��˔c���Jn����5�������o'��å5��+FP߮�p�m6������ uLM�v\�L**ӎ߹��' �O�_ t5/>u�`����q���A��Q&�տ�Y�Q��:h�F*�Άb���*������g39._`h�A��$K�ֆ��X 7�a������(�N(KW2�`�>��,}���w��x�� �^���nr ���I��X5�B1��:��ώMq��`���li+� ,��*�6��Z�bgW��$� �@�ℨ�4�X���Մ��V-Q���e;ke&� H7ɘ�򆲦%��l�k�� ��E��!뤘`u,�\����9��п����L�ֳ^��eK�v6/џ+��9w� ���ʹijh�}1��Ѥ��N |q,go�c�h �ڙcr�"�e�b�;����B���ȶ�ȒW�P�%�ٜ����&nT���M�p$�Ϧ.ّ�Ż� }�Ϛ���p��>X��豫[�iFo�"NQi+�խ�aR�����+U�Ǒ�3��eɨYå&���tk�M �7�{C5/� P���ld�� *�w�Y���Yv��U��>��K C�aL������a�v �A{���z� 22��㵪�N�'Z|X���WoCC�V��~&QY�,!4�I]�i����SVs�p���E^ʏ�Q�Z� �i2�6�j��#�k�:��!�ڒ������%���E��rȵ��6��/�I� ߉��J�(�J�|�Gk��9.�K; ەF��4q�"�����]��do�4��*9��Y>G��w�/io;}�m(�"������7h!?� v�(�8��6:+�l��-�t�10�ɹ�Z�#�p�Z���4�f��B�t!�psٽ#�y3r�Q�r L�q€���G�1����Bй�w!fv�"h`lo@Hp"(�R���)=_��0����B���D��W��'�9��g��EW�<����vOCb�/�C"�F۲�ܨWP��tD��1��FkX��2J�aڡ�t?MK,���z��E�f�\9Wd�l���*���Pb���F����d^�eE˹�F/�62fs5U�,^���|zWlMƭ0j��۞@R���&پƧw���@�����C;G�~A�zD��� �d�S��6����p�d�����~� )#���$��-�]pVj�˱p.U�]Ts{g�-�-�T5e��T�̕H��5 �� �#g���V-�)�M��\�[�qA�BB���&����_��Lt>hI�gS^����`�ax�����<^�����w9|{���8�y�G�k��WTW�Λ��Q endstream endobj 1626 0 obj << /Length1 1569 /Length2 3070 /Length3 0 /Length 4055 /Filter /FlateDecode >> stream xڍT 8���'m�$- y��ٳ��P^3�13f���"�҆�V��e��Bٗ��d�%����������������;�>�ܿs� �������A]2�.��#�-css@"e�H$&*jN��v���J#�IJ�1�� �ٴ�t�hL&�D% ��Pǔ�H�D*� ��J�6փ�����`�Zd����D������I(E�c�ဆ+H%�$�Kw]�qX"p��#�t�?RH�8��%��`���48��&) 0t'� ��T�� �ĺ����a������q��@g`� �H�A!�$m�As�Bl^� �� ��@�a� �;aA"����ڛ��es��D*���z���{Q� 'j� ���C!S� Џ�B?0��Tw���wǟ�Bx�؃��Wv� :|���S ��9$$?�\�����0<�D��E߸b��+MKK�͖:55ɞ�� �A��� �����b�%lV���Or �ߋ����`�MHl��$�g��dH� �K�6H }���b���4�������+�u'7�� �Ïu%�6�n�����M ��j ~_\cOpw��W���vA��H�9HM�� �M t�ӆ6��-���H ��da�edPH�|�r�\�׃Ir�B���:$��dh�<��R�^0$�$4���mă�"p��Pw~�� [�R�c�n���'�(@�L�J�aAAD��A9���a �Eq�l�� �����s�QH�[,�'�o (�A(3�7( �����ܩT�ؐ04�x�EAO�� 㔃� ������c�0��r��"vZ���x|8���������v�9c�M��{��7��Q�N�� r���� �Gm�����G�ov|{��'�!b�2e�ߥ�9$����ą��P�T:�$~��^۞7�w�?Tύ>��p� u��龳��(Y�\��_��X����J��#���K��R$F��iK�iI����b�:�ty�������'Kǥ��*{�=���b��u�.�e�R2z#BE*s��Ln"��S����35�b����{��2��A읒&=�nt�B3N�X��DM��M3ځ��O�����D�#�9Uū��ߟ��R��i�M�t�%G�Wz^�и��b���E��h��@n��'Y]��_��͌��gE�oi��9.���d�V=q�48�lxe������,���ٸ�]��-� �F����O�(���j���S�^]�N����?�7&�������j�%$W=�|�s�o���d]Tqq:��˟xТ��?�B^�� �Y[o����pъ'�s�1>!2cdE-���$X���.�hR�T�D�Қ7��떳C��I ��+��D��!� ��d�g&�����<���z}":�2׋��"�∊�9_���IG�"(��#BC��|U��#W-3�x��ga"ۓRjQ����a�J��,���J2ym��k�~{U��\��(^�ވ>�zz�K����8]0��J�R��;����p�g���9J�Z�y\*ȜC>��,r��ވD����h����Yi�WLժ/�]L{bB���ӈ)L��'i����K�Y�&��lG����$�Wk;�Ns�mK�Ic/$29�s����$�?����*;���oz$ �<����/������m�oD �^���J�����g<���s�L�;���7��:�e�8x�����oβ�ƬUbi�-R���O�0aEQ��V�Y���)�i��3��IG�xC����O m���r��I�\;8{ʳ�@�}�c���  U�9m��lE;�E|�mMN���8��&)�K��o�3ы2�- �UFϋ� ���aZ�Y���6�����:lܪV�g��X|Q�5��V��Q��s���+��[��b����s���j ����S�U�/���U��ٲ�������#-�H4WRJ����L��C�L}S����ז1ַ�h�"^���g�]�ft��<�}WXOY�� VE�L+���pVM���勪�Uh�K�]/��� 2z���N>!��-����D%VFbg�!���{��A3�|�@O���]��W�J{�x4%�涘8BM���Re�/��=�G.+��"}�Gn�*�X4w?�����(�V���|�iI�G�%�뽗Kg.�D�l=�,�c�/�S�~Wl/�� �_ o|o)��� ɳ;]���د��'��ԗ���.{��������ԅ�/$��<Ï���l����ֺ8f�-��3i�v�4�}h �48����.-$�?���Z��vkg��JS�'�.\Pl��ȉyGP<.d�ÞfR�[� .D��W�|����I��Ɔ ���;�+��lW4 ��N'=��W��v���X��L̅rW^�w�q~pKV7A�T���'׽Tݤ{h�l9ݬk��y��˥N�?z/R��Jfx�?a�N#vI� ��3#�N���_��{���Иh� v��\� ���l�:��� \�`����h�p�.�%SV��,�Y�o�u�n��X���}I�]W���,;���& �@�GmK�dX�8�5x�k�+�};�8�2}�F8i��ã�f��or#s���<�(H����* ��bˡ��Fśt�Ҙ���b2קx��^�`Ӭ��qb������/�:����-��*:1���Hg�/�WG�Ա\�;|y�X~�q�Jߑ��O_��[��w��&R��V;��?|j-.vd�<�V�[�l/��Zj�}U�C���p�]� P����Q\���C�~�K�fh���k�'Jc��0���jF|��ۻ?��;�pH�/L5. ��i��ի�ُ��ΣY�ɗ^9�I�6�{��v�z&�q�6Q�5g�M���+��Z�7C _�:�1A8�զ�!/2���Q�%���d�y�S����ע���W�s��3�΢0YL��Ҙ+^J�jޱ�/����s�v��C���GS�B�G��T�H��T  endstream endobj 1628 0 obj << /Length1 2252 /Length2 14012 /Length3 0 /Length 15351 /Filter /FlateDecode >> stream xڍ�T\�.Lw����t�4H�t�4 CwI ��!�J��tw�t7Ҝy�{����s֬��u�co�)�՘E��M�R�v`fv6~����:���������Z��K�Pk��A�v��;��N� �S��Ⱥ��9����<�ll66���w�H��� ,Y{;�3 ������� q�??t��v>>�����@'���@�l ��x45��ٛ��`��2A'h ;𳲺����:��;Y��g����U�3��h�+a���-��XP�� �x5{s���!l@�@;g����� qP��(9����G� �om�,��1���_�@v+����:�y��,�  @IJ��fۙ�%hl�l�7v5��@��� %�0�$�ozΦN �3�3��Y�2��������-���W| '�)����t�������_`�33�+ 3V ;�� PF�_���\lll����#�nj���yu�߇Ӑ |���$�> s � ����;�}��<�o���0��&@ ��o�h��4� ��c��;���~�C��������������#)��O��9�wx1s�989\o9�|���6�l �7�ߚ2v���b���u���t��=�m)�Cf��=�ظ�L!����o��������m��w@R.66��}��96��x�+Y0d��!K`��E������ �b��Oe�Ɛ5����OA�R w��2lj��`�Ck��b6 ;���3�;������� {ej �7�!����6��Q���������;9{��Aƈ�� ��YD3��� `e��CT��|��N(5�� �*��⁌�o� `�������A���?�C8�������B"��k�~�C��� �!؆\[��@H�����:@^;�9�7��/��=�?4'$,����C��od�Gq o+��o-H��.�`����$8��%��;;D�����D�B�;�;[�!q��:D��wS!���Φ�Nt�RO�? $�?�R�? �@H�<����Ҧ.N�r���s!��?���t��,�ڛ [���V���1o� MQok��3{-8���c &�We�9݈&ta-oJ�]�,�?y6�#�6ǫ�G�8 �t�9��f���)ט�h0%�������v��� 2*�v� 6)gZ8R�>dY���1>~�n�YΦ���M�Ay�h7�97�.,=e�� �7�L��e��/��8'�:Pt/�% t�u0>��L����5 ��Y���yo���`�5�$M$* a�Qb���X�[4���no ߤ���R�'���'i) (ۧ�!�|�+�)��.UQ ���b���M��IuɣJV\��� �{R pMMM,y����Yl��R�G�x�)��PƸi3�i7J�i�S�����J��N��ʾ��G."S5��H��J���P�d+���+ib��/P�=���c ��q.�dпQ}~/���2"FF����D(�aE�d^�1 �޷������t���^���, �e#P��ퟣ0!�� ������j]L�U�L�� ��w� ��� E�]�K� 7�� �f�w���Hf��!h�=gl�W�ڟ��Hn���F��+�d�.{���EF���(l�~�hp2^��!�VB�D�0�n��m���H-C�<�n�S��Ɩ�p{�����J0���C�m�׷��_$���(U���j�1Eԑ� �%�+����@����4��b�^�)\�}��%��V+�%H�뻞�|vC�b!d�=��M0#��ۨ0��A|L��9�<w�'o�Ӟ��}��D����� 楏w��� (�Cgt��x�uyg���Ɔvb&H��'��sق��%�Z���� Ծ^6r#�b�! ��ԟ��V��ؤxs,m4<�8�oм#Eiw��(\~3#-kz�,�yC��e���C4�h�aj� ��a̓�d�-���Y�T���]6��Vz��7�˖^�O��ifS|*窤u8��O%X�C#,���M���i72c~j%���)����}�R(���T���c{'���' Y�s�l�;��6�� �+����*0Q����)廧�^��"~e�9Y=`%��>y��۾xeC/��+�lXe`�@1��\V�%��-q�o���*7�,��SH�p�0����",v�Ä;���s��x�;��L �8��E?Kj�k�ϷR��[iy�Kk �<�pj>��^��zw5��aӸk�D�\m��C� 6�5�@�+��#����6{���I�D�ꦼ�I�2^=�s����IAu��t�+gp�����:L"B1$���`� �+���CU"�;�5�C��J�@��ë33̽6��8�>+��������ev��Ʒ��v�_.$I�y����:_��r��E���}��q���]�ڠ{r?�Zʾw�����+n>�/J��5����u��XM�<淘1.��_F��F��|t>��Ϭ��^s��H\�nhވ���/�]�� �����.>.�r�( ��.�{�_�z�^^���9-u��p���7�K̟�9B7���j�RLêe9@��@�n| �B��_;`� �)E��e�Y�,����-�n<����H7z�t���y3\�h�QQIJB׭���n��� �m�#o��ZV�c��#a6Y�7e39� �ĭ\Fض��fQ-ǚz��Tjc-�H�.��c�dR����g�Y ���G�B���,��c2HUi���mm���I�W0�C�����V�P������{%DTlͯ��Pmڭ��� ��삞VԮ,�~4��;��׫������=ɰ�Sn������$�"v�]@�m"���ɣ0aS���L�^Vﶨ������D�U���E����+�a�e ú�a���L��O�|��c��wZ^ܻ���"��U����%*��p��4�`x�8�� F��d�ͩ�[&�79P��7������q|�:Ր (��:Y. А�S\S���<]��)5�w�ר�ݖ�| ��8�pt����6]�5�e��c$������j[�R��������0ρ�T��Q߀ߚ��ʤ�s�����sPLL�5E���]���k��� ��X(B\� �i.ON���� ���Uu��D���ᗾ����gP��G���o� +"���n�s���$3�G�� ,��G�P}]q�-�JN��Ab�h�<��k���*4��xR�g;��^�Sm.��/z�2}A�D��*��$�O��s�ʸ�y������è,��:?&�Ȕ�[��T3^�W�ؗ�kTw��=�������G�x����P���B�Y�zU�^[�����o�·� � ��Ym)չi�i��'�t?[H����h�\0�T�0��\�����K���;�,�)ٹz����lX���t?� ˘D[|�qv[W�DSVR�;��D/��#���m�;�ݷ����7� ��ʜ��>����.�5�-Ґ�N,��m�or�� k Ʉ�T*�&89B��l�7�I#v&���L���v'�Y�^W�f*K�'N�lJ<(�K�7��KtUv�Ó ��n���}Ǹ�;�껮�.0�]� �P1�A��o��\���PfH�b1/M"Gc�� n����0�.�G�3z���m�'$v�S3L���n���u��xa���=>���~�!�[�<:���&�_J�\���ZOW\u6�&r��˘��k:�3��W��jb[S���$�S�ޏU�M-w�Q��ْ��� N�J�xI�p���G����o�AH:x�-�F�F���az.�g��٭����ȭ{���Ӆ��Ø�w��P߮b����׼T�ʵ�ެ���pZ=/��X�a��5�� ��f�B�b)#౔�><�C5o�j7{� �����U�[717�N ���~2��4��7���&0b�!?~"��)��'���-9Y^�?�������ɚ&y��(�Ab�u���K�t>e �5/�7�#.O �� �~�E�V���@�Q ʈ�G����� �1d�} ~�=?��5m�����)爢��ny�N�p��r�V���8�ץ���&�pO���<�H$�m���z������Ͼ}JE�)�Q��0�Fe��F���(�a�9���O��j:����$�jW��G�T�;��h��x�T�]EL� c�J+����l���>5� ���DØ` /� ��E�#�7��v���R� T��o�*Y���ca�4D����藑�NJ���-���_���9�H��mV�B��KԚ9c�dd�-?\c2[-�0�-�u�N�#? ���-b����'Dh�/ǩ>^ׁ]�!�UV4jVs3'�b�<�I����޺l�wô�c�%�Dš�FN� HE SW��s�)Pjm�� plݖ�6g�u�&��J3L�ٱ�{o�)":�m;��L�2�\ow���uben7�1���-���d�n`�Z���i��p]Z�[[Tv|-I��l`�hv��Z�x�S=J\���]܆Q�6��̓s�,F=��m�<�<�P����� n$D�_��1z%Y6��2Aw�ɸ3���3�_�P���{�t��c�#*�(B����Z�g��n,�-�$���Ʀ�bn�l"V��߉ �mF�(ڞ)P�}�#��(Mf#@ .sS$|]�� 0�C4މ��%�zMd�֌��E�c��K@��Z��R�X8-���&�k��gP����7ŒH�!$m��[D��@D��"N#��b38-ې��=Z�r ���Ҷ�m_�q�o(SVD_׷"��j�!���^��b@� �%M�i<�����s �g���ʷ��M�] %���-�}��(�3�'k:"���x^~îkͱ����� :�C�� �[�Vy�M����8[�5vb�˰P������U�^��`�I�Eaڏ��f�L_���G�ǝ�N��ku�n�[��C*�p" ¤l�P�=�a��H +����0wb'E��4���ts�4oM�%vEQ����}A����M����R� 8�k]PF' Un�Qa[��Vk]�ز<��-}g5����0���ox�:v���#�x�@�h�>(p�k�Ͻ�q�} ��y�@�cB>�B?7��2dXӶ���H����V�2�)ݸW6��E��C޸�l>a�rO�tܐ�qM3ݑ�u�6q�k��r���� ��c��n�b'���6�/��~YJ+FJ59�k��WM�h�2�.YSF��*�R[->������n��6\�i� %�m����a �}�d�P�x���;����1������ޏq>��L�}#�����4� �Ճ"%��v���j� 6���H떱�Z���z�w��F0+�[�h(�����~�1v6&Q����)���З�_��P��o�C��fH�IԿ#��XY�D%GP�v��b0�+����FT$E�J�Iig트�����'7�6�$F���TZvy�%�S,���}bxcF�\�}򍑐�t�M�)r���/�|w؋.mԔ���.(a�b[�d�q�4����l� 83.�DSgh��������D��F��&[߮�w/�ۥ-��ٽ��ږ�܆���������O�k\�5_��9�e�1��5�:���������K���n����H���2�e��L? �{�<|��ݝ;ԙS?Vz'�%�������%�Ϣ��c��+W�Nlʼn���DK^���:6��N��|�p���:�w�������Q4�$�R�_F �N�L��z��h�a9��mLե�b1o#�) ȕ���OȌ'j]1���*���n�5����& 5�?� ��2uFU}h9-��P~m��4�[ےS �:�*~#�����1� J;[$ �kR�L��Y@�^ �a�?b�b�;>A��W���>����;r6��E�x9���Ń)�����]��AW�n�yH�-lj���#D_�";)4H&��驧���f�{�,�P������z�]>�GNRv��p�!Z������]�>'�Q�п-���̪��f&�P ���^���<�'kۛW�}t4Q.� G@7t��Ψ|�������n���>��h�qA��ʇD\�n��oDn �� �9�Ƭ�[T��1����� �%?b�FO��~7��3�� *� M�̺v_U�\"~��:�̘��x����p��6����$/���=�qT m� B�W$�<�a���O�����B�H!Uy�zc����A��לa��wi;��B�P�&kF,}�\x�|/�nj.�h :��b�BދA�����!JU(�uij 1^ȐK�6~��K^h���[X�����d8�7�m+� �lfQ�V��6�Zћ���@-v��B衳�+����,�*ӄ�ô��Ꮸ�)X-�$��->:!Ư7i��;�äa�Q%γ��c"��oG ��gd���B����!gJ�jg��:��� ���������& ��D�dJ�zG���`�u��6�c>�������X�/� {��B�'��R�f*mk�w��R�=kg04�Wb��2R� �Y����b�8wZKSn��q�՘��" ��\�'�J�M�jZ"�d]�嚋�MC�bS eۇ}�0���~�͡�PkǥL�L�+v!)�1Г�ﺉs-@+�/�j׬e,�6�8$����ĉk�H'��D���G���U�KN�eʰ����B�$��) xˆ��{�<� �rM���fnT�9낛��3��-?�φv~N�x<�t�l��w�^2���x3洞���FaL��b��2�.4&1���.M�yQ�Hɱ�� |z�U*��R�U�`ց��tn���I��h�4���� q��5.e��[ ��‹���mߜ�z��yS��\a����։v\���*���#b�a�K�S������Z� �f#�Uw�kq� ��5�e���W=��n7 +�q��^R�I���kwE�3��ivԷ��X~Z$9�[�;�k��'ܥ�S0a���Ή#ڱ_ ��R�i�(��C�9n�(89w�= 6��4ֶ8��~L�H3T�rW�T(O�&�,ɖn�5M7��@�& ��3�� �jS1N 4֯���Ux�� �-b9�-x~o ��.�?Z�k��R�E�ÁMb,d��M&kidW�8M�I/��f��d�v��U��{�d -�x >{�g���و���)x���o_j��g(���Vz-����y�͉�uϻM��I�I�gT����NX+��wp/T\ӸWX,�+�T,{H�8��ý=3�U6�F;,�0�!�%M��3P����>�r>F.�]��u��7õb�-�X��?��K�l�mW3*�]eP(�#�00�1�S�]���M��d�Z��s�(H� �K��}(/���I�����a�H%x���f0M��h>��Tُ�o \C֥�|{���>�@�k*�㜨"���ڰX������\ߛ����H��%9Y'���_� )m���מ(�0�d��L8��(�Ux�᪮J>�-�}sIIz��q~E�׸eX#���0�za�����M���`�Qr���~�*𽱡��D�bqy��]�D^gw��|�; �4�o~ԙה�W�^���f#���KB��?��~��T��� ��@OLN��m�G"�IG���Gz����W[��!oI�<٭�&$FD�g�ƃ��$;����:k{@;��v�p|ԫ#r6짦G<���j�k�zQ?�/� �ڨ0�[���F?`� �K����),� �:�8%>�����r����`N�F��>���~f`,� e����Żѩ��)�p�̊�~����:*^?Gd�-�ڡ��_��+9��[�K�}��# _jR:�̙� � 8��CFv���L���Vٹ�g�ɟ���u$��� �q�u�ݦl�}�$�.���D`��hӔI���xƴ���*-s3��=�xKۏ4 ��ƌxĽ&�"�2��K�u�:���zK�g��^3yF�9�.*sh�� =��-{�J�V�p�Q�iV�?˙���(�@�#�����;DAq�}l��<��ר$LP�\���g��A��Yd�uwOa��1�,�w?���h):0��}��:�T��ߵ�}�ueAm�6�Yy��!��)��D�}dy�+N��z�Q��F1l�Ƣ-M����2�5���Y�Qv>��1gG5=>���fAg�����*L�+m��K1�O����q8���2[���:����L�Z#�H�O�N\��39%��S\�]��8b�q�ɟέ{j��Խ�� ����٘���5jxq�1�5D�/� J۳ɵ��>���g���T�� +E���.-8��r 7%��K�o�1��m5/,_���_����[ Os�s��R�ò3��[�P4��)vVT�?b"�aM���X^p�������ӝ�n�=��%�c�r��c-��/n%�aft�G������^΁� $�����8���[ܘ�X֧�����\���Ъ�="��I�H���6����/Sŝ�-FQ �8�kOc��b�s�7�����Z�?#\v[����E]�ncÉd���uhǾ@��P} �(��/sw��u��b 2��C�C��I��M;й�:��8��<�(&�5��#��纾s����)1^���W+g�I�*�_[d���b��%��Ө����A|�����h���� 70���?��v�������[��qhib=�%Ex�j�]n���~�du�9~M�zQ:4���� ��ʾ4����3��?��=!�D�jZ��w��td�Fn88�XȐY ��ۡ���N~CF܆�^ ��q� q�����pE���Hu�\�k�����Q_s4�1���s�&�ŤI����}���ߍiҵ�|��(8��C�[� ;#�(I�+^��X�]J�6Y���@5��7o`8��� G(�������/��+�e��*P���륞���2T��E6� [f䈫�/��>�!��ʼih��Na�,JV�����ϯ�/u�w����`��KX��ڟ��7��B�K& �" ��Q�4�>���{�-���e�����^����Bg�l��f�_�z;b=S �.=�V/��a�Rh��n.�}�T |�D v6�e;n��c��yQ]z� �؍׽�g�[IQY{罕7�-Nb���y8��\��U�|��O�������KI#e%��#;�����ѯ�sB,�#�ї�\���|���,td���e��9%c?�0p �ڎhU���ɲ��� �z%7;�bZR+KJZ%��������D���Š�-�䶭��c�S�H9|*&�w��^UOZĜ���/�H �(����0U�^ m����&�]w�z�6�P��I�mK�.�nR���qH��8M�g���~�L�� �Va�z�a�t�p���q�v>��L���99j n�m�>1�ò��"�hU�/W�}_�;vrԧ�n��c�1堋�{S-� �x� ��pŪ#6��ժT?�] �V�� �� �ҋ�o3��}<�?��p[ԫ-�.����;Fww�Q?��D3�b���,V /��?[��]X�0�8�&]��*��&�gP�˲��@�a%���n�EU��~�a�H�$J��@�례*�h��&� rb� k�����ɼ�������;S�x�;�7�̞ pDZ�Hc�r�ji�,��lL���Qs�Ҍ�q�6jY�}���|����MWzg����K�#z���2Kk��빂�J�H��b�R���I��h1�O���-�&��u�RG��ӊ�.X�a���^�%t c† �_��S�d_��dkE��'a�J[^Q�GhS�l��0삢��h�M�k�G$r��vL��ecYJ,h��f�;��3������}�p�� �"g��]�\�\n�M ��z �>�Z�Hn.�.|U�" �]�t2zb�u�v��Ȳ��֔�P@�������`�z]�Ɋ� 5����v�'Z�h#f��������J y&*d�x�cd�w۔J���"�@k����!��ꦕLV�1�<�Fl���iw ��4��I� "/v�K����v��^������$�r�w��K�-��A���]�)y����G���� �+������ Qʜʹ ����3q%��K@���J>&����y��z��ݟk n�V���H M��ˍ� V��m&������o�&S������)T%�W�W}4�|>F��|�'��l��M";��� �­,��{��E�%)1H����f�3���r�w�^Ħ�3��g߮TLj�IQ/7rL�c�/��<ؾa?�F�@�Oa3ٓp�"6H���p�%��z_SvƐ깱����23���"&�0X�P��+�C7�T��[B:1��9��& �� ��U*�T;y�� �%����&�O�h�Z��'U���i�O+1��K1�w�eR �q�2b�X^���M����q6ѻ�]>]2��zW�l\+��:�,��c:�@����BB�x/i�sMNA6�t��¹a�ˎ�A�&N�5@Mߋ�] Y��䒎#���ZU��Vl�WP�%JѦ j�w� jZ)�����-��l�*�w���C�=�t�"Ì�=4Q��<�nћџ?�P���,^��-�ڰ�5���Yx�U�+χ"���|�e�O85}6��Ԯ�L�4�'"<�B?���H�/�s�߄�R�{%x1zh,��M� L�e���Zy����y��@���K/��7JX#3�i0!��5%�N�,�~LJS� c�� }_w�”����qK�a[�r�W�_�&�x*���˂�Gw�����pz㪮 ��DzS�ո��2���~����I��V���j���"�J��h{ aHΖ�+Iz8jg9�٬UV2#ѐ�ȳ�AX��Rv� �v���K<� p9` U6��۴2���o-���kI6⋚�\3E:,$�ڟ�r�n��ÄfӉ�.D �n4H�P,ѧ�Q�a��w%��e���4WG�_��?`3��sΉP�u5TZ�J�%����"���=�0#e�� ��z��mGR%�¯V䖿#�X,�,;�r}v���Q�Ͽ���A���6��?1�j�}�Z=s����z�f��:�*W�������Q��no����"�4(�P�Yt~���B �Q��x��tn�‰��)�3�a�a;��2� +�.f�1ڶ�`��4���ISw�%O|���z&�YO��_�{��mB\�r�Z5��� ���+"�)��jmU�7I�ޝ�Xb��� ��L�9d�`�lz���c�F��Q�O,����ʷ�Ay�����Kv�6�˫�+�<�8**Ѷ<�3(�EE<��*p'�A�˴�5�Z�&%��2Ş?+��H*���������F#�{��8�5B_f���&�LJ:��X��wq,���.$M�c+΋��Q7� t2)�g ��t��ub��0c�L���w$��͌TݢPx|2چD֔�Kn��ԫ�Agդ��AA�g��7|_ �cg����byL},���_~Z�:�4���hEz�m2���7f��˒�Zy�����g� ������HS�I��U��z�qlXG=t[� d��j�?��K�&q�u������j�8�!�I`n�MJ`����D��3���A�5�e���m4r�E� �k���IX�� F̱��b.��R�c�㔐c̳�'N`�xj�ۥj��°����91$���ﺄ�JB�`ג�)< ':f����d�W2,��ӗw)wT�nw�_O�V�n��] %"3�l˾&J�>���B1(�LN�ZV8x�,%���|�E�`Ʒ�񧌄?zni�3�s�\tÆ~,�v��O��]�,��bO$@Nb�C���l)��,h޺��sic�*/��~���c_嬅[����!��7t�ML�:��moS�%��x��2��8K@���Z2`/3�����M<�r�oN*:��Y o�N�E��P������s S`O��9�����)�y6�M�U�᪈�3�q!y$Q��&��B�F���$�,;���|��ꥉ��_�vZ�+I�0�`ޚ��� �a*����0���K�(�b�' i�*[={F��J���u%@�(z� }�\��T+���~G�?N��بk-㓅GC�|(�m~~AFE}�/� ӑ���"EǪL�"UT���b[���GA%���&���!.`]坦�n�0����2ܳ=�����+A//��j9{����Ӓ�O�U�0���ud��6�e���.�[-4����e�,2u�� � �� �s ����V@����+�DkhR=[�2�]�?�!�pŨ�LtOwj̶7K���9���(Ck�i�&��х��6L���.0X/*�&�77�E� �uvD_%��g#]X���t��F��P�ޚi�t#�q�M�K�����B�CJrt�rl�����L�����wv�\����ǩ?������b#� ����鑯��ky]z? ̚���xl:�۰um��o�U-,�0Ź$ �Hv0<�mL��M�gje|��4���F��n�ŝ�X\*�0�aV��xP4���?^n���s�_�l����tt9ע�5�G��h��Q-G?GD��Hd�Dk}Ϲ涓�����ߙ�6�1������̌R�Q�Ύ�� ����ĭ���.I ���C�)f�f��(ӻE�^��N� a�k���~���4jh�~���}rx�$��M!b��$��+�m۪��C;��{�c� E��1���:��k��ь��A_r;�� |:g�����$������[ ���Ɔ��K��Hb�vԌt��s)bQ��_l�U��tZ�9���z}�l'�C�����#��}�T4�Ȧ�5�I��Ϩ����B1�n�, MB׸T�%y���j�B�/Z��&�q:j�`K49���͗s�ca2�Q��a�F�y~[(Lr�im���Ib�+��� F�YWL�^h�A�CGDt����dh��^}\Jk+X���x�sC�����n#�;x��%���2r��W�E&���B3� ���? ~�Ɲ��T������zI�� #�{=�d��k! endstream endobj 1593 0 obj << /Type /ObjStm /N 100 /First 977 /Length 3364 /Filter /FlateDecode >> stream xڽZYSI~ׯ����0u_���沍=1ڠ!aIx�����U���a�����ˬC�� ��^#5 �x�P��Kk 7�ås(I�->0L�X.Y"�(y"m�s"A�$��U��t�qK�%OT�!8Q�!#$Q^������h����� �ّ%FkA �3�Éq��@��ZG,s�8�f�K�Tr �Ƞ���G j�����Hg�sθ�?��x?�[�h"X o�xK�ת�FI�Z���1�Qcɳ<ɷd���+��Kq�h����1�%�T�� Ȇ%a��z�畊0�/8��r��@�줇���(�>���s �e�b�4���)�Q�H+����]�,��V���3� Y�ǭ� ϕF?�p1Kų�P��'�$����/����ϻ�н�l�2[^.&w��b�_��“���O_�g�����t|�$*���3�A~���Ǿ�����e6[A›��7���.�Q���^p|��O'�۳�iF@��*���-mD�� ,C�{3^�f+�/����OtLǷw�b9�]� zI/����^ьf?.��[zMo��I�������]�����_��C{0 �M��z2���Grp�e��9�� �ǖ�7���Dd���]����{�5}C��!� pzO��1=�����P;Gܖ�l1Y�Y��r~{;�~��^��7 ɯ���}�����"����M6|��Fx6�e�>���x�ͦ��U��VH�d~E��o��r5������b���.���U1o��;�[N~@W7�,����1�?�O�7�;[�kI5C�����w�����h.�4��ߟTٗ�\��ZQʪ���j!�!!�>�~wvB��),bH0�n&$��� �!!����C����#��bCIR�"C":<����#Dt�E;�RD�?'�u/1�3�f+yKz��g�[���*+7������l��u�C-C�ɮ&�����3�5 �7)��4������o ��_nM��LѤ�St�ѭʰA����_���"elG ��XYo�1��1�ĀH�:]�qP;>=��i �����Υ�L�j@U��D���c+������'�&�px��tp����==|pU�q'��N�A�mH�<�G�γ���e�T�W��J����o��JV����W����}����fvA�u�U�94�Wbc/����9r���˃�y�gg]t8M�����7�x9�ċ��x�]��L���� �}^�7�v���zmeK �A���������R�d�xҢ}7W��1��{��|-�A��������s'3`����eY]�u�%�b�ܸ��V �}���f�󻟋z|���o��@|g���n�jS�x�N��q��I�>͖�b6����`&׳d�qb���~ٶ�h�h��r�)�鸟]�o��Eֻv�&���;�>�u�+�|"�o.���'��-��DeX��e�҆� ���j?�k� M ��=;��}H�.$Y8�kR������#�����Fb�|i�_-�!�q��/�&�3^f��q"]�]�^Uҽ�b�B��}8�\��O����^��>=��AI]�O���7<�u��G���~�����=Ү�^�r� )��=����Ə���� ����[=�|�T�a��Pl]|��C�̨�O��ʗ�(���ܩ�4����(�#7Q��㈺G�?���G�HXm��p�A`e;{�c��(�Mxç�q��哮�$��T��6<����D`6R}7�p����Ԥ�����ź}���J���'t����P�Ǿ�cn�)�p��ujx��S$�y���� ��,��� xT[�6j�X�N��x�CG��l K��=.�Gp��er�S�|���jI~�SCB�I:\x�"d��O2`�J��pK\�'qA)q�ǿ��F��A���l4b�u� ��g�QI�Θ��� ���x�g��c>F��L��y }��g,杅���D&!� �:�:H 2ū�d2�XT"Ϙ�Ip�1e�b�L�d�% .� �����Q g< & @���!��M�.�M��H��X�| �j�R�w�QH�L2 ʹ}�ܪ�&��R�]Bҧ;~XT�jʧ��db "�^��+*剦DʃPI�Jw�JB�T$�j*(n"�%K�J��)�P�<#e��jY ����ݦtJ�Ndס���.��Z6��;v�c�^7 f�e%坥�`�t\�k*U�}��mK��#T�I�I�� ���F���t��������d�*�e :z������U���z�d5��q\�l���E�q|�Ⱦ�g�q�.����q�{��(��)�ke鴪CY��Dem��54*S��DEkS& e�W�qeeִ(3����7*mʊ�j��-��*�kk!���k$�5�L�tH��׌�{]�~�6�m!�l��F�J�t֪�Z٪�4:��m�M1Z���U�U��CV81I�G�"�R�/Dͤ,•�פ��ߖY0K�^]�ʖmPȂu����–m�- r�^r�J�d[5�"E�7E��"�F5^`�;�������\�ԥIG�AW��D��f K��D�z돿�A��Zk#!x�V���t��1��f�M�H�L:��늣[<1����h���xRkp��]:���ɺIU��U��H4��^o���K/[t9S����VO\��}Љ�'僚����ft�Ȗ�e+ &m[�����i� [ۦ�H����*���e�4٫��ӖS$E�>]�Vt�Ն.�ֽhkY���t��^�U{݆�.�W�ث �� �b�6�{U�^�a� �e/���}����{ً��`�ڰ���{Q�^�a/ �E�q����͹ endstream endobj 1635 0 obj << /Type /ObjStm /N 100 /First 885 /Length 1876 /Filter /FlateDecode >> stream x�}Yɪ�F�߯�4Ό!0c�i��xQ C� ���>y�T(�qsQ�����99HYH�t�G��(����A*GI����I����P�����(��~T����1�7:������W��p�u<)�D�x� 8���\`�0��X)���;���T#H� �� ��0��[iԀ��PD*����wЬQ�MN�(��T�P$Z� �3�B*��ƥ�! �u)�K�CVG��������/����/#s ��_�|�K>/����������/�G���__��g��񷯿�=x����q���w?��O��#���\L�c澋��3�{��y��Ͱ4ƺ�s�-杝w.,�TR��������Z�+��1�3�]�1�= ���`��K�����?*?�Dh��1�=2Iڛa����] +�Xo���}7X۾��5xR|�z�yj��y�*K�V,������Q�qc�α�Yo�:߬޺��=�����wF����Z�u��zk�o5ݕ��.Oݍ���X�tWt��+ʫ��J�a�kd�TX��[,uX�(W�n�����g� ��^���{�z/�{��^\�5�X��C�Oo��-�mގ��z���y����9������A�a�����798⁌�-��!̋��;����X�B�J^���������7s�}�Α��z��vu�%���� ���ܭ|��r>B�6���ÛeKBJ,���u�d����l��aQ���E;��l��r��)��PԢ:Z5{��&[�����)���^u �rKC}��_������Êh�FC��P�#ef�` e7R��K�b�]�)�n���œ����w��e?�g]��Ѣ -�9I��濧�F�����jDH�aeGD���1�O,��%F���7��$�=[����>���Ml�����G�e������ �6���r\q�m2���{�z.�3�K �b��;�L��ż_L�q��7���W� ��Ͳ�yr��@3���/�͐��4�����H7��J�}��#v���� qyW�ܵ�^���n⸷����;�=)Ϙ򌩞�e��^-���r��A[��y��7?E�=�-�� ^��o�+zf{w�e[�z?�n-²��7�˽���b��-VqXQ��qUu��]{�%�E[��"�l��˗��} �Yz,���l��a�K ��X���ї.dXi���a�:�f�u�t�Uaf�`��u�{u���.��{��^� ��{��^��5ҽm�X��w_(f� ��^����hS�b�����^"ݳ�?����Vղ)Z�a�)�s��p�i��95�[��4��nc:sT�`�r��:��KlG�E��fz�r��W���L0רO�Y�rdq9CF_�َ,x9�X�݉�hf��^�"|�q&v������;j���ѝ�ٻ\w9� ZN,� g��d�쌂�3��ۍ�茂쌂�3�˝X|��恖��o���{���ڞ�XM�O��f<ԅ���T�z���FV�'�"l7B5ﰊ�!��x(u��X�v#T��e�i�y-��_��K�յ�sZ����߇y��XQ��t�D� R�E?����z3�)��� endstream endobj 1694 0 obj << /Producer (pdfTeX-1.40.24) /Creator (TeX) /CreationDate (D:20220523085655+02'00') /ModDate (D:20220523085655+02'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/MacPorts 2022.62882_0) kpathsea version 6.3.4) >> endobj 1637 0 obj << /Type /ObjStm /N 57 /First 579 /Length 3879 /Filter /FlateDecode >> stream x��[Ys�6~���[�T���\N9��U�+��l�&��p�!'<$O���o7��c��%'���A��/4��p\��t<`#q�ćF�:A�`�s"DŽ�#����M����F�$B`~�X>�V�x���W��^���G>�7�ZC�����E��{H@D��~�-��q�(a=C:Ah* ȭ�� �$Ɩ�"@х�D���D�/��BG1D�$�-��A��a�A�dݗ��m�F��Eu[��*Ƕ��nw���g_^�}�=YZ��zJ��i�\嘬��q���`��c�y��uQ��p�߶�΋Fe]���Y�I��V��n���{�c�˞eb�y�$K3<�r�[Z�[մE]i`K��`]T7�����K�M��wi�u����Ү�.ʢ۟8!����eQ��f�+3y۷}Q�z��TWX9�Wi�!v�Tۗ����0K�,��ڨ�# �ۨnc`�5Ѳ6v��ǫ2muOZi���;m��*W��� ���m��v]S\���ZK���@� !bQ�S�?��ٟ`\�㸡���);5e+ZzJ�V_]ej�M�s�]��7��/�єǺϮހ�\]��Ө ��3��My:S�`q���A���y�{(�u���Nm[@�ӱ�Z����z@��1m��T��&�1��Gx�/�搟��htM]�D�����5�0�6[�ٴ �&2�%��jL%H`��-qzk6�M�&��@.X� ��G�Xr��i���6�ܺ� ���oUU������*#��X��q L�|�&طD�T�SC�X�� �拊g�����ϖ�2/�V�/��퇗�MFl�S�9_�M�^aD�ٛ��T��3���M��nC���Z� M�c���������"-��%T�`Z�:�~`�������� �قr�L쭋O�h����h3U�i��=�] �h�Ai���-5%MI�iW������dŸ <����Cs,!s_3K8�h�n~4�(ۤ�̞�: ���V75��3���X�EԤE�2���ƒO���1SV�j\����tS�u�ۡ��1��q������-?E|V|���ATY�)��ұ5�<9�qr�W]�������4)��)[)���.�t1�� �G�L�v�E�׃z���n�'���v��u�x\ǨXZ�,�5��ɑ+�1d(VM�p��[c>�=J`�f�g� -_|_B65 @NG��/�A�7L��iW͐�~��ٙ��Y��-Ե{\����)<�3$�\��I���/U�y��ԮL3�>��g@SyҚ��֩�p�2w����>4�#��n�T�w�Wj 5p�M`���~~�%Ȗ�����-�4������#5u?�W� ��N�� H �հzG�hV(b �� V�}��5$���J0��8�z<����o���i�U;�/��g!~�Q��:��>�#���@�c�(�=�(�ۚ�<ذ�D22��ÞJ���$��;X����֪��_�R {a���iz�u6)Bk^^��95֥�qM<����������C;{�g �����LA�����!כ�y �S�-�_�5���� �U �'%��3��%��i,��K��?�X@{d��(����鶧�^8�Z��g�Iw�1iuﺇ4����q~K�0`���r��s3�d>1���i�B&��?9�Px�=��P?� �~�q��~KG�|��o����Q��0b���$�d��c-���dh�3i�s]�Q����^S{.�e^*�u9|�t����ʥ/э��8��o��VXf���b~��Y"�]k�,��l lӗj����հT�0���\��0��C������A7��L�؏Q�?�����@?��M���>f�ʲ>xHf֬��A��2W�l�[ t=FL5� t5ľ�!&��}U��Ѥ��M�k2�3�;�T8����C(G),kœ���G�I�(Fx��q^8}��Ȓ?�S%�p��� @ ��Z�a-*�Bs�Ʋ:PaF���a���۝�jL�a������A7���5�<�½�W�D���p|�2�ad[�T)$k�D�r��/�N��S��3�;6�$�i7�s:�Mn�귣���r9<A'di��AZ�V�r��oh ��^�0����_ P#�E���j�_�����[fN��y\��?<��E����v�#�%�� b#����@�p�����b> �� �6#�E��{���b�1 ֔`M ֔`# �-�_v���#�A~��` �@��3�����gJj fuŬ������,����� ��'�AF/�G����B��$��d���J�+ŗ��j[�&�j�8RV\�~9 ��^��?���?�tN_�] ��'�����A��yr N�՚~�W&�{�ѫ�r{z��C�x�~�&�Ve�<���oA|W�/ao�:qN���3�� �A����6���9(�vg�8 endstream endobj 1695 0 obj << /Type /XRef /Index [0 1696] /Size 1696 /W [1 3 1] /Root 1693 0 R /Info 1694 0 R /ID [<07D5490B8148EBEEB68FD117C195DE18> <07D5490B8148EBEEB68FD117C195DE18>] /Length 4040 /Filter /FlateDecode >> stream x�%�{h]�u��:��iɒ�eI�e�J~ʲd[�lY�%K�$K����-[�e����r�J!�L[h��&ݥ��)%�&������A)ݜ�C�e}��h� }���������9�<�o�}��7����E�E���h؈�(j1P7�~�n6�]�עѯ�<��4�آ��ӁA�����@3h��h�� ���(�à ݠ��8�� �t� z�S�4�ӟ��y0.�Qp \A�E�5/ü[7�?U���9p<�����p�`�� ����A7�< s�+` \�`\��$H���� �7����XK�6X+`�k`�`l�mp�@<O�S� ����x F,��@���1�&�����8*U�@�~0��8��� X��P�y����/�+�_��1�R/��e|,^��5|z\M�>����od�����w#F�o�Q ̻�J@��Ψ4a�1j-�w������@;� ���s�Q'8�y�Q�\b��`.2�=� �z�Q�[������� �9F�@�dT��YF��� ��� 럦n�,8�o � �󀯋�tNa^��������&1G�%|��]Ǽ ��{���`=�h'0���F:�:�UF�|����n`^a��������71/1�\i�\�!5������X�w�^P .㻈oS���UF�ir%k�� C�����4�XE�&�i|�0��6>��D�����w��⻅O�>���;��� W��(����6� `�g��S�</�U����h>ŧ�{���W��zZ��1�CP��@f |/��,�| �c��� �>���͠�O�V�^�V�w�����l����uc��))��Np�r� � �S���>c�A|:E�\�)haꁎ�;�O����w_�&B��!|z�~p�(�v� Чw �^k��g05g�9~�0k�<��)�4�_�� �"�������;�0/}����x���>�1�sPZh%�5p�4�I�/�T�Lj����xs��k�� s���⑾Ĥj�H�B���-�=�k�s���j��6 ŋ>|�0W)^�ڦ���)^��{��H��,�'��/��ts ���H�� � ����@�,�CL�/X �*�.���e.��tsR�X�wSN�K�tK�4)^�<�ۘ�0R�`yH���lR��ķI�QO���j��X�S�7G�/Xһ�DIN�,)s�a9)^��k�DgN��}����P�H�Jr!o�LJ9E��<�U���SyD�d|��9����MUP���~�B�9����So�b��Ώ�c�H����Ώ�S���#���R��H�b��"UHb�ԓ,2)Q����)�Jj�T$ٝ��G��9)��÷�O�')����0 �sR7'W�+�l̇,���~ZO0(�R]��̯���z =�^z¢�%�'�K}N��z4��&Q�-� 1�+6,z����T�k�RO�z_�0'bs�;'s,ߴ��g�9���9 ����Eoi������_Q �P�����u���ج�s:����M}�_���6p�ǥZ�=�l�{G�n�1>}�d�Z�{?�����Ϣ?��4�"�ꢧ,��o�z�@��𪞷�o^��RPU/Z������9�$���:��{��_�:�� 0��M0i����y�` L�����E?�7�w ,�� ��z��k�b��Pi����E?n�U��z Z�: ^����!P7���x•��덞3�2�f�ۺ�z5 ��O��z�^<�O��z�^<�O������Np��FW)�v��ۚv�*����3��Y�:��6<��Nh��l��:�P����jt]t�,���#Thn���_0[���D;�x���G̶�u�`�c.U�+��~������/`���6��g� b�5�7�>�&� �Rz���2��� `�4�g�Ɠ62�f?����'-h�vS}��6���t}�C�w_?�#.�^�x�;f_y}����.�7�䓾{f��;Jʊ���̾� �I�����.ɧ���Mf#�TiT��f���uTK�EF����J����QJ�J7`Ӥ�e�q���Q��P�U*��M_��>��He���O�G W9��*���}��@ V�d��=�h�Sʷ��)��ʘţ����W�i*TK�I�'_?���9�K2o�E�W?%S��l���cY�x�I���Ա�����[:�1��,���|�*5��Y�3ݑ%��׎R �f��5���KWSU�V]������NQG�� @��a��/�|�^��c�7n���U����_�j�A���%B՘����JoTC��.:l�����]���?�[^Ɯ��ӿ�i�Z��Oʜs`�X��� O Qj���%K>���Qr�V,)G� �n��V���T��GmӒ����x�Y���|T�5ԪQO�(kUKu�j�5���`�PH��v-Y��N����Z��B�P �E�%O?��N���S��X�.E�%����S�6�������:@/T��FQ��������U�Ő%�2���U0/�50j�;���*t#6y $+H�e��|��u���#�[�z�|�o���u j ȅ�i/�-��q]�<*T䫪W�<�!O)u޶%�74B�� ���Q��J�X��%P����2���K�eD�&�2�h��_����ܲ%��^aSUn�R�����j���|P��)C���p��V�g�[U�0΂!0 ��U0��L�KV��Un�+@y L�)0 n�90n����m� V�*���:� 6�&�����*x��`<�rhK�9x��K� �����[�.H��:dt�I����Ci���!���q��]��������Ѭ8�u�ʩ1і����]Ul�Xia@O���pǭ4�]� ����pD�CdGX8�v�=������8pāC_G08DvD�CiGX8�v�#@� @}����;�w��Pߡ�C}����;�w��Pߡ�C}����;�w��Pߡ�C}����;�w��Pߡ�C}����;�w���������P?�~@���A�����{Rf�JO�tB ��@ !�@B A�f����l ,a�@0�v+�������R4jF�<�y@����4h�<�y@����4h�<�y@����4h�<�y@����4h�<�y@����4hP: Zi{W����4h�<�y@����4h�<�y@�]�Ț>,EV�nKA��h[���(�����Q�z��Q�5\=�Q�5��I����^w���x�5j�Ƶ�=I�5�������4j��?/k�n�����5��n;�ivO�NkzgA�C����Ш �YL�JL��F|:eM?��h������Ո[2*�m�� ����-���W�f�NF��Q]gl�e��e���d��dTO��je���1�/�zY/`K%c;!c&c#/c�.c�.c�?c7%�ߑ� ݌�Ԍ}���Ԍ����-ی=ڌ��2���ش����ب��>ɨ��+��ڌ��q�n^ƄeLX6iM��Ys���Ql| endstream endobj startxref 526869 %%EOF abcl-src-1.9.0/doc/asdf/asdf.texinfo0100644 0000000 0000000 00001044230 14202767264 015751 0ustar000000000 0000000 \input texinfo @c -*- mode: texinfo; coding: utf-8 -*- @c %**start of header @documentencoding UTF-8 @setfilename asdf.info @settitle ASDF Manual @c %**end of header @c We use @&key, etc to escape & from TeX in lambda lists -- @c so we need to define them for info as well. @macro AallowOtherKeys &allow-other-keys @end macro @macro Aoptional &optional @end macro @macro Arest &rest @end macro @macro Akey &key @end macro @macro Abody &body @end macro @c for install-info @dircategory Software development @direntry * asdf: (asdf). Another System Definition Facility (for Common Lisp) @end direntry @copying This manual describes ASDF, a system definition facility for Common Lisp programs and libraries. You can find the latest version of this manual at @url{https://common-lisp.net/project/asdf/asdf.html}. ASDF Copyright @copyright{} 2001-2019 Daniel Barlow and contributors. This manual Copyright @copyright{} 2001-2019 Daniel Barlow and contributors. This manual revised @copyright{} 2009-2019 Robert P. Goldman and Francois-Rene Rideau. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @end copying @titlepage @title ASDF: Another System Definition Facility @subtitle Manual for Version 3.3.5.7 @c The following two commands start the copyright page. @page @vskip 0pt plus 1filll @insertcopying @end titlepage @c Output the table of contents at the beginning. @contents @c ------------------- @ifnottex @node Top, Introduction, (dir), (dir) @top ASDF: Another System Definition Facility @ifnottex Manual for Version 3.3.5.7 @end ifnottex @insertcopying @menu * Introduction:: * Quick start summary:: * Loading ASDF:: * Configuring ASDF:: * Using ASDF:: * Defining systems with defsystem:: * The object model of ASDF:: * Controlling where ASDF searches for systems:: * Controlling where ASDF saves compiled files:: * Error handling:: * Miscellaneous additional functionality:: * Getting the latest version:: * FAQ:: * Ongoing Work:: * Bibliography:: * Concept Index:: * Function and Macro Index:: * Variable Index:: @c @detailmenu * Class and Type Index:: @c @detailmenu --- The Detailed Node Listing --- Loading ASDF * Loading a pre-installed ASDF:: * Checking whether ASDF is loaded:: * Upgrading ASDF:: * Replacing your implementation's ASDF:: * Loading ASDF from source:: Configuring ASDF * Configuring ASDF to find your systems:: * Configuring ASDF to find your systems --- old style:: * Configuring where ASDF stores object files:: * Resetting the ASDF configuration:: Using ASDF * Loading a system:: * Convenience Functions:: * Moving on:: Defining systems with defsystem * The defsystem form:: * A more involved example:: * The defsystem grammar:: * Other code in .asd files:: * The package-inferred-system extension:: The Object model of ASDF * Operations:: * Components:: * Dependencies:: * Functions:: * Parsing system definitions:: Operations * Predefined operations of ASDF:: * Creating new operations:: Components * Common attributes of components:: * Pre-defined subclasses of component:: * Creating new component types:: Properties * Pre-defined subclasses of component:: * Creating new component types:: Controlling where ASDF searches for systems * Configurations:: * Truenames and other dangers:: * XDG base directory:: * Backward Compatibility:: * Configuration DSL:: * Configuration Directories:: * Shell-friendly syntax for configuration:: * Search Algorithm:: * Caching Results:: * Configuration API:: * Introspection:: * Status:: * Rejected ideas:: * TODO:: * Credits for the source-registry:: Configuration Directories * The here directive:: Introspection * *source-registry-parameter* variable:: * Information about system dependencies:: Controlling where ASDF saves compiled files * Output Configurations:: * Output Backward Compatibility:: * Output Configuration DSL:: * Output Configuration Directories:: * Output Shell-friendly syntax for configuration:: * Semantics of Output Translations:: * Output Caching Results:: * Output location API:: * Credits for output translations:: Miscellaneous additional functionality * Controlling file compilation:: * Controlling source file character encoding:: * Miscellaneous Functions:: * Some Utility Functions:: FAQ * Where do I report a bug?:: * Mailing list:: * What has changed between ASDF 1 ASDF 2 and ASDF 3?:: * Issues with installing the proper version of ASDF:: * Issues with configuring ASDF:: * Issues with using and extending ASDF to define systems:: * ASDF development FAQs:: ``What has changed between ASDF 1, ASDF 2, and ASDF 3?'' * What are ASDF 1 2 3?:: * How do I detect the ASDF version?:: * ASDF can portably name files in subdirectories:: * Output translations:: * Source Registry Configuration:: * Usual operations are made easier to the user:: * Many bugs have been fixed:: * ASDF itself is versioned:: * ASDF can be upgraded:: * Decoupled release cycle:: * Pitfalls of the transition to ASDF 2:: * Pitfalls of the upgrade to ASDF 3:: * What happened to the bundle operations:: Issues with installing the proper version of ASDF * My Common Lisp implementation comes with an outdated version of ASDF. What to do?:: * I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?:: * After upgrading ASDF, ASDF (and Quicklisp) can't find my systems: After upgrading ASDF. Issues with configuring ASDF * How can I customize where fasl files are stored?:: * How can I wholly disable the compiler output cache?:: * How can I debug problems finding ASDF systems:: Issues with using and extending ASDF to define systems * How can I cater for unit-testing in my system?:: * How can I cater for documentation generation in my system?:: * How can I maintain non-Lisp (e.g. C) source files?:: * I want to put my module's files at the top level. How do I do this?:: * How do I create a system definition where all the source files have a .cl extension?:: * How do I mark a source file to be loaded only and not compiled?:: * How do I work with readtables?:: * How can I capture ASDF's output?:: * LOAD-PATHNAME has a weird value:: ASDF development FAQs * How do I run the tests interactively in a REPL?:: @end detailmenu @end menu @end ifnottex @c ------------------- @node Introduction, Quick start summary, Top, Top @comment node-name, next, previous, up @chapter Introduction @cindex ASDF-related features @vindex *features* @cindex Testing for ASDF @cindex ASDF versions @cindex :asdf @cindex :asdf2 @cindex :asdf3 ASDF, or Another System Definition Facility, is a @emph{build system}: a tool for specifying how systems of Common Lisp software are made up of components (sub-systems and files), and how to operate on these components in the right order so that they can be compiled, loaded, tested, etc. If you are new to ASDF, @pxref{Quick start summary,,the quick start guide}. ASDF presents three faces: one for users of Common Lisp software who want to reuse other people's code, one for writers of Common Lisp software who want to specify how to build their systems, and one for implementers of Common Lisp extensions who want to extend the build system. For more specifics, @pxref{Using ASDF}, to learn how to use ASDF to load a system. @xref{Defining systems with defsystem}, to learn how to define a system of your own. @xref{The object model of ASDF}, for a description of the ASDF internals and how to extend ASDF. Note that ASDF is @emph{not} a tool for library and system @emph{installation}; it plays a role like @code{make} or @code{ant}, not like a package manager. In particular, ASDF should not to be confused with Quicklisp or ASDF-Install, that attempt to find and download ASDF systems for you. Despite what the name might suggest, ASDF-Install was never a part of ASDF; it was always a separate piece of software. ASDF-Install has also been unmaintained and obsolete for a very long time. We recommend you use Quicklisp (@uref{http://www.quicklisp.org/}) instead, a Common Lisp package manager which works well and is being actively maintained. If you want to download software from version control instead of tarballs, so you may more easily modify it, we recommend clbuild (@uref{http://common-lisp.net/project/clbuild/}). As for where on your filesystem to install Common Lisp software, we recommend subdirectories of @file{~/common-lisp/}: starting with ASDF 3.1.2 (2014), this hierarchy is included in the default source-registry configuration. Finally, note that this manual is incomplete. All the bases are covered, but many advanced topics are only barely alluded to, and there is not much in terms of examples. The source code remains the ultimate source of information, free software systems in Quicklisp remain the best source of examples, and the mailing-list the best place to ask for help. @node Quick start summary, Loading ASDF, Introduction, Top @chapter Quick start summary @itemize @item To load an ASDF system: @itemize @item Load ASDF itself into your Lisp image, using @code{(require "asdf")}. Check that you have a recent version using @code{(asdf:asdf-version)}. For more details, or if any of the above fails, @pxref{Loading ASDF}. @item Make sure software is installed where ASDF can find it. The simplest way is to put all your Lisp code in subdirectories of @file{~/common-lisp/} (starting with ASDF 3.1.2), or @file{~/.local/share/common-lisp/source/} (for ASDF 2 and later, or if you want to keep source in a hidden directory). For more details, @pxref{Configuring ASDF to find your systems}. @item Load your system with @code{(asdf:load-system "@var{my-system}")}. @xref{Using ASDF}. @end itemize @item To make your own ASDF system: @itemize @item As above, load and configure ASDF. @item Make a new directory for your system, @code{@var{my-system}/}, again in a location where ASDF can find it. All else being equal, the easiest location is probably @file{~/common-lisp/my-system/}. @xref{Configuring ASDF to find your systems}. @item Create an ASDF system definition listing the dependencies of your system, its components, and their interdependencies, and put it in @file{@var{my-system}.asd}. This file must have the same name as your system, all lowercase. @xref{Defining systems with defsystem}. @item Use @code{(asdf:load-system "@var{my-system}")} to make sure it's all working properly. @xref{Using ASDF}. @end itemize @end itemize @c FIXME: (1) add a sample project that the user can cut and paste to @c get started. (2) discuss the option of starting with Quicklisp. @node Loading ASDF, Configuring ASDF, Quick start summary, Top @comment node-name, next, previous, up @chapter Loading ASDF @menu * Loading a pre-installed ASDF:: * Checking whether ASDF is loaded:: * Upgrading ASDF:: * Replacing your implementation's ASDF:: * Loading ASDF from source:: @end menu @node Loading a pre-installed ASDF, Checking whether ASDF is loaded, Loading ASDF, Loading ASDF @section Loading a pre-installed ASDF The recommended way to load ASDF is via: @lisp (require "asdf") @end lisp All actively maintained Lisp implementations now include a copy of ASDF 3 that you can load this way using Common Lisp's @code{require} function.@footnote{ NB: all implementations except GNU CLISP also accept @code{(require "ASDF")}, @code{(require 'asdf)} and @code{(require :asdf)}. For portability's sake, you should use @code{(require "asdf")}. } If the implementation you are using doesn't provide a recent ASDF 3, we recommend you upgrade it. If for some reason you would rather not upgrade it, we recommend you replace your implementation's ASDF. @xref{Replacing your implementation's ASDF}. If all else fails, see @pxref{Loading ASDF from source} below. If you use an actively maintained implementation that fails to provide an up-to-date enough stable release of ASDF, you may also send a bug report to your Lisp vendor and complain about it --- or you may fix the issue yourself if it's free software. As of the writing of this manual, the following implementations provide ASDF 3 this way: ABCL, Allegro CL, CLASP, Clozure CL, CMUCL, ECL, GNU CLISP, LispWorks, MKCL, SBCL. The following implementations only provide ASDF 2: MOCL, XCL. The following implementations don't provide ASDF: Corman CL, GCL, Genera, MCL, SCL. The latter implementations are not actively maintained (except maybe GCL); if some of them are ever released again, they probably will include ASDF 3. For maximum convenience you might want to have ASDF loaded whenever you start your Lisp implementation, for example by loading it from the startup script or dumping a custom core --- check your Lisp implementation's manual for details. SLIME notably sports a @code{slime-asdf} contrib that makes life easier with ASDF. @node Checking whether ASDF is loaded, Upgrading ASDF, Loading a pre-installed ASDF, Loading ASDF @section Checking whether ASDF is loaded To check that ASDF is properly loaded, you can run this form: @lisp (asdf:asdf-version) @end lisp If it returns a string, that is the version of ASDF that is currently installed. If that version is suitably recent (say, 3.1.2 or later), then you can skip directly to next chapter: @xref{Configuring ASDF}. If it raises an error, then either ASDF is not loaded, or you are using a very old version of ASDF, and need to install ASDF 3. For more precision in detecting versions old and new, @pxref{How do I detect the ASDF version?}. If you are experiencing problems with ASDF, please try upgrading to the latest released version, using the method below, before you contact us and raise an issue. @node Upgrading ASDF, Replacing your implementation's ASDF, Checking whether ASDF is loaded, Loading ASDF @section Upgrading ASDF @c FIXME: tighten this up a bit -- there's a lot of stuff here that @c doesn't matter to almost anyone. Move discussion of updating antique @c versions of ASDF down, or encapsulate it. If your implementation already provides ASDF 3 or later (and it should), but you want a more recent ASDF version than your implementation provides, then you just need to ensure the more recent ASDF is installed in a configured path, like any other system. We recommend you download an official tarball or checkout a release from git into @file{~/common-lisp/asdf/}. (@pxref{Configuring ASDF to find your systems}). Once the source code for ASDF is installed, you don't need any extra step to load it beyond the usual @code{(require "asdf")}: ASDF 3 will automatically look whether an updated version of itself is available amongst the regularly configured systems, before it compiles anything else. If your implementation fails to provide ASDF 3 or later, @pxref{Replacing your implementation's ASDF}. @node Replacing your implementation's ASDF, Loading ASDF from source, Upgrading ASDF, Loading ASDF @section Replacing your implementation's ASDF All maintained implementations now provide ASDF 3 in their latest release. If yours doesn't, we recommend you upgrade it. Now, if you insist on using an old implementation that didn't provide ASDF or provided an old version, we recommend installing a recent ASDF, as explained below, into your implementation's installation directory. Thus your modified implementation will now provide ASDF 3. This requires proper write permissions and may necessitate execution as a system administrator. The ASDF source repository contains a tool to help you upgrade your implementation's ASDF. You can invoke it from the shell command-line as @code{tools/asdf-tools install-asdf lispworks} (where you can replace @code{lispworks} by the name of the relevant implementation), or you can @code{(load "tools/install-asdf.lisp")} from your Lisp REPL. This script works on Allegro CL, Clozure CL, CMU CL, ECL, GCL, GNU CLISP, LispWorks, MKCL, SBCL, SCL, XCL. It doesn't work on ABCL, Corman CL, Genera, MCL, MOCL. Happily, ABCL is usually pretty up to date and shouldn't need that script. GCL requires a very recent version, and hasn't been tested much. Corman CL, Genera, MCL are obsolete anyway. MOCL is incomplete. @node Loading ASDF from source, , Replacing your implementation's ASDF, Loading ASDF @section Loading ASDF from source If you write build scripts that must remain portable to old machines with old implementations that you cannot ensure have been upgraded or modified to provide a recent ASDF, you may have to install the file @file{asdf.lisp} somewhere and load it with: @lisp (load "/path/to/your/installed/asdf.lisp") @end lisp The single file @file{asdf.lisp} is all you normally need to use ASDF. You can extract this file from latest release tarball on the @url{https://common-lisp.net/project/asdf/,ASDF website}. If you are daring and willing to report bugs, you can get the latest and greatest version of ASDF from its git repository. @xref{Getting the latest version}. For scripts that try to use ASDF simply via @code{require} at first, and make heroic attempts to load it the hard way if at first they don't succeed, see @file{tools/load-asdf.lisp} distributed with the ASDF source repository, or the code of @url{https://cliki.net/cl-launch,@code{cl-launch}}. @node Configuring ASDF, Using ASDF, Loading ASDF, Top @comment node-name, next, previous, up @chapter Configuring ASDF For standard use cases, ASDF should work pretty much out of the box. We recommend you skim the sections on configuring ASDF to find your systems and choose the method of installing Lisp software that works best for you. Then skip directly to @xref{Using ASDF}. That will probably be enough. You are unlikely to have to worry about the way ASDF stores object files, and resetting the ASDF configuration is usually only needed in corner cases. @menu * Configuring ASDF to find your systems:: * Configuring ASDF to find your systems --- old style:: * Configuring where ASDF stores object files:: * Resetting the ASDF configuration:: @end menu @node Configuring ASDF to find your systems, Configuring ASDF to find your systems --- old style, Configuring ASDF, Configuring ASDF @section Configuring ASDF to find your systems In order to compile and load your systems, ASDF must be configured to find the @file{.asd} files that contain system definitions. There are a number of different techniques for setting yourself up with ASDF, starting from easiest to the most complex: @itemize @bullet @item Put all of your systems in one of the standard locations, subdirectories of @itemize @item @file{~/common-lisp/} or @item @file{~/.local/share/common-lisp/source/}. @end itemize If you install software there, you don't need further configuration.@footnote{ @file{~/common-lisp/} is only included in the default configuration starting with ASDF 3.1.2 or later. If your implementation provides an earlier variant of ASDF, you may need to explicitly configure it to use this path, as further explained. } You can then skip to the next section. @xref{Loading a system}. @item If you're using some tool to install software (e.g. Quicklisp), the authors of that tool should already have configured ASDF. @item If you have more specific desires about how to lay out your software on disk, the preferred way to configure where ASDF finds your systems is the @code{source-registry} facility, fully described in its own chapter of this manual. @xref{Controlling where ASDF searches for systems}. Here is a quick recipe for getting started. First create the directory @file{~/.config/common-lisp/source-registry.conf.d/}@footnote{ For Windows users, and starting with ASDF 3.1.5, start from your @file{%LOCALAPPDATA%}, which is usually @file{~/AppData/Local/} (but you can ask in a @code{CMD.EXE} terminal @code{echo %LOCALAPPDATA%} to make sure) and underneath create a subpath @file{config/common-lisp/source-registry.conf.d/}. }; there create a file with any name of your choice but with the type @file{conf}@footnote{ By requiring the @file{.conf} extension, and ignoring other files, ASDF allows you to have disabled files, editor backups, etc. in the same directory with your active configuration files. ASDF will also ignore files whose names start with a @file{.} character. It is customary to start the filename with two digits, to control the sorting of the @code{conf} files in the source registry directory, and thus the order in which the directories will be scanned. }, for instance @file{50-luser-lisp.conf}; in this file, add the following line to tell ASDF to recursively scan all the subdirectories under @file{/home/luser/lisp/} for @file{.asd} files: @kbd{(:tree "/home/luser/lisp/")} That's enough. You may replace @file{/home/luser/lisp/} by wherever you want to install your source code. You don't actually need to specify anything if you use the default @file{~/common-lisp/} as above and your implementation provides ASDF 3.1.2 or later. If your implementation provides an earlier variant of ASDF 3, you might want to specify @kbd{(:tree (:home "common-lisp/"))} for bootstrap purposes, then install a recent source tree of ASDF under @file{~/common-lisp/asdf/}. If you prefer to use a ``link farm'', which is faster to use but costlier to manage than a recursive traversal, say at @file{/home/luser/.asd-link-farm/}, then you may instead (or additionally) create a file @file{42-asd-link-farm.conf}, containing the line: @kbd{(:directory "/home/luser/.asd-link-farm/")} ASDF will automatically read your configuration the first time you try to find a system. If necessary, you can reset the source-registry configuration with: @lisp (asdf:clear-source-registry) @end lisp @item In earlier versions of ASDF, the system source registry was configured using a global variable, @code{asdf:*central-registry*}. For more details about this, see the following section, @ref{Configuring ASDF to find your systems --- old style}. Unless you need to understand this, skip directly to @ref{Configuring where ASDF stores object files}. @end itemize Note that your Operating System distribution or your system administrator may already have configured system-managed libraries for you. @node Configuring ASDF to find your systems --- old style, Configuring where ASDF stores object files, Configuring ASDF to find your systems, Configuring ASDF @section Configuring ASDF to find your systems --- old style @c FIXME: this section should be moved elsewhere. The novice user @c should not be burdened with it. [2014/02/27:rpg] Novices may skip this section. Please @emph{do not} use the central-registry if you are a novice, and @emph{do not} instruct novices to use the central-registry. @c ``Experts may read it then proceed to ...'' @c some better section explaining @c *central-registry* vs source-registry vs *system-definition-search-functions*, @c and .../asdf/tools/cl-source-registry-cache.lisp The old way to configure ASDF to find your systems is by @code{push}ing directory pathnames onto the variable @code{asdf:*central-registry*}. You @emph{must} configure this variable @emph{after} you load ASDF 3 or later, yet @emph{before} the first time you try to use it. This loading and configuring of ASDF must happen as part of some initialization script: typically, either a script you maintain that builds your project, or your implementation's initialization script (e.g. @file{~/.sbclrc} for SBCL). Also, if you are using an ancient ASDF 2 or earlier to load ASDF 3 or later, then after it loads the ancient ASDF, your script @emph{must} configure the central-registry a first time to tell ASDF 1 or 2 where to find ASDF 3, then load ASDF 3 with e.g. @code{(asdf:operate 'asdf:load-op "asdf")}, then configure the central-registry again, because ASDF 3 will not preserve the central-registry from ASDF 2 when upgrading. You should probably be using the source-registry instead, which will be preserved (unless you manually called @code{asdf:initialize-source-registry} with an argument, in which case you will have to do it again indeed). However, if you are using an ancient ASDF 2 or earlier, we @emph{strongly} recommend that you should instead upgrade your implementation, or overwrite the ancient ASDF installation with a more recent one: @xref{Replacing your implementation's ASDF}. The @code{asdf:*central-registry*} is empty by default in ASDF 2 or ASDF 3, but is still supported for compatibility with ASDF 1. When used, it takes precedence over the above source-registry.@footnote{ It is possible to further customize the system definition file search. That's considered advanced use, and covered later: search forward for @code{*system-definition-search-functions*}. @xref{Defining systems with defsystem}.} For example, let's say you want ASDF to find the @file{.asd} file @file{/home/me/src/foo/foo.asd}. In your Lisp initialization file, you could have the following: @lisp (require "asdf") (push "/home/me/src/foo/" asdf:*central-registry*) @end lisp Note the trailing slash: when searching for a system, ASDF will evaluate each entry of the central registry and coerce the result to a pathname.@footnote{ ASDF will indeed call @code{eval} on each entry. It will skip entries that evaluate to @code{nil}. Strings and pathname objects are self-evaluating, in which case the @code{eval} step does nothing; but you may push arbitrary s-expressions onto the central registry. These s-expressions may be evaluated to compute context-dependent entries, e.g. things that depend on the value of shell variables or the identity of the user. The variable @code{asdf:*central-registry*} is thus a list of ``system directory designators''. A @dfn{system directory designator} is a form which will be evaluated whenever a system is to be found, and must evaluate to a directory to look in (or @code{nil}). By ``directory'', we mean ``designator for a pathname with a non-empty DIRECTORY component''. } The trailing directory name separator is necessary to tell Lisp that you're discussing a directory rather than a file. If you leave it out, ASDF is likely to look in @code{/home/me/src/} instead of @code{/home/me/src/foo/} as you intended, and fail to find your system definition. Modern versions of ASDF will issue an error and offer you to remove such entries from the central-registry. Typically there are a lot of @file{.asd} files, and a common idiom was to put @emph{symbolic links} to all of one's @file{.asd} files in a common directory and push @emph{that} directory (the ``link farm'') onto @code{asdf:*central-registry*}, instead of pushing each individual system directory. ASDF knows to follow @emph{symlinks} to the actual location of the systems.@footnote{ On Windows, you can use Windows shortcuts instead of POSIX symlinks. if you try aliases under MacOS, we are curious to hear about your experience. } For example, if @code{#p"/home/me/cl/systems/"} is an element of @code{*central-registry*}, you could set up the system @var{foo} as follows: @example $ cd /home/me/cl/systems/ $ ln -s ~/src/foo/foo.asd . @end example This old style for configuring ASDF is not recommended for new users, but it is supported for old users, and for users who want a simple way to programmatically control what directories are added to the ASDF search path. @node Configuring where ASDF stores object files, Resetting the ASDF configuration, Configuring ASDF to find your systems --- old style, Configuring ASDF @section Configuring where ASDF stores object files @findex clear-output-translations ASDF lets you configure where object files will be stored. Sensible defaults are provided and you shouldn't normally have to worry about it. This allows the same source code repository to be shared between several versions of several Common Lisp implementations, between several users using different compilation options, with users who lack write privileges on shared source directories, etc. This also keeps source directories from being cluttered with object/fasl files. Starting with ASDF 2, the @code{asdf-output-translations} facility was added to ASDF itself. This facility controls where object files will be stored. This facility is fully described in a chapter of this manual, @ref{Controlling where ASDF saves compiled files}. @c FIXME: possibly this should be moved elsewhere. It's redundant here, @c and makes this section of the manual too long and daunting for the @c new user. [2014/02/27:rpg] @c The simplest way to add a translation to your search path, @c say from @file{/foo/bar/baz/quux/} @c to @file{/where/i/want/my/fasls/} @c is to create the directory @c @file{~/.config/common-lisp/asdf-output-translations.conf.d/} @c and there create a file with any name of your choice and the type @file{conf}, @c for instance @file{42-bazquux.conf} @c containing the line: @c @kbd{("/foo/bar/baz/quux/" "/where/i/want/my/fasls/")} @c To disable output translations for source under a given directory, @c say @file{/toto/tata/} @c you can create a file @file{40-disable-toto.conf} @c with the line: @c @kbd{("/toto/tata/")} @c To wholly disable output translations for all directories, @c you can create a file @file{00-disable.conf} @c with the line: @c @kbd{(t t)} @c Note that your Operating System distribution or your system administrator @c may already have configured translations for you. @c In absence of any configuration, the default is to redirect everything @c under an implementation-dependent subdirectory of @file{~/.cache/common-lisp/}. @c @xref{Controlling where ASDF searches for systems}, for full details. @c The required @file{.conf} extension allows you to have disabled files @c or editor backups (ending in @file{~}), and works portably @c (for instance, it is a pain to allow both empty and non-empty extension on CLISP). @c Excluded are files the name of which start with a @file{.} character. @c It is customary to start the filename with two digits @c that specify the order in which the directories will be scanned. @c ASDF will automatically read your configuration @c the first time you try to find a system. @c You can reset the source-registry configuration with: @c @lisp @c (asdf:clear-output-translations) @c @end lisp @c And you probably should do so before you dump your Lisp image, @c if the configuration may change @c between the machine where you save it at the time you save it @c and the machine you resume it at the time you resume it. @c (Once again, you should use @code{(asdf:clear-configuration)} @c before you dump your Lisp image, which includes the above.) Note that before ASDF 2, other ASDF add-ons offered the same functionality, each in subtly different and incompatible ways: ASDF-Binary-Locations, cl-launch, common-lisp-controller. ASDF-Binary-Locations is now not needed anymore and should not be used. cl-launch 3.000 and common-lisp-controller 7.2 have been updated to delegate object file placement to ASDF. @node Resetting the ASDF configuration, , Configuring where ASDF stores object files, Configuring ASDF @section Resetting the ASDF configuration @c FIXME: this should probably be moved out of the "quickstart" part of @c the manual. [2014/02/27:rpg] When you dump and restore an image, or when you tweak your configuration, you may want to reset the ASDF configuration. For that you may use the following function: @defun clear-configuration Undoes any ASDF configuration regarding source-registry or output-translations. @end defun @vindex *image-dump-hook* This function is pushed onto the @code{uiop:*image-dump-hook*} by default, which means that if you save an image using @code{uiop:dump-image}, or via @code{asdf:image-op} and @code{asdf:program-op}, it will be automatically called to clear your configuration. If for some reason you prefer to call your implementation's underlying functionality, be sure to call @code{clear-configuration} manually, or push it into your implementation's equivalent of @code{uiop:*image-dump-hook*}, e.g. @code{sb-ext:*save-hooks*} on SBCL, or @code{ext:*before-save-initializations*} on CMUCL and SCL, etc. @node Using ASDF, Defining systems with defsystem, Configuring ASDF, Top @chapter Using ASDF @menu * Loading a system:: * Convenience Functions:: * Moving on:: @end menu @node Loading a system, Convenience Functions, Using ASDF, Using ASDF @section Loading a system The system @var{foo} is loaded (and compiled, if necessary) by evaluating the following Lisp form: @example (asdf:load-system :@var{foo}) @end example On some implementations (@pxref{Convenience Functions}), ASDF hooks into the @code{cl:require} facility and you can just use: @example (require :@var{foo}) @end example Note that the canonical name of a system is a string, in @emph{lowercase}. System names can also be specified as symbols (including keyword symbols). If a symbol is given as argument, its package is ignored, its @code{symbol-name} is taken, and converted to lowercase. The name must be a suitable value for the @code{:name} initarg to @code{make-pathname} in whatever filesystem the system is to be found. Using lowercase as canonical is unconventional, but was selected after some consideration. The type of file systems we support either have lowercase as customary case (Unix, Mac, Windows) or silently convert lowercase to uppercase (lpns). @c so this makes more sense than attempting to use @code{:case :common}, @c which is reported not to work on some implementations @node Convenience Functions, Moving on, Loading a system, Using ASDF @section Convenience Functions @c I believe thes are all unnecessary because of the function macros @c below [2016/01/30:rpg] @c @findex load-system @c @findex compile-system @c @findex test-system @c @findex require-system @c @findex make ASDF provides three commands for the most common system operations: @code{load-system}, @code{compile-system}, and @code{test-system}. ASDF also provides @code{require-system}, a variant of @code{load-system} that skips loading systems that are already loaded. This is sometimes useful, for example, in order to avoid re-loading libraries that come pre-loaded into your lisp implementation. ASDF also provides @code{make}, a way of allowing system developers to choose a default operation for their systems. For example, a developer who has created a system intended to format a specific document, might make document-formatting the default operation invoked by @code{make}, instead of loading. If the system developer doesn't specify in the system definition, the default operation will be loading. @c FIXME: We seem to export @findex bundle-system also, that some ECL users seem to rely on. @c But it's probably better that bundle operations have their own manual chapter at some point. @c FIXME: There should be a @defun for OPERATE, but there isn't. Not @c sure where it belongs... The discussion here is just confusing if @c the reader doesn't understand how ASDF works. [2016/01/30:rpg] @findex operate @findex oos Because ASDF is an extensible system for defining @emph{operations} on @emph{components}, it also provides a generic function @code{operate}, so you may arbitrarily operate on your systems beyond the default operations. (At the interactive REPL, users often use its shorter alias @code{oos}, which stands for operate-on-system, a name inherited from @code{mk-defsystem}.) You'll use @code{operate} whenever you want to do something beyond compiling, loading and testing. @c Reminder: before ASDF can operate on a system, however, @c it must be able to find and load that system's definition. @c @xref{Configuring ASDF to find your systems}. @c FIXME: the following is too complicated for here, especially since @c :force hasn't been defined yet. Move it. [2014/02/27:rpg] @defun load-system system @Arest{} keys @Akey{} force force-not verbose version @AallowOtherKeys{} Apply @code{operate} with the operation @code{load-op}, the @var{system}, and any provided keyword arguments. Calling @code{load-system} is the regular, recommended way to load a system into the current image. @end defun @defun compile-system system @Arest{} keys @Akey{} force force-not verbose version @AallowOtherKeys{} Apply @code{operate} with the operation @code{compile-op}, the @var{system}, and any provided keyword arguments. This will make sure all the files in the system are compiled, but not necessarily load any of them in the current image; on most systems, it will @emph{not} load all compiled files in the current image. This function exists for symmetry with @code{load-system} but is not recommended unless you are writing build scripts and know what you're doing. But then, you might be interested in @code{program-op} rather than @code{compile-op}. @end defun @defun test-system system @Arest{} keys @Akey{} force force-not verbose version @AallowOtherKeys{} Apply @code{operate} with the operation @code{test-op}, the @var{system}, and any provided keyword arguments. @xref{test-op}. @end defun @defun make system @Arest{} keys @Akey{} @AallowOtherKeys{} Do ``The Right Thing'' with your system. Starting with ASDF 3.1, this function @code{make} is also available. The default behaviour is to load the system as if by @code{load-system}; but system authors can override this default in their system definition they may specify an alternate operation as the intended use of their system, with a @code{:build-operation} option in the @code{defsystem} form (@pxref{Build-operation}), and an intended output pathname for that operation with @code{:build-pathname}. @c Document :build-operation in the defsystem section. @c Document in the extension section that for richer programmatic access, you may instead use an overriding @c @code{(defmethod component-depends-on ((o build-op) (s system)) @c ...)}. This function is experimental and largely untested. Use at your own risk. @end defun @cindex build-operation @defun require-system system @Arest{} keys @Akey{} @AallowOtherKeys{} @code{require-system} skips any update to systems that have already been loaded, in the spirit of @code{cl:require}. It does it by calling @code{load-system} with a keyword option excluding already loaded systems.@footnote{ For the curious, the option is @code{:force-not (already-loaded-systems)}. }. On actively maintained free software implementations (namely recent versions of ABCL, Clozure CL, CMUCL, ECL, GNU CLISP, MKCL and SBCL), once ASDF itself is loaded, @code{cl:require} too can load ASDF systems, by falling back on @code{require-system} for module names not recognized by the implementation. (Note however that @code{require-system} does @emph{not} fall back on @code{cl:require}; that would introduce an ``interesting'' potential infinite loop to break somehow.) @code{cl:require} and @code{require-system} are appropriate to load code that is not being modified during the current programming session. @code{cl:require} will notably load the implementation-provided extension modules; @code{require-system} won't, unless they are also defined as systems somehow, which SBCL and MKCL do. @code{require-system} may also be used to load any number of ASDF systems that the user isn't either developing or debugging, for which a previously installed version is deemed to be satisfactory; @code{cl:require} on the above-mentioned implementations will delegate to @code{require-system} and may load them as well. But for code that you are actively developing, debugging, or otherwise modifying, you should use @code{load-system}, so ASDF will pick on your modifications and transitively re-build the modified files and everything that depends on them (that the requested @var{system} itself depends on --- ASDF itself never builds anything unless it's an explicitly requested system or the dependencies thereof). @end defun @defun already-loaded-systems Returns a list of names of the systems that have been successfully loaded so far. @end defun @node Moving on, , Convenience Functions, Using ASDF @section Moving on That's all you need to know to use ASDF to load systems written by others. The rest of this manual deals with writing system definitions for Common Lisp software you write yourself, including how to extend ASDF to define new operation and component types. @node Defining systems with defsystem, The object model of ASDF, Using ASDF, Top @comment node-name, next, previous, up @chapter Defining systems with defsystem This chapter describes how to use ASDF to define systems and develop software. @menu * The defsystem form:: * A more involved example:: * The defsystem grammar:: * Other code in .asd files:: * The package-inferred-system extension:: @end menu @node The defsystem form, A more involved example, Defining systems with defsystem, Defining systems with defsystem @comment node-name, next, previous, up @section The defsystem form @findex defsystem @cindex asdf-user @findex load-asd This section begins with an example of a system definition, then gives the full grammar of @code{defsystem}. Let's look at a simple system. This is a complete file that should be saved as @file{hello-lisp.asd} (in order that ASDF can find it when ordered to operate on the system named @code{"hello-lisp"}). @lisp ;; Usual Lisp comments are allowed here (defsystem "hello-lisp" :description "hello-lisp: a sample Lisp system." :version "0.0.1" :author "Joe User " :licence "Public Domain" :depends-on ("optima.ppcre" "command-line-arguments") :components ((:file "packages") (:file "macros" :depends-on ("packages")) (:file "hello" :depends-on ("macros")))) @end lisp Some notes about this example: @itemize @item The @code{defsystem} form defines a system named @code{hello-lisp} that contains three source files: @file{packages.lisp}, @file{macros.lisp} and @file{hello.lisp}. @item The @file{.lisp} suffix is implicit for Lisp source files. The source files are located in the same directory as the @code{.asd} file with the system definition. @c FIXME: the following should live somewhere, but not in the quickstart @c page. [2014/05/03:rpg] @c ASDF resolves symbolic links (or Windows shortcuts) @c before loading the system definition file and @c stores its location in the resulting system@footnote{ @c It is possible, though almost never necessary, to override this behaviour.}. @c This is a good thing because the user can move the system sources @c without having to edit the system definition. @c FIXME: The first example system should probably use just :serial T. @item The file @file{macros} depends on @file{packages} (presumably because the package it's in is defined in @file{packages}), and the file @file{hello} depends on @file{macros} (and hence, transitively on @file{packages}). This means that ASDF will compile and load @file{packages} then @file{macros} before starting the compilation of file @file{hello}. @item This example system has external dependencies on two other systems, @code{optima.ppcre} (that provides a friendly interface to matching regular expressions), and @code{command-line-arguments} (that provides a way to parse arguments passed from the shell command line). To use this system, ASDF must be configured to find installed copies of these systems; it will load them before it tries to compile and load @code{hello-lisp}. @item This system also defines a bunch of metadata. While it is optional to define these fields (and other fields like @code{:bug-tracker}, @code{:mailto}, @code{:long-name}, @code{:long-description}, @code{:source-control}), it is strongly recommended to define the fields @code{:description}, @code{:version}, @code{:author}, and @code{:licence}, especially if you intend your software to be eventually included in Quicklisp. @c FIXME: Should have cross-reference to "Version specifiers" in the @c defsystem grammar, but the cross-referencing is so broken by @c insufficient node breakdown that I have not put one in. @c FIXME: this is way too detailed for the first example! @c move it! @item Make sure you know how the @code{:version} numbers will be parsed! Only period-separated non-negative integers are accepted at present. @xref{Version specifiers}. @item This file contains a single form, the @code{defsystem} declaration. No @code{in-package} form, no @code{asdf:} package prefix, no nothing. Just the one naked @code{defsystem} form. This is what we recommend. More complex system definition files are possible with arbitrary Lisp code, but we recommend that you keep it simple if you can. This will make your system definitions more robust and more future-proof. @cindex :version @end itemize This is all you need to know to define simple systems. The next example is much more involved, to give you a glimpse of how you can do more complex things. However, since it's ultimately arbitrary Lisp code, there is no bottom to the rabbit hole. @c FIXME: divide the next example into many examples, to introduce fewer concepts at once. @node A more involved example, The defsystem grammar, The defsystem form, Defining systems with defsystem @comment node-name, next, previous, up @section A more involved example @findex defsystem Let's illustrate some more involved uses of @code{defsystem} via a slightly convoluted example: @lisp (in-package :asdf-user) (defsystem "foo" :version (:read-file-form "variables" :at (3 2)) :components ((:file "package") (:file "variables" :depends-on ("package")) (:module "mod" :depends-on ("package") :serial t :components ((:file "utils") (:file "reader") (:file "cooker") (:static-file "data.raw")) :output-files (compile-op (o c) (list "data.cooked")) :perform (compile-op :after (o c) (cook-data :in (component-pathname (find-component c "data.raw")) :out (first (output-files o c))))) (:file "foo" :depends-on ("mod")))) (defmethod action-description ((o compile-op) (c (eql (find-component "foo" "mod")))) "cooking data") @end lisp Here are some notes about this example: @itemize @item The main thing this file does is define a system @code{foo}. It also contains other Lisp forms, which we'll examine below. @item Besides Lisp source files, this system contains a @code{:module} component named @code{"mod"}, which is a collection of three Lisp source files @file{utils.lisp}, @file{reader.lisp}, @file{cooker.lisp} and @file{data.raw} @item Note that the @code{:static-file} does not have an implicit file type, unlike the Lisp source files. @item This files will be located in a subdirectory of the main code directory named @file{mod/} (this location could have been overridden to be in the same directory, or in a different subdirectory; see the discussion of the @code{:pathname} option in @ref{The defsystem grammar}). @item The @code{:serial t} says that each sub-component of @code{mod} depends on the previous components, so that @file{cooker.lisp} depends-on @file{reader.lisp}, which depends-on @file{utils.lisp}. Also @file{data.raw} depends on all of them, but that doesn't matter since it's a static file; on the other hand, if it appeared first, then all the Lisp files would be recompiled when the data is modified, which is probably not what is desired in this case. @item The method-form tokens provide a shorthand for defining methods on particular components. This part @lisp :output-files (compile-op (o c) (list "data.cooked")) :perform (compile-op :after (o c) (cook-data :in (component-pathname (find-component c "data.raw")) :out (first (output-files o c)))) @end lisp has the effect of @lisp (defmethod output-files ((o compile-op) (c (eql ...))) (list "data.cooked")) (defmethod perform :after ((o compile-op) (c (eql ...))) (cook-data :in (component-pathname (find-component c "data.raw")) :out (first (output-files o c)))) @end lisp where @code{...} is the component in question. In this case @code{...} would expand to something like @lisp (find-component "foo" "mod") @end lisp For more details on the syntax of such forms, @pxref{The defsystem grammar}. For more details on what these methods do, @pxref{Operations} in @ref{The object model of ASDF}. @item There is an additional @code{defmethod} with a similar effect, because ASDF (as of ASDF 3.1.5) fails to accept inline-methods as above for @code{action-description}, instead only supporting the deprecated @code{explain} interface. @c FIXME: The following plunge into detail weeds is not appropriate in this @c location. [2010/10/03:rpg] @c note that although this also supports @code{:before} methods, @c they may not do what you want them to --- @c a @code{:before} method on perform @code{((op compile-op) (c (eql ...)))} @c will run after all the dependencies and sub-components have been processed, @c but before the component in question has been compiled. @item In this case, these methods describe how this module defines code that it then uses to cook some data. @item Importantly, ASDF is told about the input and output files used by the data cooker, and to make sure everyone agrees, the cooking function explicitly uses ASDF to access pathnames to the input and output data. @c FIXME: move most of this package discussion to its own section, @c and leave only a reference here. @item The file starts with a form @code{(in-package :asdf-user)}, but it is actually redundant, not necessary and not recommended. But yet more complex cases (also not recommended) may usefully use an @code{in-package} form. @item Indeed, ASDF does not load @file{.asd} files simply with @code{cl:load}, and neither should you. You should let ASDF find and load them when you operate on systems. If you somehow @emph{must} load a @file{.asd} file, use the same function @code{asdf:load-asd} that ASDF uses. Among other things, it already binds the @code{*package*} to @code{asdf-user}. Recent versions of SLIME (2013-02 and later) know to do that when you @kbd{C-c C-k} when you use the @code{slime-asdf} contrib. @item You shouldn't use an @code{in-package} form if you're keeping things simple. You should only use @code{in-package} (and before it, a @code{defpackage}) when you're going to define new classes, functions, variables, macros, etc., in the @code{.asd} file, and want to thereby avoid name clashes. Manuals for old versions of ASDF recommended use of such an idiom in @file{.asd} files, but as of ASDF 3, we recommend that you don't do that anymore, and instead define any ASDF extensions in their own system, on which you can then declare a dependency using @code{:defsystem-depends-on}. @xref{The defsystem grammar}. @item More generally, you can always rely on symbols from packages @code{asdf}, @code{common-lisp} and @code{uiop} being available in @code{.asd} files --- most importantly including @code{defsystem}. It is therefore redundant and in bad taste to use a package-prefixed @code{asdf:defsystem} symbol in a @file{.asd} file. Just use @code{(defsystem ...)}. Only package-prefix it when somehow dynamically generating system definitions from a package that doesn't already use the ASDF package. @item @code{asdf-user} is actually only available starting since ASDF 3, but then again, ASDF 1 and 2 did crazy things with packages that ASDF 3 has stopped doing@footnote{ ASDF 1 and 2 (up until 2.26) used to dynamically create and delete temporary packages @code{asdf@emph{N}}, one for each @file{.asd} file, in a misguided attempt to thereby reduce name clashes; but it failed at that goal and only made things more complex. ASDF 3 just uses a shared package @code{asdf-user} instead, and relies on the usual Common Lisp conventions to avoid clashes. As far as package oddities go, you may just notice that the @code{asdf-user} package also uses @code{uiop/common-lisp}, a variant of the @code{common-lisp} package that papers over deficiencies in more obscure Common Lisp implementations; but unless you care about Corman Lisp, GCL, Genera or MCL, you shouldn't be concerned. }, and since all implementations provide ASDF 3, you shouldn't care about compatibility with ASDF 2. We do not support ASDF 2 anymore, and we recommend that neither should you. @item Starting with ASDF 3.1, @code{asdf-user} uses @code{uiop}, whereas in earlier variants of ASDF 3 it only used @code{uiop/package}. We recommend you either prefix use of UIOP functions with the package prefix @code{uiop:}, or make sure your system @code{:depends-on ((:version "asdf" "3.1.2"))} or has a @code{#-asdf3.1 (error "MY-SYSTEM requires ASDF 3.1.2")}. @item Finally, we elided most metadata, but showed how you can have ASDF automatically extract the system's version from a source file. In this case, the 3rd subform of the 4th form (note that Lisp uses 0-based indexing, English uses 1-based indexing). Presumably, the 4th form looks like @code{(defparameter *foo-version* "5.6.7")}. @end itemize @node The defsystem grammar, Other code in .asd files, A more involved example, Defining systems with defsystem @comment node-name, next, previous, up @section The defsystem grammar @findex defsystem @cindex DEFSYSTEM grammar @macro defrule {NAME} @anchor{rule-\NAME\}\NAME\ := @end macro @ifhtml @macro refrule {NAME} @ref{rule-\NAME\,\NAME\} @end macro @end ifhtml @ifinfo @macro refrule {NAME} @ref{rule-\NAME\,\NAME\,\NAME\,\NAME\} @end macro @end ifinfo @ifnothtml @ifnotinfo @macro refrule {NAME} \NAME\ @end macro @end ifnotinfo @end ifnothtml @example @defrule{system-definition} ( defsystem @refrule{system-designator} @refrule{system-option}* ) @defrule{system-designator} @refrule{simple-component-name} | @refrule{complex-component-name} # NOTE: Underscores are not permitted. # @pxref{Simple component names,Simple component names,Simple component names} @defrule{simple-component-name} @var{lower-case string} | @var{symbol} # @pxref{Complex component names,Complex component names,Complex component names} @defrule{complex-component-name} @var{string} | @var{symbol} @defrule{system-option} :defsystem-depends-on @refrule{dependency-def} | :weakly-depends-on @refrule{system-list} | :class @var{class-name} # @pxref{System class names} | :build-pathname @refrule{pathname-specifier} | :build-operation @refrule{operation-name} | @refrule{system-option/asdf3} | @refrule{module-option} | @refrule{option} # These are only available since ASDF 3 (actually its alpha release # 2.27) @defrule{system-option/asdf3} :homepage @var{string} | :bug-tracker @var{string} | :mailto @var{string} | :long-name @var{string} | :source-control @refrule{source-control} | :version @refrule{version-specifier} | :entry-point @var{object} # @pxref{Entry point} @defrule{source-control} ( @var{keyword} @var{string} ) @defrule{module-option} :components @refrule{component-list} | :serial [ t | nil ] @defrule{option} :description @var{string} | :long-description @var{string} | :author @refrule{person-or-persons} | :maintainer @refrule{person-or-persons} | :pathname @refrule{pathname-specifier} | :default-component-class @var{class-name} | :perform @refrule{method-form} | :explain @refrule{method-form} | :output-files @refrule{method-form} | :operation-done-p @refrule{method-form} | :if-feature @refrule{feature-expression} | :depends-on ( @refrule{dependency-def}* ) | :in-order-to ( @refrule{dependency}+ ) @defrule{person-or-persons} @var{string} | ( @var{string}+ ) @defrule{system-list} ( @refrule{simple-component-name}* ) @defrule{component-list} ( @refrule{component-def}* ) @defrule{component-def} ( @refrule{component-type} @refrule{simple-component-name} @refrule{option}* ) @defrule{component-type} :module | :file | :static-file | @refrule{other-component-type} @defrule{other-component-type} symbol-by-name # @pxref{Component types} # This is used in :depends-on, as opposed to "dependency", which is used # in :in-order-to @defrule{dependency-def} @refrule{simple-component-name} | ( :feature @refrule{feature-expression} @refrule{dependency-def} ) # @pxref{Feature dependencies} | ( :version @refrule{simple-component-name} @refrule{version-specifier} ) | ( :require @var{module-name} ) # "dependency" is used in :in-order-to, as opposed to "dependency-def" @defrule{dependency} ( @refrule{dependent-op} @refrule{requirement}+ ) @defrule{requirement} ( @refrule{required-op} @var{required-component}+ ) @defrule{dependent-op} @refrule{operation-name} @defrule{required-op} @refrule{operation-name} # NOTE: pathnames should be all lower case, and have no underscores, # although hyphens are permitted. @defrule{pathname-specifier} @var{pathname} | @var{string} | @var{symbol} @defrule{version-specifier} @var{string} | ( :read-file-form @refrule{pathname-specifier} @refrule{form-specifier}? ) | ( :read-file-line @refrule{pathname-specifier} @refrule{line-specifier}? ) @defrule{line-specifier} :at @var{integer} # base zero @defrule{form-specifier} :at [ @var{integer} | ( @var{integer}+ ) ] @defrule{method-form} ( @refrule{operation-name} @refrule{qual} @var{lambda-list} @Arest{} @var{body} ) @defrule{qual} @refrule{method-qualifier}? @defrule{method-qualifier} :before | :after | :around @defrule{feature-expression} @var{keyword} | ( :and @refrule{feature-expression}* ) | ( :or @refrule{feature-expression}* ) | ( :not @refrule{feature-expression} ) @defrule{operation-name} @var{symbol} @end example @subsection System designators System designators are either simple component names, or complex (``slashy'') component names. @subsection Simple component names (@code{simple-component-name}) @anchor{Simple component names} Simple component names may be written as either strings or symbols. When using strings, use lower case exclusively. Symbols will be interpreted as convenient shorthand for the string that is their @code{symbol-name}, converted to lower case. Put differently, a symbol may be a simple component name @emph{designator}, but the simple component name itself is the string. @strong{Never} use underscores in component names, whether written as strings or symbols. @strong{Never} use slashes (``/'') in simple component names. A slash indicates a @emph{complex} component name; see below. Using a slash improperly will cause ASDF to issue a warning. Violating these constraints by mixing case, or including underscores in component names, may lead to systems or components being impossible to find, because component names are interpreted as file names. These problems will @emph{definitely} occur for users who have configured ASDF using logical pathnames. @subsection Complex component names @anchor{Complex component names} A complex component name is a master name followed by a slash, followed by a subsidiary name. This allows programmers to put multiple system definitions in a single @code{.asd} file, while still allowing ASDF to find these systems. The master name of a complex system @strong{must} be the same as the name of the @code{.asd} file. The file @code{foo.asd} will contain the definition of the system @code{"foo"}. However, it may @emph{also} contain definitions of subsidiary systems, such as @code{"foo/test"}, @code{"foo/docs"}, and so forth. ASDF will ``know'' that if you ask it to load system @code{"foo/test"} it should look for that system's definition in @code{foo.asd}. @subsection Component types @anchor{Component types} Component type names, even if expressed as keywords, will be looked up by name in the current package and in the asdf package, if not found in the current package. So a component type @code{my-component-type}, in the current package @code{my-system-asd} can be specified as @code{:my-component-type}, or @code{my-component-type}. @code{system} and its subclasses are @emph{not} allowed as component types for such children components. @subsection System class names @anchor{System class names} A system class name will be looked up in the same way as a Component type (see above), except that only @code{system} and its subclasses are allowed. Typically, one will not need to specify a system class name, unless using a non-standard system class defined in some ASDF extension, typically loaded through @code{DEFSYSTEM-DEPENDS-ON}, see below. For such class names in the ASDF package, we recommend that the @code{:class} option be specified using a keyword symbol, such as @example :class :MY-NEW-SYSTEM-SUBCLASS @end example This practice will ensure that package name conflicts are avoided. Otherwise, the symbol @code{MY-NEW-SYSTEM-SUBCLASS} will be read into the current package @emph{before} it has been exported from the ASDF extension loaded by @code{:defsystem-depends-on}, causing a name conflict in the current package. @subsection Defsystem depends on @cindex :defsystem-depends-on The @code{:defsystem-depends-on} option to @code{defsystem} allows the programmer to specify another ASDF-defined system or set of systems that must be loaded @emph{before} the system definition is processed. Typically this is used to load an ASDF extension that is used in the system definition. @subsection Build-operation @cindex :build-operation @anchor{Build-operation} The @code{:build-operation} option to @code{defsystem} allows the programmer to specify an operation that will be applied, in place of @code{load-op} when @code{make} (@pxref{Convenience Functions, make}) is run on the system. The option value should be the name of an operation. E.g., @code{:build-operation doc-op} This feature is experimental and largely untested. Use at your own risk. @subsection Weakly depends on @cindex :weakly-depends-on We do @emph{NOT} recommend you use this feature. If you are tempted to write a system @var{foo} that weakly-depends-on a system @var{bar}, we recommend that you should instead write system @var{foo} in a parametric way, and offer some special variable and/or some hook to specialize its behaviour; then you should write a system @var{foo+bar} that does the hooking of things together. The (deprecated) @code{:weakly-depends-on} option to @code{defsystem} allows the programmer to specify another ASDF-defined system or set of systems that ASDF should @emph{try} to load, but need not load in order to be successful. Typically this is used if there are a number of systems that, if present, could provide additional functionality, but which are not necessary for basic function. Currently, although it is specified to be an option only to @code{defsystem}, this option is accepted at any component, but it probably only makes sense at the @code{defsystem} level. Programmers are cautioned not to use this component option except at the @code{defsystem} level, as this anomalous behaviour may be removed without warning. @c Finally, you might look into the @code{asdf-system-connections} extension, @c that will let you define additional code to be loaded @c when two systems are simultaneously loaded. @c It may or may not be considered good style, but at least it can be used @c in a way that has deterministic behaviour independent of load order, @c unlike @code{weakly-depends-on}. @subsection Pathname specifiers @cindex pathname specifiers @anchor{Pathname specifiers} A pathname specifier (@code{pathname-specifier}) may be a pathname, a string or a symbol. When no pathname specifier is given for a component, which is the usual case, the component name itself is used. If a string is given, which is the usual case, the string will be interpreted as a Unix-style pathname where @code{/} characters will be interpreted as directory separators. Usually, Unix-style relative pathnames are used (i.e. not starting with @code{/}, as opposed to absolute pathnames); they are relative to the path of the parent component. Finally, depending on the @code{component-type}, the pathname may be interpreted as either a file or a directory, and if it's a file, a file type may be added corresponding to the @code{component-type}, or else it will be extracted from the string itself (if applicable). For instance, the @code{component-type} @code{:module} wants a directory pathname, and so a string @code{"foo/bar"} will be interpreted as the pathname @file{#p"foo/bar/"}. On the other hand, the @code{component-type} @code{:file} wants a file of type @code{lisp}, and so a string @code{"foo/bar"} will be interpreted as the pathname @file{#p"foo/bar.lisp"}, and a string @code{"foo/bar.quux"} will be interpreted as the pathname @file{#p"foo/bar.quux.lisp"}. Finally, the @code{component-type} @code{:static-file} wants a file without specifying a type, and so a string @code{"foo/bar"} will be interpreted as the pathname @file{#p"foo/bar"}, and a string @code{"foo/bar.quux"} will be interpreted as the pathname @file{#p"foo/bar.quux"}. ASDF interprets the string @code{".."} as the pathname directory component word @code{:back}, which when merged, goes back one level in the directory hierarchy. If a symbol is given, it will be translated into a string, and downcased in the process. The downcasing of symbols is unconventional, but was selected after some consideration. The file systems we support either have lowercase as customary case (Unix, Mac, Windows) or silently convert lowercase to uppercase (lpns), so this makes more sense than attempting to use @code{:case :common} as argument to @code{make-pathname}, which is reported not to work on some implementations. Please avoid using underscores in system names, or component (module or file) names, since underscores are not compatible with logical pathnames (@pxref{Using logical pathnames}). Pathname objects may be given to override the path for a component. Such objects are typically specified using reader macros such as @code{#p} or @code{#.(make-pathname ...)}. Note however, that @code{#p...} is a shorthand for @code{#.(parse-namestring ...)} and that the behaviour of @code{parse-namestring} is completely non-portable, unless you are using Common Lisp @code{logical-pathname}s, which themselves involve other non-portable behaviour (@pxref{Using logical pathnames}). Pathnames made with @code{#.(make-pathname ...)} can usually be done more easily with the string syntax above. The only case that you really need a pathname object is to override the component-type default file type for a given component. Therefore, pathname objects should only rarely be used. Unhappily, ASDF 1 used not to properly support parsing component names as strings specifying paths with directories, and the cumbersome @code{#.(make-pathname ...)} syntax had to be used. An alternative to @code{#.} read-time evaluation is to use @code{(eval `(defsystem ... ,pathname ...))}. Note that when specifying pathname objects, ASDF does not do any special interpretation of the pathname influenced by the component type, unlike the procedure for pathname-specifying strings. On the one hand, you have to be careful to provide a pathname that correctly fulfills whatever constraints are required from that component type (e.g. naming a directory or a file with appropriate type); on the other hand, you can circumvent the file type that would otherwise be forced upon you if you were specifying a string. @subsection Version specifiers @cindex version specifiers @cindex :version @anchor{Version specifiers} Version specifiers are strings to be parsed as period-separated lists of integers. I.e., in the example, @code{"0.2.1"} is to be interpreted, roughly speaking, as @code{(0 2 1)}. In particular, version @code{"0.2.1"} is interpreted the same as @code{"0.0002.1"}, though the latter is not canonical and may lead to a warning being issued. Also, @code{"1.3"} and @code{"1.4"} are both strictly @code{uiop:version<} to @code{"1.30"}, quite unlike what would have happened had the version strings been interpreted as decimal fractions. Instead of a string representing the version, the @code{:version} argument can be an expression that is resolved to such a string using the following trivial domain-specific language: in addition to being a literal string, it can be an expression of the form @code{(:read-file-form [:at ])}, or @code{(:read-file-line [:at ])}. As the name suggests, the former will be resolved by reading a form in the specified pathname (read as a subpathname of the current system if relative or a unix-namestring), and the latter by reading a line. You may use a @code{uiop:access-at} specifier with the @code{:at} keyword, by default the specifier is @code{0}, meaning the first form/line is returned. For @code{:read-file-form}, subforms can also be specified, with e.g. @code{(1 2 2)} specifying ``the third subform (index 2) of the third subform (index 2) of the second form (index 1)'' in the file (mind the off-by-one error in the English language). System definers are encouraged to use version identifiers of the form @var{x}.@var{y}.@var{z} for major version, minor version and patch level, where significant API incompatibilities are signaled by an increased major number. @xref{Common attributes of components}. @subsection Require @cindex :require dependencies Use the implementation's own @code{require} to load the @var{module-name}. It is good taste to use @code{(:feature @emph{:implementation-name} (:require @var{module-name}))} rather than @code{#+@emph{implementation-name} (:require @var{module-name})} to only depend on the specified module on the specific implementation that provides it. @xref{Feature dependencies}. @subsection Feature dependencies @cindex :feature dependencies @anchor{Feature dependencies} A feature dependency is of the form @code{(:feature @var{feature-expression} @var{dependency})} If the @var{feature-expression} is satisfied by the running lisp at the time the system definition is parsed, then the @var{dependency} will be added to the system's dependencies. If the @var{feature-expression} is @emph{not} satisfied, then the feature dependency form is ignored. Note that this means that @code{:feature} @strong{cannot} be used to enforce a feature dependency for the system in question. I.e., it cannot be used to require that a feature hold in order for the system definition to be loaded. E.g., one cannot use @code{(:feature :sbcl)} to require that a system only be used on SBCL. Feature dependencies are not to be confused with the obsolete feature requirement (@pxref{feature requirement}), or with @code{if-feature}. @subsection Using logical pathnames @cindex logical pathnames @anchor{Using logical pathnames} We do not generally recommend the use of logical pathnames, especially not so to newcomers to Common Lisp. However, we do support the use of logical pathnames by old timers, when such is their preference. To use logical pathnames, you will have to provide a pathname object as a @code{:pathname} specifier to components that use it, using such syntax as @code{#p"LOGICAL-HOST:absolute;path;to;component.lisp"}. You only have to specify such logical pathname for your system or some top-level component. Sub-components' relative pathnames, specified using the string syntax for names, will be properly merged with the pathnames of their parents. The specification of a logical pathname host however is @emph{not} otherwise directly supported in the ASDF syntax for pathname specifiers as strings. The @code{asdf-output-translation} layer will avoid trying to resolve and translate logical pathnames. The advantage of this is that you can define yourself what translations you want to use with the logical pathname facility. The disadvantage is that if you do not define such translations, any system that uses logical pathnames will behave differently under asdf-output-translations than other systems you use. If you wish to use logical pathnames you will have to configure the translations yourself before they may be used. ASDF currently provides no specific support for defining logical pathname translations. Note that the reasons we do not recommend logical pathnames are that (1) there is no portable way to set up logical pathnames @emph{before} they are used, (2) logical pathnames are limited to only portably use a single character case, digits and hyphens. While you can solve the first issue on your own, describing how to do it on each of fifteen implementations supported by ASDF is more than we can document. As for the second issue, mind that the limitation is notably enforced on SBCL, and that you therefore can't portably violate the limitations but must instead define some encoding of your own and add individual mappings to name physical pathnames that do not fit the restrictions. This can notably be a problem when your Lisp files are part of a larger project in which it is common to name files or directories in a way that includes the version numbers of supported protocols, or in which files are shared with software written in different programming languages where conventions include the use of underscores, dots or CamelCase in pathnames. @subsection Serial dependencies @cindex serial dependencies If the @code{:serial t} option is specified for a module, ASDF will add dependencies for each child component, on all the children textually preceding it. This is done as if by @code{:depends-on}. @lisp :serial t :components ((:file "a") (:file "b") (:file "c")) @end lisp is equivalent to @lisp :components ((:file "a") (:file "b" :depends-on ("a")) (:file "c" :depends-on ("a" "b"))) @end lisp @subsection Source location (@code{:pathname}) The @code{:pathname} option is optional in all cases for systems defined via @code{defsystem}, and generally is unnecessary. In the simple case, source files will be found in the same directory as the system or, in the case of modules, in a subdirectory with the same name as the module. @c FIXME: This should be moved elsewhere -- it's too much detail for the @c grammar section. More specifically, ASDF follows a hairy set of rules that are designed so that @enumerate @item @code{find-system} will load a system from disk and have its pathname default to the right place. @item This pathname information will not be overwritten with @code{*default-pathname-defaults*} (which could be somewhere else altogether) if the user loads up the @file{.asd} file into his editor and interactively re-evaluates that form. @end enumerate If a system is being loaded for the first time, its top-level pathname will be set to: @itemize @item The host/device/directory parts of @code{*load-truename*}, if it is bound. @item @code{*default-pathname-defaults*}, otherwise. @end itemize If a system is being redefined, the top-level pathname will be @itemize @item changed, if explicitly supplied or obtained from @code{*load-truename*} (so that an updated source location is reflected in the system definition) @item changed if it had previously been set from @code{*default-pathname-defaults*} @item left as before, if it had previously been set from @code{*load-truename*} and @code{*load-truename*} is currently unbound (so that a developer can evaluate a @code{defsystem} form from within an editor without clobbering its source location) @end itemize @subsection if-feature option @cindex :if-feature component option @anchor{if-feature option} @c redo if this ever becomes a node in @c its own right... This option allows you to specify a feature expression to be evaluated as if by @code{#+} to conditionally include a component in your build. If the expression is false, the component is dropped as well as any dependency pointing to it. As compared to using @code{#+} which is expanded at read-time, this allows you to have an object in your component hierarchy that can be used for manipulations beside building your project, and that is accessible to outside code that wishes to reason about system structure. Programmers should be careful to consider @strong{when} the @code{:if-feature} is evaluated. Recall that ASDF first computes a build plan, and then executes that plan. ASDF will check to see whether or not a feature is present @strong{at planning time}, not during the build. It follows that one cannot use @code{:if-feature} to check features that are set during the course of the build. It can only be used to check the state of features before any build operations have been performed. This option was added in ASDF 3. For more information, @xref{required-features, Required features}. @subsection Entry point @cindex :entry-point @anchor{Entry point} The @code{:entry-point} option allows a developer to specify the entry point of an executable program created by @code{program-op}. When @code{program-op} is invoked, the form passed to this option is converted to a function by @code{uiop:ensure-function} and bound to @code{uiop:*image-entry-point*}. Typically one will specify a string, e.g. @code{"foo:main"}, so that the executable starts with the @code{foo:main} function. Note that using the symbol @code{foo:main} instead might not work because the @code{foo} package doesn't necessarily exist when ASDF reads the @code{defsystem} form. For more information on @code{program-op}, @pxref{Predefined operations of ASDF}. @subsection feature requirement @anchor{feature requirement} This requirement was removed in ASDF 3.1. Please do not use it. In most cases, @code{:if-feature} (@pxref{if-feature option}) will provide an adequate substitute. The @code{feature} requirement used to ensure that a chain of component dependencies would fail when a key feature was absent. Used in conjunction with @code{:if-component-dep-fails} this provided a roundabout way to express conditional compilation. @node Other code in .asd files, The package-inferred-system extension, The defsystem grammar, Defining systems with defsystem @section Other code in .asd files Files containing @code{defsystem} forms are regular Lisp files that are executed by @code{load}. Consequently, you can put whatever Lisp code you like into these files. However, it is recommended to keep such forms to a minimal, and to instead define @code{defsystem} extensions that you use with @code{:defsystem-depends-on}. If however, you might insist on including code in the @file{.asd} file itself, e.g., to examine and adjust the compile-time environment, possibly adding appropriate features to @code{*features*}. If so, here are some conventions we recommend you follow, so that users can control certain details of execution of the Lisp in @file{.asd} files: @itemize @item Any informative output (other than warnings and errors, which are the condition system's to dispose of) should be sent to the standard CL stream @code{*standard-output*}, so that users can easily control the disposition of output from ASDF operations. @end itemize @node The package-inferred-system extension, , Other code in .asd files, Defining systems with defsystem @section The package-inferred-system extension @codequoteundirected on @cindex Package inferred systems @cindex Packages, inferring dependencies from @findex package-inferred-system @cindex One package per file systems Starting with release 3.1.2, ASDF supports a one-package-per-file style of programming, in which each file is its own system, and dependencies are deduced from the @code{defpackage} form or its variant, @code{uiop:define-package}. In this style of system definition, package names map to systems with the same name (in lower case letters), and if a system is defined with @code{:class package-inferred-system}, then system names that start with that name (using the slash @code{/} separator) refer to files under the filesystem hierarchy where the system is defined. For instance, if system @code{my-lib} is defined in @file{/foo/bar/my-lib/my-lib.asd}, then system @code{my-lib/src/utility} will be found in file @file{/foo/bar/my-lib/src/utility.lisp}. One package per file style was made popular by @code{faslpath} and @code{quick-build}, and at the cost of stricter package discipline, may yield more maintainable code. This style is used in ASDF itself (starting with ASDF 3), by @code{lisp-interface-library}, and a few other libraries. To use this style, choose a toplevel system name, e.g. @code{my-lib}, and create a file @file{my-lib.asd}. Define @code{my-lib} using the @code{:class :package-inferred-system} option in its @code{defsystem}. For instance: @example ;; This example is based on lil.asd of LISP-INTERFACE-LIBRARY. #-asdf3.1 (error "MY-LIB requires ASDF 3.1 or later.") (defsystem "my-lib" :class :package-inferred-system :depends-on ("my-lib/interface/all" "my-lib/src/all" "my-lib/extras/all") :in-order-to ((test-op (load-op "my-lib/test/all"))) :perform (test-op (o c) (symbol-call :my-lib/test/all :test-suite))) (defsystem "my-lib/test" :depends-on ("my-lib/test/all")) (register-system-packages "my-lib/interface/all" '(:my-lib-interface)) (register-system-packages "my-lib/src/all" '(:my-lib-implementation)) (register-system-packages "my-lib/test/all" '(:my-lib-test)) (register-system-packages "closer-mop" '(:c2mop :closer-common-lisp :c2cl :closer-common-lisp-user :c2cl-user)) @end example @noindent In the code above, the first form checks that we are using ASDF 3.1 or later, which provides @code{package-inferred-system}. This is probably no longer necessary, since none of the major lisp implementations provides an older version of ASDF. @findex register-system-packages The function @code{register-system-packages} must be called to register packages used or provided by your system when the name of the system/file that provides the package is not the same as the package name (converted to lower case). Each file under the @code{my-lib} hierarchy will start with a package definition. @findex define-package @findex uiop:define-package The form @code{uiop:define-package} is supported as well as @code{defpackage}. ASDF will compute dependencies from the @code{:use}, @code{:mix}, and other importation clauses of this package definition. Take the file @file{interface/order.lisp} as an example: @example (uiop:define-package :my-lib/interface/order (:use :closer-common-lisp :my-lib/interface/definition :my-lib/interface/base) (:mix :fare-utils :uiop :alexandria) (:export ...)) @end example ASDF can tell that this file/system depends on system @code{closer-mop} (registered above), @code{my-lib/interface/definition}, and @code{my-lib/interface/base}. How can ASDF find the file @file{interface/order.lisp} from the toplevel system @code{my-lib}, however? In the example above, @file{interface/all.lisp} (and other @file{all.lisp}) reexport all the symbols exported from the packages at the same or lower levels of the hierarchy. This can be easily done with @code{uiop:define-package}, which has many options that prove useful in this context. For example: @example (uiop:define-package :my-lib/interface/all (:nicknames :my-lib-interface) (:use :closer-common-lisp) (:mix :fare-utils :uiop :alexandria) (:use-reexport :my-lib/interface/definition :my-lib/interface/base :my-lib/interface/order :my-lib/interface/monad/continuation)) @end example Thus the top level system need only depend on the @code{my-lib/.../all} systems because ASDF detects @file{interface/order.lisp} and all other dependencies from @code{all} systems' @code{:use-reexport} clauses, which effectively allow for ``inheritance'' of symbols being exported. ASDF also detects dependencies from @code{:import-from} clauses. You may thus import a well-defined set of symbols from an existing package, and ASDF will know to load the system that provides that package. In the following example, ASDF will infer that the current system depends on @code{foo/baz} from the first @code{:import-from}. If you prefer to use any such symbol fully qualified by a package prefix, you may declare a dependency on such a package and its corresponding system via an @code{:import-from} clause with an empty list of symbols. For example, if we preferred to use the name `foo/quux:bletch`, the second, empty, @code{:import-from} form would cause ASDF to load @code{foo/quux}. @example (defpackage :foo/bar (:use :cl) (:import-from :foo/baz #:sym1 #:sym2) (:import-from :foo/quux) (:export ...)) @end example Note that starting with ASDF 3.1.5.6 only, ASDF will look for source files under the @code{component-pathname} (specified via the @code{:pathname} option), whereas earlier versions ignore this option and use the @code{system-source-directory} where the @file{.asd} file resides. @c See this blog post about it: @c @url{http://davazp.net/2014/11/26/modern-library-with-asdf-and-package-inferred-system.html} @codequoteundirected off @node The object model of ASDF, Controlling where ASDF searches for systems, Defining systems with defsystem, Top @comment node-name, next, previous, up @chapter The Object model of ASDF @tindex component @tindex operation ASDF is designed in an object-oriented way from the ground up. Both a system's structure and the operations that can be performed on systems follow an extensible protocol, allowing programmers to add new behaviours to ASDF. For example, @code{cffi} adds support for special FFI description files that interface with C libraries and for wrapper files that embed C code in Lisp. @code{asdf-jar} supports creating Java JAR archives in ABCL. @code{poiu} supports compiling code in parallel using background processes. The key classes in ASDF are @code{component} and @code{operation}. A @code{component} represents an individual source file or a group of source files, and the products (e.g., fasl files) produced from it. An @code{operation} represents a transformation that can be performed on a component, turning them from source files to intermediate results to final outputs. Components are related by @emph{dependencies}, specified in system definitions. When ordered to @code{operate} with some operation on a component (usually a system), ASDF will first compute a @emph{plan} by traversing the dependency graph using function @code{make-plan}.@footnote{ Historically, the function that built a plan was called @code{traverse}, and returned a list of actions; it was deprecated in favor of @code{make-plan} (that returns a plan object) when the @code{plan} objects were introduced with ASDF 3; the old function is kept for backward compatibility and debugging purposes only, and may be removed in the near future. } The resulting plan object contains an ordered list of @emph{actions}. An action is a pair of an @code{operation} and a @code{component}, representing a particular build step to be @code{perform}ed. The ordering of the plan ensures that no action is performed before all its dependencies have been fulfilled.@footnote{ The term @emph{action} was used by Kent Pitman in his article, ``The Description of Large Systems,'' (@pxref{Bibliography}), and we suspect might be traced to @code{make}. Although the term was only used by ASDF hackers starting with ASDF 2, the concept was there since the very beginning of ASDF 1, just not clearly articulated. } In this chapter, we describe ASDF's object-oriented protocol, the classes that make it up, and the generic functions on those classes. These generic functions often take both an operation and a component as arguments: much of the power and configurability of ASDF is provided by this use of CLOS's multiple dispatch. We will describe the built-in component and operation classes, and explain how to extend the ASDF protocol by defining new classes and methods for ASDF's generic functions. We will also describe the many @emph{hooks} that can be configured to customize the behaviour of existing @emph{functions}. @c FIXME: Swap operations and components. @c FIXME: Possibly add a description of the PLAN object. @c Not critical, since the user isn't expected to interact with it. @menu * Operations:: * Components:: * Dependencies:: * Functions:: * Parsing system definitions:: @end menu @node Operations, Components, The object model of ASDF, The object model of ASDF @comment node-name, next, previous, up @section Operations @cindex operation An @dfn{operation} object of the appropriate type is instantiated whenever the user wants to do something with a system like @itemize @item compile all its files @item load the files into a running lisp environment @item copy its source files somewhere else @end itemize Operations can be invoked directly, or examined to see what their effects would be without performing them. There are a bunch of methods specialised on operation and component type that actually do the grunt work. Operations are invoked on systems via @code{operate} (@pxref{operate}). ASDF contains a number of pre-defined @t{operation} classes for common, and even fairly uncommon tasks that you might want to do with it. In addition, ASDF contains ``abstract'' @t{operation} classes that programmers can use as building blocks to define ASDF extensions. We discuss these in turn below. @c The operation object contains whatever state is relevant for this purpose @c (perhaps a list of visited nodes, for example) @c but primarily is a nice thing to specialise operation methods on @c and easier than having them all be @code{EQL} methods. @menu * Predefined operations of ASDF:: * Creating new operations:: @end menu Operations are invoked on systems via @code{operate}. @anchor{operate} @deffn {Generic function} operate @var{operation} @var{component} @Arest{} @var{initargs} @Akey{} @code{force} @code{force-not} @code{verbose} @AallowOtherKeys @deffnx {Generic function} oos @var{operation} @var{component} @Arest{} @var{initargs} @Akey{} @AallowOtherKeys{} @code{operate} invokes @var{operation} on @var{system}. @code{oos} is a synonym for @code{operate} (it stands for operate-on-system). @var{operation} is an operation designator: it can be an operation object itself, or, typically, a symbol that is passed to @code{make-operation} (which will call @code{make-instance}), to create the operation object. @var{component} is a component designator: it can be a component object itself, or, typically, a string or symbol (to be @code{string-downcase}d) that names a system, more rarely a list of strings or symbols that designate a subcomponent of a system. The ability to pass @var{initargs} to @code{make-operation} is now deprecated, and will be removed. For more details, @pxref{make-operation}. Note that dependencies may cause the operation to invoke other operations on the system or its components: the new operations may or may not be created with the same @var{initargs} as the original one (for the moment). If @var{force} is @code{:all}, then all systems are forced to be recompiled even if not modified since last compilation. If @var{force} is @code{t}, then only the system being loaded is forced to be recompiled even if not modified since last compilation, but other systems are not affected. If @var{force} is a list, then it specifies a list of systems that are forced to be recompiled even if not modified since last compilation. If @var{force-not} is @code{:all}, then all systems are forced not to be recompiled even if modified since last compilation. If @var{force-not} is @code{t}, then all systems but the system being loaded are forced not to be recompiled even if modified since last compilation (note: this was changed in ASDF 3.1.2). If @var{force-not} is a list, then it specifies a list of systems that are forced not to be recompiled even if modified since last compilation. @findex register-immutable-system @cindex immutable systems Both @var{force} and @var{force-not} apply to systems that are dependencies and were already compiled. @var{force-not} takes precedences over @var{force}, as it should, really, but unhappily only since ASDF 3.1.2. Moreover, systems which have been registered as immutable by @code{register-immutable-system} (since ASDF 3.1.5) are always considered @var{forced-not}, and even their @file{.asd} are not refreshed from the filesystem. @xref{Miscellaneous Functions}. @findex traverse To see what @code{operate} would do, you can use: @example (asdf:traverse operation-class system-name) @end example @end deffn @defun make-operation @var{operation-class} @Arest{} @var{initargs} @anchor{make-operation} The @var{initargs} are passed to @code{make-instance} call when creating the operation object. @strong{Note:}@var{initargs} for @code{operation}s are now deprecated, and will be removed from ASDF in the near future. @strong{Note:} @code{operation} instances must @strong{never} be created using @code{make-instance} directly: only through @code{make-operation}. Attempts to directly make @code{operation} instances will cause a run-time error. @end defun @node Predefined operations of ASDF, Creating new operations, Operations, Operations @comment node-name, next, previous, up @subsection Predefined operations of ASDF All the operations described in this section are in the @code{asdf} package. They are invoked via the @code{operate} generic function. @lisp (asdf:operate 'asdf:@var{operation-name} :@var{system-name} @{@var{operation-options ...}@}) @end lisp @deftp Operation compile-op This operation compiles the specified component. A @code{cl-source-file} will be @code{compile-file}'d. All the children and dependencies of a system or module will be recursively compiled by @code{compile-op}. @code{compile-op} depends on @code{prepare-op} which itself depends on a @code{load-op} of all of a component's dependencies, as well as of its parent's dependencies. When @code{operate} is called on @code{compile-op}, all these dependencies will be loaded as well as compiled; yet, some parts of the system main remain unloaded, because nothing depends on them. Use @code{load-op} to load a system. @end deftp @deftp Operation load-op This operation loads the compiled code for a specified component. A @code{cl-source-file} will have its compiled fasl @code{load}ed, which fasl is the output of @code{compile-op} that @code{load-op} depends on. @code{load-op} will recursively load all the children of a system or module. @code{load-op} also depends on @code{prepare-op} which itself depends on a @code{load-op} of all of a component's dependencies, as well as of its parent's dependencies. @end deftp @deftp Operation prepare-op This operation ensures that the dependencies of a component and its recursive parents are loaded (as per @code{load-op}), as a prerequisite before @code{compile-op} and @code{load-op} operations may be performed on a given component. @end deftp @deftp Operation load-source-op @deftpx Operation prepare-source-op @code{load-source-op} will load the source for the files in a module rather than the compiled fasl output. It has a @code{prepare-source-op} analog to @code{prepare-op}, that ensures the dependencies are themselves loaded via @code{load-source-op}. @end deftp @anchor{test-op} @deftp Operation test-op This operation will perform some tests on the module. The default method will do nothing. The default dependency is to require @code{load-op} to be performed on the module first. Its default @code{operation-done-p} method returns @code{nil}, which means that the operation is @emph{never} done -- we assume that if you invoke the @code{test-op}, you want to test the system, even if you have already done so. The results of this operation are not defined by ASDF. It has proven difficult to define how the test operation should signal its results to the user in a way that is compatible with all of the various test libraries and test techniques in use in the community, and given the fact that ASDF operations do not return a value indicating success or failure. For those willing to go to the effort, we suggest defining conditions to signal when a @code{test-op} fails, and storing in those conditions information that describes which tests fail. People typically define a separate test @emph{system} to hold the tests. Doing this avoids unnecessarily adding a test framework as a dependency on a library. For example, one might have @lisp (defsystem "foo" :in-order-to ((test-op (test-op "foo/test"))) ...) (defsystem "foo/test" :depends-on ("foo" "fiveam") ; fiveam is a test framework library ...) @end lisp Then one defines @code{perform} methods on @code{test-op} such as the following: @lisp (defsystem "foo/test" :depends-on ("foo" "fiveam") ; fiveam is a test framework library :perform (test-op (o s) (uiop:symbol-call :fiveam '#:run! (uiop:find-symbol* '#:foo-test-suite :foo-tests))) ...) @end lisp @end deftp @deftp Operation compile-bundle-op @deftpx Operation monolithic-compile-bundle-op @deftpx Operation load-bundle-op @deftpx Operation monolithic-load-bundle-op @deftpx Operation deliver-asd-op @deftpx Operation monolithic-deliver-asd-op @deftpx Operation lib-op @deftpx Operation monolithic-lib-op @deftpx Operation dll-op @deftpx Operation monolithic-dll-op @deftpx Operation image-op @deftpx Operation program-op These are ``bundle'' operations, that can create a single-file ``bundle'' for all the contents of each system in an application, or for the entire application. @code{compile-bundle-op} will create a single fasl file for each of the systems needed, grouping all its many fasls in one, so you can deliver each system as a single fasl. @code{monolithic-compile-bundle-op} will create a single fasl file for the target system and all its dependencies, so you can deliver your entire application as a single fasl. @code{load-bundle-op} will load the output of @code{compile-bundle-op}. Note that if the output is not up-to-date, @code{compile-bundle-op} may load the intermediate fasls as a side-effect. Bundling fasls together matters a lot on ECL, where the dynamic linking involved in loading tens of individual fasls can be noticeably more expensive than loading a single one. NB: @code{compile-bundle-op}, @code{monolithic-compile-bundle-op}, @code{load-bundle-op}, @code{monolithic-load-bundle-op}, @code{deliver-asd-op}, @code{monolithic-deliver-asd-op} were respectively called @code{fasl-op}, @code{monolithic-fasl-op}, @code{load-fasl-op}, @code{monolithic-load-fasl-op}, @code{binary-op}, @code{monolithic-binary-op} before ASDF 3.1. The old names still exist for backward compatibility, though they poorly label what is going on. Once you have created a fasl with @code{compile-bundle-op}, you can use @code{precompiled-system} to deliver it in a way that is compatible with clients having dependencies on your system, whether it is distributed as source or as a single binary; the @file{.asd} file to be delivered with the fasl will look like this: @example (defsystem :mysystem :class :precompiled-system :fasl (some expression that will evaluate to a pathname)) @end example Or you can use @code{deliver-asd-op} to let ASDF create such a system for you as well as the @code{compile-bundle-op} output, or @code{monolithic-deliver-asd-op}. This allows you to deliver code for your systems or applications as a single file. Of course, if you want to test the result in the current image, @emph{before} you try to use any newly created @file{.asd} files, you should not forget to @code{(asdf:clear-configuration)} or at least @code{(asdf:clear-source-registry)}, so it re-populates the source-registry from the filesystem. The @code{program-op} operation will create an executable program from the specified system and its dependencies. You can use UIOP for its pre-image-dump hooks, its post-image-restore hooks, and its access to command-line arguments. And you can specify an entry point @code{my-app:main} by specifying in your @code{defsystem} the option @code{:entry-point "my-app:main"}. Depending on your implementation, running @code{(asdf:operate 'asdf:program-op :my-app)} may quit the current Lisp image upon completion. See the example in @file{test/hello-world-example.asd} and @file{test/hello.lisp}, as built and tested by @file{test/test-program.script} and @file{test/make-hello-world.lisp}. @code{image-op} will dump an image that may not be standalone and does not start its own function, but follows the usual execution convention of the underlying Lisp, just with more code pre-loaded, for use as an intermediate build result or with a wrapper invocation script. There is also @code{lib-op} for building a linkable @file{.a} file (Windows: @file{.lib}) from all linkable object dependencies (FFI files, and on ECL, Lisp files too), and its monolithic equivalent @code{monolithic-lib-op}. And there is also @code{dll-op} (respectively its monolithic equivalent @code{monolithic-dll-op}) for building a linkable @file{.so} file (Windows: @file{.dll}, MacOS X: @file{.dynlib}) to create a single dynamic library for all the extra FFI code to be linked into each of your systems (respectively your entire application). All these ``bundle'' operations are available since ASDF 3 on all actively supported Lisp implementations, but may be unavailable on unmaintained legacy implementations. This functionality was previously available for select implementations, as part of a separate system @code{asdf-bundle}, itself descended from the ECL-only @code{asdf-ecl}. The pathname of the output of bundle operations is subject to output-translation as usual, unless the operation is equal to the @code{:build-operation} argument to @code{defsystem}. This behaviour is not very satisfactory and may change in the future. Maybe you have suggestions on how to better configure it? @end deftp @deftp Operation concatenate-source-op @deftpx Operation monolithic-concatenate-source-op @deftpx Operation load-concatenated-source-op @deftpx Operation compile-concatenated-source-op @deftpx Operation load-compiled-concatenated-source-op @deftpx Operation monolithic-load-concatenated-source-op @deftpx Operation monolithic-compile-concatenated-source-op @deftpx Operation monolithic-load-compiled-concatenated-source-op These operations, as their respective names indicate, will concatenate all the @code{cl-source-file} source files in a system (or in a system and all its dependencies, if monolithic), in the order defined by dependencies, then load the result, or compile and then load the result. These operations are useful to deliver a system or application as a single source file, and for testing that said file loads properly, or compiles and then loads properly. ASDF itself is delivered as a single source file this way, using @code{monolithic-concatenate-source-op}, prepending a prelude and the @code{uiop} library before the @code{asdf/defsystem} system itself. @end deftp @node Creating new operations, , Predefined operations of ASDF, Operations @comment node-name, next, previous, up @subsection Creating new operations ASDF was designed to be extensible in an object-oriented fashion. To teach ASDF new tricks, a programmer can implement the behaviour he wants by creating a subclass of @code{operation}. ASDF's pre-defined operations are in no way ``privileged'', but it is requested that developers never use the @code{asdf} package for operations they develop themselves. The rationale for this rule is that we don't want to establish a ``global asdf operation name registry'', but also want to avoid name clashes. Your operation @emph{must} usually provide methods for one or more of the following generic functions: @itemize @findex perform @item @code{perform} Unless your operation, like @code{prepare-op}, is for dependency propagation only, the most important function for which to define a method is usually @code{perform}, which will be called to perform the operation on a specified component, after all dependencies have been performed. The @code{perform} method must call @code{input-files} and @code{output-files} (see below) to locate its inputs and outputs, because the user is allowed to override the method or tweak the output-translation mechanism. Perform should only use the primary value returned by @code{output-files}. If one and only one output file is expected, it can call @code{output-file} that checks that this is the case and returns the first and only list element. @findex output-files @item @code{output-files} If your perform method has any output, you must define a method for this function. for ASDF to determine where the outputs of performing operation lie. Your method may return two values, a list of pathnames, and a boolean. If the boolean is @code{nil} (or you fail to return multiple values), then enclosing @code{:around} methods may translate these pathnames, e.g. to ensure object files are somehow stored in some implementation-dependent cache. If the boolean is @code{t} then the pathnames are marked not be translated by the enclosing @code{:around} method. @findex component-depends-on @item @code{component-depends-on} If the action of performing the operation on a component has dependencies, you must define a method on @code{component-depends-on}. Your method will take as specialized arguments an operation and a component which together identify an action, and return a list of entries describing actions that this action depends on. The format of entries is described below. It is @emph{strongly} advised that you should always append the results of @code{(call-next-method)} to the results of your method, or ``interesting'' failures will likely occur, unless you're a true specialist of ASDF internals. It is unhappily too late to compatibly use the @code{append} method combination, but conceptually that's the protocol that is being manually implemented. Each entry returned by @code{component-depends-on} is itself a list. The first element of an entry is an operation designator: either an operation object designating itself, or a symbol that names an operation class (that ASDF will instantiate using @code{make-operation}). For instance, @code{load-op}, @code{compile-op} and @code{prepare-op} are common such names, denoting the respective operations. @c FIXME COERCE-NAME is referenced, but not defined. @findex coerce-name @findex find-component The rest of each entry is a list of component designators: either a component object designating itself, or an identifier to be used with @code{find-component}. @code{find-component} will be called with the current component's parent as parent, and the identifier as second argument. The identifier is typically a string, a symbol (to be downcased as per @code{coerce-name}), or a list of strings or symbols. In particular, the empty list @code{nil} denotes the parent itself. @end itemize An operation @emph{may} provide methods for the following generic functions: @itemize @item @code{input-files} @findex input-files A method for this function is often not needed, since ASDF has a pretty clever default @code{input-files} mechanism. You only need create a method if there are multiple ultimate input files. Most operations inherit from @code{selfward-operation}, which appropriately sets the input-files to include the source file itself. @c FIXME: Add documentation of built-in operation types. @defun input-files operation component Return a list of pathnames that represent the input to @var{operation} performed on @var{component}. @end defun @item @code{operation-done-p} @findex operation-done-p You only need to define a method on that function if you can detect conditions that invalidate previous runs of the operation, even though no filesystem timestamp has changed, in which case you return @code{nil} (the default is @code{t}). For instance, the method for @code{test-op} always returns @code{nil}, so that tests are always run afresh. Of course, the @code{test-op} for your system could depend on a deterministically repeatable @code{test-report-op}, and just read the results from the report files, in which case you could have this method return @code{t}. @end itemize Operations that print output should send that output to the standard CL stream @code{*standard-output*}, as the Lisp compiler and loader do. @node Components, Dependencies, Operations, The object model of ASDF @comment node-name, next, previous, up @section Components @cindex component @cindex system @cindex system designator @cindex component designator @vindex *system-definition-search-functions* A @code{component} represents an individual source file or a group of source files, and the things that get transformed into. A @code{system} is a component at the top level of the component hierarchy, that can be found via @code{find-system}. A @code{source-file} is a component representing a single source-file and the successive output files into which it is transformed. A @code{module} is an intermediate component itself grouping several other components, themselves source-files or further modules. A @dfn{system designator} is a system itself, or a string or symbol that behaves just like any other component name (including with regard to the case conversion rules for component names). A @dfn{component designator}, relative to a base component, is either a component itself, or a string or symbol, or a list of designators. @defun find-system system-designator @Aoptional{} (error-p t) Given a system designator, @code{find-system} finds and returns a system. If no system is found, an error of type @code{missing-component} is thrown, or @code{nil} is returned if @code{error-p} is false. To find and update systems, @code{find-system} funcalls each element in the @code{*system-definition-search-functions*} list, expecting a pathname to be returned, or a system object, from which a pathname may be extracted, and that will be registered. The resulting pathname (if any) is loaded if one of the following conditions is true: @itemize @item there is no system of that name in memory @item the pathname is different from that which was previously loaded @item the file's @code{last-modified} time exceeds the @code{last-modified} time of the system in memory @end itemize @cindex ASDF-USER package When system definitions are loaded from @file{.asd} files, they are implicitly loaded into the @code{ASDF-USER} package, which uses @code{ASDF}, @code{UIOP} and @code{UIOP/COMMON-LISP}@footnote{ Note that between releases 2.27 and 3.0.3, only @code{UIOP/PACKAGE}, not all of @code{UIOP}, was used; if you want your code to work with releases earlier than 3.1.2, you may have to explicitly define a package that uses @code{UIOP}, or use proper package prefix to your symbols, as in @code{uiop:version<}.} Programmers who do anything non-trivial in a @file{.asd} file, such as defining new variables, functions or classes, should include @code{defpackage} and @code{in-package} forms in this file, so they will not overwrite each others' extensions. Such forms might also help the files behave identically if loaded manually with @code{cl:load} for development or debugging, though we recommend you use the function @code{asdf::load-asd} instead, which the @code{slime-asdf} contrib knows about. The default value of @code{*system-definition-search-functions*} is a list of three functions. The first function looks in each of the directories given by evaluating members of @code{*central-registry*} for a file whose name is the name of the system and whose type is @file{asd}; the first such file is returned, whether or not it turns out to actually define the appropriate system. The second function does something similar, for the directories specified in the @code{source-registry}, but searches the filesystem only once and caches its results. The third function makes the @code{package-inferred-system} extension work, @pxref{The package-inferred-system extension}. Because of the way these search functions are defined, you should put the definition for a system @var{foo} in a file named @file{foo.asd}, in a directory that is in the central registry or which can be found using the source registry configuration. @c FIXME: Move this discussion to the system definition grammar, or somewhere else. @anchor{System names} @cindex System names @cindex Primary system name @findex primary-system-name It is often useful to define multiple systems in a same file, but ASDF can only locate a system's definition file based on the system name. For this reason, ASDF 3's system search algorithm has been extended to allow a file @file{foo.asd} to contain secondary systems named @var{foo/bar}, @var{foo/baz}, @var{foo/quux}, etc., in addition to the primary system named @var{foo}. The first component of a system name, separated by the slash character, @code{/}, is called the primary name of a system. The primary name may be extracted by function @code{asdf::primary-system-name}; when ASDF 3 is told to find a system whose name has a slash, it will first attempt to load the corresponding primary system, and will thus see any such definitions, and/or any definition of a @code{package-inferred-system}.@footnote{ ASDF 2.26 and earlier versions do not support this primary system name convention. With these versions of ASDF you must explicitly load @file{foo.asd} before you can use system @var{foo/bar} defined therein, e.g. using @code{(asdf:find-system "foo")}. We do not support ASDF 2, and recommend that you should upgrade to ASDF 3. } If your file @file{foo.asd} also defines systems that do not follow this convention, e.g., a system named @var{foo-test}, ASDF will not be able to automatically locate a definition for these systems, and will only see their definition if you explicitly find or load the primary system using e.g. @code{(asdf:find-system "foo")} before you try to use them. We strongly recommend against this practice, though it is currently supported for backward compatibility. @end defun @defun primary-system-name name Internal (not exported) function, @code{asdf::primary-system-name}. Returns the primary system name (the portion before the slash, @code{/}, in a secondary system name) from @var{name}. @end defun @defun locate-system name This function should typically @emph{not} be invoked directly. It is exported as part of the API only for programmers who wish to provide their own @code{*system-definition-search-functions*}. Given a system @var{name} designator, try to locate where to load the system definition from. @c (This does not include the loading of the system definition, @c which is done by @code{find-system}, @c or the loading of the system itself, which is done by @code{load-system}; @c however, for systems the definition of which has already been loaded, @c @code{locate-system} may return an object of class @code{system}.) Returns five values: @var{foundp}, @var{found-system}, @var{pathname}, @var{previous}, and @var{previous-time}. @var{foundp} is true when a system was found, either a new as yet unregistered one, or a previously registered one. The @var{found-system} return value will be a @code{system} object, if a system definition is found in your source registry. @c This system may be registered (by @code{register-system}) or may not, if @c it's preloaded code. Fare writes: @c In the case of preloaded code, as for "asdf", "uiop", etc., @c themselves, the system objects are not registered until after they are @c initially located by sysdef-preloaded-system-search as a fallback when @c no source code was found. The system definition will @emph{not} be loaded if it hasn't been loaded already. @var{pathname} when not null is a path from which to load the system, either associated with @var{found-system}, or with the @var{previous} system. If @var{previous} is not null, it will be a @emph{previously loaded} @code{system} object of the same name (note that the system @emph{definition} is previously-loaded: the system itself may or may not be). @var{previous-time} when not null is the timestamp of the previous system definition file, at the time when the @var{previous} system definition was loaded. For example, if your current registry has @file{foo.asd} in @file{/current/path/to/foo.asd}, but system @code{foo} was previously loaded from @file{/previous/path/to/foo.asd} then @var{locate-system} will return the following values: @enumerate @item @var{foundp} will be @code{t}, @item @var{found-system} will be @code{nil}, @item @var{pathname} will be @code{#p"/current/path/to/foo.asd"}, @item @var{previous} will be an object of type @code{SYSTEM} with @code{system-source-file} slot value of @code{#p"/previous/path/to/foo.asd"} @item @var{previous-time} will be the timestamp of @code{#p"/previous/path/to/foo.asd"} at the time it was loaded. @end enumerate @end defun @defun find-component base path Given a @var{base} component (or designator for such), and a @var{path}, find the component designated by the @var{path} starting from the @var{base}. If @var{path} is a component object, it designates itself, independently from the base. @findex coerce-name If @var{path} is a string, or symbol denoting a string via @code{coerce-name}, then @var{base} is resolved to a component object, which must be a system or module, and the designated component is the child named by the @var{path}. If @var{path} is a @code{cons} cell, @code{find-component} with the base and the @code{car} of the @var{path}, and the resulting object is used as the base for a tail call to @code{find-component} with the @code{car} of the @var{path}. If @var{base} is a component object, it designates itself. If @var{base} is null, then @var{path} is used as the base, with @code{nil} as the path. If @var{base} is a string, or symbol denoting a string via @code{coerce-name}, it designates a system as per @code{find-system}. If @var{base} is a @code{cons} cell, it designates the component found by @code{find-component} with its @code{car} as base and @code{cdr} as path. @end defun @menu * Common attributes of components:: * Pre-defined subclasses of component:: * Creating new component types:: @end menu @node Common attributes of components, Pre-defined subclasses of component, Components, Components @comment node-name, next, previous, up @subsection Common attributes of components All components, regardless of type, have the following attributes. All attributes except @code{name} are optional. @subsubsection Name @findex coerce-name A component name is a string or a symbol. If a symbol, its name is taken and lowercased. This translation is performed by the exported function @code{coerce-name}. Unless overridden by a @code{:pathname} attribute, the name will be interpreted as a pathname specifier according to a Unix-style syntax. @xref{Pathname specifiers}. @subsubsection Version identifier @findex version-satisfies @cindex :version This optional attribute specifies a version for the current component. The version should typically be a string of integers separated by dots, for example @samp{1.0.11}. @xref{Version specifiers}. A version may then be queried by the generic function @code{version-satisfies}, to see if @code{:version} dependencies are satisfied, and when specifying dependencies, a constraint of minimal version to satisfy can be specified using e.g. @code{(:version "mydepname" "1.0.11")}. Note that in the wild, we typically see version numbering only on components of type @code{system}. Presumably it is much less useful within a given system, wherein the library author is responsible to keep the various files in synch. @subsubsection Required features @anchor{required-features} Traditionally defsystem users have used @code{#+} reader conditionals to include or exclude specific per-implementation files. For example, CFFI, the portable C foreign function interface contained lines like: @lisp #+sbcl (:file "cffi-sbcl") @end lisp An unfortunate side effect of this approach is that no single implementation can read the entire system. This causes problems if, for example, one wished to design an @code{archive-op} that would create an archive file containing all the sources, since for example the file @code{cffi-sbcl.lisp} above would be invisible when running the @code{archive-op} on any implementation other than SBCL. Starting with ASDF 3, components may therefore have an @code{:if-feature} option. The value of this option should be a feature expression using the same syntax as @code{#+} does. If that feature expression evaluates to false, any reference to the component will be ignored during compilation, loading and/or linking. Since the expression is read by the normal reader, you must explicitly prefix your symbols with @code{:} so they be read as keywords; this is as contrasted with the @code{#+} syntax that implicitly reads symbols in the keyword package by default. For instance, @code{:if-feature (:and :x86 (:or :sbcl :cmu :scl))} specifies that the given component is only to be compiled and loaded when the implementation is SBCL, CMUCL or Scieneer CL on an x86 machine. You cannot write it as @code{:if-feature (and x86 (or sbcl cmu scl))} since the symbols would not be read as keywords. @xref{if-feature option}. @subsubsection Dependencies This attribute specifies dependencies of the component on its siblings. It is optional but often necessary. There is an excitingly complicated relationship between the initarg and the method that you use to ask about dependencies Dependencies are between (operation component) pairs. In your initargs for the component, you can say @lisp :in-order-to ((compile-op (load-op "a" "b") (compile-op "c")) (load-op (load-op "foo"))) @end lisp This means the following things: @itemize @item before performing compile-op on this component, we must perform load-op on @var{a} and @var{b}, and compile-op on @var{c}, @item before performing @code{load-op}, we have to load @var{foo} @end itemize The syntax is approximately @verbatim (this-op @{(other-op required-components)@}+) simple-component-name := string | symbol required-components := simple-component-name | (required-components required-components) component-name := simple-component-name | (:version simple-component-name minimum-version-object) @end verbatim Side note: This is on a par with what ACL defsystem does. mk-defsystem is less general: it has an implied dependency @verbatim for all source file x, (load x) depends on (compile x) @end verbatim and using a @code{:depends-on} argument to say that @var{b} depends on @var{a} @emph{actually} means that @verbatim (compile b) depends on (load a) @end verbatim This is insufficient for e.g. the McCLIM system, which requires that all the files are loaded before any of them can be compiled ] End side note In ASDF, the dependency information for a given component and operation can be queried using @code{(component-depends-on operation component)}, which returns a list @lisp ((load-op "a") (load-op "b") (compile-op "c") ...) @end lisp @code{component-depends-on} can be subclassed for more specific component/operation types: these need to @code{(call-next-method)} and append the answer to their dependency, unless they have a good reason for completely overriding the default dependencies. If it weren't for CLISP, we'd be using @code{LIST} method combination to do this transparently. But, we need to support CLISP. If you have the time for some CLISP hacking, I'm sure they'd welcome your fixes. @c Doesn't CLISP now support LIST method combination? A minimal version can be specified for a component you depend on (typically another system), by specifying @code{(:version "other-system" "1.2.3")} instead of simply @code{"other-system"} as the dependency. See the discussion of the semantics of @code{:version} in the defsystem grammar. @c FIXME: Should have cross-reference to "Version specifiers" in the @c defsystem grammar, but the cross-referencing is so broken by @c insufficient node breakdown that I have not put one in. @subsubsection pathname This attribute is optional and if absent (which is the usual case), the component name will be used. @xref{Pathname specifiers}, for an explanation of how this attribute is interpreted. Note that the @code{defsystem} macro (used to create a ``top-level'' system) does additional processing to set the filesystem location of the top component in that system. This is detailed elsewhere. @xref{Defining systems with defsystem}. To find the CL pathname corresponding to a component, use @defun component-pathname component Returns the pathname corresponding to @var{component}. For components such as source files, this will be a filename pathname. For example: @lisp CL-USER> (asdf:component-pathname (asdf:find-system "xmls")) #P"/Users/rpg/lisp/xmls/" @end lisp and @lisp CL-USER> (asdf:component-pathname (asdf:find-component (asdf:find-system "xmls") "xmls")) #P"/Users/rpg/lisp/xmls/xmls.lisp" @end lisp @end defun @subsubsection Properties This attribute is optional. Packaging systems often require information about files or systems in addition to that specified by ASDF's pre-defined component attributes. Programs that create vendor packages out of ASDF systems therefore have to create ``placeholder'' information to satisfy these systems. Sometimes the creator of an ASDF system may know the additional information and wish to provide it directly. @code{(component-property component property-name)} and associated @code{setf} method will allow the programmatic update of this information. Property names are compared as if by @code{EQL}, so use symbols or keywords or something. @menu * Pre-defined subclasses of component:: * Creating new component types:: @end menu @node Pre-defined subclasses of component, Creating new component types, Common attributes of components, Components @comment node-name, next, previous, up @subsection Pre-defined subclasses of component @deftp Component source-file A source file is any file that the system does not know how to generate from other components of the system. Note that this is not necessarily the same thing as ``a file containing data that is typically fed to a compiler''. If a file is generated by some pre-processor stage (e.g. a @file{.h} file from @file{.h.in} by autoconf) then it is not, by this definition, a source file. Conversely, we might have a graphic file that cannot be automatically regenerated, or a proprietary shared library that we received as a binary: these do count as source files for our purposes. Subclasses of source-file exist for various languages. @emph{FIXME: describe these.} @end deftp @deftp Component module A module is a collection of sub-components. A module component has the following extra initargs: @itemize @item @code{:components} the components contained in this module @item @code{:default-component-class} All children components which don't specify their class explicitly are inferred to be of this type. @item @code{:if-component-dep-fails} This attribute was removed in ASDF 3. Do not use it. Use @code{:if-feature} instead (@pxref{required-features}, and @pxref{if-feature option}). @item @code{:serial} When this attribute is set, each subcomponent of this component is assumed to depend on all subcomponents before it in the list given to @code{:components}, i.e. all of them are loaded before a compile or load operation is performed on it. @end itemize The default operation knows how to traverse a module, so most operations will not need to provide methods specialised on modules. @code{module} may be subclassed to represent components such as foreign-language linked libraries or archive files. @end deftp @deftp Component system @code{system} is a subclass of @code{module}. A system is a module with a few extra attributes for documentation purposes; these are given elsewhere. @xref{The defsystem grammar}. Users can create new classes for their systems: the default @code{defsystem} macro takes a @code{:class} keyword argument. @end deftp @node Creating new component types, , Pre-defined subclasses of component, Components @comment node-name, next, previous, up @subsection Creating new component types New component types are defined by subclassing one of the existing component classes and specializing methods on the new component class. @c FIXME: this should perhaps be explained more thoroughly, @c not only by example ... As an example, suppose we have some implementation-dependent functionality that we want to isolate in one subdirectory per Lisp implementation our system supports. We create a subclass of @code{cl-source-file}: @lisp (defclass unportable-cl-source-file (cl-source-file) ()) @end lisp Function @code{asdf:implementation-type} (exported since 2.014.14) gives us the name of the subdirectory. All that's left is to define how to calculate the pathname of an @code{unportable-cl-source-file}. @lisp (defmethod component-pathname ((component unportable-cl-source-file)) (merge-pathnames* (parse-unix-namestring (format nil "~(~A~)/" (asdf:implementation-type))) (call-next-method))) @end lisp The new component type is used in a @code{defsystem} form in this way: @lisp (defsystem :foo :components ((:file "packages") ... (:unportable-cl-source-file "threads" :depends-on ("packages" ...)) ... ) @end lisp @node Dependencies, Functions, Components, The object model of ASDF @section Dependencies @c FIXME: Moved this material here, but it isn't very comfortable @c here.... Also needs to be revised to be coherent. To be successfully build-able, this graph of actions must be acyclic. If, as a user, extender or implementer of ASDF, you introduce a cycle into the dependency graph, ASDF will fail loudly. To clearly distinguish the direction of dependencies, ASDF 3 uses the words @emph{requiring} and @emph{required} as applied to an action depending on the other: the requiring action @code{depends-on} the completion of all required actions before it may itself be @code{perform}ed. Using the @code{defsystem} syntax, users may easily express direct dependencies along the graph of the object hierarchy: between a component and its parent, its children, and its siblings. By defining custom CLOS methods, you can express more elaborate dependencies as you wish. Most common operations, such as @code{load-op}, @code{compile-op} or @code{load-source-op} are automatically propagate ``downward'' the component hierarchy and are ``covariant'' with it: to act the operation on the parent module, you must first act it on all the children components, with the action on the parent being parent of the action on each child. Other operations, such as @code{prepare-op} and @code{prepare-source-op} (introduced in ASDF 3) are automatically propagated ``upward'' the component hierarchy and are ``contravariant'' with it: to perform the operation of preparing for compilation of a child component, you must perform the operation of preparing for compilation of its parent component, and so on, ensuring that all the parent's dependencies are (compiled and) loaded before the child component may be compiled and loaded. Yet other operations, such as @code{test-op} or @code{load-bundle-op} remain at the system level, and are not propagated along the hierarchy, but instead do something global on the system. @node Functions, Parsing system definitions, Dependencies, The object model of ASDF @comment node-name, next, previous, up @section Functions @c FIXME: this does not belong here.... @defun version-satisfies @var{version} @var{version-spec} Does @var{version} satisfy the @var{version-spec}. A generic function. ASDF provides built-in methods for @var{version} being a @code{component} or @code{string}. @var{version-spec} should be a string. If it's a component, its version is extracted as a string before further processing. A version string satisfies the version-spec if after parsing, the former is no older than the latter. Therefore @code{"1.9.1"}, @code{"1.9.2"} and @code{"1.10"} all satisfy @code{"1.9.1"}, but @code{"1.8.4"} or @code{"1.9"} do not. For more information about how @code{version-satisfies} parses and interprets version strings and specifications, @pxref{Version specifiers} and @ref{Common attributes of components}. Note that in versions of ASDF prior to 3.0.1, including the entire ASDF 1 and ASDF 2 series, @code{version-satisfies} would also require that the version and the version-spec have the same major version number (the first integer in the list); if the major version differed, the version would be considered as not matching the spec. But that feature was not documented, therefore presumably not relied upon, whereas it was a nuisance to several users. Starting with ASDF 3.0.1, @code{version-satisfies} does not treat the major version number specially, and returns T simply if the first argument designates a version that isn't older than the one specified as a second argument. If needs be, the @code{(:version ...)} syntax for specifying dependencies could be in the future extended to specify an exclusive upper bound for compatible versions as well as an inclusive lower bound. @end defun @node Parsing system definitions, , Functions, The object model of ASDF @section Parsing system definitions @cindex Parsing system definitions @cindex Extending ASDF's defsystem parser Thanks to Eric Timmons, ASDF now provides hooks to extend how it parses @code{defsystem} forms. @strong{Warning!} These interfaces are experimental, and as such are not exported from the ASDF package yet. We plan to export them in ASDF 3.4.0. If you use them before they are exported, please subscribe to @url{https://gitlab.common-lisp.net/asdf/asdf/-/issues/76} so you are made aware of any changes. @defun parse-component-form @var{parent} @var{options} &key @var{previous-serial-components} This is the core function for parsing a system definition. At the moment, we do not expect ASDF extenders to modify this function. When being called on a @code{component} of type @code{system} (i.e., inside the @code{defsystem} macro), @var{parent} will be @code{NIL}. @end defun @deffn {Generic function} compute-component-children @var{component} @var{components} @var{serial-p} This generic function provides standard means for computing component children, but can be extended with additional methods by a programmer. Returns a list of children (of type @code{component}) for @var{component}. @var{components} is a list of the explicitly defined children descriptions. @var{serial-p} is non-@code{NIL} if each child in @var{components} should depend on the previous children. @end deffn @deffn {Generic function} class-for-type @var{parent} @var{type-designator} Return a @code{class} designator to be used to instantiate a component whose type is specified by @var{type-designator} in the context of @var{parent}, which should be either a @code{parent-component} -- or subclass thereof -- or @code{nil} (if the type designator is some class of system). This generic function provides a means for changing how ASDF translates type-designators (like @code{:file}) into CLOS classes. It is intended for programmers to extend by adding new methods. @strong{Warning!} Adding new methods for @code{class-for-type} is typically @emph{not} necessary: much can already be done by using @code{:default-component-class} and defining (and explicitly calling for) new component types. @end deffn @node Controlling where ASDF searches for systems, Controlling where ASDF saves compiled files, The object model of ASDF, Top @comment node-name, next, previous, up @chapter Controlling where ASDF searches for systems @menu * Configurations:: * Truenames and other dangers:: * XDG base directory:: * Backward Compatibility:: * Configuration DSL:: * Configuration Directories:: * Shell-friendly syntax for configuration:: * Search Algorithm:: * Caching Results:: * Configuration API:: * Introspection:: * Status:: * Rejected ideas:: * TODO:: * Credits for the source-registry:: @end menu @node Configurations, Truenames and other dangers, Controlling where ASDF searches for systems, Controlling where ASDF searches for systems @section Configurations Configurations specify paths where to find system files. @enumerate @item The search registry may use some hardcoded wrapping registry specification. This allows some implementations (notably SBCL) to specify where to find some special implementation-provided systems that need to precisely match the version of the implementation itself. @item An application may explicitly initialize the source-registry configuration using the configuration API (@pxref{Controlling where ASDF searches for systems,Configuration API,Configuration API}, below) in which case this takes precedence. It may itself compute this configuration from the command-line, from a script, from its own configuration file, etc. @item The source registry will be configured from the environment variable @code{CL_SOURCE_REGISTRY} if it exists. @item The source registry will be configured from user configuration file @file{$XDG_CONFIG_DIRS/common-lisp/source-registry.conf} (which defaults to @file{~/.config/common-lisp/source-registry.conf}) if it exists. @item The source registry will be configured from user configuration directory @file{$XDG_CONFIG_DIRS/common-lisp/source-registry.conf.d/} (which defaults to @file{~/.config/common-lisp/source-registry.conf.d/}) if it exists. @item The source registry will be configured from default user configuration trees @file{~/common-lisp/} (since ASDF 3.1.2 only), @file{~/.sbcl/systems/} (on SBCL only), @file{$XDG_DATA_HOME/common-lisp/systems/} (no recursion, link farm) @file{$XDG_DATA_HOME/common-lisp/source/}. The @code{XDG_DATA_HOME} directory defaults to @file{~/.local/share/}. On Windows, the @code{local-appdata} and @code{appdata} directories are used instead. @item The source registry will be configured from system configuration file @file{/etc/common-lisp/source-registry.conf} if it exists. @item The source registry will be configured from system configuration directory @file{/etc/common-lisp/source-registry.conf.d/} if it exists. @item The source registry will be configured from a default configuration. This configuration may allow for implementation-specific systems to be found, for systems to be found the current directory (at the time that the configuration is initialized) as well as @code{:directory} entries for @file{$XDG_DATA_DIRS/common-lisp/systems/} and @code{:tree} entries for @file{$XDG_DATA_DIRS/common-lisp/source/}, where @code{XDG_DATA_DIRS} defaults to @file{/usr/local/share} and @file{/usr/share} on Unix, and the @code{common-appdata} directory on Windows. @item The source registry may include implementation-dependent directories that correspond to implementation-provided extensions. @end enumerate Each of these configurations is specified as an s-expression in a trivial domain-specific language (defined below). Additionally, a more shell-friendly syntax is available for the environment variable (defined yet below). Each of these configurations is only used if the previous configuration explicitly or implicitly specifies that it includes its inherited configuration. Additionally, some implementation-specific directories may be automatically prepended to whatever directories are specified in configuration files, no matter if the last one inherits or not. @node Truenames and other dangers, XDG base directory, Configurations, Controlling where ASDF searches for systems @section Truenames and other dangers One great innovation of the original ASDF was its ability to leverage @code{CL:TRUENAME} to locate where your source code was and where to build it, allowing for symlink farms as a simple but effective configuration mechanism that is easy to control programmatically. ASDF 3 still supports this configuration style, and it is enabled by default; however we recommend you instead use our source-registry configuration mechanism described below, because it is easier to setup in a portable way across users and implementations. Additionally, some people dislike truename, either because it is very slow on their system, or because they are using content-addressed storage where the truename of a file is related to a digest of its individual contents, and not to other files in the same intended project. For these people, ASDF 3 allows to eschew the @code{TRUENAME} mechanism, by setting the variable @var{asdf:*resolve-symlinks*} to @code{nil}. PS: Yes, if you haven't read Vernor Vinge's short but great classic ``True Names... and Other Dangers'' then you're in for a treat. @node XDG base directory, Backward Compatibility, Truenames and other dangers, Controlling where ASDF searches for systems @section XDG base directory Note that we purport to respect the XDG base directory specification as to where configuration files are located, where data files are located, where output file caches are located. Mentions of XDG variables refer to that document. @url{http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html} This specification allows the user to specify some environment variables to customize how applications behave to his preferences. On Windows platforms, even when not using Cygwin, and starting with ASDF 3.1.5, we still do a best effort at following the XDG base directory specification, even though it doesn't exactly fit common practice for Windows applications. However, we replace the fixed Unix paths @file{~/.local}, @file{/usr/local} and @file{/usr} with their rough Windows equivalent @file{Local AppData}, @file{AppData}, @file{Common AppData}, etc. Since support for querying the Windows registry is not possible to do in reasonable amounts of portable Common Lisp code, ASDF 3 relies on the environment variables that Windows usually exports, and are hopefully in synch with the Windows registry. If you care about the details, see @file{uiop/configuration.lisp} and don't hesitate to suggest improvements. @node Backward Compatibility, Configuration DSL, XDG base directory, Controlling where ASDF searches for systems @section Backward Compatibility For backward compatibility as well as to provide a practical backdoor for hackers, ASDF will first search for @file{.asd} files in the directories specified in @code{asdf:*central-registry*} before it searches in the source registry above. @xref{Configuring ASDF,,Configuring ASDF to find your systems --- old style}. By default, @code{asdf:*central-registry*} will be empty. This old mechanism will therefore not affect you if you don't use it, but will take precedence over the new mechanism if you do use it. @node Configuration DSL, Configuration Directories, Backward Compatibility, Controlling where ASDF searches for systems @section Configuration DSL @cindex :inherit-configuration source config directive @cindex inherit-configuration source config directive @cindex :ignore-invalid-entries source config directive @cindex ignore-invalid-entries source config directive @cindex :directory source config directive @cindex directory source config directive @cindex :tree source config directive @cindex tree source config directive @cindex :exclude source config directive @cindex exclude source config directive @cindex :also-exclude source config directive @cindex also-exclude source config directive @cindex :include source config directive @cindex include source config directive @cindex :default-registry source config directive @cindex default-registry source config directive Here is the grammar of the s-expression (SEXP) DSL for source-registry configuration: @c FIXME: This is too wide for happy compilation into pdf. @example ;; A configuration is a single SEXP starting with the keyword ;; :source-registry followed by a list of directives. CONFIGURATION := (:source-registry DIRECTIVE ...) ;; A directive is one of the following: DIRECTIVE := ;; INHERITANCE DIRECTIVE: ;; Your configuration expression MUST contain ;; exactly one of the following: :inherit-configuration | ;; splices inherited configuration (often specified last) or :ignore-inherited-configuration | ;; drop inherited configuration (specified anywhere) ;; forward compatibility directive (since ASDF 2.011.4), useful when ;; you want to use new configuration features but have to bootstrap ;; the newer required ASDF from an older release that doesn't ;; support said features: :ignore-invalid-entries | ;; add a single directory to be scanned (no recursion) (:directory DIRECTORY-PATHNAME-DESIGNATOR) | ;; add a directory hierarchy, recursing but ;; excluding specified patterns (:tree DIRECTORY-PATHNAME-DESIGNATOR) | ;; override the defaults for exclusion patterns (:exclude EXCLUSION-PATTERN ...) | ;; augment the defaults for exclusion patterns (:also-exclude EXCLUSION-PATTERN ...) | ;; Note that the scope of a an exclude pattern specification is ;; the rest of the current configuration expression or file. ;; splice the parsed contents of another config file (:include REGULAR-FILE-PATHNAME-DESIGNATOR) | ;; This directive specifies that some default must be spliced. :default-registry REGULAR-FILE-PATHNAME-DESIGNATOR := PATHNAME-DESIGNATOR ; interpreted as a file DIRECTORY-PATHNAME-DESIGNATOR := PATHNAME-DESIGNATOR ; interpreted as a directory PATHNAME-DESIGNATOR := NIL | ;; Special: skip this entry. ABSOLUTE-COMPONENT-DESIGNATOR ;; see pathname DSL EXCLUSION-PATTERN := a string without wildcards, that will be matched exactly against the name of a any subdirectory in the directory component of a path. e.g. @code{"_darcs"} will match @file{#p"/foo/bar/_darcs/src/bar.asd"} @end example Pathnames are designated using another DSL, shared with the output-translations configuration DSL below. The DSL is resolved by the function @code{asdf::resolve-location}, to be documented and exported at some point in the future. @example ABSOLUTE-COMPONENT-DESIGNATOR := (ABSOLUTE-COMPONENT-DESIGNATOR RELATIVE-COMPONENT-DESIGNATOR ...) | STRING | ;; namestring (better be absolute or bust, directory assumed where ;; applicable). In output-translations, directory is assumed and ;; **/*.*.* added if it's last. On MCL, a MacOSX-style POSIX ;; namestring (for MacOS9 style, use #p"..."); Note that none of the ;; above applies to strings used in *central-registry*, which ;; doesn't use this DSL: they are processed as normal namestrings. ;; however, you can compute what you put in the *central-registry* ;; based on the results of say ;; (asdf::resolve-location "/Users/fare/cl/cl-foo/") PATHNAME | ;; pathname (better be an absolute path, or bust) ;; In output-translations, unless followed by relative components, ;; it better have appropriate wildcards, as in **/*.*.* :HOME | ; designates the user-homedir-pathname ~/ :USER-CACHE | ; designates the default location for the user cache :HERE | ;; designates the location of the configuration file ;; (or *default-pathname-defaults*, if invoked interactively) :ROOT ;; magic, for output-translations source only: paths that are relative ;; to the root of the source host and device They keyword :SYSTEM-CACHE is not accepted in ASDF 3.1 and beyond: it was a security hazard. RELATIVE-COMPONENT-DESIGNATOR := (RELATIVE-COMPONENT-DESIGNATOR RELATIVE-COMPONENT-DESIGNATOR ...) | STRING | ;; relative directory pathname as interpreted by ;; parse-unix-namestring. ;; In output translations, if last component, **/*.*.* is added PATHNAME | ; pathname; unless last component, directory is assumed. :IMPLEMENTATION | ;; directory based on implementation, e.g. sbcl-1.0.45-linux-x64 :IMPLEMENTATION-TYPE | ;; a directory based on lisp-implementation-type only, e.g. sbcl :DEFAULT-DIRECTORY | ;; a relativized version of the default directory :*/ | ;; any direct subdirectory (since ASDF 2.011.4) :**/ | ;; any recursively inferior subdirectory (since ASDF 2.011.4) :*.*.* | ;; any file (since ASDF 2.011.4) The keywords :UID and :USERNAME are no longer supported. @end example For instance, as a simple case, my @file{~/.config/common-lisp/source-registry.conf}, which is the default place ASDF looks for this configuration, once contained: @example (:source-registry (:tree (:home "cl")) ;; will expand to e.g. "/home/joeluser/cl/" :inherit-configuration) @end example @node Configuration Directories, Shell-friendly syntax for configuration, Configuration DSL, Controlling where ASDF searches for systems @section Configuration Directories Configuration directories consist in files each containing a list of directives without any enclosing @code{(:source-registry ...)} form. The files will be sorted by namestring as if by @code{string<} and the lists of directives of these files with be concatenated in order. An implicit @code{:inherit-configuration} will be included at the @emph{end} of the list. System-wide or per-user Common Lisp software distributions such as Debian packages or some future version of @code{clbuild} may then include files such as @file{/etc/common-lisp/source-registry.conf.d/10-foo.conf} or @file{~/.config/common-lisp/source-registry.conf.d/10-foo.conf} to easily and modularly register configuration information about software being distributed. The convention is that, for sorting purposes, the names of files in such a directory begin with two digits that determine the order in which these entries will be read. Also, the type of these files must be @file{.conf}, which not only simplifies the implementation by allowing for more portable techniques in finding those files, but also makes it trivial to disable a file, by renaming it to a different file type. Directories may be included by specifying a directory pathname or namestring in an @code{:include} directive, e.g.: @example (:include "/foo/bar/") @end example Hence, to achieve the same effect as my example @file{~/.config/common-lisp/source-registry.conf} above, I could simply create a file @file{~/.config/common-lisp/source-registry.conf.d/33-home-fare-cl.conf} alone in its directory with the following contents: @example (:tree "/home/fare/cl/") @end example @menu * The here directive:: @end menu @node The here directive, , Configuration Directories, Configuration Directories @subsection The :here directive The @code{:here} directive is an absolute pathname designator that refers to the directory containing the configuration file currently being processed. The @code{:here} directive is intended to simplify the delivery of complex CL systems, and for easy configuration of projects shared through revision control systems, in accordance with our design principle that each participant should be able to provide all and only the information available to him or her. Consider a person X who has set up the source code repository for a complex project with a master directory @file{dir/}. Ordinarily, one might simply have the user add a directive that would look something like this: @example (:tree "path/to/dir") @end example But what if X knows that there are very large subtrees under dir that are filled with, e.g., Java source code, image files for icons, etc.? All of the asdf system definitions are contained in the subdirectories @file{dir/src/lisp/} and @file{dir/extlib/lisp/}, and these are the only directories that should be searched. In this case, X can put into @file{dir/} a file @file{asdf.conf} that contains the following: @example (:source-registry (:tree (:here "src/lisp/")) (:tree (:here "extlib/lisp")) (:directory (:here "outlier/"))) @end example Then when someone else (call her Y) checks out a copy of this repository, she need only add @example (:include "/path/to/my/checkout/directory/asdf.conf") @end example to one of her previously-existing asdf source location configuration files, or invoke @code{initialize-source-registry} with a configuration form containing that s-expression. ASDF will find the .conf file that X has provided, and then set up source locations within the working directory according to X's (relative) instructions. @node Shell-friendly syntax for configuration, Search Algorithm, Configuration Directories, Controlling where ASDF searches for systems @section Shell-friendly syntax for configuration When considering environment variable @code{CL_SOURCE_REGISTRY} ASDF will skip to next configuration if it's an empty string. It will @code{READ} the string as a SEXP in the DSL if it begins with a paren @code{(}, otherwise it will be interpreted much like @code{TEXINPUTS}, as a list of paths, where @itemize @item paths are separated by a @code{:} (colon) on Unix platforms (including cygwin), by a @code{;} (semicolon) on other platforms (mainly, Windows). @item each entry is a directory to add to the search path. @item if the entry ends with a double slash @code{//} then it instead indicates a tree in the subdirectories of which to recurse. @item if the entry is the empty string (which may only appear once), then it indicates that the inherited configuration should be spliced there. @end itemize @node Search Algorithm, Caching Results, Shell-friendly syntax for configuration, Controlling where ASDF searches for systems @section Search Algorithm @vindex *default-source-registry-exclusions* In case that isn't clear, the semantics of the configuration is that when searching for a system of a given name, directives are processed in order. When looking in a directory, if the system is found, the search succeeds, otherwise it continues. When looking in a tree, if one system is found, the search succeeds. If multiple systems are found, the consequences are unspecified: the search may succeed with any of the found systems, or an error may be raised. ASDF 3.2.1 or later returns the pathname whose normalized directory component has the shortest length (as a list), and breaks ties by choosing the system with the smallest @code{unix-namestring} when compared with @code{string<}. Earlier versions of ASDF return ASDF return the first system found, which is implementation-dependent, and may or may not be the pathname with the smallest @code{unix-namestring} when compared with @code{string<}. XCVB raises an error. If none is found, the search continues. Exclude statements specify patterns of subdirectories the systems from which to ignore. Typically you don't want to use copies of files kept by such version control systems as Darcs. Exclude statements are not propagated to further included or inherited configuration files or expressions; instead the defaults are reset around every configuration statement to the default defaults from @code{asdf::*default-source-registry-exclusions*}. Include statements cause the search to recurse with the path specifications from the file specified. An inherit-configuration statement cause the search to recurse with the path specifications from the next configuration (@pxref{Configurations} above). @node Caching Results, Configuration API, Search Algorithm, Controlling where ASDF searches for systems @section Caching Results The implementation is allowed to either eagerly compute the information from the configurations and file system, or to lazily re-compute it every time, or to cache any part of it as it goes. In practice, the recommended @code{source-registry} eagerly collects and caches results and you need to explicitly flush the cache for change to be taken into account, whereas the old-style @code{*central-registry*} mechanism queries the filesystem every time. To explicitly flush any information cached by the system after a change was made in the filesystem, @xref{Configuration API}, and e.g. call @code{asdf:clear-source-registry}. Starting with ASDF 3.1.4, you can also explicitly build a persistent cache of the @file{.asd} files found under a tree: when recursing into a directory declared by @code{:tree} and its transitive subdirectories, if a file @file{.cl-source-registry.cache} exists containing a form that is a list starting with @code{:source-registry-cache} followed by a list of strings, as in @code{(:source-registry-cache @emph{"foo/bar.asd" "path/to/more.asd" ...})}, then the strings are assumed to be @code{unix-namestring}s designating the available asd files under that tree, and the recursion otherwise stops. The list can also be empty, allowing to stop a costly recursion in a huge directory tree. To update such a cache after you install, update or remove source repositories, you can run a script distributed with ASDF: @code{tools/cl-source-registry-cache.lisp @emph{/path/to/directory}}. To wholly invalidate the cache, you can delete the file @file{.cl-source-registry.cache} in that directory. In either case, for an existing Lisp process to see this change, it needs to clear its own cache with e.g. @code{(asdf:clear-source-registry)}. Developers may safely create a cache in their development tree, and we recommend they do it at the top of their source tree if it contains more than a small number of files and directories; they only need update it when they create, remove or move @file{.asd} files. Software distribution managers may also safely create such a cache, but they must be careful to update it every time they install, update or remove a software source repository or installation package. Finally, advanced developers who juggle with a lot of code in their @code{source-registry} may manually manage such a cache, to allow for faster startup of Lisp programs. This persistence cache can help you reduce startup latency. For instance, on one machine with hundreds of source repositories, such a cache shaves half a second at the startup of every @code{#!/usr/bin/cl} script using SBCL, more on other implementations; this makes a notable difference as to their subjective interactivity and usability. The speedup will only happen if the implementation-provided ASDF is recent enough (3.1.3.7 or later); it is not enough for a recent ASDF upgrade to be present, since the upgrade will itself be found but after the old version has scanned the directories without heeding such a cache. To upgrade the implementation-provided ASDF, @pxref{Replacing your implementation's ASDF}. @node Configuration API, Introspection, Caching Results, Controlling where ASDF searches for systems @section Configuration API The specified functions are exported from your build system's package. Thus for ASDF the corresponding functions are in package ASDF, and for XCVB the corresponding functions are in package XCVB. @defun initialize-source-registry @Aoptional{} PARAMETER will read the configuration and initialize all internal variables. You may extend or override configuration from the environment and configuration files with the given @var{PARAMETER}, which can be @code{nil} (no configuration override), or a SEXP (in the SEXP DSL), a string (as in the string DSL), a pathname (of a file or directory with configuration), or a symbol (fbound to function that when called returns one of the above). @end defun @defun clear-source-registry undoes any source registry configuration and clears any cache for the search algorithm. You might want to call this function (or better, @code{clear-configuration}) before you dump an image that would be resumed with a different configuration, and return an empty configuration. Note that this does not include clearing information about systems defined in the current image, only about where to look for systems not yet defined. @end defun @defun ensure-source-registry @Aoptional{} PARAMETER checks whether a source registry has been initialized. If not, initialize it with the given @var{PARAMETER}. @end defun Every time you use ASDF's @code{find-system}, or anything that uses it (such as @code{operate}, @code{load-system}, etc.), @code{ensure-source-registry} is called with parameter @code{nil}, which the first time around causes your configuration to be read. If you change a configuration file, you need to explicitly @code{initialize-source-registry} again, or maybe simply to @code{clear-source-registry} (or @code{clear-configuration}) which will cause the initialization to happen next time around. @node Introspection, Status, Configuration API, Controlling where ASDF searches for systems @section Introspection @menu * *source-registry-parameter* variable:: * Information about system dependencies:: @end menu @node *source-registry-parameter* variable, Information about system dependencies, Introspection, Introspection @subsection *source-registry-parameter* variable @vindex *source-registry-parameter* We have made available the variable @code{*source-registry-parameter*} that can be used by code that wishes to introspect about the (past) configuration of ASDF's source registry. @strong{This variable should never be set!} It will be set as a side-effect of calling @code{initialize-source-registry}; user code should treat it as read-only. @node Information about system dependencies, , *source-registry-parameter* variable, Introspection @subsection Information about system dependencies ASDF makes available three functions to read system interdependencies. These are intended to aid programmers who wish to perform dependency analyses. @defun system-defsystem-depends-on system @end defun @defun system-depends-on system @end defun @defun system-weakly-depends-on system Returns a list of names of systems that are weakly depended on by @var{system}. Weakly depended on systems are optionally loaded only if ASDF can find them; failure to find such systems does @emph{not} cause an error in loading. Note that the return value for @code{system-weakly-depends-on} is simpler than the return values of the other two system dependency introspection functions. @end defun @node Status, Rejected ideas, Introspection, Controlling where ASDF searches for systems @section Status This mechanism is vastly successful, and we have declared that @code{asdf:*central-registry*} is not recommended anymore, though we will continue to support it. All hooks into implementation-specific search mechanisms have been integrated in the @code{wrapping-source-registry} that everyone uses implicitly. @node Rejected ideas, TODO, Status, Controlling where ASDF searches for systems @section Rejected ideas Alternatives I (FRR) considered and rejected while developing ASDF 2 included: @enumerate @item Keep @code{asdf:*central-registry*} as the master with its current semantics, and somehow the configuration parser expands the new configuration language into a expanded series of directories of subdirectories to lookup, pre-recursing through specified hierarchies. This is kludgy, and leaves little space of future cleanups and extensions. @item Keep @code{asdf:*central-registry*} as the master but extend its semantics in completely new ways, so that new kinds of entries may be implemented as a recursive search, etc. This seems somewhat backwards. @item Completely remove @code{asdf:*central-registry*} and break backwards compatibility. Hopefully this will happen in a few years after everyone migrate to a better ASDF and/or to XCVB, but it would be very bad to do it now. @item Replace @code{asdf:*central-registry*} by a symbol-macro with appropriate magic when you dereference it or setf it. Only the new variable with new semantics is handled by the new search procedure. Complex and still introduces subtle semantic issues. @end enumerate I've been suggested the below features, but have rejected them, for the sake of keeping ASDF no more complex than strictly necessary. @itemize @item More syntactic sugar: synonyms for the configuration directives, such as @code{(:add-directory X)} for @code{(:directory X)}, or @code{(:add-directory-hierarchy X)} or @code{(:add-directory X :recurse t)} for @code{(:tree X)}. @item The possibility to register individual files instead of directories. @item Integrate Xach Beane's tilde expander into the parser, or something similar that is shell-friendly or shell-compatible. I'd rather keep ASDF minimal. But maybe this precisely keeps it minimal by removing the need for evaluated entries that ASDF has? i.e. uses of @code{USER-HOMEDIR-PATHNAME} and @code{$SBCL_HOME} Hopefully, these are already superseded by the @code{:default-registry} @item Using the shell-unfriendly syntax @code{/**} instead of TEXINPUTS-like @code{//} to specify recursion down a filesystem tree in the environment variable. It isn't that Lisp friendly either. @end itemize @node TODO, Credits for the source-registry, Rejected ideas, Controlling where ASDF searches for systems @section TODO @itemize @item Add examples @end itemize @node Credits for the source-registry, , TODO, Controlling where ASDF searches for systems @section Credits for the source-registry Thanks a lot to Stelian Ionescu for the initial idea. Thanks to Rommel Martinez for the initial implementation attempt. All bad design ideas and implementation bugs are mine, not theirs. But so are good design ideas and elegant implementation tricks. --- Francois-Rene Rideau @email{fare@@tunes.org}, Mon, 22 Feb 2010 00:07:33 -0500 @node Controlling where ASDF saves compiled files, Error handling, Controlling where ASDF searches for systems, Top @comment node-name, next, previous, up @chapter Controlling where ASDF saves compiled files @cindex asdf-output-translations @vindex ASDF_OUTPUT_TRANSLATIONS Each Common Lisp implementation has its own format for compiled files or fasls.@footnote{``FASL'' is short for ``FASt Loading.''} If you use multiple implementations (or multiple versions of the same implementation), you'll soon find your source directories littered with various @file{fasl}s, @file{dfsl}s, @file{cfsl}s and so on. Worse yet, multiple implementations use the same file extension and some implementations maintain the same file extension while changing formats from version to version (or platform to platform). This can lead to many errors and much confusion as you switch from one implementation to the next. Finally, this requires write access to the source directory, and therefore precludes sharing of a same source code directory between multiple users. Since ASDF 2, ASDF includes the @code{asdf-output-translations} facility to mitigate the problem. @menu * Output Configurations:: * Output Backward Compatibility:: * Output Configuration DSL:: * Output Configuration Directories:: * Output Shell-friendly syntax for configuration:: * Semantics of Output Translations:: * Output Caching Results:: * Output location API:: * Credits for output translations:: @end menu @node Output Configurations, Output Backward Compatibility, Controlling where ASDF saves compiled files, Controlling where ASDF saves compiled files @section Configurations @c FIXME: Explain how configurations work: can't expect reader will have @c looked at previous chapter. Probably cut and paste will do. Configurations specify mappings from input locations to output locations. Once again we rely on the XDG base directory specification for configuration. @xref{Controlling where ASDF searches for systems,,XDG base directory}. @enumerate @item Some hardcoded wrapping output translations configuration may be used. This allows special output translations (or usually, invariant directories) to be specified corresponding to the similar special entries in the source registry. @item An application may explicitly initialize the output-translations configuration using the Configuration API in which case this takes precedence. (@pxref{Controlling where ASDF saves compiled files,,Configuration API}.) It may itself compute this configuration from the command-line, from a script, from its own configuration file, etc. @item The source registry will be configured from the environment variable @code{ASDF_OUTPUT_TRANSLATIONS} if it exists. @item The source registry will be configured from user configuration file @file{$XDG_CONFIG_DIRS/common-lisp/asdf-output-translations.conf} (which defaults to @file{~/.config/common-lisp/asdf-output-translations.conf}) if it exists. @item The source registry will be configured from user configuration directory @file{$XDG_CONFIG_DIRS/common-lisp/asdf-output-translations.conf.d/} (which defaults to @file{~/.config/common-lisp/asdf-output-translations.conf.d/}) if it exists. @item The source registry will be configured from system configuration file @file{/etc/common-lisp/asdf-output-translations.conf} if it exists. @item The source registry will be configured from system configuration directory @file{/etc/common-lisp/asdf-output-translations.conf.d/} if it exists. @end enumerate Each of these configurations is specified as a SEXP in a trivial domain-specific language (@pxref{Configuration DSL}). Additionally, a more shell-friendly syntax is available for the environment variable (@pxref{Shell-friendly syntax for configuration}). When processing an entry in the above list of configuration methods, ASDF will stop unless that entry explicitly or implicitly specifies that it includes its inherited configuration. Note that by default, a per-user cache is used for output files. This allows the seamless use of shared installations of software between several users, and takes files out of the way of the developers when they browse source code, at the expense of taking a small toll when developers have to clean up output files and find they need to get familiar with output-translations first.@footnote{A @code{CLEAN-OP} would be a partial solution to this problem.} @node Output Backward Compatibility, Output Configuration DSL, Output Configurations, Controlling where ASDF saves compiled files @section Backward Compatibility @cindex ASDF-BINARY-LOCATIONS compatibility @c FIXME: Demote this section -- the typical reader doesn't care about @c backwards compatibility. We purposely do @emph{not} provide backward compatibility with earlier versions of @code{ASDF-Binary-Locations} (8 Sept 2009), @code{common-lisp-controller} (7.0) or @code{cl-launch} (2.35), each of which had similar general capabilities. The APIs of these programs were not designed for easy user configuration through configuration files. Recent versions of @code{common-lisp-controller} (7.2) and @code{cl-launch} (3.000) use the new @code{asdf-output-translations} API as defined below. @code{ASDF-Binary-Locations} is fully superseded and not to be used anymore. This incompatibility shouldn't inconvenience many people. Indeed, few people use and customize these packages; these few people are experts who can trivially adapt to the new configuration. Most people are not experts, could not properly configure these features (except inasmuch as the default configuration of @code{common-lisp-controller} and/or @code{cl-launch} might have been doing the right thing for some users), and yet will experience software that ``just works'', as configured by the system distributor, or by default. Nevertheless, if you are a fan of @code{ASDF-Binary-Locations}, we provide a limited emulation mode: @defun enable-asdf-binary-locations-compatibility @Akey{} centralize-lisp-binaries default-toplevel-directory include-per-user-information map-all-source-files source-to-target-mappings This function will initialize the new @code{asdf-output-translations} facility in a way that emulates the behaviour of the old @code{ASDF-Binary-Locations} facility. Where you would previously set global variables @var{*centralize-lisp-binaries*}, @var{*default-toplevel-directory*}, @var{*include-per-user-information*}, @var{*map-all-source-files*} or @var{*source-to-target-mappings*} you will now have to pass the same values as keyword arguments to this function. Note however that as an extension the @code{:source-to-target-mappings} keyword argument will accept any valid pathname designator for @code{asdf-output-translations} instead of just strings and pathnames. @end defun If you insist, you can also keep using the old @code{ASDF-Binary-Locations} (the one available as an extension to load of top of ASDF, not the one built into a few old versions of ASDF), but first you must disable @code{asdf-output-translations} with @code{(asdf:disable-output-translations)}, or you might experience ``interesting'' issues. Also, note that output translation is enabled by default. To disable it, use @code{(asdf:disable-output-translations)}. @node Output Configuration DSL, Output Configuration Directories, Output Backward Compatibility, Controlling where ASDF saves compiled files @section Configuration DSL Here is the grammar of the SEXP DSL for @code{asdf-output-translations} configuration: @verbatim ;; A configuration is single SEXP starting with keyword :source-registry ;; followed by a list of directives. CONFIGURATION := (:output-translations DIRECTIVE ...) ;; A directive is one of the following: DIRECTIVE := ;; INHERITANCE DIRECTIVE: ;; Your configuration expression MUST contain ;; exactly one of either of these: :inherit-configuration | ;; splices inherited configuration (often specified last) :ignore-inherited-configuration | ;; drop inherited configuration (specified anywhere) ;; forward compatibility directive (since ASDF 2.011.4), useful when ;; you want to use new configuration features but have to bootstrap a ;; the newer required ASDF from an older release that doesn't have ;; said features: :ignore-invalid-entries | ;; include a configuration file or directory (:include PATHNAME-DESIGNATOR) | ;; enable global cache in ~/.common-lisp/cache/sbcl-1.0.45-linux-amd64/ ;; or something. :enable-user-cache | ;; Disable global cache. Map / to / :disable-cache | ;; add a single directory to be scanned (no recursion) (DIRECTORY-DESIGNATOR DIRECTORY-DESIGNATOR) ;; use a function to return the translation of a directory designator (DIRECTORY-DESIGNATOR (:function TRANSLATION-FUNCTION)) DIRECTORY-DESIGNATOR := NIL | ; As source: skip this entry. As destination: same as source T | ; as source matches anything, as destination ; maps pathname to itself. ABSOLUTE-COMPONENT-DESIGNATOR ; same as in the source-registry language TRANSLATION-FUNCTION := SYMBOL | ;; symbol naming a function that takes two arguments: ;; the pathname to be translated and the matching ;; DIRECTORY-DESIGNATOR LAMBDA ;; A form which evaluates to a function taking two arguments: ;; the pathname to be translated and the matching ;; DIRECTORY-DESIGNATOR @end verbatim Relative components better be either relative or subdirectories of the path before them, or bust. @c FIXME: the following assumes that the reader is familiar with the use @c of this pattern in logical pathnames, which may not be a reasonable @c assumption. Expand. The last component, if not a pathname, is notionally completed by @file{/**/*.*}. You can specify more fine-grained patterns by using a pathname object as the last component e.g. @file{#p"some/path/**/foo*/bar-*.fasl"} You may use @code{#+features} to customize the configuration file. The second designator of a mapping may be @code{nil}, indicating that files are not mapped to anything but themselves (same as if the second designator was the same as the first). When the first designator is @code{t}, the mapping always matches. When the first designator starts with @code{:root}, the mapping matches any host and device. In either of these cases, if the second designator isn't @code{t} and doesn't start with @code{:root}, then strings indicating the host and pathname are somehow copied in the beginning of the directory component of the source pathname before it is translated. When the second designator is @code{t}, the mapping is the identity. When the second designator starts with @code{:root}, the mapping preserves the host and device of the original pathname. Notably, this allows you to map files to a subdirectory of the whichever directory the file is in. Though the syntax is not quite as easy to use as we'd like, you can have an (source destination) mapping entry such as follows in your configuration file, or you may use @code{enable-asdf-binary-locations-compatibility} with @code{:centralize-lisp-binaries nil} which will do the same thing internally for you: @lisp #.(let ((wild-subdir (make-pathname :directory '(:relative :wild-inferiors))) (wild-file (make-pathname :name :wild :version :wild :type :wild))) `((:root ,wild-subdir ,wild-file) (:root ,wild-subdir :implementation ,wild-file))) @end lisp Starting with ASDF 2.011.4, you can use the simpler: @code{`(:root (:root :**/ :implementation :*.*.*))} @code{:include} statements cause the search to recurse with the path specifications from the file specified. If the @code{translate-pathname} mechanism cannot achieve a desired translation, the user may provide a function which provides the required algorithm. Such a translation function is specified by supplying a list as the second @code{directory-designator} the first element of which is the keyword @code{:function}, and the second element of which is either a symbol which designates a function or a lambda expression. The function designated by the second argument must take two arguments, the first being the pathname of the source file, the second being the wildcard that was matched. When invoked, the function should return the translated pathname. An @code{:inherit-configuration} statement causes the search to recurse with the path specifications from the next configuration in the bulleted list. @xref{Controlling where ASDF saves compiled files,,Configurations}, above. @vindex asdf::*user-cache* @itemize @item @code{:enable-user-cache} is the same as @code{(t :user-cache)}. @item @code{:disable-cache} is the same as @code{(t t)}. @item @code{:user-cache} uses the contents of variable @code{asdf::*user-cache*} which by default is the same as using @code{(:home ".cache" "common-lisp" :implementation)}. @end itemize @node Output Configuration Directories, Output Shell-friendly syntax for configuration, Output Configuration DSL, Controlling where ASDF saves compiled files @section Configuration Directories Configuration directories consist of files, each of which contains a list of directives without any enclosing @code{(:output-translations ...)} form. The files will be sorted by namestring as if by @code{string<} and the lists of directives of these files with be concatenated in order. An implicit @code{:inherit-configuration} will be included at the @emph{end} of the list. System-wide or per-user Common Lisp software distributions such as Debian packages or some future version of @code{clbuild} may then include files such as @file{/etc/common-lisp/asdf-output-translations.conf.d/10-foo.conf} or @file{~/.config/common-lisp/asdf-output-translations.conf.d/10-foo.conf} to easily and modularly register configuration information about software being distributed. The convention is that, for sorting purposes, the names of files in such a directory begin with two digits that determine the order in which these entries will be read. Also, the type of these files must be @file{.conf}, which not only simplifies the implementation by allowing for more portable techniques in finding those files, but also makes it trivial to disable a file, by renaming it to a different file type. Directories may be included by specifying a directory pathname or namestring in an @code{:include} directive, e.g.: @verbatim (:include "/foo/bar/") @end verbatim @node Output Shell-friendly syntax for configuration, Semantics of Output Translations, Output Configuration Directories, Controlling where ASDF saves compiled files @section Shell-friendly syntax for configuration When processing the environment variable @code{ASDF_OUTPUT_TRANSLATIONS}: @itemize @item ASDF will skip to the next configuration if it's an empty string. @item ASDF will @code{READ} the string as an SEXP in the DSL, if it begins with a parenthesis @code{(}. @item Otherwise ASDF will interpret the value as a list of directories (see below). @end itemize In the directory list format, directories should come in pairs, each pair indicating a mapping directive. Entries are separated by a @code{:} (colon) on Unix platforms (including Mac and cygwin), and by a @code{;} (semicolon) on other platforms (mainly, Windows). The magic empty entry, if it comes in what would otherwise be the first entry in a pair, indicates the splicing of inherited configuration; the next entry (if any) then starts a new pair. If the second entry in a pair is empty, it indicates that the directory in the first entry is to be left untranslated (which has the same effect as if the directory had been repeated). For example, @code{"/foo:/bar::/baz:"} means: specify that outputs for things under directory @file{/foo/} are translated to be under @file{/bar/}; then include the inherited configuration; then specify that outputs for things under directory @file{/baz/} are not translated. @node Semantics of Output Translations, Output Caching Results, Output Shell-friendly syntax for configuration, Controlling where ASDF saves compiled files @section Semantics of Output Translations From the specified configuration, a list of mappings is extracted in a straightforward way: mappings are collected in order, recursing through included or inherited configuration as specified. To this list is prepended some implementation-specific mappings, and is appended a global default. The list is then compiled to a mapping table as follows: for each entry, in order, resolve the first designated directory into an actual directory pathname for source locations. If no mapping was specified yet for that location, resolve the second designated directory to an output location directory add a mapping to the table mapping the source location to the output location, and add another mapping from the output location to itself (unless a mapping already exists for the output location). Based on the table, a mapping function is defined, mapping source pathnames to output pathnames: given a source pathname, locate the longest matching prefix in the source column of the mapping table. Replace that prefix by the corresponding output column in the same row of the table, and return the result. If no match is found, return the source pathname. (A global default mapping the filesystem root to itself may ensure that there will always be a match, with same fall-through semantics). @node Output Caching Results, Output location API, Semantics of Output Translations, Controlling where ASDF saves compiled files @section Caching Results The implementation is allowed to either eagerly compute the information from the configurations and file system, or to lazily re-compute it every time, or to cache any part of it as it goes. To explicitly flush any information cached by the system, use the API below. @node Output location API, Credits for output translations, Output Caching Results, Controlling where ASDF saves compiled files @section Output location API The specified functions are exported from package ASDF. @defun initialize-output-translations @Aoptional{} PARAMETER will read the configuration and initialize all internal variables. You may extend or override configuration from the environment and configuration files with the given @var{PARAMETER}, which can be @code{nil} (no configuration override), or a SEXP (in the SEXP DSL), a string (as in the string DSL), a pathname (of a file or directory with configuration), or a symbol (fbound to function that when called returns one of the above). @end defun @defun disable-output-translations will initialize output translations in a way that maps every pathname to itself, effectively disabling the output translation facility. @end defun @defun clear-output-translations undoes any output translation configuration and clears any cache for the mapping algorithm. You might want to call this function (or better, @code{clear-configuration}) before you dump an image that would be resumed with a different configuration, and return an empty configuration. Note that this does not include clearing information about systems defined in the current image, only about where to look for systems not yet defined. @end defun @defun ensure-output-translations @Aoptional{} PARAMETER checks whether output translations have been initialized. If not, initialize them with the given @var{PARAMETER}. This function will be called before any attempt to operate on a system. @end defun @defun apply-output-translations PATHNAME Applies the configured output location translations to @var{PATHNAME} (calls @code{ensure-output-translations} for the translations). @end defun Every time you use ASDF's @code{output-files}, or anything that uses it (that may compile, such as @code{operate}, @code{perform}, etc.), @code{ensure-output-translations} is called with parameter @code{nil}, which the first time around causes your configuration to be read. If you change a configuration file, you need to explicitly @code{initialize-output-translations} again, or maybe @code{clear-output-translations} (or @code{clear-configuration}), which will cause the initialization to happen next time around. @node Credits for output translations, , Output location API, Controlling where ASDF saves compiled files @section Credits for output translations Thanks a lot to Peter van Eynde for @code{Common Lisp Controller} and to Bjorn Lindberg and Gary King for @code{ASDF-Binary-Locations}. All bad design ideas and implementation bugs are to mine, not theirs. But so are good design ideas and elegant implementation tricks. --- Francois-Rene Rideau @email{fare@@tunes.org} @c @section Default locations @c @findex output-files-for-system-and-operation @c The default binary location for each Lisp implementation @c is a subdirectory of each source directory. @c To account for different Lisps, Operating Systems, Implementation versions, @c and so on, ASDF borrows code from SLIME @c to create reasonable custom directory names. @c Here are some examples: @c @itemize @c @item @c SBCL, version 1.0.45 on Mac OS X for Intel: @code{sbcl-1.0.45-darwin-x86} @c @item @c Franz Allegro, version 8.0, ANSI Common Lisp: @code{allegro-8.0a-macosx-x86} @c @item @c Franz Allegro, version 8.1, Modern (case sensitive) Common Lisp: @code{allegro-8.1m-macosx-x86} @c @end itemize @c By default, all output file pathnames will be relocated @c to some thus-named subdirectory of @file{~/.cache/common-lisp/}. @c See the document @file{README.asdf-output-translations} @c for a full specification on how to configure @code{asdf-output-translations}. @node Error handling, Miscellaneous additional functionality, Controlling where ASDF saves compiled files, Top @comment node-name, next, previous, up @chapter Error handling @tindex system-definition-error @tindex operation-error @section ASDF errors If ASDF detects an incorrect system definition, it will signal a generalised instance of @code{system-definition-error}. Operations may go wrong (for example when source files contain errors). These are signalled using generalised instances of @code{operation-error}. @section Compilation error and warning handling @vindex *compile-file-warnings-behaviour* @vindex *compile-file-failure-behaviour* ASDF checks for warnings and errors when a file is compiled. The variables @var{*compile-file-warnings-behaviour*} and @var{*compile-file-failure-behaviour*} control the handling of any such events. The valid values for these variables are @code{:error}, @code{:warn}, and @code{:ignore}. @node Miscellaneous additional functionality, Getting the latest version, Error handling, Top @comment node-name, next, previous, up @chapter Miscellaneous additional functionality ASDF includes several additional features that are generally useful for system definition and development. @menu * Controlling file compilation:: * Controlling source file character encoding:: * Miscellaneous Functions:: * Some Utility Functions:: @end menu @node Controlling file compilation, Controlling source file character encoding, Miscellaneous additional functionality, Miscellaneous additional functionality @section Controlling file compilation @cindex :around-compile @cindex around-compile keyword @cindex compile-check keyword @cindex :compile-check @findex compile-file* @c FIXME: Needs rewrite. Start with motivation -- why are we doing @c this? (there is some, but it's buried). Also, all of a sudden in @c the middle of the discussion we start talking about a "hook," which @c is confusing. When declaring a component (system, module, file), you can specify a keyword argument @code{:around-compile function}. If left unspecified (and therefore unbound), the value will be inherited from the parent component if any, or with a default of @code{nil} if no value is specified in any transitive parent. The argument must be either @code{nil}, an fbound symbol, a lambda-expression (e.g. @code{(lambda (thunk) ...(funcall thunk ...) ...)}) a function object (e.g. using @code{#.#'} but that's discouraged because it prevents the introspection done by e.g. asdf-dependency-grovel), or a string that when @code{read} yields a symbol or a lambda-expression. @code{nil} means the normal compile-file function will be called. A non-nil value designates a function of one argument that will be called with a function that will invoke @code{compile-file*} with various arguments; the around-compile hook may supply additional keyword arguments to pass to that call to @code{compile-file*}. One notable argument that is heeded by @code{compile-file*} is @code{:compile-check}, a function called when the compilation was otherwise a success, with the same arguments as @code{compile-file}; the function shall return true if the compilation and its resulting compiled file respected all system-specific invariants, and false (@code{nil}) if it broke any of those invariants; it may issue warnings or errors before it returns @code{nil}. (NB: The ability to pass such extra flags is only available starting with ASDF 2.22.3.) This feature is notably exercised by asdf-finalizers. By using a string, you may reference a function, symbol and/or package that will only be created later during the build, but isn't yet present at the time the defsystem form is evaluated. However, if your entire system is using such a hook, you may have to explicitly override the hook with @code{nil} for all the modules and files that are compiled before the hook is defined. Using this hook, you may achieve such effects as: locally renaming packages, binding @var{*readtables*} and other syntax-controlling variables, handling warnings and other conditions, proclaiming consistent optimization settings, saving code coverage information, maintaining meta-data about compilation timings, setting gensym counters and PRNG seeds and other sources of non-determinism, overriding the source-location and/or timestamping systems, checking that some compile-time side-effects were properly balanced, etc. Note that there is no around-load hook. This is on purpose. Some implementations such as ECL, GCL or MKCL link object files, which allows for no such hook. Other implementations allow for concatenating FASL files, which doesn't allow for such a hook either. We aim to discourage something that's not portable, and has some dubious impact on performance and semantics even when it is possible. Things you might want to do with an around-load hook are better done around-compile, though it may at times require some creativity (see e.g. the @code{package-renaming} system). @node Controlling source file character encoding, Miscellaneous Functions, Controlling file compilation, Miscellaneous additional functionality @section Controlling source file character encoding Starting with ASDF 2.21, components accept a @code{:encoding} option so authors may specify which character encoding should be used to read and evaluate their source code. When left unspecified, the encoding is inherited from the parent module or system; if no encoding is specified at any point, or if @code{nil} is explicitly specified, an extensible protocol described below is followed, that ultimately defaults to @code{:utf-8} since ASDF 3. The protocol to determine the encoding is to call the function @code{detect-encoding}, which itself, if provided a valid file, calls the function specified by @var{*encoding-detection-hook*}, or else defaults to the @var{*default-encoding*}. The @var{*encoding-detection-hook*} is by default bound to function @code{always-default-encoding}, that always returns the contents of @var{*default-encoding*}. @var{*default-encoding*} is bound to @code{:utf-8} by default (before ASDF 3, the default was @code{:default}). Whichever encoding is returned must be a portable keyword, that will be translated to an implementation-specific external-format designator by function @code{encoding-external-format}, which itself simply calls the function specified @var{*encoding-external-format-hook*}; that function by default is @code{default-encoding-external-format}, that only recognizes @code{:utf-8} and @code{:default}, and translates the former to the implementation-dependent @var{*utf-8-external-format*}, and the latter to itself (that itself is portable but has an implementation-dependent meaning). In other words, there now are plenty of extension hooks, but by default ASDF enforces the previous @emph{de facto} standard behaviour of using @code{:utf-8}, independently from whatever configuration the user may be using. Thus, system authors can now rely on @code{:utf-8} being used while compiling their files, even if the user is currently using @code{:koi8-r} or @code{:euc-jp} as their interactive encoding. (Before ASDF 3, there was no such guarantee, @code{:default} was used, and only plain ASCII was safe to include in source code.) Some legacy implementations only support 8-bit characters, and some implementations provide 8-bit only variants. On these implementations, the @var{*utf-8-external-format*} gracefully falls back to @code{:default}, and Unicode characters will be read as multi-character mojibake. To detect such situations, UIOP will push the @code{:asdf-unicode} feature on implementations that support Unicode, and you can use reader-conditionalization to protect any @code{:encoding @emph{encoding}} statement, as in @code{#+asdf-unicode :encoding #+asdf-unicode :utf-8}. We recommend that you avoid using unprotected @code{:encoding} specifications until after ASDF 2.21 or later becomes widespread. As of May 2016, all maintained implementations provide ASDF 3.1, so you may prudently start using this and other features without such protection. While it offers plenty of hooks for extension, and one such extension is available (see @code{asdf-encodings} below), ASDF itself only recognizes one encoding beside @code{:default}, and that is @code{:utf-8}, which is the @emph{de facto} standard, already used by the vast majority of libraries that use more than ASCII. On implementations that do not support unicode, the feature @code{:asdf-unicode} is absent, and the @code{:default} external-format is used to read even source files declared as @code{:utf-8}. On these implementations, non-ASCII characters intended to be read as one CL character may thus end up being read as multiple CL characters. In most cases, this shouldn't affect the software's semantics: comments will be skipped just the same, strings with be read and printed with slightly different lengths, symbol names will be accordingly longer, but none of it should matter. But a few systems that actually depend on unicode characters may fail to work properly, or may work in a subtly different way. See for instance @code{lambda-reader}. We invite you to embrace UTF-8 as the encoding for non-ASCII characters starting today, even without any explicit specification in your @file{.asd} files. Indeed, on some implementations and configurations, UTF-8 is already the @code{:default}, and loading your code may cause errors if it is encoded in anything but UTF-8. Therefore, even with the legacy behaviour, non-UTF-8 is guaranteed to break for some users, whereas UTF-8 is pretty much guaranteed not to break anywhere (provided you do @emph{not} use a BOM), although it might be read incorrectly on some implementations. @code{:utf-8} has been the default value of @code{*default-encoding*} since ASDF 3. If you need non-standard character encodings for your source code, use the extension system @code{asdf-encodings}, by specifying @code{:defsystem-depends-on ("asdf-encodings")} in your @code{defsystem}. This extension system will register support for more encodings using the @code{*encoding-external-format-hook*} facility, so you can explicitly specify @code{:encoding :latin1} in your @file{.asd} file. Using the @code{*encoding-detection-hook*} it will also eventually implement some autodetection of a file's encoding from an emacs-style @code{-*- mode: lisp ; coding: latin1 -*-} declaration, or otherwise based on an analysis of octet patterns in the file. At this point, @code{asdf-encoding} only supports the encodings that are supported as part of your implementation. Since the list varies depending on implementations, we still recommend you use @code{:utf-8} everywhere, which is the most portable (next to it is @code{:latin1}). Recent versions of Quicklisp include @code{asdf-encodings}; if you're not using it, you may get this extension using git: @kbd{git clone https://gitlab.common-lisp.net/asdf/asdf-encodings.git} or @kbd{git clone git@@gitlab.common-lisp.net:asdf/asdf-encodings.git}. You can also browse the repository on @url{https://gitlab.common-lisp.net/asdf/asdf-encodings}. When you use @code{asdf-encodings}, any @file{.asd} file loaded will use the autodetection algorithm to determine its encoding. If you depend on this detection happening, you should explicitly load @code{asdf-encodings} early in your build. Note that @code{:defsystem-depends-on} cannot be used here: by the time the @code{:defsystem-depends-on} is loaded, the enclosing @code{defsystem} form has already been read. In practice, this means that the @code{*default-encoding*} is usually used for @file{.asd} files. Currently, this defaults to @code{:utf-8}, and you should be safe using Unicode characters in those files. This might matter, for instance, in meta-data about author's names. Otherwise, the main data in these files is component (path)names, and we don't recommend using non-ASCII characters for these, for the result probably isn't very portable. @node Miscellaneous Functions, Some Utility Functions, Controlling source file character encoding, Miscellaneous additional functionality @section Miscellaneous Functions These functions are exported by ASDF for your convenience. @anchor{system-relative-pathname} @defun system-relative-pathname system name @Akey{} type It's often handy to locate a file relative to some system. The @code{system-relative-pathname} function meets this need. It takes two mandatory arguments @var{system} and @var{name} and a keyword argument @var{type}: @var{system} is name of a system, whereas @var{name} and optionally @var{type} specify a relative pathname, interpreted like a component pathname specifier by @code{coerce-pathname}. @xref{Pathname specifiers}. It returns a pathname built from the location of the system's source directory and the relative pathname. For example: @lisp > (asdf:system-relative-pathname 'cl-ppcre "regex.data") #P"/repository/other/cl-ppcre/regex.data" @end lisp @end defun @defun system-source-directory system-designator ASDF does not provide a turnkey solution for locating data (or other miscellaneous) files that are distributed together with the source code of a system. Programmers can use @code{system-source-directory} to find such files. Returns a pathname object. The @var{system-designator} may be a string, symbol, or ASDF system object. @end defun @defun clear-system system-designator It is sometimes useful to force recompilation of a previously loaded system. For these cases, @code{(asdf:clear-system :foo)} will remove the system from the table of currently loaded systems: the next time the system @code{foo} or one that depends on it is re-loaded, @code{foo} will be loaded again.@footnote{Alternatively, you could touch @code{foo.asd} or remove the corresponding fasls from the output file cache.} Note that this does not and cannot undo the previous loading of the system. Common Lisp has no provision for such an operation, and its reliance on irreversible side-effects to global data structures makes such a thing impossible in the general case. If the software being re-loaded is not conceived with hot upgrade in mind, re-loading may cause many errors, warnings or subtle silent problems, as packages, generic function signatures, structures, types, macros, constants, etc. are being redefined incompatibly. It is up to the user to make sure that reloading is possible and has the desired effect. In some cases, extreme measures such as recursively deleting packages, unregistering symbols, defining methods on @code{update-instance-for-redefined-class} and much more are necessary for reloading to happen smoothly. ASDF itself goes to extensive effort to make a hot upgrade possible with respect to its own code. If you want, you can reuse some of its utilities such as @code{uiop:define-package} and @code{uiop:with-upgradability}, and get inspiration (or disinspiration) from what it does in @file{header.lisp} and @file{upgrade.lisp}. @end defun @defun register-preloaded-system name @Arest{} keys @Akey{} version @AallowOtherKeys{} A system with name @var{name}, created by @code{make-instance} with extra keys @var{keys} (e.g. @code{:version}), is registered as @emph{preloaded}. If @var{version} is @code{t} (default), then the version is copied from the defined system of the same name (if registered) or else is @code{nil} (this automatic copy of version is only available starting since ASDF 3.1.8). A preloaded system is considered as having already been loaded into the current image, and if at some point some other system @code{:depends-on} it yet no source code is found, it is considered as already provided, and ASDF will not raise a @code{missing-component} error. This function is particularly useful if you distribute your code as fasls with either @code{compile-bundle-op} or @code{monolithic-compile-bundle-op}, and want to register systems so that dependencies will work uniformly whether you're using your software from source or from fasl. Note that if the system was already defined or loaded from source code, its build information will remain active until you call @code{clear-system} on it, at which point a system without build information will be registered in its place. @end defun @defun register-immutable-system name @Arest{} keys A system with name @var{name} is registered as preloaded, and additionally is marked as @emph{immutable}: that is, attempts to compile or load it will be succeed without actually reading, creating or loading any file, as if the system was passed as a @code{force-not} argument to all calls to @code{plan} or @code{operate}. There will be no search for an updated @file{.asd} file to override the loaded version, whether from the source-register or any other method. If a @var{version} keyword argument is specified as @code{t} or left unspecified, then the version is copied from the defined system of the same name (if registered) or else is @code{nil}. This automatic copy of version is available starting since immutable systems have been available in ASDF 3.1.5. This function, available since ASDF 3.1.5, is particularly useful if you distribute a large body of code as a precompiled image, and want to allow users to extend the image with further extension systems, but without making thousands of filesystem requests looking for inexistent (or worse, out of date) source code for all the systems that came bundled with the image but aren't distributed as source code to regular users. @cindex immutable systems @end defun @defun run-shell-command control-string @Arest{} args This function is obsolete and present only for the sake of backwards-compatibility: ``If it's not backwards, it's not compatible''. We @emph{strongly} discourage its use. Its current behaviour is only well-defined on Unix platforms (which include MacOS X and cygwin). On Windows, anything goes. The following documentation is only for the purpose of your migrating away from it in a way that preserves semantics. Instead we recommend the use @code{run-program}, described in the next section, and available as part of ASDF since ASDF 3. @code{run-shell-command} takes as arguments a format @code{control-string} and arguments to be passed to @code{format} after this control-string to produce a string. This string is a command that will be evaluated with a POSIX shell if possible; yet, on Windows, some implementations will use CMD.EXE, while others (like SBCL) will make an attempt at invoking a POSIX shell (and fail if it is not present). @end defun @node Some Utility Functions, , Miscellaneous Functions, Miscellaneous additional functionality @section Some Utility Functions The below functions are not exported by ASDF itself, but by UIOP, available since ASDF 3. Some of them have precursors in ASDF 2, but we recommend that for active developments, you should rely on the package UIOP as included in ASDF 3. UIOP provides many, many more utility functions, and we recommend you read its @file{README.md} and sources for more information. @defun parse-unix-namestring name @Akey{} type defaults dot-dot ensure-directory @AallowOtherKeys Coerce @var{name} into a @var{pathname} using standard Unix syntax. Unix syntax is used whether or not the underlying system is Unix; on non-Unix systems it is only usable for relative pathnames. In order to manipulate relative pathnames portably, it is crucial to possess a portable pathname syntax independent of the underlying OS. This is what @code{parse-unix-namestring} provides, and why we use it in ASDF. When given a @code{pathname} object, just return it untouched. When given @code{nil}, just return @code{nil}. When given a non-null @code{symbol}, first downcase its name and treat it as a string. When given a @code{string}, portably decompose it into a pathname as below. @code{#\/} separates directory components. The last @code{#\/}-separated substring is interpreted as follows: 1- If @var{type} is @code{:directory} or @var{ensure-directory} is true, the string is made the last directory component, and its @code{name} and @code{type} are @code{nil}. if the string is empty, it's the empty pathname with all slots @code{nil}. 2- If @var{type} is @code{nil}, the substring is a file-namestring, and its @code{name} and @code{type} are separated by @code{split-name-type}. 3- If @var{type} is a string, it is the given @code{type}, and the whole string is the @code{name}. Directory components with an empty name the name @code{.} are removed. Any directory named @code{..} is read as @var{dot-dot}, which must be one of @code{:back} or @code{:up} and defaults to @code{:back}. @vindex *nil-pathname* @code{host}, @code{device} and @code{version} components are taken from @var{defaults}, which itself defaults to @code{*nil-pathname*}. @code{*nil-pathname*} is also used if @var{defaults} is @code{nil}. No host or device can be specified in the string itself, which makes it unsuitable for absolute pathnames outside Unix. For relative pathnames, these components (and hence the defaults) won't matter if you use @code{merge-pathnames*} but will matter if you use @code{merge-pathnames}, which is an important reason to always use @code{merge-pathnames*}. Arbitrary keys are accepted, and the parse result is passed to @code{ensure-pathname} with those keys, removing @var{type}, @var{defaults} and @var{dot-dot}. When you're manipulating pathnames that are supposed to make sense portably even though the OS may not be Unixish, we recommend you use @code{:want-relative t} so that @code{parse-unix-namestring} will throw an error if the pathname is absolute. @end defun @defun merge-pathnames* specified @Aoptional{} defaults This function is a replacement for @code{merge-pathnames} that uses the host and device from the @var{defaults} rather than the @var{specified} pathname when the latter is a relative pathname. This allows ASDF and its users to create and use relative pathnames without having to know beforehand what are the host and device of the absolute pathnames they are relative to. @end defun @defun subpathname pathname subpath @Akey{} type This function takes a @var{pathname} and a @var{subpath} and a @var{type}. If @var{subpath} is already a @code{pathname} object (not namestring), and is an absolute pathname at that, it is returned unchanged; otherwise, @var{subpath} is turned into a relative pathname with given @var{type} as per @code{parse-unix-namestring} with @code{:want-relative t :type }@var{type}, then it is merged with the @code{pathname-directory-pathname} of @var{pathname}, as per @code{merge-pathnames*}. We strongly encourage the use of this function for portably resolving relative pathnames in your code base. @end defun @defun subpathname* pathname subpath @Akey{} type This function returns @code{nil} if the base @var{pathname} is @code{nil}, otherwise acts like @code{subpathname}. @end defun @defun run-program command @Akey{} ignore-error-status force-shell input output @ error-output if-input-does-not-exist if-output-exists if-error-output-exists @ element-type external-format @AallowOtherKeys @code{run-program} takes a @var{command} argument that is either a list of a program name or path and its arguments, or a string to be executed by a shell. It spawns the command, waits for it to return, verifies that it exited cleanly (unless told not too below), and optionally captures and processes its output. It accepts many keyword arguments to configure its behaviour. @code{run-program} returns three values: the first for the output, the second for the error-output, and the third for the return value. (Beware that before ASDF 3.0.2.11, it didn't handle input or error-output, and returned only one value, the one for the output if any handler was specified, or else the exit code; please upgrade ASDF, or at least UIOP, to rely on the new enhanced behaviour.) @var{output} is its most important argument; it specifies how the output is captured and processed. If it is @code{nil}, then the output is redirected to the null device, that will discard it. If it is @code{:interactive}, then it is inherited from the current process (beware: this may be different from your @var{*standard-output*}, and under SLIME will be on your @code{*inferior-lisp*} buffer). If it is @code{t}, output goes to your current @var{*standard-output*} stream. Otherwise, @var{output} should be a value that is a suitable first argument to @code{slurp-input-stream} (see below), or a list of such a value and keyword arguments. In this case, @code{run-program} will create a temporary stream for the program output; the program output, in that stream, will be processed by a call to @code{slurp-input-stream}, using @var{output} as the first argument (or if it's a list the first element of @var{output} and the rest as keywords). The primary value resulting from that call (or @code{nil} if no call was needed) will be the first value returned by @code{run-program}. E.g., using @code{:output :string} will have it return the entire output stream as a string. And using @code{:output '(:string :stripped t)} will have it return the same string stripped of any ending newline. @var{error-output} is similar to @var{output}, except that the resulting value is returned as the second value of @code{run-program}. @code{t} designates the @var{*error-output*}. Also @code{:output} means redirecting the error output to the output stream, in which case @code{nil} is returned. @var{input} is similar to @var{output}, except that @code{vomit-output-stream} is used, no value is returned, and @code{t} designates the @var{*standard-input*}. @code{element-type} and @code{external-format} are passed on to your Lisp implementation, when applicable, for creation of the output stream. One and only one of the stream slurping or vomiting may or may not happen in parallel in parallel with the subprocess, depending on options and implementation, and with priority being given to output processing. Other streams are completely produced or consumed before or after the subprocess is spawned, using temporary files. @code{force-shell} forces evaluation of the command through a shell, even if it was passed as a list rather than a string. If a shell is used, it is @file{/bin/sh} on Unix or @file{CMD.EXE} on Windows, except on implementations that (erroneously, IMNSHO) insist on consulting @code{$SHELL} like clisp. @code{ignore-error-status} causes @code{run-program} to not raise an error if the spawned program exits in error. Following POSIX convention, an error is anything but a normal exit with status code zero. By default, an error of type @code{subprocess-error} is raised in this case. @code{run-program} works on all platforms supported by ASDF, except Genera. See the source code for more documentation. @end defun @defun slurp-input-stream processor input-stream @Akey{} @code{slurp-input-stream} is a generic function of two arguments, a target object and an input stream, and accepting keyword arguments. Predefined methods based on the target object are as follows: @itemize @item If the object is a function, the function is called with the stream as argument. @item If the object is a cons, its first element is applied to its rest appended by a list of the input stream. @item If the object is an output stream, the contents of the input stream are copied to it. If the @var{linewise} keyword argument is provided, copying happens line by line, and an optional @var{prefix} is printed before each line. Otherwise, copying happen based on a buffer of size @var{buffer-size}, using the specified @var{element-type}. @item If the object is @code{'string} or @code{:string}, the content is captured into a string. Accepted keywords include the @var{element-type} and a flag @var{stripped}, which when true causes any single line ending to be removed as per @code{uiop:stripln}. @item If the object is @code{:lines}, the content is captured as a list of strings, one per line, without line ending. If the @var{count} keyword argument is provided, it is a maximum count of lines to be read. @item If the object is @code{:line}, the content is captured as with @code{:lines} above, and then its sub-object is extracted with the @var{at} argument, which defaults to @code{0}, extracting the first line. A number will extract the corresponding line. See the documentation for @code{uiop:access-at}. @item If the object is @code{:forms}, the content is captured as a list of s-expressions, as read by the Lisp reader. If the @var{count} argument is provided, it is a maximum count of lines to be read. We recommend you control the syntax with such macro as @code{uiop:with-safe-io-syntax}. @item If the object is @code{:form}, the content is captured as with @code{:forms} above, and then its sub-object is extracted with the @var{at} argument, which defaults to @code{0}, extracting the first form. A number will extract the corresponding form. See the documentation for @code{uiop:access-at}. We recommend you control the syntax with such macro as @code{uiop:with-safe-io-syntax}. @end itemize @end defun @node Getting the latest version, FAQ, Miscellaneous additional functionality, Top @comment node-name, next, previous, up @chapter Getting the latest version Decide which version you want. The @code{master} branch is where development happens; its @code{HEAD} is usually OK, including the latest fixes and portability tweaks, but an occasional regression may happen despite our (limited) test suite. The @code{release} branch is what cautious people should be using; it has usually been tested more, and releases are cut at a point where there isn't any known unresolved issue. You may get the ASDF source repository using git: @kbd{git clone https://gitlab.common-lisp.net/asdf/asdf.git} You will find the above referenced tags in this repository. You can also browse the repository on @url{https://gitlab.common-lisp.net/asdf/asdf}. Discussion of ASDF development is conducted on the mailing list (@pxref{Mailing list}). @node FAQ, Ongoing Work, Getting the latest version, Top @comment node-name, next, previous, up @chapter FAQ @menu * Where do I report a bug?:: * Mailing list:: * What has changed between ASDF 1 ASDF 2 and ASDF 3?:: * Issues with installing the proper version of ASDF:: * Issues with configuring ASDF:: * Issues with using and extending ASDF to define systems:: * ASDF development FAQs:: @end menu @node Where do I report a bug?, Mailing list, FAQ, FAQ @section ``Where do I report a bug?'' @cindex bug tracker @cindex gitlab @cindex launchpad ASDF bugs are tracked on common-lisp.net's gitlab:: @url{https://gitlab.common-lisp.net/asdf/asdf/issues}. Previously, we had done bug-tracking on @url{https://launchpad.net/asdf}, but we are now consolidating project management on @code{common-lisp.net}. If you're unsure about whether something is a bug, or for general discussion, use the asdf-devel mailing list (@pxref{Mailing list}). @node Mailing list, What has changed between ASDF 1 ASDF 2 and ASDF 3?, Where do I report a bug?, FAQ @section Mailing list @cindex mailing list Discussion of ASDF development is conducted on the mailing list @kbd{asdf-devel@@common-lisp.net}. @url{http://common-lisp.net/cgi-bin/mailman/listinfo/asdf-devel} @node What has changed between ASDF 1 ASDF 2 and ASDF 3?, Issues with installing the proper version of ASDF, Mailing list, FAQ @section ``What has changed between ASDF 1, ASDF 2, and ASDF 3?'' We released ASDF 2.000 on May 31st 2010, ASDF 3.0.0 on May 15th 2013, ASDF 3.1.2 on May 6th 2014. Releases of ASDF 2 and now ASDF 3 have since then been included in all actively maintained CL implementations that used to bundle ASDF 1, plus many implementations that previously did not. ASDF has been made to work with all actively maintained CL implementations and even a few implementations that are @emph{not} actively maintained. Furthermore, it is possible to upgrade from ASDF 1 to ASDF 2 or ASDF 3 on the fly (though we recommend instead upgrading your implementation or replacing its ASDF module). For this reason, we have stopped supporting ASDF 1 and ASDF 2. If you are using ASDF 1 or ASDF 2 and are experiencing any kind of issues or limitations, we recommend you upgrade to ASDF 3 --- and we explain how to do that. @xref{Loading ASDF}. Note that in the context of compatibility requirements, ASDF 2.27, released on Feb 1st 2013, and further releases up to 2.33, count as pre-releases of ASDF 3, and define the @code{:asdf3} feature, though the first stable release of ASDF 3 was release 3.0.1. Significant new or improved functionality were added in ASDF 3.1; the @code{:asdf3.1} feature is present in recent enough versions to detect this functionality; the first stable release since then was ASDF 3.1.2. New @code{*features*} are only added at major milestones, and the next one will probably be @code{:asdf3.2}. @menu * What are ASDF 1 2 3?:: * How do I detect the ASDF version?:: * ASDF can portably name files in subdirectories:: * Output translations:: * Source Registry Configuration:: * Usual operations are made easier to the user:: * Many bugs have been fixed:: * ASDF itself is versioned:: * ASDF can be upgraded:: * Decoupled release cycle:: * Pitfalls of the transition to ASDF 2:: * Pitfalls of the upgrade to ASDF 3:: * What happened to the bundle operations:: @end menu @node What are ASDF 1 2 3?, How do I detect the ASDF version?, What has changed between ASDF 1 ASDF 2 and ASDF 3?, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection What are ASDF 1, ASDF 2, and ASDF 3? ASDF 1 refers to any release earlier than 1.369 or so (from August 2001 to October 2009), and to any development revision earlier than 2.000 (May 2010). If your copy of ASDF doesn't even contain version information, it's an old ASDF 1. Revisions between 1.656 and 1.728 may count as development releases for ASDF 2. ASDF 2 refers to releases from 2.000 (May 31st 2010) to 2.26 (Oct 30th 2012), and any development revision newer than ASDF 1 and older than 2.27 (Feb 1st 2013). ASDF 3 refers to releases from 2.27 (Feb 1st 2013) to 2.33 and 3.0.0 onward (May 15th 2013). 2.27 to 2.33 count as pre-releases to ASDF 3. ASDF 3.1 refers to releases from 3.1.2 (May 6th 2014) onward. These releases are also considered part of ASDF 3. @node How do I detect the ASDF version?, ASDF can portably name files in subdirectories, What are ASDF 1 2 3?, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection How do I detect the ASDF version? @findex asdf-version @cindex *features* All releases of ASDF push @code{:asdf} onto @code{*features*}. Releases starting with ASDF 2 push @code{:asdf2} onto @code{*features*}. Releases starting with ASDF 3 (including 2.27 and later pre-releases) push @code{:asdf3} onto @code{*features*}. Furthermore, releases starting with ASDF 3.1.2 (May 2014), though they count as ASDF 3, include enough progress that they also push @code{:asdf3.1} onto @code{*features*}. You may depend on the presence or absence of these features to write code that takes advantage of recent ASDF functionality but still works on older versions, or at least detects the old version and signals an error. Additionally, all releases starting with ASDF 2 define a function @code{(asdf:asdf-version)} you may use to query the version. All releases starting with 2.013 display the version number prominently on the second line of the @file{asdf.lisp} source file. If you are experiencing problems or limitations of any sort with ASDF 1 or ASDF 2, we recommend that you should upgrade to the latest release, be it ASDF 3 or other. Finally, here is a code snippet to programmatically determine what version of ASDF is loaded, if any, that works on all versions including very old ones: @lisp (when (find-package :asdf) (let ((ver (symbol-value (or (find-symbol (string :*asdf-version*) :asdf) (find-symbol (string :*asdf-revision*) :asdf))))) (etypecase ver (string ver) (cons (with-output-to-string (s) (loop for (n . m) on ver do (princ n s) (when m (princ "." s))))) (null "1.0")))) @end lisp If it returns @code{nil} then ASDF is not installed. Otherwise it should return a string. If it returns @code{"1.0"}, then it can actually be any version before 1.77 or so, or some buggy variant of 1.x. If it returns anything older than @code{"3.0.1"}, you really need to upgrade your implementation or at least upgrade its ASDF. @xref{Replacing your implementation's ASDF}. @node ASDF can portably name files in subdirectories, Output translations, How do I detect the ASDF version?, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection ASDF can portably name files in subdirectories Common Lisp namestrings are not portable, except maybe for logical pathname namestrings, that themselves have various limitations and require a lot of setup that is itself ultimately non-portable. In ASDF 1, the only portable ways to refer to pathnames inside systems and components were very awkward, using @code{#.(make-pathname ...)} and @code{#.(merge-pathnames ...)}. Even the above were themselves were inadequate in the general case due to host and device issues, unless horribly complex patterns were used. Plenty of simple cases that looked portable actually weren't, leading to much confusion and greavance. ASDF 2 implements its own portable syntax for strings as pathname specifiers. Naming files within a system definition becomes easy and portable again. @xref{Miscellaneous additional functionality,system-relative-pathname}, @code{merge-pathnames*}, @code{coerce-pathname}. On the other hand, there are places where systems used to accept namestrings where you must now use an explicit pathname object: @code{(defsystem ... :pathname "LOGICAL-HOST:PATH;TO;SYSTEM;" ...)} must now be written with the @code{#p} syntax: @code{(defsystem ... :pathname #p"LOGICAL-HOST:PATH;TO;SYSTEM;" ...)}. We recommend against using pathname objects in general and logical pathnames in particular. Your code will be much more portable using ASDF's pathname specifiers. @xref{Pathname specifiers}. @node Output translations, Source Registry Configuration, ASDF can portably name files in subdirectories, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection Output translations A popular feature added to ASDF was output pathname translation: @code{asdf-binary-locations}, @code{common-lisp-controller}, @code{cl-launch} and other hacks were all implementing it in ways both mutually incompatible and difficult to configure. Output pathname translation is essential to share source directories of portable systems across multiple implementations or variants thereof, or source directories of shared installations of systems across multiple users, or combinations of the above. In ASDF 2, a standard mechanism is provided for that, @code{asdf-output-translations}, with sensible defaults, adequate configuration languages, a coherent set of configuration files and hooks, and support for non-Unix platforms. @xref{Controlling where ASDF saves compiled files}. @node Source Registry Configuration, Usual operations are made easier to the user, Output translations, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection Source Registry Configuration Configuring ASDF used to require special magic to be applied just at the right moment, between the moment ASDF is loaded and the moment it is used, in a way that is specific to the user, the implementation he is using and the application he is building. This made for awkward configuration files and startup scripts that could not be shared between users, managed by administrators or packaged by distributions. ASDF 2 provides a well-documented way to configure ASDF, with sensible defaults, adequate configuration languages, and a coherent set of configuration files and hooks. We believe it's a vast improvement because it decouples application distribution from library distribution. The application writer can avoid thinking where the libraries are, and the library distributor (dpkg, clbuild, advanced user, etc.) can configure them once and for every application. Yet settings can be easily overridden where needed, so whoever needs control has exactly as much as required. At the same time, ASDF 2 remains compatible with the old magic you may have in your build scripts (using @code{*central-registry*} and @code{*system-definition-search-functions*}) to tailor the ASDF configuration to your build automation needs, and also allows for new magic, simpler and more powerful magic. @xref{Controlling where ASDF searches for systems}. @node Usual operations are made easier to the user, Many bugs have been fixed, Source Registry Configuration, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection Usual operations are made easier to the user In ASDF 1, you had to use the awkward syntax @code{(asdf:oos 'asdf:load-op :foo)} to load a system, and similarly for @code{compile-op}, @code{test-op}. In ASDF 2 and later, you can use shortcuts for the usual operations: @code{(asdf:load-system :foo)}, and similarly for @code{compile-system}, @code{test-system}. @node Many bugs have been fixed, ASDF itself is versioned, Usual operations are made easier to the user, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection Many bugs have been fixed The following issues and many others have been fixed: @itemize @item The infamous TRAVERSE function has been revamped completely between ASDF 1 and ASDF 2, with many bugs squashed. In particular, dependencies were not correctly propagated across modules but now are. It has been completely rewritten many times over between ASDF 2.000 and ASDF 3, with fundamental issues in the original model being fixed. Timestamps were not propagated at all, and now are. The internal model of how actions depend on each other is now both consistent and complete. As of ASDF 3.3, multiple phases of loading are well supported, wherein correctly interpreting `defsystem` statements in some `.asd` files itself depends on loading other systems, e.g. via `:defsystem-depends-on`. The @code{:version} and the @code{:force (system1 .. systemN)} features have been fixed. @item Performance has been notably improved for large systems (say with thousands of components) by using hash-tables instead of linear search, and linear-time list accumulation instead of cubic time recursive append, for an overall @emph{O(n)} complexity vs @emph{O(n^4)}. @item Many features used to not be portable, especially where pathnames were involved. Windows support was notably quirky because of such non-portability. @item The internal test suite used to massively fail on many implementations. While still incomplete, it now fully passes on all implementations supported by the test suite, though some tests are commented out on a few implementations. @item Support was lacking for some implementations. ABCL and GCL were notably wholly broken. ECL extensions were not integrated with ASDF release. @item The documentation was grossly out of date. @end itemize @node ASDF itself is versioned, ASDF can be upgraded, Many bugs have been fixed, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection ASDF itself is versioned Between new features, old bugs fixed, and new bugs introduced, there were various releases of ASDF in the wild, and no simple way to check which release had which feature set. People using or writing systems had to either make worst-case assumptions as to what features were available and worked, or take great pains to have the correct version of ASDF installed. With ASDF 2 and later, we provide a new stable set of working features that everyone can rely on from now on. Use @code{#+asdf2}, @code{#+asdf3}, @code{#+asdf3.1} or @code{#+asdf3.3} to detect presence of relevant versions of ASDF and their features, or @code{(asdf:version-satisfies (asdf:asdf-version) "2.345.67")} to check the availability of a version no earlier than required. @node ASDF can be upgraded, Decoupled release cycle, ASDF itself is versioned, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection ASDF can be upgraded When an old version of ASDF was loaded, it was very hard to upgrade ASDF in your current image without breaking everything. Instead you had to exit the Lisp process and somehow arrange to start a new one from a simpler image. Something that can't be done from within Lisp, making automation of it difficult, which compounded with difficulty in configuration, made the task quite hard. Yet as we saw before, the task would have been required to not have to live with the worst case or non-portable subset of ASDF features. With ASDF 2, it is easy to upgrade from ASDF 2 to later versions from within Lisp, and not too hard to upgrade from ASDF 1 to ASDF 2 from within Lisp. We support hot upgrade of ASDF and any breakage is a bug that we will do our best to fix. There are still limitations on upgrade, though, most notably the fact that after you upgrade ASDF, you must also reload or upgrade all ASDF extensions. @node Decoupled release cycle, Pitfalls of the transition to ASDF 2, ASDF can be upgraded, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection Decoupled release cycle When vendors were releasing their Lisp implementations with ASDF, they had to basically never change version because neither upgrade nor downgrade was possible without breaking something for someone, and no obvious upgrade path was visible and recommendable. With ASDF 2, upgrade is possible, easy and can be recommended. This means that vendors can safely ship a recent version of ASDF, confident that if a user isn't fully satisfied, he can easily upgrade ASDF and deal with a supported recent version of it. This means that release cycles will be causally decoupled, the practical consequence of which will mean faster convergence towards the latest version for everyone. @node Pitfalls of the transition to ASDF 2, Pitfalls of the upgrade to ASDF 3, Decoupled release cycle, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection Pitfalls of the transition to ASDF 2 The main pitfalls in upgrading to ASDF 2 seem to be related to the output translation mechanism. @itemize @item Output translations is enabled by default. This may surprise some users, most of them in pleasant way (we hope), a few of them in an unpleasant way. It is trivial to disable output translations. @xref{FAQ,,``How can I wholly disable the compiler output cache?''}. @item Some systems in the large have been known not to play well with output translations. They were relatively easy to fix. Once again, it is also easy to disable output translations, or to override its configuration. @item The new ASDF output translations are incompatible with ASDF-Binary-Locations. They replace A-B-L, and there is compatibility mode to emulate your previous A-B-L configuration. See @code{enable-asdf-binary-locations-compatibility} in @pxref{Controlling where ASDF saves compiled files,,Backward Compatibility}. But thou shalt not load ABL on top of ASDF 2. @end itemize Other issues include the following: @itemize @item ASDF pathname designators are now specified in places where they were unspecified, and a few small adjustments have to be made to some non-portable defsystems. Notably, in the @code{:pathname} argument to a @code{defsystem} and its components, a logical pathname (or implementation-dependent hierarchical pathname) must now be specified with @code{#p} syntax where the namestring might have previously sufficed; moreover when evaluation is desired @code{#.} must be used, where it wasn't necessary in the toplevel @code{:pathname} argument (but necessary in other @code{:pathname} arguments). @item There is a slight performance bug, notably on SBCL, when initially searching for @file{asd} files, the implicit @code{(directory "/configured/path/**/*.asd")} for every configured path @code{(:tree "/configured/path/")} in your @code{source-registry} configuration can cause a slight pause. Try to @code{(time (asdf:initialize-source-registry))} to see how bad it is or isn't on your system. If you insist on not having this pause, you can avoid the pause by overriding the default source-registry configuration and not use any deep @code{:tree} entry but only @code{:directory} entries or shallow @code{:tree} entries. Or you can fix your implementation to not be quite that slow when recursing through directories. @emph{Update}: This performance bug fixed the hard way in 2.010. @item On Windows, only LispWorks supports proper default configuration pathnames based on the Windows registry. Other implementations make do with environment variables, that you may have to define yourself if you're using an older version of Windows. Windows support is somewhat less tested than Unix support. Please help report and fix bugs. @emph{Update}: As of ASDF 2.21, all implementations should now use the same proper default configuration pathnames and they should actually work, though they haven't all been tested. @item The mechanism by which one customizes a system so that Lisp files may use a different extension from the default @file{.lisp} has changed. Previously, the pathname for a component was lazily computed when operating on a system, and you would @code{(defmethod source-file-type ((component cl-source-file) (system (eql (find-system 'foo)))) (declare (ignorable component system)) "lis")}. Now, the pathname for a component is eagerly computed when defining the system, and instead you will @code{(defclass cl-source-file.lis (cl-source-file) ((type :initform "lis")))} and use @code{:default-component-class cl-source-file.lis} as argument to @code{defsystem}, as detailed in a @pxref{FAQ,How do I create a system definition where all the source files have a .cl extension?} below. @code{source-file-type} is deprecated. To access a component's file-type, use @code{file-type}, instead. @code{source-file-type} will be removed. @findex source-file-type @findex file-type @end itemize @node Pitfalls of the upgrade to ASDF 3, What happened to the bundle operations, Pitfalls of the transition to ASDF 2, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection Pitfalls of the upgrade to ASDF 3 While ASDF 3 is largely compatible with ASDF 2, there are a few pitfalls when upgrading from ASDF 2, due to limitations in ASDF 2. @itemize @item ASDF 2 was designed so it could be upgraded; but upgrading it required a special setup at the beginning of your build files. Failure to upgrade it early could result in catastrophic attempt to self-upgrade in mid-build. @item Starting with ASDF 3 (2.27 or later), ASDF will automatically attempt to upgrade itself as the first step before any system operation, to avoid any possibility of such catastrophic mid-build self-upgrade. But that doesn't help if your old implementation still provides ASDF 2. @item It was unsafe in ASDF 2 for a system definition to declare a dependency on ASDF, since it could trigger such catastrophe for users who were not carefully configured. If you declare a dependency on a recent enough ASDF, yet want to be nice with these potentially misconfigured users, we recommend that you not only specify a recent ASDF in your dependencies with @code{:depends-on ((:version "asdf" "3.1.2"))}, but that you @emph{also} check that ASDF 3 is installed, or else the upgrade catastrophe might happen before that specification is checked, by starting your @file{.asd} file with a version check as follows: @example #-asdf3 (error "@var{MY-SYSTEM} requires ASDF 3.1.2") @end example @item When you upgrade from too old a version of ASDF, previously loaded ASDF extensions become invalid, and will need to be reloaded. Example extensions include CFFI-Grovel, hacks used by ironclad, etc. Since it isn't possible to automatically detect what extensions need to be invalidated and what systems use them, ASDF will invalidate @emph{all} previously loaded systems when it is loaded on top of a forward-incompatible ASDF version. @footnote{ @vindex *oldest-forward-compatible-asdf-version* Forward incompatibility can be determined using the variable @code{asdf/upgrade::*oldest-forward-compatible-asdf-version*}, which is 2.33 at the time of this writing.} @item To write a portable build script, you need to rely on a recent version of UIOP, but until you have ensured a recent ASDF is loaded, you can't rely on UIOP being present, and thus must manually avoid all the pathname pitfalls when loading ASDF itself. @item Bugs in CMUCL and XCL prevent upgrade of ASDF from an old forward-incompatible version. Happily, CMUCL comes with a recent ASDF, and XCL is more of a working demo than something you'd use seriously anyway. @item For the above reasons, your build and startup scripts should load ASDF 3, configure it, and upgrade it, among the very first things they do. They should ensure that only ASDF 3 or later is used indeed, and error out if ASDF 2 or earlier was used. @item Now that (since May 2016) all maintained implementations (i.e. having had at least one release since 2014, or a commit on their public source code repository) provide ASDF 3.1 or later, the simple solution is just to use code as below in your setup, and when it fails, upgrade your implementation or replace its ASDF. (@pxref{Replacing your implementation's ASDF}): @example (require "asdf") #-asdf3.1 (error "ASDF 3.1 or bust") @end example @item For scripts that try to use ASDF simply via @code{require} at first, and make heroic attempts to load it the hard way if at first they don't succeed, see @file{tools/load-asdf.lisp} distributed with the ASDF source repository, or the code of @url{https://cliki.net/cl-launch,@code{cl-launch}}. @item @anchor{reinitializeASDFAfterUpgrade} Note that in addition to the pitfalls and constraints above, these heroic scripts (should you wish to write or modify one), must take care to configure ASDF @emph{twice}. A first time, right after you load the old ASDF 2 (or 1!) and before you upgrade to the new ASDF 3, so it may find where you put ASDF 3. A second time, because most implementations can't handle a smooth upgrade from ASDF 2 to ASDF 3, so ASDF 3 doesn't try (anymore) and loses any configuration from ASDF 2. @lisp (ignore-errors (funcall 'require "asdf")) ;; <--- try real hard ;; <--- insert heroics here, if that failed to provide ASDF 2 or 3 ;; <--- insert configuration here, if that succeeded (asdf:load-system "asdf") ;; <--- re-configure here, too, in case at first you got ASDF 2 @end lisp @end itemize @node What happened to the bundle operations, , Pitfalls of the upgrade to ASDF 3, What has changed between ASDF 1 ASDF 2 and ASDF 3? @subsection What happened to the bundle operations? @tindex fasl-op (obsolete) @tindex load-fasl-op (obsolete) @tindex binary-op (obsolete) @tindex monolithic-fasl-op (obsolete) @tindex monolithic-load-fasl-op (obsolete) @tindex monolithic-binary-op (obsolete) @tindex compile-bundle-op @tindex load-bundle-op @tindex deliver-asd-op @tindex monolithic-compile-bundle-op @tindex monolithic-load-bundle-op @tindex monolithic-deliver-asd-op @code{asdf-ecl} and its short-lived successor @code{asdf-bundle} are no more, having been replaced by code now built into ASDF 3. Moreover, the name of the bundle operations has changed since ASDF 3.1.3. Starting with ASDF 3.2.0, @code{load-system} will once again use @code{load-bundle-op} instead of @code{load-op} on ECL, as originally intended by @code{asdf-ecl} authors, but disabled for a long time due to bugs in both ECL and ASDF. Note that some of the bundle operations were renamed after ASDF 3.1.3, and the old names have been removed. Old bundle operations, and their modern equivalents are: @itemize @item @code{fasl-op} is now @code{compile-bundle-op} @item @code{load-fasl-op} is now @code{load-bundle-op} @item @code{binary-op} is now @code{deliver-asd-op} @item @code{monolithic-fasl-op} is now @code{monolithic-compile-bundle-op} @item @code{monolithic-load-fasl-op} is now @code{monolithic-load-bundle-op} @item @code{monolithic-binary-op} is now @code{monolithic-deliver-asd-op} @end itemize @node Issues with installing the proper version of ASDF, Issues with configuring ASDF, What has changed between ASDF 1 ASDF 2 and ASDF 3?, FAQ @section Issues with installing the proper version of ASDF @menu * My Common Lisp implementation comes with an outdated version of ASDF. What to do?:: * I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?:: * After upgrading ASDF, ASDF (and Quicklisp) can't find my systems: After upgrading ASDF. @end menu @node My Common Lisp implementation comes with an outdated version of ASDF. What to do?, I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?, Issues with installing the proper version of ASDF, Issues with installing the proper version of ASDF @subsection ``My Common Lisp implementation comes with an outdated version of ASDF. What to do?'' If you have a recent implementation, it should already come with ASDF 3 or later. If you need a more recent version than is provided, we recommend you simply upgrade ASDF by installing a recent version in a path configured in your source-registry. @xref{Upgrading ASDF}. If you have an old implementation that does not provide ASDF 3, we recommend you replace your implementation's ASDF. @xref{Replacing your implementation's ASDF}. @node I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?, After upgrading ASDF, My Common Lisp implementation comes with an outdated version of ASDF. What to do?, Issues with installing the proper version of ASDF @subsection ``I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?'' Since ASDF 2, it should always be a good time to upgrade to a recent version of ASDF. You may consult with the maintainer for which specific version they recommend, but the latest @code{release} should be correct. Though we do try to test ASDF releases against all implementations that we can, we may not be testing against all variants of your implementation, and we may not be running enough tests; we trust you to thoroughly test it with your own implementation before you release it. If there are any issues with the current release, it's a bug that you should report upstream and that we will fix ASAP. As to how to include ASDF, we recommend the following: @itemize @item If ASDF isn't loaded yet, then @code{(require "asdf")} should load the version of ASDF that is bundled with your system. If possible so should @code{(require "ASDF")}. You may have it load some other version configured by the user, if you allow such configuration. @item If your system provides a mechanism to hook into @code{cl:require}, then it would be nice to add ASDF to this hook the same way that ABCL, CCL, CLISP, CMUCL, ECL, SBCL and SCL do it. Please send us appropriate code to this end. @item You may, like SBCL since 1.1.13 or MKCL since 1.1.9, have ASDF create bundle FASLs that are provided as modules by your Lisp distribution. You may also, but we don't recommend that anymore, as in SBCL up until 1.1.12, have ASDF be implicitly used to @code{cl:require} these modules that are provided by your Lisp distribution; if you do, you should add these modules in the beginning of both @code{wrapping-source-registry} and @code{wrapping-output-translations}. @item If you have magic systems as above, like SBCL used to do, then we explicitly ask you to @emph{NOT} distribute @file{asdf.asd} as part of those magic systems. You should still include the file @file{asdf.lisp} in your source distribution and precompile it in your binary distribution, but @file{asdf.asd} if included at all, should be secluded from the magic systems, in a separate file hierarchy. Alternatively, you may provide the system after renaming it and its @file{.asd} file to e.g. @code{asdf-ecl} and @file{asdf-ecl.asd}, or @code{sb-asdf} and @file{sb-asdf.asd}. Indeed, if you made @file{asdf.asd} a magic system, then users would no longer be able to upgrade ASDF using ASDF itself to some version of their preference that they maintain independently from your Lisp distribution. @item If you do not have any such magic systems, or have other non-magic systems that you want to bundle with your implementation, then you may add them to the @code{wrapping-source-registry}, and you are welcome to include @file{asdf.asd} amongst them. Non-magic systems should be at the back of the @code{wrapping-source-registry} while magic systems are at the front. If they are precompiled, they should also be in the @code{wrapping-output-translations}. @item Since ASDF 3, the library UIOP comes transcluded in ASDF. But if you want to be nice to users who care for UIOP but not for ASDF, you may package UIOP separately, so that one may @code{(require "uiop")} and not load ASDF, or one may @code{(require "asdf")} which would implicitly require and load the former. @item Please send us upstream any patches you make to ASDF itself, so we can merge them back in for the benefit of your users when they upgrade to the upstream version. @end itemize @node After upgrading ASDF, , I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?, Issues with installing the proper version of ASDF @subsection After upgrading ASDF, ASDF (and Quicklisp) can't find my systems @vindex *central-registry* @cindex Quicklisp When you upgrade the ASDF running in your Lisp image from an ancient ASDF 2 or older to ASDF 3 or newer, then you may have to re-configure ASDF. If your configuration only consists in using the source-registry and output-translations (as it should), and if you are not explicitly calling @code{asdf:initialize-source-registry} or @code{asdf:initialize-output-translations} with a non-nil argument, then ASDF will reconfigure itself. Otherwise, you will have to configure ASDF 2 (or older) to find ASDF 3, then configure ASDF 3. Notably, @var{*central-registry*} is not maintained across upgrades from ASDF 2. @xref{reinitializeASDFAfterUpgrade,note about ASDF reconfiguration after upgrade}. Problems like this may be experienced if one loads Quicklisp (which as of this writing bundles an obsolete ASDF version 2.26), upgrades ASDF, and then tries to load new systems. The correct solution is to load the most up-to-date ASDF you can, @emph{then} configure it, @emph{then} load Quicklisp and any other extension. Do @emph{not} try to upgrade from ASDF 2 @emph{after} loading Quicklisp, for it will leave both ASDF and Quicklisp badly misconfigured. For details see the discussion at the above cross-reference. Also, if you are experiencing such failures due to Quicklisp shipping an ancient ASDF, please complain to Zach Beane about it. @node Issues with configuring ASDF, Issues with using and extending ASDF to define systems, Issues with installing the proper version of ASDF, FAQ @section Issues with configuring ASDF @menu * How can I customize where fasl files are stored?:: * How can I wholly disable the compiler output cache?:: * How can I debug problems finding ASDF systems:: @end menu @node How can I customize where fasl files are stored?, How can I wholly disable the compiler output cache?, Issues with configuring ASDF, Issues with configuring ASDF @subsection ``How can I customize where fasl files are stored?'' @xref{Controlling where ASDF saves compiled files}. Note that in the past there was an add-on to ASDF called @code{ASDF-binary-locations}, developed by Gary King. That add-on has been merged into ASDF proper, then superseded by the @code{asdf-output-translations} facility. Note that use of @code{asdf-output-translations} can interfere with one aspect of your systems --- if your system uses @code{*load-truename*} to find files (e.g., if you have some data files stored with your program), then the relocation that this ASDF customization performs is likely to interfere. Use @code{asdf:system-relative-pathname} to locate a file in the source directory of some system, and use @code{asdf:apply-output-translations} to locate a file whose pathname has been translated by the facility. @node How can I wholly disable the compiler output cache?, How can I debug problems finding ASDF systems, How can I customize where fasl files are stored?, Issues with configuring ASDF @subsection ``How can I wholly disable the compiler output cache?'' To permanently disable the compiler output cache for all future runs of ASDF, you can: @example mkdir -p ~/.config/common-lisp/asdf-output-translations.conf.d/ echo ':disable-cache' > \ ~/.config/common-lisp/asdf-output-translations.conf.d/99-disable-cache.conf @end example This assumes that you didn't otherwise configure the ASDF files (if you did, edit them again), and don't somehow override the configuration at runtime with a shell variable (see below) or some other runtime command (e.g. some call to @code{asdf:initialize-output-translations}). To disable the compiler output cache in Lisp processes run by your current shell, try (assuming @code{bash} or @code{zsh}) (on Unix and cygwin only): @example export ASDF_OUTPUT_TRANSLATIONS=/: @end example To disable the compiler output cache just in the current Lisp process, use (after loading ASDF but before using it): @example (asdf:disable-output-translations) @end example Note that this does @emph{NOT} belong in a @file{.asd} file. Please do not tamper with ASDF configuration from a @file{.asd} file, and only do this from your personal configuration or build scripts. @node How can I debug problems finding ASDF systems, , How can I wholly disable the compiler output cache?, Issues with configuring ASDF @comment node-name, next, previous, up @subsection How can I debug problems finding ASDF systems? Sometimes ASDF will be unable to find and load your systems, although you believe that it should be able to. There are a number of things you can do to debug such issues. @vindex *central-registry* If you are using @code{asdf:*central-registry*} (@pxref{Configuring ASDF to find your systems --- old style}), you can simply look at the pathnames and namestrings in this variable, and use conventional tools such as @code{cl:probe-file} and @code{cl:directory} to poke around and see why your systems are not being found. If you are using one of the newer methods for configuring ASDF's system finding (@pxref{Controlling where ASDF searches for systems}), you can try: @vindex *source-registry* @example (alexandria:hash-table-alist asdf/source-registry::*source-registry*) @end example (alphabetizing the results here may be helpful). Or for a higher-level view: @findex flatten-source-registry @example (asdf/source-registry:flatten-source-registry) @end example Finally, if you use the source registry cache (@pxref{Caching Results}), you can: @example find ~/common-lisp -name .cl-source-registry.cache @end example at the shell. It is still, unfortunately, an open question how to monitor ASDF's interpretation of its source configuration as it happens. @node Issues with using and extending ASDF to define systems, ASDF development FAQs, Issues with configuring ASDF, FAQ @section Issues with using and extending ASDF to define systems @menu * How can I cater for unit-testing in my system?:: * How can I cater for documentation generation in my system?:: * How can I maintain non-Lisp (e.g. C) source files?:: * I want to put my module's files at the top level. How do I do this?:: * How do I create a system definition where all the source files have a .cl extension?:: * How do I mark a source file to be loaded only and not compiled?:: * How do I work with readtables?:: * How can I capture ASDF's output?:: * LOAD-PATHNAME has a weird value:: @end menu @node How can I cater for unit-testing in my system?, How can I cater for documentation generation in my system?, Issues with using and extending ASDF to define systems, Issues with using and extending ASDF to define systems @subsection ``How can I cater for unit-testing in my system?'' ASDF provides a predefined test operation, @code{test-op}. @xref{Predefined operations of ASDF, test-op}. The test operation, however, is largely left to the system definer to specify. @code{test-op} has been a topic of considerable discussion on the @url{http://common-lisp.net/cgi-bin/mailman/listinfo/asdf-devel,asdf-devel mailing list} (@pxref{Mailing list}), and on the @url{https://launchpad.net/asdf,launchpad bug-tracker} (@pxref{Where do I report a bug?}). We provide some guidelines in the discussion of @code{test-op}. @c cut the following because it's discussed in the discussion of test-op. @c Here are some guidelines: @c @itemize @c @item @c For a given system, @var{foo}, you will want to define a corresponding @c test system, such as @var{foo-test}. The reason that you will want this @c separate system is that ASDF does not out of the box supply components @c that are conditionally loaded. So if you want to have source files @c (with the test definitions) that will not be loaded except when testing, @c they should be put elsewhere. @c @item @c The @var{foo-test} system can be defined in an asd file of its own or @c together with @var{foo}. An aesthetic preference against cluttering up @c the filesystem with extra asd files should be balanced against the @c question of whether one might want to directly load @var{foo-test}. @c Typically one would not want to do this except in early stages of @c debugging. @c @item @c Record that testing is implemented by @var{foo-test}. For example: @c @example @c (defsystem @var{foo} @c :in-order-to ((test-op (test-op @var{foo-test}))) @c ....) @c (defsystem @var{foo-test} @c :depends-on (@var{foo} @var{my-test-library} ...) @c ....) @c @end example @c @end itemize @c This procedure will allow you to support users who do not wish to @c install your test framework. @c One oddity of ASDF is that @code{operate} (@pxref{Operations,operate}) @c does not return a value. So in current versions of ASDF there is no @c reliable programmatic means of determining whether or not a set of tests @c has passed, or which tests have failed. The user must simply read the @c console output. This limitation has been the subject of much @c discussion. @node How can I cater for documentation generation in my system?, How can I maintain non-Lisp (e.g. C) source files?, How can I cater for unit-testing in my system?, Issues with using and extending ASDF to define systems @subsection ``How can I cater for documentation generation in my system?'' Various ASDF extensions provide some kind of @code{doc-op} operation. See also @url{https://bugs.launchpad.net/asdf/+bug/479470}. @node How can I maintain non-Lisp (e.g. C) source files?, I want to put my module's files at the top level. How do I do this?, How can I cater for documentation generation in my system?, Issues with using and extending ASDF to define systems @subsection ``How can I maintain non-Lisp (e.g. C) source files?'' See @code{cffi}'s @code{cffi-grovel}. @anchor{report-bugs} @node I want to put my module's files at the top level. How do I do this?, How do I create a system definition where all the source files have a .cl extension?, How can I maintain non-Lisp (e.g. C) source files?, Issues with using and extending ASDF to define systems @subsection ``I want to put my module's files at the top level. How do I do this?'' By default, the files contained in an asdf module go in a subdirectory with the same name as the module. However, this can be overridden by adding a @code{:pathname ""} argument to the module description. For example, here is how it could be done in the spatial-trees ASDF system definition for ASDF 2 or later: @example (asdf:defsystem "spatial-trees" :components ((:module "base" :pathname "" :components ((:file "package") (:file "basedefs" :depends-on ("package")) (:file "rectangles" :depends-on ("package")))) (:module tree-impls :depends-on ("base") :pathname "" :components ((:file "r-trees") (:file "greene-trees" :depends-on ("r-trees")) (:file "rstar-trees" :depends-on ("r-trees")) (:file "rplus-trees" :depends-on ("r-trees")) (:file "x-trees" :depends-on ("r-trees" "rstar-trees")))) (:module viz :depends-on ("base") :pathname "" :components ((:static-file "spatial-tree-viz.lisp"))) (:module tests :depends-on ("base") :pathname "" :components ((:static-file "spatial-tree-test.lisp"))) (:static-file "LICENCE") (:static-file "TODO"))) @end example All of the files in the @code{tree-impls} module are at the top level, instead of in a @file{tree-impls/} subdirectory. Note that the argument to @code{:pathname} can be either a pathname object or a string. A pathname object can be constructed with the @file{#p"foo/bar/"} syntax, but this is discouraged because the results of parsing a namestring are not portable. A pathname can only be portably constructed with such syntax as @code{#.(make-pathname :directory '(:relative "foo" "bar"))}, and similarly the current directory can only be portably specified as @code{#.(make-pathname :directory '(:relative))}. However, as of ASDF 2, you can portably use a string to denote a pathname. The string will be parsed as a @code{/}-separated path from the current directory, such that the empty string @code{""} denotes the current directory, and @code{"foo/bar"} (no trailing @code{/} required in the case of modules) portably denotes the same subdirectory as above. When files are specified, the last @code{/}-separated component is interpreted either as the name component of a pathname (if the component class specifies a pathname type), or as a name component plus optional dot-separated type component (if the component class doesn't specifies a pathname type). @node How do I create a system definition where all the source files have a .cl extension?, How do I mark a source file to be loaded only and not compiled?, I want to put my module's files at the top level. How do I do this?, Issues with using and extending ASDF to define systems @subsection How do I create a system definition where all the source files have a .cl extension? Starting with ASDF 2.014.14, you may just pass the builtin class @code{cl-source-file.cl} as the @code{:default-component-class} argument to @code{defsystem}: @lisp (defsystem my-cl-system :default-component-class cl-source-file.cl ...) @end lisp Another builtin class @code{cl-source-file.lsp} is offered for files ending in @file{.lsp}. If you want to use a different extension for which ASDF doesn't provide builtin support, or want to support versions of ASDF earlier than 2.014.14 (but later than 2.000), you can define a class as follows: @lisp ;; Prologue: make sure we're using a sane package. (defpackage :my-asdf-extension (:use :asdf :common-lisp) (:export #:cl-source-file.lis)) (in-package :my-asdf-extension) (defclass cl-source-file.lis (cl-source-file) ((type :initform "lis"))) @end lisp Then you can use it as follows: @lisp (defsystem my-cl-system :default-component-class my-asdf-extension:cl-source-file.lis ...) @end lisp Of course, if you're in the same package, e.g. in the same file, you won't need to use the package qualifier before @code{cl-source-file.lis}. Actually, if all you're doing is defining this class and using it in the same file without other fancy definitions, you might skip package complications: @lisp (in-package :asdf) (defclass cl-source-file.lis (cl-source-file) ((type :initform "lis"))) (defsystem my-cl-system :default-component-class cl-source-file.lis ...) @end lisp @node How do I mark a source file to be loaded only and not compiled?, How do I work with readtables?, How do I create a system definition where all the source files have a .cl extension?, Issues with using and extending ASDF to define systems @subsection How do I mark a source file to be loaded only and not compiled? There is no provision in ASDF for ensuring that some components are always loaded as source, while others are always compiled. There is @code{load-source-op} (@pxref{Predefined operations of ASDF,load-source-op}), but that is an operation to be applied to a system as a whole, not to one or another specific source files. While this idea often comes up in discussions, it doesn't play well with either the linking model of ECL or with various bundle operations. In addition, the dependency model of ASDF would have to be modified incompatibly to allow for such a trick. @c If your code doesn't compile cleanly, fix it. @c If compilation makes it slow, use @code{declaim} or @code{eval-when} @c to adjust your compiler settings, @c or eschew compilation by @code{eval}uating a quoted source form at load-time. @node How do I work with readtables?, How can I capture ASDF's output?, How do I mark a source file to be loaded only and not compiled?, Issues with using and extending ASDF to define systems @subsection How do I work with readtables? @cindex readtables It is possible to configure the lisp syntax by modifying the currently-active readtable. However, this same readtable is shared globally by all software being compiled by ASDF, especially since @code{load} and @code{compile-file} both bind @var{*readtable*}, so that its value is the same across the build at the start of every file (unless overridden by some @code{perform :around} method), even if a file locally binds it to a different readtable during the build. Therefore, the following hygiene restrictions apply. If you don't abide by these restrictions, there will be situations where your output files will be corrupted during an incremental build. We are not trying to prescribe new restrictions for the sake of good style: these restrictions have always applied implicitly, and we are simply describing what they have always been. @itemize @item It is forbidden to modifying any standard character or standard macro dispatch defined in the CLHS. @item No two dependencies may assign different meanings to the same non-standard character. @item Using any non-standard character while expecting the implementation to treat some way counts as such an assignment of meaning. @item libraries need to document these assignments of meaning to non-standard characters. @item free software libraries will register these changes on: @url{http://www.cliki.net/Macro%20Characters} @end itemize If you want to use readtable modifications that cannot abide by those restrictions, you @emph{must} create a different readtable object and set @var{*readtable*} to temporarily bind it to your new readtable (which will be undone after processing the file). For that, we recommend you use system @code{named-readtables} to define or combine such readtables using @code{named-readtables:defreadtable} and use them using @code{named-readtables:in-readtable}. Equivalently, you can use system @code{cl-syntax}, that itself uses @code{named-readtables}, but may someday do more with, e.g. @var{*print-pprint-dispatch*}. For even more advanced syntax modification beyond what a readtable can express, you may consider either: @itemize @item a @code{perform} method that compiles a constant file that contains a single form @code{#.*code-read-with-alternate-reader*} in an environment where this special variable was bound to the code read by your alternate reader, or @item using the system @code{reader-interception}. @end itemize Beware that @c unless and until the @code{syntax-control} branch is merged, it is unsafe to use ASDF from the REPL to compile or load systems while the readtable isn't the shared readtable previously used to build software. You @emph{must} manually undo any binding of @var{*readtable*} at the REPL and restore its initial value whenever you call @code{operate} (via e.g. @code{load-system}, @code{test-system} or @code{require}) from a REPL that is using a different readtable. @subsubsection How should my system use a readtable exported by another system? Use from the @code{named-readtables} system the macro @code{named-readtables:in-readtable}. If the other system fails to use @code{named-readtables}, fix it and send a patch upstream. In the day and age of Quicklisp and clbuild, there is little reason to eschew using such an important library anymore. @subsubsection How should my library make a readtable available to other systems? Use from the @code{named-readtables} system the macro @code{named-readtables:defreadtable}. @node How can I capture ASDF's output?, LOAD-PATHNAME has a weird value, How do I work with readtables?, Issues with using and extending ASDF to define systems @subsection How can I capture ASDF's output? @cindex ASDF output @cindex Capturing ASDF output @vindex *standard-output* Output from ASDF and ASDF extensions are sent to the CL stream @code{*standard-output*}, so rebinding that stream around calls to @code{asdf:operate} should redirect all output from ASDF operations. @node LOAD-PATHNAME has a weird value, , How can I capture ASDF's output?, Issues with using and extending ASDF to define systems @subsection *LOAD-PATHNAME* and *LOAD-TRUENAME* have weird values, help! @vindex *LOAD-PATHNAME* @vindex *LOAD-TRUENAME* Conventional Common Lisp code may use @code{*LOAD-TRUENAME*} or @code{*LOAD-PATHNAME*} to find files adjacent to source files. This will generally @emph{not} work in ASDF-loaded systems. Recall that ASDF relocates the FASL files it builds, typically to a special cache directory. Thus the value of @code{*LOAD-PATHNAME*} and @code{*LOAD-TRUENAME*} at load time, when ASDF is loading your system, will typically be a pathname in that cache directory, and useless to you for finding other system components. There are two ways to work around this problem: @enumerate @findex system-relative-pathname @item Use the @code{system-relative-pathname} function. This can readily be used from outside the system, but it is probably not good software engineering to require a source file @emph{of} a system to know what system it is going to be part of. Contained objects should not have to know their containers. @item Store the pathname at compile time, so that you get the pathname of the source file, which is presumably what you want. To do this, you can capture the value of @code{(or *compile-file-pathname* *load-truename*)} (or @code{*LOAD-PATHNAME*}, if you prefer) in a macro expansion or other compile-time evaluated context. @end enumerate @node ASDF development FAQs, , Issues with using and extending ASDF to define systems, FAQ @section ASDF development FAQs @menu * How do I run the tests interactively in a REPL?:: @end menu @node How do I run the tests interactively in a REPL?, , ASDF development FAQs, ASDF development FAQs @subsection How do I run the tests interactively in a REPL? This not-so-frequently asked question is primarily for ASDF developers, but those who encounter an unexpected error in some test may be interested, too. Here's the procedure for experimenting with tests in a REPL: @example ;; BEWARE! Some tests expect you to be in the .../asdf/test directory ;; If your REPL is not there yet, change your current directory: ;; under SLIME, you may: ,change-directory ~/common-lisp/asdf/test/ ;; otherwise you may evaluate something like: (require "asdf") (asdf:upgrade-asdf) ;load UIOP & update asdf.lisp (uiop:chdir (asdf:system-relative-pathname :asdf "test/")) (setf *default-pathname-defaults* (uiop:getcwd)) ;; Load the test script support. (load "script-support.lisp") ;; Initialize the script support for interaction. ;; This will also change your *package* to asdf-test ;; after frobbing the asdf-test package to make it usable. ;; NB: this function is also available from package cl-user, ;; and also available with the shorter name da in both packages. (asdf-test:debug-asdf) ;; Now, you may experiment with test code from a .script file. ;; See the instructions given at the end of your failing test ;; to identify which form is needed, e.g. (run-test-script "test-utilities.script") @end example @comment FIXME: Add a FAQ about how to use a new system class... @comment node-name, next, previous, up @node Ongoing Work, Bibliography, FAQ, Top @unnumbered Ongoing Work For an active list of things to be done, see the @file{TODO} file in the source repository. Also, bugs are currently tracked on launchpad: @url{https://launchpad.net/asdf}. @node Bibliography, Concept Index, Ongoing Work, Top @unnumbered Bibliography @itemize @item Andrey Mokhov, Neil Mitchell and Simon Peyton Jones: ``Build Systems à la Carte'', International Conference on Functional Programming, 2018. @url{https://www.microsoft.com/en-us/research/uploads/prod/2018/03/build-systems-final.pdf} This influential article provides axes along which to describe build systems in general; ASDF, in addition to being in-image (an axis not considered by these authors), has the following characteristics: ASDF's persistent build information is file modification times (the way ASDF is written, it should be easy enough to write an extension that modifies it to use a ``cloud cache'' à la Bazel, but that would involve using some database, network and cryptographic libraries, which cannot reasonably be included in the base ASDF, that must remain a minimal bootstrappable system with no external dependencies). The object model of ASDF was initially designed for ``static'' dependencies with a ``topological'' scheduler, but its @code{defsystem-depends-on} mechanism (and more generally, the ability to call ASDF from within an @code{.asd} file) allows for multiple @emph{phases} of execution resulting in ``dynamic'' dependencies with a ``suspending'' scheduler. The rebuilder essentially uses a ``dirty bit'', except that the in-image model and the multiple phase support mean that's actually more than a bit: instead it's three bits plus the timestamp plus a phase depth level. The build is guaranteed ``minimal'' in number of steps computed. It is local. It assumes but does not enforce determinism. It does not assume early cutoff of the build when rebuild dependencies didn't change. @item Robert Goldman, Elias Pipping, and François-René Rideau: ``Delivering Common Lisp Applications with ASDF 3.3'', European Lisp Symposium, 2017. @url{https://github.com/fare/asdf2017} This short article gives an overview of the changes in ASDF 3.2 and 3.3, including improved application delivery, asynchronous subprocess management, correct support for multi-phase builds, and enhanced source location configuration. @item Francois-Rene Rideau: ``ASDF 3, or Why Lisp is Now an Acceptable Scripting Language'', European Lisp Symposium, 2014. @url{https://github.com/fare/asdf3-2013} This article describes the innovations in ASDF 3 and 3.1, as well as historical information on previous versions. @item Alastair Bridgewater: ``Quick-build'' (private communication), 2012. @code{quick-build} is a simple and robust one file, one package build system, similar to @code{faslpath}, in 182 lines of code (117 of which are neither blank nor comments nor docstrings). Unhappily, it remains unpublished and its IP status is unclear as of April 2014. @code{asdf/package-system} is mostly compatible with it, modulo a different setup for toplevel hierarchies. @item Zach Beane: ``Quicklisp'', 2011. The Quicklisp blog and Xach's personal blogs contain information on Quicklisp. @url{http://blog.quicklisp.org/} @url{http://lispblog.xach.com/} (new) @url{http://xach.livejournal.com/} (old) @item Francois-Rene Rideau and Robert Goldman: ``Evolving ASDF: More Cooperation, Less Coordination'', International Lisp Conference, 2010. This article describes the main issues solved by ASDF 2, and exposes its design principles. @url{https://common-lisp.net/project/asdf/ilc2010draft.pdf} @url{http://rpgoldman.goldman-tribe.org/papers/ilc2010-asdf.pdf} @item Francois-Rene Rideau and Spencer Brody: ``XCVB: an eXtensible Component Verifier and Builder for Common Lisp'', International Lisp Conference, 2009. This article describes XCVB, a proposed competitor for ASDF; many of its ideas have been incorporated into ASDF 2 and 3, though many other ideas still haven't. @url{https://common-lisp.net/project/xcvb/} @item Peter von Etter: ``faslpath'', 2009. @code{faslpath} is similar to the latter @code{quick-build} and our yet latter @code{asdf/package-system} extension, except that it uses dot @code{.} rather than slash @code{/} as a separator. @url{https://code.google.com/p/faslpath/} @item Drew McDermott: ``A Framework for Maintaining the Coherence of a Running Lisp,'' International Lisp Conference, 2005. @url{http://www.cs.yale.edu/homes/dvm/papers/lisp05.pdf} @item Dan Barlow: ``ASDF Manual'', 2004. Older versions of this document from the days of ASDF 1; they include ideas laid down by Dan Barlow, and comparisons with older defsystems (@code{mk-defsystem}) and defsystem (@code{defsystem-4}, kmp's Memo 801). @item Marco Antoniotti and Peter Van Eynde: ``@code{DEFSYSTEM}: A @code{make} for Common Lisp, A Thoughtful Re-Implementation of an Old Idea'', 2002. The @file{defsystem-4} proposal available in the CLOCC repository. @item Mark Kantrovitz: ``Defsystem: A Portable Make Facility for Common Lisp'', 1990. The classic @file{mk-defsystem}, later variants of which are available in the CLOCC repository as @code{defsystem-3.x}. @item Richard Elliot Robbins: ``BUILD: A Tool for Maintaining Consistency in Modular Systems'', MIT AI TR 874, 1985. @url{http://www.dtic.mil/dtic/tr/fulltext/u2/a162744.pdf} @item Kent M. Pitman (kmp): ``The Description of Large Systems'', MIT AI Memo 801, 1984. Available in updated-for-CL form on the web at @url{http://nhplace.com/kent/Papers/Large-Systems.html} @item Dan Weinreb and David Moon: ``Lisp Machine Manual'', 3rd Edition MIT, March 1981. The famous CHINE NUAL describes one of the earliest variants of DEFSYSTEM. (NB: Not present in the second preliminary version of January 1979) @url{http://bitsavers.org/pdf/mit/cadr/chinual_3rdEd_Mar81.pdf} @end itemize @node Concept Index, Function and Macro Index, Bibliography, Top @unnumbered Concept Index @printindex cp @node Function and Macro Index, Variable Index, Concept Index, Top @unnumbered Function and Macro Index @printindex fn @node Variable Index, Class and Type Index, Function and Macro Index, Top @unnumbered Variable Index @printindex vr @node Class and Type Index, , Variable Index, Top @unnumbered Class and Type Index @printindex tp @bye @c LocalWords: clbuild tarballs defsystem Quicklisp initarg uiop fasl @c LocalWords: namestring initargs fasls abcl-src-1.9.0/doc/asdf/asdf.toc0100644 0000000 0000000 00000026056 14242630067 015061 0ustar000000000 0000000 @numchapentry{Introduction}{1}{Introduction}{1} @numchapentry{Quick start summary}{2}{Quick start summary}{2} @numchapentry{Loading ASDF}{3}{Loading ASDF}{3} @numsecentry{Loading a pre-installed ASDF}{3.1}{Loading a pre-installed ASDF}{3} @numsecentry{Checking whether ASDF is loaded}{3.2}{Checking whether ASDF is loaded}{3} @numsecentry{Upgrading ASDF}{3.3}{Upgrading ASDF}{4} @numsecentry{Replacing your implementation's ASDF}{3.4}{Replacing your implementation's ASDF}{4} @numsecentry{Loading ASDF from source}{3.5}{Loading ASDF from source}{4} @numchapentry{Configuring ASDF}{4}{Configuring ASDF}{6} @numsecentry{Configuring ASDF to find your systems}{4.1}{Configuring ASDF to find your systems}{6} @numsecentry{Configuring ASDF to find your systems --- old style}{4.2}{Configuring ASDF to find your systems --- old style}{7} @numsecentry{Configuring where ASDF stores object files}{4.3}{Configuring where ASDF stores object files}{8} @numsecentry{Resetting the ASDF configuration}{4.4}{Resetting the ASDF configuration}{9} @numchapentry{Using ASDF}{5}{Using ASDF}{10} @numsecentry{Loading a system}{5.1}{Loading a system}{10} @numsecentry{Convenience Functions}{5.2}{Convenience Functions}{10} @numsecentry{Moving on}{5.3}{Moving on}{12} @numchapentry{Defining systems with defsystem}{6}{Defining systems with defsystem}{13} @numsecentry{The defsystem form}{6.1}{The defsystem form}{13} @numsecentry{A more involved example}{6.2}{A more involved example}{14} @numsecentry{The defsystem grammar}{6.3}{The defsystem grammar}{16} @numsubsecentry{System designators}{6.3.1}{}{18} @numsubsecentry{Simple component names (@code {simple-component-name})}{6.3.2}{}{18} @numsubsecentry{Complex component names}{6.3.3}{}{19} @numsubsecentry{Component types}{6.3.4}{}{19} @numsubsecentry{System class names}{6.3.5}{}{19} @numsubsecentry{Defsystem depends on}{6.3.6}{}{19} @numsubsecentry{Build-operation}{6.3.7}{}{20} @numsubsecentry{Weakly depends on}{6.3.8}{}{20} @numsubsecentry{Pathname specifiers}{6.3.9}{}{20} @numsubsecentry{Version specifiers}{6.3.10}{}{21} @numsubsecentry{Require}{6.3.11}{}{22} @numsubsecentry{Feature dependencies}{6.3.12}{}{22} @numsubsecentry{Using logical pathnames}{6.3.13}{}{22} @numsubsecentry{Serial dependencies}{6.3.14}{}{23} @numsubsecentry{Source location (@code {:pathname})}{6.3.15}{}{23} @numsubsecentry{if-feature option}{6.3.16}{}{24} @numsubsecentry{Entry point}{6.3.17}{}{24} @numsubsecentry{feature requirement}{6.3.18}{}{24} @numsecentry{Other code in .asd files}{6.4}{Other code in .asd files}{24} @numsecentry{The package-inferred-system extension}{6.5}{The package-inferred-system extension}{25} @numchapentry{The Object model of ASDF}{7}{The object model of ASDF}{28} @numsecentry{Operations}{7.1}{Operations}{28} @numsubsecentry{Predefined operations of ASDF}{7.1.1}{Predefined operations of ASDF}{30} @numsubsecentry{Creating new operations}{7.1.2}{Creating new operations}{33} @numsecentry{Components}{7.2}{Components}{34} @numsubsecentry{Common attributes of components}{7.2.1}{Common attributes of components}{37} @numsubsubsecentry{Name}{7.2.1.1}{}{37} @numsubsubsecentry{Version identifier}{7.2.1.2}{}{37} @numsubsubsecentry{Required features}{7.2.1.3}{}{37} @numsubsubsecentry{Dependencies}{7.2.1.4}{}{38} @numsubsubsecentry{pathname}{7.2.1.5}{}{39} @numsubsubsecentry{Properties}{7.2.1.6}{}{40} @numsubsecentry{Pre-defined subclasses of component}{7.2.2}{Pre-defined subclasses of component}{40} @numsubsecentry{Creating new component types}{7.2.3}{Creating new component types}{41} @numsecentry{Dependencies}{7.3}{Dependencies}{41} @numsecentry{Functions}{7.4}{Functions}{42} @numsecentry{Parsing system definitions}{7.5}{Parsing system definitions}{42} @numchapentry{Controlling where ASDF searches for systems}{8}{Controlling where ASDF searches for systems}{44} @numsecentry{Configurations}{8.1}{Configurations}{44} @numsecentry{Truenames and other dangers}{8.2}{Truenames and other dangers}{45} @numsecentry{XDG base directory}{8.3}{XDG base directory}{45} @numsecentry{Backward Compatibility}{8.4}{Backward Compatibility}{45} @numsecentry{Configuration DSL}{8.5}{Configuration DSL}{46} @numsecentry{Configuration Directories}{8.6}{Configuration Directories}{48} @numsubsecentry{The :here directive}{8.6.1}{The here directive}{49} @numsecentry{Shell-friendly syntax for configuration}{8.7}{Shell-friendly syntax for configuration}{49} @numsecentry{Search Algorithm}{8.8}{Search Algorithm}{50} @numsecentry{Caching Results}{8.9}{Caching Results}{50} @numsecentry{Configuration API}{8.10}{Configuration API}{51} @numsecentry{Introspection}{8.11}{Introspection}{52} @numsubsecentry{*source-registry-parameter* variable}{8.11.1}{*source-registry-parameter* variable}{52} @numsubsecentry{Information about system dependencies}{8.11.2}{Information about system dependencies}{52} @numsecentry{Status}{8.12}{Status}{52} @numsecentry{Rejected ideas}{8.13}{Rejected ideas}{52} @numsecentry{TODO}{8.14}{TODO}{53} @numsecentry{Credits for the source-registry}{8.15}{Credits for the source-registry}{53} @numchapentry{Controlling where ASDF saves compiled files}{9}{Controlling where ASDF saves compiled files}{54} @numsecentry{Configurations}{9.1}{Output Configurations}{54} @numsecentry{Backward Compatibility}{9.2}{Output Backward Compatibility}{55} @numsecentry{Configuration DSL}{9.3}{Output Configuration DSL}{56} @numsecentry{Configuration Directories}{9.4}{Output Configuration Directories}{58} @numsecentry{Shell-friendly syntax for configuration}{9.5}{Output Shell-friendly syntax for configuration}{58} @numsecentry{Semantics of Output Translations}{9.6}{Semantics of Output Translations}{59} @numsecentry{Caching Results}{9.7}{Output Caching Results}{59} @numsecentry{Output location API}{9.8}{Output location API}{59} @numsecentry{Credits for output translations}{9.9}{Credits for output translations}{60} @numchapentry{Error handling}{10}{Error handling}{61} @numsecentry{ASDF errors}{10.1}{}{61} @numsecentry{Compilation error and warning handling}{10.2}{}{61} @numchapentry{Miscellaneous additional functionality}{11}{Miscellaneous additional functionality}{62} @numsecentry{Controlling file compilation}{11.1}{Controlling file compilation}{62} @numsecentry{Controlling source file character encoding}{11.2}{Controlling source file character encoding}{63} @numsecentry{Miscellaneous Functions}{11.3}{Miscellaneous Functions}{64} @numsecentry{Some Utility Functions}{11.4}{Some Utility Functions}{66} @numchapentry{Getting the latest version}{12}{Getting the latest version}{70} @numchapentry{FAQ}{13}{FAQ}{71} @numsecentry{``Where do I report a bug?''}{13.1}{Where do I report a bug?}{71} @numsecentry{Mailing list}{13.2}{Mailing list}{71} @numsecentry{``What has changed between ASDF 1, ASDF 2, and ASDF 3?''}{13.3}{What has changed between ASDF 1 ASDF 2 and ASDF 3?}{71} @numsubsecentry{What are ASDF 1, ASDF 2, and ASDF 3?}{13.3.1}{What are ASDF 1 2 3?}{71} @numsubsecentry{How do I detect the ASDF version?}{13.3.2}{How do I detect the ASDF version?}{72} @numsubsecentry{ASDF can portably name files in subdirectories}{13.3.3}{ASDF can portably name files in subdirectories}{72} @numsubsecentry{Output translations}{13.3.4}{Output translations}{73} @numsubsecentry{Source Registry Configuration}{13.3.5}{Source Registry Configuration}{73} @numsubsecentry{Usual operations are made easier to the user}{13.3.6}{Usual operations are made easier to the user}{74} @numsubsecentry{Many bugs have been fixed}{13.3.7}{Many bugs have been fixed}{74} @numsubsecentry{ASDF itself is versioned}{13.3.8}{ASDF itself is versioned}{74} @numsubsecentry{ASDF can be upgraded}{13.3.9}{ASDF can be upgraded}{74} @numsubsecentry{Decoupled release cycle}{13.3.10}{Decoupled release cycle}{75} @numsubsecentry{Pitfalls of the transition to ASDF 2}{13.3.11}{Pitfalls of the transition to ASDF 2}{75} @numsubsecentry{Pitfalls of the upgrade to ASDF 3}{13.3.12}{Pitfalls of the upgrade to ASDF 3}{76} @numsubsecentry{What happened to the bundle operations?}{13.3.13}{What happened to the bundle operations}{77} @numsecentry{Issues with installing the proper version of ASDF}{13.4}{Issues with installing the proper version of ASDF}{78} @numsubsecentry{``My Common Lisp implementation comes with an outdated version of ASDF. What to do?''}{13.4.1}{My Common Lisp implementation comes with an outdated version of ASDF. What to do?}{78} @numsubsecentry{``I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?''}{13.4.2}{I'm a Common Lisp implementation vendor. When and how should I upgrade ASDF?}{78} @numsubsecentry{After upgrading ASDF, ASDF (and Quicklisp) can't find my systems}{13.4.3}{After upgrading ASDF}{79} @numsecentry{Issues with configuring ASDF}{13.5}{Issues with configuring ASDF}{79} @numsubsecentry{``How can I customize where fasl files are stored?''}{13.5.1}{How can I customize where fasl files are stored?}{80} @numsubsecentry{``How can I wholly disable the compiler output cache?''}{13.5.2}{How can I wholly disable the compiler output cache?}{80} @numsubsecentry{How can I debug problems finding ASDF systems?}{13.5.3}{How can I debug problems finding ASDF systems}{80} @numsecentry{Issues with using and extending ASDF to define systems}{13.6}{Issues with using and extending ASDF to define systems}{81} @numsubsecentry{``How can I cater for unit-testing in my system?''}{13.6.1}{How can I cater for unit-testing in my system?}{81} @numsubsecentry{``How can I cater for documentation generation in my system?''}{13.6.2}{How can I cater for documentation generation in my system?}{81} @numsubsecentry{``How can I maintain non-Lisp (e.g. C) source files?''}{13.6.3}{How can I maintain non-Lisp (e.g. C) source files?}{81} @numsubsecentry{``I want to put my module's files at the top level. How do I do this?''}{13.6.4}{I want to put my module's files at the top level. How do I do this?}{81} @numsubsecentry{How do I create a system definition where all the source files have a .cl extension?}{13.6.5}{How do I create a system definition where all the source files have a .cl extension?}{82} @numsubsecentry{How do I mark a source file to be loaded only and not compiled?}{13.6.6}{How do I mark a source file to be loaded only and not compiled?}{83} @numsubsecentry{How do I work with readtables?}{13.6.7}{How do I work with readtables?}{83} @numsubsubsecentry{How should my system use a readtable exported by another system?}{13.6.7.1}{}{84} @numsubsubsecentry{How should my library make a readtable available to other systems?}{13.6.7.2}{}{84} @numsubsecentry{How can I capture ASDF's output?}{13.6.8}{How can I capture ASDF's output?}{84} @numsubsecentry{*LOAD-PATHNAME* and *LOAD-TRUENAME* have weird values, help!}{13.6.9}{LOAD-PATHNAME has a weird value}{85} @numsecentry{ASDF development FAQs}{13.7}{ASDF development FAQs}{85} @numsubsecentry{How do I run the tests interactively in a REPL?}{13.7.1}{How do I run the tests interactively in a REPL?}{85} @unnchapentry{Ongoing Work}{10001}{Ongoing Work}{86} @unnchapentry{Bibliography}{10002}{Bibliography}{87} @unnchapentry{Concept Index}{10003}{Concept Index}{89} @unnchapentry{Function and Macro Index}{10004}{Function and Macro Index}{91} @unnchapentry{Variable Index}{10005}{Variable Index}{92} @unnchapentry{Class and Type Index}{10006}{Class and Type Index}{93} abcl-src-1.9.0/doc/asdf/asdf.tp0100644 0000000 0000000 00000005355 14242630067 014716 0ustar000000000 0000000 \entry{component}{28}{\code {component}} \entry{operation}{28}{\code {operation}} \entry{compile-op}{30}{\code {compile-op}} \entry{load-op}{30}{\code {load-op}} \entry{prepare-op}{30}{\code {prepare-op}} \entry{load-source-op}{30}{\code {load-source-op}} \entry{prepare-source-op}{30}{\code {prepare-source-op}} \entry{test-op}{30}{\code {test-op}} \entry{compile-bundle-op}{31}{\code {compile-bundle-op}} \entry{monolithic-compile-bundle-op}{31}{\code {monolithic-compile-bundle-op}} \entry{load-bundle-op}{31}{\code {load-bundle-op}} \entry{monolithic-load-bundle-op}{31}{\code {monolithic-load-bundle-op}} \entry{deliver-asd-op}{31}{\code {deliver-asd-op}} \entry{monolithic-deliver-asd-op}{31}{\code {monolithic-deliver-asd-op}} \entry{lib-op}{31}{\code {lib-op}} \entry{monolithic-lib-op}{31}{\code {monolithic-lib-op}} \entry{dll-op}{31}{\code {dll-op}} \entry{monolithic-dll-op}{31}{\code {monolithic-dll-op}} \entry{image-op}{31}{\code {image-op}} \entry{program-op}{31}{\code {program-op}} \entry{concatenate-source-op}{33}{\code {concatenate-source-op}} \entry{monolithic-concatenate-source-op}{33}{\code {monolithic-concatenate-source-op}} \entry{load-concatenated-source-op}{33}{\code {load-concatenated-source-op}} \entry{compile-concatenated-source-op}{33}{\code {compile-concatenated-source-op}} \entry{load-compiled-concatenated-source-op}{33}{\code {load-compiled-concatenated-source-op}} \entry{monolithic-load-concatenated-source-op}{33}{\code {monolithic-load-concatenated-source-op}} \entry{monolithic-compile-concatenated-source-op}{33}{\code {monolithic-compile-concatenated-source-op}} \entry{monolithic-load-compiled-concatenated-source-op}{33}{\code {monolithic-load-compiled-concatenated-source-op}} \entry{source-file}{40}{\code {source-file}} \entry{module}{40}{\code {module}} \entry{system}{40}{\code {system}} \entry{system-definition-error}{61}{\code {system-definition-error}} \entry{operation-error}{61}{\code {operation-error}} \entry{fasl-op (obsolete)}{77}{\code {fasl-op (obsolete)}} \entry{load-fasl-op (obsolete)}{77}{\code {load-fasl-op (obsolete)}} \entry{binary-op (obsolete)}{77}{\code {binary-op (obsolete)}} \entry{monolithic-fasl-op (obsolete)}{77}{\code {monolithic-fasl-op (obsolete)}} \entry{monolithic-load-fasl-op (obsolete)}{77}{\code {monolithic-load-fasl-op (obsolete)}} \entry{monolithic-binary-op (obsolete)}{77}{\code {monolithic-binary-op (obsolete)}} \entry{compile-bundle-op}{77}{\code {compile-bundle-op}} \entry{load-bundle-op}{77}{\code {load-bundle-op}} \entry{deliver-asd-op}{77}{\code {deliver-asd-op}} \entry{monolithic-compile-bundle-op}{77}{\code {monolithic-compile-bundle-op}} \entry{monolithic-load-bundle-op}{77}{\code {monolithic-load-bundle-op}} \entry{monolithic-deliver-asd-op}{77}{\code {monolithic-deliver-asd-op}} abcl-src-1.9.0/doc/asdf/asdf.tps0100644 0000000 0000000 00000003320 14242630067 015067 0ustar000000000 0000000 \initial {B} \entry{\code {binary-op (obsolete)}}{77} \initial {C} \entry{\code {compile-bundle-op}}{31, 77} \entry{\code {compile-concatenated-source-op}}{33} \entry{\code {compile-op}}{30} \entry{\code {component}}{28} \entry{\code {concatenate-source-op}}{33} \initial {D} \entry{\code {deliver-asd-op}}{31, 77} \entry{\code {dll-op}}{31} \initial {F} \entry{\code {fasl-op (obsolete)}}{77} \initial {I} \entry{\code {image-op}}{31} \initial {L} \entry{\code {lib-op}}{31} \entry{\code {load-bundle-op}}{31, 77} \entry{\code {load-compiled-concatenated-source-op}}{33} \entry{\code {load-concatenated-source-op}}{33} \entry{\code {load-fasl-op (obsolete)}}{77} \entry{\code {load-op}}{30} \entry{\code {load-source-op}}{30} \initial {M} \entry{\code {module}}{40} \entry{\code {monolithic-binary-op (obsolete)}}{77} \entry{\code {monolithic-compile-bundle-op}}{31, 77} \entry{\code {monolithic-compile-concatenated-source-op}}{33} \entry{\code {monolithic-concatenate-source-op}}{33} \entry{\code {monolithic-deliver-asd-op}}{31, 77} \entry{\code {monolithic-dll-op}}{31} \entry{\code {monolithic-fasl-op (obsolete)}}{77} \entry{\code {monolithic-lib-op}}{31} \entry{\code {monolithic-load-bundle-op}}{31, 77} \entry{\code {monolithic-load-compiled-concatenated-source-op}}{33} \entry{\code {monolithic-load-concatenated-source-op}}{33} \entry{\code {monolithic-load-fasl-op (obsolete)}}{77} \initial {O} \entry{\code {operation}}{28} \entry{\code {operation-error}}{61} \initial {P} \entry{\code {prepare-op}}{30} \entry{\code {prepare-source-op}}{30} \entry{\code {program-op}}{31} \initial {S} \entry{\code {source-file}}{40} \entry{\code {system}}{40} \entry{\code {system-definition-error}}{61} \initial {T} \entry{\code {test-op}}{30} abcl-src-1.9.0/doc/asdf/asdf.vr0100644 0000000 0000000 00000002213 14242630067 014710 0ustar000000000 0000000 \entry{*features*}{1}{\code {*features*}} \entry{*image-dump-hook*}{9}{\code {*image-dump-hook*}} \entry{*system-definition-search-functions*}{34}{\code {*system-definition-search-functions*}} \entry{*default-source-registry-exclusions*}{50}{\code {*default-source-registry-exclusions*}} \entry{*source-registry-parameter*}{52}{\code {*source-registry-parameter*}} \entry{ASDF_OUTPUT_TRANSLATIONS}{54}{\code {ASDF_OUTPUT_TRANSLATIONS}} \entry{asdf::*user-cache*}{58}{\code {asdf::*user-cache*}} \entry{*compile-file-warnings-behaviour*}{61}{\code {*compile-file-warnings-behaviour*}} \entry{*compile-file-failure-behaviour*}{61}{\code {*compile-file-failure-behaviour*}} \entry{*nil-pathname*}{67}{\code {*nil-pathname*}} \entry{*oldest-forward-compatible-asdf-version*}{77}{\code {*oldest-forward-compatible-asdf-version*}} \entry{*central-registry*}{79}{\code {*central-registry*}} \entry{*central-registry*}{80}{\code {*central-registry*}} \entry{*source-registry*}{80}{\code {*source-registry*}} \entry{*standard-output*}{84}{\code {*standard-output*}} \entry{*LOAD-PATHNAME*}{85}{\code {*LOAD-PATHNAME*}} \entry{*LOAD-TRUENAME*}{85}{\code {*LOAD-TRUENAME*}} abcl-src-1.9.0/doc/asdf/asdf.vrs0100644 0000000 0000000 00000001335 14242630067 015077 0ustar000000000 0000000 \initial {*} \entry{\code {*central-registry*}}{79, 80} \entry{\code {*compile-file-failure-behaviour*}}{61} \entry{\code {*compile-file-warnings-behaviour*}}{61} \entry{\code {*default-source-registry-exclusions*}}{50} \entry{\code {*features*}}{1} \entry{\code {*image-dump-hook*}}{9} \entry{\code {*LOAD-PATHNAME*}}{85} \entry{\code {*LOAD-TRUENAME*}}{85} \entry{\code {*nil-pathname*}}{67} \entry{\code {*oldest-forward-compatible-asdf-version*}}{77} \entry{\code {*source-registry*}}{80} \entry{\code {*source-registry-parameter*}}{52} \entry{\code {*standard-output*}}{84} \entry{\code {*system-definition-search-functions*}}{34} \initial {A} \entry{\code {asdf::*user-cache*}}{58} \entry{\code {ASDF_OUTPUT_TRANSLATIONS}}{54} abcl-src-1.9.0/doc/debugging-internals.markdown0100644 0000000 0000000 00000000153 14202767264 020210 0ustar000000000 0000000 Notes on debugging ABCL * Need to set *PRINT-CIRCLE* to T when examining the structures in jvm.lisp. abcl-src-1.9.0/doc/design/amop/d-m-c-notes0100644 0000000 0000000 00000006046 14202767264 016676 0ustar000000000 0000000 Below is a DRAFT e-mail that I intend to send to the mailing list, however, having it in the repository (probably rephrased) is better long-term documentation. Over the past days, I've been working on porting SBCL's D-M-C tests to ABCL's test suite and testing+fixing our implementation. A number of use-cases have been fixed, however, I'm now down to the more complex cases, in particular the case for the (:arguments . lambda-list). Context ----------- When handling EMF computation, there are two sets of arguments (lambda lists): 1. the arguments passed to the METHOD-COMBINATION through the (:method-combination ...) form in the generic function definition 2. the arguments passed to the generic function when it is being called This distinction is very important, yet not particularly clear from our sources. The former set of arguments is available from the instantiation of the generic function (DEFGENERIC evaluation) and constant throughout the life of the GF. The latter is set of arguments is not available until the function is being called and will presumably be different for each invocation of the GF. The former set is passed to the D-M-C form in the second position: (D-M-C ....). The latter set is made accessible by providing the (:arguments ...) form to the D-M-C form -- binding of the variables happens at "EMF-calculation-time". Current implementation --------------------------------- Our existing implementation does not work at all with the (:arguments ...) option in the D-M-C definition. [SBCL didn't either, btw, until 0.7.] What happens in our implementation is that the function STD-COMPUTE-EFFECTIVE-METHOD-FUNCTION calls a function created by the D-M-C. That function returns forms to be used as the EMF. S-C-E-M-F wraps the returned forms in a function and returns it as the EMF. This works as long as the EMF does not depend on the arguments supplied to the GF (generic function) call. The problem ------------------ Our implementation tries to access the function call parameters (resulting in "unbound variable errors") from the EMF-generating function. However, that function won't (ever) be passed the call arguments. The solution ----------------- Writing down the above and taking into account that we want to cache as much of our EMF as possible for performance reasons as well as considering that the EMF depending on the function call arguments can't be cached, I think this is the solution: The forms being returned (and later wrapped in a lambda) should include code which does another code-generation step --with access to the call parameters-- and include a call to the forms having been generated. Examples -------------- A call to the EMF-generating function which does not depend on the call arguments would return something like: '(CALL-METHOD (MAKE-METHOD (error "ABC 123"))) This form will be wrapped in a lambda roughly like this: (lambda (args) (macrolet ((call-method ...)) )) A call to the EMF-generating function which *does* depend on the arguments would return something like: abcl-src-1.9.0/doc/design/amop/dictionary.markdown0100644 0000000 0000000 00000007177 14202767264 020647 0ustar000000000 0000000 From http://www.lisp.org/mop/dictionary.html # Generic Functions add-dependent metaobject dependent add-direct-method specializer method add-direct-subclass superclass subclass add-method generic-function method allocate-instance class &rest initargs compute-applicable-methods generic-function arguments compute-applicable-methods-using-classes generic-function classes compute-class-precedence-list class compute-default-initargs class compute-discriminating-function generic-function compute-effective-method generic-function method-combination methods compute-effective-slot-definition class name direct-slot-definitions compute-slots class direct-slot-definition-class class &rest initargs effective-slot-definition-class class &rest initargs ensure-class-using-class class name &key direct-default-initargs direct-slots direct-superclasses name metaclass &allow-other-keys ensure-generic-function-using-class generic-function function-name &key argument-precedence-order declarations documentation generic-function-class lambda-list method-class method-combination name &allow-other-keys find-method-combination generic-function method-combination-type-name method-combination-options finalize-inheritance class make-method-lambda generic-function method lambda-expression environment map-dependents metaobject function reader-method-class class direct-slot &rest initargs remove-dependent metaobject dependent remove-direct-method specializer method remove-direct-subclass superclass subclass remove-method generic-function method slot-boundp-using-class class object slot slot-makunbound-using-class class object slot slot-value-using-class class object slot specializer-direct-generic-functions specializer specializer-direct-methods specializer standard-instance-access instance location update-dependent metaobject dependent &rest initargs validate-superclass class superclass writer-method-class class direct-slot &rest initargs ## Readers for Class Metaobjects class-default-initargs class class-direct-default-initargs class class-direct-slots class class-direct-subclasses class class-direct-superclasses class class-finalized-p class class-name class class-precedence-list class class-prototype class class-slots class ## Readers for Generic Function Metaobjects generic-function-argument-precedence-order generic-function generic-function-declarations generic-function generic-function-lambda-list generic-function generic-function-method-class generic-function generic-function-method-combination generic-function generic-function-methods generic-function generic-function-name generic-function ## Readers for Method Metaobjects method-function method method-generic-function method method-lambda-list method method-specializers method method-qualifiers method accessor-method-slot-definition method ## Direct Slot Definition Metaobjects slot-definition-readers direct-slot slot-definition-writers direct-slot ## Readers for Slot Definition Metaobjects slot-definition-allocation slot slot-definition-initargs slot slot-definition-initform slot slot-definition-initfunction slot slot-definition-name slot slot-definition-type slot # Functions ensure-class name &key &allow-other-keys ensure-generic-function function-name &key &allow-other-keys eql-specializer-object eql-specializer extract-lambda-list specialized-lambda-list extract-specializer-names specialized-lambda-list funcallable-standard-instance-access instance location intern-eql-specializer object (setf class-name) new-name class (setf generic-function-name) new-name generic-function (setf slot-value-using-class) new-value class object slot set-funcallable-instance-function funcallable-instance function abcl-src-1.9.0/doc/design/amop/missing.markdown0100644 0000000 0000000 00000002356 14202767264 020145 0ustar000000000 0000000 # Missing AMOP symbols add-dependent add-direct-method add-direct-subclass compute-class-precedence-list compute-default-initargs compute-discriminating-function compute-effective-method We have COMPUTE-EFFECTIVE-METHOD-FUNCTION which lacks the METHOD-COMBINATION argument in its signature. ensure-class-using-class ensure-generic-function-using-class find-method-combination make-method-lambda map-dependents reader-method-class remove-dependent remove-direct-method remove-direct-subclass specializer-direct-generic-functions specializer-direct-methods standard-instance-access Present in SYSTEM. update-dependent writer-method-class generic-function-argument-precedence-order Present in SYSTEM. generic-function-declarations generic-function-method-class Present in SYSTEM. generic-function-method-combination Present in SYSTEM. generic-function-methods Present in SYSTEM. method-generic-function Check %method-generic-function method-lambda-list Present in SYSTEM. accessor-method-slot-definition slot-definition-type ensure-class Present in SYSTEM. extract-specializer-names funcallable-standard-instance-access ## Problems finalize-inheritance is not a generic function abcl-src-1.9.0/doc/design/pathnames/abcl-pathname.org0100644 0000000 0000000 00000030460 14202767264 021156 0ustar000000000 0000000 #+TITLE: Design and Implementation of the ABCL PATHNAME * The ABCL PATHNAME Implementation An ongoing document eventually to be published as a paper. ** Needs within ABCL *** Pathname refactoring My original sin consisted in hacking Pathname.java and LogicalPathname.java to contain four distinct Lisp types PATHNAME, LOGICAL-PATHNAME, URL-PATHNAME, and JAR-PATHNAME. We want to replace =org.lisp.armedbear.Pathname= with some sort of abstraction that allows easier maintainence and understanding of the code. #+caption: Proposed class hierachy #+begin_example cl:logical-pathname a cl:pathname ext:pathname-url a cl:pathname ext:pathname-jar a ext:pathname-jar #+end_example **** Analysis We naively begin by attempting to outline reasons one can't replace with an interface. ***** constructors These would be present for all =ext:url-pathname= #+BEGIN_SRC java new Pathname(namestring) #+END_SRC #+BEGIN_SRC java Pathname Pathname.create(namestring) #+END_SRC ***** Use Builder or Factory? Decide to use a modified Builder so we can chain method setting invocations to contruct a complicated PATHNAME object by specifying one piece of information at a time. #+begin_src java Pathname result = new PathnameBuilder() .setDirectory("/foo/bar/") // I don't think we allow this sort of thing currently .setName("baz") .setType("bat").build(); #+end_src In any event, the Pathname constructors would be deprecated, and perhaps made =private=. Currently they are =protected=. ***** DONE Encapsulate fields with getter/setters CLOSED: [2020-06-19 Fri 17:42] - CLOSING NOTE [2020-06-19 Fri 17:42] \\ Done in pathname-2-build.patch ***** DONE figure out what to do with invalidateNamestring()? CLOSED: [2020-09-22 Tue 12:59] - CLOSING NOTE [2020-09-22 Tue 12:59] \\ Don't implement a caching strategy: always recompute. Cache result of calling =getNamestring=? Unsure what this would gain. For now, just always run the namestring computation routine. ** Description of Current Problems As noted from <[[file:jar-pathnames.markdown][file:./jar-pathnames.markdown]]>. Goals: 1. All objects descending from =URL-PATHNAME= can roundtrip their namestring(). WORKING 2. Able to represent archives within archives arbitrarily INCOMPLETE: only implementing functionality as it exists post abcl-1.5.0 *** Archives within archives Figure the hierarchy out abstractly, and then concretely in Java and Lisp. Idea: use =DEVICE= components to represent a pathname that is an archive #+caption: Example of an archive in an archive #+begin_example jar:jar:file:/abcl/dist/abcl.jar!/something.abcl!/__loader__._ #+end_example #+begin_example [file:/abcl/dist/abcl.jar] ^--has-device-- [jar:file:/abcl/dist/abcl.jar!/ ^--has-device-- [ jar:jar:file:/abcl/dist/abcl.jar!/something.abcl!/] ^--has-device-- [/__loader__._] #+end_example All the following pathnames should be valid: #+begin_example #p"file:/tmp/foo.jar" #p"jar:file:/tmp/foo.jar!/" #p"jar:file:/tmp/foo.jar!/a/path/something.abcl" #p"jar:file:/tmp/foo.jar!/a/path/something.abcl!/" #p"jar:file:/tmp/foo.jar!/a/path/something.abcl!/__loader__._" #+end_example #+NAME: Parsing the namestring #+begin_src lisp (pathname "jar:jar:file:/tmp/abcl/dist/abcl.jar!/something.abcl!/__loader__._") #+end_src would create four pathnames: #+begin_src lisp #1# #p(:device #2# :name "__loader__" :type "_") #2# #p(:device #3#: :name "something" :type "abcl" :directory (:absolute)) #3# #p(:device #4# :name nil :type nil :directory nil :host nil :version nil) #4# #p"/tmp/abcl/dist/abcl.jar" #+end_src | reference | namestring | Java Type | |-----------+--------------------------------------------------------------------+--------------| | #1# | jar:jar:file:/tmp/abcl/dist/abcl.jar!/something.abcl!/__loader__._ | pathname-jar | | #2# | jar:jar:file:/tmp/abcl/dist/abcl.jar!/something.abcl!/ | pathname-jar | | #3# | jar:file:/tmp/abcl/dist/abcl.jar!/ | pathname-jar | | #4# | file:/tmp/abcl/dist/abcl.jar | pathname-url | #4# has to have a device of nil in order to possibly be a DOS drive letter under Windows. Problems: #3# is both a file and an archive source. The namestring of #2# encapsulates this, but should a naked reference to #3# be able to be target of a DIRECTORY operation? No, there is a difference between: | namestring | type | |------------------------------------+--------------| | jar:file:/tmp/abcl/dist/abcl.jar!/ | pathname-jar | | file:/tmp/abcl/dist/abcl.jar | pathname-url | So, any =JAR-PATHNAME= whose =:directory= is =(:absolute)= can be operated on via =MERGE-PATHNAMES= to =DIRECTORY= if it names a valid file or directory. #+begin_src (directory #p"jar:file:/tmp/abcl/dist/abcl.jar!/*.*") #+end_src **** TODO Does this use of =DIRECTORY= clash with current ways of distinguishing files and directories? *** Fix the representation in CL:PATHNAME of objects to reflect this hierarchy. IN-PROGRESS mega-patch exists which passes the tests. **** TODO Refactor the Java Use hybrid Builder/Factory pattern. Don't use constructors, but rather =Pathname.create()= and the five =Pathname.setDirectory()= =Pathname.setDevice()= calls, which may chained. This introduces an asymmetry between the setCOMPONENT() / getCOMPONENT() entries, but seems workable. ** TODO Rename existing Java hierarchy? Too destructive?! | current | new | |--------------+------------------------------------------------------------| | pathname-jar | pathname-archive pathname-zip-archive pathname-jar-archive | | pathname-url | pathname-url | * Gotchas ** Should error: "jar:" prefix needs suffixed "!/" #+begin_src #p"jar:file:foo.jar" #+end_src * Scratch ** Algorithim to enumerate jars in a namestring Count the prefixed occurrences of "jar:". Return The pathname of the root jar as the first value For each enclosed jar, the pathname suffixed with "!/. If there is a path within the last jar, return it as an absolute value #+begin_example jar:jar:file:abcl.jar!/time.abcl!/time_1.cls => file:abcl.jar /time.abcl!/ /time_1.cls #+end_example #+begin_example jar:jar:https://abcl.org/releases/current/abcl.jar!/a-fasl.abcl!/__loader__._ => https://abcl.org/releases/current/abcl.jar!/ /a-fasl.abcl!/ /__loader__._ #+end_example #+begin_example jar:jar:jar:file:abcl-aio.jar!/abcl-contrib.jar!/enclosed.abcl!/__loader__._ => file:abcl-aio.jar /abcl-contrib.jar!/ /enclosed.abcl!/ /__loader__._ #+end_example * Tests ** Problem with abcl-1.5.0 #+begin_src #p"jar:jar:file:/a/baz.jar!/b/c/foo.abcl!/" #+end_src Refers to three =CL:PATHNAME= objects: |-----+-----------------------------------------+--------+--------------| | Ref | Namestring | Device | Type | |-----+-----------------------------------------+--------+--------------| | #1# | file:/a/baz.jar | nil | PATHNAME-URL | | #2# | jar:file:/a/baz.jar!/ | #1# | PATHNAME-JAR | | #3# | jar:jar:file:/a/baz.jar!/b/c/foo.abcl!/ | #2# | PATHNAME-JAR | |-----+-----------------------------------------+--------+--------------| #+begin_src #p"jar:jar:file:/a/baz.jar!/b/c/foo.abcl!/a.cls" #+end_src |-----+----------------------------------------------+--------+--------------| | Ref | Namestring | Device | Type | |-----+----------------------------------------------+--------+--------------| | #1# | file:/a/baz.jar | nil | PATHNAME-URL | | #2# | jar:file:/a/baz.jar!/ | #1# | PATHNAME-JAR | | #3# | jar:jar:file:/a/baz.jar!/b/c/foo.abcl!/ | #2# | PATHNAME-JAR | | #4# | jar:jar:file:/a/baz.jar!/b/c/foo.abcl!/a.cls | #3# | PATHNAME-JAR | |-----+----------------------------------------------+--------+--------------| #+begin_src #p"jar:file:foo.jar!/bar.abcl" #+end_src |-----+----------------------------+--------+--------------| | Ref | Namestring | Device | Type | |-----+----------------------------+--------+--------------| | #1# | file:foo.jar | nil | PATHNAME-URL | | #2# | jar:file:foo.jar!/bar.abcl | #1# | PATHNAME-JAR | ** From the ABCL junit tests *** TODO Necessary for ASDF jar translations to work #+begin_src #p"jar:file:/**/*.jar!/**/*.*" #+end_src |-----+----------------------------+--------+--------------| | Ref | Namestring | Device | Type | |-----+----------------------------+--------+--------------| | #1# | file:/**/*.jar | nil | PATHNAME-URL | | #2# | jar:file:/**/*.jar!/ | #1# | PATHNAME-JAR | | #3# | jar:file:/**/*.jar!/**/*.* | #2# | PATHNAME-JAR | |-----+----------------------------+--------+--------------| *** Merging A =PATHNAME_JAR= may have its root jar as a relative pathname in order to merge things succesfully. #+begin_src java Pathname p = (Pathname)Pathname.create("jar:file:foo.jar!/bar.abcl"); Pathname d = (Pathname)Pathname.create("/a/b/c/"); Pathname r = (Pathname)Pathname.mergePathnames(p, d); String s = r.getNamestring(); assertTrue(s.equals("jar:file:/a/b/c/foo.jar!/bar.abcl")); #+end_src | "jar:file:foo.jar!/bar.abcl" | addressing bar.abcl as a file | | "jar:jar:file:foo.jar!/bar.abcl!/" | addressing bar.abcl as a jar | | | | #+begin_src lisp (merge-pathnames "jar:file:foo.jar!/bar.abcl" "/a/b/c/") #+end_src What do we do when MERGE-PATHNAME gets two PATHNAME-JAR arguments? #+begin_src lisp (merge-pathname "jar:file:abcl-contrib.jar!/init.lisp" "jar:file:/a/b/abcl.jar!/") #+end_src ==> "jar:jar:file:/a/b/abcl.jar!/abcl-contrib.jar/init.lisp" #+begin_src lisp (merge-pathname "jar:file:/abcl-contrib.jar!/init.lisp" "jar:file:/a/b/abcl.jar!/foo/jar") #+end_src ==> "jar:file:/abcl-contrib.jar!/init.lisp" This one I no longer understand #+begin_src lisp (merge-pathname "jar:file:!/init.lisp" "jar:file:/a/b/abcl.jar!/load/path/") #+end_src ==> "jar:file:/a/b/abcl.jar!/load/path/init.lisp" Should be #+begin_src lisp (merge-pathname "init.lisp" "jar:file:/a/b/abcl.jar!/load/path/") #+end_src ==> "jar:file:/a/b/abcl.jar!/load/path/init.lisp" * Misc ** PATHNAME-URL have implicit "file:" scheme Not recorded in host; not emitted as namestring. This is the current behavior. * Have to rework? Unfortunately using a chain of devices to represent things doesn't seem to work. How to repesent the difference between the two? | #1# | "jar:jar:file:abcl.jar!/a/fasl.abcl!/" | | #2# | "jar:file:abcl.jar!/a/fasl.abcl" | They both denote an entry in an archive. #1# denotes the "archive within an archive", something that could be as the defaults for a merge pathnames operation. Or that =CL:DIRECTORY= could return hte contents thereof. #2# denotes the entry as something that could be =CL:OPEN='d. But under the current proposal, both would be represented as a PATHNAME-JAR whose device was "jar:file:abcl.jar". If we go back to storing the list of all jar locations in the device component, they would look like #1# (:device ("abcl.jar" "/a/fasl.abcl")) #2# (:device ("abcl.jar) :name "fasl" :type "abcl") ** What should the type of the pathnames be in the DEVICE? Even though these are references to paths within jars, they aren't a PATHNAME-JAR (they don't have a DEVICE which is a cons), so just make them pathnames. * Re-introducing relative URL-PATHNAME for 'file' scheme URIs don't allow relative pathnames, so to be more strict I implemented stripped out the abilty to create relative URL-PATHNAMEs. * Colophon #+begin_example Mark Evenson Created: 2010 Revised: <2020-08-15 Sat 10:06> #+end_example abcl-src-1.9.0/doc/design/pathnames/jar-pathnames.markdown0100644 0000000 0000000 00000025177 14202767264 022260 0ustar000000000 0000000 JARs and JAR entries in ABCL ============================ Mark Evenson Created: 09 JAN 2010 Modified: 02 NOV 2019 Notes towards an implementation of "jar:" references to be contained in Common Lisp `PATHNAME`s within ABCL. Broken implementation --------------------- abcl-1.5.0 was discovered to be broken with respect to nested jar entries in November 2019. This is evidenced by the tests invoked via (asdf:test-system :abcl) failing with Failed to parse URL 'jar:jar:file:a/baz.jar!/b/c/foo.abcl!/'Nested JAR URLs are not supported In researching where to fix, a flaw in the reasoning about nesting jar pathnames emerged. The current implementation uses the device as a CONS for storing the results of the hacky processing around the `jar` scheme. This was reasoned to be "good enough" in that it kept the pathnames referencing pathnames to a minimum and no suitable case had been meaningful forwarded. In the days of Überjars, where it is perfectly accepable to have jars within jars, here is a counter-example: The jar containing the jar containing the abcl fasl We need to name all possible locations of ABCL fasl files. To fix this, we need to allow the following structure for #p"jar:jar:jar:file:abcl.jar!/b/c/foo.abcl!/foo.cls" resolve to linked PATHNAME-DEVICE references: "foo.cls" --device--> "foo.abcl" --device--> "abcl.jar" Towards Fixing ============== It would be better to reflect the pathname hierarchy as Java classes. Although hooking up things is gonna take some elbow grease, being to cleanly separate the logic for our schemas like "jar", and the special handling that should happen with all pathnames whose namestring starts with a schema we handle (like HTML encoding into/out of expression) would be helpful. We make a breaking change with how we abstract the notion of "Archive" and "Archive Entries". Pathname DEVICE fields currently contain either + a single digit denoting a UNC drive (Windows) + a list containing one or two pathnames denoting paths within archives It is conceptually much more correct to only have a single Pathname in a file to denote the source of an archive. Goals ----- 1. Use Common Lisp pathnames to refer to entries in a jar file. 2. Use `'jar:'` schema as documented in [`java.net.JarURLConnection`][jarURLConnection] for namestring representation. An entry in a JAR file: #p"jar:file:baz.jar!/foo" A JAR file: #p"jar:file:baz.jar!/" A JAR file accessible via URL #p"jar:http://example.org/abcl.jar!/" An entry in a ABCL FASL in a URL accessible JAR file #p"jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls" [jarUrlConnection]: http://java.sun.com/javase/6/docs/api/java/net/JarURLConnection.html 3. `MERGE-PATHNAMES` working for jar entries in the following use cases: (merge-pathnames "foo-1.cls" "jar:jar:file:baz.jar!/foo.abcl!/foo._") ==> "jar:jar:file:baz.jar!/foo.abcl!/foo-1.cls" (merge-pathnames "foo-1.cls" "jar:file:foo.abcl!/") ==> "jar:file:foo.abcl!/foo-1.cls" 4. TRUENAME and PROBE-FILE working with "jar:" with TRUENAME cannonicalizing the JAR reference. 5. DIRECTORY working within JAR files (and within JAR in JAR). 6. References "jar:" for all strings that java.net.URL can resolve works. 7. Make jar pathnames work as a valid argument for OPEN with :DIRECTION :INPUT. 8. Enable the loading of ASDF systems packaged within jar files. 9. Enable the matching of jar pathnames with PATHNAME-MATCH-P (pathname-match-p "jar:file:/a/b/some.jar!/a/system/def.asd" "jar:file:/**/*.jar!/**/*.asd") ==> t Status ------ All the above goals have been implemented and tested. Implementation -------------- A PATHNAME refering to a file within a JAR is known as a JAR PATHNAME. It can either refer to the entire JAR file or an entry within the JAR file. A JAR PATHNAME always has a DEVICE which is a proper list. This distinguishes it from other uses of Pathname. The DEVICE of a JAR PATHNAME will be a list with either one or two elements. The first element of the JAR PATHNAME can be either a PATHNAME representing a JAR on the filesystem, or a URL PATHNAME. A PATHNAME occuring in the list in the DEVICE of a JAR PATHNAME is known as a DEVICE PATHNAME. Only the first entry in the the DEVICE list may be a URL PATHNAME. Otherwise the the DEVICE PATHAME denotes the PATHNAME of the JAR file. The DEVICE PATHNAME list of enclosing JARs runs from outermost to innermost. The implementaion currently limits this list to have at most two elements. The DIRECTORY component of a JAR PATHNAME should be a list starting with the :ABSOLUTE keyword. Even though hierarchial entries in jar files are stored in the form "foo/bar/a.lisp" not "/foo/bar/a.lisp", the meaning of DIRECTORY component is better represented as an absolute path. A jar Pathname has type JAR-PATHNAME, derived from PATHNAME. BNF --- An incomplete BNF of the syntax of JAR PATHNAME would be: JAR-PATHNAME ::= "jar:" URL "!/" [ ENTRY ] URL ::= | JAR-FILE-PATHNAME JAR-FILE-PATHNAME ::= "jar:" "file:" JAR-NAMESTRING "!/" [ ENTRY ] JAR-NAMESTRING ::= ABSOLUTE-FILE-NAMESTRING | RELATIVE-FILE-NAMESTRING ENTRY ::= [ DIRECTORY "/"]* FILE ### Notes 1. `ABSOLUTE-FILE-NAMESTRING` and `RELATIVE-FILE-NAMESTRING` can use the local filesystem conventions, meaning that on Windows this could contain '\' as the directory separator, which are always normalized to '/'. An `ENTRY` always uses '/' to separate directories within the jar archive. Use Cases --------- // UC1 -- JAR pathname: { namestring: "jar:file:foo/baz.jar!/" device: ( pathname: { device: "jar:file:" directory: (:RELATIVE "foo") name: "baz" type: "jar" } ) } // UC2 -- JAR entry pathname: { namestring: "jar:file:baz.jar!/foo.abcl" device: ( pathname: { device: "jar:file:" name: "baz" type: "jar" }) name: "foo" type: "abcl" } // UC3 -- JAR file in a JAR entry pathname: { namestring: "jar:jar:file:baz.jar!/foo.abcl!/" device: ( pathname: { name: "baz" type: "jar" } pathname: { name: "foo" type: "abcl" } ) } // UC4 -- JAR entry in a JAR entry with directories pathname: { namestring: "jar:jar:file:a/baz.jar!/b/c/foo.abcl!/this/that/foo-20.cls" device: ( pathname { directory: (:RELATIVE "a") name: "bar" type: "jar" } pathname { directory: (:RELATIVE "b" "c") name: "foo" type: "abcl" } ) directory: (:RELATIVE "this" "that") name: "foo-20" type: "cls" } // UC5 -- JAR Entry in a JAR Entry pathname: { namestring: "jar:jar:file:a/foo/baz.jar!/c/d/foo.abcl!/a/b/bar-1.cls" device: ( pathname: { directory: (:RELATIVE "a" "foo") name: "baz" type: "jar" } pathname: { directory: (:RELATIVE "c" "d") name: "foo" type: "abcl" } ) directory: (:ABSOLUTE "a" "b") name: "bar-1" type: "cls" } // UC6 -- JAR entry in a http: accessible JAR file pathname: { namestring: "jar:http://example.org/abcl.jar!/org/armedbear/lisp/Version.class", device: ( pathname: { namestring: "http://example.org/abcl.jar" } pathname: { directory: (:RELATIVE "org" "armedbear" "lisp") name: "Version" type: "class" } } // UC7 -- JAR Entry in a JAR Entry in a URL accessible JAR FILE pathname: { namestring "jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls" device: ( pathname: { namestring: "http://example.org/abcl.jar" } pathname: { name: "foo" type: "abcl" } ) name: "foo-1" type: "cls" } // UC8 -- JAR in an absolute directory pathame: { namestring: "jar:file:/a/b/foo.jar!/" device: ( pathname: { directory: (:ABSOLUTE "a" "b") name: "foo" type: "jar" } ) } // UC9 -- JAR in an relative directory with entry pathname: { namestring: "jar:file:a/b/foo.jar!/c/d/foo.lisp" device: ( directory: (:RELATIVE "a" "b") name: "foo" type: "jar" ) directory: (:ABSOLUTE "c" "d") name: "foo" type: "lisp } URI Encoding ------------ As a subtype of URL-PATHNAMES, JAR-PATHNAMES follow all the rules for that type. Most notably this means that all #\Space characters should be encoded as '%20' when dealing with jar entries. History ------- Previously, ABCL did have some support for jar pathnames. This support used the convention that the if the device field was itself a pathname, the device pathname contained the location of the jar. In the analysis of the desire to treat jar pathnames as valid locations for `LOAD`, we determined that we needed a "double" pathname so we could refer to the components of a packed FASL in jar. At first we thought we could support such a syntax by having the device pathname's device refer to the inner jar. But with in this use of `PATHNAME`s linked by the `DEVICE` field, we found the problem that UNC path support uses the `DEVICE` field so JARs located on UNC mounts can't be referenced. via '\\', i.e. jar:jar:file:\\server\share\a\b\foo.jar!/this\that!/foo.java would not have a valid representation. So instead of having `DEVICE` point to a `PATHNAME`, we decided that the `DEVICE` shall be a list of `PATHNAME`, so we would have: pathname: { namestring: "jar:jar:file:\\server\share\foo.jar!/foo.abcl!/" device: ( pathname: { host: "server" device: "share" name: "foo" type: "jar" } pathname: { name: "foo" type: "abcl" } ) } Although there is a fair amount of special logic inside `Pathname.java` itself in the resulting implementation, the logic in `Load.java` seems to have been considerably simplified. When we implemented URL Pathnames, the special syntax for URL as an abstract string in the first position of the device list was naturally replaced with a URL pathname. abcl-src-1.9.0/doc/design/pathnames/merging-defaults.markdown0100644 0000000 0000000 00000010163 14202767264 022750 0ustar000000000 0000000 # ISSUE MERGE-PATHNAMES with specialization of JAR-PATHNAME We wish to resolve the following issues. ## UC0 Loading jna.jar for CFFI via Quicklisp Currently we cannount load systems via ASDF recursively in jars, most importantly for those packaged in 'abcl-contrib.jar', which prevents CFFI from loading the necessary JNA code. ## UC1.1 If *DEFAULT-PATHNAME-DEFAULTS* is a JAR-PATHNAME, commands that would normally be expected to work such as CL-USER> (probe-file #p"/") will fail. ### UC1.2 If *DEFAULT-PATHNAME-DEFAULTS* is a JAR-PATHNAME, COMPILE-FILE operations specifying an OUTPUT-FILE with a NIL DEVICE will fail, as COMPILE-FILE-PATHNAME is required to merge its arguments with the defaults. ## CLHS Citations Some especially relevant portions of the CLHS for consideration. ### 19.2.3 Merging Pathnames http://www.lispworks.com/documentation/HyperSpec/Body/19_bc.htm "Except as explicitly specified otherwise, for functions that manipulate or inquire about files in the file system, the pathname argument to such a function is merged with *default-pathname-defaults* before accessing the file system (as if by merge-pathnames)." Note that this implies that the arguments to PARSE-NAMESTRING--which is what the SHARSIGN-P reader macro correpsponds to--should not be merged. ## 19.2.2.2.3 :UNSPECIFIC as a Component Value http://www.lispworks.com/documentation/HyperSpec/Body/19_bbbc.htm "If :unspecific is the value of a pathname component, the component is considered to be ``absent'' or to ``have no meaning'' in the filename being represented by the pathname." Having an :UNSPECIFIC DEVICE when a PATHNAME refers to a file would address problems when merging when the defaults contains a JAR-PATHNAME. ### MERGE-PATHNAMES http://www.lispworks.com/documentation/HyperSpec/Body/f_merge_.htm "If pathname explicitly specifies a host and not a device, and if the host component of default-pathname matches the host component of pathname, then the device is taken from the default-pathname; otherwise the device will be the default file device for that host. If pathname does not specify a host, device, directory, name, or type, each such component is copied from default-pathname." This suggests that the contents HOST should be considered as an additional axis of type for PATHNAME, so that when PATHNAMES of differing types get merged, a DEVICE which has no meaning for a given type does not get inserted. ## Other implementations A survey of the the "default" host for #p"/" on startup. ### SBCL A host nonce which appears in the reader as #. (Is there a different one under Windows?) ### CLISP HOST is NIL. ### CCL HOST is :UNSPECIFIC. ### ECL HOST is NIL. ## Implementation Since Windows systems do have a default DEVICE for a normal file PATHNAME, namely the current "drive letter" of the process, the implementation changes will be mostly wrapped in runtime conditionals for non-Windows systems. ### TRUENAME sets DEVICE to :UNSPECIFIC TRUENAME sets DEVICE to :UNSPECIFIC running on non-Windows when resolving a path to a plain file. ### DIRECTORY sets DEVICE to :UNSPECIFIC When the default for the :RESOLVE-SYMLINKS argument to DIRECTORY was changed to nil, DIRECTORY was changed not to always resolve its results via TRUENAME. As a result (equal (truename "~/.emacs") (first (directory "~/.emacs")) ) forms would return nil. This is a bit counter to expectations set by CLHS that DIRECTORY "returns a list of pathnames corresponding to the truenames". In particular, this breaks the ANSI CL DIRECTORY.[67] tests. Thus, under non-Windows we now explicitly normalize DEVICE components which are nil to :UNSPECIFIC for the results of DIRECTORY calls. ### Use an implicit type for merging In the case for which a merge occurs when DEFAULT-PATHNAME is a JAR-PATHNAME and the following conditions hold: 1. HOST and DEVICE of the PATHNAME are NIL 2. The DIRECTORY of the PATHNAME represents an absolute path. 3. We are not running under Windows. we set the DEVICE to be :UNSPECIFIC. ### COLOPHON Mark Created: 01-SEP-2012 Revised: 06-FEB-2014 abcl-src-1.9.0/doc/design/pathnames/notes.tex0100644 0000000 0000000 00000032201 14202767264 017616 0ustar000000000 0000000 \begin{verbatim} JARs and JAR entries in ABCL ============================ Mark Evenson Created: 09 JAN 2010 Modified: 21 JUN 2011 Notes towards an implementation of "jar:" references to be contained in Common Lisp `PATHNAME`s within ABCL. Goals ----- 1. Use Common Lisp pathnames to refer to entries in a jar file. 2. Use `'jar:'` schema as documented in [`java.net.JarURLConnection`][jarURLConnection] for namestring representation. An entry in a JAR file: #p"jar:file:baz.jar!/foo" A JAR file: #p"jar:file:baz.jar!/" A JAR file accessible via URL #p"jar:http://example.org/abcl.jar!/" An entry in a ABCL FASL in a URL accessible JAR file #p"jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls" [jarUrlConnection]: http://java.sun.com/javase/6/docs/api/java/net/JarURLConnection.html 3. `MERGE-PATHNAMES` working for jar entries in the following use cases: (merge-pathnames "foo-1.cls" "jar:jar:file:baz.jar!/foo.abcl!/foo._") ==> "jar:jar:file:baz.jar!/foo.abcl!/foo-1.cls" (merge-pathnames "foo-1.cls" "jar:file:foo.abcl!/") ==> "jar:file:foo.abcl!/foo-1.cls" 4. TRUENAME and PROBE-FILE working with "jar:" with TRUENAME cannonicalizing the JAR reference. 5. DIRECTORY working within JAR files (and within JAR in JAR). 6. References "jar:" for all strings that java.net.URL can resolve works. 7. Make jar pathnames work as a valid argument for OPEN with :DIRECTION :INPUT. 8. Enable the loading of ASDF systems packaged within jar files. 9. Enable the matching of jar pathnames with PATHNAME-MATCH-P (pathname-match-p "jar:file:/a/b/some.jar!/a/system/def.asd" "jar:file:/**/*.jar!/**/*.asd") ==> t Status ------ All the above goals have been implemented and tested. Implementation -------------- A PATHNAME refering to a file within a JAR is known as a JAR PATHNAME. It can either refer to the entire JAR file or an entry within the JAR file. A JAR PATHNAME always has a DEVICE which is a proper list. This distinguishes it from other uses of Pathname. The DEVICE of a JAR PATHNAME will be a list with either one or two elements. The first element of the JAR PATHNAME can be either a PATHNAME representing a JAR on the filesystem, or a URL PATHNAME. A PATHNAME occuring in the list in the DEVICE of a JAR PATHNAME is known as a DEVICE PATHNAME. Only the first entry in the the DEVICE list may be a URL PATHNAME. Otherwise the the DEVICE PATHAME denotes the PATHNAME of the JAR file. The DEVICE PATHNAME list of enclosing JARs runs from outermost to innermost. The implementaion currently limits this list to have at most two elements. The DIRECTORY component of a JAR PATHNAME should be a list starting with the :ABSOLUTE keyword. Even though hierarchial entries in jar files are stored in the form "foo/bar/a.lisp" not "/foo/bar/a.lisp", the meaning of DIRECTORY component is better represented as an absolute path. A jar Pathname has type JAR-PATHNAME, derived from PATHNAME. BNF --- An incomplete BNF of the syntax of JAR PATHNAME would be: JAR-PATHNAME ::= "jar:" URL "!/" [ ENTRY ] URL ::= | JAR-FILE-PATHNAME JAR-FILE-PATHNAME ::= "jar:" "file:" JAR-NAMESTRING "!/" [ ENTRY ] JAR-NAMESTRING ::= ABSOLUTE-FILE-NAMESTRING | RELATIVE-FILE-NAMESTRING ENTRY ::= [ DIRECTORY "/"]* FILE ### Notes 1. `ABSOLUTE-FILE-NAMESTRING` and `RELATIVE-FILE-NAMESTRING` can use the local filesystem conventions, meaning that on Windows this could contain '\' as the directory separator, which are always normalized to '/'. An `ENTRY` always uses '/' to separate directories within the jar archive. Use Cases --------- // UC1 -- JAR pathname: { namestring: "jar:file:foo/baz.jar!/" device: ( pathname: { device: "jar:file:" directory: (:RELATIVE "foo") name: "baz" type: "jar" } ) } // UC2 -- JAR entry pathname: { namestring: "jar:file:baz.jar!/foo.abcl" device: ( pathname: { device: "jar:file:" name: "baz" type: "jar" }) name: "foo" type: "abcl" } // UC3 -- JAR file in a JAR entry pathname: { namestring: "jar:jar:file:baz.jar!/foo.abcl!/" device: ( pathname: { name: "baz" type: "jar" } pathname: { name: "foo" type: "abcl" } ) } // UC4 -- JAR entry in a JAR entry with directories pathname: { namestring: "jar:jar:file:a/baz.jar!/b/c/foo.abcl!/this/that/foo-20.cls" device: ( pathname { directory: (:RELATIVE "a") name: "bar" type: "jar" } pathname { directory: (:RELATIVE "b" "c") name: "foo" type: "abcl" } ) directory: (:RELATIVE "this" "that") name: "foo-20" type: "cls" } // UC5 -- JAR Entry in a JAR Entry pathname: { namestring: "jar:jar:file:a/foo/baz.jar!/c/d/foo.abcl!/a/b/bar-1.cls" device: ( pathname: { directory: (:RELATIVE "a" "foo") name: "baz" type: "jar" } pathname: { directory: (:RELATIVE "c" "d") name: "foo" type: "abcl" } ) directory: (:ABSOLUTE "a" "b") name: "bar-1" type: "cls" } // UC6 -- JAR entry in a http: accessible JAR file pathname: { namestring: "jar:http://example.org/abcl.jar!/org/armedbear/lisp/Version.class", device: ( pathname: { namestring: "http://example.org/abcl.jar" } pathname: { directory: (:RELATIVE "org" "armedbear" "lisp") name: "Version" type: "class" } } // UC7 -- JAR Entry in a JAR Entry in a URL accessible JAR FILE pathname: { namestring "jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls" device: ( pathname: { namestring: "http://example.org/abcl.jar" } pathname: { name: "foo" type: "abcl" } ) name: "foo-1" type: "cls" } // UC8 -- JAR in an absolute directory pathame: { namestring: "jar:file:/a/b/foo.jar!/" device: ( pathname: { directory: (:ABSOLUTE "a" "b") name: "foo" type: "jar" } ) } // UC9 -- JAR in an relative directory with entry pathname: { namestring: "jar:file:a/b/foo.jar!/c/d/foo.lisp" device: ( directory: (:RELATIVE "a" "b") name: "foo" type: "jar" ) directory: (:ABSOLUTE "c" "d") name: "foo" type: "lisp } URI Encoding ------------ As a subtype of URL-PATHNAMES, JAR-PATHNAMES follow all the rules for that type. Most notably this means that all #\Space characters should be encoded as '%20' when dealing with jar entries. History ------- Previously, ABCL did have some support for jar pathnames. This support used the convention that the if the device field was itself a pathname, the device pathname contained the location of the jar. In the analysis of the desire to treat jar pathnames as valid locations for `LOAD`, we determined that we needed a "double" pathname so we could refer to the components of a packed FASL in jar. At first we thought we could support such a syntax by having the device pathname's device refer to the inner jar. But with in this use of `PATHNAME`s linked by the `DEVICE` field, we found the problem that UNC path support uses the `DEVICE` field so JARs located on UNC mounts can't be referenced. via '\\', i.e. jar:jar:file:\\server\share\a\b\foo.jar!/this\that!/foo.java would not have a valid representation. So instead of having `DEVICE` point to a `PATHNAME`, we decided that the `DEVICE` shall be a list of `PATHNAME`, so we would have: pathname: { namestring: "jar:jar:file:\\server\share\foo.jar!/foo.abcl!/" device: ( pathname: { host: "server" device: "share" name: "foo" type: "jar" } pathname: { name: "foo" type: "abcl" } ) } Although there is a fair amount of special logic inside `Pathname.java` itself in the resulting implementation, the logic in `Load.java` seems to have been considerably simplified. When we implemented URL Pathnames, the special syntax for URL as an abstract string in the first position of the device list was naturally replaced with a URL pathname. \end{verbatim} \begin{verbatim} URL Pathnames ABCL ================== Mark Evenson Created: 25 MAR 2010 Modified: 21 JUN 2011 Notes towards an implementation of URL references to be contained in Common Lisp `PATHNAME` objects within ABCL. References ---------- RFC3986 Uniform Resource Identifier (URI): Generic Syntax URL vs URI ---------- We use the term URL as shorthand in describing the URL Pathnames, even though the corresponding encoding is more akin to a URI as described in RFC3986. Goals ----- 1. Use Common Lisp pathnames to refer to representations referenced by a URL. 2. The URL schemes supported shall include at least "http", and those enabled by the URLStreamHandler extension mechanism. 3. Use URL schemes that are understood by the java.net.URL object. Example of a Pathname specified by URL: #p"http://example.org/org/armedbear/systems/pgp.asd" 4. MERGE-PATHNAMES (merge-pathnames "url.asd" "http://example/org/armedbear/systems/pgp.asd") ==> "http://example/org/armedbear/systems/url.asd" 5. PROBE-FILE returning the state of URL accesibility. 6. TRUENAME "aliased" to PROBE-FILE signalling an error if the URL is not accessible (see "Non-goal 1"). 7. DIRECTORY works for non-wildcards. 8. URL pathname work as a valid argument for OPEN with :DIRECTION :INPUT. 9. Enable the loading of ASDF2 systems referenced by a URL pathname. 10. Pathnames constructed with the "file" scheme (i.e. #p"file:/this/file") need to be properly URI encoded according to RFC3986 or otherwise will signal FILE-ERROR. 11. The "file" scheme will continue to be represented by an "ordinary" Pathname. Thus, after construction of a URL Pathname with the "file" scheme, the namestring of the resulting PATHNAME will no longer contain the "file:" prefix. 12. The "jar" scheme will continue to be represented by a jar Pathname. Non-goals --------- 1. We will not implement canonicalization of URL schemas (such as following "http" redirects). 2. DIRECTORY will not work for URL pathnames containing wildcards. Implementation -------------- A PATHNAME refering to a resource referenced by a URL is known as a URL PATHNAME. A URL PATHNAME always has a HOST component which is a proper list. This list will be an property list (plist). The property list values must be character strings. :SCHEME Scheme of URI ("http", "ftp", "bundle", etc.) :AUTHORITY Valid authority according to the URI scheme. For "http" this could be "example.org:8080". :QUERY The query of the URI :FRAGMENT The fragment portion of the URI The DIRECTORY, NAME and TYPE fields of the PATHNAME are used to form the URI `path` according to the conventions of the UNIX filesystem (i.e. '/' is the directory separator). In a sense the HOST contains the base URL, to which the `path` is a relative URL (although this abstraction is violated somwhat by the storing of the QUERY and FRAGMENT portions of the URI in the HOST component). For the purposes of PATHNAME-MATCH-P, two URL pathnames may be said to match if their HOST compoments are EQUAL, and all other components are considered to match according to the existing rules for Pathnames. A URL pathname must have a DEVICE whose value is NIL. Upon creation, the presence of ".." and "." components in the DIRECTORY are removed. The DIRECTORY component, if present, is always absolute. The namestring of a URL pathname shall be formed by the usual conventions of a URL. A URL Pathname has type URL-PATHNAME, derived from PATHNAME. URI Encoding ------------ For dealing with URI Encoding (also known as [Percent Encoding]() we adopt the following rules [Percent Encoding]: http://en.wikipedia.org/wiki/Percent-encoding 1. All pathname components are represented "as is" without escaping. 2. Namestrings are suitably escaped if the Pathname is a URL-PATHNAME or a JAR-PATHNAME. 3. Namestrings should all "round-trip": (when (typep p 'pathname) (equal (namestring p) (namestring (pathname p)))) Status ------ This design has been implemented. History ------- 26 NOV 2010 Changed implemenation to use URI encodings for the "file" schemes including those nested with the "jar" scheme by like aka. "jar:file:/location/of/some.jar!/". 21 JUN 2011 Fixed implementation to properly handle URI encodings refering nested jar archive. \end{verbatim} abcl-src-1.9.0/doc/design/pathnames/pathname.org0100644 0000000 0000000 00000004002 14202767264 020250 0ustar000000000 0000000 * ABCL Pathname refactoring ## Use Builder pattern Implement setter/getters for internal state. Move to the use of Pathname.create() to create new underlying pathnames. Thunk on the need to create either | Pathname | a file | | LogicalPathname | a logical pathname | | ArchivePathname | an archive containing other pathnames | Do we need an ArchivePathnameEntry? "regular" pathnames with a proper DEVICE for their containing archive should be sufficient. ## Java Object Hierarchy #+BEGIN_SRC n3 @prefix : "org.armedbear.lisp" . <> :in-package "org.armedbear.lisp" . #PathnameBase -- keep as Pathname for initial refactoring Pathname rdfs:subClassOf LispObject ; rdfs:comment "has methods make() and makeFrom() that returns the appropiate subtype." LogicalPathname rdfs:subClassOf Pathname . #Pathname # rdfs:subClassOf AbstractPathname . PathnameURI rdfs:subClassOf Pathname . PathnameArchive rdfs:subClassOf PathnameURI . PathnameArchiveEntry rdfs:subClassOf PathnameURI . PathnameJarArchive rdfs:subClassOf PathnameArchive . PathnameFile rdfs:subClassOf PathnameURI . #+END_SRC #+BEGIN_SRC n3 @prefix protocol: "org.armedbear.lisp.protocol" . Pathname rdfs:comment "Encapsultes #+END_SRC * Historical ** Archived <2019-11-12 Tue> Working through mq | patch | Contents | status | notes | |----------------------------+------------------------------------------------+---------+-------| | pathname-refactor.diff | getter/setter; object hierarchy skeleton | Removed | | | refactor-pathname.diff | getter/setter | removed | | | abcl-asdf-mvn-version.diff | previous work subsumed via abcl-1.5.0 | removed | | | abstract-pathname.diff | Have AbstractPathname rdfs:subClassOf Pathname | removed | | | build-version.diff | problems with abcl.version ant target | removed | | abcl-src-1.9.0/doc/design/pathnames/pathnames.tex0100644 0000000 0000000 00000004327 14202767264 020456 0ustar000000000 0000000 % -*- mode: latex; -*- % http://en.wikibooks.org/wiki/LaTeX/ \documentclass[10pt]{article} % \usepackage{abcl} \begin{document} \title{An Implementation and Analysis of Adding IRI to Common Lisp's Pathname} \date{October 2011} \author{Mark~Evenson} \maketitle \section{Abstract} We implement the semantics for distributed resource description and retrieval by URL/URI/IRI Pathname in the Armed Bear Common Lisp implementation. \section{Plan of Attach} \subsection{Goals} \begin{enumerate] \item Use Common Lisp pathnames to refer to representations referenced by a URL. \item The URL schemes supported shall include at least "http", and those enabled by the URLStreamHandler extension mechanism. \item Use URL schemes that are understood by the java.net.URL object. \item MERGE-PATHNAMES (merge-pathnames "url.asd" "http://example/org/armedbear/systems/pgp.asd") ==> "http://example/org/armedbear/systems/url.asd" \item PROBE-FILE returning the state of URL accesibility. \item TRUENAME "aliased" to PROBE-FILE signalling an error if the URL is not accessible (see "Non-goal 1"). \item DIRECTORY works for non-wildcards. \item URL pathname work as a valid argument for OPEN with :DIRECTION :INPUT. \item Enable the loading of ASDF2 systems referenced by a URL pathname. \item Pathnames constructed with the "file" scheme (i.e. #p"file:/this/file") need to be properly URI encoded according to RFC3986 or otherwise will signal FILE-ERROR. \item. The "file" scheme will continue to be represented by an "ordinary" Pathname. Thus, after construction of a URL Pathname with the "file" scheme, the namestring of the resulting PATHNAME will no longer contain the "file:" prefix. \item. The "jar" scheme will continue to be represented by a jar Pathname. \end{enumerate} \subsection{Non-goals} \begin{enumerate} \item We will not implement canonicalization of URL schemas (such as following "http" redirects). \item \textsc{DIRECTORY} will not work for URL pathnames containing wildcards. \end{enumerate} \subsubsection{Example} Example of a Pathname specified by URL: #p"http://example.org/org/armedbear/systems/pgp.asd" \section{Notes} \include{notes} \end{document} abcl-src-1.9.0/doc/design/pathnames/url-pathnames.markdown0100644 0000000 0000000 00000010544 14202767264 022276 0ustar000000000 0000000 URL Pathnames ABCL ================== Mark Evenson Created: 25 MAR 2010 Modified: 21 JUN 2011 Notes towards an implementation of URL references to be contained in Common Lisp `PATHNAME` objects within ABCL. References ---------- RFC3986 Uniform Resource Identifier (URI): Generic Syntax URL vs URI ---------- We use the term URL as shorthand in describing the URL Pathnames, even though the corresponding encoding is more akin to a URI as described in RFC3986. Goals ----- 1. Use Common Lisp pathnames to refer to representations referenced by a URL. 2. The URL schemes supported shall include at least "http", and those enabled by the URLStreamHandler extension mechanism. 3. Use URL schemes that are understood by the java.net.URL object. Example of a Pathname specified by URL: #p"http://example.org/org/armedbear/systems/pgp.asd" 4. MERGE-PATHNAMES (merge-pathnames "url.asd" "http://example/org/armedbear/systems/pgp.asd") ==> "http://example/org/armedbear/systems/url.asd" 5. PROBE-FILE returning the state of URL accesibility. 6. TRUENAME "aliased" to PROBE-FILE signalling an error if the URL is not accessible (see "Non-goal 1"). 7. DIRECTORY works for non-wildcards. 8. URL pathname work as a valid argument for OPEN with :DIRECTION :INPUT. 9. Enable the loading of ASDF2 systems referenced by a URL pathname. 10. Pathnames constructed with the "file" scheme (i.e. #p"file:/this/file") need to be properly URI encoded according to RFC3986 or otherwise will signal FILE-ERROR. 11. The "file" scheme will continue to be represented by an "ordinary" Pathname. Thus, after construction of a URL Pathname with the "file" scheme, the namestring of the resulting PATHNAME will no longer contain the "file:" prefix. 12. The "jar" scheme will continue to be represented by a jar Pathname. Non-goals --------- 1. We will not implement canonicalization of URL schemas (such as following "http" redirects). 2. DIRECTORY will not work for URL pathnames containing wildcards. Implementation -------------- A PATHNAME refering to a resource referenced by a URL is known as a URL PATHNAME. A URL PATHNAME always has a HOST component which is a proper list. This list will be an property list (plist). The property list values must be character strings. :SCHEME Scheme of URI ("http", "ftp", "bundle", etc.) :AUTHORITY Valid authority according to the URI scheme. For "http" this could be "example.org:8080". :QUERY The query of the URI :FRAGMENT The fragment portion of the URI The DIRECTORY, NAME and TYPE fields of the PATHNAME are used to form the URI `path` according to the conventions of the UNIX filesystem (i.e. '/' is the directory separator). In a sense the HOST contains the base URL, to which the `path` is a relative URL (although this abstraction is violated somwhat by the storing of the QUERY and FRAGMENT portions of the URI in the HOST component). For the purposes of PATHNAME-MATCH-P, two URL pathnames may be said to match if their HOST compoments are EQUAL, and all other components are considered to match according to the existing rules for Pathnames. A URL pathname must have a DEVICE whose value is NIL. Upon creation, the presence of ".." and "." components in the DIRECTORY are removed. The DIRECTORY component, if present, is always absolute. The namestring of a URL pathname shall be formed by the usual conventions of a URL. A URL Pathname has type URL-PATHNAME, derived from PATHNAME. URI Encoding ------------ For dealing with URI Encoding (also known as [Percent Encoding]() we adopt the following rules [Percent Encoding]: http://en.wikipedia.org/wiki/Percent-encoding 1. All pathname components are represented "as is" without escaping. 2. Namestrings are suitably escaped if the Pathname is a URL-PATHNAME or a JAR-PATHNAME. 3. Namestrings should all "round-trip": (when (typep p 'pathname) (equal (namestring p) (namestring (pathname p)))) Status ------ This design has been implemented. History ------- 26 NOV 2010 Changed implemenation to use URI encodings for the "file" schemes including those nested with the "jar" scheme by like aka. "jar:file:/location/of/some.jar!/". 21 JUN 2011 Fixed implementation to properly handle URI encodings refering nested jar archive. abcl-src-1.9.0/doc/design/streams/README0100644 0000000 0000000 00000000435 14202767264 016326 0ustar000000000 0000000 To generate html from rst, use rst2html design.rst > design.html The .dia files are uncompressed dia diagrams. Just export them to png from dia if you need to do modifications. You can do the exports from the command line by using dia -t pprint-problem.dia dia -t pprint-solution.dia abcl-src-1.9.0/doc/design/streams/design.html0100644 0000000 0000000 00000020742 14202767264 017610 0ustar000000000 0000000 Design of lisp streams in ABCL

Design of lisp streams in ABCL

The previous design

Previously, ABCL streams were built-in classes. This presented some problems for Gray streams, because ABCL CLOS can't use a built-in class as a base class, and Gray streams derive from a system-stream class. This was corrected by converting ABCL streams to be structure-objects instead of built-in classes, allowing CLOS to derive from the streams. There was, however, another problem that revealed a need to change the design in more drastic ways.

The problem with the previous design

While converting the streams from built-in classes to structure-objects allowed derivation, the pretty printer still didn't work with Gray streams. Gray streams replace the system stream functions, saving the old function symbols so that they can be later invoked. The pretty printer, however, just replaces the stream functions, and calls the low-level primitives directly, thus bypassing Gray streams completely. The attached image portrays the problem, where pprint will, for example, invoke %stream-write-char, thus bypassing any methods that there may be for stream-write-char using Gray streams.

pprint-problem.png

The planned future design and solution to the problem

The solution to the problem is quite similar to how SBCL does its streams. First of all, the pretty printer will no longer replace stream functions. The stream functionality will be based on closures in the slots of the structure-object representing the stream, and those closures will invoke low-level i/o functions that are stream-specific.

The pretty printer will just setup closures that will extract the underlying stream object from a pprint-wrapped stream, and invoke its low-level functions. If pprint wrapping isn't present, the slots will contain closures that directly invoke low-level functions of streams. Gray streams will still replace the stream functions, because it's capable of invoking the replaced functions.

In addition to these changes, it is planned that the stream function primitives will be moved from the Stream java class to a streamfunctions library, allowing the stream functions to be written in lisp rather than java. There's an ongoing aspiration to increase the lisp/java code ratio of ABCL, and this new design allows for that.

pprint-solution.png
abcl-src-1.9.0/doc/design/streams/design.rst0100644 0000000 0000000 00000004707 14202767264 017457 0ustar000000000 0000000 ============================== Design of lisp streams in ABCL ============================== The previous design ------------------- Previously, ABCL streams were built-in classes. This presented some problems for Gray streams, because ABCL CLOS can't use a built-in class as a base class, and Gray streams derive from a system-stream class. This was corrected by converting ABCL streams to be structure-objects instead of built-in classes, allowing CLOS to derive from the streams. There was, however, another problem that revealed a need to change the design in more drastic ways. The problem with the previous design ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ While converting the streams from built-in classes to structure-objects allowed derivation, the pretty printer still didn't work with Gray streams. Gray streams replace the system stream functions, saving the old function symbols so that they can be later invoked. The pretty printer, however, just replaces the stream functions, and calls the low-level primitives directly, thus bypassing Gray streams completely. The attached image portrays the problem, where pprint will, for example, invoke %stream-write-char, thus bypassing any methods that there may be for stream-write-char using Gray streams. .. image:: pprint-problem.png The planned future design and solution to the problem ----------------------------------------------------- The solution to the problem is quite similar to how SBCL does its streams. First of all, the pretty printer will no longer replace stream functions. The stream functionality will be based on closures in the slots of the structure-object representing the stream, and those closures will invoke low-level i/o functions that are stream-specific. The pretty printer will just setup closures that will extract the underlying stream object from a pprint-wrapped stream, and invoke its low-level functions. If pprint wrapping isn't present, the slots will contain closures that directly invoke low-level functions of streams. Gray streams will still replace the stream functions, because it's capable of invoking the replaced functions. In addition to these changes, it is planned that the stream function primitives will be moved from the Stream java class to a streamfunctions library, allowing the stream functions to be written in lisp rather than java. There's an ongoing aspiration to increase the lisp/java code ratio of ABCL, and this new design allows for that. .. image:: pprint-solution.png abcl-src-1.9.0/doc/design/streams/pprint-problem.dia0100644 0000000 0000000 00000100151 14202767264 021073 0ustar000000000 0000000 #Letter# #usercode.lisp# ## ## #pprint.lisp# ## ## #gray-streams.lisp# ## ## #Stream.java (primitives)# ## ## #methods for stream-write-char etc., as allowed by Gray streams# ## ## #write-char# #%stream-write-char# #write-char# #stream-write-char (method call)# #pprint _always_ calls the primitives in Stream.java# #gray streams allow methods# #If pprint is loaded, gray streams methods won't be called!# abcl-src-1.9.0/doc/design/streams/pprint-problem.png0100644 0000000 0000000 00000204601 14202767264 021127 0ustar000000000 0000000 �PNG  IHDR�4�(bKGD������� IDATx���y\T��?�����"�2� ����!�K.(j�hj���^-Mo�5�����k�fJ��%�R}����EIAeqd����ǹ� 3g`pP^��c�������sÛϜ�9 !��;�Ba�������z ����� ����Q��������6uD�(M@c�}""j�7o���|������fj�8�LDDD����5֯_�Rɑfz,0a&""�Gnذa���f�L�^�ADDD&1n�8����yy5hL�����d�4�� 3��fj�0��1i��� 35L���b�LDDD �fj��0Q�¤���� �B�O�#""R(�5kZ�l�s���DDGG����ׯ��ٳQ�D�8�LDDD����ˑ�����<��yyy������HJJzD�UDŽ�����ŋ������fͪ�h��㣱�����t`�LDDDD�����P(�?���v}�\]]��쌙3g� RݦM�� Ԫl\\���L�]������&��Y�&N����z�d�D�8��d���gϞضm�������#F��'�|�u]]ί�]�b���u �^���3��cM�GϞ=��;�eD��5� ȁPVV�`�Сx���ѤI�jۭZ� �|� F�i�(��0a,--���_�v .\�3����pttD�^�p��]��듙��aÆ���...X�p!��ʤ�7n���/lll��� ���TZ�����*� ����y�F�yyy�4i�������iӦ���Hv��JNN�� ��#���:?t��… ���ĭ[���N�:ܾ}[V|�����KW���_W������3Ϡu������… akk��s�ʊ_9��_n�\�x]�vE�&M4~�翾�.�oٲ%�9Rm�� ����ŧ��Ic|~�/���6m����QQQ����N��'GLL ڷo�JooolݺUZ���L��ETg� Bnw���C���{5�wuuǎ38ѻwoQRR"���ij�>+�~�m��b������K�={V!D^^��y��6/���x�״��_�~������Xt��QlٲEc�={�___��&g����������H����_~�Eܿߠ�ϟ?_�q4h��0a�(**���U�Vbݺu��;vH����.�j���㏥�;v�������������7ߔ�:T�9R�;w�aÆ��_]v���ԩ��;w�())?�������V���C_�{��!���I?ϟ?_L�8Qv|r����KW���_W����#|||Dqq��ڵ�x�Wĵk�D�&MDii���k"�~}���=z���)222D�V�4~�����Ϻ����b�ʕՖ���G�رCV|r>�������… Z���W�.]�����~���������G������*�J|���B!���Ł���~?�����o}]>�>��c@̜9S���C,Y�Dv����#̍Ldd$�J%������8��@xx8:t�h֬���d�?<<���D��ݑ��\��iӦ���EZZ z��+++��}��:tH����� S�N��ݻ�m����~���Bhh(Ν;HII�ٳg����������ի�T6==���X�f ���R�0o�<|��ײ����˗����7ހR�D�޽ѧO���t~�j?��� ��/eee�����)Sd�h��-~}�/�}�Z����%|||���OOO( ���%~]�ˉ_�)S�����~���r�Ϻ��O�>8~�8��{AV�Z���R�sss�R��R���U~�]��u�/'~9�5k&�����~���r�Ϻ��2a���������? 11���hٲ���O���O��� nܸ@���Off&�z���;�˜�_ppp0J\D��M�LVV����͛�@���P(�������X�n�����`!**ʠ���G�W�'''( \�~...*��������1c�૯��ȑ#�P(0g����͛C���������<<<�P(p��9�T�jq�+_W�����H���Ά��O�m����T�ѣGc���|�2&M�dй&���9���S_��i_M*�1��YS���T��?}翜�.�o߾=�ݻ��?����8p��oA��g,u����Ζ�W�]�{�tqwwGjj��ur�ߚ>���7������akk+��D������(**����(**Ҹ)�>��S��� ??�6m��ѣ Z_�\\\����q�Z�h���c޼y(((Pq�D||���U��o���� j�������z�j���������_d����JS�L�����8L�<٠��ڞ_��_n��m鋿Rm�G��/���K�����U�Vaذa4h>��C)a����������7rrrp��mlذcƌ ���2u�T|��gHHHP�����?k��ӷޘ�_{��.�!z��07 ����~��7,]�VVV'6��w��hѢ|}}��o�^���@��j���b˖-P��2d�A����aaahӦ ����i�&��?11}��������0�ⳳ��ڵk1z�h�T*iD �mۆ�7o����:u��ѣ1{�l_/�Z� ����ׯf̘�~��i���>� ݺuôi�ХK�����(++C�֭�R�0l�0\�zUv�J_|��G����8|�0���ocȐ!�G���������۷G�֭ �O�������嶯��ׅ���[��:���g]�ߧO(�J�m�ÇGFF��u���3���Pq�u�>}��� �Z����o�:9�O��C�b�ƍ�;w.T*:v���t��_]�����kǎ���_e���X����& U��2���,^�����ZO�����������3�#F`���Mm(G`` &M�� �CD�ކ 0k�,̜9���áF�#�D�ȡC�T�d��ɓ�5����8v�tǽ�>|���?~�Q�%""� ��GԈDEE��&���T������*� ���?Ѿ}{��֭[7\�|7nԘ�����Ԙ07"�O���zj�ƍ�q���[����{��MDDT�$�����H&�DDDDD:0a&""""ҁ 3�������J��q������H�0?"|�"��#�DDDDD:0a&""""ҁ 3�L������t`�LDDDD�f"""""�0��������H&�DDDDD:0a&""""ҁ 3�L������t`�LDDDD�f"""""�0��������H&�DDDDD:0a&""""ҁ 3�L������t`�LDDDD�f"""""�0��������H&�DDDDD:0a&""""ҁ 3�L������t`�LDDDD�f"""""�0��������H&�DDDDD:0a&""""ҁ 3�L������t`�LDDDD�f"""""�0��������H&�DDDDD:0a&""""ҁ 3�L������t`�LDDDD�f"""""�0��������H�� "�E�P�:�ǒ��:���S�B���3��֭[ ��ӧM �cO!�����&�#���"��o���3���͑f"#�3�F�T�s��5jG���� 3���� ;w�d�LdL�����P���L���� 3��I3Q�1a&""z�1i&�&�DDD��f��c�LDD�H0i&�&�DDD��f"�1a&""jd�4Fi��������ۇ�+W�ܦ{��x�"���0`�$%%����EH��`�LDD������E�����w�aÆ!)) yyy�q�f"-Ba� ��j�P(��"�?;vDbb"Ξ=�:�:���0��������H&�DD2M�6 ,�Uٸ�8���9"y������&]�B���ϣ�?]�GϞ=�m۶z�7�Ǜ���d�0a,--M���]�� .��g�1u( ���a�G������(�m۶�8q" e����,Y�#G����Z�h���$��;�V��={�T�Ϟ=1{�l 8-[�ij�>+՟���Z��^z �.]�Z��Z�Ɩ-[����7���666pss PZZ*�l˖-q�ȑj�,X�Y�f��… ���ĭ[����N���� n߾ �������aooGGG��� w�ޭk�5��Ġ}��P�T����֭[�uu�9��>���ŋѵkW4i�D�����"b�LDO���H(�J���!** qqq����piJ�f͚���I�����aaaKKKt�����uk����������s���*[5a�߿?V�Z���R��߿�~����pvvF˖-e��3g� %% ��������/F�N� GGG̘1Cv|rdff⩧��q}]�G��nP�\% ����� ���n�:@JJ ������(�􁻻;RSS��7F�j{~xxx@�P�ܹsP�T�'"y8�LDO�O?�999���ǦM�0z�h���7dddh�g ���())A@@ �_����DwwwXXX��ѣ�����U�Vaذa4h>��C)a�[��)S���#..�'O�Xw��A\�r��F�4ib���ԩS��g�!!!p��-�+//����1f��ܹ�駟P^^n��4O?�4�/_n�0��8�LD����DEE!00m۶�ĉQXX��MHH�,Y��#G���-Z�@RR`ǎP�� ���丸8<��3hݺ5����p�B���b�ܹ�6��'%%A�V㥗^¥K��V��V��e�Y�O�< ;;;��8p^^^RR����I�&��� �6m������1|�p�������z��ݻwe�����gϞ�={6��-[��g����5�~�:RSS1w�\888@�Ra�ȑ�ܹ���t_}��q�F������nnnX�`JKK�;���8qj�]�t�_���j�u�_���U���� 3=�^��cǎ�ܹs����:��u�V,[� �.]Bbb"\]]T�����!""Bk�%%%HJJ���- q��l޼eeez˷m�iiiؼy3|||������4L�>]�FW�.]������퓖EGGc���03�����B~~>RSS������,,Y�D�~ŊP*�����͛7�f������VY�T<:>>)))���Ď;d���� �Z��s����ø���z9�W��㫯���k�.ܻw'N���_����;��t��iii���Ѻ^���}�Q�1a&�'Bdd$�J%�������jۄ��Ks�6k� NNN��nժ,--���???xzzB�P ??ߨm�Ʉ  (**B\\&L�HOOG||<֬Y;;;�T*̛7_��T�iӦ���EZZ z��+++�� XZZ�{��HNN�U���G����;&O� DDD��͛�����+�����r^^^ Źs���}���_��S��� 3=����ɩ��Z��Uݕ��J�J�RZ�������p��|��whѢ������K�+L�:���R�ŋ�S�N ���#f̘�5F齹�9JJJd�mѢ6l؀+W�����~�:fϞmp ڎ���ٷo��� ///��jl۶M�����ۿ��/�<�o�#�'BVV����͛Wۦ��b�� E��V����ٳ�|��袇� Ν;�J�����=֭[HIIApp0����c��z�)L�2�W��X.���_}�����1c�૯��ȑ#�P(0g�Y�`��r�����%~"��#�D�D���O������|lڴ �G�6uH\\\����[�nժ�� �e�8p@#�mѢ�y�桠�p��e���K�!""҅�d5P���Z�߼y�N�V&��P����&M�H�+/ӨO���X�n.\��� lݺUZ�����߿Z9C����H�05P�/_�ާ��J�&�ٶr�� ��N����QTT���"������_~9998|�06mڄ�ӧC�P ++ ˖-�ZƐ>!""҅#�D Ԓ%K���OC�P��wߕ�����i��`mm-�OJJBii)���}�|��x����W�Ƃ d�]RR���_3f ������0�ر���Gnn��r��#G��ĉh֬���������egg'�DD��b�L�@eee�駟�X�����i��н{w( !�~�z�_�p���T�:�]VV����c���������-rrrPRR���>mj�'���8}������̤����AkR��U׾!"�G� 3Q�k�.|��Gػw/���0b��[�N�h�l[|||�a��X�W�^Eyy��궰���Y���o��ҥK��ʂ��:v�^x����r�퓁bΜ9��ϗ^?W�n߾����G��Q*�Ւh�G�~����j���֭[ѤI�3VVV��G�eGDd:W�\A˖-�u !���=���nM�v������\�x�[���.C�m,��'�f�† ���c�̙�ʔ��K�s^^�֤Z���ݻ�jg% ������$����^�>�^�ԩSѣG��a�L�p=���#�DD�dffGGG8::֪|iii�$://���_���Í7j�CKK��i9IwӦMk��G)??_z�y�fl޼:t� /�� &�8�wM8�D�px{{��ի�d_L���LD�T��ٹ�3w���hM��v"''999��ӦM�&�U�/5�:Ea}��˫�,11���*-Z�aÆa���:t(����="z<� �GH�%d:��$�q�����i9IwQQQ��oee%�ґ�F��L�ؾ}{����ջ�����yL�2~~~���w���a�%DDTo,--���b�e �����&�U�/5),,Daa!���j���tՑ쌌 Yueffb�ʕX�r%z���ӧcܸq�Ʉ�0a&"�Zjڴ)������V�򅅅�.�i��޽{�w��X�_����+^|�Et���֭3j�D��a�LDD&aee+++���ת��{�jL� �����k��:���r�9sAAAҲ���k<���>���K666���D�v�лwo >&L�+���7�x�-2�~�ϟ/��)Y>~�8F���͛C�T����ڵCDD��߯��S���;���w���'�cC �B�B���S�#˜9s�P(X/��W�h�W�9�Ў�ʕ+�P(��SO��^ c�3� pNW��WuJ99,,,еkW������C�>}�ǟ��5����_�H��޽���$$%%���Æ �֝:u K�.����k׮�I��ҥKظq#��������휛5k�-[���TlذA�VSa�L�ڵ+�͛��'�x���ŋYo����Ê+0z��z�G]���(//�ݻwQRR��޽{*�h !p��}GIԸ�K��4i��ݻ����۷/z��U��'�Z�JJ��-[������':d� ۇ�,Z�H�����a�h�[�f JKK����Ç����X_}R�z�񱵵����i�&�����9s�T�8eD2������+��������"::�^����+���c��*�aL}����3g�(**2j|D������emm-  �.]*>, e�UY�6�۷����(//�YO�=j��?p��B���iّ#G�رc����������?Dxx�pss���UDEE�?��Sc����W�^���U(�Jaii)����ԩSEzz�ƶcǎ��{��11v�Xamm-����| �b������GXZZ�nݺ��~�MV�Um�ŋ �m޼yR�����Ө�{�������o�6��5),,vvv�x�Wjl�����ѣ��������Ǐ999Z��v���1����z�]�xѠ>B��x��1v�X���"��ͅ�������=���������~�bؿ��cղeK@\�rE���#&̍Pll��ر���9s�R��N�;v�nݺ !*շ�zK ???��O?�.]��/��B!��ٳ����pvv���bҤIB!rssŤI���������������:�y�}DXX�WRR������h׮�HJJ���b��٢{��R�ݻwK��Ν1jk�1egg �RY�D�O�>����jGW���O?I C�WӦMETT��z����[�l��ٰaC���&/-Z�?����������())���R‘��*���ܳ��DHH�Tב#GDRR��sYY�X�p�T��ɪ�Z׮]�ٳg�|�Ѧ7�xC$''����K���ۧ���%���֥K@������R!������#G ��&����}�oSn�s�='JKKEii�����������DZ�>1�1�V�!�\e9}n����Je?��#i߷n�111"##�Z\�<� �=�Q&̼��j޼9:t�����C^^,X����1 ��O��_~�e���ˮ?)) G�Avv6�5kX�|9��쐝� WW�jeΝ;�_~����h޼9��g���f�ܹҲʧ� !�P(&m׮];L�2?���tMVm�a�~0�����x� ,Y����gQ�������V�^���xܺu @Ń]���K�������дiS��^�|9����������.//ǴiӤm+o&>|�0JKK�T*ѧO�۷�~�)������\�~]*����u�K�.E����)�p�����{fffx��p��a}� Cb�:u*N�<��ׯ㧟~BHH����[�F�~� ��&����{]s���/��>k�,�ܹ����)S�hl��q��Q]���!磋� ,,,PRR��˗�ԩS��󃿿?���`iiY-777�?^㘘 �B7R!!!8t�JJJ0`����`„ HII����ѻwoi[C�����B�nݺi,����͛7q����� �r!222`oo��jVVV(++CYY�J%bbb������P*�(((@HHH���CXX�A ���;�oߎ�cTT[��� �b���JKKѫW/lڴ �:u�[ϣ�)�!x�f`�q�����۷C� .���ǒ%KPPP���T=z�6��Ν;k����#����������R������طo_��j]޺uk���j� ff��V����TFK4 ! �-** �����OH��͑���"��M�5�ڞʄXggg��o޼Ymۇ���} ���熜�NNNX�n.\��� lݺU��������F��������07RDBB�: ''_~�%z��eН�O����sss�;wiii�+//O��A���DAA��}�\��I�&aժUHOOGZZfϞ-�]�����{�nDDD��W_�]n�С8s� ����ŋزe N�8�m۶aƌҺU�V!$$DV�,��A�1����_�ut������Im�ťK��� ��<� ��`�����۷okl#������U�񏊊��,��rrr‰'��[�n�r� ���o��2)��j�X^^��\yy9���PTT�����74�f͚I��޽۶m�b�55Uz_5y���q����@��Le*�� 9��ozsrrp��alڴ ӧO�B�@VV�-[V-����;*_��07R���õkװ{�n 8 ����X�v�4�&�����D�:t@�=���/K p^^������#003gΔʜ?^���{�.���&�B!%����������ɓ��ꊱc�b�Νx��u������ի����@�]�|mڴ���%����?����عs'�,Y����e���� {{{���I�Ι3III�3g�j��G���o��6��m���F^^&O� ggg���aԨQ��Ζ��f��n�*� nnnx뭷��S��燵kעo߾���B�޽����+V������Z�(�Ν;5Fw�Ν ܹs��_J ���W�Z��~�M*_S���S�[�naʔ)pvv���-���5�ZOMMEPP�6m�v���ԩS��M[[ ��/�s��X�|9~��������/�{�ni___�}�ä�$���N�:I�~�޽������`������U��N�:�e˖ }sR���K� ��殮Ml����裏C� ���X�m߾��^�%K�,AJJ .]��w�}WZ�� Am�9}}n��XRR�?�7n�@PP^z�%�������D��/:v�hp���ޯ���o߾�M�6�ϛ7oį��*-�6���7�}ZZ��'�h=V�%��(//���;wn��}ڷo/��}����Q�Ν;ҝ�U_��ᢠ��D-��ؼy��ܹ��ݻ�8y�X�~��={��r�>^:�U�1��� �]YY������/�\�v�V��KJJ�Ν;�?��SZޢE DDD 22]�t�UWdd$v�܉��~�w�ָ�O/��2֮] �J�����x��waii�޽{#11��_���"|��3f ���`ff&�f��7�j{�r卭 �ӧ �~�m�?�V�2e�4UU�+������:� �!X[;+o ��� ��n�����F���?��+V�ƍ�ѣGk\O�P 2AAA8r�֮]��>���!5*�|� .]�kkk��曦o��F,55˖-C@@ڵk��K���?����+fϞ���W�\��իe'����b޼y8}�4��'�g�} 2@ŴNgΜ$&&���?��3JKKѴiS8;;k����M���Q�Q��j̛���wC0U����7n���&L��-[L�l۷o�޽{5f;�G�U�Vػw/�9///S�� 352���гgO<��Sx��7q��8::��_ġC�������ףw�޵���iӦ����Q�-;;+W�Ը��ʕX�z5кuk�����χ��������c׮]RҼp�B|��'���øq�j�׷�~ +++�k�����ԩ�4�w�v�h�"���C���>�$���AϞ=���-Z�u�}�v������Y���84i�mڴ���-Ə�1M[MU�Q�V�X!���}�v888�:$ټ��0b� :TZ#M�V9O2_@@F���]��:�B�G0Y-� ݸq�v�Bll,�;&�]ikk�Q�F!""C� ��<�D�8T���?�D ���7�^��+W�H��^�LO���|�ٳ���HHH�朴��°a�0~�x 6��k2�����a�LO�{����o�Ell,���Q\\ ���Ĉ#�Q�F����đ�� 3=֊����~�ܹ�~�-�߿��ѝ������ |DDDD5a�L����$$$ ::�|� T\cػwoDFF�瞃����#%�'Mmn&��fz,�����ѣ�����_-M/]�vEDD"""�;������� 35XB?~111�ꫯ���)�k׮"##���~ڄQQc��1�7&����>}111���EZZ������������A����a�L … �$�… ��-Z <<�֭� #$""�Ɗ 3�LZZ��$�>}ZZ��ꊱc�b����ի��c�����5&��Heff⫯�Btt4~��7�@���!22 �����#%"""������͛7�GS=zTz4�J��x4�����#%"""�� 3Ջ�����!&& ())P�h�g�}���1bMMDDD �Bp�2����K��>p���hj 4���5j���L)�|L��N�������ݻ���P�hꠠ DFFb�ر|45=�xI��� ���A\\���������������#%"""�;&�$Kyy9�;�ؑ�|4 IDAT�X|��W���ܹ3"##oooFIDDDd|L�I������Ȑ��m�Vz4u�6mL!Q�b�L՜9s������Ajj���������;�0B"""�G� 3���ODGG#66�ϟ��{yy��Cdd$�w�n�����L� s#v�����"::Z���͛7�s�=�����Ӈ��&""�F� s#������� 111���#=��Y�f3f ����GS�L��[�n�믿FLL �9��h�#G"22C� A�&ML)Q�Ä� u��m��ԇ�MݴiS�GS[[[�8R"""���O�{�b�޽�����PTT����!!!ң����M)�� �c�����=����w�^ܽ{`ff��� DDD`ܸqprr2q�DDDD�'^��*++CBBbcc�{�n�GS"22�=����M)�� �c�o��رc��0~�x���C�V�.0"""�'�/� ��ŋ�|�rS�ADDD�`��DDDDD:H�d�޿�mŊ��_�j�0�����0��������H&�DDDDD:0a&""""ҁ 3�L�e1b  �]�f�z###�zSRRj\FDDDD��������H����؅�����2u�bѢE�8q"������5nzG����/]PPP�u�ݻw���7n\]]�T*acc???���#++K��ӧO#""������&L���/jlW��G�bܸq���G�Ν�mΝ;��-Z����%�����G�J�����;v,\]]aaa�3���{�6��hӦ �6m |��w5���vb�ʕ9r$F����L���j}��� �������7n�:."""��J5 ��h]~��QRR"����e������M���?����߿_XZZ ���\xxxsss@��ى�g�J�FDDHu���J�}}}�B��#\�v YYY�u�bbb���(--�������xzz"%%8s� ���q��m���Z�aii��~� 999ؾ};�����/�����;� 77�������Ѷm[�����_F��c���jL����N��:�J*� )��[v;� �2���e������X�6H�r2�0���hd,�h��v���sEˉr�����y<�9�r���y��u�'5J�~~~x���������a{jj*�M�P(زe �d����h\�|������899�O�>��#Gb���q�t���Gni;�����T*#F�����G�����Ge""""*.>��KOO��Z�Vc�ҥ�8q"����n�:i[� ��~888H)��ļ��x={����+W.��o�[��\U�V�4��kv���2l����p�� �J�*e����:C��1��-m��]&&&�>�������{���wذa���EPPV�Z�!C�@�P &&s��� ����!D��̊L==� ��>���lV��{��_���e(*?~�a�G�ey^m������/_��˗HKK�4kv��w�����۷oK���'e/ǂ��Y؃֭[��w�f�/%%�/����f͚a�С�3g�t�7h͚5�[���������9bcc�l�2�7N��jՒf����1}�t����ٳg8p�>������ ۷oNj/�c�=z��[�9::�z��R!|��Q�ƅ 2���~���@__���X�h�V�{C۱}׌3�[�na֬Y���[��U�DDDD�Y�������_�~011��A�޻rZZƍ�J�*A�V��� ���x��������.V�^ ===�|����033���ʗ/�1c� 22R��J����;J�(�={6LMMall�v���ƍ����ʕ+������t��� �J�BϞ=����a���.~��'������;;;899Im����ȉ�c����|�嗰���n����޽{�I."""�� ǂ�}��X�d ������+++�ر���˰���F��:u�@�T"&&*� �k�����1v�Xi�: 88nnn���@||<�?;;; �DDDDD� f""""�l�`.b|}}�[�i�������Ƃ�����(,��������������(,����������B��3Q��f""""�l����q���n���舟~� :t�9��3�2i֬V�^��+�����ر#���p��1���[�S̲z��%V�\��s����8;;cΜ9�[���鈈���s����ŋc��HHH�B�@׮]1{�l����������b�\�������˖-���ϡ����}�bƌ�\���񈈈���ԃ0w�\�Z� �����Ӄ��<==aii)w<"""�b�sw��=̜9��RSS����#F`ʔ)011�;Q�ǂ�����ӱc�!`hh����c���P��r�#"""*�X02!!!�6m���(W�&M��ѣGC___�tDDDDE �B��������P��N���C�B�R������a�\�:tӦM�ٳg������B�~��T*eNGDDDT��`.�ؽ{7�M���W��U���3g��� �B�DDDD� �"$==>>>���­[��j���ٳѾ}{��N,�����T�[��g�����NNN�;w.�4i"s:"""�…s�����+Wb�ܹ����i�s��A�:udNGDDDT8�`.�h�",\� P(�֭f͚;;;��h,���Ǐ���˖-Ë/�����}���� _|��񈈈� $��PLL �Ν�իW#99*� ��􄅅��񈈈� ���ݻw���͛7#55���5j&M���,� 7n����ӱs�N!`dd����c���066�;��X0��ҥK����޽{&&&�4iF�}}}��Ƀ3��ԩS�:u*�?�����?����C�Rɜ������b�LY Ĵi�p��9��///���:::2�#"""�4X0S���h4���ĵk�vvv�9s&�w��B!sB"""��ł������-[���� ���/�v���駟жm[���̔+)))X�nfϞ���(@�&M0w�\899ɜ����(�`�����+V��F\\�m۶�駟P�vm�����Q�={�E�a�…x��  �w�Y�f�Z�jr�#"""�h,�)O��'Ob�ԩ8q�����������J��9��X0�,8OOO�?��_��� }�������鈈��� f������>}:�������5k\\\�P(dNHDDDĂ� ���tl޼^^^�}�6�N�:�3gڴi#s:"""*�X0S�����u��a��و��4m�s��E�ƍeNGDDD� f*p����|�rx{{#..о}{̞=�jՒ97,���z��)-Z�� ��ӧP(puuŬY�`kk+w<"""*&X0S�ooo,_�III���E߾}���kkk��Q��wQ�gbboooDDD`�������ƍQ�jU�=111rG�Q�:u�y�f鵣�#|}}�M[[[h4�|m����8`�L����V�X�7n���HMM����acc�)S��ѣGrG|�����4i�ի'w���DDD� f*t>��slܸ����޽;�����/��r�ʘ5k���۷���Az=f�����ٳg� ������'�7o;;;�xl���*l߾�Es1ǂ��$��������bÆ ����իWѭ[7ԯ_���9�6m��������Z��B�@�-�`��j�*W�211ADD���F��_�>� &������իWGÆ 1|�p��ׯku��7F���B�PH�?�O�R�h.�X0S��T*1`�������*T��s�ΡM�6hѢN�>���J�*� ���+V�z���ӧhٲe�rM�8���;������ ؽ{7���aoo###ԬY3��^�ѠD��R� ���лwo<}�4�����1y�dԯ_͚5�СCs�"��Es��o��b%)) ˖-����t��:য়~�������ϛe@�'�H{{���o���={�H�%''�gϞ@�r�p��a���� 3+����4inݺ�3f���{��E�Z�ЫW� �0&""zg��'�T,��jxyy���ń P�dIl߾իW����޽+wD""*�X4?,��X311����q��M|���������Q�J�3<�;"@,���Dx}���+W������o����e˖���?��?~,wD""*`X4��(׮]���'4 �(]�4Ə�q�����P�xD�Ƌ��ro�޽�ر#~���l�KKKÖ-[�2e� ,, ���(%} ,���q��y��� ���b�ԩ6lJ�,)s:"�`&ʽ7n`Æ Z훖������\��5j�c2��X0i����:u*N�:������'<<<���+s:���`&�_}�BCCY0A\�L���M���ɓسgjժ������o�E�jհe���������� f�\�СΟ?��۷����ׯ��;""�"�3Q.) ������X�~=�����]��A�8|�����-�F[[[�c���� ������n/ ��|4h��zcm���ӦM˳�Q�Ƃ�����������X�l*T���g�����Z���ӧ�HD�������ۉ(k,��>�J�¨Q����e˖�_��ƍ�S�N �;"�V���Q�~}�u���ر�{3l�[�ƌ3ЩS'T�\+VDXX`�ʕ�Z�*J�*sss|���HMM��n*� �=��u��E�*U O�>�*�ÇѡC��j�-[�5Bbb" ,, ���:t(nݺkkkX[[c͚5Z珏�G���Q�\9�)S��˗/�c��F�A�j�`cc[[[L�8FFF3f�V���]�y!::�۷������0q�D���>��3;v�c���{�1"�sk3>ٍ����͛7Q�N�(Q�ڵCRR�V�^�����oѢ���2��c??*�X0�L�<�n�����ahh(]$�����G�D��ݻ74h���̜9S���֭[��s��֭[ E������عs'�?�������O*hlmmQ�V-l۶M:��͛ѭ[7k������.bcc����C�T���p���^��+WƝ;wp�� 2D��}��ABBn߾���H���`ƌ�q��RRR###$%%�ƍX�z�T�e�_9������Q�lY�����ŋ���Ê+NNN~���`899iu���'�����ݻw/���Oܾ}���زe�V��^�z�q��x�� �O�������pc�L��J�.��3g����7nJ�(�m۶����ƽ{��H�����.]�ԩS����ƍgY���S�eV�ҥQ�\9� �7�[YY�s�θz��t����i�&��Y��� www�3�,Y�?Ɲ;w�P(ШQ#���纯�双�ā0�|���cǎ����t\N����ϡR�P�re������ � y�?��?Ƴg�p��aL�4 %J����<<<��� c�ܼysx{{#55.\к`�n|�m����B� ���@�-�U�"""p��L�4 J�-Z�@�F�2�;�~��pb�L�OLLL�p�B���?:t( ֮]�/���}�>|(wD"Ill, �4� ��Y[[g��޽{ѤIXYY���6l@rr����� !!!�����#G�����-[j�qʔ)�Y�&:we���o��p~me�?::ЦM���x����{3ۨ��+ݟ]�TJ�&>6N��G�A����*T� -KxS0'$$�ŋ8t�BCCabb��>�L�6�m�_�K������!%%E�����A�Pd�nii���y��G� f�|fee�U�V�����ׯRSS�t�R���`�ԩ����;"LMM!�@ll��^V�S��]?~�nݺa�ĉ���ĝ;wп� �ZT���ڵ+6oތ͛7�����c�Z��ҥK�s��a߾}عs�{�r��cfmZXX@�P��իҟ�###�u���fm�gE��s������+W �<�ދ����� �z��x��9���������8r�ֳ��B�8�o����w�Կ7?�O�<����o��|~T��`&�D*W��M�6!$$]�t����1o�<|���3g/!YU�\���_������`�-�������8::J�ɮ]��������4  ����ݻw�J��(Q"�>fff����pq�6*V��6m�`�رR������������ϊ��W�Pzzz8~�x���j���Z�l�_��^������n�:t������� ����۷���3/^�'3�����oN��\�2�W�.�y�s��{c�1�~,��>��իC�� 88���HHH��i�P�re,Y�D�?A^�z�'O�i�8ٺu+���P�Lxzz�믿�z������hѢ�6m�o��M�6}o�֭[#%%իW���M�򅆆�I�&066���#z��� �ԯ_...�R����mmݺiii����� IDAT���!ڷo/]s�m�>6V�m��� ,@׮]ahh��K�j�}Æ ������ j֬��]�bԨQ�v'''������:t@TTT��@�����|�9�o۶mظq#�֭����v�����Ϗ ?��W��*((?���t��+��������k׮�� 0��O� ���T���;�U�V7n\�fiذ!����Ç��y����W_!44W�\�.Ф��3�D2k޼9N�:�?���������СCagg��[�"===�����,X�&L�#6A.\��۷��'�'��윧m!44�{�����'�DDǎq��El۶ U�V�͛7ѧOԬY�w������p�… Y4S��}�6���`ff�v��aɒ%�^�z���nݺ�޽;V�\��nDD�d@�����?0k�,�"����G�����3=f���X�`���I�ȇ,� ��ᒌ��3Q����U�Va�ܹn���q��a�…� 6,��� 梋K2� 0�J�ѣG#""B�[p-Z�(�/�"""*�X0����|��V�.^��ƍ�L"Qa�LT�ر!!!Z�x�b�?�E3Q��&�DT`���b̘1�>n���B`ѢE���a*���@D�{�a&*�6n܈���:vɒ%;v,g����>�AT�8p��._����P���1c�`��Ŝ]$""�,�� ����!!!�r� �\����P\�v �^����֭[#00�E3Q.�`&*RSS���P�� Eddd��F���K��h&""��Doa!I]�>}�e��c+�菈���(��Q&��*h|||зo_�cK�a&""""� f""""�l�`&""""� f""""�l�`&""""� f"\�x^^^��������S����A�P@�P """�����h�m���y�̙sssԩSG�DDDD f�O$)) ���r��sE�_9����>(�AD"�_�u��I��<�J�077�^GFF !��ի��^����U�VB1a�@ kkkall,�S�R%���s!����B�PbȐ!R�+W�H��7.�����+++iKK� �/]�$��~������c���Z�k߾}B�RIccaa!�J���+W�H��!��޽���B� ���ڵ�{�/_^�x�"Wc����~���L��M;ok`` ��̄��������x��U� [�lD�>}r�KDDy�3�D9HMM�?�P(زe �d�v�X�۷���زe � �m۶6l;;;$%%�رc�-]�44h333���!%%����ŋakk ���@�R}И�ۯs��!** ������W(��� ���BWW7Wc�3g�F����ĸq��ʕ��ٳ����=z ((�e�5���v���;(�J��#�}�v��#G���'و���`&�A\\���bŊ�U�X1ۂ���� �@�Ν�w��,�IJJ��;;;���׮]êU�P�vmܺu ���.?|�P��~�~��8s� �j5�.]��'"** �֭���P�����,�hۯ��X�yLLL��SSS����-[6Wc�6���������,�����RSS ���]ڎ��I�����#""yqIQ�.b޽ �޽{����������B�nݺ�{�.����}��������FFF�ի�V�� ���XaժU2d bbb0w�\i�73��x�_o/7�ӧ�����G�r�>h �xS����,�zv;3ڎAzz:^�|��/_"---�<������_���۷��o����X0�z��077?~۷o�ӧO�d�\�~=W�z�����f͚���@Zf��~���\�rR���,�*U `mm�^az��@JJ /^����͚5�СC1g��6po�y{�6,,L���F͚5�[��������Ҷ��X,[�LZB�!c�1r3>>>��ׇ��~�u�y���f̘���ܺu �f͒�oݺun�JDD��3Qtuu�����t��� j�&L� i@�� �L�2��kעcǎ�_�~������:th��r���4�7�*U�Z����,--��� �/8{�^�zR�-[===( $&&�؎��.V�^ ===�|����033���ʗ/�1c� 22���c�f �h'&&_~�%lll���9::�w��y����> f"- 8�֭��� T*���+h4iM�B������j8p 4�R�����jժa�ʕ�7r�Hi}n�5P�^=�r���aĈ�S��J%bbb�R�P�vm,_�cǎ���\�2~��7X[[g��!':t@pp0���`aa���x<�vvv}�e˖��HDDo�]2��p��]ԫW�J����)�}j�Z�XDDTL�`&�B����hذ!BCCѥK�ڵ �B�XDDT pI �J�®]�P�lY���K�HDDTLp��� �C��]�vHOO�Ν;ѭ[7�#Q�f"*T������ !���q��U�#Q�f"*����M�6���gϞE�2e�DDDE f"*�^�x��M��… hӦ ����R)w,""*��$�� %h4���"00�'O�;Q�a&�B�ĉhݺ5������޽{������0Q�֤I,^�0x�`\�xQ�DDDT�p�����!C����GŊq�����������DT$$''�E�8}�4�5k���@�T*�cQ�%DT$�T*������ ǎÄ �DDDE f"*2������%J`���X�v�ܑ���`�LDEJ�z��r�J��#���˜��� ;�DT主���Crr2\]]%w$""*�x�IiiihӦ ���/ԯ_Ǐ�E�DD�A8�LDE�R����/����aÆ���� )�DTd���B������ׯ�ҥK�DDD��dQ��}�v���AWW���h޼�ܑ���� 3y={���ɓ�����={��ݻrG""�B�3�DT,����S�Nؿ?q��)���� �0Q��T*�u�V|�嗸|�2 ��6X0Q��V��Z ___̟?_�HDDTpI;�w�F׮]����={��m۶rG""��3�DT�t��^^^HKK���"""�DDDg���XB�����������ӧall,w,""*�X0Q�����F�!44]�v���? �ܱ����� "*� ���2e�@��`�̙rG""��3�DT��}��HOO���\\\�DDDg����kӦ ~��!���k׮���� �0�}�����lllp��9�.]Z�HDDT�`&"��^�x�&M���ŋ��믱w�^(�J�c�̸$����300�F����)<�~�A�HDDTp����Ǐ���3RRR���777�#��8�LD�M�b�…B`РA�t�ܑ��HF�a&"������v�Z|��g8�1.� "ʂJ�������� &����d�f"��iӦHNN�ڵk���!w$""��8�LD�����c�ʕ��Ç�̙32'""�O�3��1c� 99�������;}"\�AD����T8;;#(( 4��cǠR��EDD��3�DDZ�������Q�R%�9sÇ�;},���r����X�n�/_.w$""�g\�AD��mۆ޽{COO���h֬�ܑ��(�p������� 'NDrr2z��{������� g���>PZZ:v��f͚8y�$ �EDDy�3�DDH�T���666�t�,w$""�,���>�Z�F@@�j5�n݊���������d��F�nݺAGG{����_-w$""�#�a&"�]�vŌ3���777DDD����� f"�<2}�t��� !!...x��Y��������yz΂�N�:ؼy���S�����&_�xc׮]�رc��?�����]�|���yv��������}����"z�3QQ(ظq#���q��U 0�r՛��������&��I�P�^=��|��>���tL�4 3f̐!U�0}�tL�<���n�`&"�CFFF�h4(]�4v�څY�f����s����j����9s&`��� ��ѣamm�x=s����͛���'O�D||< �K�.x�������accCCC���cڴi�[[[,X�M�4���>7n���(����(_�<�j5�Ν�e�o����1c���'͸���Hqf����q���l��S3���#������FFFppp@xx������h֬J�, {{{\�xQ�1˪/�ڷoJ�,��u�~�x����+��ݻw;v���1ʖ- $&&J�oݺ��M����5j���S�>x����4h�:::8x���}4ADDy���B�T �B!4�VDŽ�� CCCq��M!�Ϟ=!!!�v�u�� �T�ZUԬYS$$$H�5o�\������x���+1z�hѲeKi�������Bq��Uaaa!6mڔ�5j����HLL;v666b�̙��˗�ĉBOOOܸq#�~��� +����N��؈?��S!�����2eJ��k׮�!Of�Ω��qrr...R���0-尷�aaa"))I�5JԫWO�1˪/�4h�;v�{�i;���;��������.����x�ⅈ��M�6�|�����Ç�^�������Q�*U��:��|����B�9R 6,���� f"�|�믿 B�V�k׮���[�����عs�x���{۳*�V�Z%��v�P(R�"����BGGG��������k�"<<�.]�������R����z�B�^����K,^�ݺuC||E||�T4߽{zzz(W���͑��������@��ų����D���\C�18�LD�� ��h`jj����r���p�� ;v�J����7�mۖ�~/^���q�P�\9cŊعs�T4O�8���;������e{�w�>���add��5k�СC^ϾN�<���G�f�0t�P�l�2��\�T)4h����X�"�׳�O�>�u{��;�>fE�ѠD��R� ���лwo<}�4���r�:t耣G�~б�v����� �B�ݻw#::fff���A�J���o�I�w�څ�;w�v��pvv���S���j��j,�;������8�ů�&"�D�-[�1c�����N�����ܑ�{�����q��Q�����P�~�:Z�l�{��IKD�� f"�OhРAX�n*U��s��e{Mk֬��c�2|{i�o߾hѢ,w*FX0}B���h֬Μ9�-Z 00�����8IOOGTT��T�r�޽{���ʰ��(��`&"�Ģ��Q�^=DEEa̘1X�d�ܑ��(,���dp��4k� ���X�n(w$""���AD$� Hw!6l���eNDDDYa�LD$�=���puu���DD��qI��RRR���cǎ�aÆ �J��;��3�DD2���Î;��g����ƈ#�DDD�`�LD$3SSSh4`�ڵ�WQ��%DD���/���===:tM�6�;�3�DD���&L� ])w$""g��� ���4t��D�Z�p�� ����X� 3Q�T*��� \�xC��;Q�ǂ����)]�44 ����e�,X�@�HDD��dP�v�B��ݡ���}���M�6rG""*�8�LDT@���`���HKK���"""�DDT,q����B�[�n�h4�Q�N�> CCC�c+�a&"*� 6n�;;;���b���<ѧł����366F@@�j5���1{�l�#+\�ADTH8p;vDzz:ЩS'�# �a&"*$ڶm�y��A�o��ׯ_�;Q��f"�BD�޽{c۶m���/q��9��j�ci,��� �/^�q�Ƹ|�2ڵk�?��J�R�XDDE�d2�h4055�������)w$"�"�3�DD�TPPڴi���T����gϞrG""*�8�LDTH5o���χDHH�ܑ���$�0rX�~=���q��Y�������Ha�LDT�%'''cIDAT�iӦF˖-ȋ����dr*� ~~~�P����/L�0A�HDDE g��������͛7Grr2֯_www�# �a&"*"6l�+V���g�ʜ���h`�LDT� 4�F��˗/ѽ{w}�@�R����hҤ�ܑ�� �0a�{�Ƅ �����ݻ����rG""*t8�LDTĥ���}�� D�ڵq��q������ 3Q�T*��� \�pÆ �;Q�‚���(S� v��CCClڴ .�;Q��%DDň��?\]]����������Y�HDDg�����nݺ���iii�ݻ7nݺ%w$"��3�DDŌ...@�5����T�Rr�""*�8�LDT�( lܸժUChh( Νe�3Q1�V��Z ???���OrG""*��$���ۿ?:u�!бcG�#8�a&"*�ڵk�9s� ==���Í7�DDT�p�����B��� ۷oG�*Up��Y��j�c,���/^�@�F�����c���P*�r�""*�$���```�FSSS�۷3f̐;Q��f""�=z���HOOǶm�УG�#Ɏ3�DD$iѢ,X!���q���#Ɏ3�DD���bÆ ��/ �#Ɇ3��իWh֬���ѪU+����w��u���e� 8~~~O�}o���<����d�g_��y���=���>�rtG���� .�����V�nݺ!11K�.EUU�3��i�q��V�y攕�aŊ��ݻc�������v��F#ZZZ���^�zA�VC��v�j6� �x`;{�#�m�6L�>���6�w��šC�p��!<~��~�mi�9wO� 3�<Ν;����_|�իW{����F�t:���"���d�…0�����֪����_9z�(���a6�&L��Y����z���cǎ��q�c��1N�w}"�Yܟ��*����)55����)22�֬YCDD�ׯ��={���/���ѱc�ڵy��I����{���j),,�����… �N||����oϞ=DD4u�TQv��q��Ƞ.]����?%%%��d��{��1JII���P�h4���)99ٮ�?��#�������G�;v�ĉ����j"":�<���Rhh(��j�������2e ݸqém'O�l��:[ۢ���RSS)88�����T%���‘|%~'"ںu+�5����H�ѐ��/EGGӌ3��-xkL�#//O����-ʣ��%''���� Q����lb}��ŋ��,cGW�>}��F#EFF�V���� JHH����v���/��;V��]�]��[��Ɠ|"+���sTF�,y/Drc[i�v�u_�9BF��BBB(((�>��#1��̙#ꕖ�ڴѿ@ݺu�G�9���[o�6>��c�������g/N�����}B� rrr��qhI��� s�=�ERRR����0jhh��޽�|}} ��j '�ZM(88���ˉH>�,I��o���Bn~~>i4��i4ھ}���~��vu�j5u���&��f������Z�9y�Sۺ�0��lm���0�9&&ơ|����ž|�~'"�?�(7 ,ڋ�����zQ�c����'���իWE;z�^��ݻ7�޽{+��;f;:c߾}���gW�ڵk���*�d|��X��;*鿷PjO�,"�f�y��x��Js�3��Ѯ���ӣG�����T*��3g�����E�y��9����C�t���~l���8Q�kO����r���%�2 �l���é���֬Yc3�-ZD���4f�Q�k�."z2�,�)""��^�JDDgΜ!@�Ǐ�7l� �X�n];ݬ�/&&��=JEEE"�����f��ZM������#��� ><<��f3��f %�R�(''�sg�z3w(�Pjo�w��h�,��܍���hgX�uԨQt��U����7�xC�����DD��{� ��ѢE�D��� �r***D���`�s�+�( ��~��D�מ��� �6�L��fƆ+V 66�7o�k׮��̄���L����B��7'O�DMM ����=�J(,,Dss34�!�j�*���F��={�����n݂�dBmm-`�رHII���`ܸqؿ?nܸ�S�NA���d2����3g���p��y!344Z�f��V�BYY���A�!99���R}����L��m_�X�jƌ���e<-���?~�����k�.���O�����Ǐq��MqMee�]�����Fٴӹsg$$$ƍ�'N�ڵk������������Eqq1:w�,�7n�"���L���f��*++;$$$`ٲe�λ��PG�e0���R�x3w��OPjoģ�~p�lr7^d�{���9Z)+V���`,Y�������>}:�Ν�ݻw���ENNfϞ��[�F��~��I˔�^������>!o�036��� ���/�^{�5�҂�M���D����Z���inn�?����]�J�c��/477�����822�溈���d2� ���h����&������ǂ PSS��7�s=z���={0h� �~X�ѹ-C�U$�i��V���_y�|��صk���햻3&oݺ�n���G�xrC���Y\\���b�t:̛7���8x��T*�;֮nJ}� ;���9�u;111�d;�/"r�gJ�����N��E�6�ƣ'~p�lr7^d�{��Q�*G+%**�n�,�&L�����������6l._� 6;Gm��j�����Ç�v횘�[�x���KL��6Nd}��|�������`�m^�Z->����;*>�������Ynx�o�J����:k�m��> E�n���{�l�޽{���ٳg�d2�����٘9s&T*jkk�r�J���EF��lI�T_��/����R����PUU"B~~�K��IW$&&����梲�#F�@BBQ\\,V� `3~�Q�gv��%�(�\8�/O|��.��J���ڊ��&455��l�'񗗗���<�����Ɠ|�!��܍���h%TWW���WkY��9�ԩS���/AAA�:u�Ӷ���0z�hq���)>k�Zt��ɥ~m��_��?�� @.6y��x̐!C��Y�����/ΙL&�]�V�D�~<{�����ܿ�� ����� ̄����m����-((7Ԓ��8q¦]�ٌ���o���ѣ1k�,|��7b�m2Z:������B���2� �W_}�χ��`0�KȖ�e D\\���|�M��j�9UUU8}�4Ǐc����2vt֯�C���’�,]�w��A]]���kӮ��ϼ�;�������t��tX�f��������HNNF^^�S�el�i>y~��C�Ƌ�er�R�.]�˗/�ʕ+ba?~��l4�2ˤ?-- .����+�7nDRR�oߎ'N�G%dp������ 7b�����K`��?�K"����,>>^\�n�:���ܹ��Z�8���I�׋���TQ�ҥK��^뿺�:"r��==�o���.~~~Էo_�h4���l^(��{pp0EDD��Ͳ]�3��'��#[8CFw}aA���f������5�� �=dl�i>yZ~��C�Ƌ���h�l۶ F�!!! DZZ����v/s͙3G����bĈ�eL�6 gΜ�g�}��}�����aaa;v,V�\��� Em��kw����|l�����&�s��$v?�0̓ aAA�,Y�������a�!��7� "�ڵk�駟v�JR���?�l޼ӦM�g��a�����F>|���X�xqG��<#�mۆ޽{#..D���(̘1���R̋���O��a���N���&���{��:�b���\�x��}�w��i���΋���?��d0 �0 �8��`�a�a���a�a�a��f�a�a�qO��a�a� ��V��Xd�G<�0 �0���������IEND�B`� abcl-src-1.9.0/doc/design/streams/pprint-solution.dia0100644 0000000 0000000 00000162304 14202767264 021317 0ustar000000000 0000000 #Letter# #solution to the pprint/gray-streams problem# #usercode.lisp# ## ## #gray-streams.lisp# ## ## #streamfunctions# ## ## #Stream.java# ## ## #methods for stream-write-char etc., as allowed by Gray streams# ## ## #slots in Stream structure-object# ## ## #pprint.lisp# ## ## #system stream slots# ## ## #write-char# #old-write-char# #stream-write-char# #binary-output# #binary-output# #binary-output# #binary-output# #write-char# #binary-output# #primitives move to here from Stream.java# #gray-streams either calls a method or a saved streamfunction# #slots allow for dispatching# #pprint creates wrapped streams, and sets slots to contain closures that extract the underlying stream and invoke Stream.java# #system slots invoke Stream.java# #Stream.java contains functions that are overridden in extending Java classes, as before# abcl-src-1.9.0/doc/design/streams/pprint-solution.png0100644 0000000 0000000 00000427373 14202767264 021360 0ustar000000000 0000000 �PNG  IHDR-v����bKGD������� IDATx���y|�g����!��=� 8m��*�Z���"i�Z”�h���Pݦ���:Ӣ�3�Cі�����v�Uc$ �"�F"�=�8�?2�'G��s�����x��89�}_����>�s>�}�,�E��d*���V�n]m۶M��y��;T��w��Ǐ+,,LG�-�Pp�2Qi �r+-�x�}���>}������@�Qi �R���^�z�cǎT\��HZ�T���j�ƍ$.Pl$-P�<==I\��HZ�L��@q��@�!q �� i �2E��"i �2G�� i �ۂ�%�E�� �K�å���e޼y�W���u�wﮓ'O*11Q�;wV\\����nS�pv&��b)� ���L&I���Q�֭�k��ׯ���ߗ$;vLu��-��p!i � i �O�z�t��q����3-8��� IK(AAA 4nE/�u��)$$��:Ç���㋽���'��j�m۶Z�lY���v)��sd���맷�~�X�qVe}���Z�j��˗��4>���0{8���'O�СCjԨQ��g����T�R��e�v����?��o�`��2����� �6*-����իW/������_�۷ץK���O�VϞ=��奀�M�0A���v�k�� /���^zI�'�٬�#G�ȑ#2��2��Z�h����+d6��/��"_�E�׶m[�3FݺuSݺu���+33Ӯ�퉯$�cO����o��U�Vrss�FF��~�iU�ZU~~~>|��^�j��%)44T���j׮�7n�!C�X�_�rI �[o�����N�:����T��u|��\ӧO׳�>��U����ǫM�6���Txx�z��7�x����ϟ�� ���C���?~�nܸ!I:t�*U����4��}�����C.\�k�m]���V�E����n�:5j�H���WHH�&L� ///�;֮��Q��˞����W� �����h]�r���l�_A�s�� ������%�ԩS��⢔����j�̙�X���|ذa���Wjj���ۧ5k�h�ܹ���ƍ+11Q .Tpp�����#F� ��kזs�9썯��ruuU�J����+>>��� ��5k�V�Z 3�?q�6mڤ�3g���[���z饗�f���8p�\\\T�BEGGkݺu-�rƸY�f�$___�jǢ�����_��'�|Ru��5�;z�������^����:t蠎;CA�GGG�)22R����v�<�����K�IT�Z�JÆ �;n[ן# �ߞ���w�}�T������ڵk�d2�ܹs�q�/{���{N5jԐ���F�e��i���:>� [{+mpo i �0i�$�h�B���������?��ׯK����d�Xh�_�fM����W�V�����x]�bEeee������������Ո���Ӓ��ݻ�?�쳺v�C�������������rI2���3����� -Z�H'N�z?%%E&�ɨʓd�:���߰a�y��l6kٲe��!�$��������ںu�\]]յkW�6ڶm+��$�ɤ?��V�l]�((~{Ώ�����sqq�����^�-�q�/{����< @gϞ�+.{Ư�񑨴�5&��b�����ٳ%I�VXX�:w���hU�ZU&�IgΜQ@@�$)))IժU�j#w�]�Œo^�$�������o{���p���WR��WZ�/n�kժ%�ɤ��Xyzz:�}���$��իWwh��2�}����裏Թsg5i�����ի�b�(%%�8>��� .p�JOOW߾}��g�)""B&�I/����3}||��˗��ѣz�����?������Q�=�+Ln<��_��_�^������­m���U��8�3�^TZ@1l޼Yǎ����7777I�����v�3f�ڵk:y�.]���(�6j֬)WWW�ܹ3_� 4���/I:{�l�� ЩS��&4����Ta������:u�{��z饗t��yI9�Doڴɡv�,Y����;wN ,�Q�˚�������ٳ5iҤ|˂��ռys͘1C7o�Ԟ={�s�������Rhh��+h2�aÆ��?ֺu�4t�P��f���UV燽�+i�E)��e���׿�U)))�p��͛��}�Z-/�󫴮/��%CLL�y�y{{+44T P�>}��˖-Sjj��U��-Z(**Jcƌ�j���[��%OOO��J�^}�U�ݻWM�6���?�N�:勡M�6�ӧ�4h��� -X��X֮];��f�^�Z�-��lV�=���l�W���~QV�\���lկ__����ٳ��?������ԡCթSG 6�믿��r[�:~��5>K�,QÆ վ}��]�r��o�.???����ѣ��U��k������N�:z����+++KM�6U����[QןTv燽�+i�E)��e��ץKu��Q�kז�l�����>�J��L��+yo{ �I�&i����Z^�nܸ�x@~��z��e�6�{�V�n�4nܸR��]�vz��5jԨRm�n���WqԫWOǏױcǬ&����JK�!�N�� /�`3a��/�(!!A��]�v��G-�8�o߮�� 4�T�pw`"�!����+��bs���EFF*++K����5k��6mZj1�n�ZG�����fy�\����p�}�=��pN��%�B��S!i ��0{8"wBp{Qi ��Pi ��X,��4*-8��� IKN��%�B��S!i �����THZp*$-8��� IKN��%�B��S!i �����THZp*$-8��� IKN��%�B��S!i �����THZp*$-8��� IKN��%�B��S!i �����THZp*$-8��� IKN��%�B��S!i �����THZp*$-8��� IKN��%�B��S!i �����THZp*$-8��� IKN��%�B��S!i �����THZp*$-8��� IKN��%��R��-&���C�2פIm۶MիW/�P�@�%@9���_��gϖw(�S0Y,Ky�ɭ�� ����7����󕚚J�%�_TZ�#EGG�I�&T\�E���U�RE۶m#q �IK'P�zu����p$.�$-��K��%��!q �{IK'D��2��N��%�U$-��K܋\�;�{ݴi����ks��}�*55�H\���ަ����d�X,��d2I���p�ھ}�6m�d׺W�\ќ9s$񹈲3z�h͛7����:U�T�W_}������$-85��`��E�5��@�!q �㙖�;w�, ?��S ?�������+W��w��ڶm[y_���HZP�L&�j׮��Ç��;����>|�Ə_&ۯ[�N!!!e��{�=�[\m۶ղe�ʤ�����F��V��F�U��<�G}TU�T����:t����[�S���vپ}��; ��[�p!�K���� ..Nf�Y#G�ԑ#Gd6�e6��h�"����_���m՟�7*((�H�ddd�駟VժU����Ç��ի������ի�|||�������ҥKv��=�?}��z��)///h„ ���.��m�g|m�g��~�M�Z������q������$���>}��l6�ԩS9r��f�ƍg��m��=�ߖ3g�(!!Acǎ����<==��-[J����t��ϟ�� ���C���?~�nܸQ*����{��l6롇ҫ���o����s}�=�Ζ����l#i �p��q�ڵK���JOO/��i�ҥz��t����ĨF��r*5`������R\\��������C�i�…Fb����7Vbb�.\���`%&&*11Q#F�0ֱ��C=�Z�jiÆ �{+W�ԠA�T�B�Gxtt�Ν;����8qBIIIz뭷���N�*���(55U3g�TŊ�V��?l�0���+55U���Ӛ5k4w��R��{��V|�ڰa�֯_������kŊ�2{�/��+I�%�/�Pbb��W���>�L���z�����Q�S��F�2��;v��o߮+W�X-����t�����������ڻw�֬Yc�-I�$�U�VJLLԪU� \nk��\m������pW8p�\\\T�BEGGkݺu���߿��5k&I���UժU�j����S�J����ծ][&�I�Ν+�>f���Z�r�$��իZ�n�,I:q�6mڤ�3g���[���z饗����JOOWbb�L&�ڷo�ʕ+۽[��x�l٢�'���MAAAz��g�v��R��$��Æ S͚5U�V-���)>>��� :�ʺ�E�ߞ�)��_�bE�ܹS5k��СC���(55�T�g�����킂�����R�=�ڿ�룰�w�`ϴpW���7^���)%%%�:f��Xm�V%�������x/�ϲ�)S���ŋڼy��ԩ���PI9��JR��ݍ�o��4i��|�MEFF*%%E���ל9s�~~���_�xQ��j��5kZ%�JI����=|}}�׮����ʒ�X��e����o������S���͛'I:z���y��3���DG�g�6lؠ�S�*!!A...���P�����e}}�[�Ga��<� G��]!))��u����c2�Ju����uM&�C����͛�/��?���*�Z�j�d2)66V���n���ٳgK�>���0u��Y���Ŋ'��bQժUe2�t��H��jժ�Z��(l|퉯$�����o���_��)��|���kذa�1cF�؊j�8㗞���}���>SDD�L&�^|��|ϼ-Hq�WG�o��(l�?��ı��K(���+,Y�D))):w�,X������J@@�N�:����bm?x�`-Z�H7n�J6֩SGݻw�K/�����Kʩf۴i����͛u��1I����$��ͭ�]���奮]�jƌ�v�N�<��K�����o����������V�����';;[�Ǐ�������ÇkٲejѢ��zŽ>����Leee)44�H��:ٕ�Z�l�W^yšm��a�Gi�pn�*���pW S�T�N5l�P�����۶k�Nf�Y�W�֢E�d6�գG�RݾM�6�ӧ�4h��� -X���� ��Q-Z��w��ʕ+����������S={����Ǎ�111z�G�����P 0@}����EY�l�RSSU�Z5�h�BQQQ3fL��o[�kO|%Q��K��%Q��S�B%''+<<\���z��dT��u��bk�j׮��ӧ+,,L�:u���?�N�:�/G�Urr�C�ػ�®�ҌP�bbb4mڴB�O����`�n�ZW�\Q�^��믿�w�PnL�Ҹ� �H�-��>�BCC5i�$ 8�v�V�l٢�C��ԩSe�/{>��=z��͛��s�jԨQ�pW8s�>���ן6m�$髯�R�^��*,pj<������;����w'��S�ڽ~ll�6l�P���#i PL=��<�Z�j9<#:�‘�p�ۿy����/��w�]��x���� �`-�u�֕�c���4�W>��CըQCժU+��2Do��F������ǗCD%;�ڶm�e˖�^y��vTZ(U'O�ԡC�ԨQ���X���Y�7}�t-^�X��-�V�J��;�2s���������^�z���G���j߾�.]�d���O�VϞ=��奀�M�0A��ْ���8��f�9RG���l��l֢E�Jm����WÆ �����@�?^7nܰJп�u�jǎ��?~�F�mW�}����l֩S�4r�H��f�7��r���뭷�RDD����U�N����áC�ԦMyzz*,,L���V�W�X!�٬��H}����/����*::Z�ڵS�ƍ5d�eff�mC{�!IZ�j��6m*OOOիWOK�.�Z��o��U�Vrss��?n����׶m[�3FݺuSݺu�mo�_xx�z��]`�*��HZp�ԩS��⢔����j�̙�X����6L���JMMվ}��f�͝;W�Ըqc%&&j�… Vbb�5bĈRۿ���>��s]�|Y{��՚5k�%�J�V�:v�={���fϞ=�ر�]���JLLT�����g�)11Q����1�t�R���{:r�bbbT�F �b0`�:t��������l�b�|���JLLԀ �ޞcx��q�ڵK���JOOה)S�e���=�з�~�#F����ץK����?�V�ZV�߰a�֯_������kŊv�O�bbb�i�&>|X�O���~РAj۶�Ν;�ɓ'�o�)��Wq{8�;By?3 �������ӕ��� �}��vo{��EmٲE����������j�ڵz���|��m� Rdd�bccj�0E��cǎںu�$�K�.�ٳ�^~�e���/v'-KC^���W�f�$I���v���a8p@�7oVŊ��1��8P..9�e���������;���*�1\�x��~�i=�裒���=��cV� 6L5k֔$���)>>ޡ>���_������~����ѣ�׿���7���E:t(�cw*-8dҤIjѢ�"##����^ׯ_�k۴�4Y,�լY3���e�)���GQPP��f��-[����տ�J�s���ʕ+���o�jժ�nݺ�%���f�����d2Y�_�vm�ڰ�����������b�^�cx��i���6�ɛ�uuuUVV���K�����bŊ��)))2�LVU��V����JKN�b��w�>>>�={�������0u��٪�-�. ��bu�DժUe2�t��H����T�Z5�}�L�B��g��IOOW߾}��g�)""B&�I/�����m�_��5m�T�/_������k�ƍںuk�V��;�y���ի�b��������$edd8Ԇ=�0))��u���%9v ;�j֬����b.-�㗒�b���d�K<ନ���͛7�رc��WM���f�N͚5f� � IDAT��ꪝ;wZ���奮]�jƌ�v�N�<��K�***�j����:uJiii��a233������P#�W�D*��_��U�PA�ڵ����ճgO=�����J5ii�Wpp��6mj<�111��q*�=�pɒ%JIIѹs�`�#~{���s��g�����7�V���4m޼١>Wpp��7o�3f��͛ڳg�����۲o��������=��#���Vhh� �>}�X����?��ϊ������QU'I˖-Sjj��U��-Z(**Jcƌ�ھM�6�ӧ�4h��� -X�����v�ښ>}����ԩS'=����ԩS��l�_��u��Q...jܸ�z��S�N��3 ��X�z������u��>|�z�!���ڵ��l��ի�h�"��f����Xn�1 S�T�N5l�P����$����s������5v�Xyzz��ԉ'��Q�+�ʕ+�}�v�����7�T�=x�;��d��K�5z�h͛7Os��ըQ��;ܣBCC5i�$ 8��C�-z��nݺiܸq��6l�W_}�^�z�stP>x�%�{^\\\�g �C�ʕոq��C���S�z�`�V���K/iȐ!�9��U�)���� p�/��"�w�}���׮]�4u��� � IK���*&&����=�Y�f:p�@y�a��'*44�LڶX,��Ζ� �� ���TVV�<==5k�,5mڴ������b����vT�U���T���5kV�a���ׯ�w�͘1C:r䈪T�R���7oַ�~+OOO����5j��t �����_�UݻwWHH����6lжm���㣌� ծ][�����4i")g�����X,���T�-����+W��o߾=z�>���"�;g��ڵ��/����k}�������g�}V�X��&�1{8�I�~���7on�>v�X�����ŋ��O>�D?����j�7�|S]�tQ�ƍ�{�nM�>]?���$YU՘�f :T������C��Z�j����O<���d�q���iذa�V�����Լys����Թsg����I�&ڷo��l�̙�_��<==�7�xCy��*�����{�B� �8q�L&�����B�����^�z�_~1>w��飠� IR�&M4l�0}��w�����$����_�~Z�t�$�������O��s���(&&F��_T�reU�ZU�ӟ�j�*]�z��!���7���SO�����X(]$-qO Sll�Ξ=+Iںu��f�v��a�ޭ[7c� 6����<�.]�X�5g�5n�Xs��Qbb�q`߾}u��>|X����W�����m�� .�����x�V�Z%oooc��%K4�|�;wN]�v���3���ҥKںu���׿jŊV���ԫW�xm2�T�n]�9s���s�R��������-IZ�j�ڵk��� ��f͝;��b(W@@���#F����˕����>�Lu��Q۶m%I˖-��d2~$)))I������3�0�����RZZZ1G!G�5�~ �9JIKܓ�W��f͚��SRR�2224j�(mݺUR��e�j {���iǎ�;w�|}}U�R%M�2E۷o/��266V���,X��իK�5j��5k�;V�5����F�]��&����Ǎ��E'N�P``���;vLO?���O��'N(11Qcƌ���.�#�<"}��WZ�t�U��a�d�X�)'�x��eddX����UU�V�$���)++�X~��y�}�&@o���`��X,JLL4Ƣ�m�_���y�����W_-���ז-[�u�Vu��������:s�:t�`�{k5PQN�8!�ɤ֭[�l6�l6�I�&���Vjjj�C�N�������,H�8*W�\�&�k�ܹJHH�͛75s�LݸqC����s��%I9��0�LJII�'�|b׶#F��;C={��w����u�7o�&M�h„ �z�������o���rww�$�l�R_��$)++K�g϶j�Z�j:|�p���Ν�#G���͛�2e�,�1�m�ӌ=����䇟{�gÆ ���JKܳ�u릭[�j�֭ W�f͌�X�o�^�+W��-�ɺ��V�Z�X��bcc���h�dddU��V ծ][�ϟWjj��})nU����jРA������˵~��B'���I�&z�WԦMu��Y#G�T׮]��v�С:x�"""l~�#�|�~��:}��T�~}իWO���3֙1c�v�ءf͚)<<\�ڵ�jc„ Z�x�����fq9r�,???�^��j,��&��x�`�"���S�ޑU��ԩS'���cyzz�G�� �rT�JK�N�s�N��G��#FX�WP5Э ���j����h�"-Z���x�W���˗������do���:uꤎ;�R�J�N�dff:�(��p��A�٩/���f̘Q���W^ѐ!C$�<�ίjժ�\��>��cU���������c���U�n�T�J���O�/֙3gJu����ׯ�jԨ!yxx($$D���WRR�$�m۶V��Q�FQߴi���[�s�۹s����'�l���n���0`�j֬�J�*)00P��o��fӧ�~�:(00P���rss��l�s�=��'OZ�ۯ_?c��w�V�~����:u��>�$-Z�H��ח���~�a������QQQ�ٳ���̙3e2���»t�b��w���>� �|��w0`�|}}���>}���ٳV�����w����ԩ�J�*���[�ڵ�Ν;��iӦ)""B:}�����?��'�|R5jԐ���Էo_�~;�=� ������'O�{���C�U�1�:*-ܱr�d���Z�f�֬Y#�ɤ��P���[�?��ڴiS슭ܙ�s��k�Vvv������^{������JNN�$c��7***Jׯ_WŊU�F %''�O>�W_}�ݻw�Y�f���~�I?���������t;vLK�.�֭[�*U����ڕ+W4n�8�رC�֭3��������+@o��ʖ��HݸqC�t��5�[�N�ň�o�Qdd��]�fl�����Qp(�����K=��ƾ%��ٳ��/�~�z�]�V�[V� �˨�p��������bѿ��/���j߾�5d��^�Z�������`$�>��C�>>���N�}Z����7��x��<�{IK�*33SW�^��S%y��9cٕ+W�j��7oZ=3�ҥKV��#;;[�w���ݻ��k�I��^� �>>>�={�&L��S�Ni�ҥƲ�5kj�ƍE&> ��9�����b�NJJ*��7n����������H�ː�dff�~�yo���� I����PP��#n޼is��l6^���Y�7�x4lذDq����~�T�vm�u���oY�'p/�璖w�L���L���k׮�ʕ+���Ν3f�z��U�*##�xm+x��e]�~]RNb/o�ҥK��ʒ��L��IU$�… Ƭ�ׯ_��˗�e�ϟ7W�Ɯ7��x�b#i����o� /���C�꧟~R||���ݫŋ+))I���Q����]]]�~�{�ptt�V�XQ�?�����lݺ�>��sխ[W_~���x� ��-���+��J4$��׮]3�_�?ns;[�w}����S�+WVJJ�V�\��jϞ=�>�-##C_��ݕvy��Ž=8or�V�nS�R%yxx����t���+W������k����X�79X�bE�䇧��Q���"///c�����$ruu�z�d޸r-�|}}K� �G��ݻ�^���K�߿�z��a�Ǜo�Y�����7n�ƍ'oooyyy)%%�H<����X����d��bќ9s4g�I��r�-\�P}���իW�裏���4?�䓒r����秌� -Y�D�N��ٳg�믿�=�i�������.I2d�Ǝ���4U�\���ԋR�bE-^�XO<�]��w�}W����|Μ9 wx�]\\4�|���W7n�Ѐ \no�9�#�IA�����ϖ*U����]����灯��������!///������Krww��������]AI�[+�Q6���?i����ڵ�� f��\\�����=z��͛W�a��mIZښQ��YW���K����������:���ݻe6��믿��6f����o��#w��&M��رc�L�[ųc�����e6�"端��SO=e,ϝ�7ސ�� Z�|�z���˗k̘1V�����wloիW/�\�RRέ��~����߯O>�DÆ +p�h��%��,ܚh���6ni����h�7XPu`n���䠭`ޘ�?��V���|ꩧ��c������=z�~��'9rDIII�\��|�A=��3�5%I����7o��N���Ǐ;\۫W/�ٳGӧO�Ν;����J�*�q��j߾�q����hӦM����?�۷O���?�_|Q�����gi�ٳ�f͚�3f(%%EAAA�?�>��C���8z�衽{���gΜ����7nl|�S�1����?���S�j׮]��Ȑ���:t�W_}U?��ñ:r����ݻ����s���ڵk�|��.^���W���ŋ�|���^�����_�;wNW�^Օ+Wt��]�zU�.]ҕ+W���,��ϳ�������*?I�"GnU�w�}���N�������ս{w�-�=�d)�W�ɛ�6/�6������V��Օ���ڵk�G�Ƭ�]�t1���l�b����-ZHʩ�ڹs��n�F��g��8qBIII��0��^�zu�����v�ޭ:Hʹ�>w��!C�U��N��W_}UO<�_�^h��V���@G�T�ro����z�����ە�|����J�3P���=���j֬�8Pj�^�tI׮]����J��� ������v�.]���/�ڵk�pႮ\�b� -(�Z���V~t�|aITG�g�SHH���� \�A�iȐ!�f��UQ�@y˭�䙖������o���w�UGf׭Z�����f�-lfZGf�͛��W��պf��j"����Qŝ�6�s�����F�iʔ)%�(��DenE��:�`KnB���~$�1�T~�D�M��M�^�|Y�/_VZZZ�Ǟ�Ŗ������J����d� )))�5k�f͚��� ��xN݌34~�x��Aqg�}뭷���d2�w�1�ύp˗//��///yyy��dYYYW~:�D�m�,�D�b�X�{�n�޽[/�������x���P��,ii�κ���E�wfZGf������#G*33S���������o����ͪ��ُ�wFۤ�$=��V�jРA�����k�W�g�[��W�^վ}�JKFF����/_��p�^=;����ӗ_~))���E=��v�g˞={��{��~PFF�*W���u�iӦ:t�z��i�[����9��8[<�͑k�,��\w�xn�2KZ�;��#���;��=왙֑YfG�!��d�bk�X�`��]�6�D!��[�;����?�P�ׯWvv�z��ٳg[=��ȭ����Ο?/__��3}�tM�8Q����, �����ɓ%I���wL��~PXX��h)g����8������/_��N����lc�l���o@i(ӉxƎ��c�Z�ׯ_�|�}��Gv�٢E �\����V�Z�U�V�\�iӦ�fþU�֭�f��b>|��n�޳�>[���cȐ!2dH�� �_A�92���V�Z���u��E�֯X��z�!���+<<\�۷����$I˻�+��b�}T�V�Rkw���F����S׮]u��M��?�і-[Jm���L��\�;yl������������Y���/V�5�-==]���TaCLLLy�'dk��\<���� s�����x����ڵk�������:u���ԬY�T�fM�����Ϛ:u�v�޵�fr IDAT���t����cǎz��WպukIR۶m�g�c�Q�FiԨQ���7��+qӦM�w{k�[^�nݪ h������R��ݵp��"�a�9")� �I�&�d2I�ڵk��C�Z�kO?�ƴc�͞=[�~��jժ��J���߯)S�h�ΝJKK�����u릷�~��q=�~��f͚�#G�(--M*TP͚5խ[7M���mܸQ�������饗^ҢE�4m�4�8qB͛7�G}dC[�9v�16]�t1��:w�|||$����/����X����d����I�&�6m�&N�Xd<��4�kQ��n����ɓ'k����y�z��Y�f�A׏�1�t��IK��g�y��Cp�r�J��ԭ[7����[�n�W�^�ۿq����u��II9�&fgg+>>^���z��l& ���K=�䓺q���ٳg��_h���Z�v�"""�<{DFFq^�vM�֭��bѺu�ln���X���),,LQQQjժ�Z�j%ww��Կ%''K�ѿ�7***Jׯ_WŊU�F %''�O>�W_}�ݻw�-����yX�u����aw�q E�-E�ܭ��Q�\��\�RSGMk�L�I�I-M����F�pK�-�%1AQͅ����� ., �x|=����s/��>poޟ�g�޽����8;;����ŋ9}�4K�,!,,���pJ�.}��������F�����s܋}��ѹsg���r�,���n�&����l޼�.]�p�� �s����޽�#G�8O^���A������\�=����<���/9~�8{���? ���﷈�Ƚ�h)@��ӋX����[�>=zWWW�V�jt��VQ,~ �˗/S�tiZ�nm�|�' T@�MTT��ش`����/^�~�J�*��7##���@222���eժU��� �_���={Z^��_���ݻY�hC�  $$���@˱N�MFFC� !-- 777v�܉��ǎ�Y�f�����o��?� �� �^�zܼy����3{�lN�>��ի�:������=aaa�=�����'ҿ^�uK��֭[s��y��~ =轹����=����dРA��ԩS1b���l߾GG����|ye/��z/���Z4���';w���Ɔ�}��k�.:�ʕ+�:w~A2���-E䑧�}��Y���]�ҨQ#��"�`�4iBrrr���J�*��ۓ���̙39p�>>>���ӭ[�\�{��K�^�v��޽;ݻw�}����㏜={�C���ƃ�ȯ�'R�lYʖ-K�ƍ9{�,����;w//�{�׶m[�����ٳٴi.\����\��_~������꺜9s&m۶��Օ}��Y��n޼�c^��B��m������ΎV�Z�a�/^L||>�R��.##���*U�D�.]ذa�=��9Q�:���U����0{�^^���޻��Mnn޼��q�������=���}�|�����͛�{�������}ۤ���^CA2���.�cDDD���XN�d;���n����kH���ȯ�R��O�1�ի�ȑ#�ӧ�������:���}����i߾}1��w�pqqa������O>��ӧ1�ͬY�&���m�������r���{� ������N���ɱ]��x�ĉ{�#�<�=���}�MA��;s����s[V�\9�s啹��H~�h)""�h�"233-�w��m`ɯ��t���q��yڴi�СC�>}�����ŋ�ܷQ�FԨQ�-[��j�*�^���_�֭[�Q� 6rv�������{�EmРA4nܘ�3g��?�o�>��� V�^m�&{wYnי���t�����㏖��?�e8w�{ҨQ#<<<,+@���wro g������%K��q�ƖN�={�0e�����|�2�6m��׼���|y)�����uGa0�gjA�粛2e �N��?�`ڴi��;v���� �~�����>�Ї�c������$"���t���[����#GKDn����ݵk�,�;;;����������>��#˶�z��<��I��l6�]��lggw������k׮��i6�Lwlw���帗���sf����/����iӦM���t��%���]gn���_�>ǵ����]]]-�_|�E��l6_�t�\�bE3`���5?����f͚�˔)c������������͛[� �<���)�{���fÆ ��M&����� �K�*uDZ6m�dvtt��{6��|�)�� �}�KA��grww�c�� �oܸq���\��l6����̀9888_�CDD=��|[�~}��f���AiD� ���6lM�6��֖��xhҤ ,`ԨQ��߹sg~��g�w�+vvv���ҵkWv��E�Ν-�֮]����������9���ٳ;v,-Z����[[[J�.���?ӧO���1��̏��={�лwojԨArr2��'���g�������˳i�&����_~�^�z|��'�r��U���A��s�=�����;���������_ӬY�;�}�gؿ?��� ������Q�L�|�I���� ��K~�׼�{.�o���W^y����S�lYz����͛- %��f˶Y�� ��0�H~���j�Coٲe����� n�~� �~��'k�׿��M�6�x�������C�D�XY����<�.33�F���o�akkKjj�a?�� FHH����ADDJ6������Ջ�˗�����,X���/mڴ!44���4�#��C�?�`���w<������� H$"""�5w�\�W��o��@׮]�G)�T��2��������ܹ�#G�D�r�رc}����Ã�'j�_)�O?�����j1��-11����S�|y^~�e>��S�#����JEK+���Gpp0gϞ%$$Ν;�̙3�]�6�;wf����,B��dIKKcɒ%�|]EK�������l6s��%�/_NŊ��$""�+-e˖%00�C��k�.��뇽�=�ׯ�s��Ԯ]��3gr��9���H �z�j�����¤��#�e˖,[����XfϞ���7���L�8���Î;��)"%�… s}=!!�S�NS�v*Z>�*W�̘1c���`ӦMt�ڕ��LBCCiӦ ���,X���������N�8������Nݖ""""""RXT�|������3������ɓ�Q���� >www� �����*"Y�p!f�9��4���������9?��#%==��k��֭[-Ŋ�͛H�^�(U���)E�8\�v 777����ܶI�&�߿�R�H^L&��DD�%88��� �c��H �NK����=/��"aaa�8q�ѣGS�bE������qwwg̘1����FG�"�jժ|,>�իW�8�������< �i)�r��5BCC��Oػw/p���C�ѹsg��� N)"��e˖��2,,����a"). T�^�J�*q�…\��y�&͛7��_e���<��SŔRDDD��:-%_J�*���ٳg���g����.]���_|///�N�J\\��QE��q�F��� �Ν�ĉ�����LJ:u����l�^�Z��X��'O���繭�� /��f��7�|��7ou<�r괔�����ҥKY�p!������ҥK�ԩ����B�ٳ����-Zp�� ���0�͸���PDD ��ŋ}���E�$$$0cƌ��&"""� �"����ƍ aӦM�y�6lH`` /��2e˖58��ԍ7prr����7nGDD����/���>|�'�x"���۷��͛���Hxx8�j�*”"""b�T��"ŧ�~��ŋILL��ٙW^y��� 4h`pBɯ��Xj֬I�5�𖈈��̤t�Ҥ��s��J�.]�� �ҥK�ѣ_�u�k����7n�z�j>��v��ay�U�V 6��ݻ���h`B�ˁhҤ �5���F��"�c�=F͚5���)��qqq���p���m�F�6m� ����X3�i)���ё>}��}�v�=ʰa�(_�<;w�o߾xxx0~�x�����*"�����\�GDD����g����o��6�F��L$"""�_*Z�!|}}����Mll, .�aÆ$&&2k�,���y��X�n���FG�l���ȣ!22��u���1ƌ����bɒ%�MDDD*Z��ʖ-�СC9x� �w���W_�����7ҥKj׮����IHH0:�����U�T18�����prrb���L�<����B�&"""�-��h޼9K�.%..�9s�P�NN�>ͤI����w��l۶ M�*b����."b� ���gϞ<��S$$$0}��ˆ&"""�-�ĩT�o��|���t�����W_}E�v����e޼y���U䑓��@ժU N"""E�0:-L&s����Ɔ�?��S�NF<y�h)%��d�駟���/��Ѽ��;���q��qF�I�5 ����F�� i�•����^�5�evժUc�ĉ�5����B;����X'-�U�N�̙C\\K�.�y��$''���S�^=:t��7�|Czz��QE�F�B<���'��RX�Y�nԨQԪU�#G��hѢB=����X-����ī����ݻ9p�C��L�2lٲ��={���ɔ)S8s��QEj7n� %%*V�ht)"E�i �~g����ltT�%)) ���NY�Y>���Ez��U�2i�$�|�M222��|"""��Q�Ri���L�>���BCCi۶-�/_&$$�� ҪU+�/_n� S�Qv��y@��ED�YVѲ�W��#F����ѣG���S�������"����z�b�֭;v��ÇS�|yv��E�~�pwwgܸq���FG1Lbb"p�;FDD����O���ёٳg0e�.]�T�������"��_�>���#..�O?��ƍ�����ٳ�S��>�,k֬!33��"�*kx�:-ED��ɓ'�mE�]�Ү];.\���iӊ�"""�p0��f��!DJ��{��W_}ŵk��Y�&C� a���T�^���"E�e˖���/���O�j���8""R*V�ȥK�HLL,��׎9B�ƍ����ȑ#����yEDD�dS��H>4k֌�>����8�ΝKݺu9s� S�L��ӓ�={�e��?�fZ�GDĺ�?�K�.Q�B�b+X<�� <���tƌSl���M��"��l6�u�V���Y�v-������6���x��W�X���)E WV�ͅ �T���qDD���ڵ�V�ZѬY3���S��>�>>'��)S�����?��ڵk��#"""�@EK��ܓO>��ŋ����_��>>>���1u�T���x�����QS��/-�#"b�"""��7�ev...���;�3���4����HQS�R�JT�P��#GΖ-[�ٳ'�W��S�N�����r��E����F����X��N����$� �~�����޳�|뤢���^�:���?���b͚5<��ܸq��?����7n̢E��r��Q�KLL�jժ')��LFF�ƍ�Y�fF�4)D IDATǹoY�!"RTN�< ��NK���~�����&M�dt)B*Z�<lmm�ҥ 7n��ɓ�7WWW<Ȑ!Cpwwg��ᄇ�UJ� .������^x�����T����Z���S�NѺuk������c׮]��ժU���[�1{{{._� �ʕ+-EI&O�L۶m�_�>;w��>`�޽����Ç���E���HNN���T�\ggg����Y���� 0�ʕ+S�\9���-��DEEѦM������������̙���7e˖�Z�jL�4)Ǽ�w���p��Ubccqpp�����8���boo��ŋ9|���qDDD���h)�y�ǘ5kgΜa���jՊ��,X���/mڴ!44T܋EBBp�NK��L�.]puu�ܹs����'::��K�н{w�^�Jdd$IIIxzzҷo�\su�ڕ��T�?��˗ �������ŋ��O�t��۷'((��Z�ڵٶmW�\!,,��>��+V�8~n�!"RX"##1��x{{ckkkt�|y���y�7���d���F��"����#��ё�_~��~��#G�D�r�رc}����Ã�'mtT1Xn �9r��~���s�R�T)\\\�>}:���\�~��ۇ��3k�,�^�:�Ǐ����������e����INN&((���0�΢e`` �˗�������}�v����P�̜9�m۶ݳ���ѣ�ڵ�� Z�K�z��^��e�#FP�^=���6l�������[�n������ˀزeK�s�:DD���2����y�*W��֭[5������R�RD���#88��g����?�Νc�̙Ԯ]�Ν;�~�zn޼itT1@n �������LŊ-�yyy���nV~��Yé�Ԯ]������d�|d�ر#?��#aaa�o���822�����X��R�J���̙3�L&�|�I���������ggg����)..����红z��J�"33���LBCCiѢ���xyyl�~��!"r?��,��P���.cƌ�ƍ'�¦���X�-[���@:Į]��ׯ����_��Ν;S�vmfΜ��\b]r[��Z�j������ly��������u�jժq��%���-�e�z0`f���C����Fǎ���#11��+WҲeKJ�*����^ �Q����=z���h�Grr�� ��Lnnn���X�P ���Ӽ��|���9s���h�����^���vZ 2� p��)>��c�㈈�H!S�RD�e˖,[����XfϞ���7���L�8���Î;��)� ��x������e�ر\�~��/2i�$^z�%����}�ڵ  ==�y��噡u����Ʋz�j:t��d�]�v|��9���G�ʕ����<���y��Z����ɬY���hР-Z� ((Ȳ���lj�����Y����`2�,�W#<���vvv|��GL�>�2����X-E$W�+Wf̘1DDD�i�&�v�Jff&����i�___,X@JJ��Q�d 󶳳�k��d2�v�ZΞ=K�*U�����ӓ�����d2�����7�ФI:u�D�V���Q�L�V�5k�nu_���Ҿ}�]�رcY�h��������k�R�T)|}})W��5�~��8�}����ԭ[�r��ѧORSS�<���/o��6͛7�M�6 :��� "RX�NK�5}����7RSS�g����)[�,ժUcҤI9�2���a��ɴmۖ���ӫW/�7o�#�/�����3���=3����� /���L�J�x��,Ӓ����w��iy��~ʖ- ���� g���xyyѿK� &ЩS'hҤI�{q?��-E���Ç�c�L^C� ���=/��"aaa�8q�ѣGS�bE������qww筷޲�Q$���s[%[DDN�|������'::��K�Z^����Ƿ�~��ݻ?~|��"?�ɋ��"E�l6�����q�h֬��q�[�u�nݺ̝;���8�,YB�f͸x�"s����LJN�:�z���FK�w��y��ܦ""b]����|�����`ܸq\�~�����oP�vmlll7n&�)���-��?�<�������[�n�����60`[�l�c����P�bEz����%K���?Y�j� ����9�o���ܹs)U�...L�>�����������z�쉣�c�s?���<(-E�j�*���-�G�����e+WZ����ٹsg��C�"���L����\�2�����o� ˽� .0`�*W�L�r����'""��zTTmڴ��� __���}�O^J�*���ٳg���g����.]���_|///�N�J\\\��)�ILL�jժ'��fM��� ��ߟ��(˪�������d���#���� �dff��� @hh(-Z����///����G���X� ����IOO�믿�f͚���c2�,���8;;S�bE�1���,��=���V����"���Hڵk�ѣG-gaaaxyy�}�v��:X��>��m۶9�u�!2ݻw��իDFF������'}���5W׮]IMM����\�|���P���-�/^��O>��K�.Ѿ}��t�u�W�&M���O�����?�~���={�iӦ���I���ټy3Z����NK�cM������b�3��c��l6s���U�V��>}�W_}�>��3g������<�yꩧ�T��ׯgɒ%9�, ��l�|��Bbjj*���9�moo��� ���9F�����8gV�vQQQ���f3��і{q��ɋ��"ypuu��Ϗ-[�Orr2AAA���w-��ɏ��p�o�Npp0*T�����3g�m۶{v[=z�]�v�p�B�\���գz��mF�A�z�prrbذa4D�A�/_�#Fp��1�n�J�^������o��g��nݺ̙3灻��i!�em��p��ݺu�ʕ+L�0၎LTT7o�dΜ9dddбc�'k!L&����\�2_�2�w�}�={�Я_�\������ח�c�r��u.^�ȤI�x饗prr�q����� ==�y���8F�ʕ����������:u��7o2s�L�f��^��1EDD򢢥H>t�ؑ����0ڷooyIBB��_,���s��L&O>�$^^^xyy��닳�3IIIw�G���s]%{�R�J=���Ҷm[BCC���a���xzz�رcqww������/Ern)8-�#"b�HMM�R�JT�T��8�jΜ98::�lٲ�\�k��F�>}�X�"˗/gݺu�\'7�������4oޜ6m�0t�Pڷo��}��������ܹs�?�M&k׮��ٳT�Rooo<== �l3{�l�oߎ��;v�E�9�1v�X-Z���3=z�����C����!2~~~4oޜ��@KW[rr2k֬��14h@�- ��s��q����<�� Q* ������ lذ���H&L�@�*U8t���������op��Q�2>ʴ���u�*�խ[��$Ec�ĉT�V��;w�j�*��ܷe˖Q�lY�y������;-E�L�2P�Z5j֬ ��LMM���,w"�v�ZJ�*���/�ʕ�Q�F��������ё�u�R�\9���Cjjj���!JE�V�Z̘1���V�\I�֭IMM%88???�z�)���Knܸat�GF�<�Y����u�괴֢������qܸq\�~��D�����ɓ�������l�G�ɬe{E�;v�����X�²e�*U8p ���:�j�28��������[[[��ӵ���������ڵk��믭v���7oҴiS<Ȼ���ɓ��$"""����<�\��ʕ+ �СC�����3��s�=�����)�KBBիW�jժ$$$GDD ���/���>|�'�x��8Efǎ�iӆ�e�r�� ��܌�$"""��q"�P([�,C������޽�W_}6n�H�.]�]�6ӧOWq�i딙�Idd$&� ooo���֭[ӳgO�\��ĉ��#"""����kq��y@��ED�IZZ111�����c��صjՊ�^z��W�2~�x�㈈�H.T��GR�F�X�p!���,X�___���y���U�]�v�����͛�:��?�L�F�8p�@'/>������&���dff��兽���q ��P�T)���Kv��mt�-E�V�|y�x� �=�����ӧvvv�Y��g�}�:u�0{��<�(CBB����I�&|���Ŕ�he]�:-ED�ǣ:�ev�3���ȑ#1��FG��P�RD��kݺ5+W�$&&�3f�������q�pww�W^a׮]w엔�Dhh��q�^��6m�C�GPFF.\����㈈H!yT糼��o����{���/�0:����܅��""��R� &L�ԩSlذ�^x���tV�XA�V�hذ!!!!\�|��>���� ��f���S�ҫW/�^�j�e<� .`6�qqq��F?*DD��:-o)S� 3g�`�ĉ\�r��D"""r;�%*"r666<��s�[��?����'R�jU>̰a�pss#((�����u�������z����bN�����uR���y�Wh֬qqq|��F��ۘ���E�b���Ʒ�~�'�|¶m��O���Y�z5E�mٲ�:Ю];�l�bt)$�����������q �{�nZ�l���'N������H"""����RD��ի[�n�رcԮ];�}���i׮+V�(����… ��RDĊ\�r���8����Y���qJ������õk�7n��qDDD$-ED�S�r�8}�t���~�:���c„ ܼy���=����V�jp),Y�Y֩SG�g����S�tiV�Z�Ν;��#"""��~[�O�-ʱO^�f3��>ݻw/��'%%���jp),Ǐ���78I�R�fMƍ��lf����?EDD*Z��܇�� �O�~_��Y���-[]�� ���>'O���݌;���ϲeˌ�#"""�h)"r_֬YCff�}���o���㏗�ah��������X�����u����)]�43g�`„ %~D���ȣ@EK��`gg�ȑ#�۷/;v��Ϗjժakk��c�����SO�dɒ"Lz�����Q�e����C�-HHH`ƌw�&�sY���ȃ3f�C��u0�L̟?�7�x�X�;a�.^�X���͵k׸~�:ׯ_��ի��׮]�|~��URSS-�<��4o���d`��s��)RRR���t��F�y�y{{3v�X�c��#�bŊ\�t���D�Y|{��% GGG��éU����L�4�U�V��������IEDD����"R��(\zzzSl�)�V�Z��O?CDa�ϟ�J�*T�P���d��h���gٲe��ٓ�˗3g�fΜi2��~�4ibpJ�4l�0BBB��!""E��ח-[�P�J�|�c��٬ڥ�<��.��Ç{��?��<<<���"�ٹs'_|��1DD4�e̘1�իW���_���?���ݻw�h)""R@ǎ�}��*\j\������3|�pC �C�U�RJ����h)"%��̿���W�\��` �������GMpp0AAAF��B2y�d.\X�¥��B��o0�|�V����o�����:-󖔔ĠA�hڴ)QQQ��n���ŘJDD��W�L���C� ,�����<�S�RD � �"""%�:-�---�?�WWW�,Y�͛7s�>22����S:�P�ti�l�R�¥��"R$T�)9�i��}��h{u[������k� �*Z�H�Q�RDD�xf����H@��w�����+x���󽏊�"""�� �K-E�H�pY�8�ԩS�:u*���7:N�һwoL&&�����ݞ�v���\�z�jժ���lt���֖��&N����U���-\�h)"EN�ˢs���M�ƴi�T����|��c2��>}:~�!&�)�m���Kfff1%�>�)\�h)"��a-\^�v��E�Z�+/o��6�֭cݺuԨQ��8""�B�Y̛o���ŋ�����6W�\��ѣŘJDD���U�T�RD�����?���u���䄿�?�ׯ�^� ���rޱc=z��|��4n��U�V���jժaoo���#^^^ 4�r ���������9�4h��Ʉ��+iii�授��G�T�Z;;;ʔ)���/�����0d��>AAA�soڴ)_�p��!z��E���qpp�Z�j���˖Μ,��=z���w�Ν��у2e�P�fM����駟��퍣�#͚5�c��܃��5k�;w�s�Μ={�@��~/7o�L�n�pvv��ٙ�}�j%Y)��iYp�o������h����ȃ˭pigp6�2�f��s�.]��v�Z���� �{�.�,�}�������#G�ڵ+�������K/q��9�W�����?��쌻�;/^����,Y����0���)]�4#F� 88���… ����o��Ʊc��ׯ�<FF;v�������$""���&N�h�Uw���7ҵkW��Ұ���jժ�;w��+W�~�zv�܉��_����ΛU��z�*�G�f���|��w�m���G�Ν����T�REvnw���֭e˖�T�R$&&��_r��q��ٓ�{+"buZޟ�]������]�r���;^߽{w�����*\�oߞ�G�Ҿ}{�l>�� IDAT٢NK)>� .J�*U�[,}�駖�BBB0�͘�f�}��<�+##�!C�������������q��aJ�.Mjj*o���e��ރ۹��q��>��#�s�}�'N$""��m�p��9�n�Z�{���<�?�>���Dfdd���B�J� t���#9���Z�jacs������~edd�=�����r��w�<�ם�HIMzz:^^^899�U�^=v����O?mno6�ٳg�?�EDD$��m�Zh�#k- ����t�"1111��koo������-ź'�|�ӧOc6�Y�f�=�1r����ޝ�EU���3�������������r%iqR����i.i��ne�Z^���V�Z���Բ���u���X��� ����993g��#���x��s�����|��y��@�#� ,���`ܸq��1c���q��lٲӦM�J�Bff&^�ui?CE�^���>���I��?�jԨQ���������+�����{��>())Aaa! �����S���/))I�:99Y�������a`��V8���Y�f8z�(:t� ��iA������$-���������H)y� S�ӽ{wl߾� #�Z������0�cn{mP����K�ڬ��jݺ5���G��G}�7n`���8��Em���I_w����� =�]���i���G�(]}�������$ �����'rrrЯ_?L�>+V�@�z���s��s�JE9:t����~�ÇK۲���q�F�q���5,�?����C�z���ʹ�y�|�r$&&��ŋx�W��l�U)CҒ���F�&M��� --M�h���j7>nG����rU�˗/#!!�=�X��Sͤ�h���cʔ)())�*�j5������$��w�www\�v ��.��ӑ��#�^�z��a���X�r����x �z=�͛�y�����...���FQQ��E` �v� �J!6n�(��߼yZ���y4 �n݊��PbȐ!��999�'�|��}` K�@��dff�YТ}���0a�M�""��"�V���AÇGhh��aT���H4h�k׮�����x,^� UYի��?l"""�����k�٬M���T������������W�\��RmTw��0%!!At��U8;;�A��Q�F��^z�h�A��e˖����o�y�����W����B!bbbD�-D���E�&M����EQQ�B���� ���+�u��IQ�~}���o2.���,1r�H���*���E�=�͛7�B����Y�f���Ch4ѬY3ѬY3�u�V�����g�yF4l�P4h�@L�:UHǚ��}�����` ���Ă �V��gϖ���۱c�h֬��j�b���F���nݺ�_|Qt��I8::��Ç�;w��>����c׮]�U�V���Y����w�}W�f�� Ο?o�>7����_E��?���㛞�.F�!�Z���� ,���F}g��п1lذ2�ʳr�J@,^�XV_����/�K�.�ٶm�6(E۶m��.z��-�J%n߾-�bܸq�����?�,�αc�D��݅���hذ��4i�����c�l !��˗�F�D�6md_Oqq��9s��ܹ�pwwu����΢S�NbӦMe����:�NԩSG��p���.!�8u�?~�����Fԯ__�l�RDFF�~��R}��O�9oAA��^�nݤ}cbb��cbb,��cX�f��~y���{����c��!��܄V��Ǐ���e����D�޽��{"��6p�@@8p@�Pd1�L���}��w��DGG b���Uv����[�߃,�o�>d㈪OM��a.��G���NU��9J�����9���g��J� &�O�>���q��1 0�۷/�߶m���_�M�6�~��4����+��݋6m������ӧ���`t��{���̙3;v��O<WWW9�aժU�h4��Ά��~��i���-["%%EV&������������dԩS�ƍ������o��>����s�ΡW�^(((@BB�n�:��j���a.���p����[�%���ߏ@�޽{c�ΝR{��o�����1m�4|��2d���q��)i�������cm|��S�o��}�t�q��j���۲����BTTT���]P����]�̞ǒ>ػwo���֭[�_�f̘�3f�gIDDD�Cy�^�{���A�F���X|Qu�i��/���4��L�[�n���E�P�ܪU���qVJ���ѲeK$''#??;vD\\�4����@�t.�z�©S�p��9ܻw�B˖-�s�N���K�z�*���ЫW/��w���;w�������U�V���OQ�^=�;w#G�ĝ;wp��5�t:���i�d_��ݻ��k�!%%�5����1e�Y�_�v �=���ߏ��<��شi��Wll,֭[�˗/�����w��o�}�t��)S���~�Z�Fpp0���+�O���?>�������� �Ν;ؼy��>0u������>HHH��I��� ̄K�.prr��RS�'���{$>>K�,AQQ4 F����X���dž �9̍���(P����?䌟��g���������z��aҤIX�j�ju��_�֋/ "++Kzo���VZ>���2�s��3gΔ�+�w�.�(����������/�{� �����}�e�+�?55U.\���ꫯD@@@�m�}����B�V�lܸQ!Dݺu��R9�WĒ��N�Zn5�!Ί��[�nbݺuҿ�L�",X`��-�?4v�X��Ŝ�/!����f|��Ws�������޸qC�T*��o�I�_}�Uѿ!���� 233��}��yh*-�?.ggg��鄻���q�� ��]��?�X<�����A~~~RE'�\r�V�JK"R��۷�J����FOI<�L==Aʲ��n�Siٮ];ѫW/QTT$�z�1b�x��eo���&�������B!�]�f���ߩ[�n�o߾�޽{��ݻ�m۶"..�hk�����+��j�W_}%��ʕ+e*�M�?|�p1z�h���/n޼)F�)-Z$�s�N鸴�4��������͵/�s��!!!���P��z��?=�eʄ �o�Q��޽{��;w��s�h�=d�ڶm+�͛'���ŷ�~+�j�E�|r�ON~�*�}�����q��]ѹsg��ϊ˗/ '''��5�/���5�����15~�����M�?� "���Eaa�HKK�<�ذaC��o`��مx����R�ФI����_E������O�>����N�����q��=i������o�!11�|� 0p�@�6�w��J�JUf��ŋ�C� AÆ eԾ\�ş��:t(t:t:�L���w�ʾ>CU�F����j�ZZ0Ú���g 4��vpp��{�������~h޼y��������������c��h|�^� !��� x{{#77@i%�J�2�޴iS��]�|||��㏣A��|�2�ܹ���@̘1���:u�T%�~��T�ңG|��F �U���D!h�S"D����C�ѠN�: C||�E�`�رhӦ ��߅ (�1v�X888���]�v����w�y'NĐ!C���>|x�1<ZZ<��k����Z�s���'�|"&��닐��={VVlr�J�����CJJ T*z��iT�jJ�޽q��1@����z�j��ɓ�ݻ��>�{������Abb"N�>�E�A�Vc���ٳ��k7������-�Gy���@pp0�6m �J��ׯ�4���ߊ>�U=>r?#�m����y�&>�E���� ����2e >���j��Af����������PZ�Pf��&�����O<��?��G��J���ٳQPP ����1c�`ǎHJJ�ĉ˴eXU�������?,|||��%��EFF�^t�j9��=L���\9�j�� J_���#;;ۢ�@� *���Y�Z�VK𷅌� t����~� n ��k���ң��׮]�رce�f�}�����_FHH���1v�XlܸQ֢��{��믿��ׯ�Ν;���1d�4nܸ̔����]ce�!s}`��k��~Uu��)ʲE��3�}F�z|�~F*�~Uo�h�:���Jˀ��k�k֬AII �;��Q� PTT����Kɏ}����o���x����I�&Yt�¥K��us:99������t\�zբ����0t�P̝;������$Ǝ���|��7e�,+���X�{�\�_�a`iQ����EQ�5�Hy,ʪ���cM|@Տ��ψ�����?��pђ��EK����&-`׮]8r�������/cذa���7m��W�ƀзo_DEE�o߾e����T�N�={� ..:�Æ 3j��������X̙3Z�m۶�>�r����o��&ƌ�V+UN��n�����0GN�[3�۷oGnn.7n�:`̘1�5k��}Ϟ=x��ХKDFFV�#�DDDdVZRm���";;ׯ_ǖ-[�?���^�*[0�.�0�V7�/�`š��:u�G�X�z5F��!C�����g�I��Ƚ���C���E�R��l�2lܸѢ�������EE�|~�_Qі���ꈿ</u>j�(��[oY<��9ݻw79�2�ձ�Ҹ٣�� �o߾ �w��I|���Q�i׮�صk�C�f�^�q����T�֟�Y��~'O�˗/˗/Ǐ����RY�B<3g����B�Պ��pQPP {�����|P���E�f̈́V�����Y�fb�С��nݺ���_ҿ����s�=gԆ^��aÆ�iӦ"66֒n;v�-[������ǧ�B?������'O�7���"((HlٲEھf�ѼysѧO"&L� �N�*;~s�����'\\\�����?������Ŋ�Y�fB!N�>-- j��]�����>����E׮]E�ΝŠA�D�޽-Z�EN���Ǫ�ٷo�6l�B���p#����YZ�U���t:�����9� a�3Z��#�3bj�����=~Æ �A����Y�_�^z?--M >\h�ZѸqciѢ����sNV��ĉ"))I!DBB�puugΜ������?�����ڵk6m��NLZ�=`Ғ쑹��={ą ���%%%������7�aKZzxx����6��*=�?ӭM���I���_��2ii�3Q�C�]x)�ʕ+B�R��* =� ?��.���� AQQ�Z-֯_�֭[[Q�i�K�.HJJBll��*�DD����*3A7��~���C R����j�*�?͛7G\\:w� X�z5�Ν�-Z���1~�x������FII ��}t���v�Z���"++ Z����x��W��* ��O?���W�\A˖-q��eiZ���1l�0dffM����T̜9G��F���1c�a�i�;///�ݻWzL�ĉ�߿?nݺ�ٳg�ܹs�={6/^�~�����Cpp0BCCq�� ܼyEEEزe���iS��ׯ#''Z���E�/�W�^x�DDD(��LIS,DD�q��a��ׯ̴uD���p""kUE�%_|=�/VZ�= ͛7���B�׋U�V ///q��m!D��Ã��D����͛7�B���[�k׮��O?�T��� !�8{�����)�xyPP��С��~����Ѭz�ꉳg�J�L�:UDFFVwII�h׮��y+-���=D��3���UiID�0[�r%nݺ�t5޿��oܽ{C� �������*^^^J�@T��}�Y-Z�����믿��?^��3f̐�G��� B�Je��]�V�0y�d|��R���m��������SOa۶mx��7q��m|��G�ꫯ*�����8s� ����^�z�W�V�X��b�֭�[�n��#**J����~ .4��`+����B�բ^�z���Ʈ]�p��y;v �����w�ر�r� ��� � Aqq1��ݻ�������6�Rӊ��1x�`\�|@�B�z�.\�� ��/�{������_�j;�!���IK"����”�VX�j����e�)�@DT͚5��V�T���GVVV��������^�^�F�ݻwc���HKK�F�A~~>\� OOO�O�6 O=�V�Z��?�~~~�޽;`�������.�+�@ff&\]]��h���PTT��W�Z��u�&M�����e�?l�V5jv����w��>����+>��CL�<���:::�?��Z�j%��jN�.]��矣���ڵCFF��� ��_~�;#iӦbbb0c� �.�>���R�rӦMx��gyyy����|6 ,�"""%�Q:""R����___��!��.55U�Z����JU_�t 'N��ի������̚5 �O �֧O4l�_|��mۆ�S�J�&O� !��J�7n���k׌�����F����PTT$m���7:���l�/99Y�Z����?*ۦ9�Pi��s�A�VC�Vc�̙���|�U��\��������4��9/��"�Z-7n,�Ǫ�륊ͪ��� ��O�:k֬��'Z἗�� ����X�t�Mی��Gpp�M۴�M�6�I�&hܸ1������r�'22 ,����j�+W��޽{��􄓓���Q ��q`q IDATy�f$''���k׮�_��a���`�T*dgg��?�}��i���+��رcx�gL�ۮ];�j� .Daa!���t�R�;Vz4�cǎ���/EEEذa�Q�7Fbbb��7oތ�/���+W��B�ʶi�=TZ6nܸܯsss��אt��N�����������&-����m۶aѢE6lt:~��r���O������%���ի��;� 77111J�SFxx�ѼXD����4��$"ۘ2e &L�www�ر��y�+v�ҪU+��� �֭����ӧc������4iΟ?�ѣG�����*� �}�222�����@4k���w�5k���C�6m0x�`���è�� �wށ��+�z�)���ӧ#<<���سg�QT�Ms��2))I���j��p���P�h s�涗������������ƌ���Ƒ#G�e�L�6 *� ���x����=ƒ>y�Ԅ�Sl�R������txmaj �w��۷WY�ա����ǧ:ٺ(�V����$+i�����#G������X�pa�������1z�h����Ν�Dll,������ ///,X����J^�r�F����6l��={-�a���'O��������/JJJ׮]�ĉѨQ#���#22����� �֭�Z- `�_'M���9�t:L�>/^�N��N�C\\�Q���\���'>>�=��� ���s�̑� �N�Czz:�O��N�y��I���0c� ̝;�h��Y�0h� ���cĈF��w�F�֭��jѬY3l۶Mv��ܹ:�!!!طo_��7wˉ���3$-������j���,Y���� �����o��k׮��'N-�����1c�H���tB@�)�z��W_ERR���;���#..{��-s���0hР4h`�h�):�_~�%nܸ���w�\���|���P�֭���"���DNN���_�b�ի�tn��(�'d� 2._��#G�T�y��6l����A����'OFÆ ����S�N�O>��͛��m�6����x�"Μ9Sf�񊸺�b�޽�}�6N�8�O>��LRΔU�VA�� ;;���X�v-�j���;u��߿_�׮]�0a��)ힰ�0\�~���HKKCff&�/_.�?n�8��� ���X�l>,;vs�l�)))غu+������i"��U����7��EEE8w�\\\PPP���lݺUJ��۷)))����������:s� <���Dddd`�ΝҶ���ӦMúu�p��-?~\��GN����#%%�ƍ+��r�oS��� ���$�����߇V�ŰaÔ�Z �ɕhrdff��GE`` �?h߾=&L�`վU�k׮RU�ƍ����Je���,�^�y��Y�fpss���/�6m�;w�(]p���s�-�2W''��&$$���W�^��;u����q�� ��p�t}�����7���f��7o���Ç�h�"899���S�L���~Zf߱cǢM�6J��m��ܜ��0�8___�����ٳ����u�"//)))P�T�ٳ���E9퇇�K+�">>���J��<��k����Z�s���'�|HLL��ӧ�h�"��j 0={������*����/�y�8::" ���hڴ)T*�_�nq��bwpp���#�v� .H��y�L�8C� P:�����mr^������jCҒ��QmѨQ#����غu��h{���x��G��j�ݻpss�V�������W_���Ѫ}�B@@bbb���l~?:88`�̙�ܹ3�j5233���N�:aӦMe�=J�Ie�)X�[pSSrۯ��AN�� J�d�:�-�_s}d��H���Xs~�EE��������d\�p�h L��%EK1u�...�裏����#11�����?�q�F��_Q�����-J2��c���S�QsEqr�LQapp0:v�={�H��رO<�\]]X�=h„ �޽;�_�����ꫯLƤ1�իW!�0Z���ۻ�G�����ǪU���� �F�k׮a�ر��_�x1^~�e��� ;;cǎ�ƍ���� �ʕ+q��M:t~~~h߾=�ҿ�����W���\�T*��iڴ�E�o.~���s����� \��H�j��j�N,~��ڀIK"�m�P�!�X� ��hѢ��]�5jdT-d;�w���ݻ-�^�1=�����r�EDDM�`�y�~�� c��%�WS ~���2 �gϖՆ�� �� X\�&}]��k�om���>��h�E��r��*����:TnQ�%�U4>��������1s�L��z�޽��]_RR��������h4�իz��m�-�I�F�A�R!++ ���J%(o���L䙗��'�x�1F� �J�ٳg[T�nX1(��_�~ ��~@@ڵk�}�������Te >>>P�T8{�,�Zm�s{xx@���|���(-׵��� T*�&�)����oM����@��%����U8����6�����,���E��ǏǼy󐘘���$888X�"P��eggC�RU}��5�l��� �5k���ݻ�|�2�m�V�d�QPP���"�o�^J��\�)�¥K���9NNN����88p�(Y��燡C�b�ܹ���P�>x� �҄g�֭�rה�=z�f�xzz"==��s�ۢ��iѢ~��G@NN����M�2������?:d�Oe����o�������RiI������  ,-H0U0a�����7�,\�iiiHII�ĉ+U�QYr F��X����h�… 8~�8���K� ��^L�q���v ����I���9��-��;ƕm_�����#F���ӧ���i��ESr��*���=^n��"��-��Eq��Y���BS�a777�3;v���;0q�D�W70\_vv��ޕ+WL#kB��۷#77�7F�0f�̚5˺h�OӦM�z�j 0}��ETT���kQgΜA�>}������cܸq�*Fr�7n~��t�СLFz׮]��� �V��ȑ#���*m߳g�{�=t������ԩ���7�֭BCCѢE ���b˖-��7�-�ߜ%K��ĉhݺu��>|8bcc1g�h�Z�m۶̇�T����:�{��A\\t:�ф�Uy�%%%HOO�J�bҒ������HLL�J�B``������ݻ!�����Y����-}RQ��- LLتࡢ�����9#���ppp(�XGN�+ڱ���\ю���Q٢�c\UEK�e��������cs�c������ WWWq��Ii�7�xC�i�FܹsG��M����3w�Ys��77>��s�ݿ����ᅨ�]��Ν;�A��޽{��^zɢ�L����ϰ^�����G�e���{йs�D�Ν����2d�=z�X�ti��r�����ZKΉ�V�Z�%K�`���X�r���ص�Ǐ�k׮�ܹ3�?�t8DDd��bĈ8p�T�R�4k� ����t�������S��͜9111ؼy3�����DDd^�=0q��*�^���� � ¼y��7<�.��p""��8�%Q���,����G���3g0a���}��IiN� .��ᅲV�/���É��v���DD�W'""���ҥ ���k�ʺ�$''#$$EEE�j�X�~=Z�n]��LZ�9&-��j��Ri���2[�nU:""�bU=]�SO=���zJ��LZ�9>NDT{ԖJKKWB%""�ڇIK"";gHZ���) Y�޽{HMM�F�A��͕�RV�\�[�n)F����?�s�N<��h۶���վ}{�C "";��%��3<Τ%Q͖���^���@888(N����)B�۰a233��_��7ހ����!=���U*_|��W���,Y���>�?%%%��ȀJ�BӦM�����P[泴7�>�,:v�K�.�W^Q:�Z!>>���J��P����ҥK->.22 ,����[�x1Ə_e�?C� A�����jѫW/���F�Ԇ{�ȑ#���R: "��1� �VW�\AQQ<==���t8DDd��2���Q�Ո���Z��[o��ӧO+����t6WRR�Q�F�]�vHOOGVV/^����C��G}+W�T: "��B�/���K��*���������t�3f������B(�C�ʕ+5j���аaC���S��ܹs��t�>}:.^��N�N���8�6��˗c������Ν;�v�&N��F�������(,,�����EPP������ ���@iu�c�=���@c�…pqq��9sd_����{��5k �1����t�� Z� @nn�E��s�N�t:���`߾}e��;�ɓ'���j�ށ���+%3220r�H������ .�^�/7���|��� �?�����12%++ ��ɘ3g��ݡ�j1z�ht��@�N�8�N�N�:��t����?s�(�-�Ғ�Ȏq�p"�ڃ��5ۊ+��퍟~��L����j�*h4dgg#77k׮�Z��l�)))غu+������L�6�L;۶m�믿��/�̙3hҤ ��yU�_����d���!33˗/��suu�޽{q��m�8q�|��x�ܹspqqAAA�u�� �r2�>�9sDbb"222�s�Ni۸q�ЫW/���cٲe8|����Ei�eJJ ƍW�>��ߩS'���`����{�v�„ P�Ni�a���hذ!rssq��)|��'ؼys��\�zĀ��[oI�#S�4i�N�9s��ȑ#�s����pu��)))ؽ{w��M�_��ɹG�l�IK"";��� �IK"�ڀ��5������Y�d rrr���T�n]���!%%*� ={�D�z�,ng�رhӦ �A�hԨ���p��A�]�����j��;w.>��鸰�0�8___�����ٳ��Gy���@pp0�6m �J��ׯˊ�\�����舮]�J�HLL��ӧ�h�"��j 0={���o̩�����صk������ܼy�ƢE����___L�2�~��Q����߿?�u��^{Mz_���V�q��Qx{{cҤIpwwǸq�,�H5���x�c����O��D�Ĥ%�3<���p$DDd�[�n!==����5����1t�P���a���J��PZ�x1:t耐�4l�QQQ�w����t�2�edd�*=5 4�����g͵�h�y�Z���"@nn.T*���+U��bE�7 Áp��M|�����C����VO !�b���.�4����/��׮]�ޗ3F����!&&�.]���瑕��Y�f�����C�;���s<�-1iIDd� IKVZ�l����G� ��Q����o�nݺرc�9�t8777lذ.\������_b�޽F��T*��T�2����@�R��ٳ�c�iii�t:yyyx�'�p�B���!%%'N�5��}�i<<< �@~~���� ���v��a߾}صk�Q�^�F��R����%�����ƍ���{��S�N�:u����1�T���1y��2 `��{�9�75~�ޣD��o4DDv�IK"����x& ����/B���h�*����C�p��%U�999������t\�zբ����0t�P̝;WJ�%%%��������}��R⭼�j*���кuki�ɔ�=z�f�Y"<<qqq8p���¤�]\\0p�@�Y�w����˗�m�6�3��xC��;#����Ҝ�����^� ����(**Bbb"�oߎ:�W;�^����h���3@� &-�����DD�ß� �����-BPP�v�Z��y��9s}�􁫫+ڷo�q��!44�h�nݺ!44-Z����/�l�"��]�vA��#00Z�#G���oڴ)V�^��o߾���B߾}mvm�hϞ=x��ХKDFF�S�NߣG�t:�ٳqqq��t6l�Em� ���/�СC�Ǩ�oߎ��\4n�:t��1c*|<�Q�Fx����p�B����S�N\�r�FݺuѵkW���bÆ F�Մ{()) W�\����h���3@� �`/�]*))AݺuQ\\���B8::*URDDv�܉��_�,[� ���8y�$bbb�����ʩ�B� �������#-- IIIx�G����*�]�v8}�4N�8�N�:)U��>� �?�8\]]q��y���(�M͜9� Y""��Ғ����zdff�N�:hڴ���Q% !������� $$!!!�q���y��!""�R��$"�C���������7222����*)-- ������Bff���P5HMME�V�p��-8pÇW:$""�*�JK"";��,��j�gi����l�2��Y�PXX�pDDDDU�IK"";dHZ���) Y�+�ۧy��m۶�x�"^{�5��!""�LZ١��4��$"��Xii�4 bbb�R��v�Z$$$(��1iIDd��x8Q��JK�ճgOL�6 w��Ett4�T�6LZ١��TLZ�t���o+W�����9�;v(�M1iIDd� ����� GBDD�U\\���$��j*)�aÆx��7���G^^�����DDv����|���(**���?�֭�t8�������999X�d���� ��DDvF��#33u�ԁ�����Q%]�p�p$�$�J���899!..?����!���DDv&++ ���hҤ ����*ɰ ���`,X�BDGG���X鐈���Ƥ%����DD��aVZ,]�8}�4֭[�t8DDDVcҒ��Τ������l�� IDAT������JK�_ݺu�i�&�+�����T�#"""���DDvƐ�d�%Q��JKz����1n�8ܺu �g�V:"""�0iIDdg IK�#!"�ʺs�._� GGG~?'#o��\]]��g���>S:""�JcҒ���pNK"��/11BB�V+=D|||�b� ��ٳq��-�#"""�&-��� ��DD5�$S���ѩS'����W^Q:""�JaҒ���0iIDT�q>K2E�Vc˖-P��X�nN�>�tHDDDcҒ�Ȏ��zdff�N�:���Q:""�$VZ�9�:uBtt4��� !��!Y�IK"";������b4i�J�CDD��JK�cŊ����O?����8��!""���DDv��h8W�%"��XiIr���⭷�,Y�999 GDDD$��DDv��Y�|ׯ_GNN�Z-�6m�t8��7n����<̟?_�p���dcҒ�Ȏ��~~~ GBDD��*K�ԦM�P�n]�رG�Q:"""Y��$"�#iiiXiIDT�q>K�T@@�.] !���q��]�C"""2�IK"";��É�j>VZRe,X����HHH�ڵk�����,&-�����DD5+-�2����J��^{ /^T:$"""���$"�#�����$"��XiI�տDDD����>������B�� "��W\\��u� ��h����*��� 7n�@^^��ݕ�j���#//�v���������\��$"����������b’������č7�����%U���V�\ x��瑟��pDDDD�cҒ��Np>K"����hx�-��j�iӦ�gϞ����K/��t8DDD�bҒ��N0iIDT�]�p�裏* �d*� 111�h4������Ǖ���� &-���!i���p$DDTY���XiI�k۶-�͛�^�3f@��+�&-���W'"��XiI��l�2����ԩSx��������DDv"-- ��DD5+-ɖ�Z-6n�x�嗑���pDDDDaҒ��N���W8""� �^���D�T**�!!! ��70o�<��!""�0iIDd'�Q͖���{��������W:�E6n��V��?�P:"""LZم��bdeeA�V���[�p���8�%U,[� 0k�,(��DDv!33z�^^^�h4J�CDD���,�*͛7m۶ERR^{�5��!""bҒ����p"�����T�4 bbb�R��v�Z�?^鐈���1iIDdRSS0iIDT��Ғ�ZϞ=1m�4ܻw���B(�1&-���WWއ~�J�_|բ���>���j�>�JK��V����'���;����J�CDDv�IK"";`HZ���) Q�q��=<��SՒ��w�RSS��hмy�*?�/www����� ��ի GDDD��IK"";������? ��� ���/�j��ҥKpuu���ebb"�z=t:��\D���8p rrr�x�b��!"";Ť%��B��s���+� &-��j9&-�������� 00*��!Y���+V�̙3�n�R8"""�LZ�r������‘�[&. IK>NJ�1c�t邴�4������������DD�\ZZVZU7[%.���O\����V� �Z������~S:$""�希,Q-Ǥ%Q�HMM�o�ar�����=�|�I����ڵ�E�a�%=,:v�g�}6l@tt4~��ԩ�:""�� CDT���|<���v\]]�� /�ڵkf_={�I��[����0y��WѴiS���ψ��S:""��XiIDT��ʕ+�h4���V:"�Z�A�X�j��������V�\�������+֭[��c�bɒ% �����aQ-�JK"�Z,##%%%����Z�V:""�PNN�_�� ���C�p�O?�4F��k׮a���J�CDD���DD��a�p�gIDT3�ʒV�6mB�z��s�N|��J�CDD���DD���T���x+F�|}}����JU�6���"##�`��*=Gy/^����WY��ϟǐ!CP�~}h�Z��� �����>��#ב#G���t�p>KzX5o�K�.�3g��ݻw����j&-��j1&-���|�2�9�tf���#44T�0l����F�B�v퐞����,,^�%%%J�fs�>�(V�\�t��Ғf ,�c�=� .`���J�CDD� ��DD�Xjj*�^�\�r�F����6l��={�֭[���8::��ի���N����3nܸa��s��A��a���x�"t:t:���׮]�ĉѨQ#���#22���J+�{�1"88 .��� �̙c��####G���� <==�p�B��z��g��w�� �N����۷����ݻc֬Y4h���1b�N�< WWW��p�����J�AS�����|��� �?������3'++ ��ɘ3g��ݡ�j1z�ht��������c�������y\T����� �"h� �`�"�� ��J��K��S�%�JM�ԟ�f��Y.�`�KZj��Z�(�!"(�*����(� ��~�x�����=�̽�|9��>}��I�&ppp@||�V�EFF�Y�f011��� >��c������_ll,���жm[|��Ϭ/����_i��GZRuf``���( ̞=���r�DDD���DD�X�HK&-k��s�B�T"33�n�‚ �I�\\\ЦMlܸQ�~�ڵ��󃙙Y�����"99˖-C�&M������d�9R*/ ���HJJBjj*�����_H��j5���Q�n]<|��.]²e�JL��R?mᥗ^­[�p��DGGcɒ%Zׯ�� Drr2X�6�ΝÞ={�����ׯcݺu��m�����v풶ݰa ==�2�WTVV|||н{w,\�PZ^V�����NNN��������ڴo�U�Va��ٸz�*Ν;kkk��333Ö-[������"::Z#)Z��_�v퐜�����bחv|m����˃#-���ڵ+�{�=�nݪ��=�� �Jxzz"!!AZ� 6=z�m۶!00P��eff�[�n����W_}%-צ�J����C��aÆ:t(�ׯ���֭[�j777@�z�`aa�U|�~����۷/Ο?/�����,e����f��\�t �ׯGll,�ܹBH#�8Ғ�����������k�� ""���DD��iY�L�2�۷/^z�%�5 �����A�᯿�Bbb"����J��/����o��t���￯1�B�D�R �R)-��؊ė��!��* 6�)�V��k���D�]__j�Zz�_~�����Ν;���www������h֬v�܉۷oK˵鿲888 "")))�x�"nܸ��������3˴�o׮]�ҥ ��������^�*��+KY�/���ٿ4YYY D���Q�^=X[[���999�[�.��ۇs��i}�?QU����ܹs'N��DDD��%Q-�V�����RYcf�%����}�p��)�޽[�l�X߯_?�]�k׮�{ァ1�vY��B���c���B�P����ҭ����҈��W^y�W_qeZXX@�P�ƍҲ��tXZZjU?m��<5i��[��O?�� 6h��Ӷ~���زe ڶm��ÇK�+��y�����8�奵o�m�VV|���/���0y�d���"99���V�-m�������_E��̌왙�8y�$�'�p���ѪU+���={���y�D�����ѩS'������?�;""���$"���_����4l�P�g�����݋���?b���Pc��� ���ضm���� 4@ZZ�Ƅ>��Qvo��Ə/����￱gϞJ��v�5l�*� ��X^�n]���`���x��1�]��U�V�_�~Z�O��?o���X�|9~��H˵�_��+V��ɓ�3/+�������q��E��j$&&��ᅦ����v��oiʊ��ÇP��pww����Mv��6m���O>�im�_R�U4~ XYYi�mFF�4YQu�P(�J���H�:uJ���cҒ���*��[�k�s�ΡK�.033���;___�mz���Z��-[���Y�������닦M����K�.��mذ���pvv���)�~�mi������������������u��=nݺKKKxxx�_�~�ܾ\Z��9~i:t�'''lܸ˗/����|�M��`���8~�8<<<���Z������?��ɓ'K�!+�zzz���@�=P�Nxzz���^����۷,��ggg�y��{��x��W1j�(���Z�]������ �����%�_e���h��7�9�����0a����#88X�I�������q? U;6l@@@�}�]lڴI�p^x�ׯG`` �٤+�C�x��0z��J���Ųo�> :iiiUv���@�_��֭��YԨQ��lٲ2�����i*������h�)))X�x1>��C�C""��#-��j��Ix5j$s$T�bbbp��9 �ׯ�޽� &��PJ� "��0i��� s$T�8�Q��>}Z�J���Z�6���j��������͛��/��gϞr�DDD5 GZ�R�����fiԨ���J\ߥKt�ҥ #"*?̘1���y""��IK"�Z����,zzzhڴi��M�V��U�G}�֭[����W_}%w8DDT�0iIDT ���"##J�666r�CDDZj޼y��۷o��_���!��R������a������;$""�A��$"�����PPP[[[����i����,K��:t耑#GB�Vc���B��������$<�����~�z�� �j������зo_�!�s���O?��C����ǰa�����j��$"������3.\��� �Uc !��;""�\666���@ZZlmm���jN�B������M�0j�_�o��&���q��899�UCiIDT����"33*� 666r�CDDD��7���A�����q���USiIDT�$%%��_���#������j�‘��x(���l(�J����� �U�V8w�GZV���t4o�w��Att4����������$"�e8s8Q�V�^=&,��kذ!���k�G}�����U7LZ�2LZQM0z�hxzz�ڵk�>}���Q5ä%Q-��� �IK"""����� }}}�����?��;$""�F��$�����%wU�]�vX�v���*����m۶=�c�Wa����A�H����J���q��!//���(((�;$""�&��$zA !���'wRX���Pxzz�N�Uv_�Τ%��f͂��N�8�e˖�ULZ�p�gφ�����acc��3gbܸq���Ǹq���䄡C�x2:pڴi�֭\]]q��ܾ}C����%�����;� ##C� ,���3LMMacc��S�j�,���o��]�t���:uꄴ�4̝;���077��ٳK�æM�кuk���~�J�{��֯_/%%��üy�p��I(�����iYYY ���%�֭�֭[#!!AZ�����]��N�:hѢΜ9�S�=]��¤%�gΜ��30c� ����N�ն�T�A�A�P@�P 11Q��ٶ5_ݺu�x�b���~Z�g4""z10iIT��?s�����q��$&&���aaapuuEXX����f�i�]�va���x�"�u�???��� 11�n݂��#4�ӤI�������ؿ?V�^�u��il�f��Z� �n��K/��nݺ!77���v�څ3fh$���޽;Ο?��7o���'''��C4o�u����1cp��ii4�6m�k=�������L�T*X[[Wj�DDT�>|(wDU&<<���X�n��9���^\LZ�`/��2V�^�ŋ����:u*�^� ��SSS�P(о}{899��� -Z����nݺ%m�:���NNNX�d�t�v���ԩSP(�?~���^����=z`߾}ؿ?|||�׉���q�:u�Tl�QV=��)-- ����*�-���������|��L�zh#-- B���BO��x"����������P*�011���  ���t@HH�t =}����-[��B����rss�*���#G���=z�T��={����'�� ���666 ĕ+W4b�߿����#Gп�������~�-`���pvv���!<==q�ԩJkm�S��C����077G�6mt��M�ЩS'���@�R���NNN>|�����6�9u����amm �J� ���O��ڴmE㠪ӸqcL�:0f�<~�X戈�HV��j���9s�333���/���ņ 4�i֬��駟��qqqB�R�{��Xnrr�P�T�СC���@!�ԩS��������O�Y�f�xyy�իW�x�ݻw�ƍ��� �z�jQPP 4h fΜ)�w�^ⱄ�m۶���^?]wm���s�� �B!n޼Y����HJJ�Z�.W�U�� �S�N�^6�~Dя�j�Z���K���섍�����ٳB!�B��ȑ#�����m'L��uy^^^Ҳ�~��!ē��������B___fff"..N����_ڿaÆϔٯ_�g�Y[[����R۫2�3p�@�c�^��T��N�4IZ���$��̤�Ń�M�<]�+W�!�ؾ}�P*�Ŷ�R�?���Vm�Knnn�F[R���������1c�����8 ��KHH��#G����:u����R]giiY�����������`id��۷�}�vi����x2q�B�@ff&֯__�uy��Wq��5lݺ��� �w�o��F��pm<]wm����-[�C�=z���ŋ��QUmV���Yr"� III�ȼ��p\�v ������BTT�4b�iӦ�ٳ'`Æ ���(��#Fh]���DZ|�ri߈�! ��[o����<�9������C�F� IDATbb"�����_���w���ĉ��������h�"iٶm���g�!!!Az�pFF~���Ji����4��������ڵku�o߾}�;w� )) �o���ɓ)))غuk�i�����!88yyy���Gtt4?~���h���i�/�m+�C�R!"" �s����/��m۶��}�v�v��*��j���k\C�k�DDϓR����rrr0a�\�|B8;;c˖-�����ɓ��`޼yx�7�e˖b�����-Z ''�ݻ7�y�O����'���� �_�>|||p���J���� ������!%�^{�5lܸ>>>:�U\�˪gq�mۆ &�iӦP��hҤ 6nܨ�\��TU��3�QejРT*�j5�̙�3g�����[����/ �mǏ�ݻw����X�n����q�F@����;w�h]^iΞ=���4@AAF�!�+|�GLL ���Tj~ܝ9s&���`gg� &,,,��_BOO��.bbbׯ_����Ŝ9s����N�:�S};w�]�va�ʕHOOGnn.nܸ!�S��xեmΜ9#���{������dR=�۷ׯ_ǟ��v��=�8H>���*����z��2g ����s�C����g�#DDTE��IDD�-$$D�/�;"������B!LMM����aÆ��?��ضE��pww'O���]�r���-_�\Z�q��;w�xKpџ[�n !4o�NHHBϩT*aii)�{�'�6e�ѣG���%ڴi���)���:���DD�H�H�™ˉ�**88�������ҥK1r�H( ���c����~��G�L����֭���\^��ڞV��ހ��v�,,,�ٷ�I������ �j �Q���T*�׺�766�v��o�)))B��H�Br��ӊ��鉃��.ܮ��-o$/KKK̛7�e�DDD����4h��郜���ݻw/�mۆ��8 >�G���5i�111��>��ߏիWcݺu��ڵ ۷o�ŋ�b� �;w.\�֯\����I��B�o߾���BFF�\���W�b̘1Z�=,, ��� Crr2֬Y#�۽{7~��'?~S�L)�-�)����bҒ�����DT��j5���[ܼy]�v�|����FFF���Wc�!C�H��C�x2+v�{]�366�~���G^^����������[�b߾}Һ��L���I�7?O�U���Rߢ����@�F�@�U�����)�h}8�M�6!''�7o���ikk+�\Z�V$�߰a�`dd���|�X�zzz �B��o��V�~���055��� �O�����+�s�E� �����P�~}����V�8z�(���`ee�R +++��������#m[Z�V4����!�v튂�i����T����\VJJ �{�=̛7���HNNFHH�4 �$]�t�K/���;wbժU�,���4�<777���:t�(c���X�b���пi�|���@ԯ_7nĎ;��(o�DD�GZ��֭Ð!C0x�`�_�^�p����H�+V`�ȑP�Th׮"##ѪU�����H�����[�n����42���������W�FϞ=��؅JJDT[q�%Q-Q8Ғ���F�!rssq��Q&,���-^���������ݻ���?��LMM��oV�q��^dLZ�LZQmfoo�Y�fBBB�Y��7 L�6 ˖-+�DZDDT>��������$""��kܸqpwwGRR���*9fVV�]����/��K�.��p"z�0iIDTK&-9�VJ������� /wHDD��0iIDTK�ިQ#�#!"""z~�����@�Vc����<����?�NDT <~�u�ԁ��=z$�LD� ^;����k���l��� ##�V�°a�����*GZ���,���t ""�Z�^�z��o�����ʒ9"""�lLZ��9��*��?��~��������'~��G�����c���HJJ�;Lz�ԩSK�,̚5��A"�Z�IK"����HMME^^��r>Ӓ���������K���`ݺu�����۷�`�8;;�w��o��!�ܡ� �G�Ӓ���|�2�5kV캍7b��U�󓓓�u��!<<qqq�J___����K�.2GHՙZ����;�����_`ƌr�DDDZ`Ғ��*((���9�߿���Q�F�z�*�J�L�=_�����`۶mP���<�9$$022�9B���9�W_}���CӦM�������É�j ==�b'�7n�DDT�u���6mBRR�N� kkk���1b��'� 99Y�0���ܹ3� �Ǐc̘1r�CDDZ�HK"�꣏>�w�}'�655Ejj*�ի'cTDDDU����ؼy3���p��I���>��郐����@�P�%UYYYpqq��[��v�Z���#-��j�6m�h�6l�DD��144Đ!Cp�� �8qC� �R�Ķm�УG�l��>>ؿ��U/j�?�����q��a�B��o��q�ơgϞ����g/���x���#??G������!Q1�����R*�hذ!�'�8�&�J��СC8{�,��:u�`�޽�ݻ7�6m�� �6����+>��c 88yyyr�DDD��HK-|�����������͛7���'w(DDgggL���+CY}A�+��[�ڹ�ϯ�T�ڱ�*�kr��]��kjj*>��������*� ����ܹ3�O�����*��y�yG���ڵ+6oތ��$|��g���™3g��������~�)�����$}��װ����#G�z�j��!"z�)��Jw��̜9`cc�v���Q�KNNƐ!C���===8;;C__*�J��4�}Q��+ۑ��-[� ((<�X����?����rss1w�\�"�8�wD/{{{|��ט>}:������X̝;����;#��t��]�PI ����… ���P������r�ED���HK��ŋ����8q"�\��K�.��ںR���a��SS�_��'�|�;v`ǎ����9*��B����� %,_�ul޼'O�����ŋ�G���+�cIm|X��� cccaoo/-Z$�bٲe�I�&���@�o�^�_Y�.}V����u׶˪eѥm*r=��XO��JZ&�vס��/B�����]��u=v�2d�077u������cǎ������(�E������?.�X����T����{��Q��w�h�ו?�Nh��D�ΝKlK�Izz��9s�hذ�t��������������˗E�:u�B����EDD�=&-�PRҲ��Ÿ~��=����Z���H��޽[B___��� }}}@������8!��_� ��y�w��n߾](��b�S*�����]�l�3���� �/�j�Z���k$�ns���R۶���.1m kkk��f͚�x|m�׵/�;���.��&M��;99 333�)O�R�v,�޽{���a�� {&���/]��<�U]�M;jS�ʢm�T�z�˱��>i��u���.�mm�ѥ)ZW;;�g�sww�? B�Pb�ȑ��qqqҶ&L(�8w�ޕ�@����e����w�h����'�o&-�����+6l� :v�(�7zzz�gϞb���"??_��3f�������͕;"���Z()iٮ];'-Z��A���> �[�nҲ]�v !�|�/�rhgg'����B�?^ �G�ұ�/_.��LlE�5k�L?~\�L��… %�… �vfff늎� LLL�����D���H��;�}0iIT�3gΈ�Ç ###�z�WĢE�Dvv���Q�=���8{�l��!"z!q"� �9s&���`gg� &,,,��_BOO��.bbbׯ_�={iii����1B*O�Pbbb����R��3g���;v�/�����|ddd 33�����ݻ�������۷ׯ_ǟ� �R���L@�Ν;v,���q��%阏/Sn IDAT 4�J��Z�Ɯ9sp������u���������Nu(�̙3Z���ds��A�n�VVV%�y����O�:�S�w���v��ʕ+������\ܸqC�'!!����=���C֭[���`lܸСC����|L]w������'���z����V�X�����X�r%"""p��L�0ӦM������<��*����K�,A�=��W_aРAhܸ��a�P���ggg������q���DEyyy }����t��pQyyy�s�,,,t���###��n޼)���������N�=33S�ˇ���ƶNNN_������w�a���HKKêU��u 6�/���֭[�T�B����6m�hu�����ץ�_z�%����v�*���&m(�{2##�D����?�IRe����Ç����022„ �C�II�BQ����Iiti�{��X���4k�L�c�v~ !��gڶKe^;�S��ҥm*z>V�J��u���.�{��-iYY�hm988[��c����hѢ.\���K��m۶�z�*h$�J*[__����{�.����ia����YJ����D׾�H��;�|����,,,�I�&aǎǁ���H��� $$}�􁾾��ᾰ^{�5bݺu )��KDD����W@q���PQPP��� H�@<�E���¤C�� m=���=n���^7h��������Wc۬��g����L���`�ҥ9r$ ���1{�l���.1?M�Ri}m�ץ/�>�.�+} j߾=RRR ���������}������=z4LLL��~���������+���*�o�A�z��{�nDGG�� �I�*���[[[�֭[�o�>i]ff&��¤۵͑���Ҩ�����شirrr�y�f����[[[����e˖җ���]Jj�8q�O��(W�V��o��͛7ѵkW|����믥�hO�~^1��.�W�/t�������@�F�@����999=�p�%����}��R�ХK���C�HII��s��|k�.Jkg]ڱ�z�i�F5w�� L�>�n�½{��g��r�Q}V��m�~�z����-��������/|}}�m۶R�֥m*z=y���u���.���5Z[ӧO�իW���c�̙��=zH�2DJ�&^ �2����/�|�V�B�~����?�����mۺ(O_�7~��x�������bɒ%�v�-Z�W^y�����O������gΜ�;����5�̙��?��ݻ'sDDD/��|@fmU�D<�7<|�PZ���%�Q��w��)T*�����JXYYI�����m�YO��ܻwOQ�DB�b�����5{����h޼�P*� OMMը�������ӨۢE��lߒ&��5�ڢ4��_޾(�m�ggg����K���Kxzz i�I�&I�V�{�,S�Nը�޽{�B|��˷o߮�_YmR����Y��4{���i����/]��<�U]�^V;jS��QZ6�|�쒖G������2���e�\��(���K�j{�.MѺ����p��>��S�mN�8Q�1�Z�v��S�N��X��K�B��uE��� �ۀ�U���|�{�nѳgOiB7���i6l���U(??_xyy b���r�CD���HK��� 'N���A�`kk�۷o���puuň#4FK5i�prr*��.]���G��������T*aee�~���?�@�>}�mG���˗�I�&(((�K�.}f$�J�˜1cЮ];���#==h۶-���1~��*���;��͛#22�Bu����^8b x2���򢷀�WY���S�7�|���2d���T*abb�������M�����*��Q���J�T*5F�G������y���ס�/�����hmmٲC� ���9LMM1h� ����L�2v�XiĤ��<==�>F`` Ο?�?�͛7���1�J%���ѽ{w̞=.\Ъ���uy��߉�����������={b��ݸt�Ə�z����ѣ�ѣG��憩S��U�-[��iӦh߾=�ҳ�j��?Q!�5 �ΝÁ�����|�_�:t@���f�<~�X�Pk�Y�f���'O���.("���DD�5###}Æ ���v�څ��z ... �ݻw�4��L�R!22 ����CBB��!�:J��IF��F��Q�S�Wz�9::J�+ 4jԨ�Y� �����Z~~>���T*�ŋ#55J�w��A�=�)�A��G�����c�ܹؼy3��� ����1l�0i[!���aff����K˝���V����;;;���X[[k�����u��6m��o{�e���=�:��"*�f䚊���2�״�RWE���M����2���U #�Z�a����U�,,�%�9ݿ?�9+��pr_�ǣ�s��u�������q�s+..N .Ԋ+�l�2���z��G��?�Q'NTtt����4h�~��(..N?���l�"����X�hP���M�69:P�;v���0 ?~\>>>U��ѣ�8q��nݪA��d2�駟���_i����u��ڰa����ʬ���H۶mS||�x�GG�F������2?� ���Nq ��ҥK�N�:饗^Rqq�UWGV���� ��dRVV�V�^��� ��GEE�O������nݺ ��ѣ�~��_i�ܹ���������SOi���rss�tq��ƍ5t�Pi���e�hӦ�RRR�{�ҥ�������,X �0lǣ�c�&'''�;Vcǎշ�~���������O��'����_=���N�j+�⿼���p�BM�2E�?�����ˬ�T���W�Ԃ��@M�4��P�Ţ��X���W�ԧO͚5˶-00P ,Pxx�$)55U���***�����~�i������O���j۶�rrr�����1.�t[wHHH��˓����~X�w����´d����K�RRR���|�n�Z�G��_��[qu��͚>}�Μ9��#G����W``�&O�����_�xTg�k��V\\��.]j{�x�f����h�����h( �Нwީ�;wjƌZ�|��#@�@�@�SRR��;��7���ѣ����jCQZZ���$���h���*--�t�����hEDD�����)���d���S%%%ڽ{� ��H����$�������l��w���( V�&M���$����5k�<<<�k�.M�0A�����_���'O::��u��Us��Qii�fΜ���bGG���%�F���KO?��^�u"SKn��&����JKK�ҥKյkW����駟V�N�����/�ptL�zꩧ��ﯯ��Z������@�����*1 C۶mSLL�������D�Էo_=��#���{��������ƍ,�٬��d���9:4X-Ֆ���e˖�7���ӧ%I�ڵSTT�f̘!___'��ƍ�u��)<<\ �� EK@����k��Պ���W_}%IrvvVxx����u�w88ᵑ����]���ٳ�裏��H� Q�Ԫ]�v)&&F ***�$u��]��ѲZ�j޼��֭ŋ��S�N���wߩE��� EK@�����k����_]����$OOOM�:U?�������n����o߾:p���͛�^x�ё���h �S���z����d��ٳG�ԤI���(::ZÇ��drp�ڵw�^ 0@M�4����u뭷�i/,,ԡC��xpQG4nM�6Udd�>��3�ݻW�&M����>��#�9R]�v�?�����9:j������C���H3g����v�ܩ^�zi�ܹL�+-�ܩS��e˖)--M�ԲeKM�4I����ҥ���\nn�n���8qB��� ל9s��[oٶ�pႚ6m���P?Q�8Lqq�֯_�����_��$�L&�1B���o�&M�M�����~��f���(''�L��]�4h� �����^� ����ƍ�;v�믿VTT��5k�͛7�{�Q�Ν��/^Q�k(�u�V�Z�ܹsW݇�۷; ����+999z�7�|�r>|X�ԼysY�VEGG�{��NX�����O��������������N �p-�Rii�����d�m޼��0�;�C��� ������Z�J����Tdž 4q�D�V�����̙3j֬Y�f����%��������zKgϞ�$���j�̙���R۶m+���1���k���z�����Q'9���4`����Ov�ٺu���:� �i ���t�ŋ+--M111 TZZ����?���O�'O־}������Rm޼Y��~��9R'9�����g�U��m۶�Ih�Xi hp �Ж-[� 6���T�ԿEGGkܸqruu�$����nPvv������֯_��I���|Y�V%$$T�����駟�Ih�(Z�#G�h�ҥz�7l�#ٮ];EEE顇����S�^����Mo�����:�UZZ�9s���_�p;�9sFf��Nr@CD��(�?^��񊉉�7�|#�bA�l6��P�ɤ���멧���d��\111�5k�JJJ��f�ƍ=zt�� �i h�7o���(}���ڹs�Ə/�0*|��az�g4q�D]�p�NrEGG+!!A-Z�(w�;v����P���h�������]�4H jӦM�dٿ�BBB���yE[�>}�w��:�"���F�ĉ�X,*,,��O@@�6lؠ���:�t��Q��+󾓓����ժU�:�n4J˖-�R�R�>��j�֭u��S�Nڽ{�� V�����ܹ�N�����%��),,�K/�T��999=z�V�XQ˩.jժ�6nܨɓ'�y۶mu24D�htV�^-��Z�qƎ��kתI��_�c����?��g�-���%����WFF�N�8a���322����ӧOW:VDD�V�ZU�ӿkbŊ����$�:u�� EK@�5k�,�޽��� �PQQ� U\\\�srr���$IrqqQ�Ν���R[�������ÇթS'yzz�� �+���A�9:�k��������߿���/--�$�o���y.�駟�|��&77��8EK@�7�|;:F��ٙ�KRHH�233��p%4x�{�V�޽��w��JLLtt R��?��h �^�h �^�h �^�h h�>��s�s�=j۶�������_��W�0a�6n�Xf����s�=�}��9(�u�}��d2�d2)%%��q��������:t� m�;wN���JNN����ƌck;p���ϟ/I���Q�>}�yf�E-��… m˿��o�뮻TZZ��Q[�l��l��y���լY�Z�Z{�'��H�:t���4�_�h�>,I���ғO>�~��i���4i�V�Z�_|Ѷm���e�{�̙�ۦ7m�$���;w�Ըq����^�z��}��W�0a�ڷo��M����GV�U����d{��t�����G...ruu��b�ԩS���Vf�q����ݽ{�ƍ�-Z���O���$)66V�;w�������{��u�^x����*44TU�6{�l[�={���_�~2�L2����˫���D��H���J�N�>��C��W^��ݻUPPP�Ǐ�u����ٳ2 C�����~�����өS�Զm[eggk����ӧ�]�Vaa���ݫ��P���Wk���������g͚5�ׇ�_|!�b���ݽ�� ��E��(=��jڴ�$�_���fϞ������SV�UǏ�m�g������^�l� Ða5j�c7m�T۷oWVV��~�m+**J����ر�RRR�������Z͛7�ٳg������?,,L������Ց#G�����s�J��=�>���ԱcG}��7z��m�_�^��t��!�y睒��'Oj����:n�f�޽�z��-���̒�Ie �S�L����~��F��;��_|�E�iӦM:}��$���@�W��g�}���d���Uy���V l۶���ݫ��tIRii��M�f��d2I�v�ء��b9;;kРAJLL�o��'N���P����>������׭�ު�;j��ْ.����?�YM�4ѽ�ޫ;vH��v着J�)S�h����������5|�p[Ѳs��2dH����%��ѣ��~�m��~�A�7oֳ�>k[�8�v�pIDAT�s�N�9���^�;�����e{}�� �8q�>������U�֭����r�/���Ν;K��7on{���_M�\��������/..�cO�2 �J�"##���� �m۶Urr������� q{8���� ��j�[n�E�=����~��gϞ-���\\\�����m{i�������Ҿ}�l��n�MG��a���+��Rq�rNNN�ץ��W�WZZ����n㾚�fkժ����%I|��V�\i�4iҤj� EK@#5u�T���K�?��>���ݻW�V�*���7�|���������R1((H:t�t�x�e�[[VV��,Yb���̙3e��p� ��w�}��{h�իW�Y�fj֬Y����_��viEenn�bbb$Iw�}��x8b4|�h����K}��Wm ӭ��j��o߾2�L2 CK�,ђ%K$Iyyy2�������_]*((Ј#Զm[IҩS�$I����%I�������rrr��o(==]�N��w�}W�����d6l�n��;v�V�TȬ��JK@��h�"͝;W �������Լys���C��_�X��e˖�b�\�6�����?�}�ݧ:(''G���v�iӦ�VZzxxhӦM�߿������g��[n����ke���0 �k''�jekҤ�&O�l��M�6 ��]��@�a2.�BЀ���(11Q6lPpp���4(%%% �����䤳gϖ�E��8������\g�����}��:x�$)<<�^,�ߴ�:����S�N���C!!!�������%י h�������p� EK� EK� EK� �4x!!!�ݻ��c��߿��8EK@�@� �a��CP)))���ut ԡΝ;�����1\c-�+<�@�B�@�B�@�B�@�B�@�B�@�B�@�B�@�B�@�B�@�B�@�B�@�B�@�B�@�B�@�����j�j��Վ��wwwmܸQ� rt�ְ�����Ә1c�{�nGGj +-����+22��1vڹs���^eeei̘1��D��JK��I�&�馛4q�DV\�Q�h Ѐ�L&���Q�D�B���srr�p�F��%@#@�� EK�F��% ����K4- �h�(Z4B.ѐQ�h�(\��rvtT��ݻ�� /T�M``�z��hԨQڷo��QB��(Z4P���z�'���S�Çׁ��/�����-Q�Q�h�,�,X`���}���0P;�MK� EK� EKv����5b�5o�\f�Y��~����2۬_����Fڎ;�����Q[�oڴi�3gN-$�����k�Nmڴ�̙3����CG��T����Z�re����7-T���T���;v��{�=���h���*--ut�Zw�M7���wt��j��iӦ��…Z�b�BCC��"�>>���@�233u��=�������lVhh�z��%IJNN��b����u��aY,Y,��Ɩg���z��g������)99Y������'���K����6m� l}�/_��o�Y-Z������̙���bIWo�r�-�ܹ�5w�\�����G�{���'�Ţ޽{������Ϳ�~�l�R����퓒����k+�V��^��u�&�٬N�:)..�֖���1c����]��ޚ;w�JJJl����Wtt�� �n�A�G�����ٓ?>>^�EaaaJHH�"E$��ɓ ����Z�n���ܹsv���Y,���k���X,�={v��/_)��Ci֬Yv��?��ʎOM�aM��������?�ӧ�\]]����ψ��WĞ�`M�1��u/22Ґd���_����ذX,�=��cl߾���_��]BB�q��7�;ϰa� ___�o�1 �0rrr���l�0 cԨQFhh����k���cƌ1�͛g�o�w��q�b�K�.��`\�p��ӧ������HKK3\]]����*��۷�ڵ�����7 ø�曍�k���~���9s��ݿ2�7o6�f��y�f�0 ��ɓFRR��}Ĉ��j5 ��Ǐ�����ŋm����3� b.\0�w�n��Ɩ����W��S�N5��+ޯ,ìY����0����())1>��S����v��j׮��k׮����o���1c���c�ٝ��s`� ���S�sXǯ�����3z��addd��醿�������s|�c��5��\/��� IƆ �+-T���I;w�T���5i�$yzzj„ ��ή�X�Ǐ׭��*Ijժ����t��qmڴI/���Z�l)�٬Y�fiݺu�~����~��� ӷ�~kk���WӦM���@u��Q&�I?��s �޾��V�֬Y#I*((����e�Z��_�+Vh�ĉ1b�$���[�F��$���i˖-�7o�\]]���)S��>(3������⢦M��o߾:t�P��*����3g�(55U&�IT�fͪ��c=zT�W������]�tѧ�~*I:u�6o�\����K����sXǯ�������������h �RM�4�ɓ'5|�p����o߾�����꺤_�~���P�.]����^{��9֬Y���u��Yf�Ycƌѱc�$I;v�… 5t�P 2D3f�А!C��/?���N���?a��ٳGAAAenQ����F������裏�l6�{��:~���}�ʕ���V�6m����*߾_���7��d�X���*66V�Ew�}������P���O���v�����b�(,,L W���ԯ_?��f :T���Uj�,����aÆ�n��ѣ���T����W�?//O7�t�V�Ze��׿���M�&IJNN��b����u��aY,Y,�����1����:t�6����R�մnnn2��W]e�|�r�|��jѢ�|||4g�K��;RQ{���;�֭��f�:uꤸ�8��V6�ɓ',�n�ZԹs��n���QY��������O?U�.]�����H�?��V��GDD�b�(==]ӧO��b��ٳm�]�/��yi�͛7K�/^|�5�O(Z���ɓպukegg���Z�n��.]*I�ݻ�:t���D��k֬���߯&M.��#22R?����9��Ǐ�ĉz��g��'..N���t��a>ޞCkW���_Q~www���{���~���-_�\?����,Y"I�ڵ�RSS���+ @���JMMUTT��sس�������_�����?�����ۊ7��e˖z�����/�h߾}Z�n���k�w������O��_~Y�Ν�޽{աC�Z�/I ,�����������_|QNNNv�W����M�t��}�v�ڵKiiiJMM����mm��BB�RSSնm[�]�V���z��m�]�/W�5���w�u�$�̙3W��EK����Ӗ-[4o�<������WS�L�|`��j�j͚5�����_�^V�U�t��qmڴI/���Z�l)�٬Y�fiݺuW�5~�x�z뭒�V�Z��˫J�W����o��F��͓��������no�������EM�6U߾}u�СJ�UEuǷ'PP��ϟ���p=��3Z�v��5kfw����΁�����~җ_~�?��rvv��߮A�Uy��DFF�>���� ӷ�~kk��;bO�ʬX�B'NԈ#$I���5jT��wssә3g���*�ɤ����T�n�磲�k���g��S��]�v����̙3m�Ȫ\�ƞk�%W�F^>����_ ��{�p��*u��i�!�{�۷/s�ndd�������� 6���O={��t�FI9r����)S��… W�e�X*�RY��dgg�d2��߱cG����ߢE �k'''U9kE�;���|�A���k���U~�NM�Qe��^卟��%��Tf����⭪�}�Mbb�,___Y,�\�R�������#���LFF�n���j�Oe�?�� RXX�Z�n�3f��n�磲�k���g��?S���:uꔤ�]�ƞk�%W�F^>��m�$I���������xT���K&�I�������$�8qBmڴ�m�=z(!!A~�a�d:t��dҷ�~+��\�\�=ٸ:O>n۶� �Pnn�<<<$]�}7{۫��>�7��34z�h�ٳG�W�Vddd�v��$�0j4Gy*;5ui���,�g��ɓ ��x���eV�9sFcǎ�ڵk*�ɤGy��oXV���eڷo�#G�T�ͥ�ae�K�����ŋK��2v�С��;l������|T6~M������ɓ�ח�j����|�ծ����}�)11Q+W�Tppp��� +-T���]w�u�-Z� .(--Mqqq /���jUll������C���O#G�ԬY����+���6m�&�ԭ[7�����j�Νv�;:Mٓ���^�����5k�(::���Ͻ������ӧOWk��Tvj�R�pѢE*--���O?����[�nULL�N�>�s���w�QPP��=??_EEE�ٳ���t������E�L����zK[�n�tqu��\f��������ck�����=*�+Z]]]�j���Q���<��3��[�Wm�=�|�Meee��ٳZ�l�Ǝ+���{���|�K���l0�0\�(Z��ʕ+����6m�(((H��኎�.�̈́ �g�]q��5kTRR�Ν;�l6k̘1:v�X��0`�,��}�]����b���ﶵ���z뭷t�m�iڴi�ݻw����;:MU�����Ҽy�f��h�B���ӓO>�{キ�J�~��)""B]�t����^{�5��Ge砦�h͚5ڱc�<==���O���{�n��n�:u��I^^^:v�mU�t�V�� j�С2d�f̘�!C�\1Ny�{�WdԨQZ�|�}�Q��fu��]Ǐ/�M˖-��K/)<<\f�ٶ����A  :extends CL:STREAM . #+END_SRC * Test #+BEGIN_SRC lisp (ql:quickload :prove) (prove:run (asdf:system-relative-pathname :abcl "t/url-stream.lisp")) #+END_SRC * Changes ** <2020-04-18 Sat> Added accessors to underlying data Used by Jeannie to get an InputStream from a URI. abcl-src-1.9.0/doc/manual/Makefile0100644 0000000 0000000 00000000731 14202767264 015433 0ustar000000000 0000000 all: abcl.pdf abcl.pdf: abcl.tex abcl.bib java.tex extensions.tex threads.tex pdflatex abcl.tex bibtex abcl makeindex abcl pdflatex abcl.tex pdflatex abcl.tex #ABCL = abcl ABCL = ../../abcl # XXX TODO pare down to using --noinit grovel: $(ABCL) --batch --noinform \ --eval '(require :abcl-contrib)' \ --eval '(asdf:make :abcl/documentation)' \ --eval '(abcl/documentation:index)' clean: rm -f *.aux *.bbl *.blg *.idx *.ilg *.ind *.log *.out *.toc abcl.pdf abcl-src-1.9.0/doc/manual/README.markdown0100644 0000000 0000000 00000001600 14202767264 016470 0ustar000000000 0000000 ABCL User Manual ================ With a suitable TexLive installed, to build simply run `make`. If you cannot run make, the following sequence of commands also gets you a pdf of the manual: cmd$ pdflatex abcl.tex && bibtex abcl && makeindex abcl && pdflatex abcl.tex && pdflatex abcl.tex ## Generating docstrings 1. Ensure that the toplevel 'abcl.asd' is loadable by ASDF. If the ABCL source resides in "~/work/abcl/", this can be accomplished by creating the file with the contents: (:tree (:home "work/abcl/")) 2. Execute the following code from the ABCL REPL: (require :abcl-contrib) (require :jss) (asdf:load-system :abcl/documentation) (dolist (package '(:java :ext :sys :jss :mop :threads)) :doing (abcl/documentation:grovel-docstrings-as-tex :package package)) abcl-src-1.9.0/doc/manual/abcl-asdf.tex0100644 0000000 0000000 00000012032 14202767264 016326 0ustar000000000 0000000 \paragraph{} \label{ABCL-ASDF:*ADDED-TO-CLASSPATH*} \index{*ADDED-TO-CLASSPATH*} --- Variable: \textbf{*added-to-classpath*} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:*INHIBIT-ADD-TO-CLASSPATH*} \index{*INHIBIT-ADD-TO-CLASSPATH*} --- Variable: \textbf{*inhibit-add-to-classpath*} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:*MAVEN-HTTP-PROXY*} \index{*MAVEN-HTTP-PROXY*} --- Variable: \textbf{*maven-http-proxy*} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} A string containing the URI of an http proxy for Maven to use. \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:*MAVEN-REMOTE-REPOSITORY*} \index{*MAVEN-REMOTE-REPOSITORY*} --- Variable: \textbf{*maven-remote-repository*} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} The remote repository used by the Maven Aether embedder. \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:*MAVEN-VERBOSE*} \index{*MAVEN-VERBOSE*} --- Variable: \textbf{*maven-verbose*} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} Stream to send output from the Maven Aether subsystem to, or NIL to muffle output \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:*MVN-LIBS-DIRECTORY*} \index{*MVN-LIBS-DIRECTORY*} --- Variable: \textbf{*mvn-libs-directory*} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} Location of 'maven-core-3..

.jar', 'maven-embedder-3..

.jar' etc. \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:ADD-DIRECTORY-JARS-TO-CLASS-PATH} \index{ADD-DIRECTORY-JARS-TO-CLASS-PATH} --- Function: \textbf{add-directory-jars-to-class-path} [\textbf{abcl-asdf}] \textit{directory recursive-p} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:AS-CLASSPATH} \index{AS-CLASSPATH} --- Function: \textbf{as-classpath} [\textbf{abcl-asdf}] \textit{classpath} \begin{adjustwidth}{5em}{5em} Break apart the JVM CLASSPATH string into a list of its consituents. \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:ENSURE-MVN-VERSION} \index{ENSURE-MVN-VERSION} --- Function: \textbf{ensure-mvn-version} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} Return t if Maven version is 3.0.3 or greater. \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:FIND-MVN} \index{FIND-MVN} --- Function: \textbf{find-mvn} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} Attempt to find a suitable Maven ('mvn') executable on the hosting operating system. Returns the path of the Maven executable or nil if none are found. Returns the version of Maven found as the second value. Emits warnings if not able to find a suitable executable. \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:INIT} \index{INIT} --- Function: \textbf{init} [\textbf{abcl-asdf}] \textit{\&optional \&key (force NIL)} \begin{adjustwidth}{5em}{5em} Run the initialization strategy to bootstrap a Maven dependency node. Set *MVN-LIBS-DIRECTORY* to an explicit value before running this function in order to bypass the dynamic introspection of the location of the mvn executable with an explicit value. \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:MAKE-REMOTE-REPOSITORY} \index{MAKE-REMOTE-REPOSITORY} --- Function: \textbf{make-remote-repository} [\textbf{abcl-asdf}] \textit{id type url} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:NEED-TO-ADD-DIRECTORY-JAR?} \index{NEED-TO-ADD-DIRECTORY-JAR?} --- Function: \textbf{need-to-add-directory-jar?} [\textbf{abcl-asdf}] \textit{directory recursive-p} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:RESOLVE} \index{RESOLVE} --- Generic Function: \textbf{resolve} [\textbf{abcl-asdf}] \textit{} \begin{adjustwidth}{5em}{5em} Returns a string in JVM CLASSPATH format as entries delimited by classpath separator string. \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:RESOLVE-ARTIFACT} \index{RESOLVE-ARTIFACT} --- Function: \textbf{resolve-artifact} [\textbf{abcl-asdf}] \textit{group-id artifact-id \&key (version LATEST versionp)} \begin{adjustwidth}{5em}{5em} Resolve artifact to location on the local filesystem. Declared dependencies are not attempted to be located. If unspecified, the string "LATEST" will be used for the VERSION. Returns the Maven specific string for the artifact \end{adjustwidth} \paragraph{} \label{ABCL-ASDF:RESOLVE-DEPENDENCIES} \index{RESOLVE-DEPENDENCIES} --- Function: \textbf{resolve-dependencies} [\textbf{abcl-asdf}] \textit{group-id artifact-id \&key (version LATEST versionp) (repository *maven-remote-repository* repository-p)} \begin{adjustwidth}{5em}{5em} Dynamically resolve Maven dependencies for item with GROUP-ID and ARTIFACT-ID optionally with a VERSION and a REPOSITORY. All recursive dependencies will be visited before resolution is successful. If unspecified, the string "LATEST" will be used for the VERSION. Returns a string containing the necessary jvm classpath entries packed in Java CLASSPATH representation. \end{adjustwidth} abcl-src-1.9.0/doc/manual/abcl.aux0100644 0000000 0000000 00000035130 14242630063 015402 0ustar000000000 0000000 \relax \providecommand\hyper@newdestlabel[2]{} \providecommand\HyperFirstAtBeginDocument{\AtBeginDocument} \HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined \global\let\oldcontentsline\contentsline \gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} \global\let\oldnewlabel\newlabel \gdef\newlabel#1#2{\newlabelxx{#1}#2} \gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} \AtEndDocument{\ifx\hyper@anchor\@undefined \let\contentsline\oldcontentsline \let\newlabel\oldnewlabel \fi} \fi} \global\let\hyper@last\relax \gdef\HyperFirstAtBeginDocument#1{#1} \providecommand\HyField@AuxAddToFields[1]{} \providecommand\HyField@AuxAddToCoFields[2]{} \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.1}Preface to the First Edition}{4}{subsection.0.0.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.2}Preface to the Second Edition}{4}{subsection.0.0.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.3}Preface to the Third Edition}{4}{subsection.0.0.3}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.4}Preface to the Fourth Edition}{5}{subsection.0.0.4}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.5}Preface to the Fifth Edition}{5}{subsection.0.0.5}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.6}Preface to the Sixth Edition}{5}{subsection.0.0.6}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.7}Preface to the Seventh Edition}{5}{subsection.0.0.7}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.8}Preface to the Eighth Edition}{5}{subsection.0.0.8}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.9}Preface to the Ninth Edition}{5}{subsection.0.0.9}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {0.0.10}Preface to the Tenth Edition}{6}{subsection.0.0.10}\protected@file@percent } \citation{adoptium} \citation{CLHS} \@writefile{toc}{\contentsline {chapter}{\numberline {1}Introduction}{7}{chapter.1}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \@writefile{toc}{\contentsline {section}{\numberline {1.1}Conformance}{7}{section.1.1}\protected@file@percent } \newlabel{section:conformance}{{1.1}{7}{Conformance}{section.1.1}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {1.1.1}ANSI Common Lisp}{7}{subsection.1.1.1}\protected@file@percent } \citation{CLHS} \citation{nio} \@writefile{toc}{\contentsline {subsection}{\numberline {1.1.2}Contemporary Common Lisp}{8}{subsection.1.1.2}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {1.2}License}{8}{section.1.2}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {1.3}Contributors}{8}{section.1.3}\protected@file@percent } \citation{slime} \@writefile{toc}{\contentsline {chapter}{\numberline {2}Running ABCL}{11}{chapter.2}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \@writefile{toc}{\contentsline {section}{\numberline {2.1}Options}{11}{section.2.1}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {2.2}Initialization}{12}{section.2.2}\protected@file@percent } \@writefile{toc}{\contentsline {chapter}{\numberline {3}Interaction with the Hosting JVM}{13}{chapter.3}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \@writefile{toc}{\contentsline {section}{\numberline {3.1}Lisp to Java}{13}{section.3.1}\protected@file@percent } \newlabel{section:lisp-java}{{3.1}{13}{Lisp to Java}{section.3.1}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {3.1.1}Low-level Java API}{13}{subsection.3.1.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{Calling Java Object Methods}{13}{section*.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{Calling Java object methods: dynamic dispatch}{14}{section*.3}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{Dynamic dispatch: Caveats}{14}{section*.4}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{Calling Java class static methods}{15}{section*.5}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{Parameter matching for FFI dynamic dispatch}{15}{section*.6}\protected@file@percent } \newlabel{section:param-matching-for-ffi}{{3.1.1}{15}{Parameter matching for FFI dynamic dispatch}{section*.6}{}} \@writefile{toc}{\contentsline {subsubsection}{Instantiating Java objects}{15}{section*.7}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{Accessing Java object and class fields}{15}{section*.8}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {3.2}Java to Lisp}{15}{section.3.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.2.1}Calling Lisp from Java}{15}{subsection.3.2.1}\protected@file@percent } \newlabel{section:calling-lisp-from-java}{{3.2.1}{15}{Calling Lisp from Java}{subsection.3.2.1}{}} \@writefile{toc}{\contentsline {subsubsection}{Multiple Values}{16}{section*.9}\protected@file@percent } \citation{jsr-223} \@writefile{toc}{\contentsline {subsubsection}{Introspecting a LispObject}{17}{section*.10}\protected@file@percent } \newlabel{topic:Introspecting a LispObject}{{3.2.1}{17}{Introspecting a LispObject}{section*.10}{}} \@writefile{toc}{\contentsline {paragraph}{LispObject as \texttt {boolean}}{17}{section*.11}\protected@file@percent } \@writefile{toc}{\contentsline {paragraph}{LispObject as a list}{17}{section*.12}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {3.3}Java Scripting API (JSR-223)}{17}{section.3.3}\protected@file@percent } \newlabel{section:java-scripting-api}{{3.3}{17}{Java Scripting API (JSR-223)}{section.3.3}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {3.3.1}Conversions}{18}{subsection.3.3.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.3.2}Implemented JSR-223 interfaces}{18}{subsection.3.3.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{The ScriptEngine}{18}{section*.13}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.3.3}Start-up and configuration file}{18}{subsection.3.3.3}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.3.4}Evaluation}{19}{subsection.3.3.4}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.3.5}Compilation}{19}{subsection.3.3.5}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.3.6}Invocation of functions and methods}{19}{subsection.3.3.6}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.3.7}Implementation of Java interfaces in Lisp}{19}{subsection.3.3.7}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {3.4}Implementation Extension Dictionaries}{20}{section.3.4}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {3.4.1}The JAVA Dictionary}{20}{subsection.3.4.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{Modifying the JVM CLASSPATH}{20}{section*.14}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{Creating a synthetic Java Class at Runtime}{20}{section*.15}\protected@file@percent } \@input{java.aux} \citation{lea-1998} \@writefile{toc}{\contentsline {subsection}{\numberline {3.4.2}The THREADS Dictionary}{29}{subsection.3.4.2}\protected@file@percent } \@input{threads.aux} \citation{RHODES2007} \@writefile{toc}{\contentsline {subsection}{\numberline {3.4.3}The EXTENSIONS Dictionary}{32}{subsection.3.4.3}\protected@file@percent } \@input{extensions.aux} \citation{rfc3986} \@writefile{toc}{\contentsline {chapter}{\numberline {4}Beyond ANSI}{43}{chapter.4}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \newlabel{chapter:beyond-ansi}{{4}{43}{Beyond ANSI}{chapter.4}{}} \@writefile{toc}{\contentsline {section}{\numberline {4.1}Compiler to Java Virtual Machine Bytecode}{43}{section.4.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {4.1.1}Compiler Diagnostics}{43}{subsection.4.1.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {4.1.2}Decompilation}{43}{subsection.4.1.2}\protected@file@percent } \newlabel{CL:DISASSEMBLE}{{4.1.2}{43}{Decompilation}{subsection.4.1.2}{}} \@writefile{toc}{\contentsline {section}{\numberline {4.2}Pathname}{43}{section.4.2}\protected@file@percent } \citation{maso2000} \citation{uri-pathname} \@writefile{toc}{\contentsline {subsubsection}{URL-PATHNAME}{44}{section*.244}\protected@file@percent } \newlabel{EXTENSIONS:URL-PATHNAME}{{4.2}{44}{URL-PATHNAME}{section*.244}{}} \newlabel{EXTENSIONS:URL-PATHNAME-SCHEME}{{4.2}{44}{URL-PATHNAME}{section*.244}{}} \newlabel{EXTENSIONS:URL-PATHNAME-FRAGMENT}{{4.2}{44}{URL-PATHNAME}{section*.244}{}} \newlabel{EXTENSIONS:URL-PATHNAME-AUTHORITY}{{4.2}{44}{URL-PATHNAME}{section*.244}{}} \newlabel{EXTENSIONS:PATHNAME-URL-P}{{4.2}{44}{URL-PATHNAME}{section*.244}{}} \newlabel{EXTENSIONS:URL-PATHNAME-QUERY}{{4.2}{44}{URL-PATHNAME}{section*.244}{}} \citation{quicklisp} \newlabel{section:jar-pathname}{{4.2}{45}{URL-PATHNAME}{lstnumber.-18.1}{}} \@writefile{toc}{\contentsline {subsubsection}{JAR-PATHNAME}{45}{section*.245}\protected@file@percent } \newlabel{section:JAR-PATHNAME}{{4.2}{45}{JAR-PATHNAME}{section*.245}{}} \@writefile{toc}{\contentsline {section}{\numberline {4.3}Package-Local Nicknames}{45}{section.4.3}\protected@file@percent } \newlabel{section:package-local-nicknames}{{4.3}{45}{Package-Local Nicknames}{section.4.3}{}} \citation{RHODES2007} \citation{RHODES2007} \citation{closer-mop} \@writefile{toc}{\contentsline {section}{\numberline {4.4}Extensible Sequences}{47}{section.4.4}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {4.5}Extensions to CLOS}{47}{section.4.5}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {4.5.1}Metaobject Protocol}{47}{subsection.4.5.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {4.5.2}Specializing on Java classes}{47}{subsection.4.5.2}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {4.6}Extensions to the Reader}{48}{section.4.6}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {4.7}Overloading of the CL:REQUIRE Mechanism}{48}{section.4.7}\protected@file@percent } \citation{asdf} \@writefile{toc}{\contentsline {section}{\numberline {4.8}JSS extension of the Reader by SHARPSIGN-DOUBLE-QUOTE}{49}{section.4.8}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {4.9}ASDF}{49}{section.4.9}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {4.10}Extension to CL:MAKE-ARRAY}{49}{section.4.10}\protected@file@percent } \newlabel{section:make-array}{{4.10}{49}{Extension to CL:MAKE-ARRAY}{section.4.10}{}} \@writefile{toc}{\contentsline {chapter}{\numberline {5}Contrib}{51}{chapter.5}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \@writefile{toc}{\contentsline {section}{\numberline {5.1}abcl-asdf}{51}{section.5.1}\protected@file@percent } \newlabel{section:abcl-asdf}{{5.1}{51}{abcl-asdf}{section.5.1}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {5.1.1}Referencing Maven Artifacts via ASDF}{51}{subsection.5.1.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {5.1.2}API}{51}{subsection.5.1.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {5.1.3}Directly Instructing Maven to Download JVM Artifacts}{52}{subsection.5.1.3}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {5.2}asdf-jar}{52}{section.5.2}\protected@file@percent } \newlabel{section:asdf-jar}{{5.2}{52}{asdf-jar}{section.5.2}{}} \@writefile{toc}{\contentsline {section}{\numberline {5.3}jss}{52}{section.5.3}\protected@file@percent } \newlabel{section:jss}{{5.3}{52}{jss}{section.5.3}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {5.3.1}JSS usage}{53}{subsection.5.3.1}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {5.4}jfli}{53}{section.5.4}\protected@file@percent } \newlabel{section:jfli}{{5.4}{53}{jfli}{section.5.4}{}} \@writefile{toc}{\contentsline {section}{\numberline {5.5}abcl-introspect}{53}{section.5.5}\protected@file@percent } \newlabel{section:abcl-introspect}{{5.5}{53}{abcl-introspect}{section.5.5}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {5.5.1}Implementations for CL:DISASSEMBLE}{53}{subsection.5.5.1}\protected@file@percent } \newlabel{abcl-introspect-disassemblers}{{5.5.1}{53}{Implementations for CL:DISASSEMBLE}{subsection.5.5.1}{}} \@writefile{toc}{\contentsline {section}{\numberline {5.6}abcl-build}{55}{section.5.6}\protected@file@percent } \newlabel{section:abcl-build}{{5.6}{55}{abcl-build}{section.5.6}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {5.6.1}ABCL-BUILD Utilities}{55}{subsection.5.6.1}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {5.7}named-readtables}{55}{section.5.7}\protected@file@percent } \newlabel{section:named-readtables}{{5.7}{55}{named-readtables}{section.5.7}{}} \citation{pandemos} \@writefile{toc}{\contentsline {chapter}{\numberline {6}History}{57}{chapter.6}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \@writefile{toc}{\contentsline {chapter}{\numberline {A}The MOP Dictionary}{59}{appendix.A}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \@input{mop.aux} \@writefile{toc}{\contentsline {chapter}{\numberline {B}The SYSTEM Dictionary}{67}{appendix.B}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \@input{system.aux} \@writefile{toc}{\contentsline {chapter}{\numberline {C}The JSS Dictionary}{89}{appendix.C}\protected@file@percent } \@writefile{lof}{\addvspace {10\p@ }} \@writefile{lot}{\addvspace {10\p@ }} \@input{jss.aux} \bibdata{abcl} \bibcite{quicklisp}{Bea} \bibcite{rfc3986}{BLFM05} \bibcite{closer-mop}{Cos11} \bibcite{uri-pathname}{Eve11} \bibcite{jsr-223}{Gro06} \bibcite{adoptium}{Gro22} \bibcite{pandemos}{Hal20} \bibcite{lea-1998}{Lea98} \bibcite{maso2000}{Mas00} \bibcite{nio}{Mic05} \bibcite{CLHS}{P{$^{+}$}96} \bibcite{asdf}{RBRK} \bibcite{RHODES2007}{Rho09} \bibcite{slime}{sli} \bibstyle{alpha} \gdef \@abspage@last{100} abcl-src-1.9.0/doc/manual/abcl.bbl0100644 0000000 0000000 00000006322 14242630061 015343 0ustar000000000 0000000 \newcommand{\etalchar}[1]{$^{#1}$} \begin{thebibliography}{BLFM05} \bibitem[Bea]{quicklisp} Zach Beane. \newblock Quicklisp. \newblock \url{http://www.quicklisp.org/}. \newblock Last accessed Jan 25, 2012. \bibitem[BLFM05]{rfc3986} Tim Berners-Lee, Roy Fielding, and Larry Masinter. \newblock Rfc 3986: Uri generic syntax. \newblock \url{http://www.ietf.org/rfc/rfc3986.txt}, 2005. \newblock Last accessed Feb 5, 2012. \bibitem[Cos11]{closer-mop} Costanza.Pascal. \newblock Closer to mop is a compatibility layer that rectifies many of the absent or incorrect clos mop features across a broad range of common lisp implementations. \newblock \url{https://github.com/pcostanza/closer-mop}, 2011. \newblock Last accessed Oct 2, 2016. \bibitem[Eve11]{uri-pathname} Mark Evenson. \newblock Unpublished draft of {An Implementation and Analysis of Adding IRI to Common Lisp's Pathname}. \newblock \url{https://github.com/easye/abcl/blob/master/doc/design/pathnames/url-pathnames.mark}, 2011. \newblock Last accessed Oct 2, 2016. \bibitem[Gro06]{jsr-223} Mike Grogan. \newblock Scripting for the {Java} platform. \newblock Final Draft Specification JSR-223, Sun Microsystems, Inc., 2006. \newblock \url{http://jcp.org/aboutJava/communityprocess/final/jsr223/index.html}. \bibitem[Gro22]{adoptium} The Adoptium~Working Group. \newblock Freely redistributable adoptium openjdk releases. \newblock \url{https://adoptium.net/}, 2022. \newblock Last accessed April 29, 2022. \bibitem[Hal20]{pandemos} Harry Halprin. \newblock $\pi$$\alpha$$\nu$$\delta$$\eta$$\mu$o$\zeta$. \newblock \url{https://agorist.xyz/files/Agorism_XXI_I_2022.pdf}, 2020. \newblock Last accessed April 29, 2022. \bibitem[Lea98]{lea-1998} Doug Lea. \newblock Overview of package util.concurrent release 1.3.4. \newblock \url{http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html}, 1998. \newblock Last accessed Oct 2, 2016. \bibitem[Mas00]{maso2000} Brian Maso. \newblock A new era for {Java} protocol handlers. \newblock \url{http://docslide.us/documents/java-protocol-handler.html}, August 2000. \newblock Last accessed Oct 2, 2016. \bibitem[Mic05]{nio} Sun Microsystems. \newblock Nio. \newblock \url{https://docs.oracle.com/javase/8/docs/api/java/nio/package-summary.html}, 2005. \newblock Last accessed April 30, 2022. \bibitem[P{\etalchar{+}}96]{CLHS} Kent Pitman et~al. \newblock {Common Lisp HyperSpec}. \newblock \url{http://www.lispworks.com/documentation/HyperSpec/Front/index.htm}, 1996. \newblock Last accessed Feb 4, 2012. \bibitem[RBRK]{asdf} Fran\c{c}ois-Ren\'{e} Rideau, Daniel Barlow, Christopher Rhodes, and Garry King. \newblock Asdf. \newblock \url{http://common-lisp.net/project/asdf/}. \newblock Last accessed Feb 5, 2012. \bibitem[Rho09]{RHODES2007} Christophe Rhodes. \newblock User-extensible sequences in {Common Lisp}. \newblock In {\em Proceedings of the 2007 International Lisp Conference}, pages 13:1--13:14. ACM, 2009. \newblock Also freely available at \url{http://doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf}. \bibitem[sli]{slime} {SLIME: The Superior Lisp Interaction Mode for Emacs}. \newblock \url{http://common-lisp.net/project/slime/}. \newblock Last accessed Feb 4, 2012. \end{thebibliography} abcl-src-1.9.0/doc/manual/abcl.bib0100644 0000000 0000000 00000012233 14242627550 015347 0ustar000000000 0000000 % no longer resolving 2012-12-04 % howpublished = {\url{http://java.sun.com/developer/onlineTraining/protocolhandlers/}}, @Misc{maso2000, author = {Maso, Brian}, title = {A New Era for {Java} Protocol Handlers}, howpublished = {\url{http://docslide.us/documents/java-protocol-handler.html}}, month = aug, year = 2000, note = {Last accessed Oct 2, 2016} } @Misc{quicklisp, author = {Beane, Zach}, title = {Quicklisp}, howpublished = {\url{http://www.quicklisp.org/}}, note = {Last accessed Jan 25, 2012}} @Misc{asdf, author = {Rideau, Fran\c{c}ois-Ren\'{e} and Barlow, Daniel and Rhodes, Christopher and King, Garry}, title = {ASDF}, howpublished = {\url{http://common-lisp.net/project/asdf/}}, note = {Last accessed Feb 5, 2012}} @Misc{rfc3986, author = {Berners-Lee, Tim and Fielding, Roy and Masinter, Larry}, title = {RFC 3986: URI Generic Syntax}, year = {2005}, howpublished = {\url{http://www.ietf.org/rfc/rfc3986.txt}}, note = {Last accessed Feb 5, 2012}} @inproceedings{Rhodes2007, author = {Rhodes, Christophe}, title = {User-extensible sequences in {Common Lisp}}, booktitle = {Proceedings of the 2007 International Lisp Conference}, year = {2009}, isbn = {978-1-59593-618-9}, location = {Cambridge, United Kingdom}, pages = {13:1--13:14}, articleno = {13}, numpages = {14}, url = {http://doi.acm.org/10.1145/1622123.1622138}, doi = {http://doi.acm.org/10.1145/1622123.1622138}, acmid = {1622138}, publisher = {ACM}, note = {Also freely available at \url{http://doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf}} } @Comment series = {ILC '07}, @Comment address = {New York, NY, USA}, @Book{AMOP, author = {Kiczales, Gregor and des Rivières, Jim and Bobrow, Daniel G.}, title = {The Art of the Metaobject Protocol}, publisher = {MIT Press}, year = {1991}, } @Misc{CLHS, key = {CLHS}, author = {Pitman, Kent and others}, title = {{Common Lisp HyperSpec}}, howpublished = {\url{http://www.lispworks.com/documentation/HyperSpec/Front/index.htm}}, year = 1996, note = {Last accessed Feb 4, 2012}, } @Misc{AMOPspec, key = {AMOP}, author = {Kiczales, Gregor and des Rivières, Jim and Bobrow, Daniel G.}, title = {{The Common Lisp Object System} MetaObject Protocol}, howpublished = {\url{http://www.alu.org/mop/index.html}}, year = 1997, note = {Last accessed Feb 4, 2012}, } @Misc{slime, key = {slime}, title = {{SLIME: The Superior Lisp Interaction Mode for Emacs}}, howpublished = {\url{http://common-lisp.net/project/slime/}}, note = {Last accessed Feb 4, 2012}, } @TechReport{jsr-223, author = {Grogan,Mike}, title = {Scripting for the {Java} Platform}, institution = {Sun Microsystems, Inc.}, year = 2006, type = {Final Draft Specification}, number = {JSR-223}, note = {\url{http://jcp.org/aboutJava/communityprocess/final/jsr223/index.html}}, } @Misc{uri-pathname, key = {evenson2011}, author = {Evenson, Mark}, title = {Unpublished draft of {An Implementation and Analysis of Adding IRI to Common Lisp's Pathname}}, howpublished = {\url{https://github.com/easye/abcl/blob/master/doc/design/pathnames/url-pathnames.mark}}, year = {2011}, note = {Last accessed Oct 2, 2016}, } @Misc{closer-mop, key = {closer-mop}, author = { Costanza.Pascal}, title = { Closer to MOP is a compatibility layer that rectifies many of the absent or incorrect CLOS MOP features across a broad range of Common Lisp implementations.}, howpublished = {\url{https://github.com/pcostanza/closer-mop}}, year = {2011}, note = {Last accessed Oct 2, 2016}, } @Misc{lea-1998, key = {lea-1998}, author ={Doug Lea}, title = "Overview of package util.concurrent Release 1.3.4.", howpublished = {\url{http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html}}, year = {1998}, note = {Last accessed Oct 2, 2016}, } @Misc{adoptium, key = {adoptium-2022}, author ={The Adoptium Working Group}, title = "Freely redistributable Adoptium OpenJDK releases", howpublished = {\url{https://adoptium.net/}}, year = {2022}, note = {Last accessed April 29, 2022}, } % title = "πάνδημος", @Misc{pandemos, key = {pandemos-2020}, author ={Harry Halprin}, title = "$\pi$$\alpha$$\nu$$\delta$$\eta$$\mu$o$\zeta$", howpublished = {\url{https://agorist.xyz/files/Agorism_XXI_I_2022.pdf}}, year = {2020}, note = {Last accessed April 29, 2022}, } @Misc{nio, key = {java-8-nio}, author ={Sun Microsystems}, title = "NIO", howpublished = {\url{https://docs.oracle.com/javase/8/docs/api/java/nio/package-summary.html}}, year = {2005}, note = {Last accessed April 30, 2022}, } @Misc{future-history, key = {future-history}, author ={Mark Evenson}, title = "Notes on the Future History of Arming Bears", howpublished = {\url{http://slack.net/~evenson/abcl/history/abcl-future-history.html}}, year = {2021}, note = {Last accessed April 30, 2022}, } abcl-src-1.9.0/doc/manual/abcl.blg0100644 0000000 0000000 00000002153 14242630061 015346 0ustar000000000 0000000 This is BibTeX, Version 0.99d (TeX Live 2022/MacPorts 2022.62882_0) Capacity: max_strings=200000, hash_size=200000, hash_prime=170003 The top-level auxiliary file: abcl.aux A level-1 auxiliary file: java.aux A level-1 auxiliary file: threads.aux A level-1 auxiliary file: extensions.aux A level-1 auxiliary file: mop.aux A level-1 auxiliary file: system.aux A level-1 auxiliary file: jss.aux The style file: alpha.bst Database file #1: abcl.bib You've used 14 entries, 2543 wiz_defined-function locations, 645 strings with 6727 characters, and the built_in function-call counts, 4386 in all, are: = -- 448 > -- 156 < -- 12 + -- 48 - -- 47 * -- 209 := -- 705 add.period$ -- 56 call.type$ -- 14 change.case$ -- 75 chr.to.int$ -- 14 cite$ -- 14 duplicate$ -- 170 empty$ -- 369 format.name$ -- 69 if$ -- 934 int.to.chr$ -- 1 int.to.str$ -- 0 missing$ -- 1 newline$ -- 87 num.names$ -- 39 pop$ -- 122 preamble$ -- 1 purify$ -- 89 quote$ -- 0 skip$ -- 156 stack$ -- 0 substring$ -- 142 swap$ -- 26 text.length$ -- 12 text.prefix$ -- 11 top$ -- 0 type$ -- 112 warning$ -- 0 while$ -- 32 width$ -- 18 write$ -- 197 abcl-src-1.9.0/doc/manual/abcl.idx0100644 0000000 0000000 00000071574 14242630063 015405 0ustar000000000 0000000 \indexentry{REPL|hyperpage}{11} \indexentry{Command Line Options|hyperpage}{11} \indexentry{*JAVA-OBJECT-TO-STRING-LENGTH*|hyperpage}{21} \indexentry{+FALSE+|hyperpage}{21} \indexentry{+NULL+|hyperpage}{21} \indexentry{+TRUE+|hyperpage}{21} \indexentry{ADD-TO-CLASSPATH|hyperpage}{21} \indexentry{CHAIN|hyperpage}{21} \indexentry{DEFINE-JAVA-CLASS|hyperpage}{21} \indexentry{DESCRIBE-JAVA-OBJECT|hyperpage}{21} \indexentry{DUMP-CLASSPATH|hyperpage}{21} \indexentry{ENSURE-JAVA-CLASS|hyperpage}{21} \indexentry{ENSURE-JAVA-OBJECT|hyperpage}{21} \indexentry{GET-CURRENT-CLASSLOADER|hyperpage}{22} \indexentry{GET-DEFAULT-CLASSLOADER|hyperpage}{22} \indexentry{JARRAY-COMPONENT-TYPE|hyperpage}{22} \indexentry{JARRAY-FROM-LIST|hyperpage}{22} \indexentry{JARRAY-LENGTH|hyperpage}{22} \indexentry{JARRAY-REF|hyperpage}{22} \indexentry{JARRAY-REF-RAW|hyperpage}{22} \indexentry{JARRAY-SET|hyperpage}{22} \indexentry{JAVA-CLASS|hyperpage}{22} \indexentry{JAVA-EXCEPTION|hyperpage}{22} \indexentry{JAVA-EXCEPTION-CAUSE|hyperpage}{22} \indexentry{JAVA-OBJECT|hyperpage}{22} \indexentry{JAVA-OBJECT-P|hyperpage}{22} \indexentry{JCALL|hyperpage}{22} \indexentry{JCALL-RAW|hyperpage}{23} \indexentry{JCLASS|hyperpage}{23} \indexentry{JCLASS-ARRAY-P|hyperpage}{23} \indexentry{JCLASS-CONSTRUCTORS|hyperpage}{23} \indexentry{JCLASS-FIELD|hyperpage}{23} \indexentry{JCLASS-FIELDS|hyperpage}{23} \indexentry{JCLASS-INTERFACE-P|hyperpage}{23} \indexentry{JCLASS-INTERFACES|hyperpage}{23} \indexentry{JCLASS-METHODS|hyperpage}{23} \indexentry{JCLASS-NAME|hyperpage}{23} \indexentry{JCLASS-OF|hyperpage}{23} \indexentry{JCLASS-SUPERCLASS|hyperpage}{23} \indexentry{JCLASS-SUPERCLASS-P|hyperpage}{23} \indexentry{JCOERCE|hyperpage}{23} \indexentry{JCONSTRUCTOR|hyperpage}{24} \indexentry{JCONSTRUCTOR-PARAMS|hyperpage}{24} \indexentry{JEQUAL|hyperpage}{24} \indexentry{JFIELD|hyperpage}{24} \indexentry{JFIELD-NAME|hyperpage}{24} \indexentry{JFIELD-RAW|hyperpage}{24} \indexentry{JFIELD-TYPE|hyperpage}{24} \indexentry{JINPUT-STREAM|hyperpage}{25} \indexentry{JINSTANCE-OF-P|hyperpage}{25} \indexentry{JINTERFACE-IMPLEMENTATION|hyperpage}{25} \indexentry{JMAKE-INVOCATION-HANDLER|hyperpage}{25} \indexentry{JMAKE-PROXY|hyperpage}{25} \indexentry{JMEMBER-PROTECTED-P|hyperpage}{25} \indexentry{JMEMBER-PUBLIC-P|hyperpage}{25} \indexentry{JMEMBER-STATIC-P|hyperpage}{25} \indexentry{JMETHOD|hyperpage}{25} \indexentry{JMETHOD-LET|hyperpage}{25} \indexentry{JMETHOD-NAME|hyperpage}{25} \indexentry{JMETHOD-PARAMS|hyperpage}{26} \indexentry{JMETHOD-RETURN-TYPE|hyperpage}{26} \indexentry{JNEW|hyperpage}{26} \indexentry{JNEW-ARRAY|hyperpage}{26} \indexentry{JNEW-ARRAY-FROM-ARRAY|hyperpage}{26} \indexentry{JNEW-ARRAY-FROM-LIST|hyperpage}{26} \indexentry{JNEW-RUNTIME-CLASS|hyperpage}{26} \indexentry{JNULL-REF-P|hyperpage}{27} \indexentry{JOBJECT-CLASS|hyperpage}{27} \indexentry{JOBJECT-LISP-VALUE|hyperpage}{27} \indexentry{JPROPERTY-VALUE|hyperpage}{27} \indexentry{JREGISTER-HANDLER|hyperpage}{27} \indexentry{JRESOLVE-METHOD|hyperpage}{27} \indexentry{JRUN-EXCEPTION-PROTECTED|hyperpage}{27} \indexentry{JSTATIC|hyperpage}{27} \indexentry{JSTATIC-RAW|hyperpage}{27} \indexentry{MAKE-CLASSLOADER|hyperpage}{27} \indexentry{MAKE-IMMEDIATE-OBJECT|hyperpage}{27} \indexentry{REGISTER-JAVA-EXCEPTION|hyperpage}{27} \indexentry{UNREGISTER-JAVA-EXCEPTION|hyperpage}{28} \indexentry{*THREADING-MODEL*|hyperpage}{30} \indexentry{CURRENT-THREAD|hyperpage}{30} \indexentry{DESTROY-THREAD|hyperpage}{30} \indexentry{GET-MUTEX|hyperpage}{30} \indexentry{INTERRUPT-THREAD|hyperpage}{30} \indexentry{MAILBOX-EMPTY-P|hyperpage}{30} \indexentry{MAILBOX-PEEK|hyperpage}{30} \indexentry{MAILBOX-READ|hyperpage}{30} \indexentry{MAILBOX-SEND|hyperpage}{30} \indexentry{MAKE-MAILBOX|hyperpage}{30} \indexentry{MAKE-MUTEX|hyperpage}{30} \indexentry{MAKE-THREAD|hyperpage}{30} \indexentry{MAKE-THREAD-LOCK|hyperpage}{30} \indexentry{MAPCAR-THREADS|hyperpage}{30} \indexentry{OBJECT-NOTIFY|hyperpage}{31} \indexentry{OBJECT-NOTIFY-ALL|hyperpage}{31} \indexentry{OBJECT-WAIT|hyperpage}{31} \indexentry{RELEASE-MUTEX|hyperpage}{31} \indexentry{SYNCHRONIZED-ON|hyperpage}{31} \indexentry{THREAD|hyperpage}{31} \indexentry{THREAD-ALIVE-P|hyperpage}{31} \indexentry{THREAD-JOIN|hyperpage}{31} \indexentry{THREAD-NAME|hyperpage}{31} \indexentry{THREADP|hyperpage}{31} \indexentry{WITH-MUTEX|hyperpage}{31} \indexentry{WITH-THREAD-LOCK|hyperpage}{31} \indexentry{YIELD|hyperpage}{31} \indexentry{CADDR|hyperpage}{33} \indexentry{CADR|hyperpage}{33} \indexentry{CAR|hyperpage}{33} \indexentry{CDR|hyperpage}{33} \indexentry{*AUTOLOAD-VERBOSE*|hyperpage}{33} \indexentry{*BATCH-MODE*|hyperpage}{33} \indexentry{*COMMAND-LINE-ARGUMENT-LIST*|hyperpage}{33} \indexentry{*DEBUG-CONDITION*|hyperpage}{33} \indexentry{*DEBUG-LEVEL*|hyperpage}{33} \indexentry{*DISASSEMBLER*|hyperpage}{33} \indexentry{*ED-FUNCTIONS*|hyperpage}{33} \indexentry{*ENABLE-INLINE-EXPANSION*|hyperpage}{33} \indexentry{*INSPECTOR-HOOK*|hyperpage}{33} \indexentry{*LISP-HOME*|hyperpage}{33} \indexentry{*LOAD-TRUENAME-FASL*|hyperpage}{33} \indexentry{*PRINT-STRUCTURE*|hyperpage}{33} \indexentry{*REQUIRE-STACK-FRAME*|hyperpage}{34} \indexentry{*SAVED-BACKTRACE*|hyperpage}{34} \indexentry{*SUPPRESS-COMPILER-WARNINGS*|hyperpage}{34} \indexentry{*WARN-ON-REDEFINITION*|hyperpage}{34} \indexentry{ADD-PACKAGE-LOCAL-NICKNAME|hyperpage}{34} \indexentry{ADJOIN-EQL|hyperpage}{34} \indexentry{ARGLIST|hyperpage}{34} \indexentry{AS-JAR-PATHNAME-ARCHIVE|hyperpage}{34} \indexentry{ASSQ|hyperpage}{34} \indexentry{ASSQL|hyperpage}{34} \indexentry{AUTOLOAD|hyperpage}{34} \indexentry{AUTOLOAD-MACRO|hyperpage}{34} \indexentry{AUTOLOAD-REF-P|hyperpage}{34} \indexentry{AUTOLOAD-SETF-EXPANDER|hyperpage}{34} \indexentry{AUTOLOAD-SETF-FUNCTION|hyperpage}{34} \indexentry{AUTOLOADP|hyperpage}{35} \indexentry{CANCEL-FINALIZATION|hyperpage}{35} \indexentry{CHAR-TO-UTF8|hyperpage}{35} \indexentry{CHARPOS|hyperpage}{35} \indexentry{CLASSP|hyperpage}{35} \indexentry{COLLECT|hyperpage}{35} \indexentry{COMPILE-SYSTEM|hyperpage}{35} \indexentry{DOUBLE-FLOAT-NEGATIVE-INFINITY|hyperpage}{35} \indexentry{DOUBLE-FLOAT-POSITIVE-INFINITY|hyperpage}{35} \indexentry{DUMP-JAVA-STACK|hyperpage}{35} \indexentry{EXIT|hyperpage}{35} \indexentry{FEATUREP|hyperpage}{36} \indexentry{FILE-DIRECTORY-P|hyperpage}{36} \indexentry{FINALIZE|hyperpage}{36} \indexentry{FIXNUMP|hyperpage}{36} \indexentry{GC|hyperpage}{36} \indexentry{GET-FLOATING-POINT-MODES|hyperpage}{36} \indexentry{GET-PID|hyperpage}{36} \indexentry{GET-SOCKET-STREAM|hyperpage}{36} \indexentry{GET-TIME-ZONE|hyperpage}{36} \indexentry{GETENV|hyperpage}{36} \indexentry{GETENV-ALL|hyperpage}{36} \indexentry{INIT-GUI|hyperpage}{36} \indexentry{INTERRUPT-LISP|hyperpage}{36} \indexentry{JAR-PATHNAME|hyperpage}{36} \indexentry{MACROEXPAND-ALL|hyperpage}{37} \indexentry{MAILBOX|hyperpage}{37} \indexentry{MAKE-DIALOG-PROMPT-STREAM|hyperpage}{37} \indexentry{MAKE-SERVER-SOCKET|hyperpage}{37} \indexentry{MAKE-SLIME-INPUT-STREAM|hyperpage}{37} \indexentry{MAKE-SLIME-OUTPUT-STREAM|hyperpage}{37} \indexentry{MAKE-SOCKET|hyperpage}{37} \indexentry{MAKE-TEMP-DIRECTORY|hyperpage}{37} \indexentry{MAKE-TEMP-FILE|hyperpage}{37} \indexentry{MAKE-WEAK-REFERENCE|hyperpage}{37} \indexentry{MEMQ|hyperpage}{37} \indexentry{MEMQL|hyperpage}{37} \indexentry{MOST-NEGATIVE-JAVA-LONG|hyperpage}{37} \indexentry{MOST-POSITIVE-JAVA-LONG|hyperpage}{37} \indexentry{MUTEX|hyperpage}{37} \indexentry{NEQ|hyperpage}{37} \indexentry{NIL-VECTOR|hyperpage}{38} \indexentry{OS-UNIX-P|hyperpage}{38} \indexentry{OS-WINDOWS-P|hyperpage}{38} \indexentry{PACKAGE-LOCAL-NICKNAMES|hyperpage}{38} \indexentry{PACKAGE-LOCALLY-NICKNAMED-BY-LIST|hyperpage}{38} \indexentry{PATHNAME-JAR-P|hyperpage}{38} \indexentry{PATHNAME-URL-P|hyperpage}{38} \indexentry{PRECOMPILE|hyperpage}{38} \indexentry{PROBE-DIRECTORY|hyperpage}{38} \indexentry{QUIT|hyperpage}{38} \indexentry{READ-CLASS|hyperpage}{38} \indexentry{READ-TIMEOUT|hyperpage}{38} \indexentry{REMOVE-PACKAGE-LOCAL-NICKNAME|hyperpage}{38} \indexentry{RESOLVE|hyperpage}{38} \indexentry{RUN-SHELL-COMMAND|hyperpage}{38} \indexentry{SERVER-SOCKET-CLOSE|hyperpage}{39} \indexentry{SET-FLOATING-POINT-MODES|hyperpage}{39} \indexentry{SHOW-RESTARTS|hyperpage}{39} \indexentry{SIMPLE-STRING-FILL|hyperpage}{39} \indexentry{SIMPLE-STRING-SEARCH|hyperpage}{39} \indexentry{SINGLE-FLOAT-NEGATIVE-INFINITY|hyperpage}{39} \indexentry{SINGLE-FLOAT-POSITIVE-INFINITY|hyperpage}{39} \indexentry{SLIME-INPUT-STREAM|hyperpage}{39} \indexentry{SLIME-OUTPUT-STREAM|hyperpage}{39} \indexentry{SOCKET-ACCEPT|hyperpage}{39} \indexentry{SOCKET-CLOSE|hyperpage}{39} \indexentry{SOCKET-LOCAL-ADDRESS|hyperpage}{39} \indexentry{SOCKET-LOCAL-PORT|hyperpage}{39} \indexentry{SOCKET-PEER-ADDRESS|hyperpage}{39} \indexentry{SOCKET-PEER-PORT|hyperpage}{39} \indexentry{SOURCE|hyperpage}{39} \indexentry{SOURCE-FILE-POSITION|hyperpage}{40} \indexentry{SOURCE-PATHNAME|hyperpage}{40} \indexentry{SPECIAL-VARIABLE-P|hyperpage}{40} \indexentry{STREAM-UNIX-FD|hyperpage}{40} \indexentry{STRING-FIND|hyperpage}{40} \indexentry{STRING-INPUT-STREAM-CURRENT|hyperpage}{40} \indexentry{STRING-POSITION|hyperpage}{40} \indexentry{STYLE-WARN|hyperpage}{40} \indexentry{TRULY-THE|hyperpage}{40} \indexentry{UPTIME|hyperpage}{40} \indexentry{URI-DECODE|hyperpage}{40} \indexentry{URI-ENCODE|hyperpage}{40} \indexentry{URL-PATHNAME|hyperpage}{40} \indexentry{URL-PATHNAME-AUTHORITY|hyperpage}{40} \indexentry{URL-PATHNAME-FRAGMENT|hyperpage}{40} \indexentry{URL-PATHNAME-QUERY|hyperpage}{40} \indexentry{URL-PATHNAME-SCHEME|hyperpage}{41} \indexentry{WEAK-REFERENCE|hyperpage}{41} \indexentry{WEAK-REFERENCE-VALUE|hyperpage}{41} \indexentry{WRITE-CLASS|hyperpage}{41} \indexentry{WRITE-TIMEOUT|hyperpage}{41} \indexentry{PATHNAME|hyperpage}{43} \indexentry{URL-PATHNAME|hyperpage}{44} \indexentry{URL-PATHNAME-SCHEME|hyperpage}{44} \indexentry{URL-PATHNAME-FRAGMENT|hyperpage}{44} \indexentry{URL-PATHNAME-AUTHORITY|hyperpage}{44} \indexentry{PATHNAME-URL-P|hyperpage}{44} \indexentry{URL-PATHNAME-QUERY|hyperpage}{44} \indexentry{JAR-PATHNAME|hyperpage}{45} \indexentry{DEFPACKAGE|hyperpage}{46} \indexentry{PACKAGE-LOCAL-NICKNAMES|hyperpage}{46} \indexentry{PACKAGE-LOCALLY-NICKNAMED-BY-LIST|hyperpage}{46} \indexentry{ADD-PACKAGE-LOCAL-NICKNAME|hyperpage}{46} \indexentry{REMOVE-PACKAGE-LOCAL-NICKNAME|hyperpage}{46} \indexentry{MAKE-ARRAY|hyperpage}{49} \indexentry{ABCL-ASDF|hyperpage}{51} \indexentry{ASDF-JAR|hyperpage}{52} \indexentry{JSS|hyperpage}{52} \indexentry{ABCL-INTROSPECT|hyperpage}{53} \indexentry{CL:DISASSEMBLE|hyperpage}{53} \indexentry{ABCL-BUILD|hyperpage}{55} \indexentry{NAMED-READTABLES|hyperpage}{55} \indexentry{History|hyperpage}{57} \indexentry{DEFGENERIC|hyperpage}{60} \indexentry{ACCESSOR-METHOD-SLOT-DEFINITION|hyperpage}{60} \indexentry{ADD-DEPENDENT|hyperpage}{60} \indexentry{ADD-DIRECT-METHOD|hyperpage}{60} \indexentry{ADD-DIRECT-SUBCLASS|hyperpage}{60} \indexentry{CANONICALIZE-DIRECT-SUPERCLASSES|hyperpage}{60} \indexentry{CLASS-DEFAULT-INITARGS|hyperpage}{60} \indexentry{CLASS-DIRECT-DEFAULT-INITARGS|hyperpage}{60} \indexentry{CLASS-DIRECT-METHODS|hyperpage}{60} \indexentry{CLASS-DIRECT-SLOTS|hyperpage}{60} \indexentry{CLASS-DIRECT-SUBCLASSES|hyperpage}{60} \indexentry{CLASS-DIRECT-SUPERCLASSES|hyperpage}{60} \indexentry{CLASS-DOCUMENTATION|hyperpage}{60} \indexentry{CLASS-FINALIZED-P|hyperpage}{60} \indexentry{CLASS-PRECEDENCE-LIST|hyperpage}{60} \indexentry{CLASS-PROTOTYPE|hyperpage}{60} \indexentry{CLASS-SLOTS|hyperpage}{61} \indexentry{COMPUTE-APPLICABLE-METHODS|hyperpage}{61} \indexentry{COMPUTE-APPLICABLE-METHODS-USING-CLASSES|hyperpage}{61} \indexentry{COMPUTE-CLASS-PRECEDENCE-LIST|hyperpage}{61} \indexentry{COMPUTE-DEFAULT-INITARGS|hyperpage}{61} \indexentry{COMPUTE-DISCRIMINATING-FUNCTION|hyperpage}{61} \indexentry{COMPUTE-EFFECTIVE-METHOD|hyperpage}{61} \indexentry{COMPUTE-EFFECTIVE-SLOT-DEFINITION|hyperpage}{61} \indexentry{COMPUTE-SLOTS|hyperpage}{61} \indexentry{DIRECT-SLOT-DEFINITION|hyperpage}{61} \indexentry{DIRECT-SLOT-DEFINITION-CLASS|hyperpage}{61} \indexentry{EFFECTIVE-SLOT-DEFINITION|hyperpage}{61} \indexentry{EFFECTIVE-SLOT-DEFINITION-CLASS|hyperpage}{61} \indexentry{ENSURE-CLASS|hyperpage}{61} \indexentry{ENSURE-CLASS-USING-CLASS|hyperpage}{61} \indexentry{ENSURE-GENERIC-FUNCTION-USING-CLASS|hyperpage}{61} \indexentry{EQL-SPECIALIZER|hyperpage}{62} \indexentry{EQL-SPECIALIZER-OBJECT|hyperpage}{62} \indexentry{EXTRACT-LAMBDA-LIST|hyperpage}{62} \indexentry{EXTRACT-SPECIALIZER-NAMES|hyperpage}{62} \indexentry{FINALIZE-INHERITANCE|hyperpage}{62} \indexentry{FIND-METHOD-COMBINATION|hyperpage}{62} \indexentry{FORWARD-REFERENCED-CLASS|hyperpage}{62} \indexentry{FUNCALLABLE-STANDARD-CLASS|hyperpage}{62} \indexentry{FUNCALLABLE-STANDARD-INSTANCE-ACCESS|hyperpage}{62} \indexentry{FUNCALLABLE-STANDARD-OBJECT|hyperpage}{62} \indexentry{GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER|hyperpage}{62} \indexentry{GENERIC-FUNCTION-DECLARATIONS|hyperpage}{62} \indexentry{GENERIC-FUNCTION-LAMBDA-LIST|hyperpage}{62} \indexentry{GENERIC-FUNCTION-METHOD-CLASS|hyperpage}{62} \indexentry{GENERIC-FUNCTION-METHOD-COMBINATION|hyperpage}{62} \indexentry{GENERIC-FUNCTION-METHODS|hyperpage}{62} \indexentry{GENERIC-FUNCTION-NAME|hyperpage}{63} \indexentry{INTERN-EQL-SPECIALIZER|hyperpage}{63} \indexentry{MAKE-METHOD-LAMBDA|hyperpage}{63} \indexentry{MAP-DEPENDENTS|hyperpage}{63} \indexentry{METAOBJECT|hyperpage}{63} \indexentry{METHOD-FUNCTION|hyperpage}{63} \indexentry{METHOD-GENERIC-FUNCTION|hyperpage}{63} \indexentry{METHOD-LAMBDA-LIST|hyperpage}{63} \indexentry{METHOD-QUALIFIERS|hyperpage}{63} \indexentry{METHOD-SPECIALIZERS|hyperpage}{63} \indexentry{READER-METHOD-CLASS|hyperpage}{63} \indexentry{REMOVE-DEPENDENT|hyperpage}{63} \indexentry{REMOVE-DIRECT-METHOD|hyperpage}{63} \indexentry{REMOVE-DIRECT-SUBCLASS|hyperpage}{63} \indexentry{SET-FUNCALLABLE-INSTANCE-FUNCTION|hyperpage}{63} \indexentry{SLOT-BOUNDP-USING-CLASS|hyperpage}{63} \indexentry{SLOT-DEFINITION|hyperpage}{64} \indexentry{SLOT-DEFINITION-ALLOCATION|hyperpage}{64} \indexentry{SLOT-DEFINITION-DOCUMENTATION|hyperpage}{64} \indexentry{SLOT-DEFINITION-INITARGS|hyperpage}{64} \indexentry{SLOT-DEFINITION-INITFORM|hyperpage}{64} \indexentry{SLOT-DEFINITION-INITFUNCTION|hyperpage}{64} \indexentry{SLOT-DEFINITION-LOCATION|hyperpage}{64} \indexentry{SLOT-DEFINITION-NAME|hyperpage}{64} \indexentry{SLOT-DEFINITION-READERS|hyperpage}{64} \indexentry{SLOT-DEFINITION-TYPE|hyperpage}{64} \indexentry{SLOT-DEFINITION-WRITERS|hyperpage}{64} \indexentry{SLOT-MAKUNBOUND-USING-CLASS|hyperpage}{64} \indexentry{SLOT-VALUE-USING-CLASS|hyperpage}{64} \indexentry{SPECIALIZER|hyperpage}{64} \indexentry{SPECIALIZER-DIRECT-GENERIC-FUNCTIONS|hyperpage}{64} \indexentry{SPECIALIZER-DIRECT-METHODS|hyperpage}{64} \indexentry{STANDARD-ACCESSOR-METHOD|hyperpage}{65} \indexentry{STANDARD-DIRECT-SLOT-DEFINITION|hyperpage}{65} \indexentry{STANDARD-EFFECTIVE-SLOT-DEFINITION|hyperpage}{65} \indexentry{STANDARD-INSTANCE-ACCESS|hyperpage}{65} \indexentry{STANDARD-METHOD|hyperpage}{65} \indexentry{STANDARD-READER-METHOD|hyperpage}{65} \indexentry{STANDARD-SLOT-DEFINITION|hyperpage}{65} \indexentry{STANDARD-WRITER-METHOD|hyperpage}{65} \indexentry{UPDATE-DEPENDENT|hyperpage}{65} \indexentry{VALIDATE-SUPERCLASS|hyperpage}{65} \indexentry{WRITER-METHOD-CLASS|hyperpage}{65} \indexentry{ALLOCATE-FUNCALLABLE-INSTANCE|hyperpage}{68} \indexentry{CLASS-DEFAULT-INITARGS|hyperpage}{68} \indexentry{CLASS-DIRECT-DEFAULT-INITARGS|hyperpage}{68} \indexentry{CLASS-DIRECT-METHODS|hyperpage}{68} \indexentry{CLASS-DIRECT-SLOTS|hyperpage}{68} \indexentry{CLASS-DIRECT-SUBCLASSES|hyperpage}{68} \indexentry{CLASS-DIRECT-SUPERCLASSES|hyperpage}{68} \indexentry{CLASS-FINALIZED-P|hyperpage}{68} \indexentry{CLASS-LAYOUT|hyperpage}{68} \indexentry{CLASS-NAME|hyperpage}{68} \indexentry{CLASS-PRECEDENCE-LIST|hyperpage}{68} \indexentry{CLASS-SLOTS|hyperpage}{68} \indexentry{DEFUN|hyperpage}{68} \indexentry{DOCUMENTATION|hyperpage}{68} \indexentry{FLOAT-BITS|hyperpage}{68} \indexentry{IN-PACKAGE|hyperpage}{68} \indexentry{MAKE-CONDITION|hyperpage}{69} \indexentry{MAKE-EMF-CACHE|hyperpage}{69} \indexentry{MAKE-INSTANCES-OBSOLETE|hyperpage}{69} \indexentry{MAKE-INTEGER-TYPE|hyperpage}{69} \indexentry{MAKE-LIST|hyperpage}{69} \indexentry{MAKE-LOGICAL-PATHNAME|hyperpage}{69} \indexentry{MAKE-SLOT-DEFINITION|hyperpage}{69} \indexentry{MAKE-STRUCTURE|hyperpage}{69} \indexentry{MEMBER|hyperpage}{69} \indexentry{NSTRING-CAPITALIZE|hyperpage}{69} \indexentry{NSTRING-DOWNCASE|hyperpage}{69} \indexentry{NSTRING-UPCASE|hyperpage}{69} \indexentry{OUTPUT-OBJECT|hyperpage}{69} \indexentry{PUTF|hyperpage}{69} \indexentry{REINIT-EMF-CACHE|hyperpage}{69} \indexentry{SET-CLASS-DEFAULT-INITARGS|hyperpage}{69} \indexentry{SET-CLASS-DIRECT-DEFAULT-INITARGS|hyperpage}{70} \indexentry{SET-CLASS-DIRECT-METHODS|hyperpage}{70} \indexentry{SET-CLASS-DIRECT-SLOTS|hyperpage}{70} \indexentry{SET-CLASS-DIRECT-SUBCLASSES|hyperpage}{70} \indexentry{SET-CLASS-DIRECT-SUPERCLASSES|hyperpage}{70} \indexentry{SET-CLASS-DOCUMENTATION|hyperpage}{70} \indexentry{SET-CLASS-FINALIZED-P|hyperpage}{70} \indexentry{SET-CLASS-LAYOUT|hyperpage}{70} \indexentry{SET-CLASS-NAME|hyperpage}{70} \indexentry{SET-CLASS-PRECEDENCE-LIST|hyperpage}{70} \indexentry{SET-CLASS-SLOTS|hyperpage}{70} \indexentry{SET-DOCUMENTATION|hyperpage}{70} \indexentry{SET-FILL-POINTER|hyperpage}{70} \indexentry{SET-FIND-CLASS|hyperpage}{70} \indexentry{SET-STANDARD-INSTANCE-ACCESS|hyperpage}{70} \indexentry{SET-STD-INSTANCE-LAYOUT|hyperpage}{70} \indexentry{STD-ALLOCATE-INSTANCE|hyperpage}{71} \indexentry{STREAM-OUTPUT-OBJECT|hyperpage}{71} \indexentry{STREAM-TERPRI|hyperpage}{71} \indexentry{STREAM-WRITE-CHAR|hyperpage}{71} \indexentry{STRING-CAPITALIZE|hyperpage}{71} \indexentry{STRING-DOWNCASE|hyperpage}{71} \indexentry{STRING-EQUAL|hyperpage}{71} \indexentry{STRING-GREATERP|hyperpage}{71} \indexentry{STRING-LESSP|hyperpage}{71} \indexentry{STRING-NOT-EQUAL|hyperpage}{71} \indexentry{STRING-NOT-GREATERP|hyperpage}{71} \indexentry{STRING-NOT-LESSP|hyperpage}{71} \indexentry{STRING-UPCASE|hyperpage}{71} \indexentry{STRING/=|hyperpage}{71} \indexentry{STRING<|hyperpage}{71} \indexentry{STRING<=|hyperpage}{71} \indexentry{STRING>|hyperpage}{72} \indexentry{STRING>=|hyperpage}{72} \indexentry{TYPE-ERROR|hyperpage}{72} \indexentry{WILD-PATHNAME-P|hyperpage}{72} \indexentry{*ABCL-CONTRIB*|hyperpage}{72} \indexentry{*COMPILE-FILE-CLASS-EXTENSION*|hyperpage}{72} \indexentry{*COMPILE-FILE-ENVIRONMENT*|hyperpage}{72} \indexentry{*COMPILE-FILE-TYPE*|hyperpage}{72} \indexentry{*COMPILE-FILE-ZIP*|hyperpage}{72} \indexentry{*COMPILER-DIAGNOSTIC*|hyperpage}{72} \indexentry{*COMPILER-ERROR-CONTEXT*|hyperpage}{72} \indexentry{*CURRENT-PRINT-LENGTH*|hyperpage}{72} \indexentry{*CURRENT-PRINT-LEVEL*|hyperpage}{72} \indexentry{*DEBUG*|hyperpage}{72} \indexentry{*DEBUGGING-LOCALS-P*|hyperpage}{72} \indexentry{*DISASSEMBLERS*|hyperpage}{73} \indexentry{*ENABLE-AUTOCOMPILE*|hyperpage}{73} \indexentry{*EXPLAIN*|hyperpage}{73} \indexentry{*FASL-LOADER*|hyperpage}{73} \indexentry{*FASL-VERSION*|hyperpage}{73} \indexentry{*INLINE-DECLARATIONS*|hyperpage}{73} \indexentry{*LOGICAL-PATHNAME-TRANSLATIONS*|hyperpage}{73} \indexentry{*NOINFORM*|hyperpage}{73} \indexentry{*SAFETY*|hyperpage}{73} \indexentry{*SOURCE*|hyperpage}{73} \indexentry{*SOURCE-POSITION*|hyperpage}{73} \indexentry{*SPACE*|hyperpage}{73} \indexentry{*SPEED*|hyperpage}{73} \indexentry{*TRACED-NAMES*|hyperpage}{73} \indexentry{+CL-PACKAGE+|hyperpage}{74} \indexentry{+FALSE-TYPE+|hyperpage}{74} \indexentry{+FIXNUM-TYPE+|hyperpage}{74} \indexentry{+INTEGER-TYPE+|hyperpage}{74} \indexentry{+KEYWORD-PACKAGE+|hyperpage}{74} \indexentry{+SLOT-UNBOUND+|hyperpage}{74} \indexentry{+TRUE-TYPE+|hyperpage}{74} \indexentry{ASET|hyperpage}{74} \indexentry{AUTOCOMPILE|hyperpage}{74} \indexentry{AVAILABLE-ENCODINGS|hyperpage}{74} \indexentry{AVER|hyperpage}{74} \indexentry{BACKTRACE|hyperpage}{74} \indexentry{BUILT-IN-FUNCTION-P|hyperpage}{74} \indexentry{CACHE-EMF|hyperpage}{74} \indexentry{CALL-COUNT|hyperpage}{74} \indexentry{CALL-REGISTERS-LIMIT|hyperpage}{74} \indexentry{CANONICALIZE-LOGICAL-HOST|hyperpage}{75} \indexentry{CHECK-DECLARATION-TYPE|hyperpage}{75} \indexentry{CHECK-SEQUENCE-BOUNDS|hyperpage}{75} \indexentry{CHOOSE-DISASSEMBLER|hyperpage}{75} \indexentry{CLASS-BYTES|hyperpage}{75} \indexentry{CLEAR-ZIP-CACHE|hyperpage}{75} \indexentry{COERCE-TO-CONDITION|hyperpage}{75} \indexentry{COERCE-TO-FUNCTION|hyperpage}{75} \indexentry{COMPILE-FILE-IF-NEEDED|hyperpage}{75} \indexentry{COMPILE-SYSTEM|hyperpage}{75} \indexentry{COMPILED-LISP-FUNCTION-P|hyperpage}{75} \indexentry{COMPILER-DEFSTRUCT|hyperpage}{75} \indexentry{COMPILER-ERROR|hyperpage}{75} \indexentry{COMPILER-MACROEXPAND|hyperpage}{75} \indexentry{COMPILER-STYLE-WARN|hyperpage}{76} \indexentry{COMPILER-SUBTYPEP|hyperpage}{76} \indexentry{COMPILER-UNSUPPORTED|hyperpage}{76} \indexentry{COMPILER-WARN|hyperpage}{76} \indexentry{CONCATENATE-FASLS|hyperpage}{76} \indexentry{DEFCONST|hyperpage}{76} \indexentry{DEFINE-SOURCE-TRANSFORM|hyperpage}{76} \indexentry{DEFKNOWN|hyperpage}{76} \indexentry{DELETE-EQ|hyperpage}{76} \indexentry{DELETE-EQL|hyperpage}{76} \indexentry{DESCRIBE-COMPILER-POLICY|hyperpage}{76} \indexentry{DISABLE-ZIP-CACHE|hyperpage}{76} \indexentry{DISASSEMBLE-CLASS-BYTES|hyperpage}{76} \indexentry{DOUBLE-FLOAT-HIGH-BITS|hyperpage}{76} \indexentry{DOUBLE-FLOAT-LOW-BITS|hyperpage}{76} \indexentry{DUMP-FORM|hyperpage}{76} \indexentry{DUMP-UNINTERNED-SYMBOL-INDEX|hyperpage}{77} \indexentry{EMPTY-ENVIRONMENT-P|hyperpage}{77} \indexentry{ENVIRONMENT|hyperpage}{77} \indexentry{ENVIRONMENT-ADD-FUNCTION-DEFINITION|hyperpage}{77} \indexentry{ENVIRONMENT-ADD-MACRO-DEFINITION|hyperpage}{77} \indexentry{ENVIRONMENT-ADD-SYMBOL-BINDING|hyperpage}{77} \indexentry{ENVIRONMENT-ALL-FUNCTIONS|hyperpage}{77} \indexentry{ENVIRONMENT-ALL-VARIABLES|hyperpage}{77} \indexentry{ENVIRONMENT-VARIABLES|hyperpage}{77} \indexentry{EXPAND-INLINE|hyperpage}{77} \indexentry{EXPAND-SOURCE-TRANSFORM|hyperpage}{77} \indexentry{FDEFINITION-BLOCK-NAME|hyperpage}{77} \indexentry{FIND-CONTRIB|hyperpage}{77} \indexentry{FIND-LOCALS|hyperpage}{77} \indexentry{FIND-SYSTEM|hyperpage}{77} \indexentry{FIXNUM-CONSTANT-VALUE|hyperpage}{78} \indexentry{FIXNUM-TYPE-P|hyperpage}{78} \indexentry{FLOAT-INFINITY-P|hyperpage}{78} \indexentry{FLOAT-NAN-P|hyperpage}{78} \indexentry{FLOAT-OVERFLOW-MODE|hyperpage}{78} \indexentry{FLOAT-STRING|hyperpage}{78} \indexentry{FLOAT-UNDERFLOW-MODE|hyperpage}{78} \indexentry{FORWARD-REFERENCED-CLASS|hyperpage}{78} \indexentry{FRAME-TO-LIST|hyperpage}{78} \indexentry{FRAME-TO-STRING|hyperpage}{78} \indexentry{FSET|hyperpage}{78} \indexentry{FTYPE-RESULT-TYPE|hyperpage}{78} \indexentry{FUNCTION-PLIST|hyperpage}{78} \indexentry{FUNCTION-RESULT-TYPE|hyperpage}{78} \indexentry{GET-CACHED-EMF|hyperpage}{78} \indexentry{GET-FUNCTION-INFO-VALUE|hyperpage}{78} \indexentry{GET-INPUT-STREAM|hyperpage}{79} \indexentry{GETHASH1|hyperpage}{79} \indexentry{GROVEL-JAVA-DEFINITIONS-IN-FILE|hyperpage}{79} \indexentry{HASH-TABLE-WEAKNESS|hyperpage}{79} \indexentry{HOT-COUNT|hyperpage}{79} \indexentry{IDENTITY-HASH-CODE|hyperpage}{79} \indexentry{INIT-FASL|hyperpage}{79} \indexentry{INLINE-EXPANSION|hyperpage}{79} \indexentry{INLINE-P|hyperpage}{79} \indexentry{INSPECTED-PARTS|hyperpage}{79} \indexentry{INTEGER-CONSTANT-VALUE|hyperpage}{79} \indexentry{INTEGER-TYPE-HIGH|hyperpage}{79} \indexentry{INTEGER-TYPE-LOW|hyperpage}{79} \indexentry{INTEGER-TYPE-P|hyperpage}{79} \indexentry{INTERACTIVE-EVAL|hyperpage}{79} \indexentry{INTERNAL-COMPILER-ERROR|hyperpage}{79} \indexentry{JAR-STREAM|hyperpage}{80} \indexentry{JAVA-LONG-TYPE-P|hyperpage}{80} \indexentry{JAVA.CLASS.PATH|hyperpage}{80} \indexentry{LAMBDA-NAME|hyperpage}{80} \indexentry{LAYOUT-CLASS|hyperpage}{80} \indexentry{LAYOUT-LENGTH|hyperpage}{80} \indexentry{LAYOUT-SLOT-INDEX|hyperpage}{80} \indexentry{LAYOUT-SLOT-LOCATION|hyperpage}{80} \indexentry{LIST-DELETE-EQ|hyperpage}{80} \indexentry{LIST-DELETE-EQL|hyperpage}{80} \indexentry{LIST-DIRECTORY|hyperpage}{80} \indexentry{LOAD-COMPILED-FUNCTION|hyperpage}{80} \indexentry{LOAD-SYSTEM-FILE|hyperpage}{80} \indexentry{LOGICAL-HOST-P|hyperpage}{80} \indexentry{LOGICAL-PATHNAME-P|hyperpage}{80} \indexentry{LOOKUP-KNOWN-SYMBOL|hyperpage}{81} \indexentry{MACRO-FUNCTION-P|hyperpage}{81} \indexentry{MAKE-CLOSURE|hyperpage}{81} \indexentry{MAKE-COMPILER-TYPE|hyperpage}{81} \indexentry{MAKE-DOUBLE-FLOAT|hyperpage}{81} \indexentry{MAKE-ENVIRONMENT|hyperpage}{81} \indexentry{MAKE-FILE-STREAM|hyperpage}{81} \indexentry{MAKE-FILL-POINTER-OUTPUT-STREAM|hyperpage}{81} \indexentry{MAKE-INTEGER-TYPE|hyperpage}{81} \indexentry{MAKE-KEYWORD|hyperpage}{81} \indexentry{MAKE-LAYOUT|hyperpage}{81} \indexentry{MAKE-MACRO|hyperpage}{81} \indexentry{MAKE-MACRO-EXPANDER|hyperpage}{81} \indexentry{MAKE-SINGLE-FLOAT|hyperpage}{81} \indexentry{MAKE-STRUCTURE|hyperpage}{81} \indexentry{MAKE-SYMBOL-MACRO|hyperpage}{81} \indexentry{MATCH-WILD-JAR-PATHNAME|hyperpage}{82} \indexentry{NAMED-LAMBDA|hyperpage}{82} \indexentry{NORMALIZE-TYPE|hyperpage}{82} \indexentry{NOTE-NAME-DEFINED|hyperpage}{82} \indexentry{NOTINLINE-P|hyperpage}{82} \indexentry{OUT-SYNONYM-OF|hyperpage}{82} \indexentry{OUTPUT-OBJECT|hyperpage}{82} \indexentry{PACKAGE-EXTERNAL-SYMBOLS|hyperpage}{82} \indexentry{PACKAGE-INHERITED-SYMBOLS|hyperpage}{82} \indexentry{PACKAGE-INTERNAL-SYMBOLS|hyperpage}{82} \indexentry{PACKAGE-SYMBOLS|hyperpage}{82} \indexentry{PARSE-BODY|hyperpage}{82} \indexentry{PRECOMPILE|hyperpage}{82} \indexentry{PROCESS-ALIVE-P|hyperpage}{82} \indexentry{PROCESS-ERROR|hyperpage}{82} \indexentry{PROCESS-EXIT-CODE|hyperpage}{82} \indexentry{PROCESS-INPUT|hyperpage}{83} \indexentry{PROCESS-KILL|hyperpage}{83} \indexentry{PROCESS-OPTIMIZATION-DECLARATIONS|hyperpage}{83} \indexentry{PROCESS-OUTPUT|hyperpage}{83} \indexentry{PROCESS-P|hyperpage}{83} \indexentry{PROCESS-PID|hyperpage}{83} \indexentry{PROCESS-WAIT|hyperpage}{83} \indexentry{PROCLAIMED-FTYPE|hyperpage}{83} \indexentry{PROCLAIMED-TYPE|hyperpage}{83} \indexentry{PSXHASH|hyperpage}{83} \indexentry{PUT|hyperpage}{83} \indexentry{PUTHASH|hyperpage}{83} \indexentry{READ-8-BITS|hyperpage}{83} \indexentry{READ-VECTOR-UNSIGNED-BYTE-8|hyperpage}{83} \indexentry{RECORD-SOURCE-INFORMATION|hyperpage}{83} \indexentry{RECORD-SOURCE-INFORMATION-FOR-TYPE|hyperpage}{84} \indexentry{REMEMBER|hyperpage}{84} \indexentry{REMOVE-ZIP-CACHE-ENTRY|hyperpage}{84} \indexentry{REQUIRE-TYPE|hyperpage}{84} \indexentry{RUN-PROGRAM|hyperpage}{84} \indexentry{SET-CALL-COUNT|hyperpage}{85} \indexentry{SET-CAR|hyperpage}{85} \indexentry{SET-CDR|hyperpage}{85} \indexentry{SET-CHAR|hyperpage}{85} \indexentry{SET-FUNCTION-INFO-VALUE|hyperpage}{85} \indexentry{SET-HOT-COUNT|hyperpage}{85} \indexentry{SET-SCHAR|hyperpage}{85} \indexentry{SET-STD-SLOT-VALUE|hyperpage}{86} \indexentry{SETF-FUNCTION-NAME-P|hyperpage}{86} \indexentry{SHA256|hyperpage}{86} \indexentry{SHRINK-VECTOR|hyperpage}{86} \indexentry{SIMPLE-FORMAT|hyperpage}{86} \indexentry{SIMPLE-SEARCH|hyperpage}{86} \indexentry{SIMPLE-TYPEP|hyperpage}{86} \indexentry{SINGLE-FLOAT-BITS|hyperpage}{86} \indexentry{SLOT-DEFINITION|hyperpage}{86} \indexentry{SOURCE-TRANSFORM|hyperpage}{86} \indexentry{STANDARD-INSTANCE-ACCESS|hyperpage}{86} \indexentry{STANDARD-OBJECT-P|hyperpage}{86} \indexentry{STD-INSTANCE-CLASS|hyperpage}{86} \indexentry{STD-INSTANCE-LAYOUT|hyperpage}{86} \indexentry{STD-SLOT-BOUNDP|hyperpage}{86} \indexentry{STD-SLOT-VALUE|hyperpage}{86} \indexentry{STRUCTURE-LENGTH|hyperpage}{87} \indexentry{STRUCTURE-OBJECT-P|hyperpage}{87} \indexentry{STRUCTURE-REF|hyperpage}{87} \indexentry{STRUCTURE-SET|hyperpage}{87} \indexentry{SUBCLASSP|hyperpage}{87} \indexentry{SVSET|hyperpage}{87} \indexentry{SWAP-SLOTS|hyperpage}{87} \indexentry{SYMBOL-MACRO-P|hyperpage}{87} \indexentry{SYSTEM-ARTIFACTS-ARE-JARS-P|hyperpage}{87} \indexentry{UNDEFINED-FUNCTION-CALLED|hyperpage}{87} \indexentry{UNTRACED-FUNCTION|hyperpage}{87} \indexentry{UNZIP|hyperpage}{87} \indexentry{URL-STREAM|hyperpage}{87} \indexentry{VECTOR-DELETE-EQ|hyperpage}{87} \indexentry{VECTOR-DELETE-EQL|hyperpage}{87} \indexentry{WHITESPACEP|hyperpage}{87} \indexentry{WRITE-8-BITS|hyperpage}{88} \indexentry{WRITE-VECTOR-UNSIGNED-BYTE-8|hyperpage}{88} \indexentry{ZIP|hyperpage}{88} \indexentry{*CL-USER-COMPATIBILITY*|hyperpage}{90} \indexentry{*DO-AUTO-IMPORTS*|hyperpage}{90} \indexentry{*MUFFLE-WARNINGS*|hyperpage}{90} \indexentry{CLASSFILES-IMPORT|hyperpage}{90} \indexentry{ENSURE-COMPATIBILITY|hyperpage}{90} \indexentry{FIND-JAVA-CLASS|hyperpage}{90} \indexentry{GET-JAVA-FIELD|hyperpage}{90} \indexentry{HASHMAP-TO-HASHTABLE|hyperpage}{90} \indexentry{INVOKE-ADD-IMPORTS|hyperpage}{90} \indexentry{INVOKE-RESTARGS|hyperpage}{90} \indexentry{ITERABLE-TO-LIST|hyperpage}{90} \indexentry{J2LIST|hyperpage}{90} \indexentry{JAPROPOS|hyperpage}{91} \indexentry{JAR-IMPORT|hyperpage}{91} \indexentry{JARRAY-TO-LIST|hyperpage}{91} \indexentry{JAVA-CLASS-METHOD-NAMES|hyperpage}{91} \indexentry{JCLASS-ALL-INTERFACES|hyperpage}{91} \indexentry{JCMN|hyperpage}{91} \indexentry{JLIST-TO-LIST|hyperpage}{91} \indexentry{JMAP|hyperpage}{91} \indexentry{JTYPECASE|hyperpage}{91} \indexentry{JTYPEP|hyperpage}{91} \indexentry{LIST-TO-LIST|hyperpage}{91} \indexentry{NEW|hyperpage}{92} \indexentry{SET-JAVA-FIELD|hyperpage}{92} \indexentry{SET-TO-LIST|hyperpage}{92} \indexentry{TO-HASHSET|hyperpage}{92} \indexentry{VECTOR-TO-LIST|hyperpage}{92} \indexentry{WITH-CONSTANT-SIGNATURE|hyperpage}{92} abcl-src-1.9.0/doc/manual/abcl.ilg0100644 0000000 0000000 00000000511 14242630062 015352 0ustar000000000 0000000 This is makeindex, version 2.16 [TeX Live 2022] (kpathsea + Thai support). Scanning input file abcl.idx....done (667 entries accepted, 0 rejected). Sorting entries........done (6895 comparisons). Generating output file abcl.ind....done (716 lines written, 0 warnings). Output written in abcl.ind. Transcript written in abcl.ilg. abcl-src-1.9.0/doc/manual/abcl.ind0100644 0000000 0000000 00000065060 14242630062 015363 0ustar000000000 0000000 \begin{theindex} \item *ABCL-CONTRIB*, \hyperpage{70} \item *AUTOLOAD-VERBOSE*, \hyperpage{31} \item *BATCH-MODE*, \hyperpage{31} \item *CL-USER-COMPATIBILITY*, \hyperpage{88} \item *COMMAND-LINE-ARGUMENT-LIST*, \hyperpage{31} \item *COMPILE-FILE-CLASS-EXTENSION*, \hyperpage{70} \item *COMPILE-FILE-ENVIRONMENT*, \hyperpage{70} \item *COMPILE-FILE-TYPE*, \hyperpage{70} \item *COMPILE-FILE-ZIP*, \hyperpage{70} \item *COMPILER-DIAGNOSTIC*, \hyperpage{70} \item *COMPILER-ERROR-CONTEXT*, \hyperpage{70} \item *CURRENT-PRINT-LENGTH*, \hyperpage{70} \item *CURRENT-PRINT-LEVEL*, \hyperpage{70} \item *DEBUG*, \hyperpage{70} \item *DEBUG-CONDITION*, \hyperpage{31} \item *DEBUG-LEVEL*, \hyperpage{31} \item *DEBUGGING-LOCALS-P*, \hyperpage{70} \item *DISASSEMBLER*, \hyperpage{31} \item *DISASSEMBLERS*, \hyperpage{71} \item *DO-AUTO-IMPORTS*, \hyperpage{88} \item *ED-FUNCTIONS*, \hyperpage{31} \item *ENABLE-AUTOCOMPILE*, \hyperpage{71} \item *ENABLE-INLINE-EXPANSION*, \hyperpage{31} \item *EXPLAIN*, \hyperpage{71} \item *FASL-LOADER*, \hyperpage{71} \item *FASL-VERSION*, \hyperpage{71} \item *INLINE-DECLARATIONS*, \hyperpage{71} \item *INSPECTOR-HOOK*, \hyperpage{31} \item *JAVA-OBJECT-TO-STRING-LENGTH*, \hyperpage{19} \item *LISP-HOME*, \hyperpage{31} \item *LOAD-TRUENAME-FASL*, \hyperpage{31} \item *LOGICAL-PATHNAME-TRANSLATIONS*, \hyperpage{71} \item *MUFFLE-WARNINGS*, \hyperpage{88} \item *NOINFORM*, \hyperpage{71} \item *PRINT-STRUCTURE*, \hyperpage{31} \item *REQUIRE-STACK-FRAME*, \hyperpage{32} \item *SAFETY*, \hyperpage{71} \item *SAVED-BACKTRACE*, \hyperpage{32} \item *SOURCE*, \hyperpage{71} \item *SOURCE-POSITION*, \hyperpage{71} \item *SPACE*, \hyperpage{71} \item *SPEED*, \hyperpage{71} \item *SUPPRESS-COMPILER-WARNINGS*, \hyperpage{32} \item *THREADING-MODEL*, \hyperpage{28} \item *TRACED-NAMES*, \hyperpage{71} \item *WARN-ON-REDEFINITION*, \hyperpage{32} \item +CL-PACKAGE+, \hyperpage{72} \item +FALSE+, \hyperpage{19} \item +FALSE-TYPE+, \hyperpage{72} \item +FIXNUM-TYPE+, \hyperpage{72} \item +INTEGER-TYPE+, \hyperpage{72} \item +KEYWORD-PACKAGE+, \hyperpage{72} \item +NULL+, \hyperpage{19} \item +SLOT-UNBOUND+, \hyperpage{72} \item +TRUE+, \hyperpage{19} \item +TRUE-TYPE+, \hyperpage{72} \indexspace \item ABCL-ASDF, \hyperpage{49} \item ABCL-BUILD, \hyperpage{53} \item ABCL-INTROSPECT, \hyperpage{51} \item ACCESSOR-METHOD-SLOT-DEFINITION, \hyperpage{58} \item ADD-DEPENDENT, \hyperpage{58} \item ADD-DIRECT-METHOD, \hyperpage{58} \item ADD-DIRECT-SUBCLASS, \hyperpage{58} \item ADD-PACKAGE-LOCAL-NICKNAME, \hyperpage{32}, \hyperpage{44} \item ADD-TO-CLASSPATH, \hyperpage{19} \item ADJOIN-EQL, \hyperpage{32} \item ALLOCATE-FUNCALLABLE-INSTANCE, \hyperpage{66} \item ARGLIST, \hyperpage{32} \item AS-JAR-PATHNAME-ARCHIVE, \hyperpage{32} \item ASDF-JAR, \hyperpage{50} \item ASET, \hyperpage{72} \item ASSQ, \hyperpage{32} \item ASSQL, \hyperpage{32} \item AUTOCOMPILE, \hyperpage{72} \item AUTOLOAD, \hyperpage{32} \item AUTOLOAD-MACRO, \hyperpage{32} \item AUTOLOAD-REF-P, \hyperpage{32} \item AUTOLOAD-SETF-EXPANDER, \hyperpage{32} \item AUTOLOAD-SETF-FUNCTION, \hyperpage{32} \item AUTOLOADP, \hyperpage{33} \item AVAILABLE-ENCODINGS, \hyperpage{72} \item AVER, \hyperpage{72} \indexspace \item BACKTRACE, \hyperpage{72} \item BUILT-IN-FUNCTION-P, \hyperpage{72} \indexspace \item CACHE-EMF, \hyperpage{72} \item CADDR, \hyperpage{31} \item CADR, \hyperpage{31} \item CALL-COUNT, \hyperpage{72} \item CALL-REGISTERS-LIMIT, \hyperpage{72} \item CANCEL-FINALIZATION, \hyperpage{33} \item CANONICALIZE-DIRECT-SUPERCLASSES, \hyperpage{58} \item CANONICALIZE-LOGICAL-HOST, \hyperpage{73} \item CAR, \hyperpage{31} \item CDR, \hyperpage{31} \item CHAIN, \hyperpage{19} \item CHAR-TO-UTF8, \hyperpage{33} \item CHARPOS, \hyperpage{33} \item CHECK-DECLARATION-TYPE, \hyperpage{73} \item CHECK-SEQUENCE-BOUNDS, \hyperpage{73} \item CHOOSE-DISASSEMBLER, \hyperpage{73} \item CL:DISASSEMBLE, \hyperpage{51} \item CLASS-BYTES, \hyperpage{73} \item CLASS-DEFAULT-INITARGS, \hyperpage{58}, \hyperpage{66} \item CLASS-DIRECT-DEFAULT-INITARGS, \hyperpage{58}, \hyperpage{66} \item CLASS-DIRECT-METHODS, \hyperpage{58}, \hyperpage{66} \item CLASS-DIRECT-SLOTS, \hyperpage{58}, \hyperpage{66} \item CLASS-DIRECT-SUBCLASSES, \hyperpage{58}, \hyperpage{66} \item CLASS-DIRECT-SUPERCLASSES, \hyperpage{58}, \hyperpage{66} \item CLASS-DOCUMENTATION, \hyperpage{58} \item CLASS-FINALIZED-P, \hyperpage{58}, \hyperpage{66} \item CLASS-LAYOUT, \hyperpage{66} \item CLASS-NAME, \hyperpage{66} \item CLASS-PRECEDENCE-LIST, \hyperpage{58}, \hyperpage{66} \item CLASS-PROTOTYPE, \hyperpage{58} \item CLASS-SLOTS, \hyperpage{59}, \hyperpage{66} \item CLASSFILES-IMPORT, \hyperpage{88} \item CLASSP, \hyperpage{33} \item CLEAR-ZIP-CACHE, \hyperpage{73} \item COERCE-TO-CONDITION, \hyperpage{73} \item COERCE-TO-FUNCTION, \hyperpage{73} \item COLLECT, \hyperpage{33} \item Command Line Options, \hyperpage{9} \item COMPILE-FILE-IF-NEEDED, \hyperpage{73} \item COMPILE-SYSTEM, \hyperpage{33}, \hyperpage{73} \item COMPILED-LISP-FUNCTION-P, \hyperpage{73} \item COMPILER-DEFSTRUCT, \hyperpage{73} \item COMPILER-ERROR, \hyperpage{73} \item COMPILER-MACROEXPAND, \hyperpage{73} \item COMPILER-STYLE-WARN, \hyperpage{74} \item COMPILER-SUBTYPEP, \hyperpage{74} \item COMPILER-UNSUPPORTED, \hyperpage{74} \item COMPILER-WARN, \hyperpage{74} \item COMPUTE-APPLICABLE-METHODS, \hyperpage{59} \item COMPUTE-APPLICABLE-METHODS-USING-CLASSES, \hyperpage{59} \item COMPUTE-CLASS-PRECEDENCE-LIST, \hyperpage{59} \item COMPUTE-DEFAULT-INITARGS, \hyperpage{59} \item COMPUTE-DISCRIMINATING-FUNCTION, \hyperpage{59} \item COMPUTE-EFFECTIVE-METHOD, \hyperpage{59} \item COMPUTE-EFFECTIVE-SLOT-DEFINITION, \hyperpage{59} \item COMPUTE-SLOTS, \hyperpage{59} \item CONCATENATE-FASLS, \hyperpage{74} \item CURRENT-THREAD, \hyperpage{28} \indexspace \item DEFCONST, \hyperpage{74} \item DEFGENERIC, \hyperpage{58} \item DEFINE-JAVA-CLASS, \hyperpage{19} \item DEFINE-SOURCE-TRANSFORM, \hyperpage{74} \item DEFKNOWN, \hyperpage{74} \item DEFPACKAGE, \hyperpage{44} \item DEFUN, \hyperpage{66} \item DELETE-EQ, \hyperpage{74} \item DELETE-EQL, \hyperpage{74} \item DESCRIBE-COMPILER-POLICY, \hyperpage{74} \item DESCRIBE-JAVA-OBJECT, \hyperpage{19} \item DESTROY-THREAD, \hyperpage{28} \item DIRECT-SLOT-DEFINITION, \hyperpage{59} \item DIRECT-SLOT-DEFINITION-CLASS, \hyperpage{59} \item DISABLE-ZIP-CACHE, \hyperpage{74} \item DISASSEMBLE-CLASS-BYTES, \hyperpage{74} \item DOCUMENTATION, \hyperpage{66} \item DOUBLE-FLOAT-HIGH-BITS, \hyperpage{74} \item DOUBLE-FLOAT-LOW-BITS, \hyperpage{74} \item DOUBLE-FLOAT-NEGATIVE-INFINITY, \hyperpage{33} \item DOUBLE-FLOAT-POSITIVE-INFINITY, \hyperpage{33} \item DUMP-CLASSPATH, \hyperpage{19} \item DUMP-FORM, \hyperpage{74} \item DUMP-JAVA-STACK, \hyperpage{33} \item DUMP-UNINTERNED-SYMBOL-INDEX, \hyperpage{75} \indexspace \item EFFECTIVE-SLOT-DEFINITION, \hyperpage{59} \item EFFECTIVE-SLOT-DEFINITION-CLASS, \hyperpage{59} \item EMPTY-ENVIRONMENT-P, \hyperpage{75} \item ENSURE-CLASS, \hyperpage{59} \item ENSURE-CLASS-USING-CLASS, \hyperpage{59} \item ENSURE-COMPATIBILITY, \hyperpage{88} \item ENSURE-GENERIC-FUNCTION-USING-CLASS, \hyperpage{59} \item ENSURE-JAVA-CLASS, \hyperpage{19} \item ENSURE-JAVA-OBJECT, \hyperpage{19} \item ENVIRONMENT, \hyperpage{75} \item ENVIRONMENT-ADD-FUNCTION-DEFINITION, \hyperpage{75} \item ENVIRONMENT-ADD-MACRO-DEFINITION, \hyperpage{75} \item ENVIRONMENT-ADD-SYMBOL-BINDING, \hyperpage{75} \item ENVIRONMENT-ALL-FUNCTIONS, \hyperpage{75} \item ENVIRONMENT-ALL-VARIABLES, \hyperpage{75} \item ENVIRONMENT-VARIABLES, \hyperpage{75} \item EQL-SPECIALIZER, \hyperpage{60} \item EQL-SPECIALIZER-OBJECT, \hyperpage{60} \item EXIT, \hyperpage{33} \item EXPAND-INLINE, \hyperpage{75} \item EXPAND-SOURCE-TRANSFORM, \hyperpage{75} \item EXTRACT-LAMBDA-LIST, \hyperpage{60} \item EXTRACT-SPECIALIZER-NAMES, \hyperpage{60} \indexspace \item FDEFINITION-BLOCK-NAME, \hyperpage{75} \item FEATUREP, \hyperpage{34} \item FILE-DIRECTORY-P, \hyperpage{34} \item FINALIZE, \hyperpage{34} \item FINALIZE-INHERITANCE, \hyperpage{60} \item FIND-CONTRIB, \hyperpage{75} \item FIND-JAVA-CLASS, \hyperpage{88} \item FIND-LOCALS, \hyperpage{75} \item FIND-METHOD-COMBINATION, \hyperpage{60} \item FIND-SYSTEM, \hyperpage{75} \item FIXNUM-CONSTANT-VALUE, \hyperpage{76} \item FIXNUM-TYPE-P, \hyperpage{76} \item FIXNUMP, \hyperpage{34} \item FLOAT-BITS, \hyperpage{66} \item FLOAT-INFINITY-P, \hyperpage{76} \item FLOAT-NAN-P, \hyperpage{76} \item FLOAT-OVERFLOW-MODE, \hyperpage{76} \item FLOAT-STRING, \hyperpage{76} \item FLOAT-UNDERFLOW-MODE, \hyperpage{76} \item FORWARD-REFERENCED-CLASS, \hyperpage{60}, \hyperpage{76} \item FRAME-TO-LIST, \hyperpage{76} \item FRAME-TO-STRING, \hyperpage{76} \item FSET, \hyperpage{76} \item FTYPE-RESULT-TYPE, \hyperpage{76} \item FUNCALLABLE-STANDARD-CLASS, \hyperpage{60} \item FUNCALLABLE-STANDARD-INSTANCE-ACCESS, \hyperpage{60} \item FUNCALLABLE-STANDARD-OBJECT, \hyperpage{60} \item FUNCTION-PLIST, \hyperpage{76} \item FUNCTION-RESULT-TYPE, \hyperpage{76} \indexspace \item GC, \hyperpage{34} \item GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER, \hyperpage{60} \item GENERIC-FUNCTION-DECLARATIONS, \hyperpage{60} \item GENERIC-FUNCTION-LAMBDA-LIST, \hyperpage{60} \item GENERIC-FUNCTION-METHOD-CLASS, \hyperpage{60} \item GENERIC-FUNCTION-METHOD-COMBINATION, \hyperpage{60} \item GENERIC-FUNCTION-METHODS, \hyperpage{60} \item GENERIC-FUNCTION-NAME, \hyperpage{61} \item GET-CACHED-EMF, \hyperpage{76} \item GET-CURRENT-CLASSLOADER, \hyperpage{20} \item GET-DEFAULT-CLASSLOADER, \hyperpage{20} \item GET-FLOATING-POINT-MODES, \hyperpage{34} \item GET-FUNCTION-INFO-VALUE, \hyperpage{76} \item GET-INPUT-STREAM, \hyperpage{77} \item GET-JAVA-FIELD, \hyperpage{88} \item GET-MUTEX, \hyperpage{28} \item GET-PID, \hyperpage{34} \item GET-SOCKET-STREAM, \hyperpage{34} \item GET-TIME-ZONE, \hyperpage{34} \item GETENV, \hyperpage{34} \item GETENV-ALL, \hyperpage{34} \item GETHASH1, \hyperpage{77} \item GROVEL-JAVA-DEFINITIONS-IN-FILE, \hyperpage{77} \indexspace \item HASH-TABLE-WEAKNESS, \hyperpage{77} \item HASHMAP-TO-HASHTABLE, \hyperpage{88} \item History, \hyperpage{55} \item HOT-COUNT, \hyperpage{77} \indexspace \item IDENTITY-HASH-CODE, \hyperpage{77} \item IN-PACKAGE, \hyperpage{66} \item INIT-FASL, \hyperpage{77} \item INIT-GUI, \hyperpage{34} \item INLINE-EXPANSION, \hyperpage{77} \item INLINE-P, \hyperpage{77} \item INSPECTED-PARTS, \hyperpage{77} \item INTEGER-CONSTANT-VALUE, \hyperpage{77} \item INTEGER-TYPE-HIGH, \hyperpage{77} \item INTEGER-TYPE-LOW, \hyperpage{77} \item INTEGER-TYPE-P, \hyperpage{77} \item INTERACTIVE-EVAL, \hyperpage{77} \item INTERN-EQL-SPECIALIZER, \hyperpage{61} \item INTERNAL-COMPILER-ERROR, \hyperpage{77} \item INTERRUPT-LISP, \hyperpage{34} \item INTERRUPT-THREAD, \hyperpage{28} \item INVOKE-ADD-IMPORTS, \hyperpage{88} \item INVOKE-RESTARGS, \hyperpage{88} \item ITERABLE-TO-LIST, \hyperpage{88} \indexspace \item J2LIST, \hyperpage{88} \item JAPROPOS, \hyperpage{89} \item JAR-IMPORT, \hyperpage{89} \item JAR-PATHNAME, \hyperpage{34}, \hyperpage{43} \item JAR-STREAM, \hyperpage{78} \item JARRAY-COMPONENT-TYPE, \hyperpage{20} \item JARRAY-FROM-LIST, \hyperpage{20} \item JARRAY-LENGTH, \hyperpage{20} \item JARRAY-REF, \hyperpage{20} \item JARRAY-REF-RAW, \hyperpage{20} \item JARRAY-SET, \hyperpage{20} \item JARRAY-TO-LIST, \hyperpage{89} \item JAVA-CLASS, \hyperpage{20} \item JAVA-CLASS-METHOD-NAMES, \hyperpage{89} \item JAVA-EXCEPTION, \hyperpage{20} \item JAVA-EXCEPTION-CAUSE, \hyperpage{20} \item JAVA-LONG-TYPE-P, \hyperpage{78} \item JAVA-OBJECT, \hyperpage{20} \item JAVA-OBJECT-P, \hyperpage{20} \item JAVA.CLASS.PATH, \hyperpage{78} \item JCALL, \hyperpage{20} \item JCALL-RAW, \hyperpage{21} \item JCLASS, \hyperpage{21} \item JCLASS-ALL-INTERFACES, \hyperpage{89} \item JCLASS-ARRAY-P, \hyperpage{21} \item JCLASS-CONSTRUCTORS, \hyperpage{21} \item JCLASS-FIELD, \hyperpage{21} \item JCLASS-FIELDS, \hyperpage{21} \item JCLASS-INTERFACE-P, \hyperpage{21} \item JCLASS-INTERFACES, \hyperpage{21} \item JCLASS-METHODS, \hyperpage{21} \item JCLASS-NAME, \hyperpage{21} \item JCLASS-OF, \hyperpage{21} \item JCLASS-SUPERCLASS, \hyperpage{21} \item JCLASS-SUPERCLASS-P, \hyperpage{21} \item JCMN, \hyperpage{89} \item JCOERCE, \hyperpage{21} \item JCONSTRUCTOR, \hyperpage{22} \item JCONSTRUCTOR-PARAMS, \hyperpage{22} \item JEQUAL, \hyperpage{22} \item JFIELD, \hyperpage{22} \item JFIELD-NAME, \hyperpage{22} \item JFIELD-RAW, \hyperpage{22} \item JFIELD-TYPE, \hyperpage{22} \item JINPUT-STREAM, \hyperpage{23} \item JINSTANCE-OF-P, \hyperpage{23} \item JINTERFACE-IMPLEMENTATION, \hyperpage{23} \item JLIST-TO-LIST, \hyperpage{89} \item JMAKE-INVOCATION-HANDLER, \hyperpage{23} \item JMAKE-PROXY, \hyperpage{23} \item JMAP, \hyperpage{89} \item JMEMBER-PROTECTED-P, \hyperpage{23} \item JMEMBER-PUBLIC-P, \hyperpage{23} \item JMEMBER-STATIC-P, \hyperpage{23} \item JMETHOD, \hyperpage{23} \item JMETHOD-LET, \hyperpage{23} \item JMETHOD-NAME, \hyperpage{23} \item JMETHOD-PARAMS, \hyperpage{24} \item JMETHOD-RETURN-TYPE, \hyperpage{24} \item JNEW, \hyperpage{24} \item JNEW-ARRAY, \hyperpage{24} \item JNEW-ARRAY-FROM-ARRAY, \hyperpage{24} \item JNEW-ARRAY-FROM-LIST, \hyperpage{24} \item JNEW-RUNTIME-CLASS, \hyperpage{24} \item JNULL-REF-P, \hyperpage{25} \item JOBJECT-CLASS, \hyperpage{25} \item JOBJECT-LISP-VALUE, \hyperpage{25} \item JPROPERTY-VALUE, \hyperpage{25} \item JREGISTER-HANDLER, \hyperpage{25} \item JRESOLVE-METHOD, \hyperpage{25} \item JRUN-EXCEPTION-PROTECTED, \hyperpage{25} \item JSS, \hyperpage{50} \item JSTATIC, \hyperpage{25} \item JSTATIC-RAW, \hyperpage{25} \item JTYPECASE, \hyperpage{89} \item JTYPEP, \hyperpage{89} \indexspace \item LAMBDA-NAME, \hyperpage{78} \item LAYOUT-CLASS, \hyperpage{78} \item LAYOUT-LENGTH, \hyperpage{78} \item LAYOUT-SLOT-INDEX, \hyperpage{78} \item LAYOUT-SLOT-LOCATION, \hyperpage{78} \item LIST-DELETE-EQ, \hyperpage{78} \item LIST-DELETE-EQL, \hyperpage{78} \item LIST-DIRECTORY, \hyperpage{78} \item LIST-TO-LIST, \hyperpage{89} \item LOAD-COMPILED-FUNCTION, \hyperpage{78} \item LOAD-SYSTEM-FILE, \hyperpage{78} \item LOGICAL-HOST-P, \hyperpage{78} \item LOGICAL-PATHNAME-P, \hyperpage{78} \item LOOKUP-KNOWN-SYMBOL, \hyperpage{79} \indexspace \item MACRO-FUNCTION-P, \hyperpage{79} \item MACROEXPAND-ALL, \hyperpage{35} \item MAILBOX, \hyperpage{35} \item MAILBOX-EMPTY-P, \hyperpage{28} \item MAILBOX-PEEK, \hyperpage{28} \item MAILBOX-READ, \hyperpage{28} \item MAILBOX-SEND, \hyperpage{28} \item MAKE-ARRAY, \hyperpage{47} \item MAKE-CLASSLOADER, \hyperpage{25} \item MAKE-CLOSURE, \hyperpage{79} \item MAKE-COMPILER-TYPE, \hyperpage{79} \item MAKE-CONDITION, \hyperpage{67} \item MAKE-DIALOG-PROMPT-STREAM, \hyperpage{35} \item MAKE-DOUBLE-FLOAT, \hyperpage{79} \item MAKE-EMF-CACHE, \hyperpage{67} \item MAKE-ENVIRONMENT, \hyperpage{79} \item MAKE-FILE-STREAM, \hyperpage{79} \item MAKE-FILL-POINTER-OUTPUT-STREAM, \hyperpage{79} \item MAKE-IMMEDIATE-OBJECT, \hyperpage{25} \item MAKE-INSTANCES-OBSOLETE, \hyperpage{67} \item MAKE-INTEGER-TYPE, \hyperpage{67}, \hyperpage{79} \item MAKE-KEYWORD, \hyperpage{79} \item MAKE-LAYOUT, \hyperpage{79} \item MAKE-LIST, \hyperpage{67} \item MAKE-LOGICAL-PATHNAME, \hyperpage{67} \item MAKE-MACRO, \hyperpage{79} \item MAKE-MACRO-EXPANDER, \hyperpage{79} \item MAKE-MAILBOX, \hyperpage{28} \item MAKE-METHOD-LAMBDA, \hyperpage{61} \item MAKE-MUTEX, \hyperpage{28} \item MAKE-SERVER-SOCKET, \hyperpage{35} \item MAKE-SINGLE-FLOAT, \hyperpage{79} \item MAKE-SLIME-INPUT-STREAM, \hyperpage{35} \item MAKE-SLIME-OUTPUT-STREAM, \hyperpage{35} \item MAKE-SLOT-DEFINITION, \hyperpage{67} \item MAKE-SOCKET, \hyperpage{35} \item MAKE-STRUCTURE, \hyperpage{67}, \hyperpage{79} \item MAKE-SYMBOL-MACRO, \hyperpage{79} \item MAKE-TEMP-DIRECTORY, \hyperpage{35} \item MAKE-TEMP-FILE, \hyperpage{35} \item MAKE-THREAD, \hyperpage{28} \item MAKE-THREAD-LOCK, \hyperpage{28} \item MAKE-WEAK-REFERENCE, \hyperpage{35} \item MAP-DEPENDENTS, \hyperpage{61} \item MAPCAR-THREADS, \hyperpage{28} \item MATCH-WILD-JAR-PATHNAME, \hyperpage{80} \item MEMBER, \hyperpage{67} \item MEMQ, \hyperpage{35} \item MEMQL, \hyperpage{35} \item METAOBJECT, \hyperpage{61} \item METHOD-FUNCTION, \hyperpage{61} \item METHOD-GENERIC-FUNCTION, \hyperpage{61} \item METHOD-LAMBDA-LIST, \hyperpage{61} \item METHOD-QUALIFIERS, \hyperpage{61} \item METHOD-SPECIALIZERS, \hyperpage{61} \item MOST-NEGATIVE-JAVA-LONG, \hyperpage{35} \item MOST-POSITIVE-JAVA-LONG, \hyperpage{35} \item MUTEX, \hyperpage{35} \indexspace \item NAMED-LAMBDA, \hyperpage{80} \item NAMED-READTABLES, \hyperpage{53} \item NEQ, \hyperpage{35} \item NEW, \hyperpage{90} \item NIL-VECTOR, \hyperpage{36} \item NORMALIZE-TYPE, \hyperpage{80} \item NOTE-NAME-DEFINED, \hyperpage{80} \item NOTINLINE-P, \hyperpage{80} \item NSTRING-CAPITALIZE, \hyperpage{67} \item NSTRING-DOWNCASE, \hyperpage{67} \item NSTRING-UPCASE, \hyperpage{67} \indexspace \item OBJECT-NOTIFY, \hyperpage{29} \item OBJECT-NOTIFY-ALL, \hyperpage{29} \item OBJECT-WAIT, \hyperpage{29} \item OS-UNIX-P, \hyperpage{36} \item OS-WINDOWS-P, \hyperpage{36} \item OUT-SYNONYM-OF, \hyperpage{80} \item OUTPUT-OBJECT, \hyperpage{67}, \hyperpage{80} \indexspace \item PACKAGE-EXTERNAL-SYMBOLS, \hyperpage{80} \item PACKAGE-INHERITED-SYMBOLS, \hyperpage{80} \item PACKAGE-INTERNAL-SYMBOLS, \hyperpage{80} \item PACKAGE-LOCAL-NICKNAMES, \hyperpage{36}, \hyperpage{44} \item PACKAGE-LOCALLY-NICKNAMED-BY-LIST, \hyperpage{36}, \hyperpage{44} \item PACKAGE-SYMBOLS, \hyperpage{80} \item PARSE-BODY, \hyperpage{80} \item PATHNAME, \hyperpage{41} \item PATHNAME-JAR-P, \hyperpage{36} \item PATHNAME-URL-P, \hyperpage{36}, \hyperpage{42} \item PRECOMPILE, \hyperpage{36}, \hyperpage{80} \item PROBE-DIRECTORY, \hyperpage{36} \item PROCESS-ALIVE-P, \hyperpage{80} \item PROCESS-ERROR, \hyperpage{80} \item PROCESS-EXIT-CODE, \hyperpage{80} \item PROCESS-INPUT, \hyperpage{81} \item PROCESS-KILL, \hyperpage{81} \item PROCESS-OPTIMIZATION-DECLARATIONS, \hyperpage{81} \item PROCESS-OUTPUT, \hyperpage{81} \item PROCESS-P, \hyperpage{81} \item PROCESS-PID, \hyperpage{81} \item PROCESS-WAIT, \hyperpage{81} \item PROCLAIMED-FTYPE, \hyperpage{81} \item PROCLAIMED-TYPE, \hyperpage{81} \item PSXHASH, \hyperpage{81} \item PUT, \hyperpage{81} \item PUTF, \hyperpage{67} \item PUTHASH, \hyperpage{81} \indexspace \item QUIT, \hyperpage{36} \indexspace \item READ-8-BITS, \hyperpage{81} \item READ-CLASS, \hyperpage{36} \item READ-TIMEOUT, \hyperpage{36} \item READ-VECTOR-UNSIGNED-BYTE-8, \hyperpage{81} \item READER-METHOD-CLASS, \hyperpage{61} \item RECORD-SOURCE-INFORMATION, \hyperpage{81} \item RECORD-SOURCE-INFORMATION-FOR-TYPE, \hyperpage{82} \item REGISTER-JAVA-EXCEPTION, \hyperpage{25} \item REINIT-EMF-CACHE, \hyperpage{67} \item RELEASE-MUTEX, \hyperpage{29} \item REMEMBER, \hyperpage{82} \item REMOVE-DEPENDENT, \hyperpage{61} \item REMOVE-DIRECT-METHOD, \hyperpage{61} \item REMOVE-DIRECT-SUBCLASS, \hyperpage{61} \item REMOVE-PACKAGE-LOCAL-NICKNAME, \hyperpage{36}, \hyperpage{44} \item REMOVE-ZIP-CACHE-ENTRY, \hyperpage{82} \item REPL, \hyperpage{9} \item REQUIRE-TYPE, \hyperpage{82} \item RESOLVE, \hyperpage{36} \item RUN-PROGRAM, \hyperpage{82} \item RUN-SHELL-COMMAND, \hyperpage{36} \indexspace \item SERVER-SOCKET-CLOSE, \hyperpage{37} \item SET-CALL-COUNT, \hyperpage{83} \item SET-CAR, \hyperpage{83} \item SET-CDR, \hyperpage{83} \item SET-CHAR, \hyperpage{83} \item SET-CLASS-DEFAULT-INITARGS, \hyperpage{67} \item SET-CLASS-DIRECT-DEFAULT-INITARGS, \hyperpage{68} \item SET-CLASS-DIRECT-METHODS, \hyperpage{68} \item SET-CLASS-DIRECT-SLOTS, \hyperpage{68} \item SET-CLASS-DIRECT-SUBCLASSES, \hyperpage{68} \item SET-CLASS-DIRECT-SUPERCLASSES, \hyperpage{68} \item SET-CLASS-DOCUMENTATION, \hyperpage{68} \item SET-CLASS-FINALIZED-P, \hyperpage{68} \item SET-CLASS-LAYOUT, \hyperpage{68} \item SET-CLASS-NAME, \hyperpage{68} \item SET-CLASS-PRECEDENCE-LIST, \hyperpage{68} \item SET-CLASS-SLOTS, \hyperpage{68} \item SET-DOCUMENTATION, \hyperpage{68} \item SET-FILL-POINTER, \hyperpage{68} \item SET-FIND-CLASS, \hyperpage{68} \item SET-FLOATING-POINT-MODES, \hyperpage{37} \item SET-FUNCALLABLE-INSTANCE-FUNCTION, \hyperpage{61} \item SET-FUNCTION-INFO-VALUE, \hyperpage{83} \item SET-HOT-COUNT, \hyperpage{83} \item SET-JAVA-FIELD, \hyperpage{90} \item SET-SCHAR, \hyperpage{83} \item SET-STANDARD-INSTANCE-ACCESS, \hyperpage{68} \item SET-STD-INSTANCE-LAYOUT, \hyperpage{68} \item SET-STD-SLOT-VALUE, \hyperpage{84} \item SET-TO-LIST, \hyperpage{90} \item SETF-FUNCTION-NAME-P, \hyperpage{84} \item SHA256, \hyperpage{84} \item SHOW-RESTARTS, \hyperpage{37} \item SHRINK-VECTOR, \hyperpage{84} \item SIMPLE-FORMAT, \hyperpage{84} \item SIMPLE-SEARCH, \hyperpage{84} \item SIMPLE-STRING-FILL, \hyperpage{37} \item SIMPLE-STRING-SEARCH, \hyperpage{37} \item SIMPLE-TYPEP, \hyperpage{84} \item SINGLE-FLOAT-BITS, \hyperpage{84} \item SINGLE-FLOAT-NEGATIVE-INFINITY, \hyperpage{37} \item SINGLE-FLOAT-POSITIVE-INFINITY, \hyperpage{37} \item SLIME-INPUT-STREAM, \hyperpage{37} \item SLIME-OUTPUT-STREAM, \hyperpage{37} \item SLOT-BOUNDP-USING-CLASS, \hyperpage{61} \item SLOT-DEFINITION, \hyperpage{62}, \hyperpage{84} \item SLOT-DEFINITION-ALLOCATION, \hyperpage{62} \item SLOT-DEFINITION-DOCUMENTATION, \hyperpage{62} \item SLOT-DEFINITION-INITARGS, \hyperpage{62} \item SLOT-DEFINITION-INITFORM, \hyperpage{62} \item SLOT-DEFINITION-INITFUNCTION, \hyperpage{62} \item SLOT-DEFINITION-LOCATION, \hyperpage{62} \item SLOT-DEFINITION-NAME, \hyperpage{62} \item SLOT-DEFINITION-READERS, \hyperpage{62} \item SLOT-DEFINITION-TYPE, \hyperpage{62} \item SLOT-DEFINITION-WRITERS, \hyperpage{62} \item SLOT-MAKUNBOUND-USING-CLASS, \hyperpage{62} \item SLOT-VALUE-USING-CLASS, \hyperpage{62} \item SOCKET-ACCEPT, \hyperpage{37} \item SOCKET-CLOSE, \hyperpage{37} \item SOCKET-LOCAL-ADDRESS, \hyperpage{37} \item SOCKET-LOCAL-PORT, \hyperpage{37} \item SOCKET-PEER-ADDRESS, \hyperpage{37} \item SOCKET-PEER-PORT, \hyperpage{37} \item SOURCE, \hyperpage{37} \item SOURCE-FILE-POSITION, \hyperpage{38} \item SOURCE-PATHNAME, \hyperpage{38} \item SOURCE-TRANSFORM, \hyperpage{84} \item SPECIAL-VARIABLE-P, \hyperpage{38} \item SPECIALIZER, \hyperpage{62} \item SPECIALIZER-DIRECT-GENERIC-FUNCTIONS, \hyperpage{62} \item SPECIALIZER-DIRECT-METHODS, \hyperpage{62} \item STANDARD-ACCESSOR-METHOD, \hyperpage{63} \item STANDARD-DIRECT-SLOT-DEFINITION, \hyperpage{63} \item STANDARD-EFFECTIVE-SLOT-DEFINITION, \hyperpage{63} \item STANDARD-INSTANCE-ACCESS, \hyperpage{63}, \hyperpage{84} \item STANDARD-METHOD, \hyperpage{63} \item STANDARD-OBJECT-P, \hyperpage{84} \item STANDARD-READER-METHOD, \hyperpage{63} \item STANDARD-SLOT-DEFINITION, \hyperpage{63} \item STANDARD-WRITER-METHOD, \hyperpage{63} \item STD-ALLOCATE-INSTANCE, \hyperpage{69} \item STD-INSTANCE-CLASS, \hyperpage{84} \item STD-INSTANCE-LAYOUT, \hyperpage{84} \item STD-SLOT-BOUNDP, \hyperpage{84} \item STD-SLOT-VALUE, \hyperpage{84} \item STREAM-OUTPUT-OBJECT, \hyperpage{69} \item STREAM-TERPRI, \hyperpage{69} \item STREAM-UNIX-FD, \hyperpage{38} \item STREAM-WRITE-CHAR, \hyperpage{69} \item STRING-CAPITALIZE, \hyperpage{69} \item STRING-DOWNCASE, \hyperpage{69} \item STRING-EQUAL, \hyperpage{69} \item STRING-FIND, \hyperpage{38} \item STRING-GREATERP, \hyperpage{69} \item STRING-INPUT-STREAM-CURRENT, \hyperpage{38} \item STRING-LESSP, \hyperpage{69} \item STRING-NOT-EQUAL, \hyperpage{69} \item STRING-NOT-GREATERP, \hyperpage{69} \item STRING-NOT-LESSP, \hyperpage{69} \item STRING-POSITION, \hyperpage{38} \item STRING-UPCASE, \hyperpage{69} \item STRING/=, \hyperpage{69} \item STRING<, \hyperpage{69} \item STRING<=, \hyperpage{69} \item STRING>, \hyperpage{70} \item STRING>=, \hyperpage{70} \item STRUCTURE-LENGTH, \hyperpage{85} \item STRUCTURE-OBJECT-P, \hyperpage{85} \item STRUCTURE-REF, \hyperpage{85} \item STRUCTURE-SET, \hyperpage{85} \item STYLE-WARN, \hyperpage{38} \item SUBCLASSP, \hyperpage{85} \item SVSET, \hyperpage{85} \item SWAP-SLOTS, \hyperpage{85} \item SYMBOL-MACRO-P, \hyperpage{85} \item SYNCHRONIZED-ON, \hyperpage{29} \item SYSTEM-ARTIFACTS-ARE-JARS-P, \hyperpage{85} \indexspace \item THREAD, \hyperpage{29} \item THREAD-ALIVE-P, \hyperpage{29} \item THREAD-JOIN, \hyperpage{29} \item THREAD-NAME, \hyperpage{29} \item THREADP, \hyperpage{29} \item TO-HASHSET, \hyperpage{90} \item TRULY-THE, \hyperpage{38} \item TYPE-ERROR, \hyperpage{70} \indexspace \item UNDEFINED-FUNCTION-CALLED, \hyperpage{85} \item UNREGISTER-JAVA-EXCEPTION, \hyperpage{26} \item UNTRACED-FUNCTION, \hyperpage{85} \item UNZIP, \hyperpage{85} \item UPDATE-DEPENDENT, \hyperpage{63} \item UPTIME, \hyperpage{38} \item URI-DECODE, \hyperpage{38} \item URI-ENCODE, \hyperpage{38} \item URL-PATHNAME, \hyperpage{38}, \hyperpage{42} \item URL-PATHNAME-AUTHORITY, \hyperpage{38}, \hyperpage{42} \item URL-PATHNAME-FRAGMENT, \hyperpage{38}, \hyperpage{42} \item URL-PATHNAME-QUERY, \hyperpage{38}, \hyperpage{42} \item URL-PATHNAME-SCHEME, \hyperpage{39}, \hyperpage{42} \item URL-STREAM, \hyperpage{85} \indexspace \item VALIDATE-SUPERCLASS, \hyperpage{63} \item VECTOR-DELETE-EQ, \hyperpage{85} \item VECTOR-DELETE-EQL, \hyperpage{85} \item VECTOR-TO-LIST, \hyperpage{90} \indexspace \item WEAK-REFERENCE, \hyperpage{39} \item WEAK-REFERENCE-VALUE, \hyperpage{39} \item WHITESPACEP, \hyperpage{85} \item WILD-PATHNAME-P, \hyperpage{70} \item WITH-CONSTANT-SIGNATURE, \hyperpage{90} \item WITH-MUTEX, \hyperpage{29} \item WITH-THREAD-LOCK, \hyperpage{29} \item WRITE-8-BITS, \hyperpage{86} \item WRITE-CLASS, \hyperpage{39} \item WRITE-TIMEOUT, \hyperpage{39} \item WRITE-VECTOR-UNSIGNED-BYTE-8, \hyperpage{86} \item WRITER-METHOD-CLASS, \hyperpage{63} \indexspace \item YIELD, \hyperpage{29} \indexspace \item ZIP, \hyperpage{86} \end{theindex} abcl-src-1.9.0/doc/manual/abcl.log0100644 0000000 0000000 00000077357 14242630063 015407 0ustar000000000 0000000 This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/MacPorts 2022.62882_0) (preloaded format=pdflatex 2022.4.24) 23 MAY 2022 08:56 entering extended mode restricted \write18 enabled. %&-line parsing enabled. **abcl.tex (./abcl.tex LaTeX2e <2021-11-15> patch level 1 L3 programming layer <2022-02-24> (/opt/local/share/texmf-texlive/tex/latex/base/book.cls Document Class: book 2021/10/04 v1.4n Standard LaTeX document class (/opt/local/share/texmf-texlive/tex/latex/base/bk10.clo File: bk10.clo 2021/10/04 v1.4n Standard LaTeX file (size option) ) \c@part=\count185 \c@chapter=\count186 \c@section=\count187 \c@subsection=\count188 \c@subsubsection=\count189 \c@paragraph=\count190 \c@subparagraph=\count191 \c@figure=\count192 \c@table=\count193 \abovecaptionskip=\skip47 \belowcaptionskip=\skip48 \bibindent=\dimen138 ) (/opt/local/share/texmf-texlive/tex/latex/base/inputenc.sty Package: inputenc 2021/02/14 v1.3d Input encoding file \inpenc@prehook=\toks16 \inpenc@posthook=\toks17 ) (./abcl.sty (/opt/local/share/texmf-texlive/tex/latex/graphics/color.sty Package: color 2021/12/07 v1.3c Standard LaTeX Color (DPC) (/opt/local/share/texmf-texlive/tex/latex/graphics-cfg/color.cfg File: color.cfg 2016/01/02 v1.6 sample color configuration ) Package color Info: Driver file: pdftex.def on input line 149. (/opt/local/share/texmf-texlive/tex/latex/graphics-def/pdftex.def File: pdftex.def 2020/10/05 v1.2a Graphics/color driver for pdftex )) (/opt/local/share/texmf-texlive/tex/latex/hyperref/hyperref.sty Package: hyperref 2022-02-21 v7.00n Hypertext links for LaTeX (/opt/local/share/texmf-texlive/tex/generic/ltxcmds/ltxcmds.sty Package: ltxcmds 2020-05-10 v1.25 LaTeX kernel commands for general use (HO) ) (/opt/local/share/texmf-texlive/tex/generic/iftex/iftex.sty Package: iftex 2022/02/03 v1.0f TeX engine tests ) (/opt/local/share/texmf-texlive/tex/generic/pdftexcmds/pdftexcmds.sty Package: pdftexcmds 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO ) (/opt/local/share/texmf-texlive/tex/generic/infwarerr/infwarerr.sty Package: infwarerr 2019/12/03 v1.5 Providing info/warning/error messages (HO) ) Package pdftexcmds Info: \pdf@primitive is available. Package pdftexcmds Info: \pdf@ifprimitive is available. Package pdftexcmds Info: \pdfdraftmode found. ) (/opt/local/share/texmf-texlive/tex/latex/graphics/keyval.sty Package: keyval 2014/10/28 v1.15 key=value parser (DPC) \KV@toks@=\toks18 ) (/opt/local/share/texmf-texlive/tex/generic/kvsetkeys/kvsetkeys.sty Package: kvsetkeys 2019/12/15 v1.18 Key value parser (HO) ) (/opt/local/share/texmf-texlive/tex/generic/kvdefinekeys/kvdefinekeys.sty Package: kvdefinekeys 2019-12-19 v1.6 Define keys (HO) ) (/opt/local/share/texmf-texlive/tex/generic/pdfescape/pdfescape.sty Package: pdfescape 2019/12/09 v1.15 Implements pdfTeX's escape features (HO) ) (/opt/local/share/texmf-texlive/tex/latex/hycolor/hycolor.sty Package: hycolor 2020-01-27 v1.10 Color options for hyperref/bookmark (HO) ) (/opt/local/share/texmf-texlive/tex/latex/letltxmacro/letltxmacro.sty Package: letltxmacro 2019/12/03 v1.6 Let assignment for LaTeX macros (HO) ) (/opt/local/share/texmf-texlive/tex/latex/auxhook/auxhook.sty Package: auxhook 2019-12-17 v1.6 Hooks for auxiliary files (HO) ) (/opt/local/share/texmf-texlive/tex/latex/kvoptions/kvoptions.sty Package: kvoptions 2020-10-07 v3.14 Key value format for package options (HO) ) \@linkdim=\dimen139 \Hy@linkcounter=\count194 \Hy@pagecounter=\count195 (/opt/local/share/texmf-texlive/tex/latex/hyperref/pd1enc.def File: pd1enc.def 2022-02-21 v7.00n Hyperref: PDFDocEncoding definition (HO) Now handling font encoding PD1 ... ... no UTF-8 mapping file for font encoding PD1 ) (/opt/local/share/texmf-texlive/tex/generic/intcalc/intcalc.sty Package: intcalc 2019/12/15 v1.3 Expandable calculations with integers (HO) ) (/opt/local/share/texmf-texlive/tex/generic/etexcmds/etexcmds.sty Package: etexcmds 2019/12/15 v1.7 Avoid name clashes with e-TeX commands (HO) ) \Hy@SavedSpaceFactor=\count196 (/opt/local/share/texmf-texlive/tex/latex/hyperref/puenc.def File: puenc.def 2022-02-21 v7.00n Hyperref: PDF Unicode definition (HO) Now handling font encoding PU ... ... no UTF-8 mapping file for font encoding PU ) Package hyperref Info: Hyper figures OFF on input line 4137. Package hyperref Info: Link nesting OFF on input line 4142. Package hyperref Info: Hyper index ON on input line 4145. Package hyperref Info: Plain pages OFF on input line 4152. Package hyperref Info: Backreferencing OFF on input line 4157. Package hyperref Info: Implicit mode ON; LaTeX internals redefined. Package hyperref Info: Bookmarks ON on input line 4390. \c@Hy@tempcnt=\count197 (/opt/local/share/texmf-texlive/tex/latex/url/url.sty \Urlmuskip=\muskip16 Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. ) LaTeX Info: Redefining \url on input line 4749. \XeTeXLinkMargin=\dimen140 (/opt/local/share/texmf-texlive/tex/generic/bitset/bitset.sty Package: bitset 2019/12/09 v1.3 Handle bit-vector datatype (HO) (/opt/local/share/texmf-texlive/tex/generic/bigintcalc/bigintcalc.sty Package: bigintcalc 2019/12/15 v1.5 Expandable calculations on big integers (HO ) )) \Fld@menulength=\count198 \Field@Width=\dimen141 \Fld@charsize=\dimen142 Package hyperref Info: Hyper figures OFF on input line 6027. Package hyperref Info: Link nesting OFF on input line 6032. Package hyperref Info: Hyper index ON on input line 6035. Package hyperref Info: backreferencing OFF on input line 6042. Package hyperref Info: Link coloring OFF on input line 6047. Package hyperref Info: Link coloring with OCG OFF on input line 6052. Package hyperref Info: PDF/A mode OFF on input line 6057. LaTeX Info: Redefining \ref on input line 6097. LaTeX Info: Redefining \pageref on input line 6101. (/opt/local/share/texmf-texlive/tex/latex/base/atbegshi-ltx.sty Package: atbegshi-ltx 2021/01/10 v1.0c Emulation of the original atbegshi package with kernel methods ) \Hy@abspage=\count199 \c@Item=\count266 \c@Hfootnote=\count267 ) Package hyperref Info: Driver (autodetected): hpdftex. (/opt/local/share/texmf-texlive/tex/latex/hyperref/hpdftex.def File: hpdftex.def 2022-02-21 v7.00n Hyperref driver for pdfTeX (/opt/local/share/texmf-texlive/tex/latex/base/atveryend-ltx.sty Package: atveryend-ltx 2020/08/19 v1.0a Emulation of the original atveryend pac kage with kernel methods ) \Fld@listcount=\count268 \c@bookmark@seq@number=\count269 (/opt/local/share/texmf-texlive/tex/latex/rerunfilecheck/rerunfilecheck.sty Package: rerunfilecheck 2019/12/05 v1.9 Rerun checks for auxiliary files (HO) (/opt/local/share/texmf-texlive/tex/generic/uniquecounter/uniquecounter.sty Package: uniquecounter 2019/12/15 v1.4 Provide unlimited unique counter (HO) ) Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2 86. ) \Hy@SectionHShift=\skip49 ) Package hyperref Info: Option `colorlinks' set `true' on input line 11. Package hyperref Info: Option `breaklinks' set `true' on input line 11. (/opt/local/share/texmf-texlive/tex/latex/a4wide/a4wide.sty Package: a4wide 1994/08/30 (/opt/local/share/texmf-texlive/tex/latex/ntgclass/a4.sty Package: a4 2020/02/18 v1.2g A4 based page layout )) (/opt/local/share/texmf-texlive/tex/latex/listings/listings.sty \lst@mode=\count270 \lst@gtempboxa=\box50 \lst@token=\toks19 \lst@length=\count271 \lst@currlwidth=\dimen143 \lst@column=\count272 \lst@pos=\count273 \lst@lostspace=\dimen144 \lst@width=\dimen145 \lst@newlines=\count274 \lst@lineno=\count275 \lst@maxwidth=\dimen146 (/opt/local/share/texmf-texlive/tex/latex/listings/lstmisc.sty File: lstmisc.sty 2020/03/24 1.8d (Carsten Heinz) \c@lstnumber=\count276 \lst@skipnumbers=\count277 \lst@framebox=\box51 ) (/opt/local/share/texmf-texlive/tex/latex/listings/listings.cfg File: listings.cfg 2020/03/24 1.8d listings configuration )) Package: listings 2020/03/24 1.8d (Carsten Heinz) (/opt/local/share/texmf-texlive/tex/latex/tools/verbatim.sty Package: verbatim 2020-07-07 v1.5u LaTeX2e package for verbatim enhancements \every@verbatim=\toks20 \verbatim@line=\toks21 \verbatim@in@stream=\read2 ) (/opt/local/share/texmf-texlive/tex/latex/changepage/changepage.sty Package: changepage 2009/10/20 v1.0c check page and change page layout \c@cp@cntr=\count278 \cp@tempcnt=\count279 ) (/opt/local/share/texmf-texlive/tex/latex/base/makeidx.sty Package: makeidx 2021/10/04 v1.0m Standard LaTeX package ) \@indexfile=\write3 \openout3 = `abcl.idx'. Writing index file abcl.idx (/opt/local/share/texmf-texlive/tex/latex/enumitem/enumitem.sty Package: enumitem 2019/06/20 v3.9 Customized lists \labelindent=\skip50 \enit@outerparindent=\dimen147 \enit@toks=\toks22 \enit@inbox=\box52 \enit@count@id=\count280 \enitdp@description=\count281 ) Package: abcl ) (/opt/local/share/texmf-texlive/tex/latex/l3backend/l3backend-pdftex.def File: l3backend-pdftex.def 2022-02-07 L3 backend support: PDF output (pdfTeX) \l__color_backend_stack_int=\count282 \l__pdf_internal_box=\box53 ) (./abcl.aux (./java.aux) (./threads.aux) (./extensions.aux) LaTeX Warning: Label `EXTENSIONS:URL-PATHNAME' multiply defined. LaTeX Warning: Label `EXTENSIONS:URL-PATHNAME-SCHEME' multiply defined. LaTeX Warning: Label `EXTENSIONS:URL-PATHNAME-FRAGMENT' multiply defined. LaTeX Warning: Label `EXTENSIONS:URL-PATHNAME-AUTHORITY' multiply defined. LaTeX Warning: Label `EXTENSIONS:PATHNAME-URL-P' multiply defined. LaTeX Warning: Label `EXTENSIONS:URL-PATHNAME-QUERY' multiply defined. (./mop.aux) (./system.aux LaTeX Warning: Label `EXTENSIONS:COMPILE-SYSTEM' multiply defined. LaTeX Warning: Label `SYSTEM:FORWARD-REFERENCED-CLASS' multiply defined. LaTeX Warning: Label `SYSTEM:MAKE-INTEGER-TYPE' multiply defined. LaTeX Warning: Label `SYSTEM:MAKE-STRUCTURE' multiply defined. LaTeX Warning: Label `SYSTEM:OUTPUT-OBJECT' multiply defined. LaTeX Warning: Label `EXTENSIONS:PRECOMPILE' multiply defined. LaTeX Warning: Label `SYSTEM:SLOT-DEFINITION' multiply defined. LaTeX Warning: Label `SYSTEM:STANDARD-INSTANCE-ACCESS' multiply defined. ) (./jss.aux)) \openout1 = `abcl.aux'. LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 13. LaTeX Font Info: ... okay on input line 13. LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 13. LaTeX Font Info: ... okay on input line 13. LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 13. LaTeX Font Info: ... okay on input line 13. LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 13. LaTeX Font Info: ... okay on input line 13. LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 13. LaTeX Font Info: ... okay on input line 13. LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 13. LaTeX Font Info: ... okay on input line 13. LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 13. LaTeX Font Info: ... okay on input line 13. LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 13. LaTeX Font Info: ... okay on input line 13. LaTeX Font Info: Checking defaults for PU/pdf/m/n on input line 13. LaTeX Font Info: ... okay on input line 13. (/opt/local/share/texmf-texlive/tex/context/base/mkii/supp-pdf.mkii [Loading MPS to PDF converter (version 2006.09.02).] \scratchcounter=\count283 \scratchdimen=\dimen148 \scratchbox=\box54 \nofMPsegments=\count284 \nofMParguments=\count285 \everyMPshowfont=\toks23 \MPscratchCnt=\count286 \MPscratchDim=\dimen149 \MPnumerator=\count287 \makeMPintoPDFobject=\count288 \everyMPtoPDFconversion=\toks24 ) Package hyperref Info: Link coloring ON on input line 13. (/opt/local/share/texmf-texlive/tex/latex/hyperref/nameref.sty Package: nameref 2021-04-02 v2.47 Cross-referencing by name of section (/opt/local/share/texmf-texlive/tex/latex/refcount/refcount.sty Package: refcount 2019/12/15 v3.6 Data extraction from label references (HO) ) (/opt/local/share/texmf-texlive/tex/generic/gettitlestring/gettitlestring.sty Package: gettitlestring 2019/12/15 v1.6 Cleanup title references (HO) ) \c@section@level=\count289 ) LaTeX Info: Redefining \ref on input line 13. LaTeX Info: Redefining \pageref on input line 13. LaTeX Info: Redefining \nameref on input line 13. (./abcl.out) (./abcl.out) \@outlinefile=\write4 \openout4 = `abcl.out'. \c@lstlisting=\count290 LaTeX Font Info: External font `cmex10' loaded for size (Font) <12> on input line 22. LaTeX Font Info: External font `cmex10' loaded for size (Font) <8> on input line 22. LaTeX Font Info: External font `cmex10' loaded for size (Font) <6> on input line 22. [1 {/opt/local/var/db/texmf/fonts/map/pdftex/updmap/pdftex.map}] [2 ] (./abcl.toc LaTeX Font Info: External font `cmex10' loaded for size (Font) <7> on input line 1. LaTeX Font Info: External font `cmex10' loaded for size (Font) <5> on input line 1. [3]) \tf@toc=\write5 \openout5 = `abcl.toc'. [4] Overfull \hbox (6.49327pt too wide) in paragraph at lines 102--117 []\OT1/cmr/m/n/10 The im-ple-men-ta-tion of the \OT1/cmtt/m/n/10 EXT:JAR-PATHNA ME \OT1/cmr/m/n/10 and \OT1/cmtt/m/n/10 EXT:URL-PATHNAME \OT1/cmr/m/n/10 sub-ty pes of \OT1/cmtt/m/n/10 cl:PATHNAME [] Overfull \hbox (10.13367pt too wide) in paragraph at lines 102--117 \OT1/cmr/m/n/10 most read-only op-er-a-tions (\OT1/cmtt/m/n/10 CL:PROBE-FILE\OT 1/cmr/m/n/10 , \OT1/cmtt/m/n/10 CL:TRUENAME\OT1/cmr/m/n/10 , \OT1/cmtt/m/n/10 C L:OPEN\OT1/cmr/m/n/10 , \OT1/cmtt/m/n/10 CL:LOAD\OT1/cmr/m/n/10 , \OT1/cmtt/m/n /10 CL:FILE-WRITE-DATE\OT1/cmr/m/n/10 , [] [5] [6] Chapter 1. [7 ] [8] [9] [10 ] Chapter 2. (/opt/local/share/texmf-texlive/tex/latex/listings/lstlang1.sty File: lstlang1.sty 2020/03/24 1.8d listings language file ) LaTeX Font Info: Trying to load font information for TS1+cmtt on input line 292. (/opt/local/share/texmf-texlive/tex/latex/base/ts1cmtt.fd File: ts1cmtt.fd 2019/12/16 v2.5j Standard LaTeX font definitions ) [11] [12] Chapter 3. [13 ] (/opt/local/share/texmf-texlive/tex/latex/listings/lstlang1.sty File: lstlang1.sty 2020/03/24 1.8d listings language file ) LaTeX Font Info: Font shape `OT1/cmtt/bx/n' in size <10> not available (Font) Font shape `OT1/cmtt/m/n' tried instead on input line 442. Overfull \hbox (3.81293pt too wide) in paragraph at lines 453--454 [][][][][][][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (22.71289pt too wide) in paragraph at lines 455--456 [][][][][][][][][][][][][][][][][][] [] (/opt/local/share/texmf-texlive/tex/latex/listings/lstlang1.sty File: lstlang1.sty 2020/03/24 1.8d listings language file ) (/opt/local/share/texmf-texlive/tex/latex/listings/lstlang2.sty File: lstlang2.sty 2020/03/24 1.8d listings language file ) [14] Overfull \hbox (4.97552pt too wide) in paragraph at lines 570--575 \OT1/cmr/m/n/10 Note: the en-tire \OT1/cmr/m/sc/10 ABCL Lisp \OT1/cmr/m/n/10 sy s-tem im-ple-men-ta-tion in \OT1/cmr/m/sc/10 Java \OT1/cmr/m/n/10 is res-i-dent in the \OT1/cmtt/m/n/10 org.armedbear.lisp [] [15] [16] [17] Overfull \hbox (51.77336pt too wide) in paragraph at lines 770--778 \OT1/cmr/m/n/10 ing the \OT1/cmtt/m/n/10 AbclScriptEngineFactory \OT1/cmr/m/n/1 0 or by us-ing the ser-vice provider mech-a-nism through \OT1/cmtt/m/n/10 Scrip tEngineManager [] Overfull \hbox (1.79208pt too wide) in paragraph at lines 808--810 []\OT1/cmr/m/n/10 The di-rec-tory where Swank is in-stalled. Must be set if \OT 1/cmtt/m/n/10 *launch-swank-at-startup* [] Overfull \hbox (48.98656pt too wide) in paragraph at lines 810--814 []\OT1/cmr/m/n/10 The port where Swank will lis-ten for con-nec-tions. Must be set if \OT1/cmtt/m/n/10 *launch-swank-at-startup* [] [18] Overfull \hbox (4.2739pt too wide) in paragraph at lines 823--831 \OT1/cmr/m/n/10 Code is read and eval-u-ated in the pack-age \OT1/cmtt/m/n/10 A BCL-SCRIPT-USER\OT1/cmr/m/n/10 . This pack-ages \OT1/cmtt/m/n/10 USE\OT1/cmr/m/ n/10 s the \OT1/cmtt/m/n/10 COMMON-LISP\OT1/cmr/m/n/10 , [] Overfull \hbox (75.70952pt too wide) in paragraph at lines 848--868 \OT1/cmr/m/n/10 ports com-pi-la-tion us-ing tem-po-rary files. Com-piled code, re-turned as an in-stance of \OT1/cmtt/m/n/10 javax.script.CompiledScript\OT1/c mr/m/n/10 , [] [19] Overfull \hbox (40.88481pt too wide) in paragraph at lines 918--924 []\OT1/cmr/m/n/10 This func-tion-al-ity is ex-posed by the class \OT1/cmtt/m/n/ 10 AbclScriptEngine \OT1/cmr/m/n/10 via the two meth-ods \OT1/cmtt/m/n/10 getIn terface(Class) [] [20] \openout2 = `java.aux'. (./java.tex Overfull \hbox (2.10675pt too wide) in paragraph at lines 43--44 []\OT1/cmr/m/n/10 Add JAR-OR-JARS to the JVM class-path op-tion-ally spec-i-fy- ing the CLASS- [] [21 ] [22] [23] [24] [25] Overfull \hbox (9.56848pt too wide) in paragraph at lines 668--669 [][] \OT1/cmr/m/n/10 --- Func-tion: \OT1/cmr/bx/n/10 jnew-runtime-class \OT1/c mr/m/n/10 [\OT1/cmr/bx/n/10 java\OT1/cmr/m/n/10 ] \OT1/cmr/m/it/10 class-name & rest args &key (su-per-class java.lang.Object) [] Overfull \hbox (8.0664pt too wide) in paragraph at lines 668--669 \OT1/cmr/m/it/10 in-ter-faces con-struc-tors meth-ods fields (access-flags (quo te (pub-lic))) an-no-ta-tions (class-loader (make- [] Overfull \hbox (32.38686pt too wide) in paragraph at lines 676--687 \OT1/cmr/m/n/10 (argument-types func-tion &op-tional super-invocation-arguments ) where argument- [] Overfull \hbox (9.50836pt too wide) in paragraph at lines 690--691 []\OT1/cmr/m/n/10 (METHOD-NAME RETURN-TYPE ARGUMENT-TYPES FUNC-TION [] [26] Overfull \hbox (40.07188pt too wide) in paragraph at lines 810--814 []\OT1/cmr/m/n/10 Deprecated. Please use JAVA:+NULL+, JAVA:+TRUE+, and JAVA:+FA LSE+ [] [27]) [28] [29 ] \openout2 = `threads.aux'. (./threads.tex [30 ]) [31] [32 ] \openout2 = `extensions.aux'. (./extensions.tex [33 ] [34] Overfull \hbox (19.18938pt too wide) in paragraph at lines 354--355 [][] \OT1/cmr/m/n/10 --- Func-tion: \OT1/cmr/bx/n/10 compile-system \OT1/cmr/m /n/10 [\OT1/cmr/bx/n/10 extensions\OT1/cmr/m/n/10 ] \OT1/cmr/m/it/10 &key quit (zip t) (cls-ext *compile-file-class-extension*) [] [35] [36] [37] Overfull \hbox (3.78679pt too wide) in paragraph at lines 780--781 [][] \OT1/cmr/m/n/10 --- Func-tion: \OT1/cmr/bx/n/10 remove-package-local-nick name \OT1/cmr/m/n/10 [\OT1/cmr/bx/n/10 extensions\OT1/cmr/m/n/10 ] \OT1/cmr/m/i t/10 old-nickname &op-tional package- [] [38] [39] [40]) [41] [42 ] Chapter 4. Overfull \hbox (77.01479pt too wide) in paragraph at lines 1016--1021 \OT1/cmr/m/n/10 put-ing di-ag-nos-tics to the stan-dard re-port-ing stream. The gen-er-al-ized boolean \OT1/cmtt/m/n/10 JVM:*RESIGNAL-COMPILER-WARNINGS* [] Overfull \hbox (0.54178pt too wide) in paragraph at lines 1025--1036 \OT1/cmr/m/n/10 INTROSPECT con-trib. Af-ter load-ing one of these tools via ASD F, the \OT1/cmtt/m/n/10 SYS:CHOOSE-DISASSEMBLER [] [43] Underfull \hbox (badness 10000) in paragraph at lines 1071--1071 [][][]\OT1/cmr/m/n/8 See [[]] for more de-tails. [][]$\OT1/cmtt/m/n/8 https : / / stackoverflow . com / questions / 41784555 / [] Overfull \hbox (54.13358pt too wide) in paragraph at lines 1120--1127 \OT1/cmr/m/n/10 pro-vide a SETF-able API for read-ing and writ-ing such val-ues : \OT1/cmtt/m/n/10 URL-PATHNAME-QUERY\OT1/cmr/m/n/10 , \OT1/cmtt/m/n/10 URL-PAT HNAME-FRAGMENT\OT1/cmr/m/n/10 , [] [44] Overfull \hbox (36.03406pt too wide) in paragraph at lines 1204--1209 \OT1/cmr/m/n/10 and cor-re-spond-ing ``!'' suf-fixes to en-cap-su-late suc-ces- sive lo-ca-tions. De-scribed broadly, a \OT1/cmtt/m/n/10 EXT:JAR-PATHNAME [] [45] Overfull \hbox (12.93993pt too wide) in paragraph at lines 1242--1244 []\OT1/cmr/m/n/10 The op-tions to \OT1/cmtt/m/n/10 defpackage \OT1/cmr/m/n/10 a re ex-tended with a new op-tion \OT1/cmtt/m/n/10 :local-nicknames (local-nickna me [] Overfull \hbox (41.41306pt too wide) in paragraph at lines 1304--1308 []\OT1/cmr/m/n/10 When in the des-ig-nated pack-age, calls to \OT1/cmtt/m/n/10 find-package \OT1/cmr/m/n/10 with the \OT1/cmtt/m/n/10 local-nickname [] Overfull \hbox (18.64778pt too wide) in paragraph at lines 1315--1316 []\OT1/cmr/m/n/10 --- Func-tion: \OT1/cmr/bx/n/10 remove-package-local-nickname \OT1/cmr/m/n/10 [\OT1/cmr/bx/n/10 ext\OT1/cmr/m/n/10 ] \OT1/cmr/m/it/10 old-ni ckname &op-tional package-designator [] [46] Overfull \hbox (70.62pt too wide) in paragraph at lines 1366--1370 []\OT1/cmr/m/n/10 Contrary to the AMOP spec-i-fi-ca-tion and fol-low-ing \OT1/c mr/m/sc/10 SBCL\OT1/cmr/m/n/10 's lead, the meta-class \OT1/cmtt/m/n/10 funcall able-standard-object [] LaTeX Warning: Reference `closer-mop' on page 47 undefined on input line 1372. Overfull \hbox (3.81293pt too wide) in paragraph at lines 1386--1387 [][][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (35.31287pt too wide) in paragraph at lines 1402--1403 [][][][][][][][][][][][][][][][][][][][][][][][][][][] [] [47] LaTeX Warning: Reference `sec:asdf-jar' on page 48 undefined on input line 1468 . LaTeX Warning: Reference `sections:jss' on page 48 undefined on input line 1488 . Overfull \hbox (1.74713pt too wide) in paragraph at lines 1490--1496 \OT1/cmr/m/n/10 pack-ag-ing for in-stalling and us-ing java de-com-pi-la-tion t ools for use with \OT1/cmtt/m/n/10 CL:DISASSEMBLE\OT1/cmr/m/n/10 . [] Overfull \hbox (117.7723pt too wide) in paragraph at lines 1510--1515 []\OT1/cmr/m/n/10 The user may ex-tend the \OT1/cmtt/m/n/10 CL:REQUIRE \OT1/cmr /m/n/10 mech-a-nism by push-ing func-tion hooks into \OT1/cmtt/m/n/10 SYSTEM:*M ODULE-PROVIDER-FUNCTIONS*\OT1/cmr/m/n/10 . [] [48] Overfull \hbox (7.30168pt too wide) in paragraph at lines 1516--1516 []\OT1/cmr/bx/n/14.4 JSS ex-ten-sion of the Reader by SHARPSIGN-DOUBLE- [] Overfull \hbox (20.6358pt too wide) in paragraph at lines 1542--1547 \OT1/cmr/m/n/10 With the \OT1/cmtt/m/n/10 :nio \OT1/cmr/m/n/10 fea-ture is pres ent[][][][][], the im-ple-men-ta-tion adds two key-word ar-gu-ments to \OT1/cmt t/m/n/10 cl:make-array\OT1/cmr/m/n/10 , [] Overfull \hbox (66.8128pt too wide) in paragraph at lines 1566--1567 [][][][][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (85.71277pt too wide) in paragraph at lines 1567--1568 [][][][][][][][][][][][][][][][][][][][][][] [] [49] [50] Chapter 5. Overfull \hbox (74.77414pt too wide) in paragraph at lines 1616--1621 \OT1/cmr/m/n/10 com-po-nent can also be di-rectly ma-nip-u-lated by the func-ti on as-so-ci-ated with the \OT1/cmtt/m/n/10 ABCL-ASDF:RESOLVE-DEPENDENCIES [] Overfull \hbox (74.96739pt too wide) in paragraph at lines 1661--1666 []\OT1/cmr/m/n/10 For use out-side of ASDF sys-tem def-i-ni-tions, we cur-rentl y de-fine one method, \OT1/cmtt/m/n/10 ABCL-ASDF:RESOLVE-DEPENDENCIES [] [51 ] Overfull \hbox (35.31287pt too wide) in paragraph at lines 1676--1677 [][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (35.31287pt too wide) in paragraph at lines 1677--1678 [][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (35.31287pt too wide) in paragraph at lines 1678--1679 [][][][][][][][][][][][][][][][] [] Overfull \hbox (35.31287pt too wide) in paragraph at lines 1679--1680 [][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (35.31287pt too wide) in paragraph at lines 1680--1681 [][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (35.31287pt too wide) in paragraph at lines 1681--1682 [][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (35.31287pt too wide) in paragraph at lines 1682--1683 [][][][][][][][][][][][][][][][][][][][] [] [52] Overfull \hbox (77.24521pt too wide) in paragraph at lines 1810--1812 \OT1/cmr/m/n/10 The fol-low-ing \OT1/cmr/m/sc/10 ASDF \OT1/cmr/m/n/10 sys-tems pack-ages var-i-ous ex-ter-nal tools that may be se-lected by the \OT1/cmtt/m/n /10 SYS:CHOOSE-DISASSEMBLER [] [53] Overfull \hbox (142.41266pt too wide) in paragraph at lines 1837--1838 [][][][][][][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (274.7124pt too wide) in paragraph at lines 1840--1841 [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (54.21283pt too wide) in paragraph at lines 1845--1846 [][][][][][][][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (230.61249pt too wide) in paragraph at lines 1847--1848 [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (287.31238pt too wide) in paragraph at lines 1853--1854 [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] [] Overfull \hbox (306.21234pt too wide) in paragraph at lines 1858--1859 [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] [] [54] [55] [56 ] Chapter 6. Overfull \hbox (46.55148pt too wide) in paragraph at lines 1964--1969 []\OT1/cmr/m/n/10 With the over-haul the im-ple-men-ta-tion of ar-rays spe-cial -ized on \OT1/cmtt/m/n/10 (or (unsigned-byte 8) (unsigned-byte [] [57] [58 ] Appendix A. [59] \openout2 = `mop.aux'. (./mop.tex [60 ] [61] [62] [63] [64]) [65] [66 ] Appendix B. [67] \openout2 = `system.aux'. (./system.tex [68 ] [69] [70] [71] [72] [73] [74] Overfull \hbox (9.33665pt too wide) in paragraph at lines 1077--1078 [][] \OT1/cmr/m/n/10 --- Func-tion: \OT1/cmr/bx/n/10 compile-file-if-needed \O T1/cmr/m/n/10 [\OT1/cmr/bx/n/10 system\OT1/cmr/m/n/10 ] \OT1/cmr/m/it/10 input- file &rest al-largs &key force-compile &allow- [] Overfull \hbox (19.18938pt too wide) in paragraph at lines 1086--1087 [][] \OT1/cmr/m/n/10 --- Func-tion: \OT1/cmr/bx/n/10 compile-system \OT1/cmr/m /n/10 [\OT1/cmr/bx/n/10 extensions\OT1/cmr/m/n/10 ] \OT1/cmr/m/it/10 &key quit (zip t) (cls-ext *compile-file-class-extension*) [] [75] [76] [77] [78] [79] [80] [81] [82] [83] Overfull \hbox (408.68188pt too wide) in paragraph at lines 2285--2287 []\OT1/cmr/m/n/10 These val-ues fol-low SBCL'S im-ple-me-na-tion in SLIME c.f. [] Overfull \hbox (2.58932pt too wide) in paragraph at lines 2321--2322 [][] \OT1/cmr/m/n/10 --- Func-tion: \OT1/cmr/bx/n/10 run-program \OT1/cmr/m/n/ 10 [\OT1/cmr/bx/n/10 system\OT1/cmr/m/n/10 ] \OT1/cmr/m/it/10 pro-gram args &ke y en-vi-ron-ment (wait t) clear-environment [] Overfull \hbox (32.44228pt too wide) in paragraph at lines 2337--2339 \OT1/cmr/m/n/10 Pro-cess ob-ject, and the PROCESS-INPUT, PROCESS-OUTPUT, and PR OCESS- [] Overfull \hbox (19.3499pt too wide) in paragraph at lines 2340--2341 []\OT1/cmr/m/n/10 c.f. http://download.oracle.com/javase/6/docs/api/java/lang/P rocess.html [] [84] [85] [86] [87]) [88] Appendix C. [89 ] \openout2 = `jss.aux'. (./jss.tex [90 ] [91]) [92] (./abcl.bbl) (./abcl.ind [93 ] Overfull \hbox (9.11005pt too wide) in paragraph at lines 34--35 []\OT1/cmr/m/n/10 *LOGICAL-PATHNAME-TRANSLATIONS*, [][]71[][] [] Overfull \hbox (7.15172pt too wide) in paragraph at lines 65--66 []\OT1/cmr/m/n/10 ACCESSOR-METHOD-SLOT-DEFINITION, [][]58[][] [] [94 ] Overfull \hbox (11.04059pt too wide) in paragraph at lines 102--103 []\OT1/cmr/m/n/10 CANONICALIZE-DIRECT-SUPERCLASSES, [][]58[][] [] Overfull \hbox (1.19328pt too wide) in paragraph at lines 115--116 []\OT1/cmr/m/n/10 CLASS-DIRECT-DEFAULT-INITARGS, [][]58[][], [][]66[][] [] Overfull \hbox (8.0545pt too wide) in paragraph at lines 145--146 []\OT1/cmr/m/n/10 COMPUTE-APPLICABLE-METHODS-USING- [] Overfull \hbox (9.86002pt too wide) in paragraph at lines 148--149 []\OT1/cmr/m/n/10 COMPUTE-DISCRIMINATING-FUNCTION, [][]59[][] [] Overfull \hbox (5.62396pt too wide) in paragraph at lines 150--151 []\OT1/cmr/m/n/10 COMPUTE-EFFECTIVE-SLOT-DEFINITION, [] Overfull \hbox (16.45726pt too wide) in paragraph at lines 191--192 []\OT1/cmr/m/n/10 ENSURE-GENERIC-FUNCTION-USING-CLASS, [] Overfull \hbox (23.40173pt too wide) in paragraph at lines 195--196 []\OT1/cmr/m/n/10 ENVIRONMENT-ADD-FUNCTION-DEFINITION, [] Overfull \hbox (7.01279pt too wide) in paragraph at lines 196--197 []\OT1/cmr/m/n/10 ENVIRONMENT-ADD-MACRO-DEFINITION, [] Overfull \hbox (7.08228pt too wide) in paragraph at lines 197--198 []\OT1/cmr/m/n/10 ENVIRONMENT-ADD-SYMBOL-BINDING, [][]75[][] [] [95] Overfull \hbox (30.34618pt too wide) in paragraph at lines 236--237 []\OT1/cmr/m/n/10 FUNCALLABLE-STANDARD-INSTANCE-ACCESS, [] Overfull \hbox (39.6517pt too wide) in paragraph at lines 244--245 []\OT1/cmr/m/n/10 GENERIC-FUNCTION-ARGUMENT-PRECEDENCE- [] Overfull \hbox (28.74896pt too wide) in paragraph at lines 248--249 []\OT1/cmr/m/n/10 GENERIC-FUNCTION-METHOD-COMBINATION, [] [96] Overfull \hbox (9.65172pt too wide) in paragraph at lines 411--412 []\OT1/cmr/m/n/10 MAKE-FILL-POINTER-OUTPUT-STREAM, [][]79[][] [] [97] Overfull \hbox (8.74892pt too wide) in paragraph at lines 483--485 []\OT1/cmr/m/n/10 PACKAGE-LOCALLY-NICKNAMED-BY-LIST, [] Overfull \hbox (7.15169pt too wide) in paragraph at lines 497--498 []\OT1/cmr/m/n/10 PROCESS-OPTIMIZATION-DECLARATIONS, [] Overfull \hbox (19.09613pt too wide) in paragraph at lines 521--522 []\OT1/cmr/m/n/10 RECORD-SOURCE-INFORMATION-FOR-TYPE, [] Overfull \hbox (7.7767pt too wide) in paragraph at lines 529--530 []\OT1/cmr/m/n/10 REMOVE-PACKAGE-LOCAL-NICKNAME, [][]36[][], [] Overfull \hbox (8.88773pt too wide) in paragraph at lines 545--546 []\OT1/cmr/m/n/10 SET-CLASS-DIRECT-DEFAULT-INITARGS, [][]68[][] [] [98] Overfull \hbox (8.40173pt too wide) in paragraph at lines 560--561 []\OT1/cmr/m/n/10 SET-FUNCALLABLE-INSTANCE-FUNCTION, [] Overfull \hbox (20.55446pt too wide) in paragraph at lines 609--610 []\OT1/cmr/m/n/10 SPECIALIZER-DIRECT-GENERIC-FUNCTIONS, [] Overfull \hbox (2.98499pt too wide) in paragraph at lines 612--613 []\OT1/cmr/m/n/10 STANDARD-DIRECT-SLOT-DEFINITION, [][]63[][] [] Overfull \hbox (9.92949pt too wide) in paragraph at lines 613--614 []\OT1/cmr/m/n/10 STANDARD-EFFECTIVE-SLOT-DEFINITION, [] [99] [100 ]) (./abcl.aux (./java.aux) (./threads.aux) (./extensions.aux) (./mop.aux) (./system.aux) (./jss.aux)) LaTeX Warning: There were undefined references. LaTeX Warning: There were multiply-defined labels. Package rerunfilecheck Info: File `abcl.out' has not changed. (rerunfilecheck) Checksum: 86413364838BC39D783091E2317C2A0B;11390. ) Here is how much of TeX's memory you used: 12651 strings out of 478268 198719 string characters out of 5848327 711913 words of memory out of 5000000 29613 multiletter control sequences out of 15000+600000 477461 words of font info for 56 fonts, out of 8000000 for 9000 1141 hyphenation exceptions out of 8191 75i,8n,77p,678b,1819s stack positions out of 10000i,1000n,20000p,200000b,200000s {/opt/local/share/texmf-texlive/fonts/enc/dvips/cm-super/cm-super-ts1.enc}< /opt/local/share/texmf-texlive/fonts/type1/public/amsfonts/cm/cmtt10.pfb> Output written on abcl.pdf (100 pages, 500188 bytes). PDF statistics: 2816 PDF objects out of 2984 (max. 8388607) 2649 compressed objects within 27 object streams 1078 named destinations out of 1200 (max. 500000) 553 words of extra memory for PDF output out of 10000 (max. 10000000) abcl-src-1.9.0/doc/manual/abcl.out0100644 0000000 0000000 00000026176 14242630063 015426 0ustar000000000 0000000 \BOOKMARK [2][-]{subsection.0.0.1}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000F\000i\000r\000s\000t\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 1 \BOOKMARK [2][-]{subsection.0.0.2}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000S\000e\000c\000o\000n\000d\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 2 \BOOKMARK [2][-]{subsection.0.0.3}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000T\000h\000i\000r\000d\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 3 \BOOKMARK [2][-]{subsection.0.0.4}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000F\000o\000u\000r\000t\000h\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 4 \BOOKMARK [2][-]{subsection.0.0.5}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000F\000i\000f\000t\000h\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 5 \BOOKMARK [2][-]{subsection.0.0.6}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000S\000i\000x\000t\000h\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 6 \BOOKMARK [2][-]{subsection.0.0.7}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000S\000e\000v\000e\000n\000t\000h\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 7 \BOOKMARK [2][-]{subsection.0.0.8}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000E\000i\000g\000h\000t\000h\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 8 \BOOKMARK [2][-]{subsection.0.0.9}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000N\000i\000n\000t\000h\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 9 \BOOKMARK [2][-]{subsection.0.0.10}{\376\377\000P\000r\000e\000f\000a\000c\000e\000\040\000t\000o\000\040\000t\000h\000e\000\040\000T\000e\000n\000t\000h\000\040\000E\000d\000i\000t\000i\000o\000n}{}% 10 \BOOKMARK [0][-]{chapter.1}{\376\377\000I\000n\000t\000r\000o\000d\000u\000c\000t\000i\000o\000n}{}% 11 \BOOKMARK [1][-]{section.1.1}{\376\377\000C\000o\000n\000f\000o\000r\000m\000a\000n\000c\000e}{chapter.1}% 12 \BOOKMARK [2][-]{subsection.1.1.1}{\376\377\000A\000N\000S\000I\000\040\000C\000o\000m\000m\000o\000n\000\040\000L\000i\000s\000p}{section.1.1}% 13 \BOOKMARK [2][-]{subsection.1.1.2}{\376\377\000C\000o\000n\000t\000e\000m\000p\000o\000r\000a\000r\000y\000\040\000C\000o\000m\000m\000o\000n\000\040\000L\000i\000s\000p}{section.1.1}% 14 \BOOKMARK [1][-]{section.1.2}{\376\377\000L\000i\000c\000e\000n\000s\000e}{chapter.1}% 15 \BOOKMARK [1][-]{section.1.3}{\376\377\000C\000o\000n\000t\000r\000i\000b\000u\000t\000o\000r\000s}{chapter.1}% 16 \BOOKMARK [0][-]{chapter.2}{\376\377\000R\000u\000n\000n\000i\000n\000g\000\040\000A\000B\000C\000L}{}% 17 \BOOKMARK [1][-]{section.2.1}{\376\377\000O\000p\000t\000i\000o\000n\000s}{chapter.2}% 18 \BOOKMARK [1][-]{section.2.2}{\376\377\000I\000n\000i\000t\000i\000a\000l\000i\000z\000a\000t\000i\000o\000n}{chapter.2}% 19 \BOOKMARK [0][-]{chapter.3}{\376\377\000I\000n\000t\000e\000r\000a\000c\000t\000i\000o\000n\000\040\000w\000i\000t\000h\000\040\000t\000h\000e\000\040\000H\000o\000s\000t\000i\000n\000g\000\040\000J\000V\000M}{}% 20 \BOOKMARK [1][-]{section.3.1}{\376\377\000L\000i\000s\000p\000\040\000t\000o\000\040\000J\000a\000v\000a}{chapter.3}% 21 \BOOKMARK [2][-]{subsection.3.1.1}{\376\377\000L\000o\000w\000-\000l\000e\000v\000e\000l\000\040\000J\000a\000v\000a\000\040\000A\000P\000I}{section.3.1}% 22 \BOOKMARK [1][-]{section.3.2}{\376\377\000J\000a\000v\000a\000\040\000t\000o\000\040\000L\000i\000s\000p}{chapter.3}% 23 \BOOKMARK [2][-]{subsection.3.2.1}{\376\377\000C\000a\000l\000l\000i\000n\000g\000\040\000L\000i\000s\000p\000\040\000f\000r\000o\000m\000\040\000J\000a\000v\000a}{section.3.2}% 24 \BOOKMARK [1][-]{section.3.3}{\376\377\000J\000a\000v\000a\000\040\000S\000c\000r\000i\000p\000t\000i\000n\000g\000\040\000A\000P\000I\000\040\000\050\000J\000S\000R\000-\0002\0002\0003\000\051}{chapter.3}% 25 \BOOKMARK [2][-]{subsection.3.3.1}{\376\377\000C\000o\000n\000v\000e\000r\000s\000i\000o\000n\000s}{section.3.3}% 26 \BOOKMARK [2][-]{subsection.3.3.2}{\376\377\000I\000m\000p\000l\000e\000m\000e\000n\000t\000e\000d\000\040\000J\000S\000R\000-\0002\0002\0003\000\040\000i\000n\000t\000e\000r\000f\000a\000c\000e\000s}{section.3.3}% 27 \BOOKMARK [2][-]{subsection.3.3.3}{\376\377\000S\000t\000a\000r\000t\000-\000u\000p\000\040\000a\000n\000d\000\040\000c\000o\000n\000f\000i\000g\000u\000r\000a\000t\000i\000o\000n\000\040\000f\000i\000l\000e}{section.3.3}% 28 \BOOKMARK [2][-]{subsection.3.3.4}{\376\377\000E\000v\000a\000l\000u\000a\000t\000i\000o\000n}{section.3.3}% 29 \BOOKMARK [2][-]{subsection.3.3.5}{\376\377\000C\000o\000m\000p\000i\000l\000a\000t\000i\000o\000n}{section.3.3}% 30 \BOOKMARK [2][-]{subsection.3.3.6}{\376\377\000I\000n\000v\000o\000c\000a\000t\000i\000o\000n\000\040\000o\000f\000\040\000f\000u\000n\000c\000t\000i\000o\000n\000s\000\040\000a\000n\000d\000\040\000m\000e\000t\000h\000o\000d\000s}{section.3.3}% 31 \BOOKMARK [2][-]{subsection.3.3.7}{\376\377\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n\000\040\000o\000f\000\040\000J\000a\000v\000a\000\040\000i\000n\000t\000e\000r\000f\000a\000c\000e\000s\000\040\000i\000n\000\040\000L\000i\000s\000p}{section.3.3}% 32 \BOOKMARK [1][-]{section.3.4}{\376\377\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n\000\040\000E\000x\000t\000e\000n\000s\000i\000o\000n\000\040\000D\000i\000c\000t\000i\000o\000n\000a\000r\000i\000e\000s}{chapter.3}% 33 \BOOKMARK [2][-]{subsection.3.4.1}{\376\377\000T\000h\000e\000\040\000J\000A\000V\000A\000\040\000D\000i\000c\000t\000i\000o\000n\000a\000r\000y}{section.3.4}% 34 \BOOKMARK [2][-]{subsection.3.4.2}{\376\377\000T\000h\000e\000\040\000T\000H\000R\000E\000A\000D\000S\000\040\000D\000i\000c\000t\000i\000o\000n\000a\000r\000y}{section.3.4}% 35 \BOOKMARK [2][-]{subsection.3.4.3}{\376\377\000T\000h\000e\000\040\000E\000X\000T\000E\000N\000S\000I\000O\000N\000S\000\040\000D\000i\000c\000t\000i\000o\000n\000a\000r\000y}{section.3.4}% 36 \BOOKMARK [0][-]{chapter.4}{\376\377\000B\000e\000y\000o\000n\000d\000\040\000A\000N\000S\000I}{}% 37 \BOOKMARK [1][-]{section.4.1}{\376\377\000C\000o\000m\000p\000i\000l\000e\000r\000\040\000t\000o\000\040\000J\000a\000v\000a\000\040\000V\000i\000r\000t\000u\000a\000l\000\040\000M\000a\000c\000h\000i\000n\000e\000\040\000B\000y\000t\000e\000c\000o\000d\000e}{chapter.4}% 38 \BOOKMARK [2][-]{subsection.4.1.1}{\376\377\000C\000o\000m\000p\000i\000l\000e\000r\000\040\000D\000i\000a\000g\000n\000o\000s\000t\000i\000c\000s}{section.4.1}% 39 \BOOKMARK [2][-]{subsection.4.1.2}{\376\377\000D\000e\000c\000o\000m\000p\000i\000l\000a\000t\000i\000o\000n}{section.4.1}% 40 \BOOKMARK [1][-]{section.4.2}{\376\377\000P\000a\000t\000h\000n\000a\000m\000e}{chapter.4}% 41 \BOOKMARK [1][-]{section.4.3}{\376\377\000P\000a\000c\000k\000a\000g\000e\000-\000L\000o\000c\000a\000l\000\040\000N\000i\000c\000k\000n\000a\000m\000e\000s}{chapter.4}% 42 \BOOKMARK [1][-]{section.4.4}{\376\377\000E\000x\000t\000e\000n\000s\000i\000b\000l\000e\000\040\000S\000e\000q\000u\000e\000n\000c\000e\000s}{chapter.4}% 43 \BOOKMARK [1][-]{section.4.5}{\376\377\000E\000x\000t\000e\000n\000s\000i\000o\000n\000s\000\040\000t\000o\000\040\000C\000L\000O\000S}{chapter.4}% 44 \BOOKMARK [2][-]{subsection.4.5.1}{\376\377\000M\000e\000t\000a\000o\000b\000j\000e\000c\000t\000\040\000P\000r\000o\000t\000o\000c\000o\000l}{section.4.5}% 45 \BOOKMARK [2][-]{subsection.4.5.2}{\376\377\000S\000p\000e\000c\000i\000a\000l\000i\000z\000i\000n\000g\000\040\000o\000n\000\040\000J\000a\000v\000a\000\040\000c\000l\000a\000s\000s\000e\000s}{section.4.5}% 46 \BOOKMARK [1][-]{section.4.6}{\376\377\000E\000x\000t\000e\000n\000s\000i\000o\000n\000s\000\040\000t\000o\000\040\000t\000h\000e\000\040\000R\000e\000a\000d\000e\000r}{chapter.4}% 47 \BOOKMARK [1][-]{section.4.7}{\376\377\000O\000v\000e\000r\000l\000o\000a\000d\000i\000n\000g\000\040\000o\000f\000\040\000t\000h\000e\000\040\000C\000L\000:\000R\000E\000Q\000U\000I\000R\000E\000\040\000M\000e\000c\000h\000a\000n\000i\000s\000m}{chapter.4}% 48 \BOOKMARK [1][-]{section.4.8}{\376\377\000J\000S\000S\000\040\000e\000x\000t\000e\000n\000s\000i\000o\000n\000\040\000o\000f\000\040\000t\000h\000e\000\040\000R\000e\000a\000d\000e\000r\000\040\000b\000y\000\040\000S\000H\000A\000R\000P\000S\000I\000G\000N\000-\000D\000O\000U\000B\000L\000E\000-\000Q\000U\000O\000T\000E}{chapter.4}% 49 \BOOKMARK [1][-]{section.4.9}{\376\377\000A\000S\000D\000F}{chapter.4}% 50 \BOOKMARK [1][-]{section.4.10}{\376\377\000E\000x\000t\000e\000n\000s\000i\000o\000n\000\040\000t\000o\000\040\000C\000L\000:\000M\000A\000K\000E\000-\000A\000R\000R\000A\000Y}{chapter.4}% 51 \BOOKMARK [0][-]{chapter.5}{\376\377\000C\000o\000n\000t\000r\000i\000b}{}% 52 \BOOKMARK [1][-]{section.5.1}{\376\377\000a\000b\000c\000l\000-\000a\000s\000d\000f}{chapter.5}% 53 \BOOKMARK [2][-]{subsection.5.1.1}{\376\377\000R\000e\000f\000e\000r\000e\000n\000c\000i\000n\000g\000\040\000M\000a\000v\000e\000n\000\040\000A\000r\000t\000i\000f\000a\000c\000t\000s\000\040\000v\000i\000a\000\040\000A\000S\000D\000F}{section.5.1}% 54 \BOOKMARK [2][-]{subsection.5.1.2}{\376\377\000A\000P\000I}{section.5.1}% 55 \BOOKMARK [2][-]{subsection.5.1.3}{\376\377\000D\000i\000r\000e\000c\000t\000l\000y\000\040\000I\000n\000s\000t\000r\000u\000c\000t\000i\000n\000g\000\040\000M\000a\000v\000e\000n\000\040\000t\000o\000\040\000D\000o\000w\000n\000l\000o\000a\000d\000\040\000J\000V\000M\000\040\000A\000r\000t\000i\000f\000a\000c\000t\000s}{section.5.1}% 56 \BOOKMARK [1][-]{section.5.2}{\376\377\000a\000s\000d\000f\000-\000j\000a\000r}{chapter.5}% 57 \BOOKMARK [1][-]{section.5.3}{\376\377\000j\000s\000s}{chapter.5}% 58 \BOOKMARK [2][-]{subsection.5.3.1}{\376\377\000J\000S\000S\000\040\000u\000s\000a\000g\000e}{section.5.3}% 59 \BOOKMARK [1][-]{section.5.4}{\376\377\000j\000f\000l\000i}{chapter.5}% 60 \BOOKMARK [1][-]{section.5.5}{\376\377\000a\000b\000c\000l\000-\000i\000n\000t\000r\000o\000s\000p\000e\000c\000t}{chapter.5}% 61 \BOOKMARK [2][-]{subsection.5.5.1}{\376\377\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n\000s\000\040\000f\000o\000r\000\040\000C\000L\000:\000D\000I\000S\000A\000S\000S\000E\000M\000B\000L\000E}{section.5.5}% 62 \BOOKMARK [1][-]{section.5.6}{\376\377\000a\000b\000c\000l\000-\000b\000u\000i\000l\000d}{chapter.5}% 63 \BOOKMARK [2][-]{subsection.5.6.1}{\376\377\000A\000B\000C\000L\000-\000B\000U\000I\000L\000D\000\040\000U\000t\000i\000l\000i\000t\000i\000e\000s}{section.5.6}% 64 \BOOKMARK [1][-]{section.5.7}{\376\377\000n\000a\000m\000e\000d\000-\000r\000e\000a\000d\000t\000a\000b\000l\000e\000s}{chapter.5}% 65 \BOOKMARK [0][-]{chapter.6}{\376\377\000H\000i\000s\000t\000o\000r\000y}{}% 66 \BOOKMARK [0][-]{appendix.A}{\376\377\000T\000h\000e\000\040\000M\000O\000P\000\040\000D\000i\000c\000t\000i\000o\000n\000a\000r\000y}{}% 67 \BOOKMARK [0][-]{appendix.B}{\376\377\000T\000h\000e\000\040\000S\000Y\000S\000T\000E\000M\000\040\000D\000i\000c\000t\000i\000o\000n\000a\000r\000y}{}% 68 \BOOKMARK [0][-]{appendix.C}{\376\377\000T\000h\000e\000\040\000J\000S\000S\000\040\000D\000i\000c\000t\000i\000o\000n\000a\000r\000y}{}% 69 abcl-src-1.9.0/doc/manual/abcl.pdf0100644 0000000 0000000 00003324355 14242630063 015373 0ustar000000000 0000000 %PDF-1.5 %���� 2 0 obj << /Type /ObjStm /N 100 /First 834 /Length 1582 /Filter /FlateDecode >> stream xڽY�R#7}�W�qy �Qjk���f)*� �\s 6l���h���������j43���>��,g�)�,��3�$��3� �i-��̆;� w+�^ Vhדx��-�s혴L�p�qŽ��\r���� +� ����q��V�0��� �W��1 `�xf Zb�Q��{�8<���[f @�dV�jMC��Yȳ�!�� �i��P�A^�� �q��%�P�{������PAb��B5[x\m�&7�w?q��5��S�Ùr����(4����24eh��k�����<���947$xLC_��FM�WI�[k�C�F�>=Dp}Qʨ�(sB�#3 �C�й��O$=]�2f�+�r9z��� �?��íz�?S�n9��h�p]р�+�W�̯�kI���`�P�\���c.�M�y$1E���T"7�v�#/鶚��vm�ȇ�O�I��'�^�!�R���'=����lUvB|Vs>����{Y Z��?�>7�c���nj?� ��O���z�@>&1w��E��8�3l��zudΗ��i߯A�ɦu6�f+�Gt�/=뾬U���6����t�R����/$i�J�%f/4��9����q2����u��vٸ�U>����&���T!0j�x�+���I�� 5I�U~�@��K`;u�Q�M�\���vN����&}r���|� =o�q��)U� �Q߇�c�)�9]��1(��.�D4J��07.f�j3��Co�bP�Jj�%�~����vo��D�e~�>�'�*~JcgS،_��K��Sf[��:� �s�a��h� "��Mc�R�3 t2�=�21�SZ f�r����L+�v?t?��ޡ~S��o�応��̺�bͰ��L�5�mN~�f�N�G��I�ڣ4rJ�w�{i%;�:��l�I��KĨ:c�@�Av3{���٢ ����"�/ Ǽ�������S."�%ݽ�}��4=ם�%)\Ҙq�����-��$s~ў�t�IA7[�;�+B�ۋ ���o�w2J�H����~�(� ���eo�k4�����kH5�~&U��lQ�4�����-{���y��Dz�g�ΒZ�w!�)> stream x�u�?O�0��~ ��!�}��xlQ Bt�� b�� �������]�b���{���9y#��.�?u�,�[4Dh�B��9Q &�&��*E�#y��й#-$GX;;���>���?S'��F*�]l;(V0[O_���Vr"3Ja��aXb��ղʸ�>b8�6_5�0&"7�ڋv_4�P%4�~�l�z�c�OٵM޽�&w�kXy7�m�t ��zo�jD��\�BHfJ�w9�޻<�@k�<�޶����,�$֬6x����2#���ٮ�1&*f���������6����p� endstream endobj 290 0 obj << /Length 63 /Filter /FlateDecode >> stream x�3PHW0Pp�r ��w32P�Գ432SIS�4P07��301UIQ��0Ҍ ��2��G�]C�Ei endstream endobj 335 0 obj << /Length 1242 /Filter /FlateDecode >> stream x��Zے�J}���y��W�~4�85g��ԩJ�@�* 1��������✌�墶��^k��#��`�}ӻ��E�6w92zCC@� ac̍�����$$����o��;hCC?�������rI a ;jE�m���ň�ҫ�w�ȴ�|�����M� �Hm Hƾ�y��D��I N� �`|��B`����P!N�����_A�a���� �|���M� ���]�������q�^����q�T ���� (=�%���M��h'c}�T��ed)k�����5�t;����eq]��ԓ���X �7XWҕ�,S?Ĺt�{��svݩ�ւ��� �}��[�*TE-T������p 3A�r�;*�V��U\]�/W�\e�W�,+o�d7W�o�������0Hb�0�E� "E�Ʋ�����FϢ�D~��P��A�U+9��ʀo������*�Pc[ ��;���n=u;�P��t*S!��c0���*$� �'!oP)�y�f&��әiɝ(�����v��lu�ҪLW���c���yI3���E���En�l'KQO�s|_$QCXc���!��d��3L�aM+���?3�x��5�{ )�VRt�q0�JX&Di,�B��r="wQ zʯ@�x�L'�L�S]�y�#��s����&-��>u���?���ݱ?��E'�>Ȯ����g® �%����ċk��N/�@�G�W��h{�]�'ՙ�_�>8מ���m-“Eu��C ��� Qg�Og��r���)�K���4:˪'�|D4���"��Uz��w�M�d�?50(i2���r�o�f��;� �|YuK� v]h�uv�� ���N#�뾗�ˀ���+��y��� �O/�΀0|�\��h�[�'-�no��@��2B�s����w��3����U�{қ�J G[`����n����#q��+ql&�����z�n���^,v��18�_Fو!�����H|������|�K endstream endobj 371 0 obj << /Length 1711 /Filter /FlateDecode >> stream x��ZK{�8��W0�� (�hv~�uǎS�t�~�,[N����63~$$Hlh��N'�E�K��^�{t�c�����3=xu����1]�1|'������h�֟ӷ�!��z��_�P4鎏���i([8�g�v ���̸y9y-�"p�C����� K��찫f�[ ��> k� �6F����F���$�� 1,��)G`�-�u0���G,C���y��[������I՝�<�W4R#:���y���:W9���ߜ��w�h!�7햅g�"d���1Nx���V�6���E[Pa[��"��n�ӳ8�r>�j����[��C��vשŬ 4�=6g�D���yoZ$�}`�v��:��h[k�\a4O� O��.k���G�OuͶ�"���ž�W {&=c�P�p`�J�>��t\�v|��Nj���AHC����8�S0����gL�R f��%�-�҈���x�$��UKw8k�zώ�v��Y��J׌XN�Sa�3/�,W��I��'�j9��'���J愗�l�i����Zh�"�+��)���YD��N�q-�4*�������'�΅���K�)K�Ƹv�k_>�,Ö�QB�:���,6P���ߝ &}�`�Ԛ��<[���u�t�~���a� *��W�ʋ��%��8� `T����+�^޴'�������t�}���xگ�߻'`�N�E40�wX���%���AP�n�q��M�����|���o�'�v+@���FOR��j���x$��6"�B��bW �������D��\IԴ��J"=U�/�h6_l����KU`�P)]��p���*�>a ��uj�&D�(��HKI����l�2����Z}��D��y�y7�:��&oj9��g�{I';��`���gt�"sgy�����!�K]�K��/���z�~��:-�}s���$�/h*".K��~� Z_� �s�ٶ��wjA[Vk/�Z\/���EͩV�R/�����Y}�Ã�gR��p9.�d����ߔ�;Q�i�욧IV�.��������f�����[���K�S�)��HҪ����0�:�ZՇ<��񾹦�ʫ��G��C�%d����~�pN��Nwh�(� �=�'9�x��$xʛKw�a_���Gs+et��Ө%B��J�x��;OU���,Oҫ�W��[T� ��՚�v��kN�݀@,�����g2/�M�-@���ƨ�n�#���Z�!��G�`Q��Q� bz�F�¨GJ�����+>0��E�!�#�-�;���waXQ�p�q�T~�}�j �x�o�4��i����D��F,H9E��Ar��Z�B�GA��v�}�_�P��S1�������x��>�U�h9Fu��,�e5~ȥXS�l캆����2�Y:�Kզ� Th�q :p+�B6S���v�z�H� aMI#g �|l(���`�-��r���!`#\5���?ZA�W'��K?��+9�d���⋢4u�� P�����dz�rM����lY��u ��H��5��V�O�yڄ���m��� L�t� ���Ǫ֦. �} tq���e��0K� ]R�F?/�@�t!p�|�-�ɢ��� l No�I,�f9-�D�*�]���~XN3��D/����y<�V�`�)�]Ƿ����ab5�χb|U�_5�,�v���z�*����a��< endstream endobj 203 0 obj << /Type /ObjStm /N 100 /First 888 /Length 2434 /Filter /FlateDecode >> stream xڵZMs7��W���ז+U�m��k]���W�A���YETIT����� �����9��o��Fc�q�(g�"B�M���?���Y��P{E�k�%<�Y��{�Tpv����A��T9����x\X\"1.���V�)��������p�n�p!8�%��K,eadv�AO��y ���# G�G@N(\r� ����?�d�\��AE, �c(��2R<�2�G2X� '<����%�-|DA�% ¹� �r�lS6�n�P�$7F� r�!�� P��aT��9��b���Y�c9\X� �=s��jH��� +N��2#��QzE��J��<�<h�c����l�'�� 5��B���? s�� �lhDxq�٨BH�(�D NV!��-h��*:���"%®���ɱ��!�UL֎�MTɔ�I%�@����#d�xb�"y���*%�1L4yL4��G"�,"5d�x��c�E�#Xf��Y��hʳƒ���1k5,� �����s5>V��Nfj|�����ϧ�k�ښg�F߽����1?J�Q��)����b*Ŭ��ΰiMg���K�J�H�Z�=)��^�}����������'�گ�_�T��6��m��v�t��\��F����B��5���ׁ5�^���e)�7����E��n<�^���`���e�t��-v��5=[�:��@�������7R���N���'!= ����"�˶�d ��=�V��V~���_k}��;k����g)~m/�b�m3f���l�����6�5:��A�u���̀��U/ ྡ�5�L�1� �.��ۺ�/���5�e���|f�BY�s����Ю�_�v8o<�k|�Ҥ�l�n�x�����)ܜt���ۏۤ�@��ڧ��E���:��5�O�����K�6�Ga��,ɫv��ߤs��UF�m�O��h��\ٓ{�/��j۫W�5����[vW坟V��nn&�ӏzo�D�?�%'���ח�t���-K��ɋ�L���mW'�&�sb���m�q���T�;����p:/\�?�O>�L������xv=�\����F�h4>����o�'weGP�z=�����}T���!�{?�-��],�*��k{���DD�|}u�~S� B6� :]jwzJu�@{�:���ܠ������x2W�����L>�U�X?�lV���z�y�p�![&�-̉���e��%��{��3@��}�p�m�C�kjk�j�0R��=Զ֮�Tk���u�u�u�uų�V<[�lų�V<[�lų�Vlh6z���0����zr�����0�$o��1F�������� �Ӕ4Ž؄�֒׀Ӓ(�V&�a`�Y�j7�Tz�I�!h���0�8K�M;����qА�(S�,I>"�R/65�:)k#�E̡(ٮ�p�u��g�c��Kl`��������>%H�4@e&S��b1�贕 �(|M�\;�t�4tJ��-�n˵-��[%a�H���l����6Yn�2�"�ĺ$u��.�� 3��q�����3�,��{�C�%��%���3� 1�e��4X�Y�������k��*�aV�GKrP��s[�BH�IlG,���γ��U4�q浗=�s�.B;vg�B�P�wOBApR��Q��PM�Nr�ga�>w�e��c�DK���b�F�\�!��}��6���E����ŪB�� �+�����CGԋ�c=�{r��I�(�69�a3���&��p(H�߱2Gߋ��2련�f������6�a3����xm�����|���b3�� ql��x�]��X(,��C&���`��b5YVƤ9Ц�K#2��D(F>��^� ��=�$$�#�l ����,Dۋ�b���^�) Z>_)���aԩ|�ҕv^jӝvF�I�j�y!y�'�F��Ln�+�ܐ�2�+_���%��'��'��'����Ϗ�׌(׌(׌(׌(׌(� +�����+��x�����+��x�����+^�x�⅊*^�x�⅊*^�iƶ�!F����G��U@d�7,�Q5�ށ���W>"�:f���0oua������a1��Q�6`�ɮk��0Y��h�Y�i,aY>��ڥ܇�Ҁ����kؕg��t�h"Œ|�h��!��u`/��F���$' b���D�>>%K|�$$��9-ۈ �y�N��U'!�:F�m�~������V��wC�Udb�SB���>�ܥ�0����O�t�/N9h�i,D��9-県텄���� ]N��#��o � endstream endobj 386 0 obj << /Length 3295 /Filter /FlateDecode >> stream xڭZ[w�8~ϯ��*�ԪHQ�Է�q��I�qwvvfh���ؒG��v~�u�C7i�<$"!$A�Å�Fw�h�������E���0Oy:�ݎ�h$�,�D2�-G�o��f�������//x4` �X�,g�,'����B�ca�$��-��K��7Q��t�O����U }:�e4�{���4A����'KӘ��i 1�VCDa,R����K���خ�͝��阧qP��< �P�l�k�����h��g�m�����VegFl���u�T��$���$�fQVw��6z9ת צކ���Q�{�@�i�$�1��d�y�TjA3�����ۂ� ��i�oD�RK���8�/+�8�2XQ����V���تtO�\�Pfq�����P���$�Z�۪��D�a����i��O�,���'a��YU��n��P��W60��FQ(s����3`{'[9�i��e �&Rٛ|�<�7��� 8{��v8sq���˵Y�F�6�,�t�6�uA�MIF����h�oOYP����r����@�ݍ�����H���,��z��H�Q��7"��Y`w�F��ܡ����v��m�v��j�=��۲����P^yo�;�ꯍ� �����}��ڎ����ܕ眲,��C��_o^M?]�?N��N�>x�-�P$��m��Y'�YG�[G�,�1_�ֱ7�����'<'<����`s�+I�ϨF�Wz�Um�Y�� �`���p�#��؊����o�����������,L��`j��)>w����Y�[٢�las���A(�U�HkI��]��X p��lj �$��*�S���k��1�� Ү۪��J�Z{��\Â��;T'lI/�JQ��q� :,!g�����6�5|*"ICK;4v���ڨ(�\Y�4�qg�r� j�[���_�1YA>`�`F�~�/�&S8.��֡�9͟�H]�-d�3�{I ઈ�s+/`c�T���IM\�0��R��ܙ�S:H�e`jz��8 �eq�+�m�c��s��{E�[��vN�߯K�Xi�(���Sp�Ɓ�7쀹{u�m8���� ~��/� ~��SK׬����>7ʸAM���$m���t|�CO���.�&�v�D�$�����h�^�.LU�<�细X�UYᖎ[�(k��+t{��K��<���,��c�Y�.�ShQ,�g(0�j�U�~��3#�Ӧ��c��L�\ ����w�����y��.ũ�� �Ti�9��{��2�[X��?b �,�-\��PxSZ��ܤl �o�ǀ��%Q����E�N�Ɍ�/Uw�aw��d���: ӽʌ#o��+DIr 'ż�0z��d�r��=�:��;H"ɽ�� �u�_�C� l-�[�` H�Fb�97���G]�Rnua��S"K¬�2�� 8�H����$�C����s��l�`/�s 1� ��GB4H�ޅ��3᫸0H���>9��Ԓ����#[Id�f��ҵv�[�:;R�cY6�_}V*,L�׳��C[��Y�� �3q^�-� �/4���� ~�3�� G���� ���L>(`��/����M�`圑sx�eWX��J�ֶ�)Y԰#! �<��պ��mJ�5Ql%�NJ|�{W��yA���RюApsOX���,,�r;��kA&}W��R�F����T����rI�.1d.#���������0͍����Ы�Tnw��& z1���b����JE��3�C�v�X�ڨ{=VU��yL �a��ש��//X�Z.�̞�PB��)s�d��G�BfݳI�p���*�#�2?�KQy,�-4@��t�y � ���f�+��� �:K<����A�Sq�5�6�������@?��I��ɓ� � Fle,DF���إ�%�'|��`h��$�<,-�Ls��!(���:Zi������'�]��p�c!�� �Cq ~�'��w۵j7Tn��on�{����`cl���Y��wj˂���L9?���D_(��w����t��l�ϫ��,�dX�W�����O��'�v6[��!9��i]9,ُx �}g[���˲��:D�M�mQ�ty�������8l85mɐ^*�R�܀;��k���u'�P��$�����\����*O�Lcq�F��΅.�Ll�?T��XK��-��x9� �x{��غ �G��rL>�n�ۭ�K���Y������ʛ�W�ׯ'�w��c���M��J������$0t��06v�qr� �Rpa�Gfuy}v�ӂ�3B=����M��g3�*s2�~O�X@��h{A�������z��o'���;�.�x���?L�o' �<9iJ.�t���L�C��d����2W�ɜ/F�7ͬ�16pŏ���A�q�t��-s�U[��"��ۣr~š�~�t�4��,��L��bxK�]��ڴ��4�r/P���}�F�jEw���|c�O�g�!τK���Aa/B�T��S���s�d�ҹq �@Q� �����E,�� &\��u��;��Z����?pV��ak0������S�s�����r���]{�c����r՗�Z������*O[��� &S"qQ!�lʪ-�4��[,`�cr�V�-J�]w�}�굓Aq(��o�~n��.l����z�lL���ӧ{i�c��N�> stream xڍUKo�0 ��W;�@��e�>�� �u@�����J�ͱ ?��ߏ�4I3`'I4����Qf�CĢ�g�ʳ��`QA -tT���E�)SiT�������B{>Rk�X���͗��Ky�<�X@�X(qN�4.&�%" ���2�Y�p.R�u0�ji�Df)������� ELK64]�v�]�T����T�^��sI�!N�f�(4D���=�3��ƀ��`�4yt_���r�?{��7vi��9@�q25~�]3N�}c<^J���aw;�3l�t;�=�r�rB�;��;.յ˲�}g����0B�#�v+�_��8V�2�Qj�5\S�︻�M{��Ӊ*�I���K?פ�6�}�* �g;�Pտ�S�)�A[;��P)�8?B��TʩL2,4�Z �>+�\�f���e@�D��|�ta,h&���N�n����]�W/:X7������,?� L��� n���Vݰ�rH�7�y�pg��� k7�ƅ@�~��Z�.#N��6}c&G+ƽ�|XWsst�uޛ05��5��=�; �beJ�%\S �X�ι�����Ǘ֍�v=���>ضj|z�;�m����y�ymm�3�' �vB��V���o�O�@H�Y����v�K�y�$�>w�l;i�4S�!�Gr�1I��X���6�ے �1JB�G��G��0e�t?��q��M��� ��r̻')��������I/=��l����/5��c endstream endobj 416 0 obj << /Length 2619 /Filter /FlateDecode >> stream xڭYIs�8��W��DuE�p���dRI���;�t�D[p(R��nW��y H�۩9$@���-�[x7^�? ���˓��1�S��"z��^xQ )�r�}��6ٮ���Rǡ/�.?� #�$�x"�&��|�C���o� �HݭZ[�|N^*�HE�X(ED|�����RŁ�6�jI���n�0�~�͎Ga�1#�R)a�3��g�f�Ձ0j��$� �f%_m��"���B%~���{u=w��B���ڳ��d��وb�d�h7Y���t�T��v���� y�[���!Eo��*���OÐi}�u�e�J�<[-T�ol���#���E���� �J ����Ĝ(!a� %h���ߴ��;[�� 5�i��Ə�5I<\�V�v"t�k�HR�*���=: � 5����X7 �99 D��?��7�x��{�0�z�Hc�Г$xN�0�3}�D�O0`��A��ݯP��o� �-V���� d��y�zp��S��<�ԴRΒj ��y��7��aJv��Mմ��� � ��c������������n�8�[��Ug��]H�g#+�<)�Ƭ�T!�����vyy���̰eB�>��j�d�>���$� )�Pў�nJ��Y(�(=$���L���L�5Ӽ�Jc�R-�J�������� S��a�5��!I�4��!!@V�`q��8�K-"�����k�z@&]����ں����_\�����T]���k��2��([����������k��6[^���S��m�2KՀ�W �F> stream xڵZYs�F~��`�e�Z�`��Y�嵎�gSI rH� �ʯ�> �rj��Ź�����g�L�g���O�7�\gّ����j9�� mGy��r�N��>� ��7pm/rar���z~v3�I)-aOgAZ��ZW�>��_]�2o�m��A�ם�^`�*�B������`�>�Xjh�e�����k��u������Mou��8[r��h.,�*�ӊ�Ck��'���*7s�!��C�k�(l�8����瓛���������J��f�/���iޮ�UG�᎞c�n������c�̤�ہ��v���+��r��R ��%�4�#����n�~���>;=�p~:���ؑl)K��j$�nF�w�p�U¦�b�K��̹��,��}1� +ga� 4j�yP��9��wG(X��p3�F6(��I��T [�nOt2r�A�I��b@4��� �����:���v>B� �v����A s �%�����U� ��J*�r�o��&F�����Ο>MCI�F`CI��eWz�[x�&�i���l���,q��܈r��;(� ���.�E�)��.u�%�D�6��̄�#�>��gʁ���)kU���iZr�� ���N���|(Rᅶ��N~:�2&SIj���Y2�?�� ��\ޞs�4�nr�$h�XJ���� ��#�v|�����X��I&��BC�����鉽�.f���s�o��9����0�=�vt��y�s �������?�q+ J�@iA|0&‡�F��g�|$h���\�i�H*��GD ����zC�>'ie�j$'[�@ɈhR2���^%Bm�6PK0$*�cL�\;T-��Ҍ��G�#l܎���t�}°�w�67����h.��;�9�&�9I^0��M^�K.w�R�������e�D��b3�^7����39r��� [�.�p=8`6���AE�(�藁�):���̂�E����8�r���������/ �U������F���Vtl�C��a�oǔU���xRט�?� nZ鸪 (Q"��f,~���y�,W���x����l��ك���\a{��WG ��H|���W�b$�&��Mi�K2�}|3���2����IY"�m>C �@�)��PȬ#�A ǔE�8R�  7!�l�w;?���P��=?��E�Â�W ��,�)aٜ����]���w�Qv/�B5Y1�e������~��Lû�K�l�1�6�4�0$i���! l���U����`�ʳFs��z7���8x�- ��3�e�� ����c��Ϸ:�~7��F�u��M K����px ��=Yo��0ٺ4�0zN*��bAk\�16�O[ܟe���������dg��]���_]ގ�����#��pG�g�|��s�2�_���דWܧ�������zd ��~Կ�A>uV9�9 a�v�������cLR����v1���ԃxm�K�"�AxE��A�(Spm�I~���Ii�/�Tf �E]F�O��˲�W�~o 겗K([*�� h�%X5E�O|I:+�Ba�,p�E � ލ�y�'+�U�XV�-1t��*�b[r7@M��B��C��1* [ �fȃ�����\Cl�i��(���%���i'��Zr��B�E�%ޓ�l��*�������!@�����H�*�E�)��b� ������;}=��������a{jԊ�-FA�2A๫����n���>v�/���7��΀:�!`��.�6�!�?1A<`X�^���+�9���k��B9�VS̍��'Qr���yBw+;����2��s �<����%�!�luL�1��f�Ȏ��f�4]���3g�Fn��x&�� �^l�ت{�8�!%Ik�*�jL �W8L��5o��I: V��=EG�����kM�%D$[�����!�� ��������|���.�����,`+T# h�D���iC�\�.ʹ�[{B�:�ӹ|J3���n�g=n���Sz��Sy����n�T���Bզs ��Ќ�jO&�P�86�_ub�3�)}pf����Zf.5'�i���i ����67Y*�]�A���.bz‘�a�I):4�Qpk�W l�gD��z�� />p�R��:g��ɽ[3�l^����;��$߃� �/��k�d����zI���]��ߏ��v��A����o���� ۸��ջ#���P�D?r�|k�E�a@��1!������al^�S�B���.�������Q�{|����xq����}��RYի�����t�Rr?42ML��^��C��AK`3��t\���l���78�_ɩ�b��?���?�����#��B��7B[N'�o��_HwlVmG��L�N�{��B�(pg_ƒǵC!{w�����$�o�?��� �o�ĠT����83wY����\e�7I{�,K�'3�լ[��NqՔ̐�ռO�� ۚ�[Xk3��ϳ���L��Qɳ]%�:�߀��sz��m�Ks�����u�'�w� M��X�m;���4@p�ia�qߟ����-)3p®�4� �]��G��2�V�w��� ��;�t][u��_>ݎr��-�Hv�k� a<��} ���� J����zF��4 -�z��A����������4$ ҟ�T��#G Áa�<�1��h� ��r֧D H���I�ޞ�x���p�<��h����=�Q u�n!j�[(�5�%P1��b� ��2_���#?O���A�"����5����&�j|f�� 暙:�e7����&�N�@��&�%g��ĕB�ꦃ�<�!6Hzc�&ԥ�� ;��� !\��3����E�^��p'�ͧ R�H �����u�Ƿ�݋;� <擑7�d RF�Һ��U:L�+�⇺G��{�B�X�[�ᆾ%(��}�%��#��^f����睌����R�ŮH�w�9=SE�ިhKn4�?)�b"^����=D*}r���D�u�TY�s0�yc%��&��i�O������R�~�z1������b����W~%^$ ��/\�w_nNFy��ᴦ�"��q���s� ��y��Vz�jƉ���ñ]w`L`�ɮN���W*X�*��μ� �{��T����q|�Hm�cX��qU���q��c��l��{W7�Z��C��_�O� endstream endobj 445 0 obj << /Length 474 /Filter /FlateDecode >> stream xڵ�M��0���>��? �q� �FjS��كK �!v�G���w���]U�6�/`[�~������2��c�ȍ|��E4t��t��0s�K� ���k���|L7ۄ<��y���c�bl;��}�L�y�]�� �rx��Hw��7�w�q4q�j��#��۾�rEx���ys0a���8X��M괔����>.tc�$q���F�\ ���ozS��Yk� і���I(p#��?�f���k�dWNI�ԡ��.n�>��jK���T�F�.�rΥ6�e��bZ㸗��k�����t�%���!�E�E�6WM�hZ�NZ����;�ӽ��#̘�(2=�y�U����|'��^3���6�%p��[M4��SO��,��[Y���Jv�]����Q.�O)���&tԥ��`�j�u�-��K��ua���`CT����W�s�wI[>�~��3,��_���t��l�w endstream endobj 450 0 obj << /Length 120 /Filter /FlateDecode >> stream x�]���0�|�+��p�ɕ� X���c������X8V���^ ��QM�3A�4�@�B�쩪��l w�K�G��8������i��U��1F�+R�v�tq��|Z[�i��~�٩y/K� endstream endobj 457 0 obj << /Length 2126 /Filter /FlateDecode >> stream xڵX�o�6�_!`{���ᗾ��vn�!i���}�e9f+K�>�����ȣd�QZo���#yw��ݝ�w�Q��u�/�g�%�8%a�o���T�$ ���{�Z�m�U����O>���Dq���MJ8C�۶(tq��/^��v[����<�vp�)�-{.N\B*"`�L��#C�oU:��y���ϖHUvU� �5H�g8��*\�@��mݪ<�I�6x��3ݬAY9�yB� �iN��O������I=���/�Z/�[�r�0�YO��r�y�وSABy�M#I�E�œ�g�"B�^r��{� �WƱ�Pv�ު�ea�+��qok$�򃡐���\�F��"�zZ?�M�A��Y�n�h�-� �k�������$*�eE�^�ԩr��|m=C��B���*p��/��Y�6VM�_�X@G��6Ca�FK$�pKM���Q��Ԉ��X���𷳟���QB=�^u� ��o Y�$�Dl�M �ӗ�!.������d�}������q����,�������������+*�&t�^ߏ��aq������]7��g fҬG ��ʌ�c^��( ��O�;�2���.�* v��� ��`�-Y��x�0rүl�]C����{�-1�������C P����� #��%{7��vjL(I��m���� J��tw��v1�hj�F[լ]`q� ؇8$�Ob�r��_�T�QM�s� ���_��`�܎쭆�D��qj��`DO�{����,������� ޟ9 q��o�G<� h/�]�p�Uھ.��u���UaD������� !�#�A����$v��D�l�,�p'�������h�f;��\Xw*-�Y�HU����p��:�s7L+�m��;�e � ���;���n̻B����Y��8�"/��B��o���P�6��(a�h[�r� ]7�j��R�Om�xf���O��{/ȝ���< 86����d4�;e�ʂ�6wl��G.�88 �8öq;x�Q��* �8�r�g��Y� պ^oX�� u�4��o�C�0aЭ[�Ia�v�+���ܘa��z_N�ZI� ћif���i=V������U�h��AD@t�`1f�qi���,� �G�_Z�~�M�?�>`D@�U��6pЮ{pwn-X�BD5'%�#a$���i����NVRV���Q��m��,��g���dB��?0�&B��e���0��y�ۢNOM��ɒA2��1�ڭ�t��> �]�ì)V�_>v`6� �@q��pr;�PD���L�c`�]g���W������"�ԝ>��u��. 5l�- �u!)m+�/���#�7��`c�FUM�E6�"nR6m�B��.TQd�iz8�F���x��¾����"/���TD<&���� bz�*3!S��|oѧ�ST�N�±ή���k=PV>�$�D�f�"� $�����3�tYn������� � +��L�@ܿ~w{�{X�٦0o�$t���x��;,@��{��|�r���2v��F� �8�����~u=�����?�=�=�t% ��!���g����+:1n���kJ��� �%�#|d��)��cuii���<'�s>t��|O�}��� ��3�� ��B�����3+ W𘱪�� 0��h���أ��� z�]t�3��G!H�,� ���zL;72���z�i�@�@�4��K��Y�m���^�Bc�?�!aO�A����aX+�� NƇ����?d�E� \�i}*7TL���>��7��:��l�Ҵ���H3\���L�p��N�"��IU�vR���paf��m���Q��2p�ݨ�N��9�}��\S�Rs��&�;�zg�X��m�GT��D�Wq����W�nn^��qz}�v6}q��כ��9���?� ���Vp߹�f�E��cWGsB~�t��;������3C�1��`Εn�����?��6��˴�X�JbTȽ��_�{3t�1���2{�������1/>ʰ�c�I�$f�o3��0�����~�> stream x��Z�n�}�W4��!=]�շ�0� d pA��8�(j#�vri)�sfge���Y�C��;����U�U��'Zs���ĂQ���Q���1�d��\y?���{v���D��xSÛjt1�I ��I�1���*~D'-b�lNC�{sr�b���F�_�S���i�r�&�,�_��c�|�9m�R�� @Pp!/� Q�̂� �c%�fx)���v��9[�_�3���d�&�Y XD�h@���BP0f�������? �� h,s��BM7<\ &�K{� " :7L���Nu��-P%�\J�'1K�n �R�4k�20Y��,$�Ux+�LK[(.W��Y퀶��2�47�L�H���A�%(@c�%@O}���$�E� �,l1�Bh��j�])��Ai�rF��4,�uU"V�²|J]%X���d���\o�L�}��k�Z�`��A�+uXW㏂�6���҈��B+�k>f��qb�-�ZPD�x�a��BSC�b�fxO��wC㢰m0g�\0 UR����+P�L�� l�R=��Y���>h�ШxFIH���"ݶy6��;���_X�o��#�'M��� ��� CZ�^����[��g$G�u���a�q��I�v�� e4�t �LB�್���G�n�����*��2$݁q �H�%QzZ�kL��Iwb�}���>bCG߶9�g(����+=M�;ER�6��|'ja�q4`[�[�蘷��S�V�2%G�@��agǝ9O�OA��}Vli�7�8:;��ߝ|���AK�q8"����l��0N�����!�*�Qw�xt�c�:���u����`� ��旧�o��4ԁ��q9�J@)2&ׂge�!�d1_��x�_[=��� u�� �k}���J`�`�h���=?_��Aq�{����^�>-ݛM[�(��Y����cч<�lR��Y��D��G�B[�`�l|- �]�j���� BsFl���x6 ��vV���ə���Q1R�Z����$���umF���%ˎ ̲%umd��<�-[�m���[�:ñw����Ք�*õ��}]������o�=|k��?m�7���<�Q��}��ې���l��FF�8�6�i�0�a��ئ����U�`v�"���� �l$�L�(�EV$�S&R$���0%��Uu�z5�D��V/�(�J �p�wʖz����-Ζ'�&d�V=j}���g��ͥ2&�*��m�H�.��0R#�����Y(}+����uZ���#�L��d�U�ҟ�%@��a++���)�L��5&����� �� �{���,�-呐2a�-��f�xof}�zF�U=����uζ`&W�GzR֬QL��o���� �������^v?�x����\�����{yr����ř_������<���2;8�rj{6.&է�v˭���z�x�'����f��t?�ݬq��l�ƫDq��i�Mrk���X㭘S�k�)�72'*�LG�ҁ�� LJ&%�ҁqE��ix&�\FTQ~!�> stream xڅT�n�0��+t�T W-�$Ȋ&-���F�c�hHt�4?ߡH:v"�'�Ù7of���'W������FuA�d�Nj���B��d�J~��f���'��>p�%G���|ίO�-/��1�R��eY������7�W�g�_���'��$�xAjaa����f9!T�7��Z��������w �U�0Eެ���uj7�;s~��0�o%Dr��@�.��v0YU5j=��h�`���h�1;�g$���4�@��"��ko48C�� <:��Dȧ�Y.�Hu�"�U��6���52P�~�X�*��e�?�ʩ �� ��"��Ǧ�����HN�^����w�>�޸1��Tc���d�ڇ�F[5le����1��/`%)rԀ;GuUs_:.�{.�.g=��z f�;ݻ���G�+�؈�� ��v�f����ǝ�_F�7������`=��!0Q!JDl�c�&�3�(.��}�# cy�W�"�v�N���� 3��X�i�0���7�����6�5����?�J�Vd������L�0Y.�/1�ӡz<���]�ĞLg��U�^X���Td[�'���sl@v�7�S5�s�4�m[���<���s(��U����0T����~�o@�k�{c���q�]�:�a�z�\�n��t endstream endobj 477 0 obj << /Length 2605 /Filter /FlateDecode >> stream xڝYKs�6��W��DU� ��s��8��.��*�`�@q�:|LH���o����Y'�@��������M?]D�}y{�ݫX&Rij���>(� �bU�v| ���nr���fIh/������L�(X%�26� ��K�C�RVS�w<񱞶ܚ��?��Tw��||�K�((T��ԯl�19�|�SM�WC���|�ʁ[�}��v�~S�;n��q��.MN%��#�p XU��^R�=�;n��rS^�,|�LRO�XӾl��p�m�9u��M���W8s{�C�!�蘆*��ڍ�P�{:�e��8l/]v����R�x�q[3�ɼs�F��)��Q�`���r��v���Ԭ+�F�d�s�7�J� �ID ��^�\"6.S ��⥾�Qi��JW/�ߜA��*�V�L��H[7�u4*?�}ro����B�����=� X�Y��E�@`L����|���&�� ���N=�z"h�B��r1q���˦��8VVr�b*`"�̄ �τݺ�����n͍APq�� Mʞ&�G@��̞܋F`�}q���@Hl�o�A�ӗG���]��ك����rr $��بz�u�{��e ۰s�߲ A] W�(�e|�_���U ���������j�-�أ�q����;&5 ����oQ.����0g���5�� �=�c7�m�{���5��"RQ�66�q��O��u���lN�*J���T�4�"A���r�Yq�#��*� �����Ic4��7i��,�d�qnNe�� )/ ����X�w�N�#L$��,uء��id3 �@٨�D g�!o���?l����0Z�u����ށ�0R���E���͑2�;_A1���3:�y�rж��H^x���x�lfv��kф#IN�?CO6f�n�7Cٶ|�����~pL8�-<7LcI�HE������T2U︧��/q�7e�&�gI��N\���� �[Ϯ�� �\�h�7_C�� (�L��C%�l\q����B�|���o�P��=D���ObC��!~W�G�� ?�/� �~��ʩ�� ����ц�����r;��^���`k�7�<�Iõ0u�� �������:K!��~.&��ɨc˂�+���gm���/�� ��h�]�����������t6��~6\�o�����!؞�Ӡ���+[w��[KNe9�`�%GJ�m������/�c�g:J�h/J�VY�2 i���6霖�Ӱ�U���Cv�>55d?@�����i�.�U�>-'H�S�w��A8���X��lj*0`���A���qܖƏAݰ�q���8�7�R��B5E�Ld��>GI4�kC�& �_ʇ���E�\�Ir��*�:�⍷�f+)=�J�I�t��;=�)�-���r��Cp�`�'_� �Q#f� ��x��gl��O'�\� ��T ἣ�� ɵ, >�T���3�,���w_���MR ���5�7$GE�ci� ��E�$Y���l(���5��j�Sm�G'E�A��O��O43Qv� �g��r���b�d�ٔ�IA��Jiu�c�����Z���=��@x�Q�z=~�;[�ǯ�s�G��K��mBʓ�Ve������ Ga�T�r���ь�ʱ��r� ��I��q����'�� ��_���x�^^0�"eUcES�z��J���RE�]<9�홯�Y�"����~?6R�9��wQ_�ފ� d��\�']T��lsܕ�\06�jzD^C��8 r���[#�� ��4Ł���i��#�a��*�&� ��y�d�9��6���zrS�78�f��+ut�Y��� �%��3pl=�gT�:�1IQVp(�ws������o~��9�����q��5d���<�� ��Hl-����Z���, e�����s��H6��E���z ��Q)T O���S�m�w�T5���0��Pcq��c.��,��j�Qx Rԛ�[�P�g#W�23�����~s���-�e�Cz��ex��M{.%pW��[[��K���_�9�T~�C�a酨P���`ߖ�3u��� E� ���[��|ũهš�2����U��Lx��lw�*�'��z��r��e��I����EΤH|��8�"��$��xD�q���b9�H��l�<�3��n��)2���Cz~�m�N�=Ot��]�� �߃kP�|x�k�lM.rDg����M u�n��ڐ�b���i��^��~p��O'��K���%v/c[Ywa����XE�y�а�dlxq �����_�/����̆1[��d�1!͕�3 Nq:?& ���?x�ǡ� :1C�=�ja*��r`���R��� I]?�eS�I@G�^�$(\� �' L��Oշ������!��n(w�R~�¯�@&JU���$J�&mO��?/$� endstream endobj 486 0 obj << /Length 3868 /Filter /FlateDecode >> stream xڭ�rܶ��_���L��!^�Ƀ�ʱ<��:�d�i(.���%7$ײڟ﹁)�v�>,���vpp����&������'߼��&�XǛ��Ml� ��0�\m7�z*<����7/M�4Ra�����ū���ߟ�c<㟜&I�]��ىN�W��2�~��z�ͮ^�3��򧫋w?p����tO�oAܩ2��ls�@���]�0�@��X�~����g?�=������߸�l�8�Ķ�z�Fk����2|W ;��]W� �.ߗC�I��9Q��6�Fu���\��^\n�[Cy[v��@+�;��4JP~���3PaGca�]{r lq}���a�K�`V�4��C���Va����4$Q � ��� c�JߕñkʭOT��6`F�eS�����tk��ʱ�.�/���t/�8V]�%NE^5p���T C�.\`�~ĥ��#Xʄ��"?Y�X���ٛ7+�i��><��vU���8� m1H�R�p!f���i;��%�\_��Gu����B3V��x���@�cV-��NBIv2u�ho�?�]V��{��$��޶�h ��n�����oҌg'��@�P�s�,V�D"/D+"_笋 g9W���Bk4W��1��_;�����JoW�f �;˴w�p�ag"�y(� �����~��Fh��-C[0Q�P�s }H{���E���3�G�c�^�},0ׄ�xMX�kB5�E���Z �I�x�ąU0�w�ZڡjKV0��Y��V��Y�ȏS=�0j��Љ���C��(D��n�!��L<�_�����?��?�Vz*.52~��s�t���[K�^"b2��nƂ��?�z��܌����j�=a����� y��7���faJ�� ֑�a���lL8�!h )H� `}���A�1���-�J{���1�9+d�d��f�ȱ�?e>�_�TӸ�^��H��u��I�w=2_[c��l�^X2�t%�[̭X>�w���~���t���C]�mb�BM�ѫ�J7Ə���\h qq ������(����/(���������(:E.&����Q��a���-��� ����wX��T$�N4�ض"�\l�AFl;k\?�]�X�'0N9�U�۠F���k�c8�5+z3�/yIV���3�2�0�(�������u���~ܴuM�N�X�����kN �%�c�iD�?��iT��D�/G��j�a�4P�p'd�!o��J�|~� R�)���*�5 "�)�}&�n)�)��Ê��1w���ł�}zj��wOߒ����!�5 �)�T(�[�jP:�H�.���|?з�oA_$'�\�i����3������%����@ߎ�TY6��R�f�Bo*�.$�C�@�}[���*@}�Q�hK|I��4#�fU�Q͙̈�Q���05�9}{����p$�K�H��2�=$�n �"�B~"^mrF����������s�k�w����`�=zLX��"_U(�3����O�~�c`[Y�y� a��e���xH��0�ۀs6mh�" }��-��ڞ�Aֶ�+J?�"qd�oۮ<�K<��'"��L�a���=��p���G���|�2�c@}�@����JWB�ďL�&�q0�+�&s٢Sc.0~4�\�!��� `r3�q:�Y�����N��Ǩ}�0Z.��T��7��� X J:P���J�\ʝ��;cd��b֡�Rϥs.}rZ�����K�Z.5H�񞣽P�S^�:�{��f�L`ߪ}5��W���Fz�b�1-�S�;ַpt���$!�f��ɽc���UVp3���B��m�xH:�Uѷ�y��z*�o~�uj2Vjt����k��$�טG�eM��L��q�!�nK��pӀ��ct3j��������c_j��O����Gg'j�Vv7��=�q��Wjq>B�b ^6š2َ_��y3<�[X�L���p�����qu1�`�˪[��쳏�jF��B��N�O� {.\SA�p6�# �O?)q4�YC����w]��� 1}#�ZӾ��A�����z'#�Jۯp�fd��QF�AzN&%"��l�2;g��p��:��4�����Jr����ENG�X#�G�L�9/�)����0��K�j�����!��Hۜ���\�`TQ��&G�if�O���9KG;����v�,S���Y�fۻ��Ç���T��+��H��*�[I��q�h�$,�ccy$fyv�Dt���'{�$�������GB���:H�"-�����c)w�)�qSnm�<�r�_H����K��VP�Qd�GJn��\i��m%��c��\�x�ا̤��\?H̅����F�W/3�-ShL�F�֖RKc���P=��%�%���S�k1{�xe�Y�d���#?��/z"�'���W~*��0��vN���'�9�v��w�k����t�N&���|�� ^����#/����-�b�Zc�C5ܠ�{��%�Cģ=M�38�8�T=c�,֍�U��t���u��H��@�Ȼ�^�m�����ɼx�Z�[.t����������B�`�4[�8�:�u�8�"_��O����E���F@�u։;��|�e���LO�+� ���.�b?R�T�F@?�}U������ޞ�2� o�o���]��؃�[΋�H�Q�{Y���ʯ2�{KD�}:X͆�A껊ϖ�r�}O���N���IYiW�����qy�Лm6ah{|����9����ݠ�,��� ��6bd�À7Qy}������I<�s.�S�#]�j��2x6���=A݈+%�4cKBE��S�8� ۪)�m�nv�g #��Ɉl�6��;�~�Җ�ھt��>��ʹ���m?�ԣ-Ķ]u[5rC����f1��B`�y�H��S)�P,/�U�LɃ D=�ݐ���4���]��ia�k���$���O+J�2��9!\9} �(Ӊ���P������oѤ�"�!�'�gZfݜ�Ϣ��8��l�\@�� (�*J���<��d�B���ڝ�pz��-I H�8\� �T� ԃ���{.Y�sEL� &Z㾋M�d������#�v^�O0^�� �Qjp�����%"���=�r\�h�pݵ9�Dl}2 ��ޛc��*�D߱�,��tv^�uz ����6���2�����@��t�^��^z�uIJB�(J)�p�‡+���O�GW��/o��c2UX��Ql;�K�Z�$�/M ��zC�f��]^�[�L�����1��`{'T�%e�!w�v�����m'CHFX���f��i�PɅ92�A�E?�X86ۘ��ބ�h���W�������k/E!IG}n�|h��y��Փ?��} 6 ��F��)�)�O~�-�l������Q��Fř��j������u��x��$b!h��&�|�(�Y�S���_��Ʃ�Se\��r�~�_�fq��{�$�����m�2Ix�Đ��Z�]�:on�����+a3r��O�1<����Ix�m��z8L���ݝ endstream endobj 509 0 obj << /Length 2799 /Filter /FlateDecode >> stream xڥYIw����W�0�l���9Ɏ��Oc����a<��$�$��<����Yz�Ej�R]]�W�pq��x�n���y�/r�'&Y��y�H�L�6^�w�߃H�\�i|<[j������rEQ����//��,�X|sn�1�#F)\E�t�{^�r��skF�Wn�ʤ0���~_�7pM�e���eb��g����x��˕�������o�`���.V:WQ�������dA�\��uS���i�\;Z�a׽�a��uٖ���xK����1d��]����Mۢ��.�����X���l���B��*�4p��-�]���]Q*%N��~;{���~���Vn�Jk�Ǣ���:T}uO�[W�.T�X�8��n���n7Ǜ���:d=0��`�����$�7� |�������}ڐ�|��y�S̘��*��)2i�y.��|xHa�`u���a��0�m�0��y�꼣]?� ɝ�h@s�� %�ꄚ[�4& [Jz��5��# ��#�B,���O��~&`��=AH6U�|���9�f���|��M�.R$,`V%U�\!s��=�?π�g���Ɋ'v��ÿ窑T��~ ��r���$4��EN����;5��wA���;�L�(���0DP`�5�ѽ� z��Q���bO@�CW��ٙ�be?�z!(��e����\J�#����<����� ���(��e[��R�(�/)��+� 'NkG���#�L�>ΐ�q�3~�=�����Ύs`,�p�8��n4��_7W�Y����V�/>\κ��n/�5cv6LTnO�6橫�sx��ǷP֚��Vi� N����r/5��P;��p�k�6p�����T��<�{��I�]c9 )ws�y�XtJq�9��5�c�'ZI�O�F�`��x?��������Ѐ% ɿ�04*��� �D��V���7$�����`AH���ƈ��c[�n;��sE�������s[�탬Լ�cK�8B,'�Ĝ�Ȣm����bfR9����j(I����Jh\`�������&:��wD�r��$N�2���F�E61C����kqA���+.\q8M����O8ĸ�"�ȥA��pyW�*��S�OU6o��cU[5GYe��i��E�kM-���b����KGb��c`jR�5��� �������)=��x N��V` 7�"(�m펊P|W#����'&HV=)�O���2�>��0񈀄޴\٧^ Y/Β��ڀ�䈴S �����o�vä'Av��ʔk�Hw���{,|;�G H�� 5U_�Z�9b ��.��~���|H�W��WY�7����.︿LA� �Y h�jtxrf��p�xƎ��� �HK�q���ɮ���J�|l/�7�g^�6|�+��L-� �.?�^~�ɓ�{8�;X�;�Yz, zm��]V�ka ������ʋ=j��,5���|w�$� ���i�3"� �F>4P>��y4��C>u�c�G���A*3H;Q��(�m|�{c,fXM2��×b� ;&3��0�N[C!�ck��ꏟW��,Sg�:5�`�1�}�6�P�¡�͝t1R[C��Z��:5d��!�[��wjSջ�;(u�=¿w� �~A�$V��� �;�X3�c[vP��1�W̰�1[p��/� Qi�K�~{���y���`5:�?�y������>���ػB�5�@Q� m|&^�B�8^)!�B�q�R�A>�H#�m8O m�W��8~�ӂ����NM�ӳEۧ�/�"�w�+c��{l�<ι)T�Cx����<���xRɻHS��o_�:^:�4_�u��'�K�U�sH� � �Z��!���|pM���Ҵ7�h�nS��Ͽ��i7� �F���VG�q�eb����K��^cld�;����Jj�Ž]�Ku#�[��˞x[�K�^�#9 �(G�6�#1�i9���c��~ٴ�}���R~�<���h�_�k�r�e�wSF�IDžP"w�G.=㢑B��!wm�j��C�y���߆���.Hs�ۦN�yJ��X�m�h^A��͖��J`����%� �| OGi�)��BF���_`A'$%��t��&q�������oL)� endstream endobj 520 0 obj << /Length 3666 /Filter /FlateDecode >> stream x��k�ܶ��6@�=�+�zQj׎ϸ���9E���v�{'[+-$�ه���I�Z9�8��Ò\>���pf�pq�_?���ɳ�Q�(�"����nQ� �A�����⇥���}���˸p&��b������7/�;[�q��������� ��Ϣ|�����&�\ܼ�i7�^p�՛뛋��y�����vOB���'H� �HBg�h -C<��`�vP �>Te]?0�j�cr�vw���7���|����]����`ԈXeA��1mw��^mת삺���� �L�%M�W��ܨ�.V1#-" YE��rs�:�7ɖ���F�l���="�:��(�Tr__5��p�XQ�b~��Щ��������M3=��������鶴��H�U��4��=�G*k�O)#s�~�Dc0/~��6|�Y?�2X����V���\qT��r�Gl�����Z�z��]�m�S��_GnA�(;���)*��ѡ�6��p��H������g�@�Œ��V�Kr��4�.h[T�mQŨ$���:�jw���;v��u��G:L���TB�X� }�~�6ÌI�@v�V�����N�-��a��@H4��>����Y`�U�u'zW1h�� ��E�^���*��dr����&��=O�f㧧��^oT��c�LN��0� 9 _�\?)a&�W��{�� ����i�l٘��7��:jծx��6�C{��&6�Q ��w܇�W���]����]����������S���*�U��$� �Nf�Eo����46D�����/t������[_x��A��\ �� ��KMP�r˻2�Ul����Ў׌��(��\�q"|M�LI� [@�u���DZGZ��~�(2wyF������Y�yͧxlN��L���Ǝ�6�Qm��ϥhR��†^�$�V����V��[Uu���M�"�Q�R���'� ?����T"a9�t.�E�)6����?�Ύ���<���t<�h��i=M�5��c��ѝ�� 0��X� z�+�;��>�,�$��"�W��!(kɩG\���ʣ79���z�����'`������pG��l�F˟��sО0�>��TjdX"�th�B#�;���fe��gO�.�OD6�'��"�XD>f��� s#R�P�����I���k3# 1-� HB@L�-�(j��s�QtN���o����K��f�ci9�ޚz_{��/��+�[��5�/��������(� "��ġʃ�ekG�jdM1=2�!`ԁF޻�O!j�kDH�V W[�ι�x���*�|�U�ͼ�ꁫ�7����L��%!���36�,�ű��$�I��U��L��n��H!��ȵ��$��3(l�*g~3&��Dd� \`"8A�,|�F"�H R���Ϟ�5�-�5�/yґ�4Tn�Y`�`L5�T�;��� �wڿP�vAB�Դ�vABX�6�k$+�1����66h&j(�4τߞ�� Y��[+�#� w�a}j#��)J���o���l��h �5�G*ӏS�1��#���={�zMDӬ�3���i~eX�j�]����֪�e2�X�Q�b���" 9&%9)舘��.L(5�6Ӕ�sd`��>H�tYr��݀�O������lP����hg����QY�}�8B��lx���9��S�D������`��ys`�n�� � �N�L����H@��pmӲ�|N��}� ͂����c�N��$>�%`�Z �  �a����>%�J� ���A��(�y��)hz�7| 4����P��Q�R���ڪ�\c\G 0��0�4��t�`#:'��;DJ �C�&lƃ�[ d !�H���iڅY-Ͽb���){���m� o�=�N#� ^�g{�g�_u�s�܆�9iaR��m�c� 5b� �|�RQ�'�.���$���c�j���i;��l�?�T������r�+�4� ����b�?I�1Y�3�Ƚ� ��V�爎9>D\���C ���8I�����_cČ{�x>|��1�O'�Ԯ�0�NY��P�P� an��c�kjL�k^����zɇ�;{�:j!G �1� ������[���;�S��$CE�����Ct�%���r�uiJt�>�Q���,� �N���G\_��'S���n�����܍'����Ap7��:㕠?�;�Gz�$nT_�ꟾ:b2Vƿz�D�7:�1X���� '=�3���Y[9�Hc��3���>5���&�j.7 '�dm��x��M�YZ��_�m�I�)wP�6�Ȃ����F��} ��gH�b��������ys�fA�[���T�^?�2H���665_>��S�@bm��l�M�]B8�j^!�ql�m�ٯ�vm�76��|e��ʜ�o*�� �{�s?��[�\�{�.�I�~s���@�%p��� =��2��<������}5�DtO`��7Fr�Zo�q�"�u[����~C�ՔŶx���(��Ob\EoD��)R��C�ٖG9��H�9��MlϿ�$)h����u��ΫZ<~ƥ_�*�M��k�>ܥ��y��� �pf�Ug��Sb�K�����ר��[0 �C�.�@�U]��6X`$��$Lf����F��/�p'���ȁ.W%7t���? Ov-� ���V ��?��� �0�ua��I�����H�����z�,���V�VQ�#�dBg���~��Nn�7O� 9�� endstream endobj 557 0 obj << /Length 2930 /Filter /FlateDecode >> stream x���n�8�=_ћ��1nE$u&�N0 lx� �f�+w�ne�R�{������dSm9v��>�,R<�uW����,��{�����*�e~�xvv1˂Y�~F���싧|��I�zLJs!������B)坾�t�����;~'� 8'��m�[�^5_��WR�Q���= ���G�N�-��͙L2��'�9 ��$R�+$fL�-V�=��f�Ң��r�|m�]�\�hA[S��I輘v�t^L�%z�ڂ�@�D�S���~'8Pf�؅�/�!��B�B�Y��� �j7ԞS�P���we�Hp ځڂڎ�:%��� ���6fW�}�Գ�DT�$�D�� @�`Ws���+��F��~�]5Zy�� w���f���6��-H�CjO��'��R��w�<��1�OHP���[�?|N�w+�, ����q�}����LFĘHKGE�`d`f̡Q -A4����"ᅣ��~��x�����ȑ�� �#�ж,�Z��/��=���ٯ��l|7����e*�0�������}d���&�lzY���M"�l�I�h�jy���H�9f2�����o#�Rc~<��ϙ������_Y�" # �] �RBB�����E����_�l��@;P[PK2����[���{f:z����|4}H ���E�QƇ&��u�;��oǬX�i�������<.5tMo1��:��`d\��<����靷��6��ޚ�mt."����-���L�hoJ�&t�x sOM��� ��c����x�'��;TΚ���>���'c&\��]@ ��?ǡH$� �����)yf_� 6�/�+��}�~�k��x�.��Ag����|����<�'%��lI ZjKjk��X;*3#�h���=�k�z�$�� {ǹ�|��� }�=�gFm�(��4�^ޱ˸ �.��9i���/�7��*����Q���� �1�N`�R~���������y��e_� �*��T��'e��hǡ�>OD�hQR?�Z�5���۶�z.Iq�j�6�e3t�/l�/�Z�.��ו�)5�d�Ey�k����ۼ��p2��4�&��G܁����r�w�����m�T+����u��/ YG��\��� IP�4Dl���j����GOox��5�f�,�O��\S�8dz��<�Q�M��@�����ͫ"��.��� '�̔�/B�n�} @���x�`� ϛ��ۧ�؏�Ȭ;" I��?�>����&�NKT�v2e����E ��+��;^��𲨋6�����xyt��O�i�{5,2� { SS{����F�OBK�ˢ�T���i�#�Τ/w����eS�d��[--�+5/&PA��KR�0��s5N���� �[1��?��XS{���E��=�)�g����u4N[�t�&�5����?��I�� ���5~0_�:"AW�y� nn��E-����13���2�)�[1Hʴ�p#yZ�~b~ rŞ���(Œ �Ҙ1�a�t���:ӹ�;~k�l�eU�S�jH1V�i���E<�ڨ��$�7���ҏW> stream xڽXMo7��W��(����0�n �@�����!u��m`������D�,�q��]�};��!����rq�]�� .9�y�Wu�eW��rrB��S ��.��H%8+�s9�qq�p�X�5� �T�4�m,D$5��bJ�Jõ�E�bu��j�g`4.f��QO`�a�[���$4|�V'����Ej� ~s�aL�h�JC1J��8\�$�� c�9�`0� �嶰� �0�D̹�ssi���`0W2W�Tႅ�s�Pj�aa1�`1Ze",�(4�)@�Q���j��i��x�XY@���bC�SovZ����<1ABi���R`�K� �3 ��h���A�goi�h�90�*1�^ 0� 0��(�靱"l ��\z4 ��Nfm��K�������^���L��lШ� $!FY�1[d�`��0~>�t��� (I�Ȧa�X�/��_�?�^�^(����bz�NX�{ᦟ�������w��݊A��|�(z���o�ZW���t=R�+���_���/�2w�b0/H��o(��������8�����cdZ1�� b.H���}������ �'!G�e5nn�jL��|g���.V�/�W��M?=;vӫ�+�ѽW����o�X.��puy~uɤ����by�zq����q~����ٛ'���ˑ�'��7x�i�v�r�W�6�P�|��N�0��� ��o���Q)e/*��CQ�q�{|~����Z� [����������-������8;�k1=Y]�]^̟ ������ӓ8���S���f�6��\t�24 M��җn�n�j同����Z]�sK�k�A<�Z|��R�Pt Lhȳ<�[�ċg�so^�M� T��&>����~�� 2�u�~�\+�G�ˑo|���� (tT貯�\ �p�`t�N��*�kE���2���"�=�wDtG^с�踾A���?RԚ�����jGՇ�-��ŵf�]�ΕH�ĞF��Z�֯�m k1d�R�e��%K��6�˳*vq |�M��8���q<ֱ]�j��2�&���j�[����I� �!�#� pi�}�| ���8Ha�ol1x��@^ ���!��;,=����2���st�Sظa�)�f�Z⃖.�1�~'�����'h�-�禭������|P(6�.�B�N}��ɝ�Sy;��e��>y�*��WEk�{tC��� VMl� ����:����1^��gXv��&����*�S���շ��b��2@��[j�ɭ�j���QN�Qi�4�2��Ϛ2�e��a�*e��_2?PT���Z?m*����c�q Z�5���,�B����8�����-z }�����_.Ц��A��͢��%�v��al�������|x�{�Fe_�mCĶZ�U�� 6�\c 3B!B��d�� �?//���k��3^<���X���AdB�>"�O����' endstream endobj 595 0 obj << /Length 2951 /Filter /FlateDecode >> stream xڽYKs�F��W�| �2F� @�9^;��q\kS[�=��! XxHI~�� AC�f{�0������ �E���ُ�g��t��T����z�ȂE�*���:_�� ӫ�?\�3�٢0ʔI Ak޼�y��˕o���$�V�`���N�7��/�p2�~]�������x���z��'������g��wA��HE:[�:�A�ׯ�E{�GpS�6]QW��]�i��+�Nt{7N�q�ha������q 9mz�㛏��p����ȭ��H{���Ck���@XUˀ���;"�E|C���i��(H�^��o�=�m�#�ka���e -w}W7�-e���}��x����o�:9 ����8��W���̢�-λ_P*�'��Шp9jþ뎯����Tu������g+'�m��5����h۵����k�����ǁ��~B1�t��4H�"OP�� V���;�X��p�4h�+���L%�fP{���{�4�w��\��BM��L��+�Io�*���%�Ҍ�臖g $��*�MgY�l%��y����?�x���5���ىŦ踷�A��hY+�'޶�r���RT3� �k���W�l`���P�B�!�~,�#���n\�w� z�=�U�pX�É�l;ӄ-� DZg�i�Iv���.� �P���k.[*��1� CѼ%o�4���<�� �qj_i/�Ec��R� �!@}[�j�Q����G����GJ�:Q"/8�m� ��XEqziz��΁��E�'ޯ��*��,�0�����&�K�δ���q#�����\�p�苰[�j׃3���w����n�J��\>�P��X| �l��ӄ�ϡ&u�4�p�,�/�j�,��=�⓻�Yr�l�!f{ňqA�����;�c]y9���t��"(�ޗ�O" �Й5G���v;�#�?�y7\h8����Ҷ�s�P,����1=Y���4��ve>lp��eִ�A��i�;�( B:�ܢر��.׈q���W���5�8ښ�#�-r�{�;� �I� [�v�@ۺ !go�����:�Q�m7y�x���x��n`�B`,����bV.0he!�&�a�2���SЀ�$�ᐙ�w4�sDӸ�vi3� �&`�C�����x��s�1 T��� �w�nA}�����R@�솂!��<�$��W��� i� B�O� ������6�D��^L��d�;Tk+�����ʼn2���82E��08剻��]�Ab���}F Y�.pt�¤�a����l�c �8FL�8J���Nmy���,g���'��=��؊շlϴQ�C�%+�3<�� �K\[�Ќ�ܷ( ��>��ď��AON�}y�;`]��1��Z���a#:[�d�Rm����Ԁ����H��P&}_��Ö�c�o��= [�����"8�02s�϶�jf�ƀU��"o��q['�.�����K�M4g�sq�d;��x�M?IT1|$�.�0�687��t����ȁ8A66xh��f̄cGJ�����d' �x>"��P����2rDL:�����F0J&�S�Ts8� �t��x�y"�-�i3T`vX�)���~�Y�����`PY: ��H��09�@mdž�P�u�p� ���H�����2n���sGry��+^B�4F(8Z l�O?��D�9�Q�B�3�>�n[�fY�XOX�8RZm�F�B�Z��Jx��È6���]�A(��d�9��N�����ş�@0o�&�aQ7”$Tɥ]S�I��D�H�$��Y%�pE�: �#*��b���pu*d6<���nS`�����Q���d���A{��7_V��s��Γ�8Zr�wT@�ڛ��/,�3ڗ���sp:�%J�ٔSg�I\�N^��lxidڀZ�y/@�>��ટ��~�œ�GP1�����V��. �17�x��:�kTZ`�5������&�����N��I\ Έ�۾�r7�R(��)��x%`�ˣ�z�K1Aa�k(Z�����\j?[ ���x�T� ���"�Ḉ�9�?A�������+��|��s�K�N~�`��ޚ@��a�0�5F(s[ۗݨR1U_�d���ǐ�ST�����R-��Kd}�\�J|�i�e��8$�/��ؚ���B��m9�I��_��g����5r�eR�Ŗ�I�$@z��!��᠕{{�NO33.��& :ٞ:�t֯v��h�SҪQOA3Seu����S7e����,e�?����$�il�U��� k�pt�p�dS�;� ԥ���r� =� %g8D��CA>���x��ˀd, �6Eᡔl�<ފ�0��9�-���W�3"�b{���@H[� #\�k�x��� �p��r�>�)$z���E�~�`�;�v>���i�9e2"�&����)n�vV���CA��8<�ء�)u �#To���x�%Ïr�� �S8�6/�y�pu��!E�O�}�j�k/D�=����U��&����*�����#Z}�܁/�'fɅ*LY�IKME��V)ls�S`���9W�aG�9�.�P�A��ܷݐ���9���b;�����|�T�e�B�mQ��$��T������ �W� endstream endobj 601 0 obj << /Length 3660 /Filter /FlateDecode >> stream xڕZIs�F��Whr �,��s�(rJ�l�$%5S�9@d�D ��?ok,t��\��C�o��k�g�3��7�x|���(?˽< ����Y~��*>{\��ۉ��;w�4sn�A8����܍��y�����x��~]|�Ɔr>���p8��8a%8����O�C�� "ϏR� ����/�3ϟ��v�A��)#��{.�/�i���Y��LR/��d�ǭ>w�0t���̯�[�ʗ���0u`n�RV����u��u�rc�Ե^�eSw�8�g·C'�>�2m��Z��1�3�)p�l�mU�������E��o-u� �(;s���ccٱ�����#�iP��dt�s���(��ן��8T=/��<���:�w� ���1΄��2�c��^i�b�*�oEU��gʹ�9��)p��w:�$87hi�@�ac��]V˶��W��������0��$4�F�m�%J=c�Ǣ[�Ohm�LN��:e��u��i�S�L:t��N���aD�{*N�⪚b%ʗ��yr��E���M ��6�����I��/���C�� �<籗 qp%ډ ��V�N�U�Ԉ RMxf-�J����)r�����zn���A�yY��g?P�C[d|0��P�EM��z��c��\:�M�~�.p?��v ��{�]���Mwa���˂�ܮ?����.~�q �1�v`�N6�7�$��5�&�±"o4�,�[�&����-y6��.�S���i����=��2�c��eYTLy*��1�16�2��ll�m�^J�L0��9�V�Y��P>�=���A2�+�f�tF� +;n�к���)_9��1��}q�G��'oՔFJH#/��������#���a�s��Þ��-��Ϗx���Y�>�l�y���}��}x�Ǵ Əa���;}���ء�l&�=��� �-e�نC�"�Q�"�!�ʢQ�4��x�0D���J/+�0jd�^<��Ԗ�\��hCA�,�3o�{y|��^8�����������x��iL}����G� :����r�~�7�x!{&0��d��V��^�2qT�7bD�K�G�ሖ�@DT��/7uӊ�����ŃT�N�|�lۢ{�� >�⹉�iO>� ;�� G����bЁ� �!:J�iPa�k7k^���N�%'79��[$��"�g��!-�qtH�� \]�\��M � ܤJ�<|~����9���g2��R�O�(�I|Xr4��_����實h��h��n_V� �g������@�j�f�}��:�8�yL�{q<������c&x�E�%�T �z4���C��-R��ж�� �Ή�njC�{�a�yHp��Ma�3��kD���y�ޙ�d>H�(TiS����u��C�D]�W�����r!�S��7+~F9� +���hc� �p7��CB�r0�#�j$l!��h�|��/zy赼=�(^�=��H�!O$���c�\�*�|*�L{J� ������U�� c�e,��j ��� �hΈA���]לU-/Jk��(<���y�e��7��VR��AO'�ds\���:~a�Y%�����5p �`�"�v���N�4�Z*i��,��� �W�|0;���t�Ԕ�Q��k V���}c�{�Ҝ�WL�t�v�^�?4�:@��%�h����Q��*����`�ne?�i ��S�Y$��6����l���F�sE�>�KMF�1p��h-�6�J�*���l#f'`F�i^1���|�X�$B6��G d�l��@ ���g�Nq[)����� ���g��¹jܮ�iJ���I�N�,8��%���R�e8�mO�`aH-�c���8���D�#�k�I,#$z�Q���V�u&|�O�_d7К�Fxcט��z�0hΔ�]a�<"6o�{�Q͋g�;*�/_�[���b��t�ٵ�]B�9�y�j���6�X*��;P�*{U������ v�Fe<�CW�xz01�#�{c��v�J㊖P�� ��d��u_����(G�*� E�6O�P�5x�y�U;��d~lz� ��&�̉)�s8p��D�{�H��+z��[3��1pj��Ä�����y_�S9=O�r�~����6Lb/ �B�o�������z��_�,����{�@��N�`U�d�|��'n,St3G�y/<�k����?�)�ia��-������W!�T6�V(�H�Q2�����͡",��O�����'�%f�5Ũ�hRh�tQ�-1�8W�cSJ�+�j�ѓ ��#���1�����#E0Q0zɘ�$�i�F'�? �OE�W;��g |y�׵.��g�ű�HƤ��#7<Ш7� �����`���;��-�_L�eջ���i D�Cch䠆�#��|H1�F_�0���\:Q�Ot� �Rc�r�g���KSs� O]�������͇ůW�����n1�?��Dc������\���ff!Ovr�,�.�: �ԵT�X8T�� A����q�rS�v���i������`G endstream endobj 610 0 obj << /Length 3129 /Filter /FlateDecode >> stream xڥYYs�F~����!� ��骤��eK.YJYt��H�H� ��a[�>}�� ��x�A�L������Mw�[��w�^���|빋�IB/\������q�`��Z������˷2M~��H�4��j�����ҖRZ�Y�Q[׷@Z-�غX_���o�q���i�Kn\�ݯ�o�����?�q�\��˷��p�-���^�������|H�(�XW��v�V^��~H�Jw�BT٦m^�L��:b'-�[���n�y��_~���)p��B8I��2Aҙ��㻾����R��>E�|]���%Rz��tPmZm������-�rW9;�/<�ڴi^���6���x�������9����#D`X��-Ҧ�����=3 |DUO�Դ5�C�2=�3���ɥ��� ��P&rpf��' �^��W=g> � N�π��{���"��Z�8�5(Mj+͑>���,�O_ I6�n�>�T�ʅ�M����,x��S�����P�1Cu �z����x)8�J��{޴�|�����Ϋw�\��� ����� �9�{���n�/���*�s�R�;:��x vV�s���SH#w��U�ժa��A��'K���󱄟3 �0�>y�<��f�!�V |��I� n���fF@�8f����C���CZ#[~�X�j��\ ~� ��E��6�4�Q��/�6-���xS��{M��F��2����9��y�T)iY/n\�9���$nVr�I|��]�4l17嵱��� wl�Q�8&ʫߦWz0�(��2��4����븮�� �X��G ��FVf�ci�=�+�0��sbҁ�`f7돵aLz<������z���5���2�}� (����N�#�N�ƍ������ BD�.�w A��k�H9��O�J9~���"‘K8�[T�/�w �(bm,�^gb�OA���#c�����#��ƸC�C��/W�5���iـU��}���~�>�" � ��q�;z�����f�А�}8��~M?�U��A7OA����ն:�9ő �~����+������}��p9�w,�pX�h9g�� �[��e�!qW�iw�a�M���U����+RiM��'8'$v/�h�*�Jث�k]?�h���� oAL���l�uHQ޾��t�����k[�`e&de9B� ~Wp|�V_h=�{�i� �켩dN=��z �Q�ė!l;���`�n �F���'�~M�����[�W��%H��t���d0��d Ac�WM�� 3#��f[�o���^�;H��t3p�T�k���Ӣr|38�v~~ ~��S�Ig�J/��'<�-Cߑ�(�m斉#��S�6���OG _8�H/=v��E� õ�)7<�>�,�&�8���� �Ac|mk@��L�i��@'���ɩ��}�� �Eڶ�1�iQPV���~? �����L$s¤����I�1��4�����9� 6�ڰUa B�#B�0�NKt^��F����J� 7������S���G��X��Uf҇X�*� 8Y���o%��k�FBR ���{�ʦ��� Թ��s]�1�&L��B��,C!�8�h$l��X�/n��y����z�@vm&o�u��<\���L�� zj?f��3�At�5\QC��담�Ʉ�6��HNr7�b���uQ$�$0F��*�̩r��!��M����}6��>%��k�>��_�����������g{ �]��� �w�0�{��!9O(6�j$�1��y<��8��3`� D���Vi6[� �P�qX�BLY� 䴱�9z�Ղ|\�@����Lq�e9�F}�>��Um���E��R ��VkP�� g�J9�E��H�U���x ��T����s��oS�olL!�r��3���=sw�rQ����w��\���[�#����'{Y#�F�񌫉�8NzO���8 ��z�Zb�w��N<���1��dTl����������v}��=�\� X X�Tf�:qϜ�����(z�Z endstream endobj 619 0 obj << /Length 1976 /Filter /FlateDecode >> stream x��X�n�F}�W~(�&ܐ��-- ����� �h�@Kk�E�KҎ�~|gv���V�\�`k�;sf��,�����{�����^<�Y�`����(t"��X�~�<&����:9�:��O/�HX�q�Y��ˋ��y�5�m1�����~99ƹ��d:��8}��;�;��1� A}wq� ��4����<�=���nz�'*M�3����s�0����ǭ�q ��.��64�䲲��.+��v&��j������2����~���0���ˆ��Y���?{J�wc� @C0��™�ql �*�׳*U�ˤ���\���;�������ba_�|:=^Ю���uE�7��F���j-�CZJ� �]�ž�������%�i���Y�t2v] ��'�2Fs�x2z �CKR��M�*�{qrF3�@��R� {yA�Y�I+�e���E>xH����!/o���/���cn2~�)�燌q��o����p���p�*"��1h�~��V�զ�-��km���g�����F2G�,.����2���!,s��ad?� AJ�H%��X���;�uq��m)'r����z^�:��̥J�t�[�5@sUZ�C��>�j�KV+��e���6��/ ��%���x��d�=O���>9�@�3�rf�Ϝ�9��c�ƶ6N�t��b��$Y�H�C��~^0���'�N!Y�VE�Dݖh�W��.�D��P-j�y�(0@����,���FC��B��F��m��Ъ�*���,3w�FhM�*o$|DB���n m��ͪg��ǚp���d���+����y3�ra��IN��n���� �(���m��#H�:[a|�,�o٬�(�B�G���3��N>���Ȭ�J�G�k@��P���NM�-��~ �wSdY� ��lOP<��@h�������~OC҃��j�10�I+g��h�,���T=+���K���F������o\���B��uP^T��P^�c2��T�ڡ�y����pM�T�5F���O��֐b�}�G�뷾�Y0'j������l�a��.�A�Dy�B��ԲW{���ZY�W���ܡR��2�@1Ƒ�R���MMI� i>�u�o��M'����h�z�}���2��_���s6��yn� ���;`�dE��a�H��}k���he^��c ��W�ܵRF��}4'�Jn�:&|㱾A����fvm����'S����~[|�F�]�����۞)�� ��V���Yn�v_ʲ�e��R���IB����}Y�r��5���+(�X?�W� �z}��j]˖���xP��T��W{�f;�����z:;"[b��;��LRCթ)�r��N�#��lP���ſJ� endstream endobj 634 0 obj << /Length 1503 /Filter /FlateDecode >> stream x��X�s�8~�_��)*������8�8��k����`�!gCpr��?�VZA0�.�7}H,V+i��ծ��r�^��^3w�(`�(^�"w$ܐ��?�磏c�����1�:Jԋ��:�'����v8�'�#DhMg �,����Luz��i|�j��'��t��Oߝ��\c_�8��xt�02������!�6yZgE�;���X?$�+���v�MY���̂�*��U��e�c�֥4 ������3"�v��D�zg�� M�l�Q������ �ȃ�G�OQ9/jg^���n�`=4j9WS�'�58�� �\.���q`����K@����,��8i���)�U� �j݃R9���/V/�}�����%5X�S4lԝc����.d�)� ���%�X� ��Vn�%tC9�誶~$���6�pK#���!��,4�Cϊ?����T��.�b���[Dďu^�5ΣOv^c��~8(X�~� ��.آN5�w�4�_(����`�Ǜ�e���뢒���T����� �un�j�ѾV�O.�Jؑ��+�W�= �G��#���]Z�0��ֺ(%����J <�ޗ��(��������@BX��jm*�y:��w�p�A���Bi��9H��jJ"���[Z�|Y_�+ ��3Q�&�K0RŚ���HK}���p�1{���3�-N+�m ,��*eЪ�;��&=W��I�\ `�S���n�����o���:��3��Y�o��I�"�/n9�H���/O��o�?��W��U �F�<۔R��g����a��Yi���fٛ|����KH��������~�Y�V&e�f��ǷRV��0�XS`O��7Yuk�xe;����/�CP �EUeW+I�v{����/F.~%ʩ+9�����%4�[�]�u�z���=�)I�tJ�C:ڒ�S�S��J�C�3S>P-G����#LFq/-ق6[5a�����6�P��� -S�D>�Qp��� o�����������{�.Ym�����;h�D�^j|YCNb.+�&��cb�E��Hޥ��7�i� Q�Qw��mȏ',dC�c�7?���{t�@�'|��Z���B���[u�¨G7��a�Q8���G[q���ڃ>���&*'؍�C��=��#�In���%�M��|�M� �74}�=A�;��?�s��z�"�����xg OWKj�v�^V������`’@6��0��+E/8�'[ƚq&�����U�̓�J� l��#�(�����M�~n� 9�#�Yޗ�Qqn��<V�_(8m�#���NZZ?�� X�?%^�dkr��W����܇�V�ݣ1j��:��Ā�s=�e}](��f0 �g����\�;���J�N������RA �ض��y��R�� i�X�x� Z���u�&����s19��"G���2V��xv8A�}��|�I�%8a��P 뗘׺�����z����ϟ�v��P�yT��zγ�sgU5/ MY���$>�%�,� endstream endobj 652 0 obj << /Length 1593 /Filter /FlateDecode >> stream x��YKs�6��W蔒3!L|��)�*#KY����@S�EG&5$��g��ł��҉�Jv.K`�����������۳7���K�",����텮 ���f�����N kx�~_��-<�o n͆���pέ��Y<�6]� /`�?����ٻ�K�n��QN\* ���̙kt�9���C��P}�Q�o��6��i�����Ƕ��n��]��VN�؜Y_�4 ȣ���� ����:_������hDB��O(��- ���������Sk��#�~heyU'��P+�}fI�+��j�&�{[�X����ˉ8 �2'�� w�6�,�O��f�ZVfV��;r�]�~�N�GPcG��Q�*��68���E����5�d|��׬^�LR�n�e[�Z}��C)�|����}{M �`G����E�@H�ZޯM�.p6E�d�J3�4�RV�U�R�>;~�����(���k�7���֝Lk��txD�� *���URU�a >��B`̓{�������b 'KV�<�Xi�&sY��0$�����zS���:G�?�\�R��=肋a�緼Lj`���r��ϔ��v^4t�e=�hD�I�0�G�zr5�0��@������]�]S���R?�.#����q�7��a<8��(W,�� ]��#�\�y�u���g��o�\�s���e�Qʬ77�,=�K ��)�����f|��W+l|t}'�u��!e��Bc.AQ9?G�^�hfV�ʧ�xp���7N׋5^쒣��RmIq����M>NT���,I*;�)��z/zmr?���(��(�7{�%�P7���� |��7��Ƨ^�c�����h�5����B��_4D8 G2�uîK�bg�H�Ǒ���#�G��#YÑ��#��m3��6Gv�d֠g��6��y�\i%�2p ��7���mB�G�,u����tM��F�\��v�r9 js�� ^}%���o8b�½���G���� m�Xzm m�C1W塯��9*�rhO�&͉�h :|���jO����^�����2_.1��W��!w��)�l� b��d�ʴ3ܠ����+��pd(#��R�2��_L1�)Q�<��:��H��,}��!;�"@I�`��н ��`тzǑ� � �nb��U>���k]�-�9 c��Ȳ��9ds���'|"�����}M\�V�|�{X��ߴh.�āɛw�� ۏ5z���a�~K'�z��l w=��x���MЛ�$��.�f���x��!1��B/7�״h��G��"�F#��EUe7+I:����"�� endstream endobj 592 0 obj << /Type /ObjStm /N 100 /First 870 /Length 1514 /Filter /FlateDecode >> stream xڽ��n7����L �K΁���$p��8��P!I�J�$����ډ%�17v� agw��DR���I��E]�Kr��]Lv-��]�#�rpd\���Sr��D3A�=g'���ƩS�r��f�W\j\u�8��q%�l� ��gW�+�J����%WM_����B#+Ckp��R� j��*�i9BP"�'6]�W��C��J�x�*�Iįf��&6#�05rDd�(�d0�f1!C(��|J_A0[R�W SL!��d�We�0(�$,�H6���H �� � `� �CP��a0���d�,&@O6��%�d��`B��� ��Ph!1�1b2Ip�XLL�I�����9�`�`��6� ��\ c*r �X��$�����qB�D�(�dI�RlI�9%�97�s��97��� =�lF��Z�k x�p��b���H& �c2![R�P � H2�r� ��n�L���D�qp�����8d&����Y\���N�<�"'� ��rL��}<#��\(y��P0Q�sE��}�<"��R��#�Q�U�~�T}@�v9N�G��F�E�s�Ǘ���f��ϱ?.*�[�r1zk�}�}N�����q�R}Ѿ>�|k�/)�`�����!�F����#�+�#���#�#"��t1�>ƽt>Z.6��� G�����#�x�tu#� ��됰�� V|wu���/1(^�����Ɲ����#7��ܸ����|��w��� 6��5�����|��X����G���~�>]~t'����J�f�·���;\,�Pu�|���{�� ݸ��t�z;_5��t�ix1<� V�S�b�%���"���;+�ߢ�rB̈́�7�~���k8<8h# ��͇�b8~}��~��o6�? �����/W��j:ެ����+�\�c{7�?N�>?���?׫��1쾟騫`˭���O��[R�LB���r��*������:n��6Ӗ��֯]NA�>'�����u��Ns]*;ձS7;��U���=I|P��u7J��*��d��o{�^dv��i��R��`��.G�x$h�� ����b[؋�d�^��=�<(N1�����_��f[x�Ŏ �׻Z�Uq�Vݷ���n>� Nاbw������XW�A��w؜|�����y4{?=��W^�/���6C����  �~k#��{A�ĪD}ޯ;�ۍX�[����mFK�:���n*ٗ���/��'p�-{�}.�����p���=/�w��rݭН{]�; �޵[o�n����+ ��N����T��a��v��rZ���>�����p��v��q$(��t���=�wo���;��w����=V��_�O����d���L�MK�~Zn3w��>'��Xȷ��S��p�r�,���4#y��J���^a�Vr�s��ľ>;��d]�#�[�H��)�X�a+���{����bP�Q �[ �Ű��U �zt.��4���¹��$C�v9�hn�?QAS�>���1N85o���n�� endstream endobj 671 0 obj << /Length 1484 /Filter /FlateDecode >> stream x��YMS�8��+攲VdK�7�@ E �xwIf��S3���!����ۭ��5� ,dS���c������z���ՄO�����> �$aI��t>I�$�1�RM���G'������C� �|�0 P�e���>��'�ps�(���S�s���O��NqR:��G$�Џ��iz|���������ƾ �<_$L�/�`L����C7κ��EU��2�U1�yԙ�eV�M[�gmU���Q(WI'�qD]��0�e��7�N6��OX$�N�3I(1܏��n�Țƫ]�;��S��ޚ_cg�o�˖y�מ���bxo,}��\��n�>��u]6����O�ĩ�y^��,�Ѷ2����e��T���z�Ӻ�cb��Tsz��M����!�-�� �WōDN^�+`>X�e���P��?��zeS��=ȑX�Qq�L9⭲:[6c�r��0�gs��6C��T���Y���qʨo����>ױ����ž�\���O\񍼀Q��y�>i�w���N��9�������2y ���l1l!X Ÿ]u�ŧr�_����9�b��4��Z]ث �S��ë),��P�'�MQ^�̗����"+�ؙQ�39�kО�Oܗ��r$���a��TS�^�A�wv�Vl^p����J]�9!��Z��l�uS rn��:֑b*H�i]�T���в��wYh��u,�[�aAQZsX���P��r�GN -�xn,�LN�+jU��f��j���-����F���]}�b?kr�w]OJ���[7�����a�ݽ�' 7�2����bFSF1��U]�{&�\8�� r-��.b(c� mE I��*��Ŧ`tg� Tt�����o�� �w�S��~�4WDV�ax�EHH],�֜�^o�Y>�SCCk3z�� ������߿m����) ��-�|�� �e�F#t|�_��� ��W]Y v��a�Y�J8 Cέr�aۻ@I�,4e�+;��9Z�N�pF���=���z�z\�s��{A��4 ����l���ܴ��(KJ;D�1�8��ږ���u(�F�$�F]��\3��-ɍ�F��]��}��+�)���a���k�һ?h]�n�v�ѷhXmZ�e^d�I�y]-��r���>4�'���I���Bov6Q�Ў:��H���=����!��߶գ��ib#6c#�؈� ��9�.5i%�^�����Dg���_8.�m�i]��״Ӿ�A̎N��dfS���Y�\a������:n_��,����i&����iƆ �cL3&8�����m^�[&eo0ޅ���o��=3vʪ5��\�ڱ���v���uͰ5ɸI����z��� meݔO�����"���B���47��O$��sү��/ ��0?�0�Gf���S/@� � �\?�0���dK���7 \�� �1�c�G ��O���q<�g�����������z�Q��7�3� �� ��q endstream endobj 682 0 obj << /Length 1956 /Filter /FlateDecode >> stream x��YKs�6��W�TS3%C|�7ǖ{l'c��N�%B]�Ԁd\���w P��$n㉛� `w�}r'�w�������)���ȏ&�Մ���M7'�l��bN�L�8N��������|���4a������f�Y��糫�X'g�8wt}6��~���:���������:�����O��JGv�3�"���("�M�!�NC�J�u�b���mo{^��C'px�.עieY�vR�?��'�gY��W�jᆔ��V�$J)ꪕKAÙ(�Fd������@����#~����r� ��q' LQ�}(�MZ.�]���L.�þS�0u�U�;*L��&��'�x<���sRN^���Rk��Z������ }tC���R�<���Fc_����k6E ���(y��r�Vy�݈B�X�[��yN’�./�Yt4A �"��o����B4� �3ݰ��2�3�z"�1wX�q>7k��C�����7�y��T�i�q�-�Qs��+�;녴�� ���Y�$�x[�X�uH_��M^ޒ \��� j���V It{���Eg��^��oߝ� n죫�dvzCQu@��|����ή��ө�yE�����0/d/��}��l� �� q�|'����i�NȖOl�J��\q�-B���J7pp �8��ц��hak��X�QE>�)���5qL�J�(�Yz(�@&>�^P�h&�.0�p�����Q[~Ȭ"�k�?v\׿Bq�&�dmQ X��+�)MA����:y�G�u��Zc�_�䝵�+Ш��:��l��[Ŧ(�eI��ka (�c�ҩzPI�w�ic|�q��35�8��'k��G�Ș�J��YV%�]�e.TLWRn�/s#�X5�� �eg[fg����)�Я�-�]���3��"��3����4��Q�T�`�A� �0�}��� Z+-�cz�0/�t0;#�.[���WAoD)d�${:���+��!���c]�[A篇=D�&aϪU��G�B�0'��/�A�U��r�y@��Ĺ)K5 8�,�܉eC�AF��)�Ǝ�1��182Ȅ*�R,Ź��G���,�>��Om��0� �(]���4��J�I���LD�޾h���:VR�� ��J �k*j{! ���0�2��CW­?�誖(���U[&E�fh���J7�u)nkC\�|F�.�"�����P��� ���`�>�X�f�W"�Ez�1�8:�GTaB sIC�d��N�(距ۂj�ط� k.��ѿ���*�t����$���:��)�{ �j�������l�v܂Pp�V!�����!��} �\^�� �"~���%��#-Ay��3���J� `�=!Gp0Mݡ�}�|i _5�Lz�.��M�*��Aq�F�_Ԕ�ٯc��E�l�X� �T���"�҃|Z݌�z)s�(��״kQPd�W#�SN�0T�+��d8"E��*돸W�̅Q�w=��^ �t�2E�veRcN�{�k�m*�< ���|�/@?LE�cY<�l������.���B]��j�0R�r������zulD7(hy:6�/��37y�aؽ>D�==i�}���GO��5��>]~as��\��.T�Z��޲id���?�����j_�N�j�`F���E=v%�c�z_ö�ٵ�mv�Dy�.e5fGA�p��ّ�u�\�<�ky?���y������+��)��O�x����k�IO�u����k�t���{�7�:փ��ݓ�~�cf6?���� endstream endobj 698 0 obj << /Length 2374 /Filter /FlateDecode >> stream x��Y[o�F~ϯ�@JaC�3޲O^G��r`ѻ��%ʦ-Q*I�p���2ËB9^l�b�`�s������u�nF��݋&/�?��(v�@�d9��Q�F���Q��`�`�S���/�0 ;^��9>=��L.Ƕ�y���0���)���2�����)N*��g�)�%�~9��%g�w<��_��������l�Ŏ#[�@��뿱��q�Y�b^�� �Y��Z?r"74[�[g��VJkao�2]W����H��Y�ÀP�A��L� ��8PV: L�N� ��s�^�#pܨ����i�f�� ^��T�2.�zW+(eFH�y�)��Y2���ՙ&�����ȭ%�����'>�}�z�|�VUV��`IK#�|��^���l.��� �o\I�k�;�ِ���Q��?�W� �o3Vt�U�U=�W�� zp�`1���� �"{P$ȍB�'�2GH6EU�;� ~d�*�>�PU�0-��zp!�%|�Mϳ���m��$�+ֶ�R��=!���t�\"����Vrq�y}�kqiy�[g�պb�-}7s�=�vZ����~�ı����V���k�@0Dw�O�}��U��E}�<.��FT�+A� ��� �O* ���|�b�yqj�ar>�&v����5s1�8Ix#�&�p^0��M(��I�ľ6C4������,7�'-B��?���M��6�>>��j�|� ͂s�Pl8� ��A���1ŷ��x�~(�ɮ50w-�E^�0�md�(�C������ʋ���U�k�`B����j�HY���Y���C��s<7��ل�����1���>#���0y(��MF��j�o��'�GJ�u� ���S� D��0n�>Ў}'��7��'C4 m���+���T��� �?�5�O�g�LG���E'>�ݥ�Sg�7���]�,�P!���ud$����t���EF�����JU��� ��U�/�eU�X ���tX~�m�nw�+`��M�P�:�)7��4\B[IY�N������Sd�7壭7+��=�W����w �{� �]��j�. ��L���j��7ݻ�Y?OW+�D��`����|��ve�q�l3����XH_���it��h6��G��9�T�����;Qf���ºC�N~��8 !,n�'3�`,-<>Q1;?�ӀgG���[�lg�y�9�χ�1�V��M>q`3�{o�~w�)�_3��n�]e���� ��@1��Xa�-!u;��J��!ɷl����RW�G��^$<^�1|S�X�f3���tH��!�� @�֑�l�� ��N�`�����:�ȳ^m�u��X�+�``���)m�6�T�_�1'_�{M��v��p���l۔v1���Δ6,ņ�6,� K����s�7�/�9V+����۲�f������UV܀K��A���ϋ�~����P��n\�i1Ϙ��s}�Wߙ�v������¬Ң+kq������=ढ़�VB����3� �b�#z�5�YiY2`�D$�^�Bܻ5����!��I��E?lxd$,��]�]tx�i< �X4� ؕ@go�+���4Z�w�� �ט�bv6�.�+5�n�Ͷ����Ƃ�']k��8:�������x{7$Q?H3%�����/�:�,nK������-�~�#������j0�t�&�*X��|SK�w�7�� 77����|Z/�Z����E��/�s#��[�� �����> stream x���n���=_��v��,�2�ʐ%CR��&�m�xI*�ߙ��nf�D�苴;���}�Fo�3z?��Z����{�z��[<�B���n8no��~a���}��6��Gw�d�6�6[����f�6�~^D���:�z4�g��(��[��pcw8����+,q^������wz��������n��&����m�:��z`�H?�}�bM�i�x�6��x�����A��}oO�#��}�a����m�ȿ�k`x��-B��$�����H�� q�4 �3=X�V�h�Dݔy��7��_^�}�i}�d��a>�캌g���� �^ Z���i���߁6���� ��P<�5�cO"�?vZ�Gy��Q�� XQ��� h������*]�<�H���d��>Ң٬ol:�Gq�')*���#�J&p��¨��ղ�!�� Z��r��J��n7}0-&tɨf�z������5����Y gZ�����]���f}�ڂk;��LK7�ϙ���JI���l���V��� �+��)��<f:*�e�TV��� �Ki#K��FRD�)� �]�/�%�h8���k7�@��P@t��k���{�*��L��r��x�t'���INc ����J���ئ,� ��Q�ۿV����*�ۚ �pS�]�������gZ�nV��Q��T��x r'�QH4[�3_8�ɮ�v^�A�Tq�`$ai 5��㜯EB�{p���>Z�0ѿ? �z�|��`8�6�R,Ӫ���y���K��n���-�/>�\.}���X ٖ��Ŗ�^sZ�x�h�s}���$�z���:n֐���A��Lh����#JNhkQ� �I�:��r�o�b $�hh�$�4�j�KA ��Rn*�4.���L���*�I�k �U%��u��T)O��_ Ӊ ���<!kL�$[x���h���Z� �"�B���d�@&è���M��>,�¸e�e和@����봝ɜ\7��2��iY:��0����I��%�4�e���xO�.>2�ܗE�֫5n�6+���cQHa�b<@��[�V�i� �z;����WR��?�o��b�e�0H�O�ê.�|�2duR����J>^{� ����J���v��cg�k��Xl_��_C�]>��Ƕ�U���j�#��@���$Y�rJ��S<�9 T���0أ�������,�G2R#��W���dI-�G�A��9�����EYJ[�IW�S�Y|VTI�] ����}ś�M׀!cA7eu�8�ӸCy�# �o�UvT�W����=�{��3��RBR Gq ��VSU@Ȭ��ǃ��8j������J��O]� O���ߥTӀZ�;' 8�rfZ�V�> stream x�u��n�0E�|����Ə8��KQ� *pR�"@ T��R?�6&*��F37�^�C�PЪ��Z��)0��<�  ՄF� x�\���ԛ�\�Xd�P�!��F;y�ia!a�4�r�Jװa�^�|�l;�l; E�7�Y� ��S����)ߟp� C"0W�'��O�4�p����]��o�&��*�~�)������ (�`�˯q���@�rg\�y�x�a‰�u%������à��B��4� IC:�,>ʫM��1�j�:b"X���o�\�ݬ E��/v@R��ǎ�mV���b�8 ��l��A�0��q�tS?��zS��v��_9�]R�12yF��~�~ꈭ#qP�}��}�Ic>���_�ȼ�窜�\Mjk���4 endstream endobj 730 0 obj << /Length 505 /Filter /FlateDecode >> stream x�uSKs�0��W�Vq@փ�8�5N��ݎ͡3I2Ș�@���Gba�L��}|����BQ�(��|�&ӅHPB��G(ۣ���JB�ezĂ���X����C�Jי'<�������8������x���r��2�z���t��U�� BEl�-x�0:p�.�#Ir��G��c[B|���qvжol���t6߂3�rS���.7(P�3I�L�T�!�g����vt~��m��j��jJ�^<.�6�o�V�.��:?��S�P6o�Z�`!��۶�f���&8%a�Gyơ�B$$ �{U�c�� m�R�W D�W�Ѹ��%�۹{i�N��|��Ho���t���՝��T���շ!�Ϲ��5���1 �����7E�>5��&?u�n̍��IȢ/Z�(������z�4���VƆ.@�"�]+PT�}��{�V)��^��n����)�j7@ZH�v ���2a��֚P�@]������2�r&��`�ϟ�f�wN3�4 endstream endobj 735 0 obj << /Length 1544 /Filter /FlateDecode >> stream x��XKs�6��W�R! ��ޜԎ���q��3I )�(R�#�g�㻋eJ�S7�Ճ-`w�\|���h>�F��N���H2�h2Io{ �D8�LG�?O^<9�'� �x�A��yvz����b�r���n'��9���A�<���9G�p>�MNIlrzL��7o'g�ω���k�܁g��2���d��A 4N_����'�I+�~�կd�zkÈ�$�L~�|�T:���]�� p�*L�6񈘔ݪ�zGI'@Z�=�e�N�F@2k��@H5E #�HB�#b~��� ��Y��b��%^���U��ƥM �!�XV� 2K �E�B5mUԴǔ��R3�g��MI�����W�O[����/|SU7U��]�����P&?J�?`1W��D(�F] �!.��!�)����'1/Y'ﲳg��*�'L��Ve�Z]�� "E��#���a�-lPֵ�X��!^��+��K���������^S��jW?���*&<�W4}G�� gf7���yDuC��L��ݼzP.6�̆�}Fp�\�F�0f�ά�2etC���/]��k"��;�N�������[F�_!�Я��a�m=�=G>T/S�q&o��_j�����w��Y�\�MکA�U��V�`M�=�lF��!��ez��gC���� ���U��hb�Ks���"�]\o�M�U �(�����[����1F\@�T�z�f�e�"�6�Rk�Y����&�2���&�"�媡r�J����-�䦙�2� �bnd���Z��{~�� ��m�>ށ��+�EbYZ�XV�T"3�U��D�j��Եzh���D��� ��U��N��ݻ�i"���qi�"|c�˩$HO8� rjUcJ��FGt�x�\b=3�[��zd'�I�FׁBX 0>y��j��z�t-�U�jԲ�� ^����^[Z��� ��`j�)�F"�Q/��� 8�j�0�V�TC$v� ۘ���� Ȗ��N��3 ��ȸN[�Zc��t����wR���&JXE��]��b�bh��i�4��#�o�@�?H�b ���C�֞�9 ��)o���>=�:��2��q�r6�1Q�O�̦F����r(���j��9�ٞ&uw0P:ΐ8t�H��_�E�b�~����Fu�S��� ��,|�w�9�}�����Z�U�l��ei�ގP�p�/��c!���;�'�gY= endstream endobj 753 0 obj << /Length 1822 /Filter /FlateDecode >> stream x���r�6��Щ�fB� �Wo���nc�c3�t�h �`S��Gg���ł�(��������b��7���F�藃����/�,�`��G�3 ��9�%���c���0����?�NN'g�8��8��dz6�=ϳ&��م� ���1��O&�O�o�޸���{��B����Hs��F�p��톰�#�h�7�q[d�*����p�x���5��rlº�Yce��w�! 6K> 0uYDA��d:�y!s���}" ��ފ9Q��Z�}neM������=�� �0 �ǟ���f�F��Ƕ�ծ�X)MkU\��$:��E�T����%U , �� ����q�-�B5e^��:�4-p�V/Hos�b��+��|�J+����bp7D4 eh�z��mn5cn�D���0)�D�,�F�6�2d�(kY����ue�A"TZ��36t�d�+ѱU����<�%���*���3�z�,k��`�7ә��J�G�sb�,����Z�r��Z�M��}A�����s㵢k��Mb�ZɁ�5�������Y��d/�Hs�y�U ���Y�BkV�̶�ȇ��Y�GO�6H8���\��-�� q14�w�8��z�1���i<nѻu��G]!,Ҏ@��,��9�6q.�����h(D�� J�v30hj��n�����%�����p�v3�D��`��f���,�fp�3�3z���s���]ď�~���G����r�-�~*Wx�4�)XN-5�l鋮`xr��Ӷ�N���`���01�貏�* v��<�F�!\K�L�4ݤ�u�&xE,�\h;�5���|I� .3����3N���;��D�d��"��R4rI獬���N����2+�.������z�8ک�UV%��2-j6%u�K3U��G�  r�c)Aǿ( {î�m@;zo[��kA�(h�үH���Dse�[V+���Nk�]���tE�T�%m�䉤��Lki/1����2���\o�=���(p��~~8�����rv�IW��6@E�C�|D��� ���w���C��XQG�r�L �J�� Y#���5�"CC,*�G_���t�9��<��kPj1��4����{a gi�8u�A@W�}��$�u�Y ���Ø�(z��_X��PS�g�i�����L`��[�p��#"��Ӥ��i��85�sUə� ���\<�� �-�%�_�'��i��8����Yߠس��TCA ����o�~��ǂ8j�u�,8�R$��V2�uș�07X ������-a�S�i�x�m��l�J��y�a����^���0@C�|m�<c��"�����ЫԒ��0���������L��Gl5 !uB�B�KE�e[�s��`����qY�)Э��C��뮦jWM��Ԯ\�K9�0?�W_�8~��oYv(� � �? 8�y�Nv|�žNӬ*+l�bg-ʭj�l�N��&�˸q_��߭��pJ)\rz��0>n�{�9;6i/���M��h����A҃]��ڪ�.�/������ݛD�`��� �z��9�[��=�-ÝX���FXo�ǿ�$ض��Z�ݫ��F6O�wJ�Cͣ2O�{�%���;U��a-���"0��o^1P�Ӯ�����k\�Q��~��|����ޞv����fR�Dt�!��6P��Z��iױ���;=� a���{�n��4�s8b� �G�w(�nZU U@.X ��e\t�����܉�����l�\���_��� endstream endobj 772 0 obj << /Length 753 /Filter /FlateDecode >> stream x�mTMs� ��W�g*�@��4ubgZ�k��$9�Jd�A(��뻀�ډ��}�>�> ��#���s>�����p���K/#^BRL�����bt���^\���f �s5�����>c 1<��$E�%,]Ni������C�s��,���`~������͔�����uxA��(���?T�ilX���M� �ʷR%���g�T^�����U#�:����@��4s m�=�� �a���n�j%�W�����JC�d�F��B�P�=S6 qF���)�:�"�7=�G���n�D)���X����q�iiˏ�vۨ)Ѓ��e�K�;G� a�>C7�p��.w�ӕ��|C��D�����Ϣ��|�#ãZ �7��Z���3�h��4@��r��zH˵+ĕp�=�MPc�)t����"]+ʮ�y�tM?܊1���Qo\�Ju��e'��z��4 O(�-~P���w5וܘ��І�o�רWk�;h\�����'1�T'e��Ze��K�W�F�݈�����n��@�E�-<� ���_��M�Q���'��UW8���nt�ײ�ժ ᭨�.2�Ԭ:Qa������ �����Q�Ġ�n�\�ؒ�f�;MW����L<�c��x���� �� �N�X|rʱzOPHЭ�}�]�r��EO�����$���Jr��4N�x���ソc���@SlQ�M���2�*4���q���)�0L�H�h3|g��EƘ� endstream endobj 668 0 obj << /Type /ObjStm /N 100 /First 876 /Length 1334 /Filter /FlateDecode >> stream x��X]o5}�_�Gx����ǖ�JmC(����!�W(��Ei*�ϙ-�۽M& ��r}���x<���Ʃ��$���5��5-q�XKb�YI"����a��&S3M��k��cK���ؗ���d�kr:�. ��!�Q�h6�=J��E�V�z"b �Q\i���N�H�<�UHY]����6 �b�a�Ը@Nk �J_t&S�c�Űu7A��:�Q��b4���`81���ՠ [��,F�*�?�:�d�v ���d��j�(f5,h�;�����a��xե`�nu2�����N���Y�xO2*� �Q8�5��D��Y�bCjs�Y��d*ip�)�΋��W6�Xs�� �IW�ܻH��Gs0��@,jq�x�Ÿ�)��K�N�I.��ԁt=��TĽ!е� ˨��+�����\g��8��0���� 9���c���p��%� ҢL�|�N%�H�Ͽ���”��o_�>�=���-�B^�Y`�����)�X�!u#^׬+����:���#eb�y����o�?TXN����_mϏ7��$�����r��:�+��_n�����4?�J���7(.�V��b�f���|�f�3�_?n^]�=پK'ŋ�'��S,sv���!M���E+�m��%��̰ˁPvrAJ�<1�s��:��b^�� �<ђ�א�ò�҈g��n��G��(���;������}Ե�;�~�t7��y:�ƬҲ���i�<2Q�B���g�+���*{�P�N�`����r� ��۲a��Y�q̫ �Dn!OͲ݁��d�!�-�N���%2�� i\�ĩ񪍐G0J�X �2=�7 �*D���Y�� ����?}�����ڼn e���6���֚_<����c.�>4�e;] endstream endobj 778 0 obj << /Length 683 /Filter /FlateDecode >> stream x�ŗMk�0���+|)�M$���[�nʖf[S !��$���b{K���#M� MX�?�#��f^�4��h�q�.���c��*���&Ji��*d���U� !Z�xv����b:�#��`�;�����G6�_�oE�a�~xw�m6�L��O��>C0���`71��SDu﵈���E�ލt�m�v�T��I],�C�7E^��ol �6��+O"Z=����]�ԝ'�d��8�^?Q�W sj�Aw!@�=ֺ�I�$���جl���ޖC��` F:� �U��ω�G�j`�쵫jg���� p��NAK +ݻ��]lnI��e�; ���׋R��%���x,��\���a�� �)�J6F��U�w�] 8���v ��q��c�%�����+���mtXN��;l=��ޚ��_�[)^SE�YHᔃ�b ��n�݀m�7-�����Oc@�5�d�Q��m�kGc�=�('���!��|��o7��V���w�aT��a�^m@�(G�u[�f�#S���['&�2�q������'�4���9O� endstream endobj 798 0 obj << /Length 1152 /Filter /FlateDecode >> stream x��XQS�6~�W��c3#aI�%� 2�脛t:I���s���N|W� w��Kə����v����Лy��z�h�wpBC/�ILco2�����aĽI�}�Y|��98aɚ���-Z�W���M���1�3 !�vS�������}���MN����� N/�&g���7���q{a���a �����9�N����>��W&Wׅ���ѵ�<Ƒ����F߬r�Qݨ4`����F-��[�q*!'!�~؜b��@ktY�UYl� �eԛ~ڈ�� qJ�0C$r�eՠ� ������6:��=�H�pX�<�ZY(������ƨt��a��S���qaO�G8f�踬�K����b�ڠ[��2e^��A�p�����������@U����ǐDe�@(�W)�,��RF 1�,\����˪Lmh���$�;�U��ew�8��L���T��ݫR-D|=UD0�tg:8���f�9�; <��O�s�:�����*mV0�l_�_ 07�K�DC'�F���n�X�T�\�C��G���Y�������_{��d0�B��$IK�X?� <�j�e(�S���K�o�!�)f�����B� �F/�E^7�@�`I�5�4���1P{!ƺ��Ld�1C�.�u�n�'��66�5�� �O3��)ӊ�|�ey��})�o�nܬc��U�3]j���O�� ����1���e`��_wgt��7��5��s���Ź��F���6���n#���NU| ��o�#Ժ�"�m���1�gsI�7"ز�NT�†B> stream x��]s�6�=��ZK�d�>:�$����A�u��g_m�pL|w��}$�&%!<�IZ��[�+���I8�m��l���(�dA&����,�$a���̊�{/ �`�'I���>><9<�M��;���7;zu:��(�����u�������9:|;=����%�x�, �( ��@����4����x���D��qz���:7eS?#�1ߢ-� פUo��Q�rD �g��ZWu�+�C��ZU�We��� �|{$�# ��� 7w�����Nԍ� ���_8��-���rq�R��i�����%\&���x�8x)��<�Fs�0�s��F3\ ��sKt[T�mߙ��F�Z�-�8 X�C"�R]7��!� �>j<�"�� �t���>���}�7U���_W_Q(�[����%��lW�N>_ġ�!!�N�B��Q]�RU��}���1PU����K�X8��� �Ѧ���]<�e�9VH��k6��Bx�Ko J7V~��A�\a�"�w��)O�K([@�����&���fah�R^b����0f�9h��oP+� �yuYnP������} �q΁L�kPY�%���#�lP��2J�Y�v ����#�f��ܠs�>"��D�&^���wV�aIDZж�jZ)*wo�uv��K��]�\����-�� ��:>���D;V�2^���>fe4��������*�m�X;�܇+4 ���T@�����+�q �W�.��q�ꮯ����r�L���������J!@z��n_� �r[g䎣p�4^��M9�#lc�Ć�_n�2���-�v�vt������N!05z�w� MHP�q�A׊9jЦִ�BzM����>�>��# �Um��Ę��h�W^�]k��djH!fq�5� G��=��0���(��d�u�M���x ��,��4�q��D��r'�D��H�����[��+�F{�#wu#���8��v�&H9�������#F!�N��몥�=m��I{Gf�����+��X\���C f���^�4�L)����[�Y�3(-�����jL��80��*�p��Kx:�I�H��EN<�;H���,ri��lNf|Cg��Z]��i�X_dvc�w^$�2ݕKĉw�цr���K�"�B]�6��Φd�e�Ug�g"7����<:�;�YH��G�z �p��<�ܮ���)�Z�@ ��}Y4U�Qa�t��@8V�6>T�4m�[�a�t�âP)���#�X�w4͕5Yh+S�C&�TI���*mZ�r�-�!Y ��!�F��J�7�i��J���m5����#��@]x�6X ��\��2��po�B�^3�e٭lWDێ��h�����NY�����N7]�(����:������;W�ꂀ<�x�.T��K�s~�K& X�y�4�eYi�[uF/F��$ ��Cd�t��O�)�ᄡ�����Z. l�zPo�K�˫��I>��HC,�0ا���Z{kR/).�� �4���WD8�@�/��n�7��}Ǻ7bC\�Ʒp��o��ˢy�R�oKu^��x�A����Eӟ�2�QƯ�4��ˁ���6B� X�F� q���|�q�"a�������*��1W *>���D�|����ɤ�K��B[|�JHp>t���ԧmR�L�> stream x��XKs�6��W��R3%C��+=َl+#��I�Is@$�bL�*�q�?��XH�lf�i{z�X,v�}B~������G��˼,�^>�e~/�S��Q/��>8a����~qfD�g^���������}7 C'��n���p K�� u���7���0?!��d@����|8>����N�=��wO8����Y� X ����Q? ���袮^��<�8�^�'+�gR�V�%n]¹�dk��/���U�6�"��)_�~$�(ܠ�=?M�R�j���7q�d!�%��������]� ��r� {.�F\��Y����3^JwZ(9ѵ�u� LP�= ��~���H����Q��r%oq���S�SW*��-̎�-����cI�-���(����0�� ����ȇ�C>[ԟ>ܚ��Y�v��%^D���_�~8�����~^:x� a�����r�!4��짹Ti�E<{�к���j����$��� ��]�f>�]�1����S��2���� �,������#��C�0/��m��&��\Rg�TJ���B��v1�����zFg���te�,iD|\��T!>2�Q/�,�o�p�]���9%ie��������J��-M�F���7�ı�XfU�Un�I1A��Y��h/�rE�v8��p�b}Ǧ4 �+��5��XtX4 vɥ�W�2�@N�MW�lK������XѮ��m�z���v:� �.��� �U�HB?�n`� cPAA�v���2N�L��ν4�)������q������zA�h�m�[� ���6�j����v|1<^��s�,E�~G��j�o�g�l2�`��w�&���x�?r�p���t�,��;�q��'��51��F,:%Yc �)�]�W���>��Ŭ�a~�f0�?1�b!ݯu�՞%>q�,����EQ�]�bHi;6�>�ķ��\��B��� �S�ka�VhR�\���D�ڽ5�cP2g�h�P*YM�>&2���Vًf}�zq�ѱ��r���0�qޓ��a�WP��]E��9�搉���=�F� Z�. �a�J �۲��cִzaV��eh,3ЍF� s���mF�~S�B��J�.���n������RL���F4�T�~��l���J��qݙ )DC��ލ����� �� GЇ���j]�H��h���7s �(�L7AL�'!���ќ�bZ��:c�<6�Bݥ����x젗�E��j�b��gy _ U�O����yIwE9xI�X_K��x�u��7����.T]��O�xׇV��?���T��LaI䗢��o���f�17E��ʊ��Gޣ��E]�ĺM�F�`֐y��%���X.A=S/;͆�tg�YcC�v8+��Xj��(*�d��� ��p~�RDz\��˶��̋�'}�2����gx��g�T�]j׼`*Ð'O �%�ߍ�R4MpG�+Q> �.��W��ߔ�g��������)��{��w� endstream endobj 850 0 obj << /Length 998 /Filter /FlateDecode >> stream x�ŘMs�6����N.�O��oOh��' �L��Ҏ9��=���/y���w���[��.���]a��ܜn͝(��/SW��1�" �j��3���gCJ��l��處b)�f�^u�na��3UB�Pl3�������J7榩`� ߘ�=S^ڦ u}�Ce��j9DD�80"s��6���� ��J�|���N �b�[��;l�˼m}P9�T�G�Ey��j"�X�,Lq��SD�p�|��7T��q���8�gr ?�cw�F�"/�5Z4�Zt���W��N����n8�$��tL8�n���Ժ��ڦ��<'KA��|5���(!�i�a(%N�e{ ���;M̎/\{MX��u�� �ow�� ,��T��nH��}Z��Z�cj�qq��js�� ��ڰ,*��z���{�h���b�y&��f��;���QBC��'mJc`��#�?�����q�M�I]؃�B�W<�� �dg�1m�<�y���"@~��*�똚���e]L�>�`Xg����̣D̫D{�&���o=�L�� �aYJZ�(��߱B=s��-� ���w�w7u^��|�r�����,����kS#�Zg��ʰO�8�k��5��c�K���K6J��}�8���\�Z�]BC��ES"��PԎ��k����ߡF�u���F��zQ�bHsu;�Ppi���x����<�d K�GaV@X:�5�0|��)�F�|wp�b�J�E���B~�����7E~Uj/?�����T�k���B�ns���̂J�_UN0O�C^:IJq��^�����x'��x��~��=q������Q��(�O2���ڧ�4Ʃ�c�>��]�n�0!�cp��:��|���?��x� endstream endobj 871 0 obj << /Length 1356 /Filter /FlateDecode >> stream x��XKs�6��W𔐙!�I����ʱ��J-%���MB6k>>�h�?� �t$��5�cM.�xp��]`�����ѫ����V�B���|a�� �@�{�<�.l&�����#�M">w\Ƙ͐���'g :p�����������6?���t6���6�'�O��F��oK9��qb�43_���s�Eu��Q�ӵE�!*h�k�f�'�Q[�MY����0���/6�(��~���ȢNˢڋ _��u�q���C� ��äӳlܤt\�/nsY( ��-,P��#�n�p�f�E܀BCXx |�{Y�m�~v����=F�JQ4ۀaR��57�0�-Ye���6�Rc$����ի��y�/�n�;8��}r<ώ��!v��6���5�����K 0!p����݇0�c����� �iWe].�����a�]�Ȑ.�X�y��܎������8��"톴9;��r)B��$�a��<�غ��[:�߂��ڎw3$����ῡ�Vlb�Q.�JM\�YZ7Chq��9���!������F���U��B`�?i��8�X�xm� #A����$6�d�ۉP��� �&�o+��q�H��7�n$���H�*��!Q:;8�)�\�J��Bvd�w�o�#�q�/�L��!��b�����1�taڢ4�6]�/��_)�_1晥���*��N��a΄���9�n}#�̅�>��d�ޡz�}�ʊ}yf�5q�b.�O��!GVw��Ut������.\��Y��"�*5-靜�(��q��,'?�ɿ�.�1�э endstream endobj 775 0 obj << /Type /ObjStm /N 100 /First 874 /Length 1165 /Filter /FlateDecode >> stream x�Ř�nG���)� �v�_WK�y I D��HȎ�H��sjĞ�.) 4g�������3�\Z�…���ʈ�(��Yhx� w��ָRቿ���|�E{�[Q��(�p^l�f�AeL ����и~���9�R|�aL-38�4�D^mf�F�ܻ��K�� $Cx)�� ����Pq�_P$�CxDր;"�uD��MB �yD�!�v��h�w�2!p�1N�P��BP��B0����Q�A9�Z�ș"r&�/i���1�f��&g4A> �< ��������-g�h� U�4P-M �Tg�9J A�-�B,�a�,��X"c�P�F0�/�Ydƴ;�E`�NX,j Fc��@@�h�!��86 1�Tq,@7D��9�e�>"��3nxF� ��I���L�8���a� �!;�C��t}`�� ��VDZđ�n�Ed�g ��y��8���ct�y9���o`���o߾:ޔ/C�����������#�=]ݼ�+�X�������ޜ�/F]~��������X^6�`����y��b������]��PmX�)��"�k� �qƩy�s��N�5�ĵ���b}՘��k\�����+v��VUr�Ƭd�s<���-}Z=oKW��J�.z� �����q�ߡE�پ�Psk��hC�3 5�4ԚSp�9���L9E�[>�20��o��Qv��� ��Ӽ\6p����y8�2f^.��3��N���*wN9�vd����r���Ud|�k���k��q����5w�\��xV3J9��H%Wի���v��R2b[N1��//�O��9�r�U���9S �z����]�$�fIr{���{��В\s�ȍf�u�D)���������+�d &]r��sMPF�cG���.�'��\��{��S�S�:z�U�Rn�C���Ck��A�,;��2s;�f�Ú�����v kn�v kn�v n砰�v l砰�� n砰�� n砰�v k�;���>�_�w�|��F��u�y�]kN{�n9ױ[޷�8���=�v�y�Xo�� ל�ڛ�\ç�ߪ�mA�x endstream endobj 891 0 obj << /Length 993 /Filter /FlateDecode >> stream x�՘Ko�8���:-�X�E�M�"�m�h��@ۃ*3�Yr%j���;զq�8�%����G��<�ѫ��ѳ�#���2�."��+����Y�1f��I��*>}�ן�7ӳl�x�|�X���=�$��x�!���K�<=v;��O>g���P�f��0K��`B;�#<�%���G M�7,H�,�8�}]ز��9]�-R�Zugڿ'�ƦM�иp�+��&E�tf�A-��l����R�V�k��Ft ���+��AB�5 ����n W�n@Y]o)OH*�p刀�����Ӳ�&Dă� @��o���f�و��@["F�/Ѷ�'LD�۲�'K�)kG�&����D(G��!O�oW�;�&Tl[?_v�bO!MS�ɾnl2���_��1�f�cΗ�C�-iMg�֎1�p Fv���g<�J�C\y�v,T����_bs�8y��bY�|vI �̫j��(����@@�$�?9���o��c� EA�*+�Ƹ� �,���-�/��"W�K=,C�Kj3��Λ��]�ԥu��c�8E|��C���=���`��-h�+R�}�%�|Ձ�/�:�����k��r�`,{�̈́^y{8Igb�&�H�D��;Q́E��&,)b�I�-{�����Y���?}�aj���y��&��Ӂ�r���S-+����;�mµ5�o�p��Km��nC��m��h�ps�׳ ����e\�E��~ؚ�=L5�V]t18N���ø��n� ��t} Ra�!|�y��9��VF�fm��؇NQ�C�q5<˫$��`2���ԏp�@\�z� �����r_���yX��讀�[�! �a>��լ�6� ����p���Fp�Pڱު���O�e�m�@J��0�/�������������η�z !2����0�\F�a����m�Ce`E�! �Zr7A�����F�� m��ܼ cE��%ط�� �8�z��#X!�ٽg�TL���L��? endstream endobj 911 0 obj << /Length 992 /Filter /FlateDecode >> stream x�ݗOS�8��| �:��J�%��fB�C�O{��`l%�lbge�43��x�t���"�W򫟞Gz��Y���o���#�UL� � I��<�2}N�Qu/3��v�.f|<�H&����F@��ٮQDd8NN���C~p���?j���,�����u3/���p��.:6k�1T�߮������ߍ�����Z���������^����7�2��:9����S��*��Y�.��(faj����R�}D��)��>1�,�l<�5�ؓ� `��%h��+��=��ؒ�ø�1�<��I��9�ǐ��>H��+6z3>�F�t}�W�q�1g��`ϳ�viݍR�m<� 6��g����r��~[O-��� �t�E�j�qS�������� C|��?�R� u�{�?�u�nb/zX�j2&Cq�Z�[��5R���Rƃ��z˴YW�^j]U�E�� �.�3�&4�zgXS�ms*���43Uuf�ut[�6�]���r��E��dC��]5EoyM�MH<�� 0�*��)@���;�r�i !^TD�ۄC��[�EZ׽��D�; �}{گb��~�i�b�; m�ye _��@C6Lq�گ�A*:��ǩIg���XA���ՃQ�F�DD ���V�^" ��B,mj>�p�|��G� endstream endobj 931 0 obj << /Length 738 /Filter /FlateDecode >> stream x��UQo�0~ϯ��H�k� foiJ�lmZ5H�����aM��]����1�Š�L�'�����>Թs��vp� ��X�D$ ��IND��JB�p��s����a(����<��'�+9���d|9q1c ş�x2m���G�7��S�6y|�ӽ�c��:hJp�� hۓ�9��p�٨�ҙ)�)2������{��$��Ro�~H��H� י�|�Tk�ӓ�Q��s7=�}���VE =�=��Gɷ��6B����P)���o���Ğ��������hQj�~�JkxtE�\�>2��2 ��P���jm�3�#D*/��T��] k/?7�$����{kďv�Zee1�뤡��<��Z���kO��x��ƞ�� }�#��}Y��d|n�m��~�i=kD�@b�%[��jZ����+ �ʵ™y�}�$���̬�%<{֪Q��!&�,;i�bޝf 6���z��Y�X����Y7��췖�����ӎ���t�O>'�j����+Shh�cɻ��"�'��|�ʍ��>�?�_}d��Auix��ժٻ�G��Ø�����Ș��|�`�Jk��Y������k L��i<���N�gXX����?�*NHoq2�$O+� endstream endobj 940 0 obj << /Length 141 /Filter /FlateDecode >> stream x�]�1�0 E���c245qh��Ti�J��Z0 6��-e@L��{�?� q`Q�!�И� ���h���IkԝǺ��#�l��h9�q�Ԟ8�UED�����2�e�*�e�y*+��9m���4͜˰��r\� ������ w) endstream endobj 949 0 obj << /Length 2652 /Filter /FlateDecode >> stream xڝYIw�6��W��2T��C��6;�H�F�I^��DBj&�d�dK���� �2���n� �|U�ރz�B�{|{�Ϸ*�D$����{/�$TA�x����?Y�mo�ÅLc_~�}�T�fi�Bo���b�pl�e�7u�{����M�^�H�.�0�]W�ߵz�~>̤��p��ܯj�����m�X�����a���Bd�a�fڮ3��5���>���lie����ʯ&��B�<|�f�i��L�U���< �nn7T���l �����_�����n9:>���+A���� \�-T�i�x�( ��*�4|<��u�iI�����]i�h�ۛ��:��j{��l#ع2U�{]� xQ�MK7 ���<��7 �%�b8X�_����Or \���_���q~��Q�D8}���r�&BI8�$`�����A�?ʆD/v�#:���u� G���� �0I�>l�}n()�}ؽ�A���AC�i"��h����P�q�D�W�D�����.��{b����}�U��A.�ﺕ�e��Ao�����;rR�]�d��%@��Gy5N�-�����d��$� ?@������x<��4$�?�vA �eU, ��`�8� Q�������H�A��bP�?$U1���+���]��D��SY�1�a��6��OkCJZ/� D"|5Iw�nHw����2�i�j��n>oE9���e-�N$9�{��L��_# v�d�阇������5���W h.�����]�P#�!�����c�{��٭��=����P!2h�����~1W�mw �B���t�� 0<&(�m�+Z�� D��pV��H}����Q�#`��M�k��γ����z.�Ih"�dRŽ���ly����ba���ůG7W�W�?�%;�b_mC��z&Cx��zCZ@�)S�5���9 �� �Yǀ�<95��z���}j� .���K��`@����<�/@�il��c�.l��`��B{@�A*���|y�\�]ϖ�i ��Ў����Ȑ^�r11�����3�L��3�� b(�v ��`LJ��Z8������@�-� ���}��*[��\ #i��gEY�e��= B�Ձؠ��=7 ��[nX�.:�3��X��%P����񛻇*\���~�2�x����l������a>}���f95�0髍��p}��P�s�Н���0�"Tb����n�� 7@� Eu�Vw��Qc��Lip�z��ߡ7J����v{�������i[�+@�O���.X�#��"n��n�:�\W��T��\w�d»Q�˰�Kp5�޼E�O &|��L�_�� �����Q������B�68�| _��8< endstream endobj 965 0 obj << /Length 3677 /Filter /FlateDecode >> stream xڝZ[s۶~ϯи/�L x�t:��qg�Km�sz�>�$m1�H��������x�i9�Cb�b��org�3w��W��7�,D0[��bw�s�?[��?)���-�x�`���<z��g�V���y�d�EFΫ��?~�7��}��@1/\3��� +p!B��H�>o�yI�K9�qƑ����h�H�LnǨ:���Y�w�'k`�A:�u�d����7�"�d%�oU�W%��Y�7��У����LԶ���R��O�ݮͰf;�=9 D��r��1�_2�dz�,�� �������퇳��� \�H�φ��?/b�E�{������_G�G!sݰ^�Ǥ{��wg�O �l���Cm�� ������D�(@�̓��k[g7�����S�7��|�]�u~\���t����lﱪ�] �u�._°E������'�P/&��Ht��E�~�w��uRh�I�ܪ䫺͖0,+�-�[tR�d�]����l�rQ����h����G\�U/��]�j��ddk�4��ׅj��7$A����p��E�����m�jT���6OԃU��<�;�=>}���6�/&�1��s�Z�&mR ��$��F,�ñ�Z��/� ���W�1V3�[�(^a�>��9��%�7����9����H4�6�(u.�65�>ԝ�@��jO$�g������@N/�7���%�9�z���� �� ��?0�ц!�Ew�@2�G7�3���� �9�4�0�WqO]�F��olG����-�=��Q� U��i5�ځ��5)��IK#^Wb�)Z;�&kU�ZՏՆkv3�[��j�!��gۂ7�%A��7@�� �#����MX���­\%�)�C#�y�?w�l*�>�BaU}����� h��͢]���6�[��U�5�~rr@'�a!]p�����aw��e�.���tnTS�>�Lr׈q?~ do��< tC�a�' �%�x ME>�I��B/|^�Z8�o'P8baj�FB' ��=t$Q�^O��u]��0o���x����D����� RN�Et�����92T AbK^ OX���o"t�feV����3b�8r���͔Hi2��vuݪ��⑏L�P0�'������?Ll�a�UIj��%��-� wGZ��^��t� �!�OTYV���'K�P�m֎�ؾ�[�Q�l�B����y����w����Aa��@�s6Ek!A�� �|���� v��*$���CxKm�(��|����ˍ�.��}�m�D��T5�"5We��-�����gVo1��Z�MH}���%�*�J"��d���)\r�q�u�'t�1���5����ǜM{�$A����2��~��X�~l�v� ��#T�:籣v�1{n ���0��5�ÿ��A��F_��'�:o�ojz{b�I'�{��J�]aVp݅�"��6&�X�8Ȧ�E����ȍ���YǮU�a:��~>�D�?�0��\��ٿwY}?>���) Xb�����88X�K}�?�?��:Z� t�y�֛Z�nF��M�M��'6��2>��!�b���.P��,B0�.����<���b �` mO�w�7 �+���tz��w1���^UE{��)u�MO���� ��2�ƒ�b2m��A�mW�=45j/�7 ��u�L�}�fK�4�yaF��%��X1�tH���.��_�S^ZiVu����جL���合�w����@��C��E���8x��%�j��N1��Ub���мXg�f�R/t5��o�a:�|����sF^"C�{�%�`!�L(����a\��D��dOx��9|�™�@c� �y�&v�����7+�1e�JA��2᮷?u|�r���)�� i<�^���Oe,�]��r*Udq4Ɉh���n �.<&w!C�;8P�h��a,<��� 3���$�7���{4ţX� <�g�Z�cl��*zxb:�Cح��9">~��:*�����3d��VFiT ��ޘ�3'�-=�'X�:K�Da�1A�}H ���S%Q5�ȗ��<��t"u�?%�cB�i��,��`�u���]��*�P�6��A}�ޢ�j �ҝ�eá�>�J�<S�;e2}�K��#�i,���:�`c^ȟ���A�������Y�@� s���D�H0�/3��ԫ�+u�����4oU�t��ƶ��YIU�h �bCÑ�� �_�v����� 2L�������,���KB=�V׆����j�4�Ӽ���ĻR7|��\�KǠÄ<�/T [~��%�k��߳��'z��6h��X�r��Ջ�_౻3���=�|�l^��;K��ֲ�8��� �U�\���ů��"O����O�Q`�+�xp��� �� !3���E�dW��5�t����:|�^5�;�t�ed�8�MU�`�G�E�}�{�,W�pXa��k4��e���s�ku�YT{Y��yC�̝��a$}�_Z�L"ANo��R�B.zrQ`�S��v �8K�����_�d =�%�E���Tt��G*�!��0� ��s,�i^J7$�U�v�E[-Rs ���j�:�j㣳_@Ddn� ����J��ه�Q��Q�=Pm4�,a��j���'5?l��fK�&��͔�+��{oS��tSm&#����@3ԡ��ǰ�kO�'�v�7�'5(<�B�������I �E�j��Ǻ�ǫ�tdo*i�H��z���^�M }7;_�ϡd�򠁵%,��A*M�Q�5��֡���2�R#��m�xߡ�A+��"*�C���<���l�(�d�,O{�z�XSWn����$)xDzu��T��wCz8x���є]���B_1Aoo槍��ă�� ���SG�\ endstream endobj 979 0 obj << /Length 3819 /Filter /FlateDecode >> stream xڥZYs�F~��`��`ʄ1��J�J���Q,ykk?@��B �ʯ߾!0�+$03=WO����Yl���g?\?{��K���n��^/g9�����:_|�|۳��(���e�['K7�N�Gl�x������b��<�z{~��ۓ_ή��z��uF��ʳ/�)y�i�9���ʴ���xLUt0p�XE���j���n;�suW��f���hC���'\���ߝ@-WA�X�wDTWܥY*�, �Ju���J+����eiUWE���_iW�޻���2��0��벬��=rƬ��̲V�c��J); ���֢� p�����{�LJ� G�8� ��4�u?�kt^4:�Z�.V��t΋6K�x��߷�i�i���B��i�-l6[JeQ]�vzn�)���*}�|�\�D�DV�\MKn���� 砢^� /t\��0� ���[�ݮ|`&H;۽�ynh�al��������g(�32:v칆v�W� 7�l�$~�̼. �3���_�w��<�����ax��C "��FJ���O�f9�U�;���u�aT4�,қ��n�*����wtR�� �@�T��͵��9'o�o1�������zf_�R��C�պIۮ��up�-�@Ex�}ٵ\��)*T�N�5 �n۴)J!��q���V���M���~"Em��+��1�v���f1.����5��ȋI���xv�do��Ma�1����`�P�V��!����[Yv�9t�ű�3I$�q����vl��J��~?����k�H�����!e}X!�:�1����Ӌ��=p\��-iY�3���`V��4緌&g �r�v� V��z Ծa:�T��� m�ܡ ���f{Pd�9Ev��ٔ�];����/���hw3[ ������xF�:=tp>X�:��PK����^���ԝ.����G��C^�l-I`���//�a�?�a82g����� ��Ay�Xh՟u�w� b�}�!n��Hm����f��B��H_�I�g{!8� �U�t�\Ů�%hފ����՜��;[����z�/�=����?��A��ځ���q��l����ATZ��8�^��h��̸ʋ•Y.W�o��X�g�~G�娾��w�����T �o���?�����w�j�CS���\�;s>�c��8�?��[].���!��A�e���X�c�τ;�Ws����8�w�>Dt�肮;��������x�6C��c�u�O C� Q�q��@ x2�!U�o�uvдq�l���cz��e(A�ߞry[����=(�,��a� @ &V���sQx�N< !M�����.w\�N9<+QaC����� W� m�}�:��]Ab�a�C������>\� �)d��n�h�f&N\�j���$�� �Z<��� 0Nѓ�8دY+�� '�Hy�DG���Ɩ�����ܙ��V���Q~6���pf�(}��` �w�<� ��xá�@ w����A�}��d��o��S?��`�\�)�԰rS#�=P�1�Ɗ�,�n��b�.�n�A ��^;��=Z�g��%T�� "1DX�lԘ��<̖������hh��c���r�psp��Yef q L(�!�\��- �5LA��`��� �Dɡ�(K~��$�TU��8���A�r��*e]uL�VӰ�P�$�g�R��!��\�H���â��� ,��tD����AϏ�� ҇�8�������s�ҩ�p*�,��k AE��H�e,�@XN���@֌�ZJ�^8ak��FO|fN $���G���c�ڇBD&!L����r��Fo�NF21PO,%:� ��N�+`��9�@��}#� J�u����q�!�<>"�no�n����3�Uz� ��^%rd��D$>X=�9(|���2*A ���'�D�0c����Mפy��'����WE� �Q��o�*T㠎�F���E��2��Q���ORYp ����� �q6��'���T�ڇ�D+� ��2C�'�#�T�zU�j�XT��isS)�3sW&E .�2���ي�p�����(xk�P���&K[�s�o)�0nL���U�YÀ�F�*,���s�8ڗ��S<��#mf�|<�pN���o΀� �x��WA���K&ܹ���SQ72К���a��J�(�N������z�b�n�S}AD; '5ӏ}#ư�=�9�x����ȵ�}B����W�g��o�O���ݫ���A� ��,3YZ�X ׸�wX!IdY�������G�����gL�R����G5��0/��y��[��(q�� N(P�u���$0)-o>��ڵZ���̦��Z�^�9�m�)=��/f\r?��3[}0�(V�nj!��o���goN�_\�XI�շs-x�#���q�9���y�kX�ja� �d�8d����Q&r���9��K��sA�t��͚Btz2O�X-����G{�O�t��>X4M�}) �A&��P�T�pS�X"�3���$�W�Qd�ɀ�MI�[Y�## uxz��Ϲ!:V�u+��Elbk9�p]��؅c���s�Qh�{#f�q��QX�m���i&�[鼨��r`��RH�.�,����6*���`" 3&~.7�[L�B-��8�q@_}�7��߼��`)��;��N�H�F{囹�Sv�?��{E#|G �xi�� �6T$�u<疖w���m���4�'P�Ꮓb�����/����n / P��O"�mLlΘ���c�q��Vr�[+�E����ŏ��]��j��5����"y����|�jS��p�+�b����0'aB *��*�5s���1"�n{�m+�#|l)�ۯ���N �dy$�,��^�����7�f���� ��_�z~蒂�y���� ��r�r��dK��k�A\]�l( ���{ ���8ܙ͂�rŮ���&f�(f���OC�}�����;�T(�Q=�+�b�F��P��;��b{[7���u�A���a��+24�d�bIP���� }+)�I��hX���]kܘ�2�o����E�HV4�,�c�lS�������wcp}�P��-ˎ������M� � 2G�^�?|C��J��x�XC�!x�=w�s��0'��4��j��zz�m�����ts��q��*c��~���d��[!_��k,z�\�����EJnQ"G<(�i��#u����!���蝏VAvX�)뛡/� ���|���I��<�RC1�Vk��avH�yug���|�f�Y(��. l�l���Gg�C�O(��q��v�d�C�rq��7�&�]���d�������&@�xK�(���_O;V�X"M ;�z���X���J=���a�\�� |���|e�sI�!����vT��� �P�!�-}ug&���,=`�J��a���8W����@�MPjr���H�I��3y���{�M#�� �x����� ;жK��*�0,�<���-�H|��ƚ� endstream endobj 888 0 obj << /Type /ObjStm /N 100 /First 873 /Length 1878 /Filter /FlateDecode >> stream x��Yߏ7~�_!�^���H�(��E���^ �E�myp�I�fc���i��~�u��ڎ|�q�b�5��CR�9Skt��J.�®ڒ\$[�E�X��jkq�X�:*�U �sŊ�3���K��''l�8)�f����e1|uYmUW�: ��bkt5�J�Ji��!9p�t�A�0 1��0�U]�\��8� �2�i��%pi�$z��7q1��6qR��Ԇq�6o�RU��6.)����B?i�Pq�/�qT��mf*�-�6q��h[�� ��zDa�k�r~m= �]=^[�kg/�;�e���*� �-�'�k'�9J��{��!Nr��H4qA=� ׇ��_��G"�E�z0�y(��I�|��P�,��c [�ѣej�F̶�|9�]��Ķ�.z�A�Rލ.:9�����#��w�+�ɖ;8����np��� ����,���9q=������vē��5� �TC��p�g�9X]���b��ݚ6�l�<�D�uOo_�����������e��w_w�t_^�ac�N�%S�6(� C��l��c��`���������ҟ}�j>_�q����<���-6P��M5�͎�U�+���� �N�3/���&!B�Ga��0��%�`^��0ku1�J��m�GoT�uF�gA�'�w*�R� ����%����d ��&������}̐X��&�ɓh�8�H��#���.�2�4�EĚM�px�|�$�!Jh���ތ���҇�������C.���:�+TO�085#f�Ɉ�O͈��|r'������Z6�u��sfH��h`A �-d����2fj_>cN*�+�SBb ��=���S����I"H���(!$ ]&���a7hK�z�|��W�[e�����\����F�ƫ9��q�q�j����%���u}R�TdУ{|y9��š{�}������z�X���V������~��f��O�ﺟo���W qM"�-����b|ss��],��u���v���M��_]Lg?��G'ke��+p/(C���h�1��V�QBH4��}��/�����բ���o�����|���ǢGz��l2 �_���W�� ]N�Bw3̡�K�O�>`k��a��(��⹞�.򸢳5M�@�3lz�s z�m��� z�wef��n4���w�,e:gJٞ��t�#{m���\ZIWϗt y�v�D���8�>L����Ϸ��ۛ�jq����ՄV +���wfs��]��E�gmБ$ �?�՗��\f6��W��Q���"��\7<���2�ct*i�-�)��\�R;��rz���������B9bV(۽�ث�Z��a\#iㆆ���(�kv/æ}��>,���ߙ~�iH� endstream endobj 990 0 obj << /Length 2611 /Filter /FlateDecode >> stream x��Z[o��~���Pp s̹��q��c�n;�$A�j�+���rײ�����pxY*�E�>�;<�9�9�|C%GgG��׏^��a��0�tSWe�������ā����%�a��vǔ�f�ͩ�l���5�Z 벣Xj�H��O��R*�\�M���n3�Af�J]/��hN#R,Yl���]٬��]-bU #AGӛ�j(Ҝ-�y"����S�F?'i2~�͐�"U� �K}T��fv.����L��uP�ׁDN{��m����c~\�Y��#�y1v���K �rY� �B{�zC���"f^gr8ǀ�Y-7[�2�iVUs�tV�ǽT)JղJ�8P^}...��ٌ;bi�A��D$ޠh}��#�ޥ��hM�K4^��#� �u�q�?Z▵��u�O�_�&4%K �b�D ]wt-���֪��&i����:�8ѠS}�˚�؄��.6��"�M�\?�s�i��Iݖ��"��$^ҴoT/�T�*;'zg��qdB��� ���4nh\�99�䈞�|]и�1I�O�w���)�2u���R���:`3�<`3Y@�y��u���N<2O6�,-��芊Z�uF&�PE�^��Ƨt�е�<.��I�dO_���+��,� B���ÌgC��`����^��t}�q��&��.]?x sa������-�h�t�3��(��7P���-� m�Ж8[�c��%�匮%�������fp�T������ $�{���<� ����2��1�R ���1񟎉izx���S� ��F`�3�A�+)����~�>��"�ѾYb���yj���IB�]����L�0 ���7����1d0��O3�A��B��0�[P�/޴z�ZD�&��TF��_�mu�;h��b8i��3DOV@���ޗ��4A.��a�~��� �6뙍�r!� � L!�"������36C.�It����:�f�!�u"%��!@���b�,� By�84��1 �l��I0�t�������y'��x�`� �� P�D��ֿ9V�����U��oƫY �"l���)���:�|� ��YaCL���d��)�ப�Ƒ��9Le�aЃ5���Z�UM�+���Q@Ϊ�k���� d� �.��oa�@H��Uhs�z�"}޺��2ثw�.n�p��%U ��޳�����-yq~�f/@ 6u�>��S���>*�`�r{[�i �g[��w��%a-�4��%���|�X����%K�KO���R��F>�WG� &u��n��a�;X2�4۩n�(9��0��gC��o��H�� r�$�$����G�'o��<�0��X�-��P�`�xKk�E�V C��� �OT��'s�2x�~�BU_�&Ō�P�U|�����2�M�ɲ�ʖ}����l)��@�˖9([����K#  N���~u�!uη��|‰%����t:�D��J�/'0���`�+.�01!L��$���pJ��v�����s�5J8)�xgc!DB IS�ct���0�&v壏"���X���X� ��*���3N�!�|��|�jgʉ��۟��N8�L@ ��3�P�3]�9�&�&����X'�.�Ď�x0��'��5����BJ5��u��}�� wR�E�=T|N��`.ȧ�A�l�𹋹�`-��o�j�)�dY ���m�����'�� �,�՜�Nh����dsb_S})f[M&���쐣����g�{���3�������.�n1�!��k��w�>�KT�uխUc��� �v�@fa������/"X�\2�WR��9��*j�hE��F��{sV}����} s=2����5�����/��ݷ߾{6c�x��о��JF�0H�����{4ͻ�_{�x� �� �}4�}M�ot2��Fg��ۿ�7ZH햟4� �]��aGx�W���ҡ9��*��+Ԥb�+���k�E���V�ru+�S�<�7F��ǀL>�!�3i|7}��V���I ��1��B�|�"�ٝ���2�Ӡp��p��Vs.>wFS�3'��W�3��R=�4�$-I�14y:Qg�#U�3��A��*�=J�op�TBj�Gq$%�G�G�I�Ӏ�1���<�@�~;Q�Gb�}_V�t��# �#� �����z�H�z���ؑ�ox�-΢ɛ�#��?�[�#��[�#��&����b���'����T=��m�sث��Gpu6�j �L���m��fb��Z4���`$�.ܤ�>l�x^�f7���e&Gd������F�?O�#(�񍦫� �#�cT�Ũ�Ig�'u���������!�ce�oʷ'��)��d�՚�H�w���H)?�Ɋ�a N�+��= ���z�k�l��؄����@�Ӆ�7h����n� t^�<� ]�b� endstream endobj 1009 0 obj << /Length 2769 /Filter /FlateDecode >> stream x��]s�8�_1� ��-ɖ�U�V�*T8�����}Pƞ�s��`{��_H��8���a"k�V���� ׋p�����'/��l�Y"���j�� �A���e���S� �|�S��ߗ��/�^���RJ�������?9�8�����7"aQ� B��F��Iho}�FE�HR%�}� (d�E"�N�vŶ-��nֱwQ|��e���D�`$�k8#T�S����3�#�z�9��\���W�C��]Ul�-u-o������ݺh�Ӻ�I��E��WvM����5/�ꆏ#&p�uL��EA�=�-j��[�P�) ��Q�i�9/�eS,;� ��- t;L צNU7���˺��\Yo۠*�݌�A1A �ǀs��m�[:ǀ�N�?��,�l� SN�U�5�/cê��%��vf��&�_� �tǞᕁ\>��L���߼�#�Զ�� ���^t_02TA�%c�����s0��h� X�e�ƃ��� 2�r]4(��Z�:&���,#��ޘ�\2S��j�V,� 1���8�R�;�`cFǮ�v��� �j^�H��$|�@ʈ�99�S��y>���VNi� ���Wd���!8:f� ���4�i,i��w5��Wp"��X�� `���)� �%�5��h,�w;��Ɩ/�I�b��zI�N�j,պ[O���LN�����{� ��ݮ�;���qWh�f��5 ��ǚ��> 6 C�+:���-Z�����O5��'�v�3�s8��ER������SA��g5>�9��<�F��sJ�,1�9�,�-��4��䢹^�~z�H�dfv`�OFqh#CF��uG�\/����@��?���ȏ!��:�,N��� �H�aw����KW�JhH�-j 4J�����- $޹��Ł�<��A�F�R9Pa�6h�v����U��x��(�����a�wP���oEc�YEˍ� ��z]�=�B�@ �zSt�p�d�r�/���(��c�\QQ�����Y.JDƙ5�w^��l\3�0Լ��0��2+ {G�9�6�4��hn�� ��+�%�p2�D��d�@��R�}c�#���K ���f����/Hc.HI�Y7�����S�fAKGȻ��'��OO.�>����TI��X`QN��H�@����*þ(��E9'�����;� �#O�0�H���8�,�_���`P��n@n��cS�sڌ�r������9˗c�?��e[��� �D�⎉x$�Yڌ#��'�~�#�GcI����X_�H��8�������� �>���Kfʎ� Z����ʒb8f��c2�I,+���M�9�\5���<|[�7�(ʨ���͓�A�EŘ!A���tҗ� �d!��]c]���M��*ܡ� '+p_k��zF "�@D��.�MO�� {�x�2�0X� ġ�q��IWQ��^�������E~}E�:ib�>��J\��{�%����3"q�( � ��U�=l(';�l&k;���F�92 �&�ލ!JćqLM�m�BM��C�" ��� ^�h(yQ�����F�_�_���, � ������񘱛;�t<��ߏx�i���pR�\��gs�� ч�eU�E�oj��Wb"���/��VeA4�?����(�������� @.A���#��;��6BǤ,A�|�%��G��bJ+Wx���D��Q����"-�ځ�yN� �w�1��S�Ax׎��H�r L@���+;V0����b[4���tՖes��9x���틹N�m�-��,PC!���W7VlX���_\����޿}�X�i0���L�)��7��� �$�����<&�W=~�>#��|k6<ס��� ����7���o^w��(��Z�A?j�-o8��fJMЛ��^Ծ�b r^s������,弢9���w/|��4��*g8 ֬ͮe�r���CR͔a+�dC埛�)}Ȍq�)ys4i�q��w��.��O�Qű|�D��t��y�J>�^��:�D_�Pa�x7�{���&鴁���;�?�#�������;��i^�<���t��[��s��C�逦N��TL�xCcA��Aj�0%`���X�~��4��u�8I�Rz!�x��Dl�(I�Q#�6HFސQ�G����\��i���t�}�b3m�dT�cb%��yG�r���H��m+��]*ց���6$3�� �ň� �>D����/qy����~�r�a���ƹ��������R"�v����Lqb#N�Xᄋ�|�~�N,�oK�3:N /���M��! b��n��r�CD�q��_�vmA뇃�A�µ�^�sܻ�|m�"o�-LŇ)e��� �&�ۃ�wCfFn����Ls�]� ��Ts� �X�n����F����s���(�|3��F�m�9�6�Q�yݷ�3��=˾c]���mߍ�6gߦ���\���j�p���u�Sb��1��w��ơwM}��{ݳ�e�����(�Z�䣳 �{��)�e�Xĵ� ��n1�:^�c�b��cڍ6Ʋf�nȌ��<�>#\��n��*�U��f�CZ��N��>��DM����5�ƭ���5�OJ������$9)Q�V��@�5. NG�v�h�v�:�o� ����ۍ�]eq� WN�6\fd�|��ntG5��$\�=\���t������&������S��`/��# [����C~����H�]�!d&�gfl�^2���8a�?9a~O/��d � endstream endobj 1045 0 obj << /Length 3306 /Filter /FlateDecode >> stream xڥZ�r�8}�W�fBU�8�k^��ę8;�%��V2�DYL(R!)��ڏ��h�e:�wS���F_N_hgt=rF����V:�Ȏ|�f�Q�'����/���������Pڮ�^�������x���\{< ��zu��o�v|>=�m�s�oo]1��\_҆�flj p�2g��x"�����:ɫ��+lxV]��Uƒ�$^$%�ڻ��-�퉈���8T��J+]o�d��cZ5���j3GV2O�)����uCH�ylV�w�+�cam�|Nc�`Y���.wi~�D%��*5,̉�U\��:)+~��K���X�!�f�,]O;��V G�����ף��)��(P�Vh`��)�f��@_=����G����_���<^'�nra�i�+:���!j���D0�[,��:��9I/��0|LP��V�prW������l�q�]#����/�V�En�� KؖL1���ȯm�'�$r]�(�M�;�5v�.)'����FarϩK;�WtW���~��Fx��b[o�f�+�l����5��d(\�4�j��^��k)�W���=�hk� ��1�:1�yQ�Iŗ+���y�m-d[ $f�o� �f��4fX  4����? �C���X��c>�t���b^k�Ν�,�檄�Bٙ+o�:B �U @Y�� :� :o� \�Y7��4H�"��//N>_�^���,��k`>�֏�����p�������y���,]'F��r|�0�Y�� ��/���;0��:f��u��,���3�q�U��N�=8&6w��Vr�̷�X-������3����0��̵���b��0�j�&���"�^����v���������۟�@ �qð��|�`)���k���3�e��M���C�p��fP��򣝫U�1a`��۴^�S�F:�'�'��x�}���}�f���[�,�@�d�05� ������Ci��!�M�L��M\�*=�� �w�^=��];��߮Rv�=.>��=�۴J����Eƒ]f�����FS�v�pYc��Jl��B3|a-�^B�Go��@���N�\�.p�-��/�ģ�iؤ��B:�Jh���7������\WßY8��z�6�$c����U�&�U6d�2 !��z��v�Q���?8��<u<�DxNIy0��<�l6�2�1p�p$��ֹR�I��~@`����g��y�`���Z,_� &�����v���O�u"�E�DK�9~ݾ�x>�8}�d���jժk�Ȋs��cm�ժ!2��X�If2��I�%eV1U�G�IIy̖14k�������ڔ��9b1�x���!����a�� �er=a�U@`��Q;��rGu�OU���D�6��p-��O%�Sā���I�|^s5+#��zXM�q_ ��z��� e��K�N�H�*�y�#��i�"��0��&�qB���O�V Q���t�ؼ�I�'T��/Z6�-z��@�|z�����2�vd�׼w��#^����9�&0���'w��w <��iAk�@����H�N=j�P�@�ߤ��!��Ng;��}p���m��@�T�c˚��*Qfnv��q�3���qId���!�M��ϳ�ɿ�ؕ�%� ݌�jq��t(_�LK����ZӤ��ܷ�зE�J��>�̶p�az�T[����3m U�ЉEg\��� v�xb��S����9A�VƔsdx�i~j���� ��ڠ���Z�}~:$�8��H�{b�4K�mq�@��b�E���zR���4����������,�r��G�;�I��L��s��:�Q�A �|K;�-�1���t����8� �X���@����\P�:���,~�N����pQ�\.w������D�Ư"���j3!�����|�*���"C��6��9cXP���ڲ���ˊ�J����N��:5:%R̋��F#�R~�g v����ˆaP";tUk�'�^^^ >��;;>J�CH2���é�����M���2K�+���*d:��+<�9[��E[��ߥ&А#�^��˦m�L^S�|��- ��ҦF�j���wy�*�>�U�njDi �4���n�*'l<�&�����y�`�XX�A�y<8,Sy�vG�í�,�`0}w|�iz�����������㹾������rFe>�ޅ9��ڂ�|}��/g������Q8��+��]���l4=�̟cz����s���Lk�������Ta����t��”9��|?"Г��4��|�ñ�kb�SB�BΦs6:�0�f� -t�gfnAb�uQ�\$u�f�#��:��d?���'�ap����t� `$�P�P���e�N��O��P4�i�������t��F���fk�ذV �#�< ^�a�Ħ��#/ �[�R �g7����4߰h�����l���M7�N��H��z�f��D���p��F�K��j 4�+ݽ�Л���tzr���Bʖ�_e��Q C:�9�i��6��-����7�m �.�d����f�s+��m�-�_���t׭����%(ƶQN�AƚCݪ0 �b�+�b[Γ_�/�`d M�N��c��VG�rƒ<�S�T�z��w�Z��$��j�]n�iNj�'���?����^�~^/�L�)Ty�g�E�*��]�xH�� �rR�B$���4���(�:G��^� ��+�g�T��(�L�U�n-�rz�[�]in��� �O�\5Ga原�9�JG)���ӗ�UQ1J�Jh2�Vi �D�b�$kM�uC8�VL��q�Le��&l��E�ٮ�6��;�I�H����⛬��1���gN��0(d��tUl�/�� ]V�Rۼ$2�1"�~YD�!cBAl�h��6����|?0^������dH��~2�_���k�Rw㒀{�$�����`H���EJM6�����V�~���nG6�`�ޚ� �:�߿�f���� �"��.Qx������tvqr|65;wjo�Mx����M���������A�> stream xڵZ[s�6~���dJeB� x���؉ܺM�F��ͤ}�H�bL� I�U_��﹀�(Ӊ��>�@���ùQ��vd��?����^�p�г��|9 ��o�r��<}4�������l66�R��?�ɻ���;n^_b��&L�N��L�\������4~8��2�����������|s=�����xzi[,8R K�� s�K�ܖ�����%S��jd�>��ZD�41�4J�h��uo��Um)B�L ��7�KU�����x״U`D\���&�Sn.ˊ+K���ZSb��J��8xg�fu����K.���܍]׈n�Z�N`=ngi�ֈjTݎ���OF�`\���Ad�(�o��}<�bY�T�mլ��a+ҨY���ʂ�`*)�N p�H�ǜDd�ƶN+��q�E�cB�g� �Q��� �� �-�^�=�N��\M��:•^;t���WQ��k\B���7�z���嶈q7�Z�!é��܆÷��� �lל}��'?������ \�_�׿^�%2/o޽��U��`[��T�E-QW���\� ��& ���t�c���V�57�[�V��P46#= O5��ݮS�)S�[QV��h��^��ع�5s&n��N=rH\ʷ���:M�ܻ�1X�Ͷ*jiĴ�,́U)��ﻫ�C� Kvc�ǮW{����R��2� ��Ӻ^n󖩺��I�<��=G��M9��P�gӎ�e 'p`���S�pm���]��M�x�&�(Y)Ae *���c% �P��n�,������}J���`������ B��Z���c�mH�%He�d�(���Qn� � Rp��m^ �z�P��͆���:��wK:E�t§�ͱ.~���2jo�~�\�w����%��+G��l-��2]�vQ���}oJ�t���:�� ��(�D�I%�%����\��{Dd�sn�,}�d��Bm:��Ҭ���W�pB���F�����ԭ>�:Y�J(�V��9�$/i��1cz1��h[��X`ʬ��Ȗ'L�to�[�U�r��� �/�� �C�œB��99�x=��h ;h���[=qQ�J^�梵|HO�e��|�~��������Rx��4���*�b�m�w��� ���lh��A��A�vQ��&]���5k�d] � �I�B+��E�!^k��S�_�e�DU�?������v$���j��'�4��%�3��<��I="o� �X|��=�a؛*T���?�u�X��Y�ꀠ�.ևO0�� " �I;�ש���� ɦ �dd���7���l`=Szqt�BК�J���m���4L���sF� �!���g���B��8�ʂH����[zf��^�y}�5�� �!�0��L��� ��Dp�Ws�$��� ��LZZ�M��N��`(�K�����y>�����}��&�-�� ^��UЩ��"+洁K�aq�F�pi�>Ӟ��B�o��[��� /�vq�|�%�:�g;��B?[o�ud��S��f�!��.)�������Jx����E�־?����^����lݥfTU�n@��&��٫pR���D�Z�g���.�����.��0 ,�s��Ѓ�O�}d�/ɪ4n��,���9�W�c ��[�b�0 ��!D��|�&��1xtd���c]� J�� ��5+%��p-�4*�T7�C�r��-�C{��)���-.vMz���bmg0���ʒ�h )>�s �4QG�VK�E++�ӈJ��u�Х��G ��oW��"i�Ey�W�G��Qr� [�&5�3�ԡ'���nZm�3�; ����>��n3�7�}pF�eT�&�\՟U������� ��PϨ~Kς()���T_P}G���C#��[��m��� ,ϐ���������i���MOvt�ʰQ�c[�-a����ҧ(����2��v d �>%��7z�'���4�{*;�N�>��U �u3��Y���P�5�ψ �1/ ����b�qO�)���A�+�zۚ���.r~x��g�m���U�m���I7}�Ͼ�.�}� U�o-��Y�5�Bk�;zn:��l�; ���e�k�gT��6��f���hf������G�S�7����!����*kC����&�'qOl��S�_�|}yy��Q���� ��/E�S�����Y4�=���dΜ}�q8����9&�.>�'毓������;~����y���@�p��[W�ۏM��5�]]�7����?{9��ʯ0�I.�]�&��������'��E��==:ڒ=K�#�| w��+9Þ5XV���>M���ăд �#�fTGQE�&�d��S$Q����E�f������U�@�,��#�~V�� ��I����-�1~�{1Y������ �Y�H��P� �듏X��?"��`�@c�pm����4�hv�^_�G.��o�D� G�/l'<̎�89��ַ$��"�LqR�l~[e�4,�8��Y;��̞w�w���Oa���PH�8Kn9,W �)����j?dB��PJ�X��UT��EV����:��Ѭ�"�u���#�l�,��B��5�BL��.H��b�5!�5��Il��gXy�Q��w� ��.t��v��q�I܀p��O�WLТ�I�h���nW8���2c�mQ��%+��|Ǥ�*��6|��������������9�po<�6C��b��8�Du�aȤ�}��I�Ih�;�� �-�M0�b�H���[$�ݱ�� Ǟ�uw�<�H-؜k�����N�`׳��z�ό]N-+&�����<�����^������y�ð��Ӈa�����u�೷��!�J�����,�˳z3�'~�D���S= 4W]R/p�ޥgY�p1���`�4�����6�`n�]��\���e��zM]���%a���,� Y� 0��� ��#�4qְ�?.A%���� endstream endobj 1080 0 obj << /Length 818 /Filter /FlateDecode >> stream x�mUMo�6��W��*Y���'v�=�A�@P4=pW\��D �`�}f8Tl{�p��8� )%A$�������C��xWeUp8�$��&N�28���L����>�W����"���a>������K�yΊ8��aw��>=~���ǯ{��I���x���F+q�Ր̉���:j�'FeV���S�q����!���}�%+�]RQ�ƻ���� E�6'g $zAox�[�qR�+X�a��)SZEי�:]�JW�2�v�1_��S�L�ٚ%�3��4��aְ簬����n����0����i^���HG�-�&�[�&�Ћm~Ƃ�ļ�Ӫںi�]�-��)�˹Pl{��Q�^e�<�:�$O|<��J$(3�Q����Xwף2��Fdl؉[��O*�� �^�k� �IZ=�ْ�d��� E�s��N�~�vE޼�7�J�)ğ��������Lc Dr�� !F�É�l=�^�:i~���X��ȇkR:n���I��O�T�|��Ud9���Y���`X29N�i��29���^�Wl�/P�+"�@0/PTY�T3�� �����"U�\f+�?=���L��o�(��ia\w��+B���K pM���L�wm�i�Ǎ�Z�/6_7�j�P�?��� ���E����4��ϋ���Sw\�]R]S2�>��iU~��N"����?��\�� endstream endobj 1084 0 obj << /Length 2148 /Filter /FlateDecode >> stream xڝX[sۺ~ϯМ'��7�̙��(g'�}r�L�Z�,&������w/ E�t����bw������,���U�o�_���ș�D+;�^��hGF8�g׫�?��M�o�zjg;����"��8#��6&V~B��k�uq��*��"�U� +a�a��M�U����BG1Ȓ����� M��l'��UU«�F�A����l��ͭ ��|�_��?Y���Y��9~�j�� `� 6�j��搕�= �-he'�� A�Tg`v�,C�-��c�'m� ��` #�t�PJ�ژ?��!�S5MqCvDQ�Tۼ��[~-�ol�c�d 5iXK�� �"�]7O���X�AZ�v�u;F��V�sW�޶*[�N@�'y�NW�ݗy��+��t�[^|��vgmˆ:IQQ��t��|���5jSA�[��EM�MyK��?#ij��Ůh��,�������o7S1U6΅���￟].&�h +�^n�Svn�]�l�f� _Wu���6��v�$&MD �8 LÙ�/ �h Ӵ�7�G"�ԤBi���Ad�:���e�@j/z�3G\���[Gl� ��Tn'�I�+/ ��|T^@�4�gQ��t8������á�G�����c~S;'"{�'��4��m������5_���<Ż�`���a #�]|��;� .F<��"O���΢ ����������M�֠�1��S�ߪ�P��R�� �p�'<��bG 8���L�9�ćKmB� ^�B-�u�'��+js�#Qs�#Bh�3j�����]s���B�ECdQ;�0�� l\���{j���Z�1qK����n��_R��3��R��O���R�O����f�H͢C��.�rd��u;� ��p��O�KJ�п�ہ�-u<;B���f:����_�'"��V��)`���H����GÏ��[;���#��X�~���4�yU/����m��tC�.�_R?�7����.`8�x�)��*��� %�A��~ۅ>��7R��PmD h�-:����6�>��"�_���3�n�y}.������FHR)H���^=BO�n�y�z5���biTP�5rǂ�|�<�|�|��c�h�a�z���7�EA�F540}]Jc!S�"�膿6�,н�)��k0�{��-{�eP n'�b|1}��&���|�L�F�l$d����E�������2�?�(�E��SNh՗�H�%��UI\���Q���x��Z�m ɛŏ����=�����F7^��;�SX�H�v�������u� ��P���m��.m�T��9��|� C5��YJ�^����Y=>��8�_�,s��`麮�K�ZH5���~�������zb5��RfH�A�͡� V<@�i�@6E��+0~o)�e����������h)lZ�/�ǽ�k�"�*B�p����ׯ� �7�� endstream endobj 987 0 obj << /Type /ObjStm /N 100 /First 959 /Length 1962 /Filter /FlateDecode >> stream xڽY�nG}�W�c�=�u�K p�x`X���d�J�آ!�@���T�����iɄ$�̜�:]]]���� ���VWkt��_rTq��c�_q��W�D�MN�~���+N9�j�N��!�B5!�$M �J���2�Q\�&0� �IM�?J&A[��f1G�vˤ�B$�n/D<ДLƒ e�O�!@����LF&�YnD#�%�$@���3lm��l������JAM)1$�8�l�/j�%GD:(CJ��GL�I�4q1)'d�`<�f���0��j�0�'4k�$c���jkfs��XΎ���%V�Xqu\�F��O��� M�H� �[�X��UZ�� �Y@qO�����9)�z����^�1��4:%��0�r���S�:�[S�7�in�Ske%��"&j��Bu�� ̛��)���c%f��R6 ��V:�ϒ���%m�K�4UR[��L<'�d*0���[H�,�#CG.:`�6�1��1r�v���'l�c3h���X�|��(�2ù;&K�$HYg''����z�NN���Vʃ{� 8,a�/�̌����,��h^P�'׹���߁�16��O6C��l��f9?]��;7����.�\�������������GP]\�n0�X����v��f��m������������a�x�t5�7x�Um3���Ց����_tן?|8;��6l��c�8 ޢ�$.`l�) ���d����V|� t<�W�*�|�Z�iGT�0��\�L��$ۡ��c4�Vn�A��',�G�EM��"��c�#`ag)�W�4�4 {�� ��IZC��<,�ցP+�A+#�f�����aj�R�x0�*���hiL��,�}�,�jJ�ԩ��&��{�^p27�O��������>�`&>�&�@�}$*�t//o����6˜a5�ˆ��c��1w똻55/�c ���`?�d%i��u��A��&�<;F�M��Ѧˊ�@v��(�����mfg�"�'���@d�G�M�Y�.�i7V&ا���bt�?���<�=�cm�*F��! +h��Ku�<8���:�b#��B����-�<�D���il�8��B�[��)"���#�f��l��&�8a�N&���!��[�)0�}��v�/����H>�sn��f2�89i�/�FN�_��l���Z}��n~�Z�����/?��˫Ϳ�ǏW�Ar�t~Q�k���e-����C* T̥��>�{^{�t�T5h}�1�J-^8#�$8 u1b���d���H(,B� ���ñ}`AW;&Ch묧���;=#���z�0O��Xr]��XЁ�Ԉ[�\/4��L�`~B��ں�ǟ������0v�D1i^�_W�p�0��q�ᶵ����G~Yy����� =}^�;��6����e�����ո� endstream endobj 1102 0 obj << /Length 3466 /Filter /FlateDecode >> stream x���r�8��PeCU���V)��I�yL��f��P�Ą"5$���o?@ �屳��݃�&�ݍ�F�d5�&�O^^��^)o��$T���j�x�ȋ������w'P�?/��^��B�^(t���s���������Z;���Q;��_~z�{�xf���\�H�K���N�`���v�f�*��]�3PﺶX�W�?��ҹ�J��Vh��k�|Í��O�U�u�>�:�wn�*vr��vM�WXѕw�.�,����ݺ0r�ϙ��*��=3�/O����٫��]�g����g���o���{"���+�H���u�!qk�9%;Y��-������*�t�u ڡS��"��<@��Ś���)x�����k3�ͳ]WT+�x��;��!,o[�I˒�&wq�����`�6����o��y�̫��[�N���`�KV���&�ߥ8dڶDJ����kVM�] #49a:r��Z��4j.�РNR�Y���< �7U�5�̬*`b-ab(hb�"��Y=�ʈ�k�Q̛��J��=�@��p#)/�i��tL�oa���-U-;2�JD�=�s�i3�-K ���e"�vg0���]�v-7\�^|���:� ~@�Hn���z#�Q(d3�g��t���9�R:.�������`y� ���с�x ITq�&>�NFpI�KpJpK��+��������!����_�%�]�P\�[�*���������8�6{� �@�%J�(7\%�f�n&D�PrMI%�k….+�Ce�U�h�� ���+N�4��NPv�3����Ŝ��;`?��!ipW�H|mFy�ߠ ���{*�@) � P,Q��#�0��WW�1X�sZ��K*T^�5Q��� c$7:q4T�jB��9�gT^ pD�!�3��#�ڜʆʖʂ�R\�Z��:Q�� ����bi��ɥ�c3a�fJ{�ʚ~?q���Pp� }(�P�Ǣ�a'���< :������A5��>AMU?�5��O�hK}�T[�7��JAeb��86pvE���Uu��i��hFNpC�K0�0 q<`h�nO��@����ڡ���JUi���OH�Y��nk{Npӫ�w)�|L���R}φ�)��Ԍ���A�<�O� ��� �7�l�qNRo����������ʆjj����WC��p�/K„�dS"����WQ�Š�=-�F������t$��������h��濭�$Re��,�a��Y�g�a�*K� ͠�����Tk�=vmP��R���4� K�z��-tt��F�+ѝ��-��Z ����$41H�{����Ꙇj��Ic�j�4Fl�zi�wV}m��k�l{�#뤼��0��5qu�����l�r�j єX4������[mk�TJ��,*��#���G#�Lx�׽��)�yky XTGR(*Qu�B ~�:��:��:�O��F�(ȍI��!� HD��K�Sk�²���y���%��'Q=� �$�RYRY��Y%� sI�ZJeG%Go��E��3���q��G��Ճ(�51pnE ��ҝ%��r�-�����S��.U}( ����s٢��-Va2޲9��Y�>:�`�Z+~g�����wC�gkFȶ36 �-�����'�xM���l�Ҫ���-�bK[c$i���ᣟ�iF�������Hݻ(W�h��p���F-��}i���{ɘ�3⋴��&{D�a!��n/����A��sa� }H�>�P����S���I']R>u�����ۥ%�||��Ra=�v��sq����b����(�3B��\��@X&F�N�YH��4n��~�G%�P2�3Vo��_��������������磉S�� �XqVy�7Ef�W�*���#�z"���$�4m�� �Ij�N�&�YZ�k�G��dV8�Z��� ���,�8k�D���&��H��� S��ž�cx4�z��#����L* ������9�Ƕ���6�x?�����¼�:��9�UM>J�cՑ;V��4.טt-&uqL��a�t��ME�v0e_?`�mA�����4�\U�����ol��b%���d�o=/KN� �Zx�b�wu��� q��.��{�Z�vc�R� �F����f[榚���3��qU�z��c� o�?=iV���qlޢH����ۺ�/f��KV��Y���j֥�vfҤ��?�/(�YVW]S|���r1���j�i1?{������o���qSx�X��X7#��~�X� ��cyqA�����~M�.24�#�K�1������2H�nF���X,I� �����{hۦt1�m@T�:~O��q�pl������,�Ci����<�|�G�q �M��y���[� &�_ (�#�$Rx{�~��I�g���aJ�w�ҐP��v�eh�כF��t����ms��Dž�@�ס*��-���_xi�+��&ݟS���T��c��-�=GN<*7�&i�IkPt��Ik�!{�m�9`^��2l"ۆ�`۸'�6�+��"����� �M�����ۆ��l��{L� #��q��#�����k�>����Z��oU�#�%C�ib큊 ;)D�@��hڴd���mMzkƼb���o� �mӢi� 斻�~'�;{V���x�&�������z�-Jz mҬ�[� ���3�U�횴|� AL�$�1 N ? 'Z��ww'hpN$�=:�u����Q�_��&/��˰������[�w4�m:�$���ȝ;�G����j��&oz�!w��-�M ��6p`��ĥ!�߱�³b(�g:��ʯ�ŀ�l�O�=?����J ��ű'*JA��z��e���3�d���'��qOz`���z������o^�w�>|~y�p���rq���E"9t�t�9�*G��0ſ�N�� �P��s-�$8it��+�4In��x�eT�>���֜���bf�5��V���ͳ��M�Sr�7~{��y��(P�g�y��Bk������|3�5�h:����i@��{k����ݢ�cD���7�*�M��{E�c�Y5�}�5?���c� ih���A�6���1#v� �M���OT`�T������jo�u�ϸڕ���fx�$�GW?u��ۈ��6>�a�;1 ķ��D8 ���8�FZ8�9�u{}$!\�j�z�}�ۊ��f���Jth<̋ 6�i����bV����x�z �dqy�� �M$>v 0~ѓls����d �t7!� !m�?�!-d9�8���Lj5��Qd, �j�uI˅���͊<ɞK���4�/r:b���&]���Z��Cj�C�0���pb��,)�*�/��`O������ĩ���q�Mw���U c�-a,���ԃş���8 endstream endobj 1128 0 obj << /Length 3552 /Filter /FlateDecode >> stream x��Z[o��~��X$� L����h ȊT�P�T�<I�]�6��p�������6$wE�.�@4�9s;s�\�3Z������xs���Bg���� �ݬg�?K����hv����D^���$I�wW��_oޝ\�hB�������Ǽ�e���P͔�( p�k��AKh�����U*��w����I��M�)&6�g�J�(婧5���)>��]U`#t�5���7�D�x�X�qǧ��Sa?�kd�z$�~[�yW0��+&�H/Ɇ-�y�9�X�S{E^�"l��I�t�Vv0 �q���[&��f7wad�vea^ �ha7P���L�E�gs7 �+(��R�'*D9����:��ב���w:������7*�T�Tb���.�5���Y��R�����Q*k*;*[*q���G&�q���Jc8���۹k,U�\�=�~�|�+�Ңo�<��j��m���?PyC�5��v..�/�s4��Q�Z9���~p���P\:p�=E�a�/���A�<9xF�ҥ�'*��9կ񜲌�D�����Ȓ��!�� Rы���Z�:�ј�נ��e馿6��%�� e����P�ۺ҉��'F5��k*7C���.�4TvTTnq�>��'�����Y�歞�1f� �uT�TV#Y\1�%"q�$��x����n����[}VN�����Tvtլ�[��x�"�z��ʂW����M��8Ge��Iy8��)���b ��3���_�(s��+�wl�8�Ջ������r�o�U��Oˉ}+O�jBp淸�O�|b?w���n�S�GPA4F*��T���O!;�� ��y��?{�l���iX���/Uῼ��J��[�9E���y +�E �R���*>Y�^n�RØ����8��܅�Gʺm$ 8k�[�L�*����5��@��A=ߦUS�7�c�%;ҭ�K���>���2��)��Xka$Z��.)gY�`�P����T,� �8R��7gW��7�� s�/~�gC�=*!���l�GwU c�]��=0Q1{��Hɥ��'��N!tG�������;�({��N����#Je����e���qF�X� �|�� ���i���64���ƛ�I�Ei<��/�R|ҞG���x�1���t�@Y| E�I?�4=�y���鏗l���RH�=�^�g����yL�z�d���~o���!--Y� �K�qT�Y�)�5��l�kk� �QM���V���Ja,؄� ���̧/Iz�"7��� �� <���B����$k$�Eٚ]�J8h)�5FiJ��, �, {D*����ܪ`/Z�$C$���\�Hw����)k >�M�ՙ�_���d�� �PP�#1��cJe��)�]�bY�x�2H��D���x �%��J8>VH-K��{�إ"3[�An<����윂"�ye�ʦҘ��b|%�%���A���%�Æ��j�9�\9m��:�2U&��Ò ;+�p���/���aM<E�}kU�l����Z��~�; _C&�Ȋ* ����$%��������8*g�F���uU��[Q�:���*Z�p�R���zXN�i*����$���W��1!�F����I�0;%�f�po���t�[�(��+�J��&`���ͦh�W����'�?}~Y�7IIf�!���@Ql8�] �LP��~�/Bµ > �^��~������!���n���y\w�뇐��+�P���o �ծ�^��!#�w�>��{�j 6,� �? �'��w#�! �P�:�K|���)�m^�]�vL���5�{�vn�2�l>�)P$�G �5� �kD��qY�^�x����aX�g���10�G���(h��j�t a����m A�h_1�����/(� ���8�[��]��XJ;��G(@�>F�wHy�a�pW�e���I7�'-n"�a��Eh ����npW咽�c���*���'�xF �d��b 0v��d��W��)[�e��ґ��9��5c�4��ws��+���8(�ժ:#�p����a .r �d��f?�߭���pH�W�Y6}�^��H���bm�� ~����B�2�2�1��[���OT���-Wc���Ʈ\F�2���q{_��-��鳕���^��O�ԓ,��� ~W�;�oJ�"�j����h��D���OF��'#�6B���X�d�P9�z����t�8�����g~T�FO�Av�T���_�ľ/���.�B��a�y���5��.'�����M!T���셀���`�k��ڌ��ֻl��� ST���ק.�A0���8g��AO��/^��}�~q�y=qX�w�2;��x����>���7/~{������(�< ʶܾ��W�2�gVg��mg*��PϪ�����WL�,̟�q��d@I�D�#�� �,��x�S���R%z�(��^�02H���=�����0d���,�*��!���B�Q��p��a����2�F:�i�Z��BAW9F��,�͈�•�1��J1��Z�3�|�>�y?T�4m4^�#4��Q��qQj��ݞ�`E5���0��(�Y�.��P������H#�,ņnp���,r n�;�t�S �f �Â>��%�)�f���K�T��Rڶb endstream endobj 1144 0 obj << /Length 2188 /Filter /FlateDecode >> stream x��Zms۸��_���L�LE �ɵ3�,��[#%i�׹�^�ȧH*I;����ų$ʒc�5ur�~��ž` Ȣu���;{Ý΁��O�ҭ�y+-#b_�Qk8i�Ӌ�� _t���(���X���wݳa��n;/�w���^��d��pώ��t�smζJB_C��ƀ�J�1�s@"}#�o�J���r:.>LGk#���R~�hJ�Jj�o�#��&����vۉ����3�핶ט�{jG$^Jm���9��,� `̀���c�6X�YT�D���^�)dd`������I=���oj����Nۀ1&aN,a-"���t���>�a���BN�թ� ���47��2��hd�'�:q��5X\*�:tz �=�Q튪=�����j�n _���b�%9� �S���_����~�c˵�S%�9�ݙ� ]d&`[��}���-����@�C���:v�H+&)�x�M�'��8��b��D����=-�J���=��i��a�`Q���CH������A��Ϗcn��#~+����q���� .o�1l0����mk��j�:�F�2������c��� `�ڡϬ��o �?Q�C`hM K ��lX��z�P�{ k���5��m�.��.�%[�dƳ��]M����y9��� �Q6CYA��c�XX�KΏi� uM�e��"EW�i�{t��e��ʬ?�-���L�`�O�N�J|`���cK�(���>ѿ���ڣ$1s6�޽��zs.� ]n��ǟ��L좢b` \TE�- ���9����� =#����b�r�<=��S�9h�"��+�ܩ��@+��^��bW�Ksл�ŭ:b�� �@XU8����:iM��JC�ʬ�3~��ϙ� �SЖ������g� 'ȸ��`�.�� j=�u�HAg<�þ��t3�F\��~ʌgu��蟹�l,�T���ejC&�%��3�N|rlU��i�*Ӿ��X+0:g�?�e��E�lc%�%�3�p�8��Z���&W���l7q23۷�{mM�͚��~�p�9�9����r&�e4՘k;�6��϶,@%�� �n �1��p�d�6}f�ĝ��R�ԡg�>����E��4�7�-�Kn��0�&���EH�"�2ξN�}2�Ba�8�?C��'�bD;�7B��� �������)��9�Gู� K �BRI����u��&��.��[�d�rd�^���D�8�Jv���y��%}]�q��_��Y"k��N�6�B���}X�{�'�����{��ڪ=T� ��z <� ��u���*^8s}�<��U1Y�㻕o�0�' J /AO�O(���l������&X��W*�N�c1ND_�Q�`�I��1R�)��1�� ��Yk��`���B'��N�Lv��1�-'���.)}�|���#�r̥��+�:1�3����bÌ\dN]��o�@Y.�<��Zl�%Cu��W,���~�}�ƭNP����`��~o������ ��e�*�� ��> stream x��YYoSG~���Gx`��Yf�"���  %Tj��$�������Lb����t{�8w�ݳ�Y.1�삣HN"�I�������.&#*@A�L�rT�옲�8� u�# N4�Nj1���f��#0U��8��H�& ��x�lJ:!�ydGF���'1 R��VI�(0��1�*&'BN-��=��Q0(�:�p�A�(m��j6�IDl� *��8�hD�� 0�QP6�dTΐ�N%��(%���xpuB�\z)F1�F�W5�r!f"P�DpD A��)�a��f��Y� �]���q)l #��(��Y�xpU!x�"h�I`��$d@ �c���P1fH'�'d��eJ������A���e `� ���K.�'�*�%�"�J��F��2��jсå6@Y �pTs����� �9 P� #!'�9 ���r4���R� ɤ\MFga��T� H�LFgM&��LF��r颩�*in��!#�\͐QZ�f�(-W3d������(�Qs��K!����dx䎑� }膟~��U���'�g��ݻ����_���g��� �q<�Ձ�^RCC\�q`d�]*���q`,�'�����T{8&��oH�Gd��`1_��=7�1r��q�$�|�;�$�z��/k�A�=���|�8=��ܱ�?:pË�Ǖ�$�ş�g�a�z6B�l���b��L�������t����ٳ������;�����֜@�t��Qؑ� �?�/����#�>�#4�:��I\��Fl�֘L����l�$�����tx���S��q�ޚ#1 ��"M*J4K���;��r�������^0쟮���h������u�z��0L_���������������> �p���e�������p�x�ѳ���������]�3 ��}�I<�U�(�͞���`K��}�[ ]��Պķo���f���`d�J��%Y�gT��p%�5���ami@�E{���M��� {��~+4Gn�~�b�P��> stream xڝVMs�6��W�HΔA�_�ɵ�$cg2���( �0�H ���.�WO��D`�v�> �A�uq���݈*�X��y���$(��%2 ���0c9��(��執��w�W�����49�&�`�(`Q����E⶙�HpɄ�S�{����mŜ�YX/�X�i����'��~ L�L9M}1��3��>���F��d�ũ(�?eة'���C�����"4��}G��~���(��z���%��M?u.�4�,>��L�"eEŽ�n��a�-�b���(DP�*s�4��<�,�m�� ��P7QZ��"h�k�B�v-�D~�O��$+e�]ͦ6��4�n<���{���L> b0��n�s�Ggn[j��'�����LÀ'S����#sY�,&D2.�2�$+�r�g�hv�j,�,�bt��b�%/��/�-e2)�ַzU[� !���t?9ô��v V!$8)�1������!�:RX�e�05H�?�����i�z�LB�a)U��oʓ�IG�ٖOn�g���KL� �������N� Uc���J�Xn0�Wt8�d��Z?��e�R�U3�z���q G<����z8�hc}w5^���J���a�m̍��|�JΣR� \�-{^�*��M��@��������W�[G���t ��=u�ꆑ��!�7��V����;l�}�Kd�z�X'{$�4�Xц+��ջ��i'ϧ�B�o�6cY ‹N�G���Gz�����x�aq��x��r'Z����9a�u�~��; �� P?K��Pb$\�5�-Y�FS�1�sZ�=W�p�����=�V��o(_��8�iGL<��?�C�+ u`�$;�C�˨�_ge��5,��� 쀝�Bl��tQw�:5��G d�y��7�u=}WT�ڷ���1,�7NFr�''({����m, �'�av?Y��S��*��Ƙ�7�Y�lZ������L�g�Ò���Ҏ�Q 찕1{ �4OY�3��v�PJ�XT����J��+� �ջ�U���g����a~w}��_-旷ןϔ@Y����_Hr�$�@���% v����A�Ա?F8�J���./����:�Y�P��ڽ�C���<�2sAU����i���?�3R��)�c�T�v@�+��i��s�I剷�^�� ���]�N+T�,�e�v96�~�v����f;��LM��W7�t����LK��������iS��EďQ#Y���"sˊɽ^�1Ȟ'^���Ô~��^�CZ�ώ��Q%�m?8���[+�ǂ�׋��>�e endstream endobj 1203 0 obj << /Length 112 /Filter /FlateDecode >> stream x�3PHW0Pp�r ��w32P�Գ432SIS�4P07��301UIQ��05ӌ ��w3�DRdl`�glj4����1 �5HS���X�TOS���B���/$�� ���j:�� � endstream endobj 1211 0 obj << /Length 2515 /Filter /FlateDecode >> stream xڕ˖�8v�Wd�:��,Y~ͮ`h�=p�{��B��D�cgd��f3�>�!�Np��ÁHWWW��0�j��V��E��ŧg�?)��Q��2Y}ڭ�h�FI�r��\��<�S_ٛu�%Az��{���,�ވVkU��������}t�jU�E*S���0�RF�{��c�h��aR$�LH_od��y�Z�7���G����շ�j:�6��u����Z{�~�n�8})���ŷ|v�n�k�W%o�{DEΫ �:�>�B��d��f-DX$ ���jDz LxA��Z�*������H�;Q�(����a��C[߈��]��|��1`�ެ�t�����d���L;t�G8h<� ݬ*����Jw$8��Mm��((C��ѹ��P�U���@v�Gӓ�p���B�Doj>U����c�7�Z��xҠ棧�G�Ht����}|˫��N�pߙ�$�9�j��t�~��4�p��*��B�����nrP]{D=�h�WI���ѠBμ�N��iX۩sV�{Jݞ��LxPC�u��i��=��Z 7{�r�� u@GC�4=U:�D��f�$�ݎ��c�?PC7�m���Җ#�9υ��=B�r����5_� ����I�ߡ�PxF!E��röG�v �VQ�� 7�$���� vq��-�ϢQ�y�(l�x6Y�S�D�[�t��Z�N��l$#������䨍�"�T�s�B��A�^J�t�5~���߹j���TÚ1}ǚ:�1��}��3�͌��� �{��\�:l.�J�B�ua��@���۾u�l"�s֜���%d���� N=�.�\G���Ϛ�t���� �����އŜ0H�\o[]W1=��8�� � R����HNI��v� �B+_�(/}_e�*�Hϙ�Wo`��eft� �m[�E�('*~���SfC]��"T!�hNLy&х�g3�J3l:����1+ ���S�oƠ�s�hX�� ;��Q����́���D"x_�;�����t����/�|�C.��t̐���u���+K�Ď�:q��u1���|���1��!��`�q��u��:�Õ��v4Zoo�/y��gcM����{�8�P��� ����q�&����Զ��e �$~0o*s�<������wҤ���I;�R�0lB��[���&rݧ�"Kcؠ��6?�b�P��� g�S�T��SR �Rq�$���l'i%c?�QÏz�y���i�1Of)���xN�p�``W�3����U X`R)�w��~�9�֭ ����Ev|�I��[��8��`�¾��8�pȮٔ���d��c7��J�I1��c ����G*���O�=CXiX�\ �� 4n������Y6 �����MG���a��u�(g�-`��1�+ N����T��zp�y�3�;e��s���Ov����Wa�7�3]���j����TG���� �x\v_ %XF��"��(��^P_ i�W�% s{}�O�Gp����g"5�;��q���_�9����W|6��.�7:̿{�vڶC�?B���<^��~��PJ�¢�Fu{�C}q��gIP��p�-�{�x�9��]���N��6���ԣ�|A���zh:�o�r�y�)�9�)�08�AV��8�S�KD!���%U��1�c�R" 0}��c� !�#�S�_�A��i��n�_R/���16u���z<�ʂ�w=%�����uu��fE�Kfc��l�����oz�+��KM#/]k�Įypkѹ+�k�9���@���o2&�D�P����cPD���=��1�e+�>��0fv0w�8QW�d�\�SϹ�}�0���>���ǿ)��+�X�g��/Jg�]�F�;��7Z�����7d(v�x�nE�q6�_�����^�h�{�g)�"B�e�J�8IBǣ/< �~�L��h) F���?z#������:��UR>vu� ���?�&�hK^&ОJ�]R��`S��5+�¢H�̗�:m�&ne�(V�<E�+Iv���ӳ�N��o endstream endobj 1218 0 obj << /Length 115 /Filter /FlateDecode >> stream x�3PHW0Pp�r ��w32P�Գ432SIS�4P07��301UIQ��0�Ќ ��w3�DRd Tabd 4����1 �5HS���X�LOS���B��38�?H��X#d��Jt�5� ��| endstream endobj 1222 0 obj << /Length 153 /Filter /FlateDecode >> stream x�U�1�@ ��_�J�wW�QLL���,H���{%gL�������넾w��q�P�=�3(��G+ ��CZOS�[��c7> stream x�͗Mo�0���\6���߰�n���NZ[M6u=0p24U �N��} �KV�K��rA������ě{�;���'G��x�$�^<�"�)�1�g޵/Ip8:��F'�)f4�!�>ӫ��������S )��?�>|��������Q�2����S����?!}<��PBC�G����F;���ʴɫ�M�`?�k��1���lnJ��Ӯ�8Tb���1�J> ��n�@�R�u���G�7e0�z�a�ǎ�da`J��_/����n��"@�^�����/J9&LAC`!�%,�eU�����”4��=�#�C�+��l��YO ^��-���X��I�����ha��̙����q����2��8RX4!��B�����9hqٳ�{��c�e@嶅d� $��8f��>Ghh����|i�f3���$��@hh�E���z���I]��h�hIq����Ӥ��> stream x�͗Mo�@��� �*���~�تD�[��k/Ī?�mZU��B����Z�-h<�}<ﻳ$ZG$��}Z�� F"��b*Z�"I8&\G�L���yt+�<,����T���E���'�>�O�8��][d�/#�m��ES����� . �.CV�]����}��WcX�j���dcX+�P5OF��)��ž��G9Ԣ 5R���M����m���ˇ� <6�Mƣ�6�ޡt�)�,�^:T��ށ�8�1�BA}1$�P55*��K _Y��Ŕ�F���OX4,��z�v-�:og0l�9�NO�_��n��^v��e.wu�v�}�% 6D�!� ����&W`�V��QQ}ڮ�҃�T�0t�_�ʋ.k����~��jL���f�1q^�n��F(w��� �9�@� �� �Mt�EoŎ^�� �+@}���c��O@-*oŚN�K�a.�4�C-:��>��o�@���s�W�e�A$�e F&r�����Q����6PJ�I���fy��P���a�B`#�m(g)����Ü� ���I�t���H��a[�;�@��Ѳ�4_H~\��+J�V�"M��M$�L��S�i� ��2�1��~wc,��.��e� 5��k�Q>��QP�W�������+d s9 #d ���:�}��<~�VX�0���Z�r�{���r����� endstream endobj 1267 0 obj << /Length 815 /Filter /FlateDecode >> stream x�͗MS�0��� 탄�%�F�P:S`:9�C98��86�ʹe�㻶��$�5��d����w_��w��d��xoĈ�P1卧^H> stream x�͗�r�0E{}K��}I�L���4 ;t��$�"��σ)٢ o �t�e�w�3�- �MD������l�Hd�ULE��H� ב&!�M]Ċ'��o+��!�Wi!�a'V�I�<>w�k����:1"��Y_4�'�l-ؑ��XpQ�#� [��~��� �F��T`���"�a��aA�lQ��!��膏7��`=I��<�Gy� f�lW�:�/��}�q��2 �Fd �4�}8QQ'�AضF�D����eEZ�]�B4��M������%?Z�01A��[�Hg}��IpD�Šx�w�S9�Jz�U���ܓ�Q�V�ϫ�g4�1bz�A��2��'�E�ۛ�����.p-#1�3�Q�����8+��iׅ8��c6�Q���D|����N����)�o4&TLR���G�s(�!_(��\�-�?�Ӟ�*LBMd�8��bb��|�Ee����F�efJ�x�I��D��v���Cһ6T{-�\�M�TLW:�H��N�j$h�ښ��j�#Rtł�y��-��FԺ4w�h��|� ��X��?O��_|�i]����k���:�l�0�c! R�/]�N!-�@ǎ ����y�dAK��3-��� ��٤� ����Q�������3PZ��U�PQw}Zg���H�)�~����mZ&>F���;�����_}�2� |�NЕ 9�������y�P���3e0h)��B�$����/�:�w endstream endobj 1191 0 obj << /Type /ObjStm /N 100 /First 977 /Length 1611 /Filter /FlateDecode >> stream x��X�n7��+�Lᐼ����$p�;�^H��*K�$���\JN���b����6g��>yI[��2��D���e�ʳW֕A��d�3$��� �r���(r2`�(���2�f���L*Y����0����#�f=���c.��\@0�����8��8 �(����(q:����Ç\1�d%?g���!��<&y甋� ���l����D�,��d�� SmPd�*�"Ņ#T#`���B��%bKlQ"���28�Ņ�a���@e�!Jf�#�2��"z�c$�qˉ�~Q�R)��l�/�G�<�GΒņ�/J�&�7t���dE�+.�w�1�b�0 ���LeF�( ��:7˾D�޲/�zX%R|@sŞ��h%>�����<|Ĝ��s*���)z¹D�5ĹD���, �GoX�a�zSV:�mi:��V���X��#{袧TF��N,#-�eF�=_VP����2�>IH�'yD�e�D��F��|,�F >�NÑO�~� ��7�ˠ���t ���l� ��u�`@�''�杺 �>W�o�����F�R���tz5x���� �7���%M�s?��X����5�E�8�]��l�c�(�6�l>[��՜��.���3aY��>c�fzx���� ��A3�?�z�a1_�+u����T���R_���Ň�M;h�"�v�Z�LF�?h����~1n�k�,�~i�'�7�����E�����h��l;���fsX�\ ��S|3��u�����A�f��nő�j~j�7o�%���tSgQ��p*���@Šɂ���`��y2��9=9)���j2�5ͯ����ŧ����S=_�4˿f�jx�l���4cg1��F���u�4E�#Ԅr��*���v&�h��^"�����H���m;�,o��lx�^�Z����p4m�G��P�!�M�"�h,7�QCb��`�����8��6j�M'� ��\�������{�S�x ������z��b/{%��Ou��fK��ѴSu��H ��9tEGNd_%:�* '�g �_tN�����S�E-� �����Ût��ym��̴�r�"-k2 +�H�,�1�N3t�2Ұ��`,���#�f�R�����E��M�qmy��Aҏ�q:,1��g� �wz֮�Q�F�qԆ��k8 ����񣊣��͗���1� �� ��;9�j� ���� ��8�8W��ɪ�w��u{;_�T��,���ʼ�S���_.�U��v����#'=UO�7�t�i*����m~ ��6?*��9�9�9���}'g� .�����Ჺ��,'��!i���q�˻�;] �|E�̬�����h�\Q�yڏ��y���� �H������p�{FEu����*:(�i�+:O�kw��ׁq��K�?���;ǵ�[߯����q-㸒q\�8�e�2�kǵ��Z�q%㸖q\�8�e�2�kǵ����I��I�z0�B�]z �,ɺ�>�uq�$��I�����'Y�K�.��d`/ɺ�^�u��$�{I���� �%Y�K�����ƥ#�j�j��g�?p�1 endstream endobj 1308 0 obj << /Length 666 /Filter /FlateDecode >> stream x�͗Mo�0���+8������WS�ɪ��*́��E]��V���;6JR�6m� /����Co����u2;8�Ћi,Azɵ�� 5 E�%�w�K\%oNx|�!���1D��|�8>?:�ι?��R�ɛ��ƻ�E�8:;L������������G~��*=�Rjz�����Y�bCb�����umQ��1��a� G��Q����&�f��s�ًF۾Oσj��v[4P��,�t<�ϫ�]�����\%k ��a�P�E�c��.�]%�#<��JȞK�$̧L�n���sW8�M��MSTK�ك�����^�3/�՚�} �������*� I��z�V��s�`0Y����v�Eݹ| �U���3�����M֒e�lCg�(�p�Y���*M����f� #�x;B�~��[��d� �X�M endstream endobj 1328 0 obj << /Length 677 /Filter /FlateDecode >> stream x��V�n�@ ��+t�bf_zlQ�ٷ4U'�9A�~|9٭k51�T>y��py|$M���$�����͚�ĂUL%�m" �u��"d����T��~�eE�WI.��I�4��Q�G�s��OM�����f-�o�fZ�k���b��,�����n|��K���$0�9���f0�J��i� ��=�ܟ��+=�(0���� ��~�+����ܵ���0�}�I�-�pH0V�U=�r�}ܹ����뾛�D2�T��yH -��Y��GP�� ��.�F ���E�bH�>ج3��]W��� � �g�]8�n�9@Йf�b@�w?�v���=��f-�o �9:�"�$M�(M����c�Ӵ�h�x������W���瓱@���˾m�.oj?�;ƫ~�wH��zrpE�ޜ� ��.Ӄ8 q]��#Fp��e��G�Uh�2���� �^����ƭ��P��" � j+A��n�=E4��!U��u���8���`[f�k�u\��Z=gJ�ES�1�`n(�R �X�C}quʡ�c�C�$}8�Lm��򍷃JY4 ����}�U;��;�/��3n����1��l V���A���(X9�_��z,�5.�d��;?I ?�Fy��'�a#O��m��;��X�����0�-Sx���� ������'��V� endstream endobj 1343 0 obj << /Length 134 /Filter /FlateDecode >> stream x�]�;�0D{�bKoag�'. q�H$V��!�� ��Q�h��4 ة��f�����"AK����^��  ��z_��j�c_Nh�Y'�&�V�>/�q�K��V �'tzL3v��o����̢�j�$� endstream endobj 1347 0 obj << /Length 262 /Filter /FlateDecode >> stream x�m��N�0E�|ŔN�W�( ,H�u��7�M (%Y�� Z$���9�jft@� �6����R�� Ij�%��'t9�e�)��>|D�jԔ��.�VZ��G�kʓ��>��ǭ�<$}�%7}�F�`#��5Ś����xڽ�v���d-~:���i{�u�Ü�ѵ+�Z��Χ��r�|ڕU���v��c�ѥP�.��a���lQ�)6�DžӃ�����+���X���CE��T��5Ͱ�u���ml�j�i% endstream endobj 1352 0 obj << /Length 724 /Filter /FlateDecode >> stream x�͘�R�0��y _:c$�gI� Jh�L)S|(C9(���u�L���Ỷ&�i 6�����]}Y�B��G����xtpˆ�H2��S/"�"zq�]�R��ǃm)1ʱL4:�����ӯ��G8@R*?�0n���S�>>}�~>;�h�_֦Gd˽@#�DsX(������I�}U$.+��m��mm5�Dm�{c򼄍�O��h Ab&�EYQ9S$��q'r����U����uR�T��;�p�9�[�]�!�Ґ��[�$7Uụ�h�g� ����ҡ˴���`�lZ���a�Ě����R;5���̙��1���s(>$�Zn��'"�{@�-m�v"#4�7{��� È� .��d��}o�b�X����R� ϣ��F��Kׅ#�M�F#$8bt�������պ��4a K�c�h��|` �� h��j@C�pu���0y�˦h�u�(�L��)Ba �|������(W����TC�k��ǚ:�k 3��Ĝ�̽�8���p�P�lja�FyV����q�e[F0|��j�cm]R)�SI4Us�2���8� XѰwfM1@<�~j�V���� "a�QC��t��m<�™M����j�Fo��r��!��f[6�P@}�P�_�_�"�ia 2�BN��qh�u����'BV����.wH��_V��I��H�Yg�8"��� �AOx>01�G��9 endstream endobj 1372 0 obj << /Length 795 /Filter /FlateDecode >> stream x�ŘKs�0���\:)z���ԝ�ٷ4˘��D3���W�iZ�q21�,�ݕ���()�|^|\-.�9JT<��j�0D ""HBDY�Z'�)W�����@��� ȅ�$�ԯ B�e&I�7����}лX���$�HxC�һ����<5�h�u�F�G�� �T��\F��P𣀽���"v���{��G�z8� ������iX��eZ�;�d~��:�HQP2O�C��ނ��m@���5��( #��ހŁ!�&D��:�Ƃ�ڶ�q1,���;�s\�k�\,=� �< ��6 �/�+ c3� �Δ�. ��ޠ�'F�_u��;5Ѻ��{b2�V��4��A�^�osm�ʺ�ٽ8Χ���b��U�eU���6z�,�<�g�񬣝�뺪)Os+�|��ҴuX�|E�6O�H�1gJ���9���O���]yd8�tƽu#�끳�(a�0+�w�j7�DHkݭ���O�7��뻘�K EN'�Ý��@ᇮ{s� bJ�g ��������X %�Qu��@������| �������"P��Ti�1�r1' ����ۦ�� ��ɼ�Q������яu�8d���t=���9�Fۻ}�|_�N�S�j0�!ex���^ߘ��p�p�����T�N�Ȕ@.�Ǻ�3�O���Cy=`��uU�ڵ]�icn�]��ԁ���:�A��o��C��Í�k��]i���t�,;��w�����Z����Z endstream endobj 1392 0 obj << /Length 760 /Filter /FlateDecode >> stream x�͗Ms�0����0c����0��&Pf���N����bƱ3����JCJ LjsI��z���՚w ^�N��ф� ��d2Ho���hLb�yp*]���&<�Z�(�2��[s|~>~{z�!B���GHJ���n���"�q�ӳ�ٻ���#���6􈬵�"1�h��m�݅���/��-������ƚ�{}�cѴ̚���L-��m�,-*��f��ƅx�?�+��q�مa%7 �Uc���ǘ����9�C� �%�1��}U��:BL����T ���� ���XSvP83c?����� �p> stream x��WMo7 ���/�J$%J��C�V Hshk�`��"@`�����3EkV��^������g3�R��)H�O��S���(!W��k�T��@R�h��b���!sJ�k;��AR�'�-� _0$6���dO4��f���09m͌�p�'Sh��9s������K��x2bIlD�$������\�"�H���9YDj�� f2�j��$-��X����c �)3��b| H햂�l|��%�`n� 0�j| 枌��ba0z�0@@��`I��=:�4��Z &M�Ik2h�R{AǤ� u�BF"V5�� �Aj-�:mF��Q[*R��]��R���⾞{o�V�7>��Y *��� k� L�m�Ղ9�z1�C�>[�a5XKA��,��C�r��Q���`��_L�섂Yӂ󚛂Y�‡���'�ܖH��Ak`^' ��u�PIK��$� a�%/�B�� !5�@wd5�_PT�,j�P�f醃�ؤ�;,5>$-ug@��S&�����p|��i2�7���/���BM= �����ËS`�-b�@���^�@i%V�n(�]���1!�] �.�_�8J��H�#a�����7Gu0Q��:��(�� �/���Rl��G��ۛ�pq����l!,.Q�}�/ŦS�/8u|}w����C� �ׯ.�����C�B���?N��������n�� mv�p|s���t��t�^�˳O�}�~y�9\%<�����;8���i\Ѹ, �Uj�>��m)���#�i�SL�`IQ�7���l��lNE��D��D6g"��f"�S�m�3�����6���6���F�f{k��'��Έ��!2򈌼"��"�x�L��>$�g���Zy(ȥ��"�~����#�1���5^0���<�r�R���_x;���>�Bߞ�}�===�J��ҷ�T��dx��)������گ�5�Ǎ{~^ m P�� P��_��yˌ��*q�U>�|NW����8]�#p���t����*��U>��|�W����8]��;���s{���3�ũWq�T�z�^ũWq�U�z�^ũSq�U�z�^ũWq�U�z��� ��Y�ȺGd�+��Y���{E�wD����� endstream endobj 1413 0 obj << /Length 615 /Filter /FlateDecode >> stream x�ŗMo�@���{A�;��$��9���`�8!ި�㙥Ii膦4�^ffg��%a����|2� F�f *=8�$ 8.�Gr�T+�ޅ�.����U|m�� �= �:��Q��Az��b��_Jh��m���zP�0���/ �+5/��S����=���f���%��j��ହ���zP�v"�_7�P�#��i��&�r~� ����զ U��H9��7��*ƈL�Y�B(�����S4�|�����Ɉ������� <��h����cE�� )Z{b ΂�jڜ( ^�~��쿸�*^��4�ѐ2���m�sm@Y;�lp���|�$:G�J�F�~4H�2"H�@��z4����lWxP��|� :�dY endstream endobj 1433 0 obj << /Length 1197 /Filter /FlateDecode >> stream x��Xmo�6��_�/�b�7�؀�8��6 c]���"16Y2$ک���E*�Se����t$��sϑw�{����u�`��wL�^����u/�{�a���8�}B!���;f�A�0�L4c��Ά'G�?�c �!�Z����x���G�����d��1tiL��n/6�Q�!(�]�/k��L_�Ve1����d�����T�J�_���Ux�)�ځ�:LQw��U����Dn�獃�m�#p$F�8���R{Y��h���L}�̌���b � ���g��玽�o B1��?b<�g��0�"�ɪ*��c ǜ�{ǂ�_ ����D/f�5!�e�I�jh(�<�r�.X������nU�y�DO�d&�y0q�Y��p�ۗ��F�n���~ U7�l�zV�L��66���`#dR�j1g?o�RO��;�G�\�oO�? �6-�KU�n`�������9�ƍ�|Q8�g� /?����7f�@�ڴ�_x�ʍ6d��� k���ư����Ֆ�V1�T%S]V+��f:E�iYkgj�ɥJe�c�}��5�m6���0�9�U "q�K�)�Hf4RE�F�i�mOY�V'��vVS��O��l�������aL{�,S3e*� �M���F��1�?���+�!�~7�%�J�r�C�m���\5wT�{� ��}��!�!a[��i��x�|�d�a�s���; $dw�8�몴�NRm�1�f!���J�$W_[��*�븼�������;�{�����H�� ż���~1�R�� ɠI�=�E����A�ǘ��>��3y��L�=ǽ�4ld�ۥ��bfe݉�0���C|s�?�g#��~%����&xJ�%+{0_ռx¶g�̓��T2)��Uig��K��]���"~�����)�2�YY���3�->jOd��c�����D��lH h4��Q@ʲiwf`_YB�x����/��ʖ w�0\��ހ5��ּA�2�*�\T��Ͻ9��V�e1��n� L�g�.��i�D�r�=��2���4�ڥ�����L^-&]p��[,���ĶÎ� 3^^��>�ko�͊����ł#]U�.�H�ޣ�A���{4��Cʹ��ǻb���g������/ln~Wb��u} ��������j�u2.�� �B\wno8���G*> endstream endobj 1452 0 obj << /Length 1074 /Filter /FlateDecode >> stream x��XMs�6��W�HfJ���o��I�:���9�$$!�H 9�L|v ɶ��4.u"��]>�}X@J�y�?�M��_�$(H��4���p��,Ȓ�$B�*xf<�0}s�l��X�W&��eɽ��Q�9��r�Ψ�Z�`��+�!%"g��zQ���ˈ�":�����) �]�����di�s�� ��y� ���������Q.I�d8 ��J�E�,+�BҰ��3 M��.bY�ޚf��'/_ON'����� Q��5���� 4T���D��3ms�@ �b $�mE�Jdr��z� mW!�"�������z���l�� R��h���ƶn�p09N�'G �=�2�7(�x�v�44�0 ��E4�x��-�݁��j<�ՙr]+��ex�H��� �E���� )Ha�Pn�ʵ�6V[3o�/v �1Ny�v/S 9� ?��m�ڽʤ��q�o2���Y���?'@��y��k^O.�G�y����HAn֩��F�mss�#n��:��Ԣ �b5� �VW�t�i6~��j�yu��/qH��iU�Q�>I���Ǖ.����xH۪�;�X��H������J�!�����2~���~�z���|�=v��� yzp�o��3��+=S�k C�������V~nm��`��ݻ�[��,�^��R�f�ٗ5�҄�O Sb�b ꉚ�fq��#{��y��[^j���]�[A/}�q>�WEt�%�G$���%I �#�]7��5.�c���>��)��?t���ŧ��D���uq�{|����{fR>�jh�C$Ȅ��� �� Dd��@�3e�nU��!Ҕ�\�& �my���p�7h��6�����l42� �!v�i�%�p4��_/�4m��!���R�sS�:^)�h�RǮS����&e��X�QI ��}4�ifm�l�0���PX|*�!�a�L;l�!'y�Ƣ�Ȉ� ,���Pp�l��4��G�<�a���RB�>O���(�!U ?�A���XGG! ��� ^ ZW�,0��|4R"�\(�,u������xB��K)�����U������� endstream endobj 1471 0 obj << /Length 954 /Filter /FlateDecode >> stream x�ŗ[o�6���)�(�ëD�]�-Ś�1����ȴCD���؇ߡ(�I�����/E�r���yx��M��_N�,ON�(2�%4 �� �A�%�\�U�)Ly�y���eOQ�P�X����rq���C3��7(��$ ��.|������o�=�yy����H��[��|gHL1l"4R�d~���2����M�~�r�d�H�t��UQ�ۼ� ��F����a>N�4�,Ei��ڇ֪jb�\ð�Ϝ�AL����ັ�b*â�TAê�["�Y�� bD��:/[[��a +�p�G�!��.�`<(����'&�k�pt�n,� .�lX�@$;��j��^PR���;�;GB=ܻGcV����Z:_bpn�����m�^77�V��^M�%�����1X�O"�%D���ɴ)�)���!(�cN/�q�ptuauSO�H�G��V� �)C�$?���3HO@#,��D����"d�v o���m}W��cU*�a'Y~_�H�(��`;���*�j�K5�1��ۄ �����GG��>��ҝ�XՅG������e9[���h���L݋��yY�F�4�͍;l}�w�yW��������֍�m޶0Ƚ��ה[y�b�ʫq���U��e ����2.,̄bZ�.��%b��#�[�4�������ya��pr���X���J8�t��A���]�M��ޣVW['7c�0�߂��o��W��[���ǎ���o谇�f�e�ɋ�"H_X̥x�" �E�N@�ɻQ_�������~l�����Сk? ~�;/��3�����ӥ�u��0�N��?2q��wg��8FPx�݂������W�F����1D���"���4 �}��R*��,��U��>�R��oNqF҃��o�w¨��M���S82����\S �_�Xb�<�<��3 endstream endobj 1491 0 obj << /Length 1249 /Filter /FlateDecode >> stream x��XKs�6��W��<B�ҷ��;�$=D��t�(�YS�J�M����AY�ٱR�҉x�.�.�D�Q�|�����%M��)M��e$�&#�d8�"�����OW��$A+B�JI!*A�y�f�1_�2mijݞ[�W��n���,�`�)�E�ۺ,���B���Mt�{�5w|#�a��Q�Äq�e���]o�j�㘱|��%ےHq�m��l�ߘE$X�KA�v� �� �,.��jg�0��#�r� #�'�8c4�Q�s�*U6EWXUd�����XM�J`&U>7�m�R��*!�HvtP{�נ�R���Rm�O�����W3Ab�m(pRdqo��ئ�U[�� ����[>o������{��FuSh'�<=x����S�x��������^��ڝ�V] �<�C'fn�0��N衩��™S�3���R +u�G|{��/����Ż7o/�1�G9J'S(���܀!��~I��(ԝ_����o��]���{ը��as�|�"�.� J[��e�W>�6^��p����϶�??��|�p .��N����H1����9�_���6Ut�k�Fe(tb�2�*�����ł%3{>Sd�Q�۪��[�s����\VfXy+:�;�-��i�R�bh 2PC���Т� =�)9FB��~��g@�ً\�h�9��>9)��#"1�[���u��DŽp��K�*U�U�V(d�!�(>�Piݮ���4>���C��um�@lB��vTħ����/���U*���t�6����cK����d�cBR֐�:F�b[8ό�#���/3,)��������y���$�#P����>&"����a���v�lz>x᳭�#�g捛gN�c"0M�n�`m �7l�+�˯f$޶?Ҝ7��`lH������BMݯ7|�O=�9&���ş�R����:���C8=e O�,�����tC9�G"O1y}�툝�3⒄;f[��t[���1u�)� `�m� 2���h�G[ �2h�kW�C�n�f�lA����L9�[��P� �p�X��]w^��ե�]j��[s��� ~l+~�dU�[) �muT�{q�>�-P{m�¨p\�> stream x��Wˊ\7��W� Ԫ�������.`/� ^� � ����)M0��ݹe;�,F]��t�zI�Ľ�B�ZQ�O*�� KX�2�0�`Xa�0z���Ex�1��y�K��8�* %.�ᇴ�EEV��a�2haF��Yf����\`neN�g��+0��=≧�" �c[�1��bc,����z2�𔱰�`a'0�D�T�!pX�l�p�l��m�?�cW*x�}YX���b�"�ᑅ��H#j2G�X�"�H�-�W,��Jn�^u����2 6����)8L �E��Ɍ_X�N��Q<�����,�B�<��Svx�#��\xP&��E|h��:8f��=d[��b�?�a�V��� .�У!�VWQ�f�+ � � ��{9L���*J"k������`y�a��VC'8lD���V�"K �t6Ɉ�*�,c�*Z+���`���9c�W�]`��@� ��3�Cp�Q���P���ń�"�1���B��Ĉْ��ʁ�h#, i�b���qu}}uxZn�:�����O?�RB��j�`�����˫'O.U�����&�!�] �[Q�}�j�b�*c���2���@�^%�Cf�II+A`���ubl?��ܽ�/���p�!~�� ����B���1�\���{���ܖó�7�����|����?��ǫߎW���t|{�>6���������û���=|�����_}w���6|�1���^���;�{��H���<�� >S��@(Fw�MFh����5���]��Y�%<��<��w����%�m��w����-��N���^T� ��N���~���u����7�L2"��ȶ@�ʬ �� f�^��8P��L�!��[�<�Y��F��@2��Q j\ժ�U�l�c�5��U$QG"�� j��D���qe|�$k9%).�[%%�d�T�hjr�ph��q��<[��j��� P��dDc����js������O���U1Mq�pM����I��H��|����2t*��_/��2x �Gl�E� �����6��� Ή�7� P'�(�P�*8;b ^a�'���G��{9.��dX�ƻ�.�\�1� O$'��K�a������g$7�Ar���g%�bL=�k�ԛ��[�g7� P=.{ �a�9���7K0��Uf�Z��d��cT��Gf�<1��ݺ%<���W��R_�� endstream endobj 1510 0 obj << /Length 873 /Filter /FlateDecode >> stream x�ݘ�n�0��}��Pfa�����DA0 *`�ɸm � qBU��s�T�Mi�i"�hk[���g����4"��'��D[�T4?�,�41�͗чX�٧�ˇ�^��(�J(��y����ѳ��3�9���RJ����������P~v�t~����ۙ��qz�lr��b1 y�Gs�~�i��ţ��`W>������j��B��q_�����*·� L �Z���z�3��et�k�� ��m��S�!�� s�᤬VI�ҙ�qY�U�7��J?�j��vM���f�����6�Tql����Bm��(k�,g��8mc͠P�e0B�b#a 6��d �EX�5�a�[���[1��4kȯE�ok~���a���l\�!p� �M�u�]V�a�oy8�ܘ���7�ny-�S.�o�F D��ܹ���K��&5E�Ԯ�t����3+&w#1b0��X7��[65T��n$��~��U��P�-K�6ӥ;��X��ъ$"d`�Ҍ;�����!_6U�P]%�o�A�p2���c��JaI�N���4ĕ��([;�0I���^���[8M�N )K�;P���<L�v+;���)������ �ਆi %�\j'x�2��Op�������ɱdf�>��E����rl�^����%1Ub�SK Ō� ,�2��^{߳5J��U�3���������k�訬� Ӧ�Z���/BS�Z���v0��pZViU��h��P<�GW��ɷ�����5�:��� Nfٴ8�K� �Yvz�Y��x�g@�[ 3S3�h���Cr+O�>�����T� �S�7f٬��O+-fڌ��&\��A�Z3����.�pgx#��|�'�B6� endstream endobj 1530 0 obj << /Length 1140 /Filter /FlateDecode >> stream x�՘[o�6���+�V� )����$��lC7�0��mѭV] I�?~�%v*�^��ٓI�::�Ε"���?��OON'1 2�%qL� &IRL��y�!�2�8������.�Kx��]_#� 'Q��U=��c��A��G�}�?�G�KL��Z�9�7.���l��Fq��8vg����E q����ۦ[Z z=� ە��0�/l�涺T���m��Q���vc�~�.�6��a˰WE �ô�V^��6�󢅗6��C6/> stream x�͘ϓ�6���Wp��A�~K��x��L�L�C2I�� ț�L��J�u� ;f[z!?=I=}�dm"�|�b}�욠(�� "Z�Q�"�D�G�"�K�|^��욦��P0�\��7oV�_޼O�4~ ��׿���wޭW���˛���o�/�&���� 4�囁�\'���t�����͵o�7��� #s�����0��$���-���,|Yp�g�^�>���$)���q��8t��uVoG�P��7�}�-8}`! R�� O8���u ����#P�ÒC�bW`��a�LcA�$��8�o�I\���;�M���� �s���� �K��I]�Y�?"K���Y�D�����MfAe�j�R��/ �%�=�䮣4�_��#}�Ő@�D v�711"P�#n�'dZR�� �ɍ� w����K���;S�> stream x��WMo�8��W�TH@��K$��H�.�E���큱i[�L�l����r�$�V�$�Ŕ��h��� �$��$�N^.N^�3���L&�u�� W�"�'�U�1UE�i�� �W%H+%������ q���L�������a݋s�~��ƚ(p�-�X�J�?x��ƚ]\p+$�0�����K�����^����s^�>E���`!1�7�,���[gv��������sF,d��{��k#2& "�l2�ӯY.S�����w�٭�&Z6������u����r�1�^��w��L�tq����3�M/��!Ek����i�tR�0'|��|�a�NC\ț�jd�H�E��)����Vu� '��κ���= �C0l�3H:�� �7)R�V�oB�+}�h �Z8(L�]���� �s���^�(��X21�߉��:��g�vO"@ʊ���]�J���d��UЃ�.��}S�;�m�ƽX��-�2�^�@�EЎӗoΞ��������7�\���|�p���,7[�Dz>��6?�sN1W�I�u/ A2wD}4�C r�A��p�:�,��R�"Ǵ�%��cy`�ρ H%Z��*H���!F��g7�mZ���j�1� �X��t���ý{�U�t����-�C��'x�����>Ο���ƃ��:��̶�N��|��i�P1V���d��s\���I���$ݵ�� ���a��G9�d���24B�n_V������|S9V��E��gO?�-7�!���-gOQ8��'r,��E�~�K�5(Wå@q5ٽB��|(oc3��*� rr��/?�p��:0ʡL2=#�����E���a�ZNF2P�|N�o��@�{Q�M-א�1���I�����.�~�n�� W�Ϻ7��x��MM7� ����kfj�_�9<[�|�S endstream endobj 1590 0 obj << /Length 1010 /Filter /FlateDecode >> stream x��X�o�6~�_��AF���ܞ����M�Ŋ��L;�ѓ�n���(�i��צ�^$�t:�}��xI I~99���^P�h� Z$�y�I"�„�d:Kަ�d�W�L?P�9�/�Ġ����ɋ���e�1��� �L��N��՛W���0~zy>��~��&S,}�M��їG%0�b0� da����s[v�O�3N|���n�X���[S�խ �Z��ۈ1�e�6 ݺ�M�㘱{;�b���T%(�Y �����e���Zݙ&�Aof�B���J � ŷ���ح���]�@(����A�h�)+xZ"��`�c45h I1���4r/h�2��=P(0Q�W��Sw���iQ£�¹K��8�zD� ]\yV�e��F���E���8�w�vc�U��0eZ��Jm��a���Ek�`��iݚ*Cyڻ�??�F]P��6�ŭ���4=����W��ɀ�A��k1�o�;O��d�@�> ����{K�\�K-�`�E��]��[�hHE$��`�ء�-���~ �R���"(Ak�Et��Z?�;�z, �T�H�Y��nf�؎TJ�w�1�09Њ���j�ĺ�jU�7�IŤ:�*����/3��}5��D9����X�d��-W k���[�6��J�Ƃ�cpt D�F���=���F�Q8dȣQ�7X�\�cTT�s�CQ�^\ �7\�k��LpKWi�� A�s��A������]x���E���L��`�<|���;�rc.­ �й�����|z��?��k����o�,�#��Q��B�:[W���cw����*ofh>~�W��T�|�tn5d���.�����ǣ"G�H�m��WkN�40� G8�Z���Ң[%e��D�����Ie�:���{�e��X�ͱ6��VpL�_���DZ,��f\Н�"�TNNiڷ+F���Yz}v5t��Zn>j�R�����]�~qQ�*v�g��œ ��a��Y^���h<���?8�� endstream endobj 1609 0 obj << /Length 945 /Filter /FlateDecode >> stream x�͘Ko�6���:5ҁ��&{,Pȱ�[�Z�k��ąD���w(��v�$ bK�,)>��7����U�'\���xI��`#�Lv�D� �L%*�8�"�U��T�����E~�� F)� �`&����c,��4KǮ���~ ��_r�t�u�@�4�q0���f<���eP����І�>�5Qʳ}B���,���B+�y��a��8f̜�}�#{2B�\�G9�>䴩�H���QK#�°�4������ QMSmC��]����_t��n�*�][kQ6�p�Vv���»>����ˌ��:~�a�/L�EFuz� ��PpD6�}j��2�� ��>*��%��b�;<�F�`-�4��',�-�ޡ�i<:��N���l@���h��_L����G����ck������݄ dQٸa��̡%\p��� .�rL�ܒ�k�uc{����q�-s`HN1��u���V�aK�X���S.32 �&#Z�chAs���r㾱��p��Aa(挬~S��G.�� 0� �|(o��um�ς���\�6q�p��� �NZ���}w!$x��T����O!2��/�Έ���s��o�96���b,���{[��K�]��U,X=�7"j_���6�u@��.#vTu��9��C3M���� ��{o{�$�iN0���e\����X�9j lC�>��Aћ�:�p�n���]�DLa'+�?J�7�!�3��а�"���g"�B�!�`͆Dc�p �W3�Wާ���0��-/qSL9�碞d��� �X��Ww�/�r�O44�O�*95,�Ma���Ny�> stream x��X�nTG��W��t׫�%�E���� �ba�Qɲ#c$�{N�Dߙ�-9Dd5��u�u�ڮZ,�T��$�_�H�*�Z��%Rs���$�ih��ݰ$GpKbe�'-��H*�J��n�d4 Jf��V� IM��4��d��SPK�<���G��JqG �:�L���Am�cPyr �� ����Π`�ȼ&b����M�xp����`�T��l�H�~�h:��չ��?�yB��.�=+j]&� �ɡ��O�ɡ-M��C�kxV�B�4q� R=#��΢ $��H�f!���! �-G���ԫ���{Z��w�5��)(13iì�i3X3��`��'��(�d� [SUp� kF� ֌��Ԝ��qt�������i�q�����;n�_� ����m��}�b�_���-�8y R��V$!������Kh�����]��b�]:���� ��<����n�<]U�~���߼�\R�\��ۏ77�vϞM����C��H�K� �:��x3p��9��?���������*�_<�L�W�O��W��>��v�_��p���o��n������������w�������O��A�P�D��8��;�a��������P�Gy���� �R�j��m\Y0��@�&S x�U�n�M�tͦ��E$�跁�s��� m�d�'7��F&\:�@ny�@up�f�u���Y8��Z%��6��PDd����gG�BqQE�j��֒�l�6�EbĻ%��Ci��jȚ�I��<$C��r6�`���gZJ���Gb4������VW��4P�.�����d�j���iڑ�η��jg \�VK��Z׷������m��n�%pu[-���j�[�V ���ZW��������m��n������,�8��DqQ�EgA�YTqU�EgQ�YTqU�gQ�YTqU�EgQ�YTq�d��p��3O�ޟ.�y��p ��U#K��d�J��� �#��m��-���W�3w���aA�cG��V�!L:�3��8З� ���J�QԸӨ՟����n+Lᓅd%����'� F��0��Jy�[��� endstream endobj 1630 0 obj << /Length 915 /Filter /FlateDecode >> stream x�՘�s�8���W�����o��k���(:���҅p�����{�z۲#]+�K�$9���{N. N�}�(9xp�H�X1$���L� �8���+�`����˗�����<|�#���'�Ë�o_'�φ��㿒���� ������ G#0�����S}�9��/\���spP����`C��U�eg��T�9:O�I�3�Vv�{mb�b�w}�M�ΰV;�v�v��� ́�h�a��|�Bab̕�7�"I�=�v�� �)����B�����u�� ��ʺ�����16�*l(��Y�5�Q�@���޷�i属@W�� 3���X?�A�;��?a�n��,>[�y"�M�d*���&�KE�Π��a53�Ыp�,���r��P� nj��B��a(f���Qj��� C�c� W΂��^.�% �6s��6�� �����C��ծ?��?N,�0L�X> stream x�՘Ko�8���:ҁ,ߤz,v�h��0�CуbщZ��T�Y��w�G\� b��^dJ��8�pf8"�uB��.^o.^^2��8WL%�]" DŽ�D���ɦLާ�g6o/Ȩ� ��HӠ��/✧���i綡jܫ���R�o�`�!&�mj,�Z�Q�]TN� �FL*�g&eX+3 �;�~f.0��$�a��� ��1ǵe��M�l��x�a�}�D9Ò+H��H�5�`+3��[�� �2N� �c#������E�SU�3d��PO�Կ LF1��)̿�4? 76�`;��� ���gD�B���/�**�.�~�g8Ѹ{_ ����i��!f�_��k�צ �����W�����!���8s�O0�j�D�\}�=�p@�0U�����)��}6#�OMԢl�Z�x��Ó7�;�� `�D�/�(W��y����8]3��(�$)��f��|>I���k�����f�T{�_�����f�R�`I����i�z��4�-_Z>�;�C�4. �⪎y\����1�����E��A�El0W��miwEW���^:��tU��6Hj��/�>�E��b?��b��y��� ��m��@����G難Rè;3{Rh��\�)����mc:�k�/H�"3׳B�P!�Hp;����̏�c���h��W����$���2�F�� ���b�v۴%�M�n-�\l��/sС �P* #zr@\����q���0�A��ps��$0�c^���q.�/��n����\&�?=����tn.��� D endstream endobj 1669 0 obj << /Length 2467 /Filter /FlateDecode >> stream x��k��6�{~�$r�zP�ep6N�A����^��-�k%z������o�C=�7�]��Ŧ���{���ݙ{��٫���=K�$���,q�bw�,<[��~�&l�����M� �|/p" �3���_�������z��(���s,>.��KZ��8_^\_�nG��������.�}�LX� �տF6����7eZgU9� 2p8�� ��I�Vrm������rSɂ�QVv= |�a��-A��.�ű3 ��/G���CP��BsP�A��0�`�;A�%/HO�nz��z^���<�O� wS�b#UPY:n��<' �)5^o�p��m�P� ��愉X�L%m�[�n2]\���|N��ȳd���5n=�P3L �4N��>��Z� �f�s �+'���︑������L�?���`��4�X����U'�T�t|�F,H�5�- c��i�S����U�z[i��-��k:w'J!��i�'��<�t�)vR(Q��j�&��e0�jC[d"l�<���}V޵ YLO��W7t��v{E�aȺ �莀�X��~�bd�ד�bk}Z�"mp���g���Ȭ��NSi���fzJƟ�E���Zo>\��fk?� ��9_�x�z���乆������$'E�Id����j���P�ژ��vNJ�zt����`��9-*#,W�rˑᗑ����k�A"o@�[�@ٞ�J�:s)L�npī��aywڥ�iΕ��0��_F��e�W�а�r�sh�Us �� O�����⩬Z�?0�=k��Z���i1��Gq���MZ7�̚R�4Y������҉��Jd-y���̕[H @���|�ЍP�=T'~/^����u���ɝ \�4��ș�_���@�e�l��`nl�}�UX��t<��Qڬ���"���<+��]��j��k���(�� X%^�9����񆧫$ R/�oD2���\x�y�������L����p�>f��=B�� (ȏ�� j�[�J8q&n�7*tЇ���G��0p����t#��=�� �ۯ�eU�kJ�iS�uD+#�� �stQ�*������vv a[aOX���X��%� m�_ЯE�;��ګ��lo�9��_t�{�I���7B����M�$Mvt�nJ�G���R)�&a��R�;�Ti�x�WiS�;Y�I~LQ\��B���'��vZ��֦^��l�5i36����E�%�3%(�& v �4rL�5����e ��.���T�b�Eƒr�4�r��X��%Y���xG��� {OHb-�&�ml�]����!�B���$bK��k>ph���ج�ݧ��q%��묿iZW����٫))��!���-ZmfFo=��Lo�]P{�����.�����jIh�NG�� o�\�T�����#&�م��i�Oլv҄�P�K�+3y}͎OR�f�E�! ����٭��Ƹ����F/d>�� ���!2�i�xIs��K��*�bM���i�K�k�s%�JqOߏu��4��b#��7�u��]Uھ��{#m�]�C���P�dX�nE&���fV��I+����[�:zK�p�wD.�����a�Aˇ��F�p4�<�F��X[�*�Y7�-� ��QfEw�M3 F. ?�1�h�{ �ׂ�Nxo]ϒ#�f����[=������߾3 �k��1�Ȋ���EE ��w3=��I����W���Kں�|g�����f�=� ���'��$�3F������1���狅}qu�a���O ��ò��H 1����-!ܚ���@*��~tУLS0�x�FY��2���+�v*ɡ�90��?����h�vj�wY� �>�yy7&=�L�_#�rhP)�cn~U��oܦ��e���?mV����jj� V��Sw��){��L�]�`D8��b���b���|;�C��a��z�<�l�x�Ñ�%-u=2�/�4P(����i߫��7�J�y6�vY��N�'UG(+��k��M^�vPN{��B��� ߆M�v�"�F�<�pN��lMkz��" Ř��!��Făm�A`+=�UV7O ��م��m^�Xl�0sa�37HrL7��s�7�@KC"�$�~��Δ �� A�*�!r��B=) ^TL¬�- ��<� ��tE���Y�ڛ�m����� x��FC8T���W��vJ�}]�!��bxͨ�����e Lt�Vf���K|��x\��o�/�%��){ap~�����z�C��/ܖ|���k`ܿ;�#�X�I9�ڦǓ@ �oI����;F���X�^\�UD��,~�/���Z�zV&O��� Q>���T�f�M��ّ�95��#E� B����a�|�o��?� endstream endobj 1678 0 obj << /Length 1847 /Filter /FlateDecode >> stream x��XKs�6��W�H͘4I|��&r�LbklezHs�%H�"5$e�3�����B�M��'�v�a�Ò�h=rG���m����wG�~0��F��+�Q�F�+�h�}�"5�<��5�F����G#�a�`��"�Ii�|�G�}Z������Eh�]aXy��Woߟ���h/�ey�r��2+О^����ҫ�������K ���ʜ�� !���RV��u��j��e)��Z�ܟ �!���6��y��Z/2���)"��KRX)}EHH��J6��6<�SbK>��R��}V�= ��:�tϾ��ѲE��O��]YN ]U�a���d�V]9hI��xdvϼ(�9j����}����UާՎ{=�P���f]&[��1�w{�ߍ�'ϵ�gf|~�i��eJGG�,�<��A�.����JX������Yx~�4�+��A�|�����Y��=�辢8�S�f �@�ği�,p�-{*8�p3GҺGš�qu�a�[,u���.J�*��%O՛$?ء�!�!��,�˚lO��n0��_Oo!�n�Wx�3����,X���=<e���p�hT��A6A�� D{�ɧ+;/j[I+������|1!���cd74.B�p�B;qށ��8�0�R�nK�<��1��� �2$s�N�77��� +�S$/�%ƚ4w�" ƌe�Q�eY��[��&�0 ���o��*�%�r(8M��M>�QL6P�����H�?�-J��2�g)�M�[�L�l�x��^�֊��"A���$N�Y�0h?v�0[O�]��9��'`��1���b~ ��v84�@�ؠ�v��+8`;L��7�T�v�ذ]���Y�1�,��YO&<� <�OM�� ���P�'<���%�v@��� \����'=���q�Y{]��*��� �D!���P��^�"~�ь>��x�� ��������`����;�� �AgƩ �wk_�ψ�8�m1r�[x۽�%���澨�>ƒI w�=�dh��Ol��Cߣ˄��@aƐ�;F��ECz��M�R��]�&N׉x;":$=鉎�DԪ��}"=h[� �����8���N�L����u I��� f��.��NB~L.f����a�P#ٙ��% � ��hH����R���>}�p��M)\��SgR��r&��S,�ZGLټ��wOፕ��n�-��TN*��X�� b��He-�.P��)x� ��V�9K{%;n�H*�·��e ;�g'�-te= ~�u�����w+@Ӻ��c 3�D�e<�Iit��:��n�b}��}�~��uz�N�Х;,3���l$_����k�S��>��E�`�rM��N�q�&碤�7PC�kx`���]/ r�o�QP �(�6�#�������\?��_���|z�R ���'�[�Ӯy�o����+��9Ge����D����/?�Q�]�b�o/kl;��"G*S��:�����uZ�T>��~�?D�Dn.p���^$Yf/ ��@L����E��Y�i`S� �V�z���#�#Dܨ}>�����|�+�����7U�b��.�˟F9�y��R�*b��_ �� �����@8�+_ L��`H8d����J�3�q�.��IRa���_� �;����� +�<�j{nÒ/���h�7�����P���x<`��?%ڞ:��a���O!���q�y�C`��{a��'�0� �K���d.�l/r�S�:Pq��+��S������ �F�� ��W��dTX endstream endobj 1690 0 obj << /Length 861 /Filter /FlateDecode >> stream x�͘Ms�0����:p@�B���Mg�fͤ9`��S\��I�?�+A7QZ'ЋG�H�գwW+�s�`���~��{D��H��'�N�%Œ;q�\�Rx���#m "E� 0a�읞�N�?y>���G�/D��oGM���Y���Z ��@O�I;���/-x,���)��8��鬸�P�}���K��6� �¶W�ޥ��2��U�˥lj��i��T<�N@� �!x��_ �)q�T������Ezb���M��� \���{� ���W�[�l��������P����@��"�{hp�|Z�(���rm�Y7{��{�ɩ��)0�:H�mN�Γ*�ڞ�N#*Y�i�6�����+-h�\'��nґ0A���+M�v  ��n3"�L�xD0�BʆȤ=��3x �2�51�Ps����S�+-�&%=-+�H>K�<�'um��("��w�K�,GY13Yʚ: ��k�R@���U��B�J�Z�^[)E? {�EL�ݵ����o�,�2�}6�~��ym ƀp��4�R'����V�O3�A��;��޲̽������t����_��cG�?:H��6T��> stream x�͘Mo�6���<-�~,�Z4r+�[6Ef��Ht���;���!5�J=I����w���Q������S��\�� RT* 2�*Z��efM~��X��,�ee$���L1��'�B��<�"��eX7��8��\��7Xb��@��.��2�Z�+_߆�a«%YI$?L�L���h{����I���^�] #�8� ��8� E]�e���_�߅�Lj���7D�=�� x��۬�m|��M�a�UQ��I 6�9�2��e��' wbr����� �0���D����_�d'!���ľ�!Z�y�����d���;b Ԝ0;�0}�� &ܚ��1<~E��l�G#��|���$��YY]�JxE jr���ǎq­��5Ӳ�0&&�e��l+��Fٴo�9�r�(%\�9�>��b��� ]J��8%g5Q�^�=�#� ۚ�O�7���M�7E�6�2o�M%�À��dR�����mX�e������� �e��o���F̐�;p�/��گ��~.��^�=�wB��-�.6��]�1eo#�0��8F�s���Yڢ<����9�j�sNu\W�@� Ʒ��^��SP�˝�6J�w�����ƍ@����պ��}!F���p�w�ݏ�Y�j��r�FCC�9¸@�q�Q�Y\^Q��/%�Y��� 8����U����y���%���4��B������CE�'��_co���R@'���0� |��dJ�2�T��U3X�ct5�W���c��*��8{"r|?��>�Y�&���g� -���`�q���C75%Ч;Xt��Җ�g- e�uO�J���7!����21? endstream endobj 1627 0 obj << /Type /ObjStm /N 100 /First 973 /Length 1167 /Filter /FlateDecode >> stream x��XMoUG ��W�/�7c{ƶ�hQv�e��@����HE�D�}�'U ���k�ts�K�=�<3}v)���G�?g1��Z:q��2�P� �2z!aPa�ap�W0�H�/ ���Y�F�2( �c"�Y� ̾�A"��k���N`��ar�y�Ns��W�Ұ0*Lc���¼ ��3���3�U?��E���:�dx<|��V��<����1�ъ� k�Pi���h��Nk���)�� ‚��ÂGS`)F��< V W4^zTR��`��� E�MF����d妡?�H �H�) �/>0�财�2<�C@�Ὼ��:<-/!1�����?���1[uо����'O.���.P�WA.�@�#��C[k��h�3��Ր�.��i���8�(T\e&r���v��'rQ��Tnn�ݗ��r��sZ���ҟ/�@ �z�W�g�o�|�//���ӛrxq�x_�"|��oG���/ǫ÷ ?����÷��W��ǻ�������o����7���M(A�^�����u�������N �A �i����?N�� �} �Hg׼ �]��V�%��g�r5�}�H�c�6����٫QG�II���HY�[�:�g��u8FNt�w�}$:�� 0ƥ�/)n�Q�|��$�8�*n �z� �ۨ������L�"�Q9;�[ S��x���Z �������Lԛ\K�<�k����K�����@pc{��W���S�L}�v�%�3-���ݶGS(T%�YZ��w�.��m�_�S;mn�T�晆�&�)(��qw�>�7�ٵw \�D `��3���qv���^�� Pg����+���]��g�+ΒK�e�J�.��]*-�TZv���RiɥҲK�e�J�.��]*-�TZv����R��Tq������]�}�'ŝ/(�wIq[�Eŝ/)n ����%ŝ/)n ����VqB,� endstream endobj 1731 0 obj << /Length 683 /Filter /FlateDecode >> stream xڽ��O�0���W�iJ$b;?��(��(D��!m ��&��u��s΅� i/��7���הz����N���9�^N�^����˨ 4N�b���B����s�����4N!E������ ��'$�4� 7�7�����i1�����[��G]/� �"����ȱ�/Lsn����Qu�����DA�]OZ�p�L���҈�<��u�c$K�.��6F.;��p����1"����y&[#�4����$�}��(o��',8py�aƪ6�B&��z)�#g6��`&D��?����rjj��F=VrN����;�DqF��Q��7�MK�6��5���Vj���f���hNX;����T�.��7��#�j'�̫r�Fy_i�����=Y��S�13��ZPE�󩖥��c��łk=���jc�t�A;����Q\���T��u�ݥi�K�ܦ.�U��F��f.�˥�_D��}3���$�_?�}]���>t�m"��� VEF��8��ym%`��G �T��Y��'���b9;9��?0�$���b��J�F�w�k^��p��c�r{T�p��ਸ]�Ei��mq5�ӑ�&�)3����(wqG��n�D���d���m���0l� oDU=�Ag��U�%���%��t��xq,�'��OJC:�{P�~r �� endstream endobj 1738 0 obj << /Length 217 /Filter /FlateDecode >> stream x�U��n�0D{}ŖTafy�,sn�.H��� �@+A��!���Tb�-f�� �ާ�<�i���@8�G�h����q]۝,�S�-�3�� {�4�\'*��Ӟ;� �H���@�%�[Z�>_ ��{+�6�;�w�Ry���=|��j���JǶ���/��9��楺?i�YC�_���mف4U*�q��9 ���ߥ�r#|��I���Z��K����uQ� endstream endobj 1742 0 obj << /Length 1972 /Filter /FlateDecode >> stream x��X�S�6�_qO�/S+���K��#!$״�������� s3�㻫�͙�B������jO���ʙ]Μ��WoW��x�,ei�E���,uf��0'g�|���:��WGo�t���' B��}��8y��yn��o�E��:\������姓��y�[���W�9ȽS؞�2� aѧ����|��\�����ogs� ��ý�J�k��3Ymx[�e��}�ھ���?vݘ���o�uB���(���fJ��BP���}t��;�� e���9�K�?�E�jnAd��l�%��-�r�7D��k�m�E�bkK��E��(�[`лb �@dyA��c�dz�)M��� ���n Q��ᰶ�44!j�{����,A+E`���X)�6�Zi��{�Tm3e�4d�Ë�|/p���%��J���+�F��rK��F��J6$X"k oY���#��<Q��7�hh"k�k�� 6_��v=m�!ڊ��UJ�O�+�7��0���7�-�����r�f>����l2���6�ӦhE�iI%h7�sůqIu�\)��Fƕ�����������(�v�kԂaT�����F�Z��������8���;��8�n�L�.�Y������7���7J!y�� �����j;i��i���������A�i;it;������)�u�)n�quD"����E-����u(����t���dJ�&5})QB�쩐S�$��7 �E'+Gz4����E�tJ|]̦,愰�?��d-s����x��tI]��Q%��{ Xْ ������� X���ԯgV0�T��W�z3� �m�\��=�字 ��W�i���`�{𢖭���*�Ϛ�.E;��T���壘yI���aB��<�2i .&V:���7r���e�:���k�әNH���]Զl.����>�,N̢��x/D}��.(;3E��Y����������6nj �0�������#Hn��ˋ]"�+��i���1ε��r*�-y�c_K��G��B+7'��E�d< �����Ə�]��@ɚ7�ol��8Dl�L�|�]��{���v�Ѩ>6-N#kw��bKtt@�\t5����h�(E.j*K��D�����ڢݢwj����Z&��X&r���}E}#T��u�X'��UR5�ܧ���D�l�����D�돃c� 7Ush ࿽�"!�|t;��~��L%.T�̰ ��a��Aެk��A�b��j��Q��CBӕ�cA!q\ �G��ާC�ĕ:$���^iо8�}+�I����lE� W��ܬ�2�Q Q����!�����AN���5t}��އ������@=�+����Ǧ�Ǿ���X�r�� p�G�:�����������ڻ��j`_�<�&J�) ��������5����2�$���$+��������r=@:�?΅�� �������g��|�wu��_��|„������;��O�@k���"�v��������9xMd%L|h����Z���Nr��B�$R����]σ�2q��y��Tb�:CO��ۙk�6�����T���8L_�����&�$��k����%Z���N+rzIY��]=�K������~�Y [}|J S�ȯSeS��0�r�* �^�Pǂ߲�ge�}�;��6�-�\'�g�v�j!eMB��� ���h�w5\� 6��E�Ow�:� �:��W ������ ()���ʢ�z/���˂r<�֦�kO�`Pa��S�v�%�%WC�9z�)���#P�U�חli�E������(r#��g6��3��W��b�BM���]�I�� ����80HӪ.kG��R������m}�6���)������k�F/c�t���7��Go�p���`������{�ς@�g($f�,E�a=�oH��Ș���P������UVGl+��7�F��� �J�����I�-V��n�~T endstream endobj 1758 0 obj << /Length 1557 /Filter /FlateDecode >> stream x��XKo�F��W�TPA��k���5�T���Z HrX��E��\��ߙ��,ɴ���P��kv�;��7õ�[�6��2=zw��F��� �����l/4B;b�ύij|2cg�ez~d�]��T���N����,��̳Q�]�ȼ�~�}��|w�"�!(R��Ģ���5떤7�����^�Ӏ>�����vH��2�Ž���ޚD��(�Z����ƕ�vK�̏�a9>��O�?tr�ɑ�{�)�u*Qf-u���(�s.Fnd~qn �I Ѷ�6�H���y��I�4Y���_�]G ��l���\�z?��#l�Y �0����z|��1���b��t���A�+/5܍��s����{%��v�"� �3�x��B`9���X�(p���0�(�X5��ДPuL��)� ��B��%ht6�8] "���O&CاK��+ ��k���D$x�y��1藖��"o� ��/9@�׀ǃ��c��NN�� @����a ?��>:�P[3�0�$I�4����4�;��>�F+���<��J�����A��5����Rnk����*�S��i0R�H͛�̟��O`(�9���n0!�ݭ`��d�Tk�'��2;�v�����H�%��iK�Y��E�B>F�}�������dBéb`J L�pGS��cd���K�WueUy�؁Y��+��7�mF�i�&M�lH�s��k ���Z�߭ε�7`�L�O�[] Җ@��A�ÿ5ԧ�e4��L���h}_/Ϻ�К��D�#ѫ ʤ����V�[��{�i�@G!�T � շ`~�F��"�]�xmЂ֚�� 2uJb����hŔ:��{2����*]��J В{��z�`{� �3��ڍ��l��� d��D2Hq�"(ZǑ w u/d���P�� �u��/��=�X���"+5H�q(�kAmA�^ 8��F?����?J�� ��?g_�����7xe�E����/)�=0��G��; �×+��O��p�H5��r;\�[��Y'��e����u�O�ר�K�b�y�wزx�M�,绾n|�u㄂�����t���;Sa�����=��U��$����@�D�:g^�/�.�. �Y#-`܇��` ���S5a���n��z���|�r�<'�w$uQd�f�O��rA��� ��.�"o�=eY?�_9T B֍N=d���?��n�L͏ ���ծr�St������������_Gd*\��pp�;��[����/��w�\��W0Tڋ���חx�{���ś�nU��;Ӊ�ǯ�tN&����"i���C?�ݝT���)� <=�� ��裰3�4y�f��O?�~zr<9���[��+q���mnO�o,Vy���|�� �;oh�ܺ��ii�� ����zS|X���X�>�Mѵ�:������['�^3�xx�F�s�9buYE�j���cUzkE����R��C4�Av��a����N�ω�D�p���<����M�B�J�+�*!��Z��T�8��֐��)����g�3F{��tz�7��Y� endstream endobj 1774 0 obj << /Length 1462 /Filter /FlateDecode >> stream xڽWKo�8��W�������7'qZy!v�-�=�2c˕%�D� �?~g8�"9J`�\lr8�|�5X��ǣ����3��,�`0��� �"fy�`�|5bg�m>}��-&Ǎ`��3��_�N����'lhAh�?��0��hq:9�O�.G7��5���#K+r���81�,!]�ο$� ���D�E�����e?b����bO<�8.sC����#�aa�YWU��a>�y���8fE LIƫ���F�~d�Q}���mhp�]V\��'pY�8�vY�$��ȸǟ��� Axɕ^L9R�~`p�$E^�r�ȢD�g���x>����хv�>�+Z��@��CE� x���b? E�w=�؆�N��@�(���ЄAN�������(�<�L�&%IQ.��,��l��fGG׻jdzN|z�F��PK �� 5ݘE�>���d%���Cׁ��Ϳ-�٢'���� ���Z`&���VN��=�vu�[4Wa��|K�抢x����]��s�47�j��F�En[�\��3!b�l2>?�eqG�W���ɜ\�ဴۡm�����a��5Ҋ�ur�H U$��j&I�1�ޠ}'�1F=�X�蹱�Z�`\�ɔS����U�P�/�g%��Py�t-��\� �)��,�����T��yG]�)T�'��^�0���X�JŇuKa�<`��D�0 _�e0��NR.��H=���)dbD&�d"lw[}L������ů���0����,�-�>�WME��E��� t�D��+Y�#�ə�?�N�k� �z�=�k�1T҃t�r�ε�-��Wv 8dū�F��'s��)� C�w� �[�z�r>���Sc���=�)��� �Юj��,y"_�{lN��_dD2�o���5A1|Y ����7B���j�����U��8!����"�����@���!n�� /ʈ ��E�S<}-��0S�kP��?Ҭ�e��� ���}��x:�W0_E�>���9�P�p��}�w��l*:P��g8+�S�{���&73b�*���W�ؑ�4T'j��4 �y� #E*Zn�b�V45�¸�W����Yw]Az$�)ᩓB��i��'����;i���8� ź�>�gz�/��x��W����+�;Ϡ�>�c�gj���3N�|���߰UAԸ��%bh�l��K�[�z$��RӶ�=�-�<�9Ai�-(�L8�^jXɥ�� zsk#䊦�Q�JuL~����N�d�u �l.�lHnxQ�ݖ��%�5n5h�A��^�f��ղ���e�� � ;���R�濽~ �^袈�_P�~HKQ&uhj4�[�-ո�g�Y}��� �P��a���I�+u�����KQ3�P�+"�e8�� Uだ�bQ����q�N���4��tQ����f�j�+����c�h��#=�.�j�e��V����G�$+s[ endstream endobj 1798 0 obj << /Length 2426 /Filter /FlateDecode >> stream xڵX[s۸~ϯ�[�� ą�%ovg��mj;ӝfw2I�)R�Kmg��{��ȍf� �C|����bDGo_P�<�{^Dl�#�� ��GŔ���l�)87��T�Z��c������w������d1�q.M� L�n�s�~ۑ}��D��_*�4X�'BD����'Q$�t���Y7�Б��Q�=}�A"�D&�S�ݬ ˶]� Ç��;��V��Ex�3��$�Y����J5��W�n=�7�S����'��)�d��'<�$�F��.�|�.���;"IipgV�-K�p�R���JkX>YpS�m�����̔ ;�����+U�V$ �UcJ����%�Dp3ϝ�OX���K�g<�X׿а��B��'A;f�B�o�8�(#"K�ɤ����vn���9�@6&��(R� 4�=R��҂mA;�E��8�=u/Gq�D���+��U�0�K�8��V�(�O\5�*@�����jt m��'V��u��u(�ȫ�Z�fj �z�Q�P��خ�T��S�5�R�� ����ϭ�N�]z��6m�� ���U������yU��*�>� �O��\���u����Rj� Y�w;�i]��k��*ڽ����XU�k�Ϻ�f�.�ʫ �S�� vH�M�\�v�M ��s�b�[�&c�I��Gl�ӈD�-�^�m����s�=;��������+��>h� :~}+F<��eS��L��u��YZ-@dV�y�x���y�w��'��M�6�3}���/qs�]�ΐe�:sl_�i\�yR�,�J���?���j6:TӼ�E5 W���Y��4��%vԞ��,�p�5k®.��l�� x&~���e2�2�b�ۺ��{�qpm�mh�%i��:�BY��qp��f���2�m��F�Ԯ����c)��CϺP-ȭ�"R��y����H6����f� ��L8��L�]�oI�!�M^W��[5 .!�]�9�MH �)��9�Q<`_r�#Դ��w�+� 0߮4�f]W�U8���-�/�cA_��+4�L#�vU3�4%�9�.����`�>֜���2 ^Z���4 �9N��{��Kt��&@d�f�u�qSk=3M[�iתi�������&U~���� �7���ݹߖ��=N�hFR���t���ֵ)�t�3m��r�Ϫ�t�4��ώ� N�Y�.�]�O�f)������ �I H\O����H�=����OOBD�����{F${Lh� =��$4��PchE��U �E�m�7* ��ٞ��_~��|�ٞ�z6?��%#T>�:�H(�/w�,G�a�[����om�)�WZe��a��U�p��@!!��l]5���Y�ϵ���mpE΄�]k �ce�A�t�xWs/����`P��b�Z��!U�qG�cA�X����u���,���돡�� ���V��a[W�CA;y3e˲NP�Q��H&@/��M�Q�����=��po���6X!�4�J�B������"�"��5lBš�<�=�X,WJ�Nz� �'k��'��0>@PS��&]��8`����9"烌��s ��to�f��s�2� ���|�-��+!�]�j[e��:@2:�$�S�b�@"��,�J�P�d�h �� �f���+b�~����^��Ж��6:L�@�������z~�&�߃hqQ�A�t+`���!��~?^R?ɏ�͏�tx�\ja&�o�栔��� 1�R=�b;��ׯ���¹<%�D�0� i*�e&���L�ȼ�{�_��� endstream endobj 1900 0 obj << /Length 1241 /Filter /FlateDecode >> stream xڵZM{�6��WpĻ �����`+�H"�4Oo����;��_�MU+�Ďc�3���$q�3���C|�X��oM�i��u�?�M��e'y�~!����/~SO�}k�8�D�U����m��r����D��M�h�����4�[��5yQr .2��e�(�,�2TՎt�v@^^E��GN ��z-e��%m�zw1!�o����դ� H!4Wۡ���|��$����oU[HI�M��3�9>�$�+5Fq���!�=꽇O3�W�����$ɖq�h�#��s ,�¤8��g�W�:R{Au�۪�W'��B���r��t��D�T9&�\�������� �yU���^ �� t%F�W��p���s,s2�-B�� �^�D\����P�f`���3@�H�^��� '9�@�iU�f��s��5�o �|j�,�$ ْiq�ǹ�9����Ng���[���k���O��R�$v�?��ԧ�P�j "�|B9�K⸩��s�H6�m���G3:���~�U�� ���HBVt8"L��9ٶ|K� ���sg�)�)׺�A�e��� M���$z�K훌b��Ǝ#�����S�Ax�2� T ��@!�3iD�d�m+dр�n1��r�>�9�6��y�FP:#��uޫT�s�f^��B�{����a�����0,�Z�K��3���5����J/і�� ͣ�g�\W��>Pt�D������_'�A����'�$J�n�5�O�nin�����G?�<��\Ό Ƿ8j+(���}O�������x�;�^`@{LJ=�΂�d�w���+�����D��\�y�<��m�J�� �Ѹ�oN�P���{ endstream endobj 1728 0 obj << /Type /ObjStm /N 100 /First 966 /Length 2484 /Filter /FlateDecode >> stream x��ZKoG��W�19��υ��W/v��v'�aPñL��(�al簿}�j�������Ads����z�L�Vha�u���"[���Q��i��ո�t���i��vrVxK4(�a�EЄ���2-\1%Z�R6E�M��" 8)���'�)��д�.౷q�V�iR]��n����$[���uPW� ��UIiG_E ��G�=�UX��B�6`��9��&U�D�G�fCt�9�Z"@s�X*�$%�#�i �f E��T�łUU\�Xe���V=''������t��}ex>�1@%6X�K� �P����P���ʖ,V�x��Hp� ���cs��p^�9����R=Y�R@�!���t- �6w����}���N<�q_*E�`\��q�tU�A;�V���ŊPt"�(�FWʼnh����Wk1�q̖x)E�+��H���trGg��!#s+@�8ɔ��p��=�nP- +3#Ӈ�jQ��D������9�}���a� N1�I�|�U��%�%�B��hY� ���Lڄmi��#� �C���S���ɑz(��5 ���P�~�48�"-(������w��L�,8���Ї��F� =��Oh�4�콄�� s���[��D�S8�-v��)����ӧ�o��@?��i�5O�A<꧇�B=m� b ���e����H��v9��솞?R�۾[�����z��t6��{'�k\�8� l4Y�iČ\7�H4�� ސ�u����b���' Vx�~Bc� �4 m:��J��S�"��4F�iG�Zj�6�4܆͏Us���~*�ׇ����?$��I�z('���!g��::�̽�G��>�0��3��#vv�p���f�b�O��.]��q L#� ����E<8\��a��d>��0ƃCiͻ�.�h�~"鈭Q�J*���0���v ��q�ԶdI��~d0y?��If7�GJ�p���H���/���F�Xf��[&��g-�C��Z�.!B��n?a@��F�]B�x*_�z���Q�!Q��A�)��rˠ�,�Оo:�6�#^=�lu��+_孻�|�Z�:za��0���D� P;�L��@��E�Z�[�~��/� 6R�~��.� �@o�`�^T!��� �f%�xH���|*'�\_����ԦY�ġ�^���:���m�.Q��O����3�d�^7�5@��&_�iyo�FP]��� F_� .�)�eq��N?ʘId�.�:€rҔ<��!�^;/�%�����N�k߻��"GI�R�9������c��v��Ch#���B�}��[�~F��.ͧ�(����^Bԑewb��E�4\�;��R��_p��q�V��d��yw���x_ͳxdfxRfx@fx.f/> stream x��Z�r�6��+x�� �EKn\�l� жƕC�&���xRI���D�$Lȓ��V�z��h�~ �u�:�����ݧ�_:��r���t�����A�/���^ƿ��O�綞 ������~l�g���A��#o.��맒�����_����?���W���� ������;�v4�N�a��,a����#�sl�&@P�iD��h��G3j@��]��D�Jq �@�*�{�QB"΁�d�Z�������ͳ����ka��_���9������X��rj'L�?�b����ѽ��~P�,�r��X�Cm�9��.��L6�RT(��� u�ڰJ�F�Q�1 YQ�֭�`#/u�R*�"g�v�.#Y�k���mu� p��us1�m�c�������3.PRwDi� ��eX�o�Lj�h� UĈ �hb �����������߾��gɷ�?�u���x�ǀ�c.`y!��ZD8C�6�=`��7r����H���*,v�`�Y����HrQW_�؜]��Pj�,o{�Ϻ&��:EMo���F�ɳ�ܥ��;z2T��+�����Ҧm���Qj"/=Il�UG��I$���L�2s�U�R�v��dNϴ2 : �4��[��!�'-�I�s��]�L�a��e���,�?m���r� �˩���]̹28">��L���wf�?�y�a4C��Z�7q�,M�6�c��ʺh8����S���֐X��l�w�9=o2_4���U�`��uF۠��B���S�!.���:�O:�Z ^���pV�gQ��n�[��e �yhcP��U��:��Ho�~�uE��p�H> stream xڽ[M�]��ϯ�e���]�� ���@��"��B��`bf�hο�9u�Y�� F�3��t���8U]�Ϊ��:kKU� K�=�\�d2�����b�� )i�qQS-Ƈ���`8 x��9�cӟ�~l 71n�]�䯲�T�`Z��Ek���$V��Ȑ��ڒ�ѹ���=�P�Б���ΤZ����)ߧ��6���u�5I���GS*����Z-���&���Դs�6R����L�+ߨ��F�sVR��W5Yq�ᵬ�aS���V)f�on=Y�� ����lwÑ�2�[/�K%J� �.�����z������Z�h}��Q*��H�6Ǜi����[�TP�0��i�+Ic��=��u���?Q�� �� '���HМ���)�X ��'fI�aU�\����WU��T��(^z6 ��H���;%�!��() n-�O��G�)��|��J�.��d��4?��O՗x�BK��g]�k`a�J�I�Sx�q� R��)�(�}�J3G�?b�[T� ���u MK~l��ݢ���B�G+�[z���q��S��Ē^���>�?ܼxqsy��_n��ۻ��Ǜ˛��z������n.��?�x�� 2���?_�r��]�_n.?�~|L��j��f��\�+MRjF��sߦ/��M�����}��L��ÿo�(L�|s��N�cs����H0$�{��8�M"��a(m���"��F�1�13D�6ZF�H�i�d&�I23�aO2�PZɅ�O�ڤ1��� S� ��1׼lnBq���3�N���~"��; d6d��;��� �B�j����L���;�i�� �HU��gi��Ԋdd5�F�w� ��ZO�À%@�����d���\�z�=��aI�ǐ22:xT˂E��_6Y�TX6�8P�� 9��P����zHT�e�{� �D�F�:�͹��3��(ޘ�S2 �T˵B�5��LM�� ��u�L�@���.�YH��D��]�t��(�\��SO�1w�R�<��� tS�MZ�HY���#`9�i.��ܣ�:@��h�տH��h�3��:� Y:?~I�m����!m!S��Ԟ�i|8�ݤ�':'mdV�A�P(�[nJ[2+��\-j�4�T5�_������ZA&Q��Mv0�2!�����Mg�MB�غ}+k��fe�S�.�<�5��ex��!+�2��e+H�h���&9�C&�ͱv)1�za7�à�!��ܓ����^5b��Z/xU٤���{�6��OE�^�P�>��lgj�0y}A�ī�Ia�B6�v���Y�: fY5�W�qb�eZ�1�{}\�U�F!��#l���� ���8�}�f�\��k��G��O�E� O��:�&��x�ˠi 戼�KX�(:�nbZ���f�7�b(:���TF�P���lijB�v�&P��Ymʐ5��(*q��6{Û�V�HEگ���پ��Gv�O�/z�j��0@�g&Pn޼cݠ�k�h�]5W3�rt����%���M�����.xȀg��e?�Z�m'^�)c#2��q���l r��+�S�o�{�* ���kb���3�@�F�f�Z=F���i�mW��:�sS<�zP/���g�~Zdž����ֱ/��]������`Ú)\�+ �;�v�����X��N�Nh��YW/NS�#oH���)JN+�K���f5�N�C��|�׮�Nu �x��jA����^:;��"ę,^裝���A!˜ml�~驡re�x���EU��UQ��]b s"��b�(��F�@&�ojG0$,�V1>�.O��t����#��� d���l������SR��Ʊ�M�J���<����M�,�7߭��I�������g�+q�����?���^��=:�+�}�<�~%�M�ILy|���"~Z�XX,z,�<¡����z��.5D endstream endobj 2123 0 obj << /Length 1318 /Filter /FlateDecode >> stream xڵZ�r�8��+�����`��؍Qb˾�������ܚ�Tݙ����aC�X,B��s�V?N�𜟎��O��mx��]GA�?��笼��KG��|����w��m� מ�E��П�,���ؓ�ក�� $X�7C�5� �̃x� R$�&��YB ڈ� ��9�/t~�t�/y��|�0 g�w�,�����J�ԐҤ�?����L� ww{�f��� Z1�)��E �W����a �<g��P����f��,\\5Ж@2�!W��:�FGX�FDB�8j� K���H����n,���9���?{Տ I���8b_wE!0)��.A�*e�r#ͯ�Qz�e�7�����-�I6���Y�hQ���#�kP��lCcA�"��TR4�H6T�rat���)Ӊ�ݺY�XX�K�����}#e�"G���vX�����\߹�q&*눊�7g<#��A&� ��N�Ƈ����MD��c6�a�c6�����-�_���[&�P�l���so���O� =�����)����x�K2�]/#Cv�r�Э+�6�Rm�ݾV��eG�q�:�P6穅��EsLj��V�pe�-A�Z \�T" ��d;����8�X�z—ee ����0�B�uU1��Z��zqh7�/�ܡA�� �x�6��c�� ��ķ�ʭ=ݢ�[�U����&���%���� �OF�2����G�I�qRWT�R�ƞ�L��K����=-�MGEY�jy ��Z�"�t�[ Ef��0���=��!k�٬?ҲU�w��������}' C7 ;TJ��0\�?���6�j�*�.iv�t�{cj��uyũ;N�CD��0��:'�֫�Z�����$/ Pe��ޖ�eR��D==PM���_������� �ry���j��f����T�B #��Sd�{�ʴ�@�J����0}��Oe�0�6�-q�ڋN� ʀ��؃5�9��z5:z�3��n��Gf�\��S��8����Q�mD����|� �n�d�B� Q��w����W雽���3ߋ�E�t�����e��)Z��Զ�i�4w>�/vR'e�F!A�y�d�em��Dc�� 88t�l 6I��*1�N�AV��`:�p��Im���P�_�������튴J�;T����5�^��K�7fc��͠�]' �&0��B�|�bk��z�� �\��akwq�p�L�=d�;��q��> stream xڽ[ˊ]���W�0��[�U�BI ai�Dh��M01�Fp�>k�����9��8w�:��{ו)Qj�)���hk\�bsr1K�b���\H�sp�e�p�������n�£�DP�yK�^$fb��]��Fƿ&Q�¯M�|��&w3/j��l���h�+��b�W��x�6��k1�r)�AV��b��[�.Dq/6|bbp_o�E�������Q�z�f�d�xs2)�;��F>+� BQ�{�xH��#2�d���F/�L���k��,�q7,f#J���̕��)SE��w���S���5���z�7zic�i[pl�%�\�GD����)^�GJ�[�m����>�c����jeԑ��2To�a�x� O��ZF�9>��|s|m�N��ʬBh|��ѹ�nڅ�f��ri\BR�'pP���ٳ����r[.����������O���?��������o?��� ��受?]�#�������O�4?�D�G�QKo ���#��ܷ�ٳryU.�}_.���~y��ۣ���7�����OBu j�а�.G�qD��&�DG��|!�h͞&�ډ$�६�����Î0�jG��I��Np����I�* �cPݎ �PkǠ$���.����� 5�&q�$j�:��`PQ�^��xףM�$��|%aN�i� ���~�t���Yp��*��.�;<� nq�I�J"�08H�qTg�d�"p���]:��ap�_H� R�i� X$����T͏���-t�J c<�d��!Ldk;2a� �NC�о�PK�|�ę�!�>��M��<�E�>�&pQpOH��̒ɉ$*|y�]jI@��ǁRIa"HzQ�LJ����B@IF��p�Ỳ>��J�����X�o�&�l�Q( �R���~ ����L����J��Pl?I����8s= }�rCL�r���0:&(��Ñe�S1Y� ��6 ;��Z�2�TLIoi�D�dS�# AED�c� ��!���v�� ��a,<�F I��&A��L*�&�;8��v��<*>���J��398��@pۖ��ɚ�Dco`O[�#�ȫ �7�º#Poն�<��1��R#���R��&��e�� ��Q�[V�7q0��J.��q�#�x���G s�� G�ePOG�1`��&P}� �:���\�9lD8�A�U}S&���@��� ��p|W�ϰ�{ZȦ7�F���x��I/� ��O�+3Lϑ0��]ٌg�3GeZ�"��D���i�J{�̤�����W���1��T�:/�P+�P ��;�9�V�: ���pا�Ԝ@�r�pU���NN�誑YU��Ά��&ȜDt�ڜ�2�'Gmgzl��-��i��F�g��j��s���S.��PNJX��K%x�+�\ʫ�y�  ��� ��D"2Z;t����˯z�5�<3lD��G�6��C���"� H������c�8�1������n{�#���A�TK���٦�kjy� ؘ��|�w9g�C/�� �M&�(=\b�����3�Eə�os9B�N����mU㭘�%�YlY��.G ��e�%$3�#�� ��p�{@lS�@���8�����`9�Q���Q'n��u����u3��#�R`Y6Q����4�?ȚOA�9w���I��t�@��tޓϜ[v��k�E8��,��t�M ����ѼZ��k��to ]^���T��� �Ï�t_��^Ϭ6z���V2�p�s����gR�a��Eg�r���!� ��,ߦ���oy�Ӳ�𼍜��.�l�#�TZKO=̶�g���d�R-?��_������U���~�zq�)�^p��H�O��ʟd�}�W��������������w���ZR � �\���w�mƇ�S��1^�c-��B�Z�Z��Xp�kk�֢��Bօl ��-d[ȶ�m!�B��l ��/d_Ⱦ�}!�B��� ��/d_ȱ�c!�B�� 9r,�Xȱ�c!���r[�m!���r[�m!���r_�}!���r_�}!���r_�}!��<�X�c!��<�X�c!��<�\�s!υ<�\�s!υ<�\��Yj] Y ] [ _�X��}-�Z,dYȲ��Y�,dYȲ�e!�B~�����r(B endstream endobj 2125 0 obj << /Type /ObjStm /N 100 /First 1014 /Length 2554 /Filter /FlateDecode >> stream xڽ�K�]I ���W�&���vUIQK H�Ĉ�Y��!��� �=�� a�� ��)u���ǵl/{Uzm���k[����.=�E�e�E+>�L�%�k1�ܦ����/���*Jk�������y�y~r���Y��6�>;Zi�����%+dJk2c�O�|������ o�=������\Za�nz�� մ��2��s�8F�s6�0�� ����1���EkL�`s�ϭb��>�ź �n#d��b^�_Ղ��j����[[�Ƚ��*��h��xO��*n=߼���Ҩ�c�}�Y�.K9߮O�(Q���F�ӧ�%��g����Q�o�3���J��gM��Vf3�Kf��cr�V�f~�>�9/3f>e���d�x*G��zV�,N���Fzm��,���ˊ����第����w>e�!_� �ҧk�=ҧk����]ˎ�U8l?a�{�;}�8��T~�@�v�B��:X��@A���+��x#� �1K���ƯBK0�[K@܀����߆%�5���N�!���`� ��z�M˗�[B�%�����v룹���MA�N,]Q�N,g�ƍ�������CT<��jo�޽=��������>~z{|���|ʟ����|{���O{����P�������_�������S���} _1��d�h�&0]�}[޽+������X�)����E�e��7��`����Y�c� 6's����~Ȉ�2PX��pg�"�|\@��&L����:�Q/�X!�\�5��1�F#v�:�>�ˆ̑W#��o�8dg�-k�ZU�&$ڼ�+P�i�� ��o㽀��&�#���z5R�#(��"�`���*�]J�>A%%{0�,P9��F�u�� j(�'I [%7@�<���E1��I��;h��;� ?�c����0�FΆ�a��v�lN<�r@$u ������0�Ψ���A5������&���(q9۠R��$A��J;�(U9�ζ����s’l�K{��;=������2Iu����v�0T�/XP���f\"�6��3F��ӂ�<`D69�m,G?�2N��\Mc�� jA�v��s��.Z�9I���$�x�5ʗ�7��i���0����R���J���^@�e:�Jh@����h�F�CF@*�elB#Q��*1��h��ujc�i ��2��*]��F5��Pg�H�2�Ȩ�*Wg�5*��t��>&ٵ_�:�r��6 PI�nV�.��Ï��_FS�����a:��S�j�����䨩��1F�S��M)�[yJS%n �^��bu�9�T:�5P�J� �q�O�����9��#�z����*�3�<5�Q�5������FƸr��ǕCB�������g��F� k�{]��T���v讶D%9��Uf?刦��)��#p�RHT��'�� JQ;�!���nU�b�� &F�TU� -e�,��Oyj�kq�X{<�>��˾����R��Rx(�M8Ŷp?3�PP�֓U��S���n)q*Q���r-�-���hD?t_HOAcI^#>}?�8��YW�O*�a �� ��>�����"~�{*]�C��N�@$x�b,\RQI ��i^��&��[u>%��C������ԭF����ƺ ��T�,�j~����r�i_�8��eދ���W�q��{> stream xڽZ�R�H��:�Snmގ����kQ�J������}��0��`AcU�r@8�2�^."�~EI�{ت�M��6��2[F��h�D�d=O�E���^���2�[=�h���"��I��(������p#r�=�V�orw�cEK)II)i�����i��lW �r�$r_y�߯��c��_I���z3�K"�f�t���}9[��t�u{�q���W�K��J�^'hZ�5�-T�sD�����j/��$^2*����:��m?�x >O)&�dk�ȍ�# �9��K� � �J�t>x����k�������؅���ݠ�N(6����f�/|iͯ��o�H�: ��5|�<���h+Q��k@�`�Aϟ�c�ʶ"�p�/yM����C/̷�c@��ϓ����l��JA�/�ɰ�mu/ty���`1mHp@BA�Ū��m嫸.2'���s��� ���}��.i�Qd� ��>,���e@Н������!_\�G��x{�`��;���) �I�M'o*��>,=�t�h���jNBKA��O@�R;��r���kc:[���V���h��Y$�MW5L+���[�i��U)!`�b ��}�FY���4Z��|����l[�d)q���W�Ϗ��7�7`+�b���?2�S�ЋOВ E�&�.�[xj;t�h1�b&�t�~�~�KC�=�����3f]扝xʚT�u-ՓD3�*p��k#�� ��k�������*�'v�.�{#.�y�a�ȁ[O=s�)�����,�y�������H7�T�����J+r��\}�!�8�ڼ�@6�妪��K���e�[>�f<�2/��1Щd� č�����^j =��.0p���v���5h=�v��l����<�����WM��>4�(@ _a��� U�|�[��S�ϻ������P����f �i��)��=�W�2���;8I�z��כ>E��R&��ߛ�ߣ��O`����0�) ��`��buI�G�����~��z�Jf9 endstream endobj 2126 0 obj << /Type /ObjStm /N 100 /First 1023 /Length 2945 /Filter /FlateDecode >> stream xڽ[M�����_�e�ё�K�@�ЂI�hk�p�K �����>��@=�� 0�9��y4����GiEz��+ �"�I�ϚED�h�Y��M�_+��~j�>���4>'xn�y'����)��))�c��ϼ-R\Ԅ��Ij5���h���,��~n�fX�ZQS�Y/��_JG㺦E'��EWټX[�QL6�6��s l�l��V���5��]z/6'w�R�u����ʊ���ŭ������G{����,�˹F�mr �?𗔔P��%lr��ѹ6È��9�s�`���Y� j��b��ʰ-������ ���2f��8��{��T���px�f����L�\c�2�P~P�9����\{����{o��d� �b��]��s���{��@�6�*ku�8������ �H�[ݖ�4�4����Ap��hD]rn��&t�ׇ�C]�����ƝH�jPG�t�CI��cQ�X �q�X ��X O-�Xm�&H�&���XML6.V�t�&��,����aT ��YX � )���j����j -%��4hʲ-gN���i={vwy�ߟ������>�]����O��_|����7~����E�7�?_�r��u��.�ݿ�T^��Av��0�ڰ�� ��C_�g����r��ë�ry^�����W�,_}u�7��f ��V��V�r��{Yx^^C��������'�6����?��&z����{A�^OO��+����������{0V./��(�W��|*o~�ח����-����H�=�����w��;{��o�?�����_ʖ�67��������?b������O�Hb&��h>�= IB��$<�H"�5�5�-�-�-�-�-�-�-�-�-�-�=�=�=�=�=�=�=�=�=�=�#�#�#�#�#�#�#�#�#�#�G"�D�<y$�H��#�G"�D��<y&�L��3�g"�D��<y%�J��+�W"�D^��y%�zB�W}"z��&aIx��Hb&��=�{"�D���'rO��=�Ӛ$� _%�ȒȒȒȒ�i��6(i��6(i��d�on�%�W�c�QiE��* iCE>����\�s�PO�D��H���$�+��3�gXi8�RS&�J����� �*֪3AL��^U ^�hBȬ�T�{��B4� `��C��� s��P�S�X z�7�mg��.�_t���R���@X�ND08̺�A� 4��SKe53�>��B5|5��)A؂^b������djBENy�O���ʭ�*�#�EZ�PS?�Do80�Զ���� 9t�@umPGV��m�!~(l�����f@#��/8 � 9�-We�[TG҈|g�"�(ȵӐ[�.TY�����������t6A6�."G�ɯ1���bڨ�F��e8�c"��٠�X�9�9��*yUC}`1����H���!j"`�¨������)AH5$��Z�(��|����)A�: nڤ����i� �k�%ה|[�!�@�Tq.}A9� M�-N�^)�Wlt��!! 8.h:�7���LTѺ�ag�����M'v���k����)u��jd3J����(��ev� � �� 2vGP�T��^c�u�8Pw*u�)q`ݩ�L��C�X�B E��`�V�H)�~J'[�� T�L x��RfuzJ;[f����^f��vF�S��o����I��-��V���e�}xm�w3B8~�ξ�)���s�� :9GA���e_� vK��xñ`qE��Y /ij3L��`�':��s�58�@51ƹ -�O����8�dc��q`��U$P��A{� M�S:�`^X/�n�'�f���!�X�Xk�!e�Zc_��F4dps���v Q��ɾ�&��� ��M�:b/�;���0A�di�V��F�K(����#�nH���\���cr�l��XdQ{f]e7F����p� Q�m� a� *x�rN�Н��C�@.%��n��L��B?����-��d!��s /���8$^ �>$�lf!�@�Wk�[.�(�}Ɋ�up� ��8� D��<^`��f_�pK�-r�_�k����kcސ���P���`�B#���&g����^�abC ���k�9ܔ �F��W44g.c����|uM��� C>��ڵv�Ma� }�G�e�z+�u��R�6 o^y��Nc��r�S���C�k7���34qb�q�ίb_�C��#OdvHs���bgx\#JpA�vu���dR DmަtG�`�m����D)n�TAI5�����w5��8婐��S�jUe�!��'�m�bpԙXxO9Ѱ���r] ��K�������^�#���At?��$�$�> stream xڽZMw�8��W��s&�|�ᢩ!�I�ڞ�͙w?�1 �Ek���]T����~ߋ������F>�*�I�4bG�뤞���[E���y_���o��� ��Ma�^�(��L 8�۞��������0�Ve{@����_��9�_�������'��a��+2������h����Ar4������� �#%p�� ]\ĮQ5( Q) pc 7�x�aS�$\�|���Yq��d��>�Ѭ2QN�� p��Dž��Ţ�� ��e�,��ri�@�X�ʆ�3j8���s�ג���Z3"X���j&�K�\b�ºnD 9V�ov��r3!�mw�T(.}�_���@��ѭ����S��L�[*ߔj:� �����M�U�3�� t2��:d�_���01p�j���TE�`�z�a�^Uzb&�9��d�jc�Sm��P&iC�"[b ����)Q��� �2 �1ݢ<�q�YZ1����`: 4��$��,������8�J"�Z/O&�L:*�,��]A�,��E�j(>;�WA]`jT��BXC? �H$N��S�Xi/\n���[�{_ �9�Q�SUe�0y���%x���C�5�f�X�ӣАY+{c�o�p.� nY�]fQ'<������{�@�t�k,��f�� {����˼#�a˟����1N����bt�d��CA����� ε ~�����{��� ���c� endstream endobj 2239 0 obj << /Type /ObjStm /N 100 /First 1020 /Length 2913 /Filter /FlateDecode >> stream xڽ[M�d�ݿ_�e�Q�T*����0I ���E�a��#����|���s���� �7��a�Ϸ��JU�>��ZRI�VI��EM�w.4�t.Z2.,�޸�i���H�N.��=�$�%H�IkW�� �N����*�m��/Y��cr�6�2u�yj��LM&峒�V���֌(��= x�=��涞�Ԧ��z2�����Cc�-��� �zI֍��l8��k�){tM�4�@�]�(�V! �[��}��/s�Y��Խo����sCҐ·5 ( { MC�- +� G��+�6�X(�[�'/���L����Kr-� Bb[>�5�u�x-e=ג��(��s���4˲)��(������f[�1K���S����?�p�Sake��V�,���PN,aF��B��k��e��o s����H�l�>�-R�-0S�'���fL��I��`7�T�BS"P,��M��g�[-e�b�* [�::,���`�T`e � v�q '/x��]�M0�n�r�a7���u�޺p��6�V^@�Fu]o���Ma�wϞ�]����������ǻ˫O���>������]�z|���������ϗ�\�~-�����w�k�-7�E���:�g�:���}��=K�W���o��y�Ïo�}���1}�����B4�y��kVh��dX�jf��Bt9O��\`|����9������R��N�z��4w:W+Y���j' QKvZf0�F���X&��41�BLb�Kˍ�[�w޷���M��� R4�w7�\�f�I�#"O� ����}�(��yp5ƙW�3|������c\q W�MZ(3� �D�h'�9(��QB��!΅q�)N��� �a� !����� v�I�V�U�~S����NHԠ�����<�?4�.��?A.�p$=|��7�ЋLJ� �"�b��� rK�C~�����߽��`�����t������ͯ��%$��| ����HR��W��������7���o��}���ǟ��BG(�/���{|��֯. ~�Ƌ�R��to �E���ϴXX,z,F,<�@�@�@�@�@�@�@�@�@�@���r��=�{ �@��y���#�G �@�<y�dddddddddd��3�g �@��<y� ���L�z[H,j,4-�� �E K K K K K K K K K K �@��\�r ��5�k �@���������I5�5�5�5�5�5��j�A���7�x@qa(Yp?A�A���9��M � �<�e���I�l����=d����4��Y@T � ���l��z.+�d H�� ����{�t�f����� ���`n�uS�"�7�q ��-dB�*��t�3�3ȅE�^2 $~����DM��$ a���fp*c��L�� ��������`*��y��B�� X�]��ѐ��. <~�]� ��<��'�>���@��!u?�rPd�-O�ޤ� �0�q�œ)�\f87�ӳ�D�����D@�:� �l���pA�$w��j���aϓ�`�l��&�2wi�Ә ��U|̬�[�y��x(I�q* �f��4.�n�pT$��@�$Y톍N�|\��m�S]Ȋ�+��=�\5�^v�)xj״��`<��ۏ5qf�b�6�x�V V�X�~� �5A���DZ� �ɖKm�k�qȵ�� ���4��Qv{*���c�3���ܐ����U6�2֫fGv�ϴKP*��:��H.Knl���g���qC%!��c�,{�3�yI6�:�ˉS�D��اC&���.E�;E4��هZ�!m▵�̲ri�8�l�!�I ����&������lO�aH����a�M2��V�lK��آVx�CE�y�i��)x]� ����!~j�L!���,���ϒd��T�Fd�H/�ī���N��j��N/j��%����0��*�6� ��n�a�xȿV&���kZ�� N������2�qd 1l� E����U�*�̿��T���/F�0���tXV��4x'��KWE� [�����>�`��� X&L��\Ǯ >����_I0;Z�N���sA+(�l���2yJ��άAv� uV��}i���uO�T��p&�0h�?-é����֩c�:�kN�(��Q)�lnY8~$�j #�K��8b���`�����k�]״���vf� �#F`R�c�6��Y��"8���p���,98jV��Mׂ۽��t�A���3 RW��G6��e7\��ϥRWz"���S"�z%@Z�3�=��W���]�xm������ԸÙJP�9���o�(��}��x�MX�[ñ&�q�u5�ܥ��K����qqj�:�G6y� ����#ay<կ ǣ �Se@&�^xǩ�Ωi�R�f_������}�Y�@�j���G�H�*��Xî���� {}��%�s�V����j���]F �To�>�V(}�k�on:��Ƅ���#V��w��2 �B�h́����L�f�,�!�e�U9G�����v�n�>�W����������r���-�Ƙ��7�j���"Ŝ ��gpأ⮌k�on;��uCb1�����8��7�ZE��5�q�<��l�n�}�c��e���(k���M]E���7�l���$d5��=B4�&�7ӋiW�}5��n: ��U�t#��l�?��ץ��7��e�N6�ySK:�4�����T�}UłS��v4����=�܍|&�f4d�׶[?��۹��7p�ܮ�����]{�USN�������nv4�uf7�1{0J���ť�P��n��3͡��( �k @W� Lb��d��?�c���o�A6�I��Y��b�)� endstream endobj 2458 0 obj << /Length 1199 /Filter /FlateDecode >> stream xڽZMs�8��Wp��F6���Ta�!�B$�I�mk������f<%��9�\��{����}��{LJ�|x,��K7iƞ��K}o�'���?����[��Ϗe�_<� ���J�X��g��C��(ܫ���S �(�YӠ��m��\'�*['ە$�}1�3?���O��W���QmWqr��{(6�n7&* �(�� Tk���t �i�3o��,�����9.0�1���0=S4����?���P�jN���x��¸��u��:JŽ�zT��0E{k\˖��فbDXc %�ߘ�(�$���q0J �L�L��ԧ��u�*���=I"�[O\ ��L��>g����J� �oeh�S&�����(�����9�v#GD���N�v;�Hg��Z�Z $wͲ�8��wA �g3����o�ѩ�RoH�>��K�k��u�r���2Շ傰�s��CHU��g���L��o��N'xh)tu��,�Ğe���y�q�� �_�QG��~�qjZ�P0|������/ � ��5o�R|�T�nu&8���a�� �a�J�U���k��Y`'(p�p�FU����� ���� �2��sw��F�_�:����8X�{��,,{�>{V���\�Z7t�% ,��t-ZNNo�Hx��e]����&�|�� ���E����QK���@�7��T}�(ʊB� I��x�^s�ڒN3��X�~�~�ǯ^ěmxqm�p;p��=Ő�0ug��F�)yF�T�����W'�C�&���G��53J���qN�T�4!H�Ir\m�2$���.� � "�h���aA�)���� �,�~����� ��f�����p�ӹ�Y�ac��X��0 � qY*B=���hJ(ئE����fl��B��g-�֘����1Бɴ� ����������ēZ�6� �ݣU�� $�h /����+ò��A �SЕ> stream xڽ[M�]�����2��J��f`f��@fƋ$� �ӄ!C�`�a��s�^WO��{r#0Xݾ��n�>N��Z�����%��EK� Ouv.zju=3��zf�> �z�9,$Ii�+M"So���\���jK��zΓt�z���s#��9<"2�2��7� b��`�#���(wǏk�n��j�Cֻ��i���de��$ӵ���#V5��ʕ%siأ�d�(U�d��7��"덑��zc����zI� �uI�Q� �5���kj��-�i�h�K�ܓk�nޓ�ϯ�[�>q�����W��%�p�uM�J���T�Ю����:)��m�v��:n|V�s��t룲Gq�6$A��jhu��4̹ǰ4��P�躞�4���zsr�1�X� L]1aBuYĔ�#�sxxz�s�����������R7�0�"�Z�pR�:l|�[�υ]Bz�R��\�Z��%̵L�� �U�8�0X��7Xb7�f��n�� ,��x���$E:Fy�}l�&�M O�`&�B5v��-��)_���3&�M}r �n:�[v�[ ��2���L�[�b�ݪQ�] �`J_�T�-O�ܼxqsz�ϟo��뻻���������~��w��9}s��ۏo �Cyw����o�������퇇�֚�I���CE�yX��V&�:�x�Nߧ����ܧ��������6��6}�� ���2��sa�%w�L��'�pH�Y�,D��@�Ɍh�� �!+�G��}Y��d�a�28�����di*_b聊�#�J �X㾢2L¾,�.$� �E��Ǣ�b�"�%�%�%�%�%�%�%�%�%�%�5�5�5�5�5�5�5�5�5�5�k �@��\�r ��5�k �@�@�@�@��p+P�X���r���Z���ڣ�;&6��q|�#L ��XU��|tиM9B��L�2&�,�(����g��B&6C�V3#���+SUޛ�����dE�8�˦� �t�cO��F�%w����)�M-�A��X��*D1G�%��ɔ��ȹ�F0q!�k���6Bt���y) ��ȣ^@_6���d��4/�`�"iF��e���$�6� ��H�/ �����~�, "p����m��=��M`�PDEuŞj܆d��3#S�)�Z��uMX_���U�>7 ����`� \�� J �!�ȥ;�r��l*�d �U�1oB(Sۤ �P;�F4���?���=����Z��DG�d �1\��d�ml�z�r�Dm����: ���iށM�l[I/�;lݢ�=��d�h���M� ��a"��}�&*]�%��&��Nq8��+c��Z��P�da�ytJ?��H)��p[7�cɠ�͊�:f��!{ݞ�6�1d�j��&!��Ī���+b3xV^ �M��"��U���PlN�(F�=��Q z z�W�SAo+*�r���P�d\�M5ݒ�ၐ1�嫨w�rT��,���s %��d�~)���6� ����&���M��pP�� (oE�K�B������XPo(/��H�Ue�w�W��Y��;8���Y}�&�gz�����R� ��%��}u���b��A2��v��#mB�:�IE.e����(/��`!�����&=��J�A'��Z���|n��2b�BE�8�\�7��x2����{)t��^w)�&�r�ɑp �\�A�6ik`�����<�K���2 X��*��<�.Sy��}���I��Ϸ��_(����7Ls�"��,��}�,6j��X��Z��qi#����Dg�lkAY��PqT��KJrokA� D�� ��R)~������\Y�#dON+ 'g�.����OY���eɤ����R�H v�3�(��@59Q�c�D}{pH!�r��M��eW�29*�Yr� "�p�Q�e s�����(| �^�E8RVw��GǏ%g���;tj I��_;~T�&�;~�ȹ��GǏ�T����C�PV}���[3}�̵�ߑ���!J���� �j��HM�Rh�SǏUS����?��&"�Ӵ���M�cb�1��J{n�\�*r���n�fV��l�z��;�,�����C���';/���`���0��ʥ!_?t��3��K�� nR�3zm� 1xsm� 1y�>���;2J!2p�'~�h�V赆ߡ�PYM�h�YepxF�ώ�,%��~cF}F��P�D��>ƌb��~��B���(�<��w���=��~��Ť���|�#8��>��Wn����8�����l�=��SǏܦ�_��)D��~��x>�c����Y�1 endstream endobj 2509 0 obj << /Length 678 /Filter /FlateDecode >> stream xڽW�r�0��+t�U+G���a0J�p�Qǵ���}����*���(Vr�]���5�n ��F��.n���l�%QB�7�ٲt�����)[��ۛ*�&w�[�$��M\���ݶ`#�T�����b<<�����2J�V�g(i+ (+F�OL����_�_���ueg�����*�l^�5BCs�L�y� �0�;��� �6W���:p`M7�X#��+� ���x�U x4�:�q�����;��� �k����:׵t��ؼо���)�.5��y��(��.�w�f;�X�V\Z�UF�[I�\pi��b*�H{n��z> n�65:C¡�u���!���e]g�s�g�ڌ�����Noއ�`�E��fϋ�5n<��Q��,��3&HߘbμKz���i������Y�}� ֭�x�� ^�&3B+�K�7nm���7���T���D���̾����\p�cfL|��rN��'Z!r�����*�O, ��;��" ��v.���n(����;��e��)Y秲s\�����<�5GУ[�I��y�l \����z�o��i�J�=�D��^�F��>�Qc����=�8Ջ���lO8�)�qt�~�̷L��'�G�vTk�7��{#�����ؕ�CE�,�6`���zH�i�9�+�w�p����p��И� endstream endobj 2460 0 obj << /Type /ObjStm /N 100 /First 1016 /Length 3848 /Filter /FlateDecode >> stream x��\ˮ��߯�2�p�,��P � '��}1t I���9U�;=�5�AgoM�X�O��VzH��"!�Jb�"���:�� �f5���1�D �/4����Qm!�Y�@u�,� �[��F�}R�(F͐�sȖB��7�˙�7t)������[ �g� �I#�׆�_�@3?L!5�2C��I�U��\z��^B����dT �a ^��3 -%p�IA Dž�MǕڨ�'%4� uu{��Aϕ\��^�Z�f����]�x��?�}L�)t���A\ϣ��I� �gLA\ϣq= 2 �1F��E��i\f٬�)��)�4���9za?�}H�~-��֯� �����'���4�T��l�fP3JÐڕ�f��I��jV�dtjm�0s�60�Yh��u �1G�= 0�q�aL�IS�2|2��@�p7���Jw49�%A�WS�ΚF�s��ދ��$T���;�0(�=!@@��1��\N �e#I�ñsIÞ��K��Ѡ�\`]<-��c�S�)F�tB� �$1��HƙPq�0� #�#�s7�wH�&�{�����~��O_�|xsw����������N�=������ܐ^��|������>ܝ����Mx�����LZ���"�)�> O���W�������������}�����'w��Å�s�*�Y��qK3"��3�4����6�t��k�Fp֘�ET��EbQ��+2�k,p�*=�y�&r����Jl�-,%�"&k��� n k������-���cV9�-�9 ����"�T&l�a �5I�ca:��k�9�+�Œ>[�XBZ�Q��j걖�4�5 jG*��@�����=+r�A�@����g$h�Y�G劮9����O&��T=�&�LEf�9H��$a�L�@�2��j�x����-*���;�c�%D��S�D�_K��jX�c��$|�/9E�.$)�W�����w,�Ѐ���Ԁ�f� �� �>�P,H��fC����RD� �2C eU%N`^TF�y�&0sÈ5&.�2�*5�W����n� �|�b��J>Z��/�!���9!M�m,�(pah��8�Mh�����i�z�ǑUk�#�6��"2��� `��`=`5g=J����l�u��}��j=H *|3#5��/�u�Ȣ�������쎄t��V��r9J �y��;� �B�/���̀1{ HU��QE��P��tЀ^EP�r� j)�W�V�^J�Ex�1���p����X���˟��������7��)� �h��rC�?���٫�ᄎ�\��싧����/o‹˩>�w��������Θ|�3z�����_��=����?|���/�� ���8�g߾���U��)�5�]0�c�`�(Q7�m�cgو��s#m��yl���yl���yl���yl���Y7κq֍�n�u�g�8��Y7κq��q��q��q��q��8swky#�Fԍh�7�9����g�F�d�:��+�#�.(��Z�]nU�!b^Ę���T�|�4�ٷ��j�p}A*@Q Ȃ" � �\��DFi��DR3��@�$�iX��$�%��-i�X��$ ��bqJGi0���$�V�7 � K;JX '��55\B"R�$���Ć���� ��āT�gc��v� �sF�0��l;a�(R��1h)��P$�� �����*HeSH��'OЀlU �K�OaxT�1�W��� �[�0��*�J5S�Bd��S0T��8I.Q�*� M�j��~F�I�R��\��u%qS��N��n���0v�V��[�]�� 1�s#i|��Z� PL��0N��(V��q��8!��U��3��]!T��� �����v���Z����r�"f�D�Kzi0� ��04XTqW�!�y.��Vu�v�1���'y�\�f�)�m5�U�� z�=�-�Q9C�R�͝e���w�pS=d�`�nD��i� ���$J-l���Si�⦚��9w���W,��I@�� ���,��s�M��#/ݼS�[�a�u�X�{�:�e^Z�s�dYY����0�k��i�c��S���'�O ��U�s棰%���SbI�B�<��-��P9Qe����Xr��?�:��r eߴ�Y�gM��������|T��XxhZ��= ����T9F���b�!�d#�Iq2Hk��9sp����U3/5@�V�A�_�� �����X<ҡP<�=�/d��U�F�]b�*�[���A�u��d�0/�e��FluԾv��!�݅�3 /\Q��m�ॾ(�E!�9�"P�A�ɫ0�Y��+��ȃ��JTX��cnۗ�?�X?Z �Q�1�����;�\�yE�6���:$�9h�E�~��y�^h�(��<��M�u֜ ]���Y���\�����\kw�uq�u�\����I:�e9���Ȼ�@$�Ma˫Mv��~�m�r�� v7�z�U<�V��<��yS�㿃�� D�0p1���A��&��w 8�ۜc~k�<��|��a��v�@*�0y�]؃�F虣i����i����t9k�������vM��i�]�c����Ѩ����k�<���w�x�ʧ֯��P��0@�;N���_#�[h��=���|�Oܢ{���?���n��������S��[hy�N/Ư�G�-���"�@�k��G�4���߷��6�@u�5� oi�-<�*t�����І{�=ᥚ�m=������}�x�|�=�����e����[�Z�\p��v/��k2���j��O~ �mڞ�:�2u���{r� ��s��sa���$��,��a�X2d�GY�Z����^(�􅪌������=�� ��n�qӹ/��{��,I�G3�� 9��st���L����B��T�-x+/���쭍Y���[i�~�Z�c�հ�ˬ��u�������iOk}�}� {=Ɇ_����%�I�Ѳa��t��z��<�z���1�����\�svk�����1�����,������O跓[ V��M �b4H�+E����ЈɣY�P>�2z=7N���<癛��}vO��wY}r�~5�x�f��]�ꕯ9����_���ֹz��֟���!�bO ��&��XU�9ُ��)f��><-�f�.�˧ �:���egy���s4����\W�,k��G��?5�X�s���K��ɼ.g�J��5�%u���N�{�2e�6➃9���ߑ�m���J)��<�����p�V�ɲ�k�q"��0�J$��LԘL�z�?�f�qF�0�]�I5���9{�֎t�7�ѿ�U�5�6����Κ�toc��ڞ�-֛���G�B��d�f����io�ZJ�漶��m��V��a%Lk��O�h����ؾ� �� �u=�x�ҼF��N�{��]��G꺄��.�;�l<�X-?�\��n��ە?R7?�X�� ZƤ��Z<�B(��4�w`ޟV��E+�a���t�f���P�"��=�G`��6�3�ͬ^�N��3�ξ|zau�~�'n{ﱯ�x� �V�PϽ�;אӫ��,�����k�9�W_@'�3K��}*��m?����ϝ��>�s�.֘���A��5�S�1[���;��� ��3�e�~��{TK��W7��[���ޞ}�{�{ ���(v�M>�-vk�� aIפ�^ [��r��[:���K�H���zُ�/���bjW�'�V�����wIV|>�f/nϧ$��d.:O��:"�fڙ*������a�:��g����^�]�W��:}���u�[�y�qu׾��/�^�� endstream endobj 2532 0 obj << /Length1 2483 /Length2 21079 /Length3 0 /Length 22509 /Filter /FlateDecode >> stream xڌ�P\�Ҁ �����������!$w��.�%@��.� ���N�#�����ޢ ���޽�(IU�E-�̀RN�L,|qE1V ; %����=�?rJ-�����#�_�@Sw�L����������X��X��XXl,,��Qtr�H�z�X�rN�@7Jq'gW+kwP��|И�Xyy��1�:]m�M����@PDsS{���� ���\�X��;�13{yy1�:�19�Z �2�lܭj@7��'��d����ߥ1!P4�m��u��d��e� ��6�@G7������P�U(;����/���`eb���[�vd������������������P�R`r�vg�:Z�V4�wsٛz��؛���I� %� 0U�����]m��ݘ�l����� �͒��N@Gw7���Iظ�A}�a��p�����C�6���˰�pf�t�q��J�[$B�#��8YXX��x@��ܚ�w g�?���Š������2�6�@�?7SO ��������++����`��qD��$Z��A�w��賀֏���翟 Af��h��G��3K����*�������9y�9��l�,VV.7�C���Q1��w��:Z:x��.�O�I���;@�� B �__JN��h�,� '�9����u����ߖ�������7#){��i����sn�`c��o ��z��n���.8�_Um࿮������=�u7�QG+�����M��h�b�nn��u��\��E��q�8���~�YYX���v�ہn�����<�R������-cM�����4dq�XA���������A&PqK'W����0������b��,��x@+��x̒�%n��b0K�!6��b0��!��EW�C��]���+��x@�U�(��EW�C���]��:���@�h�!P<��/(3��(��h_l������5�C s��'����4��H~���/���J�_;����>w�]��J@@S�7u�=���J����,�B���� �oe�?q���DX ��s�Vw�p�+H��/���O�@Ѭ}���������Jm�BP���BP��J�av��4P�x��:�.�_�ڝ�$2v��cP1��Ev��3��V��t�d6N�������/7 �˟��&��?���B�?��+�_u��x����M@Ͽ�� Rw�%�� (i7{S7�\�r�S����n� �k�@Ms�r�����/���/u��uY{�� �>!�N��X�������J=����|G���K�N��m�?~��%�bܝ����N�e�[r��xD�M�����z+�2܋��-Is#�L��w��֖�����l��6�ێ�8�=0Yt$��OOȨ!���������K�2�ŃE��ޫOڻ��be�����^ �<�s� c�f������f�s�d0�Dpt�ި?nng1r'�H���c؋��6�b�|Vi��u�Q���A�`�MS�����,���D� .�pG� -�K����# T�u�X�(��ЅIѝ�e��j�e>���&i�� �,��L�&.3�&� zx!'RO�����!�>>���O���c��5�@|+��ՙ����\i:-��b �F����=3�� �6��X�����Tr�h i�_��`��ׇ�̓�2�d�Ҹ�tv�R�o=��T�����q'o���;�+{R3��GY61���l�!��u��wn���S��:Ǥ����(�/ٝ'�+���'@�(�D��H� � �qB���wxNs���Z4�=�$���2���L�fW���9����9��w��H�3C��Ly�0T�z\�7U�3'�m=��iC� ��\��^�jCɟで�D-)/�z�A*2� �RYw�r�O���LJ�G��Z��.p r���p���[��K$@� �sU�X�DY��P��^�o��k�T�R-���Z��"�v���_�$ �}+�� l��s�ꐔ�I�y������eD��;煅�*s �q܏S����w��9����ŴwYCՉI_�!��蚎 `~��D���ķ���׬ć��Q��ZX߫k��J�I)�tyn�Z-��� P�$��+���>���{ �b�EQh!����c� �V���ϖ���)�,��'Ħj�F�4�� 8��䣤^kl��펣���Qo�' ��I�S~�:�&o��L�)^��U;+�*�lb�V��^Wfv�R�9��J-m�c-�����蹎+�z� ���n���NO��1�UwP�J� ����������F}����������ϑŌ����� �#��b] .|}������_��i�'�$�7j�*p n�6E�}٩KK��R�J>�����DvQB�Ӥ\g����J��2�A���` '��٥�9נ����} �ݚ�3�yx��i|[>������iNٍH�tA�s� 5 }��e�koj�o;��F���D��� �{*U���!��#�"3���[�S��֟� \���9SK�r�5��u֠v/ �FO�H�F70�+\Y��''�tvt����g�y���Y�CV�{�,l�/��@��M���g�v���{2��{��a�ß%�I���ԔX�11�5 ވǧ�����oc7I �:�Ȓ��� #@Z�h��������Nh�&�[��1�;L���#�V�^a��O�u�C��3�V�l���]Qs�vdi�Y��s���fb_uq� �:��2.���1��n�U�)��!{��#v�����P�K7�<�gmB��2�y�&�}��߂���i�]ڶ�gbr���k � ����!Di2A!KF��o��B̃�-���nIb&T�>�����v�w!o"װicB����^`��٥� ,o�<��߇��B�p`�?ѕP�Z�$R�-4/S\�s��pV����;ƚ��v����U���^uҏ�闻-7"{��O�-ߒ�{ ��z�-"{�j�T�l��v���ώW<õ�� D���қ��7�>�@��@d@����t E(��z��r@���Ep,�9�G8��Id��.��� ��k�X��,>���(��E������C�l#��0�jh��}���7�9��2 ��bڋ nm!��=sD+]�v�ñ[�������IS���,>��'帹��7rp������O���իx�1ɂ$��'��-�Aᔡ����en� q�����X���r��f]m�C�m�5�>T�&�x�a=d��t���������4�H�n����g���h���Й r��j(��>��-4h�Jqۄ_�Ȱ� "�vC�g+����Zc�g���I�u�1(P�p�$��m�Q ��������{�]�v�{�Eѩ_����n�ɏ��S��� c�z����!!ƪ=��*m�im���H�]�7����U�����օ܆��� ��ƍ�e\���� c�Xm�Q��Pf���&�=5�/?{�s�h�o��eI��i�"��N':%Oa��l�G,ъ�E�t�,[�?���vH��,%���0���B횖�m&4}��F�.��=��e�4 �R���؄�u�~)���<$ 7g�p�m12� JA�j���L>�Q���%?y���-�Q/d���V��/�@���x�z����ZL݁�!���T��p���Q�.d��b���e�Іυ����7���^>>�2���?ib �w���*^A�#�u����,�.n�O�{������K��LT �E�}ELJH|���¢�1�$/ l�GL�UރF�B�D$�Q�.��f^N�{�R��nF6d���>�^� �M��ϋ��M�1�ؒ}�_����AV�ĉ�<"���v�Y�Ӆ��)j jY̧�&����O ��8L�It"�n�+6���`�f�[��1�(���7�<�+F`j�w�S&�ˈVx �ޥ>�D1y��, �R�ti��,��⇻�d�<���Y ewo��H�●ai�.��{�R��8ctԐL�W;��`yM�y6�P㢶���0$�B����^����=M7�w���5)���!����LN���%{wQ�� �eԐ�ɤ2Ot�j��W}&�<wUѭ+�<9�`g����0��&�y.ʒ�z�1c����t��O��h҉璘��m*�L�f>�{}(&�����Q8=m:SB��_CF( �lΜ'�?YIO;F)�p���=������v���_2y�Ʌ��+|�}�y=���P� Im���kA���*\y�TDr���7��E���H���\��(*r�i��dw��Y��'I�ARB��Q��x7L/ɷ�����c��J��O��<��' H���T� J毿���Yo nH5����2��։�i�P�~��G�r?/�,/�!�9� S~���zp�Ӈ��6x �V|�<Í�6<�؄2��<]��Ʊ���m�lv*�O[�k�Q�Ͼ��S� ��Y�C/%j ���o�I{��i|�Ѹ���H��z�3�Й����'�� Y���ӶmI��cE����Cn_}}��о���V�o��1'�?t��tp��8�[b+3�H � ���围��'�^wwv��Q�>ϩ���Zy�ξ��ψ�2�������k�K�v�xc���.ޕ�/�6��#���[ �:fW\K �΅�D���g&"����"��\J�d��8m�l;��N�5�&ԫ*XP3�+�տ�[ul�}��8�9 Eo����t��Q8�#��l�:?��B|l>����X����0�h�_�\�17���l �"�*� ѥ�P�,�(B�$��%#j��YE��h*���E�f��A���@ m�,d�܁�� �#υq�U���x7�|v.�\�0�D��$m�^J8��#�*+9x�S[ejk �,��y���b`D +����2dǨ���k��h6�֖H�d� �g�l���c�W9Cŋ��q�k����K@�k�L�N8yr��V�Jş��;��P����[����E��Ҍ+sgà� �n����t��B��]���p^n��s ��x�ޞH!�� Jۼw>G =x����� �0�$�ϴL���`�߲k,9�n�*�b�uZ[ǐ�ȉQ��| ���Z.w� ��}��B>J�F��\s��HCc�&����YR��b������U=�I��"�ʟ�%�kN�o1�1�bC+bZ)�s���a�˅�@�S�FZt�*�x�qY��);mB"���w ԏMV���y�F_:I~����q\t'J7b�a5a*Jl��� �4E���������l���rK*�!����� ����F��/�\�N���7��_ׂ��Γ�n�ڏ��Iif��S�Ԟ~H�}�1d ��Q����>�|戜�쑔� ����r(�?v�Gq� ���7z͜~XU��>�qP�`˭]rH��0�3 ��0�0<�&�%M�a����#[�-* �u;K���V��� =�YcD��#�=�������A�ɕG$c,8׼���#�žS�d�ׁ�@Y�FyRv�� � D0ջ] ���t� `2����#\�h�hz5�"�0�������r��:7,L#y��':+�䳾�e�Cu���;}ۡd�mO�bx���/�::��N��Q��ݷ��s��er�[|����]�ahi�Φ��Pd�Cn�Ti5+[���Nz��|�׌_m�G���ζ�c�sp��-�=8YV�=�>D�k� X�N�8�e���sQq����p�������/��,ZIР�ׯo �.Q������y���%O����8,�{/\G�ȓ�|q�J��jXt�������!eL+H���� �j|��������=�z[���O�֝گX���� ��)M�_�6�� j_����d�M��ίs?��� ��u׬J!�x���h��㖤� ��6QH��Q[S"�����V��PJ .�Ӡ8��y�h��4�������1~�����Nʏ���q^�[U�K X�gH]9i8L�kALD�99_�5�Y�q��F��]���;7$��Ԟ��R�#V��<Ϡ~ne glؔ�Y}�(=�3w�۰O/��oi��j()���n��9�*��~ΰIѱ�- Γ�V����zY��=� j�b�lI� ��t�����w- ��W���/o-V���&�zl���S��Q�S~;�r�i�j�EH.�4k�+�}2.[n�$�M4*���V�d�|�LW�g�T��_ ��#F�>����F'):O��ŰL ���!�4���C��� ���'Kc��a}��I6��"�pA1�3�?��\_���~�{=v�;^����kAӂV�S���E^�1;7����A�9���pW�քV#gބ�M�TIW|��K�)�|:��$�`�D�8n��$D�F����r��=�י�r�]�zd���@��`�� V~����1�i�M�L�np!ˈ8��k�'�Ū��.ä8�M���A@������O-q1��� ����Y݌˫�h �F��v:��fW���~n�?�gG7z47� ��o8�>�K�0$ tR��D�gWD��t��s�gƜ��������4�U�+�PB�΃�'l!�\�곾�o��H�J>����K�]X�m��w¿�Zk�i�/N�� Ոk�e�I��t��K�_�Wg�f�j�"�2�Y�E&�4~*i _�D���7m���� l���pn*�Gn�<��{�Чu{Q��&����8ЬT�A�3�L�a&٥z$�� ����k�� �x>��滱E��\��|���\e��x�Wfs��u�1r(��w�"򷢻l�-%;9H_P��d���++��Px�T��:�a�>�8��L#� /�R~g�2 [�Ǔ���^��v�M�C��DY}�ve<�E���#�2K���>�"ָ��?h2�]| ^�Ϙ a�T��� ?[D��������ؘ:<�s!b6ڂg yi-��B��E_�l���K㑠 ��q���95�^�� ml@�1��[��NK�9:s���������-��*�< �dո��������{2����1��|a��c+|��E̫���5�85�4���*�+�̤< !?�ޑ��6�-c�<�L�\���{|�fy�+ �|��P Ǒܝ���S'�6 &���.�3����K�;Z�pi�f �_6R��:�*'���s Y�Cή��.�+cs�r����"�Gμ_���:����'�3O<��ό0�2#M�q��8J��S�i�;)c�–�sP������3�d������{��v͵�{�h��]���;<�A��J7 ��{b���-��<'��U�8�(g6Yl,���� [�;!�pG�,�X�,W��y�a@]A���������r%Ͽ6mwJ���nD�qq���w�h:������D�y���c���7�ӝ����K�<�l�(�6��@tej1�϶�\b�H�e�L�U�-�����u���/�-��T���dVnD�rZ�U�$���j�W��W�W���� �000�|E⋁�x�d� �OR� ��������=��4G��JM%eu}�s���7߃���^!+zr�b��� MxP�d� Sv1M~��r��#�>u��-��\gU��ӷ*�#�zϠ�Xқ0?��)����]d�g����)^ ���TX!߭����zZ�Ϝ��?�}Q@zP;D�,�9W��)+��@3\})�<^=�]a~��a���6.�"�GT�.2.�J��k~ҭ6k�H�'�P�b��� ����ҟ�� �QPa�CB��$gs s�疎E�}��P"��f�k\��᮱o��#����E�[��%~��c�r.T�ˎ�L��>��-��{:e�#@����q. �U�qL��ID�r��u1h�V2 ��ٴGICr�l�.�+����j��V2��!o�}-��>�@�/&�{p�4��W��'~�uA����o:7�UDr��j���@�: Лٷ��a%;>�*�_ ���o1�`�]��2��B�ڼm��b��w{ҳ�P�O�C+B�]0WWQ���Ҷ��H��U�&k���-�E����W�ׄ����(�~�+��~�,�4+逨 :a�W�lנ/*���3���-7�J���w��\�D��T�_4��#�gP�|�ҏ�G*�­�j�sh�O>�Ŕ��WK�>l���Vf�9ܼ�{��yͿ�J2���N�J�k��Q�ހV_<������J7 �-@Z|,lRy�瞹��i�����e�ؕi�vN��!:D����p���J�� ��m �A�������aT %jʰQ&/�v'��'�xLҶWz��c�Z��������8)��ʈҝ��)�&�O���k:+#� �E���_µ��^㿊�Q�v�̔�K��nk��Q�{d�d��F�I�ٮ�>�g'�1?�˱�/�v��`GUQk+��[,��ЦC���;���?�'z�O~���in� ³��ł:i}^�&i��~���R!^��N%O���[��+�eS�b�z��}�ON��"���`�d�y�Hʪ4�ʁ���KXW �ظ���/�����o7c�c�!��\�������9(dW8�*6�� ��afȕ* �U*+�8_�3L�?��Dq@b$�Z���u(��4+�7ϵ��� ����%��j�_/IQ�^��n�:���0�I�v�2��B�_��2t� I/o:R��2�#��� ���₅�9�V�88%����? ��;�]XOS75a�H���Ӯ?���R�����H�����F*��rcR*Ȩ%�3�bK��x��k�LaM\�:l��) �~˜QX����̳�wo� ΍��� !6x�r��3 �k��JM͌�b(M�f��53�O�f(uI�Ea��r��Ms�W�禎���!��N�|>��j�]rO�vjԍ`k-�"t���\qo���E�����z�ǍD��N����F�_�aS�*R�f�����l� �M��.�w�`�7��gV��~\�ӗ��Q�{ �O �K,��i� L�5 ?�ߦ@���*uH���X�b�5��Z�xn�]�k���\F]Ʌ�[���X�X}����c�/:����r�n�.���zz���Z������] �� �G���6/^��lQhbMi�kr8�*������Vz>�{��yz�Ô?��O�+��p���na��?� {7������OkS��B��grzv��e��Ԋ?M�����`��g���;e�%jo���ܺ\Bh������q��;�d�����C�O���\F5��p����g�U_ �v�>VR��g$cc�s��o��C�XWܓ���໙$):73n�Q,�%G��")�PHc�m��ꦲ^���b��^h��5���M�G2�"�i,�cW��'�ЈK������4z�>Ɋ����7�` ��ʇ�����������jk-w�]���&��W }�xҎ���dP���1��l�*m�jJ �ƅ����9 ���3��i��5��[����:�.wa��N5�lv���z7 4�CM$"D�Or���7c㭏߿��UT��%���hR���A����!�� -S�n���I1Yۇ���za�l!��E�眻K��ab��*G�y��)Tk�y��S-B Q��v���B����3f8^�v�hwT�� �הxb.�r Lл���� bƦ /;xb��:Z$-F� ��v��駎_�|%�:�g�$�b��"> l��������]�C�6,�:w�"�V����>�Ey�*��|�jE\����1*f�G�\�_�X�\q�_�q]��@��S�^��������%6I�`�!������m>��ܟm_��O��$)����!����ڦn~N��+At��Œl��Z^���Sy$��sfgS.,������� NDh�@���y�X�94ڭ� �$ 5F0�'2�kp�=�!�,m�n�S�<6k´e ��[E}����8k�T�n�=i mS/��]!�Ѽ����oM�Y��ԍ�®�V�6X;�� �Ϻug�ؠ��{����k�¯o�׾���%��˂c���&��D}�f[GUڒ-0�T�zR��'lo�S.��+�`uP��(!�9��8kң�wl��e�6�dY��i�IgG�s�-�H_r~��pJ=c��{�y|I��g�&�F��Q�O�C�;R��I��ȫ ����F ��F�z4���U�.Ӌ��PU)+k��{��o6҄R�ݝ�'3�� �G��srt���D5n����<��SaK�,15.?�\�u�@�љ$�U�$�s��*�l}��_$�0#,�1��rp��.�~!w!����1f!�r�>'��Ȝla5ǝ�bi  �6��/����P�q��� ��R�3�����ݱj�|�!�[Ky��I��C����<��v�Peʺ�Տ2���l9Y�P�����D���8&�ޥŠ�?ū� v�~4m(bT���:4�ǭ�q�6O����� 5o����N�9!�x��YO]��r ���ң|N]q? Y�����{SwkX#��IpL��Q\{��gq}fK�4�VK�:�(o����r9bWvJh�tNT�+��"z�R�z��0���]�� |.;NZ�j-�`wVz�D�^vِߡ=���}�G���q�^�Z�؈��D��������%�V�Ƥ{;ƙ�|۶��ŵ�w���ȓF���-��f0�c���]�2w�$�}�ݹ��1mM�*�QhVr�x+��wQT):'�� �F0F?���R�W��� ��������H~�ΰ��Df�9p9�A�], e(CCꄱ���>�2<` �G+�j��Y� �j��x�w�J�Y��H� s�ݤA5s�Q����v��]�IyM�I§8��t@7k��1�M�nh�o(Y��$�6�;�j���1"���ۺ�/O8艿� ��1ak�\�H���s&Bnss�F�J�8�U�[#�ݫ� ����C`ܱ�h;o����;7��a)-o����aRv�3�p��(�-���h=�}��~,������� �s�u���ĝE Szй�b�DY���lVF_鮍��-&_�\p������% �-�����K4c�� (!�|�;�Y>�Г*�i�q,~��%�k�Kuo����,N�_������s�M"࣓C�3��l���6� ��B�x/��B3T̵��!l���݂Y��S�Bl���Yεh��'�����ɦ�`���~݀����5pU�F"T֕���6c��wKx�u]>�kD�18ۏ)��x�� �f��O�R��_b�}x6�Q�k��x7�_�R�~�y̲���"��W�K����p��H]��j�(� ��L����l���1���k ���7e SR�p���T�����j'cd�U��@�����V�>0 ��3�o_V�Y���Z- $�/��&TYT�zY�j(� 񅌔H��W5�Yi�����b\�@G��-���p��S?�Ϧ�_lE�$s`�a�OJ�"��`ӝ�8��9 ȅ]�i�/�\��.Ȑ���o�jr�W�)?�»� �T��edg3t``�`�#�٧Q��~���yj��2xH D�[n� �� eP#G�k� /��d�{W�Vݔ�>���?�L�&��s��0��2 ��]���æ�mqw?p ]�� �I�qj�R�S��Y��uy�R�&�aߣ��~��|�2�/�Ĕa� ��PŌ彂�ɐ�X#�>�����@2��Vcj���RK+��/���}�Jy(k�����V9�� ��7����QA���FAu V�ew7�����Dї���_e��� �pٷmdBt�{�NA]�*�nZ���rS�g%[W�(��bm�l�?�]<U�s�X&�|N4L���\� G�A�݆���lrQ������.����Q4�bAh��0�ͱ�|�����u{�FIؔ�C��� 7�]��lB¦َ� �q�r��q��5R�H�D�;D"����i_�����9d���E̩G��Ʊ2B�D���C��)�U�U�����D���U5}�_� #�GI�� RW�u� 5$|X/P�÷��1o�=��� �$_ �|�I� ��L��mc� a|�����f0�O��k�L�����.&����{1�}�8ZكdZꀨ�}ڙ������6f�埣^?�jU���O'9�������Լ�,�o��V�3��l��{G�EU�|� ��B���5S��T��t���nJ��*��S�!/E�q��\�7�T�j1���I˭˸�Z�F������� ��R��^2(��,�ya�pW��q�6D� $Slw�^D�Rn��c��m���P0���� ���D D�(��O~�H7R=�?k�t���b���e}kךQf<�y��h�>%c}��������0E�c�T�����9����Ko/ ��mU=���kK��b8}��W���(8(Ŋ�\:\��E?����YK[����Jʴ���ȵe��+E�#� �el��5�a�)�� ��"C4 TJ$�k�z�ZG�̎Ltr�(;�q���#ӱ����̕��婸������~\�=�u�a��Q�����\Ь�����Ξ����v����:[��x�4św�4�|O�uS���0�6WI@R�M5�Ne:�2{������dȱP%��0ɋQz�l���,�Q'\瓵��[�9�8���R$^e]W��� Ը૮�G����O��a"�&ܕ��.u��%j�_�qY��GXQ�,DaY���8�S{�.S�� -� o ܦhJ� Gb!�Ρ u�󇧊S͑,�hs�w��xJ������eP�3�'�(�CX��T,Gh�F�3���Qh%�tG��/Mq_��e;�TY��5�G�exQ�}�xYG�g{f��;$U�"`E�z��li�Q��F��iW�{��##I�w'CU7��Y���q�Rd�[���2��|v"0���X�s�Ѻ��Xw���-W[�Ѯ��� =$h>�������7u�k��i#�∧���R�O�M�!��ne)Ϲ���I<m�/X�c��q]r й��9� ��ǰ��^ȏn2�{[�j�æ��y�p&���`j�p�$Z�T�>�SB�D���X(�$,m���0�e�퀻{�+7�4p��߳ VT Fr|e��`2�)A,�V�`���v_AĨ���d)�٪?�t��^>�aڒ�ߠ>�֧�����w<:V�|�M��zdU�X�c�z��mq�gK7׬m�G������������[�u��'�/%�ʴ�L��G�y�'�Zv$�8<ZA<�}�&���#�w�ҋ�j󍲌�gձ��M��㹊 롣�΍�P*ag�5��W]1�Ji�r��� ��0WXڍ8`�ӕ���n�t�lT{y�`���d���9���0;F��iG:G�('̈́9�ْ���~���X��U/�>+�� 6݋!�OR�MPS�u+R�q'��[l�-m�c���n6��"�� Gj�2��5_�f��20��KQE���Y�{��3de��38��@Ҋ�ruY��) �b��ܜuNگ���/F��� ,�D9=q36j���C�o\r�CY�A[�ȶ]�� c���Ϳ��w̲䐪&��)E4w�m���_A��[�T�c-$�+�����F�p:�$V�o�Y�צ�jK� m|PÑӫ�o�nY�6�����܆L���m��G�ۉ�ٶ�F�Su�,�ک|��[VX�'������� ^|�F�ӧ�cU4�z+�c}� �����r��ll�T�ߍ]����]}y���ʐJ�6��q ϫ��E�{*����F�/��NË�I�7�'��TϨ�k��Cf����D��E��ڇ���g�M-�u9�b �dTYfQ�i� K�/���Z���lJ�g;����2d~I�ꖛ��q����%�In��7����j�$���-aO��-=�r����6�� +�>���?;S����/��a0O�/&�+�'}?��G��,ű AЫEYM��҄�"vf���+�n�V>��/���}0���?\���Q8�y���:Ƭr�qqC�[�! W5P�##%��f ݄�T��Nv�'Qz"K���Mv� la� 7�� Gu�l;��� �)��/r#��ڞ�_�����}J���ɗ-�;ȡP���ls"OKi[��4�� �3��Xkjh�v�wߢ�u ��T_�u�����ɯ)@3�6S�"I�? 5m%m� �XVa�34���y���x-�ŹO4N !�6R;=��~�E=+���=���s�a�~�[�R���[��_`~H��+a�m�G�&.L��w�O����`��O� �t~PҠT�a���c �����u���$���\� 7�*�y=�*�%�����괕�J�m� �|Q�����_��`p-�h�����3�i�-�/�K��co��<ޡDH��Ia& ���<�k���p����R��S<�����Sb� I7j��2]�#:���c�M)��T3W�M����]�=Q��!�ޢ�-̩=|C� ���˒M�4�GKd�^3;�޿��P#uˏ!"����k�f�h{���V)ݢ�S��y�nt*J��kZ�k6�� ��E{�,6�3/�Tų~Y�M�2���hS�*QSRub�}X���*�?p���RSF�se���^��l��,Ej��:�[����y�K:?8Xc�@��}�d,��ۛB�Zu�\D�k0�V����|�-��_�>�p���w�OT��;9[&�3��oėmM�B�fb=�2�PU ڼ ��a%m*I;��`���N��W�T���{\��Fl�;���lfAO���ay,�C3��#��#�B2|��P�5���%���^�1��0��?–���^����<�r%r�L}5�q�M!j*%�g}�s��B��UbP�c�r_���7;'7�t��~'�o���E��U/��V���j��L�g���m�T���Z�0�z��Kו�{˼�n��T�8oL�BG0��/ܪ��Ĵ���q� �>���{w�$�j'=س��9` �`�˚h_q6x���Ly*@x̠5�/�����iF���栵�8����ɴ<�p����yhs�RF^���XjS�K�Zn]�����;�� ��zO��'c����?Hق ��đ��B a����x�m� �T�Rl�9�p�H`k��%�&Z�]֜k&�8�"�������k|{�p)S{?�P#>@�nװ�D�G0�X�1w �K�p�O��N�Jbel���:/l��h���}�6Z�0�=Z��淵��>�����W;ž�l��"�t��2t�b#�]E&�X�r����,�����#��h=\�3 ���V,���ZQv|֋�3М\-ΚM$��mh5���ǰ�<}�������������Bb4�~����$�t�?j��?O��!�j��K<_#��$5�׶p29����zw�on��_yǦ�Qx��h��8��+���F�}�%IE9W~O}>w� b�N'S��y�ț*'x�B?�8xO>Xg)��(eR̗A�j2�C� ��zKw��T$ʑ&��r��9)4_�`�{���_���&[��ÙD9�ݞ��8�P�� `�V���k�-"R/p�������=�h ��c�Ji�SK1-K��5N�D���5�ok�ە�bD��{*��A���{E�S}c�I&�-d&A�YF���:�L�]%���.}�ӝ��Хb������)�,z���]�ㅝ�� �`Q� ��)C��r���#�@� �3"'^�Y� V��lmO�k'F0#�&"������C��ѱ' �pPC�3���En�=��v�"��w ����g\m �b���F�#�ڎ�j ]�/�����y�ԣ&����D9��T����f镠�`*~�`�S��3ByG�[)=Iﺊ{%�eۼ�Ũ^2A� ���1-�ǪY4K���K�Kt �U�/0b����8c�1F���v#�/�?�{#�׏9��W�� �ێgC��X9� �����j����� M�Pf��p���'&y\�����wB{ϕ�r�H�����"IPa]�.]�١��m1!)-��SmU����EH`?�?�!��c�a�^�u�]��#�g���iq���Dg�Es�� �K1���ſB��# ����X�F���fu_��t���N+�8����’H���݃��j�W�'Qg, х�1�"���fi鉢�2���K�3�r�"�O�9� �+���m��Z:k ���� z9F�2�����b�^�?|�������6v�����1W��Dzn뗦� 'Ѣ}|_��U��W�!}�-���y��L�c,}���53ָ<6_�⒍|�~>)�w�8(���%�T& " �#����(S�ZX�Jt9���p�ɸ?ͷ�k���,a%I �d�X��mYmS�l��d�N�cfc ��|s�<$TX�1��%��U)_z[����aq����g��1�0���������ZT񢐑�6�܀:�"e�d����bt; 6��s ��,���I�7~�n�v`6e�z���/�@����-�XQKX�s��5OyCnmQV�ir�*��ˠ�� �fǽf����1�\A镛^Ϥ��r�C��怋���\�(���>��M�Rm����Bu9ŤJ� ��{n#�MPD�n}X�䂪���b.�{���͆u��2avS�mJ�\���j��E�~�3%�ceŲCj���>�v� ����Z �,��k��:����Һ��*KUSKG�tҁ�C�r�Y��(� [�l�nH �o��y��ϟ=o"7�4���"u�hP��=���DC:��Z�IȨ��`��.�:|ca�)u�z��s�5�h�u�Tu�} �����/��X�V���.{r&[ C��:T�&�b�¼)�u���e�� ȇ��$$�/5ʂC�'P��G����_o[�ͷ��>�:z�A����s���������#�T5]��[�q�*}�����L���|*@G����+���|$���կXC �M�;7k����*��u@ �t��زзƤ������ln�?-� A�U)NQ9�_T����%2��}��H��#�fL�i_��_6e���UE��`��|�?O2�� elduY n�ƍ�a� �s�;4�ac�Y� \]�St����*(k �Ӝ�Q��`��/�)O]��I5eh\w�Q�$�z���|����S?Z��;'�ge���H§�r�/=q�U���"FM����m�� N�o����|8'A��7�w�r���!��#&VD�Ӟ�B�Yj��{����B��X :��`qsމ6�7���h�ѮGh�==6��n�uO�}� ����dMu 7ZE���?�l����p�i��)Tܢ8�����@�.��Y��A��S*�t�$߫%.K��Z�Jw���S���ّ�.vsݎ@��Z�b�j� f�OĒ�(� *�&��I8 �P%���vh�G�j� �:Ƹc�@���azUUo.F���G�7.�� H;�%e_��w�tQ�6Hx[_'K5�jƶkR��R��K�8EM���a�cc�� ��z2�c��. �{9[�|WVXT�?�U��l��Ҵ��¸ �M��n�iX�e?�#����Y�����\ *���R7�<�^�v��� 4���4��(�����V�J^�W��` y3f�>����u���� �߆����ʴ�)��Q��6����vׯ���*Ț+9�U9{H'�=Z+�)v< �t� #��>����IK?^l�g{;��m�0`9��h�?�j�*�\C� y�M}z�� �U�B�����>\'.���^Pؽ GpJ�1������蝹8/lE2��� �E�]� '޺ș��?s�����Qֿj�f��i�}8ro*�����s���ު���g<�>=��_ ^�t��jLg�C)C��`vN���y �6:L�m�\Z�}��� i�v1��+LS�g&N~}�����6 ����fFѬ!����?W����?.n|�Ca�kf���]]�Nq>V�1��ؓ�ޡ�TwV1�;��P���K�Պ�Q}����<Ȍ�� endstream endobj 2534 0 obj << /Length1 2379 /Length2 17933 /Length3 0 /Length 19311 /Filter /FlateDecode >> stream xڌ�TZ҆ �n!�6��<�K�4����!�4���'���wv9sf&g��_���ZM?U�k�U��n*2e5&Q[#����#3+?@\AL��������ʎDE�n�h���Jv0����G�8t|�I�lm�NV67??++�����?��`~������ ���9 Q��ڹ�Ϳ�9���Zc:㿖D�A`sc� @�h�~��hP�569��O ZA3GG;~f���-��0#���� � r��A&��J(�A�.�� �nf��C����� V�� ��%N6& 0�mw���<@�d�w�����7�����t�^�W"s�-�Z�m��m�Lͭ@%)yfGWGF���@�����z�3�� h��/�@��� �V��s0��9:0;�[�U#�_i��,ic"nkm �qt@�K��9d��w7���������������2L��X4l��@2��y3!��}9�XYYy�� {��،� ���@�r��e~������`�V�������� 8��@^�t�/!��L̍F�/�6H���A������]��o��`������&������O����EV㣒�ÿK��SL������`b�b��q�x�X^��Gh�o���ؘ�����֧�Hv�� ������7������]����������k���)�+����_ERNVV�������Z�[��;�mr��n����]����Z�����������8�������A��d�l�hl����m���Y�ۀ�m��zZLl�����v��-ߞ����� �vy�wKIc[��n;7ݐX�F��� ���vM@���b ������[q^S[0�_'��`���7qX���E��X$��E��� `��Cl�?�`���8,2��ml�Л�?��E��iQ�CoZ�Л����?��E��iQ�CoZ��Л�?��E��i��Co�k����?����t��[��z�4�/q���m���?��Ο�����'�M�ߣ�'��?������ ��$`��`���W��������b�_�|k�����z�l���7����VX�����5������'3��R��������ļ-���[1v�o���~�l�@�����o+��������!��G��j��?����[���E ���-�������m�?�=�,�f`�?��M����?����|k��?�z����l��������?žer����c'�[k��Կ�2���v�@� c��9[c�@�����*QB��1�i�]�d:&�Ep��o4�D��t�u�h�`�ʶ$�͇%�g���:���x��G�'�X���V�� ���#�ڟĈDL��<��=5�,��!;e���xєs�߻��v��Y�<<���W�-��T2����W8C�m�1�G��D�@�y�>ss;��9�J*ˀ�uɑ��0�Z���ЅO���G }�92I�!v�$�;�QT-^`Jl0�(܎��&�\,��;4�/Aߞ �6V٢<�R����̪�)�zf3�ErP���q/�I��Y:�(�����Y��Њ�u�$�s/�����󞢩�{����n����tE=�⹿���A��{���DX}�h�8�fF�)����@_櫥0$aq�$���H��l�;�k���#��%���(P���N� &%��ɨT ~�n�a��0 v��*݄��bF�"#e ����5<�E@`^Rh ASȗ��;eb����⩯ȇ&�b&q��2%�A \�*�W���($$��2J9��s�B�G&�:e�q��+f��������x��e����ߓP�(҄u,�o�r��5^\*_/����(cvz'��6����i5��������{�8ޡ�Έ�\Zb8t++7ޕ wD����m�um�����Dl�w��5S�����r2+�����[�n�V� 7(��kl"���A�a*sנ]&�(�������ྫ�5;�J�6�9ʜ0�m��R�������6�SPG0�{!�Kny&�r����t{6+$]��SY|�|%֠q$�jq6����3��n��ks��>j}:�X�4bkOc\�����A=�`E�`o���_�'(�Y��z�Ϧ�(i`��9��6?���K��'Qi�]�����C4K{�~ߺM�P�X򍵾H$�?��B �V��C/ l{��cq�3�����}<�9��_m�*@�G�ҫ8}%F����� ��2�Hg]��A��ݵ�Y�E���)��T��]�2��$�dW_�r��Ԑ��t�>�tTˆ[F��G� L���� ؇�8\��� �(��0\�)�k���j����'�ٱ!� �U+��� B�:0u�޿�V��u���<�P7�r4ӄ��{.��Y�Q�}���B>��?o�6o��FyǨ�Ƌq��gĢ���d�|��ʿ*���o˅a���'6$��"pƷ󺃠4d�N`�-�� 3~��0(����~���MÇ�$�Ʉe�0>����-�:�|�a,� \�X||�SX��tdMd����pׄkN0gM�����=Y�9��x\�$��mTiG#��Œ�v6^KI]E�Ӣ}��!�'�z&a"�A���&��Ǻ�����޵�V77ea��&)ly��,~�_�����W�"��T����84=�*�VsG�� [�<d�P�n� �{��S�u�>�G�p�{�w,��٥�be :�*�9%;mï���$�hUJA�,�5��vҋGNe�� .fF�>8�%���u����U��)����u%�8=���sWe�z8DcBl�+�����[�ŗ�L/iښ|�u�� �3��Y��4r۩Kv�E']��8k)�򅧚�(*@�赠�$C+a �d������rCr�tL�ϋ�B�bj£�*���mG;@d4K��.*� _eN�F^OeetA,� ��2�Y#����?r� �X⿏����#�SD|����m?�q�x�� �U8{���+C��#Lчy:��;6��c�.g#�+�,�W�y����M�c��>X��{���9���y���p��,@�`ڞ�Ս^���6�\Z�����Ii]�,�ᮣBh ?�Ϫ�K�>��l��g�I^�mL��g����pU�Y�_FD��"Y�ݡ����I�s�‚oI9�w��id�ӻ��˝�U^7%@���eL�g��g:�f�`""��ŽD9�D|��Ĕ6#�OMj�ԪCo�n�ƴ�kh|~�:j��q5|)�ql�ߓ���B�;5�� �*�m�`�k�B�'=.��D��EglݠO�ut��8r;j�Du�6�)� ڏ��Թ<@�>ʗo����,Z�~ n�>�?� ��8�T�<��F!��$�L�[m @��t�� ��@����_��=�n)�`ɹ;�"��I����ݍ� 2u����^�N�p��L���W+��6��3u1�Lu��v�Ofĥ�ji�[����p �F�Ǔi�5�I����G�j�.',�:�����&�bcy��x�{uY8]~�2�1�����P��pl��*EX�Sy�+S��B�\��[��C�(Y� ��/G�w�v�4ز�U�0g������$�Y��y)��3M���O�N��(��d��|C�Rd@98�>&O�M�i��]I����W�:$�>M�Rv�Mŀ�0T�T�MSZ����}����zL���l� aK���x�G�v����k� M�� E�����Kt�*��%���eJ�y��+�̽�+�C�oK�3�+�fгM��cbE�<4�մ g���i����l�2�1�w�VY*3��RT�E�uHl���F��Z�k �r���}����+,޹?*o�xrXx�˅�m��U�|��6l��d��>��A�r����ua�J�Ue�ϡx���P'�S����_�uܽ�D+�Zt��e�,S�HA�j�.}��pn���ƿq�/ �S�iD����K+���^�t�k3��� *�kz�cs.����N r„�%12��i`vRtD�0rf��� �d=_��8�bk��`�s��Wr m�Vm�g0��/�ʺ�Y�'��czS<�42H ����!(F̮mW�� n ��W �U���m�����ȃ��N���F9M,��ҝ�+���wz�z��6�g)o�Bt�"1,w|Q�i���40~-�T0gqo�5l��Rj����x�d﷩�]߱}�+<*�O�LJ >�`谵GV��~�=�HݑB��9��5?lpٟr�x6I}��> ƠrZ�NӃ=��O��F�-!��^�[�D&߯�xe�nKg�}G�P�ߗmU���p��`�C�eJ3̴�Z�][�J�Q�� �����(&��}��#8i/5J�'�ݦ-�|��͙K�s�77?�_Ɂkv�u�$X��?�d���p��Dž�DR� !a�8�a>�o%VI�gi��5Li�?1����J��� Z��_G2�L9� F�,�h=�{G�W�R�_���@�� F���~�"�ՙO#f�w �c9>a�� �Ҿ����f3���!�/&G�/�Tu�R�O_0�3��©s���82%,�>G�e��L��/�̛E ;NC��l� 'S�-o�f��Im>��v�Ǟ�cOM\N�ۡ�8A�~��x9Cx*�ߪhГr��8�"F���:E�r���R7�qd�흏)�<��Bg`i%^s�޲BE�BJ7AeӠ5+��������V�3�5��}�c�~R�Dj.��GY�)>��F�P�S��d?���<ґS'-IbF�z7�Os"vI�1�Ϸ⦍� ��K3�%��F_��i��6� 3A�qN���W�;3�3^���_D��|��#��/�`�4��( T�,#_���mûւa�ަ��n��%�U��\蓪X���)P:�x�<2�αד#�#CƘ������pWh��(�K�?�O�_ IE� ��f�O���bA��~FN�������^#e�C9��i�A��5R}1A�n��1�>�Ӛ)=��r���� R�ιe�L�N��������7��s��`X�IJ&���݃����;aӵ��k���'���F���h2��B�Q �9��vQa)�vK�4M�g:|�����D����Y4R��c� eҌ��I�$�����InW ���B�͙��= =%%�V8�; u �y����P-����Z���4X�Ҕ�@ ��%b�z� |ڊE����X(aľM���CzO�(`uD��co���3N(�xx�)#7����A�.{��}���ǵa-Q��p[e��v��$�H�mŤS�ɑ1�:ҕ��`�����\�$�EYMڤ*��j �#{�v�g7����S��{O�q�e�s~|�ʟ�_x�BHF�[_�\�:��V1�覺���m`| �И�&��m��M�1��9_�G<�[��p/�C�BzGT�~�Ě jG������:����n�r�Q)���IA�bXUf��$��� mj�ѯ�1 J�W�7f��ث ���c �ܥ+O��YSc���n��j���_>��qK�#=�%�< �h���c�D5kKzAT��클0[ 2��T��s?Ù���I ��p̤<�@��n)Rᬩ������z�QK�G��X �C /R�Ċ�e<��2�g��*M��-]�ѧ����M�i�ߋ���'�H��L�>���֏�GIK�KO:��e%�0�/���9�d �ft#�^�4Sݏ�%V+��~C��!�}h?Yp�g�� [�L&C��:�m#�O*g�� ${x!�gu1�ޣ���}�����B���?4�Ԣ�n�-z���e9C��'�"����B���Q��Em������F�������R�^�W���oT6S���[rn~N��5���-�[:���7�K8��m+�pB�OU�^��j ?�g�>�K�G�. ^�WGL��'T䫕�b���Y~����!�"uBM���J̚����rmڧ���W�]���܀�*Ƹ�6�I���=�-/.���� &�'G*)/k�u���.����h�� -i�ܱ7O[ =Sn��&�7�D��d5T$rkv����6v�8$��Z �C&Z��5nl�F�X�ڜ�r��5?Ny&�9f��8���6�c�I�W���p�����ސ�r���+��:�.F�WmG8dO�=Z,։=C�}��$7���p��q���8�f� ����̾�� �S�ِWo*�������d���d���櫾Q�3X�}�+��z��=:���Pi'����m�#Ӟ�A����:"0e���(M�1�5)�+�N���/U�@� ��w4.����C ��ËeoY~���j��\,�� �6�A��q/�򧁦�u�p���L����I_1hk�!U���K���|�sY� D���Ϲ�<4�v!�~�wf>l��7�ϩU=�ȡ�_�<'I/ �H�c��S�*�N��%�c���_u4��W����I)�����M��XR����kU�|���L[�pd���|?��E{�'�ck���WfFV��>�L�´�]lU�=tzP�;�c�����c շas�z�8b�[?�[<�ت���J�^���D��x�Z�=����IM!�k��h��� �2 b�f*�jl�6IOs~&�#V �n�I�K��s�g1���,��7j[2 ̘z���M��8����Y&W<��O0AT�V��Qy�;�F�հ���>s�B'�+�B�iA��ltG���}��;Rxi�F�W��y A��n�H��۩k?�l�q/�>6$��P~R8���4?z�f -ǃ�2 ��t�E��{�H��FV�� ����h����� � ��@���65Q1�c0o���R�|E��ֲ�|!�V1�O�IvL��� ����~�����/OHY kV �������r<�p�,���� �V�����v����O>��w� ����r�S���&iQO�,Q���3ו;'}R>L`��ؤ�@X��A�u@K���j`KEĤ:S�]\`K�g�~��ڟ��1�!�Qf��Z`6�{:��^5{�\f �<�=�Yl9����S���"���<ΎG�8��:�z�MFuf� ��^�����3��4Y^;�w�nj��6 ��k ������b N�-+�P9�-�v�X| ��8�H=ұ���n��õ�q����i��H ��u6���)�b��ې��yu�a�M��B�~��t��Q&vX�{�Ù(����.Cd}�m�����y�i��Sr�1�\�(�Q��PZ��3;����fbۘ��w�dJ7��FH��d÷�H����}�+8s���1q�"�mN�$_�\jĜܰ�C������o��z�>���/���}�ﰮb!�9�K�XH$Q=M���:"Il����|���?)�����F@`�w�9O2̇��!0���&�S��|��0��S^_�!Bd�������j]� ���ULW�kٝ~"-��œ&�Y����8O�kw�< �ǂ��mC�LS�&�f��ކ� p��7�z:[F+�FO��"���|��x:�ߕ�ڔ�􎩓5e]:�e!�4J�����+i� �����W�����c-�v��^«קs���^���w��I�$l�EN&x$���}����w:q��~��,h�����-�@�d�cc�Ç�N?G��d�K�Ǫ���c�e(~+J\`�Fqr%��(h�7�BK����E-cFBSG�z��w��Y�dV��m.�7�T<�cg���g�-2\T=%D���/=R�(�� j�Ǭ�ƹ_y>�ċ��;I�`��ߴ |�G�?�T��B��K��}eyn'9��D�<�i�H���dM�C/�)�O��o��k� �\��0�Z�|朹QX�3焳���reV��b�W6]�����U}K�w�:$U����-�cKY��B��u�w�Q�g�q:�J�Bq ;�E�T����14�A^���ם�A�0ڋO���o{E�y���%*��EX8��2'�c�)���d(MI�E] Rk�:�FOm�_m� ��(ι�=��h!��AZN �5�K])E�J/�!���ʑ:�<67���ua����HN�YLB�} k���{��=����g:$Fԁ�N�Y"Hl�����'�#=�/���&H��_��#nz\�u������ޭ+�Λ��la��� �G |�h�uB�)����6��.� P�m��*��rz��V;��أsє�������g��#ޱ�&�"��=9Y|r�U�����n4�B�!8:l#TԨ��߀�����D�l�6�F�?�_vY� ��"�n@��[����F�7Mз�Zhe[��k��J�1�0n:8U�ē���KGM����0�ET��Zڬ��(~���;RW�^��gp�:��*'����4�L�A'�~c��O�Gx��Ζ���w���B�������%27�;�{P���h���A%F_Z�ed��Á����\$ʈ���Dqu-�Fg��I��m]��4���I���4��O�m5�/�r|�͐rC�X@m���J�ed��muK���S�7*�݊9q� {� @_�S"?k�)�E��ԍ䫛1@PR�����pN�q ح�"�?��_�a��������}P��x�L����(��`)�% H��=�tS����2?C�̻E�b&},-I�-�Q�TK�*�%��j��!�}���|�w�E�S�6�4�P�C&���KdL��|Q��R{�� �{}�G�y����8��[,%:$F���9)j����gr��^G�� z�z����:��\d���p_�B��"Lt������}N��T0�k�jD�,���6��r���G�p�n*]�����Q'�a�(�v"]���I gfOY��L�hPؖ�P�[�����L)�Ы�Ѓs�bl{Spn�OrP#=PQU��"?T��`!KO����M�btI/���--�V 4��[���D����G�:f��Е��ў���S��R�����C ��(�4+x>��V_!]�a�H%h��`�|��0~�Ѡwi3��h���(;�ye.E���=�`"Z����v�T�l�/֏�ɭ��f��w,j�f]�����D��~7$�L0՛�,8�Y!!��8!�p&ڦ�R_g�ֳ#t�y�����Gj���CH��P�� �Li oQUk:v9�����kE���ng�A��)a^4Z���/N�jF%����őA[u�4�Y �1f���í������;����6�N/c�֩+�/��(%(wwt�8��1���M2~Ckǭ�$f���pF� I|�W!T�[��.˫͟}E;J6K�m�G-�*7تJ��"�v ��_e��n=��INӲ���]>;��C�kFstȦ��7�d���j>�O�\;)��j�i `b��Q\�)c���=�eKC:�ZbF�����5���J�\!oT�9M�U1��X*�S�!D��3�[!����oM���o�2-ӷ�����d��m.�I�&#���P��n�Q�U���}�W�n-�6e����(��N7��,6h�ýׄn#�,d��k:��j�Q��vH�I:Ð6D�k�yX/��*��͕?��:SE�6�T_�D鹞�}@���ْ)G����j=��($�� M>�=c��\���԰�h6���Kp���-3��^+���@�>��2��K3m�6ԡDq��zZ�!uN���� ��y���#k����v���E�'!�k���\9F�^i�����ִ�˾�eȩV�O�ܴm������i]���k� �� t�����Ca?��yp����3<%~0Nt��|m��H7$���ut�fRi�}��;h���z��tq.zo�Ӊ��B��ժ� �d�BXh���+q��(�^s΄�g��mđz}��j�0� �/���ti�ۼ_1�Fc�n�5�o�겤��k�}��q���_�jJ�$H����ȼSf(�ҝ�)s)�*�����*e����U��� W���5[��d4�$%�r�\������{��铥 �-y? F���Zoq�=a�NѵY-p��@a/��2)�-y� A�w�o�4�}�T�O �vS������쌄� L�d_��Q"�N�ʳ�_�J�]�``Q��T������VʥI��\k��i��[E��GX8 �E�Z�C �G�"� U��g��=� n0��)ZDk�HdL�����Sa�Y�XW��w�A i�bn�Y����d��S�� s.�QT��a�o,��L R�2���{�ԉǖ��ExM�� ��rs�[�̌X ^��z��賾��,�ߚq��2�t � �͟I���]\��ǂ�ѝP��Ζ��<�?D$���=b�d*h��]:m�m�%����w*˸�XU��H6�sBO *Y��2��m�Z��t E1�<�����z���J e[�9$W$�K�h7�W��U�����`:t0;��s��x�Z���V;�5q�CB�xs�t� a���/�������T�(0�&�ӆ����������������X�-r��*%���\F}z /7��`A?!}�k'V;ˇ�[�H7q��*G�/���J]�����_ܟ�W���/"2*��On�#����I�^zH�!3���kv�D��9��HeTY<#�l��/@7�b �/�*}$,����A��#/�)�:�Z$��g(+�e��X2��#P=���r�Tj ��Tȟk]�;럙��<��H��a�~2)S%�v���>�9���5� Z�SY�� ?��?�D��ū�n�=��!���hv`���b�gd�ML�����)���9F+�f�1X��8۠���pe����$L�.g���-4��*D�����2A�Zٲ� ޜ� �����K���x�4+�3��;�K�kA���R8�ͻ��S]�oUf>��z�~A�^��S�fFjz'�O���iaNx���j@7�r᭍����pw���Y��Ntʏ�q;x�+�)�&��ﶓ %"'�ߛ������ ��O9P ��ݫpL�q<�g���� ߑ�xl��=��+l�ĺ��S�q��qfGEI�=ب��ɪ[��=�7ʲ��V �U�LP'�N̳�6-���m�v��A~7}�W��9p�4=�I��;�+f|c�f�����P���)�$��pz��c�7K�M�H�Ňd�[cU�4����&x��Y�p��-WT6�O��޷ӯ��(M����x�R�0�葸���k_{�r��ˍ�_���Z3Ԩ$+�ئ�LJ=�����H 鷜�a#�Pq��b;�!9dŮs9>[�Hʨ'��m����]'�Q�<�~T[� N-PIŸ�ɺ�� x�LA���Kzg=��Y�C3HW��{���M������h1FfL\K�v7�����W�[|��扯�� �j� �\�*�z��Q�����lu�Kܞ�[j�Y,�=FyE!\s_���I�2�� �,�!��l������05��'*x�� blV�dQ!j(�?�ʯ�6}�;n�]���h�T6�ڌ��ƹ󨜎=׀����.\�3�R_܅k/o��z�z�S�ׅن�#=�+�s��d)V���O��zhXѵ傃�H'���\4� �9B���5E|~.< ��y�tZ#O[�H *�eˈ�F��/%E�D,�WxΠ��N��H��C_q =�L�#� ��Ҡ62�[�)�),E2��L� �i�3�F�iO Cn=�MD�r�Iʛ-������P�N�G�n����ݓ@!��Ṭu��sl3,�L�A��O"ݙ�4尬��P��_���hO���Ȟz���U�$_�`PX�eK]��ٞ�(�g ���(�����%+��GB�=TIn��TD��]�v��_�v\�/L��]Δ�ٸ�y7-�=6%DŽ�9#v�Ov��9O�����41�������b����~�AT�������P���(g��?ن�~�2�(Q�Gvn葐�m �_��7�e�x��K�k�;X ��>�%� ;��ڤF�?�U�8*'1�� �N��xv��O�񖵑�9� ���1�f�#N�z|�]��ZDf�ۧ�۟8�Ϳ�F�䔷���Z�7�������+�Q��2I�����怳�Ix��m��Pr:UY m�g <)h��Es�\�����?�?�Mr���%9$1Tc��K-Jh������^�=��h��yB�)����Y9��t�*�QQ��H6���K�)r5�0��6��W� KA����8 �Tf4(=� =Fs�����x]�ٯ��uUfg�c�7}B#)޿�2������x]x�\�6NB���ɳ}��꿧yYV�Hp��l$,�iIUm�{Q� �k�T$󥇧ja�E��6b�^2�Ϛ�}���8׍� up��HgW�!�8�J�bS��? ��P��?��(�>�R�ϿPx��Rq(�^\/��|�;��_�5�I��A�@�"�Dc�-#i3��we�?̓V��s�-�}N���Z{ф�b�w�Է�̾&4��|lɓ�P���E\ʩ�F3{X- �tiqId�����r��5�n�d�?�>��t�פ�P���T����4���c�KX�� ]�����b-�襁O��[�v�V���Be�&dlWr����/��8�r%o��`��8tf�H����4=Y0]��ƾ�=8���zSZ�t��sLJ�F�LQ�D |1i?wq�O�� �ع��DG)�,�w(E'h ��IJ�R�x�Py�Pxn=\�B��Z\%��F�Ւ+~R ���=��1��*�-�<�^yafc9~*�7WU��b* �JR���H��b6`�Z}癋�[M �C3�`��/L o�%)�����{���#7�T�Oe'iJ��Wa����@@�ϣfO��8�>�"vԯ���� kZ�K�1_o0�fl�RBnC���kq�G[j���e ���8(Z��n.�����|�/�4_�G�#�Q�=� ��f���:B�O�<5dɯrQ��*���[�"��#�.��+�I����h*���������H�/̗�����m�sdc�VN�m�jf3T�dr��qB(w���w?D[UB�P%>����2���㽺r�ȴ�ݑ���^T�3�V�R$�#T�N�ߕґ�H�4a���I�~Q��ц��CT�r$�^��K�I!Y1-[���+�+N3v�g ?fJ�J�S�6��B��f���*߱�x>�'�E�9}��v)�����~)�����h�\�!�W�YCT� 8���;{t��#�^���J��BN�}{��^˜�i��d�*�t���_��`E����AfKQ�H�<�mq �/���%�aT+��b�B�ǖk�����C;�k�Dh�YU�c����60�5G,|����)���3��q,J�˚s�]�ȗܶ޳x��2�w��f��t0�f�Ά��2p�V�m×B��w�4��qY8��j��y��N5���ث�����'i�H����{�^�ƪ|�B?u�����rQ朵N��H o����v;u�������{M���۳�:M�x�="�R8&HV@������I� ����%E(�=��!(��$(G?�V�-V�_> �����n�7��+[H���Z�(�^8��c��UW�IЎ`�H��}K!� �wG����� Fŧj�؍/j}O��)��5PXx��X6����J����oR&92�廑R ���Yf"��`V'�ɠ�l�S+����,º-r�F�Nж�5qH��sP��>9'%[�ǵ~ĉb ��>����h��j��,���g*��5"�c5����Hڿ���ܨ}�%)YUY Lo�����h�01QJˆ�< ��� ��-�H!�F y~/�����n_0��*}�w�0�R����c��IH�t� �D�NZ�!y�>�[�;e�$M'=�rKC��_t�p�*����%'~-'����m��i{C��p$��~�yK�?�h�6����Kx%�����D�jeI���꟔��J�6Ϋ�/���7'��dǙȚ���b������*�LΥ5��|sk𝵶��)��|�����і��׏f���)J5viIg��q�e��5�q���Q�q�B�}�o�f�� �7��jc�/*_Χ��O%��p@E�I?�b����i��k}�')���z��>����`@��i&d��3��Б�le�q�p[i��jy����n��S��gG����a����;���?� RG�(�� F<֝�J%c��ki��\�i�b��n��T\c�I�,z"^���-wƃ��,[ J�����+�Ӎ[����ᡥ�9���4G@҂����8��ݑ��C4m��e1ע�b�Y���gr�N�e�$˓����@� F.>�s���bO�+�"��~��z���W�WE�m��9y��{ 4:���a_�Â�o�X��DI��LuO���T�q9��_���������+<�Zl�$5x+�sX�,�r��ӿq[ �p�����z�s(�oUz��5ʪL��9[�m�|j�\9��1N ����.h�kz�̎�(!��p��8k��.������9б?�щG�PP�zq����w��ԇ�6�Ϟjf%��J�]��$�[�5|���5%����Ռ�P��>��{Ă'��ʼn-;/%L +�7& ���Pf��f�2'��fA�L�5�m�sK��4 � .��mX�w\e������>�}E�?-�y��1�{H���v�:�?n�nC�Z���5�n�Gq����/%�q�%ҩlYJz i�Ee��[^���Nb���u\�� n� j&Rܸq.С9cf��<��T��Q�R���!�̝N��pP,�`gԃJa�� '-�_VX"�[�Cr�e��^��;qB�f~ �P6pnS%x��c��l���U��� � 2�H���1��0�PW3������G����%�a���g�R`����P�W���}��ƫmR��%F�$GH�>������54Sa�*���b{��.��`�����&��qS��~�Fgn�,6�Z�::����i�����N��K�H�?D�R�;��Ť��X��T%��4k���t�J������M,����q���R���r�ojk�_20�Z��˯d2'�������&��`����'���2�*,��b�X�8W崔�/r^fCK�@�9PѨ�x�����,��lv�4�Oʪ畞�A �堬J�t�w�گ��H̆>�[��T<������bh ^����Y�b��f� �-Oc:��H==Wv�=p��p���k{?�Ws��K��04���7c%<.���sR�M�� �)Q���2�Eie�.ޓ1K�E�%�c�X���s� �@m�J��ư `����y�G4s9Cg�m,U=oV�/��O��K��z�$�0 TY�m�_^w���S3��V�9�!$��������ϐ N(D�ɍ�5%�sv��_�Ξ����؟͑�p9��ư�OX3kI����C�އGc�ꃗ�Ѷ2��8�ì[�� �ucʻ� ��FM ����d�������������vo���3z���5D�+����W��\��O�d�*�ȩ� 5��N�? zZ-�i�������]��Ŧ7!��:�4P�b�:�*������E> 7���L|���u��d��I=I���9�@�+ �&Y�`���l�s��}�5/��xw��!��[Mq�qu�[�0�OW[�d9�&��^?ϥڵ6�]ނG�&TYo�}:�h�k��ɽT[�Õ��(H�ua�nmB��Y�y���wE���&���1��Z��qt4t�Iդđ��:�Vr�����[<"4�ɳד��Os�P4���ɚ��� ��|B�APG�z4�~������ba��0��*��ֈy�Z��:������k�j<�.�k-�F�{������MC�"({nd���ث8��+�6��"�0 �޼�Uv�>�*��g�ћ��1L�'Z���3�a���N��f��-/�E[;��~|z��!_El�R����p��� �ݸB�+���^"��X�*�<���=�%�H@��Ǭ+v-B ��X͋�H,L"8��c�����k\l ߔ���=�=��f�\6�am��=L:�Ϭ��>�%�J6$�� �z>@ W8H_]a8�q��қ��9oޚ�s�ή�(X�Ɗ�f �Z�Y9c�Vjh���f�� q�G�S�k������0�m�n���'������Z>X�i[ �}�?��$�����Z+{�B�ܵ�00&�-��ط�9�2!���s�S��֏�(K�ø3!� �k�V����a�!��??t�޿L�~���i� ���"A�.u�jbj�8��a~_��`���j ���Hº���?�1�Қ��%� Ʀ�I �������}�?��^佬��ŲL�W9‹[�vO�-^lsy3��U�3���������*�X�� ��1PG�[��%��� �W1���3e�U�}���ʎ�l1K�" ^�r�M��~E9�K�~D��a֠��7w�E�Y�H�%R�3�m_�59�r�)�eHR�,UP���P0 ���,����t0|"WU���i��>=V�RR���-�Ϻߘ�IZ���+�cWV�51c�;�ʔ�ۋl�IBgR�SN�+'̩�W|�c��0��1�ș�'+�$�F�M�«" �7+���X�`$��&���@����.��*F�C�Z&��^ �x[�ˋZ?�t�^a �!i���t�.P����Cu=���@< �I�����r4�`�� endstream endobj 2536 0 obj << /Length1 2287 /Length2 16917 /Length3 0 /Length 18260 /Filter /FlateDecode >> stream xڌ�P�� ��| ���������� �n��!�kp�&�;�s�������+�`V�^�w��*ȈU�L퍁��v.tL��9&F## =##3���� �82u������?BD��F.6Q#��H9{;��� ����������`fd��O��7@���� G���:Ñ��;x:Y�[�|���J*���![�����@���h�q��� @������?%(y-\\�����l������h�.e�3�� h �K4@���m�pdU K�yT��\܍������ ���#�����8�"% Pp��+X�_��w�D���r���������F&&��Fv��v�3K @A\���Å`dg�W�����G��������G��܍�BJ����l�d���L�li�H���|�Y��T���h�� �?QK'��G�=�s��v��v���f�v�f 1uu`P��ttJ��;����ft�1rr�22������_G�z:�v2�e�P���`�0���4~���v6r\�\����t�/�cb�Z�����vp���f��#�d��a��@&�_?����1d��v6����e!muM5��h��WX����� �cfc01rp8>>��oE#���G����=�Z��h�8��{ (��$T��-&o�1�@�a�edc4�����y��N��7�U���KI������G���Z�x�;�c|]]>VA��c!��o��_ ,4�t���^)����3��o/-��-=����.&�������7K;�����_O �������>�����q�����?6���[� ?v�)�ٙ؛��|�l�#''#O����@l�𱥦@��G�@og����� 0�w�����>��/ӿ;�A��0��A��?� � �_��`��� 3�A�b0H�A��?胋���E���"�}p���>�(�q~pQ��>�(�A\���.*��?胋���E��8]���<�?胧����俈�#�������c�kL�?��������o�I�����ş�f�n�H�if���!���E��~(��t���և������?��F��Y6���m���'��Oe��T��A���C��2���������Q�����h��+�L��:�o�>�A�t��C��&!��?T�}�;<�>d�)��1�X8���6.���H�P�������G�?�?�^@�e��J��:}hq��!����࿿\�@� �꒽ O�U}H�C��;��/�y��&3�T�>�ː؜�N�Jv�� ��A&q}�yaLJ���k��FO�;:"�#s"�/K�w� I���$Kȭ ��„ܥNC ��(����C*d�>�+I��e�ҡ��ݽueY�X�\�'��.m�#��l7�(rwm���F��g���v?�%�עlYG$��v ڿ sA��e��U_/@z�-u����m,�.��t��}�H �V�Ry��� �zZt�Jk�H0�� �¬�0VjMܤ&KE��;��8<�̠mE��]��6u�,�w疐�F�����d��jY���k:/���d���<.@���7£���%g4B�uȊ?(HW�Ur}}�GՇ�e���<�PT��f%޽�"�~����.+f��G�ÓՃ� Vɉ<�"8]��<"�xݟ �B!Qm�sp�4���ޓI LH�9�)�t�]K����:�!U+w�SC�M��3��G��(�lbr�XÐ�x�io�����B�b�(�aӈ��� �}�[� �;k+ �U _���"�S��gi�N*���k1��˘3 ����(����.���ոV��+�2LlZ�{�++21��A<�`J��Y�A�Zw�o�{\�]>�l�x:�K�r��C� �ՠ����_����~r�� nb���Ç�����|�5���:�=�rVV�ƲQ��Nϰ�[�D�(jd�C8d�φ ��0�Wφd��ڙ�F�~����. �U�5v!���k�>�J���[0�D�W��Y$�:vg�g0�� 6W��sz���W��ǗAz�5�a+|D.U��-FZh���vU닚l��bir���a ���9�C�KpZ��0pO�K܏Dv-�K��h�D3�S�}�PÚ���̌����C����@�� {���e��F;p?3^��}谋��������#�*Zv��썃Jc<\�8w�ǝ���wEI,�A��?� N���a�F[2�ѕ�+.N�˩���5W/�� �'���;�܈s%��Ƌ�^d�*h� ��^F����-[(��!��i�o���A]q's�I;k��� -�,��Iӄ���>�� �nC0���D��yf}?��0�$�d*��2�p��-�����pU�*]x���5��'TPDd���37O�zGK��u-������g�oV�#\�I��޽V�C���������%�*3�8���bYET�z�����#"\�m�ˏp��� ��2S6b���ȚD[�н�M�M��Xj��}�ҝ�j��� `�&+D�����۝��I�{o��'��E���V‹�K�2:=|f�E�Z����w����p����uV�r��z����^��V���s���L�P�sN䕾�R��������iI�z�� �(A�l�> �K�[+T;L�\Q �/ț�����ζ=�1�L������fc��ƶU/_�~ߠ�F���D�4�3;ƅ�>��>�v4�B��)GASϯQ��b�FQ# �K���ԦݲiNȦLD����or��Gox��=��Z����E9�۶��f�:�-�L�" 48<]���� �B?V�R�b�����`,Q��N��ˇ��*���¹��N|g��)W�����E�'��l蘳�E`;��A�ZmtM�Y@`(���,E^є�a�t�������=va J��Pm�K������~�?�D����-����}�7qT��٭�Y��[g�ϯ�F�$�E����-a R�Q,!�*+��j�E�>��S0=�c�G*}Z���уs$�AzF����q���G�9�0��°�#{�[�+E����{��XN* �I@o"l�J:����0m�Ȑ��� ]:�O�a�'�� ȁ��O���/���qn i�~{�c6���/:~���B�Y%��'s��a��WK�K��>��8=�;V N<�E��^Q�bI����2E��sGL����RW�\-�l�.�x�9���?;�Oj>����ZA�b���z��aj��y�"����k��®d=����$�&�%��C԰`�n��,Y����[�X ) ���A�F��lR�� �����w�t5ye�/*��S�J�;G�����pR��hWb���M�e��ܳ# {��޼�������H����A��9�\H��Z�5n3f.@.:t #�S�5��U�*�����s]��pA�+�a����� ���B�7E_Ѕ��`�/�ʼn!0qms:��-�1�1h��jP��8>���^�1�v~��4y�qg[���e�Q #�@X~\,�&D$�7�ԮŎq�) u^U:�oh�L��7�j_U�qfpu�U�j�v�Ai�-R��DO}���W����c�:"����&��|~��vيI��L��G�W��9��I�7�l�/���sۦ� ��k���S�� :� <���?����%Y��Dm���S��*�sђ�+��3��o�Y� �6���g=SE3�9uN[��9�D]Dv��F� �N��X�V 8O��<�,J"c4� ��zG�4�$�UW@���%�c����링ʉ�,��)l9(RH7�A‡o�zb���F�p�;�/�{�|��.�W�hѝ���]��ɹ�u�o�{�y�o��uV99U�rȐ���w�|Ⱥ�����f���7CNc������9U�.]�� ��˙ᴔ��J�k�~LW6r� �f�~��U�K%g)�Y��#i���"w��`,�T輩�ǪX���Ry��n�kqw-d[�c�M�*T��j���6?u�O-y�<�,$6X����[�f ja��V�6q�y��3��q��Ȩ��3˗�k�F�g��?�*6��긞�w���7�%�o���K�<���z7� ֐�n��~AV�0*8����P$'�:jaT�U� {|��E��i���{X��+zo0B�l:;ޡ�D��l�� )��0�"��Uz�`l>Թb>�s4�*�<����)���&�`U �(Bz޺B�&�ߣ�� λ��s:�0s���C?;��Z|�g��_|��( 03`M� �%�����`�W����JX��n���ݧT��+I�R�[6�?���� �� ��b�{-���5G��j+M}��Њ��m{��i�:T^�9��'#Uq䷷kxwh��y�;B6�(��a�ٓCf�>?�G�j6TA ��ݼ:qHZ�� ���d�/��p��q�q��5g�;o%��0�=��V^�nlT��%I�!獦"��Ô����N�wUB�b�T��ѳ�QT�o�tjÀ�[�7� �Pڂ�o[���e%enb� ؂"K��+A��l��A��a�"kP����"����3 ���*d�F:� ���,zȽ���WX #�V^�!֐�r�]SK���g5�A�St#C�� '��ڒ�)39rq: Zq��f�-���D�0�TM�ln` �X�)�ќ����[N�ظ-��m��<]1�Tx9��kѕ��z�cKX�)l�̴��|���딀����/�b� f��&�Jz��_p,�Q����Shє=��� �Kw��3M� �z.ۭ /܀H��_�U�k��/���M�1��-��|բ4l��$�� y�w�i�N"����I��=_��a��h�ٚ�ߵ`�a&��{��1�����$@���i�0��3��[������e���-�r�a7����c�t��M��'��W])}�;Y(L�u�a��P�k��O�m�w��E�� �zB����]iS� ����O��G��̼'�I���x�ֶ2�TGe���Y����̽˪���It�1�)_�{e D4�a T%U=�#,�]�P�UH�,rp�b>&�����"z�s����}^����ա��vw&ָ��ƸD�c%�)SVZ5�^u����zo�H���+7g�H<і���mx��[��`���#e���ʁ��ԧz����r!9��_���>��Q�T���C���:��7��.`u��Jw;���΄���Ŕ몥��m{��;�!�Y+R�z�򳕳���<�������=� Mߌ�g����At �jd�|��·p_�\(��=�DЦcP�7�,�j�)L�B�?0�J��rY+F�����fSP�57��۹id�ӱ��`@I�s�p����a���'����g\Qn�)?���y� m��D��/�, ^�̝��@̒5W!@Ǒ�mC9������#ޝ�w9�^�ͯ۠ ���3x�+����o��㊥���Çx�W��2m)��A��7��M�CaK�I~_XFB�'b\2׬,O��q����1�$R̚�RrRb�aray��;cX��{���w�G�d�k��8������a*�� ѷv��n�� *s@N��gS�����R�A�5���w|��p�>Oy��Á��� ���G����B%-��p�.�4oN������݂EM{n}��1$��E}�0]�=Q.{�b��,+f�Y��g��"ڳ�ə��4Ax<��dH����(�[�U<��}gTɄ���N/c�tCj���k݆du�Q'rO��፮�r��ƕ!d�f��ϊ��E������b��w4ui;Ѿ6����n�O�%����!l��=���ljP3�����Ѵɦf�j2� ���@� Lt������>����K����v�d-��*l�ǟs�О�9��C�||�o�E�lG-Z���/������;�z�KQ8�w2�v��Q5��`d_E��o���0xM\�s�o�f��m�oC�'��>������"�&<2���H� ៑��~�5^���&�)���LeRs�F��[�*�3��$�1�I}� ��]S�V�ؕ�]��r� ��XY�W�,�����ׯ����iʶ��8��}�S)�AC-����˫:,s�)�V�.(����O�{dc�����5&d��W�h�VW:��ny��}�-��8�[�WJoWVN�61� 鬣:����%�P�7�8����OHC"�bi�Y�iR� �o};�}���2~����np�"�����)TNP)R��5�������0�Eߢ���~s4���SugV!��p��x!meE[������WI���~ޫF ��8Lh�U����J�"K���~!8C�*�������m;���/�7�����K;t��-�9��d�I��Jk��� j�ְL��Νم2�/2�mf�$�:aA�¥1ڑ��1R�9�,V��w-\?ȯJar�.�a�b<2wa�eZ��6�S#+�H؇}t�/H���U �E�!�Fg��a�m)R[�{�-e� �:!�Jî�z��ħT�o�D�i�?Y(���I�t�7O���Dn�J5Ѹ���`��C�f����E���g�"�PC�\�͊1���8���_UX�1�ňI;�Bu�X��B��oLE�@Ͳ�\U�a5Xk� ��eD�0��(�o누;E�urx5;��A�^!�������� ��!ׅ zz��f֙ 1�p�@4Ӕ��(|��Nv��y<���X����S��-�J-�N����).��3�=�F ���{ABd��d�Ư\������Ѡ��k�r3�L%��H���s�G���&�7���.a��\a���ڊ4��� �(*ԶJ���+�h���9�-C�Y�W�d�����З-[���c�?{�_U��F�9���^�n�M6�A �����>G-/۩����q�T���)��P �x.���T��W�z��Cʉ��J��D-�p��|k�a!��l�,5 ��XW?m�#��=D��7� �����s<����2����B�\+���=>İ\�k -����-t�����~�5�te���Y�����;��  �1����f�2�A�+9 @*�%40;�������Q-�����0�C��)4s�o�"Q���MEپ ?,nӤ5�9���*s��[��|F��� 4X����CǢY ;� +�9V #OԢO�9�S�/���h��}3�%�ά�`��?�4Mt��w������/?�L}���֗o�p��e�Yy>�)d&�ˊ���I�#��0�+S����ޖ"N0���9{�`L�x��D��%3Hnk(#���z�uv#p�L�G�G:��1?!2�ח�� I�R.s�d�����i���ʃ��E��,��MĜo�vPT��]m#6��QŊ�3������%,���+�!M�2�}�ڊok�侔>���;��gzB�ݤ־.��=�5�=���wK�R��1�݂j��V$��Z�&�p�<��"}�h�'��6y嵻M�s �qe��q2��R��嶸�6߅�˔\ep�A��#X~r t��Jf3|%g}���%�J7|b�Vl:$nO�ʭ%I1ڞ��(���k���1���2��^�Aw��W���{8t���'U%*Ē�pT� X�����C\D�ѱ�ls2��&�+խuU��7i�$#Ǵ���޵�%�����8٧Oo���`N ��II��5��w����� ��r��)f_?��k����7�h~C��mb�$��r��إ��b��FVa��&�,�ɉa��w���� R F�����d'-�k ������:�����L�"�esb��B�K��E�wp ��hXgN���/d�Ȏێ�S,�M�Է�����Ȃ�~���%ӆ����0t���_�Q0�&@ "H��[9����`b]�އOЙ�7f�Y��\��=�!�/��N�b�'H����&V�n������������m(x��E288*�8 ��T�ǹ�c� ��KS��G(g���(�`���]�����*hˉ������X�%���Zn�^@B����{�7ԑ �m�1�)Jؗ���2<������y��,d)��k~u�&���D�ˠV��b�,Z��0��X}�����L���b��B���e�rl� ê��Z0�H��b7d�7�H�"�-^�+3�0z��<��2s��{_U��� ��7$�R*� Wdh�/)��X�QARZEܞD�og�lؾ�y?���_{����9�ߝ�ɒԍk2-��!��{��E4<� ���b��z��sªG��� �C�/�R�"sؓ�Ζw�ciDB���=1h_���E �k���(2 �n�7���~�����?5�ߜ��z���כ��ʵFh-(�����d+�-��-�9����h Ǎ��^Z��̾-z}�l���=�)W,��Ȓ\�kB:�)p�L���bN�G�9±l���qQ�&� ؙ�/�z��w��a� ���l��O����q�Y�P��D�"rG ��wz�N0KK���U��/5:Q��U�f"p��i�xUin)�3B\S���T\Z?-h��X!Th��j �W$��-��V%�����͆07� �]���H��N��H���aUh�!"����\G��[9����;�juW܅ �&5�kƁ���G�R���S�7*v�-�>Ј#�GD����NЮp�J�$LA��=GN��r��9� �̔iڲ�>�-q�����2 L�( ��o�*�m�"Yh���3ҵ�a��ɝo|��:M�Ǝ� A�t=��3��O���{�wV)��&� �6�'��[a���ӵ������-N��k&v���aH��������T��� 5`:�+��(�IF��L:��#�A���o{�%Ž�KHȰ�]e$� ��~����>��]�. P��cl���+�[�a�� z�1���ɳV��`뽂���/����R�_��!�%C���B_@z��D���!-�s/ @��J������w���)�y(E�x��J�٘�}8��\7G_S����њ_�P;�/ F�����N��AF'̎��Q8����? hq,�����&�K��dq�W'b}�o�A٠��� �ц��9�=A~9�5y�����z��1�����:��פ ��ڜ��ZD ���R���r��r��Ϩ���cy�� �ʜ�f.-٥E^�?�/`�r�e'$��8Rq��`ǘ�$�i��2N��v���=�0�������5Ɍ��z�Stv�����+q?� [�*�G����Lg`_�s�2���oG�y���~ۮ'�tɨ�˵�."1��������Q��H�<��ẝ�;@��C�B�=|q� ^��a������BRV_ i|AW_JԮu�8�|�;���V��r/-�QxC�c�SW�/F/+� 1P�R��թ�f�b*�����I����z�5FВ8��E������c�`�oљ���zZR�`���2��y�찧�*IZL,���)�TzJ�r�, E���o����wvn�Rԏ!���_��3)7�f��2H{zP�ak���hh�����6 ��^n$ii�j�3�ő*�2�����78�њ���qV�Y\��L�����fx��6L�����sq���oZZ�Y�LH��;e-���9�e��d�� -8�{�SMy�L}��ܥi�sN�5c��F��"��6WP�%ŬI+��[���H�H���'�{"ΰx�BLȞH#����`Q������]T�<��Ts����S i��m��/ܜs=���ذ@�������g�[#�h���b����a{A��E�sK[K��"��m���Cn��>18ߩR�f��M��!��V��lU"ˆ�A �7� P7�kJ�� M�PP��řZ� ��<��������d�%m �l��E]="�����t�����7���!R}��,�L�h�ނP��{*V��ɧ�U����Gf^<��� ��� ւ���j�nv��7��ouω��a�d��g�W�àsD�W�T=�8�����3.!� �<ђ�p�c ���#X��}�\z������N��\���Y�� 5×��K ���X�+�`w,z���Ix���%K��bxc�Щ�G� ��f�^(�-)�Ԙ!��5SI� ����q��uD���t3Q�2{��I��l�"��/P��EN��HH(R��#*���#Y+� �������О�F(�c ���T|~>g��� �� � W"z����<��F:�D�=�aT:$��Y�5���0�m�a�H���Z`�ùQ�X�B�U.g�x�t�Po�������РG�x�0�&\�k>�qj��Z�"�9�4\���'�Yn��G�w���h�RU$��($�i!F��h�&8��@�����w ��M���q�6���Tҕ�� ���g�t=C��G��;�c2`�l~pD�xg2���_"���{��Ѿ��� �``#Af:��{#n�z�CL. (:��/O��"0���&�|9I�IH�Eor�a%���w���u�JBQ̣�hM���|�+D��n���Ŵ3�M*���G��Ό� V~IJE���,݄����8���L���cbi88 v� � ���<�����|.�Y'�X�(ne��gŕi�������7�;��!������- _ ��$�Rц�1B��]%٧e㦤y���X�|�6�X��8�XN�*-GFj����hh� Yx��+>�q~G��%,;;LMd��1�[{��m�/8�T�R��&1�1s0 �B<1'g=dC��eP?���tx��l���NXMў0�ya_�-@Ǔ|��(��7�|�xHR�l�M_�� ��rdӺV2�毖y� �"��w�̧��3ҳx��;�R��������Ͳ]� �=��/����n.�9��fު�89�Ei���KX���*bʈ�����%�G77�2�]Y/��|Hg5xK�R��lE�h�����ך)�z?��O�� ����㌧���5�li�s,�#ʽ�o�'�������Ф�y@-�(�z�� �v���r�B�� �R�4;�6�o��8�N%���m%^̄u�=7,�?�.�8<�[�/�m�� ��+%��������:Nb���>��߫�Eou��+#Tif"�.�Џ$Y�3�&�H���'����P��W =��V�����ʿ�W�nH� ^��be�H���Ҥ:iJL�cY��)B"2��(�3��}B*/xG�{��X���>��5�%�[Na�Z�%�e�[3ClT �G�ި��+�����QJ� � �`�W�'�Yq/T  �K�0.�����8䭆؀1��K��d�U�O6�� �kOBX+��,� �j�����\ܮYBE_�1���� � �$�bfX�S����vL��u$Ո�q�cۋ�r3����.����������(��6� -�=��zE(l��^�R�]��}�� ��۞:oGEM¾���Řl@���f��c�����?�Vom �n���6ɭi����Q����{�m+�~j=�-(}�Tqo&�!B��~��/[_��^nC5�o�`���2+q^;X޿��2����P�'�a�)��3������sw9Z�^�ޕ�O��E���nMX�����l{��tlю4~�Ŷ����Z0+�H�3������t�"���rS�5A]3HN�-$����f��3].'z�]/����� � S��)� I��~�N�H��8fJ��l��_iX��w]"����2lB�����vG����:�����<�m�IW�9��=>|J�(t�:-�f�& g�V����Q�+��(_�ľ�X����c��:H!�@_6��Y梑pU*T��~P��9���3b�sJM}눆�q�(?��D���}mT��k��D���Ҋ#���9�h�I��_��' ?}���[ |2�j`����2�X���z��D�PNzA#�W��Q��gt�(�=ʼn�՚f�i[h�/���=B�/L8�j��&a1��lIX{�r8x3e��p��s6��Aj�d8�C�u�i0��A,|D\�>.R:�����"��4Z�B��(���jqa�3r�����{��ƤX �^I�7d?�̗��6��r��yĆ�� {��������*�$z�揊���s��X5�,[�C�3��,��޿�2�J�ZJm{�Q`�5�㮮Ǘ*���+��6� ���ŋ/|{)9+}����[}�TJ�T׿��Y��{|�WzF���I�{��&�+�P�9/S13�Sazg���D�w$Nd�"�s�46���)1av �\�ҚW$aa��Լ��L�����=�\�-�`�:m�O��#��SQ����n�s¾Ɖ��BN��%�� �'�v�!�#�>8-@��+W i�i�'���ְ�W�"�G1_�� -u�/'1��"W���q�"~�m�G�� �[��{A�������x��AԱ����b��j��qN��e�h�gz>��({�8w��l$��8�,�Yd��Z�L�=n{��*�����LC<�\ 3ʀ�[g�)!��[�DB��x]�r�3IRųYf�'B�_K6��$�@l�~D�0�M$����&ִ�C���}����2[���aޡ��$�`�gZ$pv�{f8ţ�����e�N�U�~�-�6��=)ծm\Pb�2�b��8�Zw�d�n����ɷlF%,��|�ջ�(SX��a5�+Y$�.#��F�8=��b%�W�c��o����xx�XQXy�Ff� }�G��23�htƣj]Y�y����h��A��޲��� ���d�WaXoL�_���>�`���s��/L�o���2�-qA_������$|���:��SrvB!�U'l��u�M�b`��o-�1k��Xף�;�zְ�ܿ�� Q-�$Ѧ<�����,�c�(���E�����H�+{VN��t�i�����gA �CZ΃�ɳ-��Aъ�1�)��|�E$�T �΀@�s�R- �ҴO��$LO�E�"1�ApŦ�E��xvusu����V�M�dWp��i�����.�nZ��Q؃�GA���d-^R,ie�/Թ� �0qQ��%���u5���]�B��/t!��w�9������eS�84�,6�1O�����6������r�ct}�{;�"x�K\q���b�eU�3��f������3��/ O�7(�l>�_��Y�ùdr��…�K�D�`�� ��W[���I�����;��[��LF��Ђ��)�� ,1�1�7��b��<4_^D;!���I��Bv$�`C�޲���Өgm�o^N!�?z=�5��hv��ZOU^��iA%��U�C0�)Ѻ����x4^�0�� t� ���.%�ʪ�>).����&KO�����<�}� � [8�@�D�%��[*K�r���YQW��D��~�@n�Zh�W�G�k��w�/��X���2�������$�+)6��ڂF�L�\��R�M�QǥN.�zֈv+7�L����\�2��-i�5m��x!����!!, !���NfOC/��G���a��b�up��~��ˢ��a������a�bKZ�7m�G��!�<������q���TWw_�N�A= ��'.Lπ��6�� �0 #ȃ튁��{<�E�L��jr��`�[�o���Xv�*NB�ͯR(Ʃ�� dpp���ܠ�+C̱s�}��7;.z�˱�I�c�����"�'Z��פ�0�-���ڰ�3�� �T�qI7ʒ�� F�V�5��������Yl�SD @ǃ'�Q#��쨝��~&�=Y��+�U�faI9b�s���ٵ���˨5�9�*J�K},�EE4~J.䒙��f�#��:qZ�Fz��3{\O�T�`��U�b}�;�:�7ʻ�{��X�i�d���K��>�R4el�י����J�g0� u�ؕy�9��|:;�ۯ^�(�5l�Jnh�ɘǮ��] ��X��c2z���]v ���Z���04>�N�,� �Ż��k#E� l\{A���]s:�+�]�W� ٲ=zf�0��g��9��2����{~K8ik������ҙ���GW� �����.E9� Z����p���L+_��L��j=/�S�a�T^��*������m�taĝ�g�Sᨋ���f67t�Q�{Q �![ǟ�W����;�c�\$4 _�/֒�9cE;�g����>��Al����^$���x�=�jo���BB�M������$);����S���vN�C����W:"C]F��ن:Z��~g�����E��[G%ޜ���D'sQ����“�*M ��V������At��5;�lP?��r��4 yD�n��vm��!C}����z��� i%)��5%Լ��ݧ�q:�qJ�]�qx�QE� ���1�Y����"ΰ(rC�f�=m����r��:#� ���6���X��O8b6��T%$Ƹ�1u�����ݡ��� �3�Ki�A�^$4�'!��?G�G�|���:�'�����O۹�>Pg#|��=�5`����)Z� ^��I������Gʿ{8�!҅�/�Ky�szH�6 �h� =< ���}��ǻw�����;Tʒ�gw��Q�a zV���}}H�p�xg�gY�>�*,&F��RQ�1�Q��N�g�[B�t�ʘ�oҮ�<)غ�u�����-7���E��-S ���E��� �3��� W�(掜��m����H��J2G�0u5��E�3a��k_Ҥ�`72/��J��x��><�ZV��m�D�����?�[��� ���|wYG���俪�k䩌n���H��r�j#��X���� q�H����m,7o-�a*z��E�|0 Jm{-���f���=0���@���J�6-��0���� M-�2 ���.Jq�`�ʬ�_mgv.�О^7ET?i�/�T�Q�ˣ� ��w��?�#���׼a��9��!S���1������U�]!w�}G�_/��E�s���� �F��o$���� �O�T "}��w / �*H�īM�ր.�VG������v��G q�4���}��͇L X�~=.�Q�{d�d�T��O�'0�f��|��AK7�)� �>�)j��c�7�-�� ��;�� ]�v: 9L[�5^���ca/3R9(�⤚<ƨ��d> stream xڍ�P�i� ��]wwww�t��w ���;�`!8 �=�� A�dw�%���95U3s�]�}w��CK���*i�ʁ��Y9�8�Ҫ�::�n6.dZZ���_2��� v��D�h��ɘ�C,U�N%'7��O��_�����!�?C��@��dPe(���nȴ�`gW���;�� ��NAA~�����@W���@����a�4wh�-A@w���`�uwwbg���b3wtc�ڈ1��@�-���h�]4@�����ؐi:� ��5�`kw/sW "pY�� >NV@W����Pw:�m�� ���8�8� ����@ ����--����N> '�5�P�Sas�vg�;Y�64wpC��=�A���r7�Ij�!%�S���+��ݍ� ��H��a }�u��;:��ݐ�'rZB�����w{9�� �ANVֿ ��pf�u�xe�1����e6@w/?� �z[ڲ����q����-�T�� vXC ����d?7sO ���������`�tXm@N���!b���2� o�1d9�?��3� ��������SfWQ��בd�_��j����?++77��O�'��o s�?i���d ��-�M����!`�gE�����.��<�/9x9,!_����/��s�;�����ߔ�<�2`���������� dx=�!�� �����5�����@+�����*��CB��2Ԭ���3��K?#��3�����9�rψ�.���� ψ���� ���®� ��®�� ���"��3��i=#��3���<#��3���=#��3����!:���� 25 7�g��ſ�� �����%�h���������3�:�/$�%�2 ��A����7��d~#�F=@R�~I������[ �p��bb�������ii��s ���8���"�!���B�h��T��1�@��c������B�9�?� w;�9�-����R���� y:��0x8����,x Y;C��G�!/�.Ϲ�F@��v�Bn��B�;���*�����?�܂�H�K�� �G�9!�|�/�� ���`�@z��`�f����9(�fw�u�q��f�{��p���xN��׻��%��ώB���I�돹���BX}�����]����]f�� ��_O�E�?��{� �D^�[ ��5�v��I�x�n�s����|��A�s��d��Q#�/'�ɿHɖ���1~��:��l����T'6N6�B�![����)"��G/qB,aZπ� e�OCZ1�1l�p0^ٍ�:< yea5���,� �]ȱ��C�����'���4���o��JF(͇�8՝�f3�}Rh�A����� �$���B�ƺ��l;�%>Af)�Σ߽`)�^Py�HM�􃔨�&��@�-AHugW| �$pj���<1�H8�qa���|OՉ0��/QDWQ�j=oPv���]�U�F���Jk�`�f�b����F� F����L>�}��y�q��[�XNM����mzݤ��C$�zm&3>T�vE;�2Ř���NJAz'Znm����O��x�K7��fu��Xf؎,u�N��Ώ��E�L/YG��+�հ��l�������͍?���c. &��ziBy1�_�[ۖ{ݛ�2��$����L�f��V�8y������P�Q�ӎg���~Cdž^f������?���>�3@��C� N�� L��v�� ����Kj��7��x5_SW�X�c�ewp��~Xzg7�z�����=�P�w��Pۛ���v��� ����R%��o=g�\Zߡ� Ԥ��3�m���Z1� S���i��:��NM��|��!| X�%5[n�� �����s���BTt�� ���������g��&���`��Ѩ�j�!.����$�Ⱦ+���pR��!���:���>ia&C?����#� �t����{�L�{铠<�Q`�|��q_)naĝ?&�Ҥ�|6����T�h�[e �p��Ĝhx�D]��'�M���% w~�B �:��( 2��|Me�ﭸ?��%��/x���9(.�_�c��E���7zo$��C�)WŤj�_0�f `H��6�§�n�W�:-�h� �<�7mEV�GPvޝ�t��3�V��4s���tqy;=�Ȅ�!�c�Z���/�5��� �V�n+&����"i�]c�4 i�rpE� �z(A��@�on}�'�O>2e6n�.�� ',����J���_��$��K��Ok������ �� F�A�Dt��N�4����tQ5�����՛37��T�.� -B�9C0� �z��)�3��#cO.�"�s��z8R���^H���P5�8���?n�-C6���t _��c��$���`#P�8��7fy+����~�9x��åz�b��z�q���@��1�=4%��Q����q��v'�� ���5�q�=�ix�N����H��5��^5��N��5f�j�Ύi좘(�O����y�Y��=}2)��*�~��2���.)#Lu��p��l;짙I��q���ѐ ;���N���f�F�����g 9�{G�ۈuلO�$Vc#����� b�(��}{�?Ӷ��g�"/�G���۱`����?v* �0���l�dw�3?␞4-�6y�bzr.7l�@�.� 7��^��[z�%Z����O���||��,Teb�ʘ�ιJ��VG}`{�`���� zPU)ǚ�+E����693�q��$w�x���Tc�}!E��+�y2,C�b.S��k��8�)���F�D}0,4i�R��H��c��v�����s�I�XuO]<�,�~B#�2���Z&>XGzUQ�Gw���-fg�[����S-������.��ߣ��b��_�]rɰ ��zDŗA��_U��Y��ݿ����r9 �ɻO��<�ؾiK��9�x���>��{h/Ju�e�*�M�/����< ���4�LM�T�ʈ)��Ïfp�e�>�:�v��r:���?�H�����E��NN�7����JE�o�� �9WD��ɑt��t+��X��-f�[�T Ѩѩ a���۹����$�a㕓uX�hwlfs��ÖD<�۳9�����L}d]��Q�j޽ И�|�;��a%{ت�"�~�<��^�7�.FI���Q�(c�/�o<��@�K��D�b5�����ȕ�:�R�0a���zz�yL�����Q~�5E�D��)��6��R���N�3D ��Q��',=�w����3�^(��ڰ���{-�N�r�)��%O7\��wNg�B�=v�`뛐T�Pv��Ny(���L���9b �Y3���K��k�*�UX+O��4��v������Ӛ� S��=B+b�50�9����w2;�Ǡ�A�oi�,�t�F� ���盧�^��S���ge>��`�E� X|"U�S�Fͭ͡�V�I��u�vL\�����ޢc �/�y/�T�p�:�N�>�|�! ���M~��}ڈ�Q.b`���,.L��Q����^ܒ�s�ix����'���I�4��*��R�l��V:�EMa�聁v?�����6-{ �h3�p�E3YĹt`!���݆�G��� "�����~�]Lw��~��ǹŶ����Ig�G����js�Y+u��,IXDL��2�\��cBe��*�Z����Z�ۜ%XȚ?�K�2ͺ�`� JrR:oQ1?�z�L}��A�&��^���0��uNמ+t��Y��P��V�s��f�춱��v�o|��k߂V�G�riq5G�YQ�r�v�=!^<���y�5��j��һ��jT�V9��/Ho.ul:V��m}����?��(vG�}���o�G��a��N�{�P�����qC�Yպ\���+�W��NL���2�~�0+o���Ϧ,Q��v��q��5��5D*��(�1��k���&w�M���C�{Dֈ㮬�Ɯ�5 �8�"-���h���§�8�0�8fЧѥ�"]ŐL�@D �u����as4��΁�y���:�����M`�vbo��0ҧ�/�4ٳ�L�b�b��n�(^Y��~���RƀB5*O�5It�a����4��&��þ ��z|On�5��qy>R���&`Z�e���d��I��gҞ��4qB�p��B4���.n�m,m��¼8پ1����3���q��L�o,G67�@e��"ڏ���\꼳��10z� c72 À�쟎�6����]����U�t%o�+u 2�YR�җ�=�Z�I��=,g��^1� C�ֹ �Lz���(z�Y�ϖ����ư�� :~�|����V��Z� ��ܼ=��I�R���*n���{�-� /C1�<�n`*�L���8B�y��Q�"��ԇrU��p�.:y�*>L�E�d�[_2S��Nnwjg��4�0�48�ۥ���X�JWL�L�KM߄͠ȇ��&ɐ�*�(�V�*�b !J6,�(���Y�������1��P5�%,��#R�V���w��������9sL4L.��灸p�}�`#���F��g���P���$Xݲ}�Z����|���i��(����hE\{�L`k�q�Jƈ�)����#�S �y~5��K���縡�;b����\_��4��oTZ�)l7�fPN�yr� �k�sd|21�=an�KJ ��xZ�_��N��\�Dȥ�,����̉/>�o���iB�51b�B�.��.>>�ɳ{�� 6�/��:U觹�u��<\�_�K�ٝ\����BM������Ul̜[�-�̈zWϷ�dn���)�@�]2%r����>+I��D����w�b�ϓ��ѱ'�/`}��,1���|�Q�Ӊ�Q�}|16��+*鏙ƢzĽz��u��������R��v � @R�Xʹ�شd�:/cz7�((���b��M2$[��Vn�� d.}��+��U���`��!T������[�p0�=�H�ݡVou�V� 6QP�N��ne�78�[`h(�0I�4Ф�I�D�-p��\�V?%��oAf��a�I�5um��;���N����:� �!�����w���Py�,�}��,4�<ө������0�`�� ���%<�?�s�I����{\�8���{�n t���Ȗ����8�(d~�|P�(feY*�/wI�r�4��L*LJ��-�pp/�,�� �$n;[)���b/8��6�������ԛ���?�� ����Y����v�f;�#U�>�_XE}��C�ɤ7iV�b��o�;#ےDgZ�?�q�a�E��S���Q��n��Wt�m���,���0駵�wH�?>ʏ~Φ'}�G�rl��,�HN�bW=QB�c��F���g��dž)�d���Gљp��W<���J�I��P\�a_؃��}�^h\ SF;k�Of��1�Y��]{��'P�J�!��r�β��x��#Âf�]�ҕ�m�In�^� D�-}aU��dgL�["�=S��:a�g�4��n �BE}!m��B�����{�/�e �փ{װ��e��k���#s�Ӗtn(F(�yi��*��ԗ ��y{r���R�S �RPʭ�u�ǯ�s�ߓ��0cua��������TD���)8Ԭ"����&y��eZ+NGBo�$e�j���6��f��L�b w���7*�W��xA�Я�]�vn�oe�M���]<�� e�[�d���͏���Lk҅��gy�Z�m\<�h�Z��G>vK_�éKav豍��A��X{����.�;�;�o�~f����[H��M���z�+��ѓ����}��~�B�.� ����h͞q������A �D�� ]Xh���Qt��Dܙk�q�{!���"����٪V�t?B�#h��w;�X���:$�ֵ�u�r����R&_8 o�x�Ġ'(��H�X?�q�K;����T����~Hhu�7� ���,�$ �_I��7U�d�f��4��uE�� 3���?�p��agI�F�2ҧ1q�8@��˧�S]/E�Fx2��z�#�3j[�1]�H��)��8C�Vx8�~3⁌�h&d0!�ɭЫ`�1�Ţ�q���0�Z�F����A����E��Yƥ��3MT����J�-����׷Lv��z<~��%Je�I���7�QA#��\���c+����^�a]B�O��X�� �Oz��mX�����l<� ��W��?�k��6�����f��B����vi���w<[e�^�e`�(ƞ��<%>���G�S-�R�R�lW���!�J͝M�\�4�dw%۱fI��d����֫*����Ď���D�5�#4�[��ڵ��V_]Jչr2W*���5���V4F1�*�2���xlN���5���e �<�K����%��7�Q�7)x#�p�_�h�L��|�#�Y\��ҡIyk͒���k�4֢�խO�l��-���]����6 ,ѝw;�W����T�\���4��뷻��/7�z�%Y��)���dJ� D��C��D��������('<�� > �|~{>k9"����vA��p:��S�����I�>|��D�s0E {���V|��+i�B��Zh�)$��e�C9H��^�ߴ�0Z�bh�p���6 `�z��.< ����͸=�eٜ��J�-��� 6�Da� O�h�|"ok7ݙM~��m��N� �2VH� Q1{K�1Xi^T�Է�*i=� n�[C���n'�D�R��1�$�hz�νk:���RR�T������{����ڋ�#_f ���%� �n A�5�L'&8{���I�k ˶�q�@{g�V�d��r�Oݥ���C�a�[s!�2�J�zP�ފ�m�PRa�L���� ��{ ��z3���_LZ���N�X0O�Ig�3��9���l;�p- �<�Sm����=�0�h��Y5Y��8ƆERM��>:,���.D�[�� A��e���|��8�Ɋ�D>a�x��! ]���{X���+�J� ɛ",�~%�oF�#Z �(��FD>P�U�ٷӒ�D�,3l刲:Y�^y�ap��^�M,�rk�7鵐{�b-�â�&l��R��yj��V �:c=�~���J����%A�P�n���N�E��=o:�ʖK�U5+���R z�*���~���n2N�B���Sx[��o�F��(\@����P� �-ۑfG:;�F��Jy� �'���Z��s_��SHA&U�}{^����� ����aa�����~m��K;ğh����o�E���j���VO��{���?��>Ň�ҫ �(:ڝ�g�J-g�W�S C�mS �w�i �vc��TAd�uN����D�C/�*Pb2 1$9�(�T��~�4)}�朿Y������@��sWGq��6utν~iG�7�J ���.����e/�E�w0!��e��t�׋�/����� �ˬ �L�B17���� �>U��$��6wй���KȆ�^d�V��qN}Z(?�hEi��&�C ^�$�&]�\ߞL���/lt^5NeF|%�@���g�!��`GgkV� ��A3�n+�c]�WW?r/U��uXF�D�{L�C>,����w^B2�(S��]�<\X�9V�M�g����r����i��ن��y�p�owS(�=w�=� Y��4�n��ͳ" u�Y2���R��x���ylu�W4�Z��CN`�N\�~y_ ��ʶ�F��Щ�~��nY/zhd�M �G������y��'�U<:"�|`ܮ�J�� 5G��CX l+���7m)��O_uq>"kS����\-�� {��8� Xˬ��5o�FNx�#��-��y t��v�r0���_L�]���9/��[:��` �.c]c�d��MLJm��b�*|}U�m��.�a|�O��6A ��H!w�O���{D�o3��hJ��d��UG�t�Nn��_hأI�>�1��e�-�ԗ(�V�N";�Q~��Rs�+��q�~'��YDQ/p:�j3���Q�'�2vLy���Kk�/���+Ό���kYs_��:/V� �l�&.�����|ri#"V�����4g��2����mL���=ׁ��h�s��ߝ� !�Ƙ��w! �������7�I����Rmt�<Í���yݰ�)h�L�{+�uK����VG�(L�k%`�ne�� n{H���+"���ٶC���cA�đ��p��>!,$8|�Py%����CR��m71O��3�V�E�#Ga���8��L*��V��ӯ�C�� �H�D-����e��p�K=�����j,�i΢j���v�︓��Vc�o��P!�3��8�JSPG��B;n{�K[�ӚE�(,�֜v}eUd����̮�~LAo}D����m�̼�t�S�?ݎd(�싦z�W�&��<�Yt�&��nQ{M���j�C�9QF>�[kaۡ&��U^�a��3)Q�|1kl��;)r+�U�B�va�&@���ӂ%=&�W�T� ��+73�Wk󎌤5dR5X������[_돫��Z�e���P���Z'���:�s��D�c�,n�E�#&6Mk$�h���M���&��[�X���1�%����"�>� -��'� @�~5`�WXԄE�c� �R�4�į,C��{m�_b����v���Tt�����Ml_�X$nR�q9�C�l6���,3,�Z��X-��e"���><����}�H��'�D���k K�����j����� �k��W��Zj�h��t �x���l�w��Ӏ\�z!�T�j�@�+� �������pX ���~HjP�D}h �w^�Y?��ᘙYI3��|ͧ�BX�����-�ud2��K���Q� �B���O��7�b���ݑC�"H���8 �K�q}q�;�L�1��*$�OY��aIx�s܉"���n���>W:`Ч�N9xDFS�b߈3N��ēXd8>�*y�B�`��N���ؙ�� �@�gGg[��ᖵ>�m�o=1&�B_�f���+d(WcĴ�����M�$����"�V{��l����� �an)�(X�3�deR?;�kj�k #� 5&�W��d�lK�� �h�|�" �����e��ړ����c&%��I�ȱi���[L����ô.��x����#�i}�|��^���Ĩ4����w��?z�����.~���`�X�K���a�D�v��?2m]l�G<���+z`Y���Z�`�GK�Q!�w���z_h�ӛ�4����ۈ��cMb�8:�m��vK�.u�څ�mE��$)\�� S�z����]�U�a���w�\=a�$_�㏳�0F��@����+�u&�q �hެ���#v@e��v��&K���-�j�1���,ݙѤ5�~�L I����Ik����ip�;�a_��&� �J�W3V�����M�6�#2�� 'V2�t��Z�)P'=�HVZ�כ�- G��cwvy���f���U��&ћ�QB�[��?�X��]�E��.�`0�b�q<�7�o�,T�h����&G&H�_*?����U�s�`|C�[��`(8_����*(g�f( q~( }���U���u���S���Ō�w�~/�ޤEz��K�o�Ѭ�h� >I3�l���u��+����!�%�ڑMI}����ۏӹ*['��_;(�kǓS*��j��p�n���m+̕~7�2�L��p�����ڣ���w��1,��K�S��$�� �����A|�����U�{�(X[�*�zƺ�$ -_ib�K�2���.�&LEϹ�l�xx0*�y,v� ��H�rᴞ�8� υ)���)�~D�!/�\I]�e���L��:}=�g6�(raQTgIq,���|�4׿]�!���8>�X_��b���vة�����z�]i�r��A��[��e��(!��Gk�.x��FU;�R�y�0#�Vw������������2�5�������KS���X��f��Z���7l�w�oW�Ih�� ���D��v D#�-��d�%�;4�Kf\y�j����}�5 �L��(VV��e<+c��� `ʄ���X����d��Q�uS5�X �����&K~����.��u+���T���D�"iz ;�}�� zV� +���V�޸�\JB�>�E�q���x,�+���(���[���E~��]�X�C�2,����!P'ɕ�o�����P�{v��"]�G�� x}'t�7�1p��N�������\ײ4�7]�I�l�T�1c�v ?��vq�Q�f��  ��6�?q@�w^��&�E�M6-Yy'����.Q}�*UQծ�dn��fH�\���IU�� t6��/�;�J�H��@��%�YW!�!�.���l�k���rʯ̓�� x��l2�6���'(���٬VйK�=<'tF%�<�\�~���Um���[}|n$���\L���Vb� ��&��բ XR��>��߶���)y<��^��y�/����MӸ���v_u��۽����<=]�mڍb0����g^����Sԩ�ζX($�)W���L��������̝�U��u��p@\��ҹRߍ��5L��y���m�\h���v�s3��������fL�����Zߜ��f��efXF%�i.�;��K���*�O��So��(8H�N�6��n�WN�{͞�m��w5��u$�K�k�b���x@��H���F%���[�A�,�iW̩�G���ᆺ5YdT ���&�}��Y���lNǘZ�l���M���I5Ҋ��� �p��Q��EE�(��3���&��$���f�o�R�Wh�=$��,S4"5��dst�����8�Nds���x��&%������ �3G#� m3�F�2��͞n_�}��,�; 0(RR ��"GMlT���[iW�G�u ��EM풜�Fy���\��@�=`��<=�ũX�ä� ��h��%S����ǀ��V�����GN0������Y��ք���)j��r�r�`Ac��K�3�����h�;�@2<�8тoP�UYBS�'!�i}�M^)�JcvY��Y���C��x�lTl�\<8$4�S���ˇ8�[���0 {���co��.� ��Թ�Ǽ��XǭD�ۛ���Ø�I�U�f��@A@�%)t_n���}z�X�� ���tN�o���iI����n�$�� �R� ���>�@ a\��`��{�6_����/�lh��zoe� U%WGr?�������w��LM����1��'�v#��hfB��?����V�B���釅�4��(��B]=>��dӸ�О�������.�0�ttd�� ��Oɵ{�%�-�Ґd���{ ���9x�?�̢A#A��/�/���|lӪ0S��!-��6"��g:����})���WJ��d=N��E��i|ʬ��g=*c��;�ˇ�8�����^6��~p0?��"� M���p��l��׌qy�#у� e�'_�xWU�:�� �J�2pO��9id�p�^����h����������������C�\��F� 8Ճ��̵> �j����S��G�(�Nu={'N�����RG��["#DE8�3C{F~���^Y���a�ɚ�57f���e���(������g���ƫ� %\��f8V���$Ԋ�tGӆ�9E�8g�#��7�U���j1�&A6,N�o�Z��v����5EO%.����XT�[�p��ڷ/ii�R�)]�G�� ����,���t�q/)�ɏC�U�c���:E+ñ���C����o�OnZ:a�H�%2��iW��;�3t [�\��ν��5'h���/��Z�w⮣M�^�ScPe4)l?�܈{�f�;e����{�WpDćܯ_׊�>L�d6�������}��漬SP`OV�K����������)&�Z^�ya�/���$�л&��׺��?:w���~�eEP��pP���KV����r��g�l���!���Q����?���="� v��Y����E�b�G���pisT��f U�1��-5xz3����x��]�K���쳚�"c�p��oe���~����#��x��P%����V�5ٝq�W���P���B�Vd�ce7�`���Mmx���W-�cxJEԮ�;«׵Y�b�~W�K��.�1<�c�7C�ݾ�,�5�Xl�,|e��b<�j#��K���&�t�����ꌡ�cw2;W��Y�*rõ� �ժ�Z�*���q����k|�Rd�r8~���b��G���} #M�'8�"X�K��� ꮏnz�P�XHTTPH��>�S�L ��b38b��,#kz R� b@a�}�B)y9�K�b#^g�~ �i�=6�m]����ȉ��1��P>�H�>r�^:���]�z��5e�-�u�ځwҀǞ* k�v]�lu�k��jXJ��#�F��5x�h��a�ְ�Z��-�F2p��$�~�X��j_��{����C+c� ���Zo��K��4Mj|>M���Q��Ǿ�a����� � ���Pk�-  X�`IG-�q����J#��H;"����������#��. endstream endobj 2540 0 obj << /Length1 1493 /Length2 7178 /Length3 0 /Length 8183 /Filter /FlateDecode >> stream xڍwT�[�5�t "����I��*]�J�Ћ �{�E�J� M�"�t� E���_�����������<3�g��s��������� � ���cx�� 1����*��yA >66}� ������B�p� �QP�S�`�@M�����Bb`a1���D�� 7� @����C�$l��' fg�����#�Ú~�{:@���YC�M��]���CXà������`�b@���;/�͋@�Iq>��0�](�r��~QhA��R�%a������w �:�`�P8�� �����z�m$�X��#�����S���_�`�ߓ!��g$� ��laNP���/�����B��l>� s�Xa��(�� X��C[�`H � s���� v��6�gg(�&�՟ ���'���u�#���Y�0���/6�H��� UU��u���b� a~A�����Z@� �=���r��F"�[, �/���!�FCܠ �������-0`����v08��ձn��6��Q0� +?0���'3��lp'Ͽ�1PI�XQS��O�� ��!<�<�|>A c|�]�1�g��U��"�����Q����8��N���i!�҅8�V�)Hd������{��O濪��J�\��~�s���g����t]1�1�D`���P#��� ���:�wT���,�+i�/H�? ���<�a�����~�_��C#а_W 6 ��vʬ����?B4v�0��/�����F���>>A!��x�`k ���1��z��n���`SXξ[���AcE �8!�!��x@��a���tv�����0@$��d!����n�Ba���9,����o(�jM25���P���R�ΝguP'�� �`�9�[q�b)^/+sZ���TX�ܡ]K��${~r�{����S���Iiݎ�*v����X��1=���F��F�r�bŨn�� d��6v�zlw}~������NY�$�Ԣ��QY��AE/j���.�ɪOU�������1�ˑ�a)Z�,�m�$��d���}��] �"�ܞ��d Ɛ+���+V��ݹ�)v�J��R�'�e��f�3��Zk�~eoˌ�#�C��2�6��딁9K)����_ ���a�k�J8Fv��T�ϗ}epT R���^�pUOQ5�y��H3^�t�o[k��m0n�o���+��T������y=�NY�GAcF|&"��-�RE��/�������v�����}�%,4>�����ok�c�v���GQDz-�����<�?�Z�UE�{�;/�Tx,�i�:# }˼Z�,N�GG"�Lٯ6��_DQ�6����,w�2������h�9;��ԃh��'q+ �<����Mh� k��_?�/n8�n'ԛ�M�+5��zW�9E�_M�Y4p��_?��E���ƝGռB!J�s]�L\і�k��so�#��sJ��������Ń����*���ZJ$�xE_}��:෣��ϔ��d�f�tmu����S�ް`���G��=#�4�+�Y�!{��Jh�8��l;6|{M�Zo�FU�|�d�u'�i�Q[vxZhWr��l�֔���c�fUl���q��� ;�!�g�a�;�{��4z Ay���|)�W<#������I7�������:\w���" *SQÅ���d�m���Mː ֋^@���8�>2���O�����B�1H�B�`y�>��y��x�{x�|����Fu�|�HD��y�0�6�~�I��3&3}ţw�}�~@�sҕ�M@z*ٜ�Ȋד�xd�ANF� ���l�M=s����@^�~��)A�G�gn���c�f'Ĺ���>�����xP�3���-q�ZG��5 ���IC?��I�n�6�K�tP��eult:�g�8pf5#K]�� �]}�����v�4U�1��s�=ZJxnX�x�Ҵ��~�@�-A���e�a#[�$�O�D���ώ�����M����~�Cl뺧�.���0f@�vH�{�a�� �﨩<�4��}��Y�~���"��y�h{��A�6��Y,rSOw�I�� �Lt-�C��y�R`3[ǭ���Eo��(`ni�+yg��*h����%r��7o{*�p�pBsw���2P��;]x������L{�4��_��:@��I�z~��{px o��L�zc͂��@��Å>bX����^㇏g��S��X� �!E���Y�:|O�Ũ���$�����'�ֆ�4�xB(M��0L�����k��`>3kd�H`�Zr��*��L��9�;��*Ӄ/�a���h5���q�u�� ��.-zP��"i�%�5�H���z��ڶ0��|I83,����s���rږr���)�U�8��禇E�=_�%� � +Jf�:/G]+�xM� ��Ʈ,G�-�#��Q�Ӵ����kY� K����U��E��?T��6`z!��Z�$#~�)�# �`W2� ɻ:�=-���B��Hmi�8("$��&2����\�S�z �;��rƗ�W��0RrZ7��8��gA����k��O�M@�TR�c�����O�;4b��O^���Te,4C���U���#W�]P���� t�����pD?Ӡ���,me�Ϋ)`N��=�6Qy�,S� ��V��9���Z��o�����4i+�Ი�@�IR��[�\EX��v6c��Pqa\���\�P���_�ך�g�Y�  ݜm��\���񔀛����kB�5;`�Z�O�2i��5gbK#��IA�?��ֲ���,��uy�6~�)�S�H��-�NNz��Ql���Q�3}j+ _�Ԡ�#�w�cI�<�+a*��ЇtbI��� ,�4K����?В/_��<��ߞ�J�C�3t�zku��k��Qg�¦�z�ި�^6s�R�B�@x��ƴF���3�d5U����N�>�/�Tκ.�����L���l'��D%�����|�?�� }���^��48F:��tBv�{�Ӊ���ƍ�!��\&��X�����4o�eF���c�)Ecg�p ���x��'�EޭT�@�Q߁�0��z\�'��2�Pt0�������� 5.G=��}��G��S~�L�c �l6� %˽���;�'��Z�L�����-/�r��pT��-MC��G����`��R7*˪����w�^ℐH� a�uN]s�o����qr�qT���,8����Y@���anX ~�$�$��-H�롡�]65���e�V�g]"�FďL��5>���������l���W��۝S-Q�_�xQ�D�x���&�x�J/��Y, �jM^�A����\a-�{M�� ��&�(Gu���d�W��� ��Ж$�I>�� UT9 �?�/y�[�6e�$;.��Ug,w�����(��mm��i�h�#V](�� ^YTG�����a�Ofd/E�e���e޴i�gYI�&�/iC.���o��W.�㟠�9�2�k�G�N�-D�!�p<�ki��� $�}��&���ʠ���L����~���R�t�D����HV$�C�Gφ{'&�V2+/P{=��p1h5(����nܜ��Gb��"�I��ʘ$QXZ��'��A��o��J���k���y��b]�t���(��~&O�ʽ����~�i����K)�[˪�:^I%��s��|?~)fAw��� b�pd��O���f1�����OcX�ۏ���?*Kv�������X��#��;�A�?8�P�� &��E�}��4bۡbY�R����G���@Zݙ�3�mbm~�SgkG0��{�Q����M�w��!V;���]�;ك/���R���K��j5�������s](��-~�e�)�}h��"�v\~�>Aի�&#�#d�ؾ#A^�`�l.ǔ�� �$�]b2ʣ�X��q�*���Ϟ��%�^���4^�W�?Z��}t� Gƴ��ĵ/F�I�ZC-��>%\9F�4 (+ڏ��K� ��[,��L�Z��`NE��h$@�S�t1���z�W�F����@<�Gq�v5(�V���\��JEC�E+_b�ԛ��.����,0� e��}��&�BA��k�q2͉�;|拨�B��R���べ�1��/��/_�:en���i.�z�-�V��ّS���FJ�t 7%{Y)���]�x��oR��#��M�-�nAE �X9���� ��U��׎�,��㳼�vk�hl�4h&��/߳Z��o� 2���n%��� bN��[Q }("~��˽��}�M���JI;��yq�sҧ�[�^��Qf -(?��I���0 悴s]H����]tS��:���r�������[Ԭ\ Bq�g}����́�L�R���w�G��yKl����@��K��8�2����(Xe��k�[q�o��&��� �n�{�-L�f΢�\�����y��ן�{�7 <' ��yS���3F�H�渵�e���N�^Q�7�8��,� Џ��ݼ����G�M��ۅ!7Ӯ6�M�+SH��]/=� t�b�o$u�ato>���iy�x,װ��c�k~x��ۭ5�S Õ3��nM���V5@Oj!�q�����``+.��W*9�I��u2������vGy0��m��9rPaF���?�N���Wf�|��,骸����Bı� !^�P���p�0��zʇ�dȫ_8��� VN����n��7v�<��� �[��6���]�X����C�[&�Qf:��q�͵�iA���A5 ߥ�G����]R�Խ;���-��]3I��]K+����ed��p��LY��YM&#�H�6����/K]��p-sQ�WDz�e "=�݈X.$���m��#'�b+�����n\$<;>��s(����T�/��u��/���߈�.Ef'!���������)Hr:K;%U7Š�z-~H|©�3����A,8�;m_�YA�f3g ԇk]����J���rp�N@���M��>{O���+%q ���A~�>{o�����Q�EL;�]V�-����+N�lN^�t��[��cy-u����5iŇ����$��%LJs9�2z�g>j���*�7�(}%��H+Hp�L�1+ȸ,�Nz�3�������^�w �8 ���몚GK�8�"T@M�ʆ��9��B�=���q���E�ay�V�I�9M7H�s�C��%og�T�y��K�LX�d�f s<\�$�LTW���}����a5��<����+c�-�F��p(�?�ght�M��s���*�R�8Y;7_ң���?b���"��n���Km��`Y�ꗦ�K��wIzXD�{c��6�cᥐ6Q������t��o� �o�p��M�<�� ���,�[E@��}�9�U-�u� H���W-K���'+þ�)������s AnG2x��%� M�?�����Q�8ё8�������o��8� ���FD6���K� �^����L%֎'y�����' ��%Ǵ( +�z^�M�2i�bc��lz��!�=rX��ko��n.�T!���H��>>�P����fU^A�w�:��'�sZ�J����� <H�N�1/��Rs��@$��e)�IWI���b������r�&��vz�w��&��kSZ��C�k��D�ijх�V����S�7��~� f��E���3���=�M;B'��U�߱�D] zfL�l'�PIFš֮ ��ͨ��g^*uΉ5�'�.�`}�NĬ V�A��ƉKH �^���H���e��H9��oC�u&2��3����,�$-,��E�{�M�!��J�0��LC'��uR��#i��AF ��3�x=�~%OSNs�f���~���aS?]���n��d�´i���+π���uS�o Zp�:���Q�Wn��I�ԉI{Q7{H���؅ oyD� C���]��[�N�����Y�o�iXy�X�y��J �b��Z�~/��}�j��Gܗ���e���M�T��jy{o�M�D.g�r�4Q�"d�?��]�jPk�#��?��{��r&!e��q����U�΢V�-E�Q�.H���`����- O7n���� FS�� �C�ʫ7�^�X�a�+��V�b(����+U`cR �גLmEq�3��7�p����im��C3�JR�����M<��8eDn� �iwv�.2� f=Y�y�:��j�v��0���i��c���kfW~L��cRQ)=F�ns�j��ޕ�c�gdDCQ�>�kF椯� ������l�,2ܣ�S02N<��O�x% H�����A��h��A�+������ܵ�AJO�;̳*O�̪�k���;֟�c�����,�x�� .%�_v;�2u(ɤ�#�qO��޽˓���d��ݞM{=g�D���`[��x"YbDt��L�E�E��<�OV�z9?��kGJPN��n;�Cg�3������' �hN�_<I� [��H���C � �U!}�gn��h��Z��o�Z��Ut؊c )������6e(��gg���ٛ�2M���,tt�#�y�;.jRq���Qq�;�w�-)e(�� ��|?�9�WT��|4A��z3ƒ��>��m�*�>.���uu@P&�Jlҍ�+Tj��n����y4��˒�M��r�f.L�bxٶ���:��ߟ��E����Z ����Ӡ�C�g�0;p# |1~���s�!���ϝÉ����:��C�;vlƿe��;�g+�/c�[2��jk|��K0e�2� �r �3�)S��@�������k�dgDu����Deݣ�`d�P�{���Ovu�l3�v�b ��NS�%��>�V���r���v��m�a���ij�Ǐ.�*��y�⛁��Q���d�{?,}��=qG�7�C�h����K�x=V�ؓ��x�r��9i�~��8rK`f#�����pM�|M�,�,�L;F�9��/�9c*{���d�~5���}����܇�PQ�QU��X�P/���<�� endstream endobj 2542 0 obj << /Length1 2940 /Length2 25434 /Length3 0 /Length 27063 /Filter /FlateDecode >> stream xڌ�T�Y� #���ڸ����;���Cw $Xp����ngf�!���Z�.�jzWթ��ή�Y[GO��������"�ݝ�4��݁2����Lp�6K�������� t�̬�~�W�v��d�mU���������������xn.�@�?�Ep,,sk37�)����5;� ������ �� � ���߿� @�2wt��~ ��|�D5��%�����_������������ `�-2.����Q6����ke,<����=��?�A�o.EG�j��W��3s0��>X�?K��%���;�����/!Iw;�������&��v���D��G�8��P-��C�4�v���^7� �8X���FkWIk/��������j�ۮ�{���ʎ�ֿ��h��4Zf����$ɿ\@���wK 3G��#��� 0qq1�2q|Y@�h��K�&FG7��<��� ����0��6��8A*zE\&�W� `E<&�3�I����^+�I���d^;�I���Ƚ"�W���@\_��ҿ��E�����"�W���@\�_���+q�|E .Z��E������x@\t_h�ɿ�ib�ڿ6P&{'�p�� �geq6q)����5(����4u11��an�v������f�"VP�f =�ٽ��m`�h��<~G�.�?*��( +�>sk� �t���Ƚ�)�?\X~o�77q���b���6��y��A7Ŀ���efgb���?�9�j����������Z�b����6 ���`� =^kb�mx ���������? h�׺�A�Yy;Y�� �����4�? �϶@�Q�At�2��Q*�#��9@K@�kA;9�ۛ���-�`�E��A9�X��%N�n�N�����������*�qk�?$ꏓ�����R��S��܁�]��Y_��9l���n@sS��bcu��y�����x��� f���?N��\^�s����;<�c��1(�+��o@'�j��!`�z���dr�r�1K���y:����������Q�V{�A����&���e������?f�.�v�� 4������^@3��9G3�0����ۯ"�� �c��Z�4 ��.m��Ho�h�2C�]~�$ v��lKP_ /?�5ս}ל�����h�:���0��7^x$R�KK��.�����l ��]�"�ٝI9�ֳGʫ��ly$bnWe��S��l�!V#F?�� E�i�,)�! -ڙ����i���b�x:8��X�"_� �w�>��ꬮ�为8���h#����ɲ��%E+} ^M�E�9��)+ (��U֪� ��#��,;�I�0*�>����� #R%̪�ht�j6[ �A���j�/�N ��%���� ���QPc��C����P�MDJ��`��v���g�^!KOZ +���e� ��2�Q�-�  ��G�#�I8�oȹ�=�V!3�.7T7��O�\����g��3��v�h�/���/��S�� q��$�3#��2$:���Q����gB˘�6*��K����8��ɋ�e��w�+��C�m�x jVh�|�(P!�9�f=� ���e~����QC�CGͻ� �H����\ay��U�r:\�ҤD�!�o�g�aM�N�E=H�␵��G;�=��d�)��z����-,�u�~ �z��ZӦtK ������"so�̨m�A��O_M�6��g�{~jt�dxr��׮B�3{O#��#& �.��d~;(�r]�:&��"�qM�S�n��:c��~<0�F��m3��ر4���*sM���e.1�f�'K��8�Q��U�f �?���~�8���P��؉�GΤ�)/�<��/��Q�;�Us��I�'��Y������Q���iHb,µC`�P�a���g�0j��Uѕ�$�H�x�Q�P7�'D�d���{j�d��d���(�}��?rVÑkNtOt��I��'^F3�!I�[z�Jr|�����v \r��I�pn ?e�O��1������ǖ��5����n�#"�^�F�����fUb��L��Q&'�{8�/odH�����9��F�����ʍ�S�RX~2��yw#;��F���P�ڃ�析��n��6����� ��� ����u���OXf48��7��g�9n�B���{��Տ<��Z�s���3 ǖ�~͍ i�zp;�țOUn�;�h2� � W_ݟ�0't��9�ܑ��M��Q�T|����\�d5p,�^T= �X #��������gA�YH6�)�� �XZJ"����;p�]xR�2M�ʖ�-���#0@��C=��*�h�x_7绣�@Je���0��DŽ��/� U8�a�#ܠ5Q�SXa�bJ��� E{o�~��'/q=���;ˮ�BY�5��HS�FMT�i�� �'z�X�H��M�_��p<5Y�6��$t)L4X*X���cjg�:6�������s�������t���3A|����� gЗ�jö�lba%��<�,0�s�O�ؼ��Ҷ͐�'�zu�V� ��_�}�c$�a���v� V�,h��i���k�||��6�l�K�w���T ����E2���M9��M��d���b#�1m�HT���+��*Du�k���;8�}���^�K�U�}c�;��ǰc:;_<�����G#a lN6<�ue�I\�QL��9�}�_X�h�v�cѪ���M��"�|W�F`�+Tذ45��ZG#���*���7��[�����wG�[�� l�Jn��Iު�>�Ʒk�������Z2���]%i<(�M���|�3aWa��:�³�Y��y���jh{��j�!��'��mE�~!��|���Գ2�����PE��h).ry�g�D�K�M;No�w��q�J��r��Gʣ�JDDp�<"צ��)��ouv������&vC);��ϸ��Lְ֋S�x]bp��=>"�E�9l�pތz�^M[�n,"�eYN"�z�j ������n��?�x8V�#5��i$D;_�踜� =�p�t��� W9$*GW1�r�V����o6����D��'��p�3^����^$���;������sl�Z���`Nu A��E�b���9s���|���������_B��"5 � �I���qщ�E��k����E��=9�C��X��}�[��0�M 7؄�⻙h����|?f�%視�b/����66�̟˻N�*P�i[�����{���� ];�y����$��5�6�{(0U�$���z�&QC��>��N����(����ƺ��2ޮ B �/�/֘���I��軵3N`Ϸ���F8�Ov�U��#��N�tD|˺�/�`��{��K�`�tͻ��F��F��ח�P jf�!��f�eg����lթ�βQ���?:�;,���ɋ�$j�8F�R����{�����v�'|X���: �Y����j���l_d���’�ϧ��a����*�L�N�r\�ZO�(?���5�(�� ݦ�*v�X ��=��W%��I��d���`w$3�203:�%�9�rfEU��D��#2�Aj�,7���fT+�=�y�2�ݐ5�go����T��ϛX�7���:`X���A ���xp����Yݡ ���6��Q�]1]0C�V�����&檪��mS*��z�(������ҿ^?�XL�H�d7�7�o˘� �IS&�@�&�|�p�FΒ !��֬.c�4�!��n��=����6#)�:�J1Wx�{��d�϶��q4\ܿM*U��Z�Oe��:�v�X[K����W}C�NO}�!|��<��h?�t�i��� ���b��o�|�j�.�d=�j� V���ߖ!/S�Y s���<�� �<N��ɂM7)� b�H 4��8�s��S����vk�L�lx��H��8��gƶ��=B��� ��E��e�;����s7G�w�Ӫ�l�=�m�1�}x�[.͞5��En�Rx�2u�P)��PR���yK���`��A�7r��'4;B�Ϟ���I6������Aᇂ�]��@/�S�oPo�v޹~Hev�E�E���-���NB�l��>!vb���(x�<�3וPt'��\�>�Z&��1��g����6s�Ieh�D��"�n��}-,ۑ6v�l�����Q����$s'���ѵ�W��' �i[!,�� i�t}d/�N�Ϙ�H7�p�:�d�j�\ �%$Lp ��^�I;|̆h.��"=��P�gbu{R��s�-z��ѾJ�((͜��zz�C_,֖8���2��c��c���VvY� �cI�� ����f��rjQ�@���^����%4��dż]rN�5 2po���Z��Iٟ*�t�U��4�X�zn��ͽ�>�Ӎ�L"$!$<_l��U��~O��� �J��D*U� ۀ)�Y�b�Kb��2Sԓe�F7���L�CyJ/?3 ]4ׂ�p� �6A� �l��t��e�Ar8�����MH��+R�P�[�F�W+�t�\Hό^Mw��/H�b�+���U��\e��/�i��К�nc�h�o��[f\�U��1T��d w������Ul�������ׁ�U���t��:ck�҇���v�����a�-`��� ���M��P��.LJYc�S^�8-l��#�Ġ�l1� �?�t�>��&�)�ƒO�����d���ba���z����Hn�G���{O��3K��aL�� s�����H�����E����� M� pr�R\qۤ~*� ���w�>�~�!�=�uj�QE�Ae�����D�N�����Y{p���j�e3�Wj��*.�̎�p�������mX&�2D�]��0+;&+�qGd=�����a/��Ǔ4�>~̄K}�P ��[Y�����%x��,dF��b��D�eET��'�6��<�,��{�'���@��uu�дT�z����� ]~{@���n��H�Rѭ�S�_A���'b.#�o���`�����@y�ʔcǣ �c��_�*R�U��)�� ���Y�Ǯ���8e]��V��Į":���d��D�P��7H}��C�fp�J��Ҵ��ie�I�}8r�5���l��׼��s2������# �K⨆��ϰ?�������� V��zu@����J�����%��'-%�2F�� �����&�=5�F�ND�F�<��혴(��43q���߇2���7�)S���W;掷wV�� ��b �l*[�p#A;�#HVzXb����zs��s���/��un������*#7��"���Dc�~fʶ$�&ǐHۜ�������<�� ����-l�X�`l��̭��Z��#�!B��v�����5��O�ʾ}1 ϛ��Y�-�W�Z�����! ��1��`H� ����r��߳r)W|fr#�9�7��bKGwVEE��\c�� y��#&���CH?w��6o7�%Ρp|�7�_U �b])t��<�� �z���89��C\�Duą�p�":�$n?�\��0 l܏�?�" ��vZ��K�� �ѐ)��!x�2Ur �d%�p �6����'P���R����|������1J-9vmFz����g]�v� �VÛ��&+n��w�O|M�gv��L�qޢX*y��i�3��$��i���=v�%O�e<m� #�P�ނU�G���4�g��-5���E���ف/���7���+!�x�I/>�4���MS�'9�.�}��d�FN��cܝ�1Ib��T�f��m/��/�w��bN"�mU�)�V-�O�N$�����x*����T���~��X<���cQ.�T��>��� a�iL�܁w��^������Ú�D���O_�D�e��%鑚��2�-U,�`֥���_8�Ι��#*�󈝴N�j�-,� ��ɇ�.���_�fLJ�R%��Ѭ��g��#����t��<ң��̙Ӭ�`ņl=������N���i_�Q�$̔=�=6���HӄID�RfP�XSH��F���Y�РT��8$��[Ż�&X&&�ϕ ���ם��+� ��W��(  ������5��E��6�'�pedH&e{a�,V�ݻ��'��+UC�#d�x ��=�I���__s^2�W��q���dlo�D�m֨���xO���������7DOphB}� &ߐ<��,�8\z:�9���?��XI�'U����N��]�l���13l�]�+�o��ց��w�P ; �v����҇���2��-�����:��G���`"��#y�Y#�{��G*d�0}��1�؞ �~3D��>z/T^L`1��2��!n(��[D*�xy:��f��$��~�����1�J`��d�<)���4�6)�4�Yr�[��(�K@������G#_��6g"����)�N��a8�SRL��X5���YY��m��s�����nn���x0�ت��t����#�:˭�zi����.�Ca�H� � �����b@�����l���-�I�,A>��b��l�^�_i�9���A/SW�fW|�tk����;{X�A���,_6�X�S��6K]�'�)8UH�E~������3���&ay]�5ײ9*���3��|�KNkA'2����b(n�v?����������`��5����4*�V�� †�RÛ%� �H5�Qi��y�u����T\U�1iw�bX�=[^ח��j�X��>�^��;�˽Z�^u1��t��3y(��c�c��sc���H� Z[��`6��`��O�Q`m:K=�Ofj?���B΅�7N��Ņ6ַ��1��9:�RG�͆� �4ɽ���!���ʝtߴ���J�{�."Zmg�j,��Ul\Z'���7c&�/�Y�9��a�ہ�z�q�OI��nu��Y�M �:Ѯ��6L_����}�FFU.����E��ٕ4�s�)��"�0f.ҩۃN0@k��᧯_,X� 6� qЧ�{���_'�0�u�i��Vzya��P�W���x4yG;� hg�ON���'�A�+r�����O3Y"HL�2�l�@B�]�H���*���٠Ǘ �t��� Z(��;�O��$��}���kl=�H�-��Z��R,�ө�lR*�2.��4� �w�L��L��d�"+�����yU������'�dS G��IU��� �L�JYe�+:X�}���p��;� �U� �wi�t��F0����ڥ�d_�|��a "��+-�-G��L>�3 Ɠcꞷ7\����y�����������3k7�,OĤ�������� :� ?0ڶY�D7?f�|�^���� �%�%��P���+���U�0��uc��Gd�]V��d0�t:�&���4Y�K�YB?+��zz���H"|ۇq;<5Zk�>g�f�Z��st%͗���.�n6��u� �XcF��!���`g��6�gib��5菱�,�G�P�:�?�"�3{�(�%U ߸�;j��6z������ǐ��۳9���m֣$�� Q����k�n��^�)����p��s����T���z���yH���/-���q�혠w��,/��ʣ˶2�Ug��χ�?�����l�X����xO�Ri\րi~�D����I�O�n��\���v��S���q�-j���J���LڗT�_1����W�(��aֶPt�Cuzp�fk`�� w���rA�y��SJ�vʏ�����(w )���`���L�`[���kݗ��D��ە��=�ʿ���82F>,:�d)���Y^�׹g��;uǡ�\�S���c�2}Q�3�Q�" �n�r��/��ƨ9�ˌ���1e���� ��Sc��V��-��4|��)����"MW��C<���dju�y�܏��y&��E�ۗ%�ٽU��<(�b��<�-��e���� ��Q)�A�E��b�f�N�E���Ї��EK���B�Rj�e(�ܷI3�Xpc�V� �%j��2�h㖷��=�)-��4N��j~�}l�[�:���CQ���+i�Q>E�ʾqj����yK�Ō�3T�у�(/LB:����E1��G���GnMo�Y�\d�T� Z 9St�Q?�-n��%�ψ��?�å4p����H��c���Z̲�D����P8cWȑ�s��>0E���MI�D,I����b�"��z��1�/����o���S7q+��7S�b5Jb�q6X�����r C��S_Ng#�G v&'e{��J�M�I8����;ƅ��J��f���Q3�.MuWX���%,$���:!c~��`��i_3cr@L1:��o���O��ݱ�/}��0�����Y�ImJ��P챊x��5��C��,X��z�"̅`���B��2i�v�����E��A� �vR����(:�&l�v�ޜ�M����`�����vQ?���j�d���H��3�H�;oj/��1�lЋ��e�.N�X�!��Q��#�w�a��B�t[�M̻p� .��`��-/ ��/D���]���a�_�� �N�IE����8gqbw��µq�o��Qhi[�u,q���ν��I���]ŭ{c�F]�S�-8i��X�o�cZT=�I�uU��Ü�pGpodQ�휁�x���I�%�0.� ���יA��T���޷_�=�&d!u�8�G��~��)���ʊ�M�>�,���������!�"�%���*�N���A'��ν��|qM ;j)G��<���睸D&i���N#.L�'�+VT���F�pVd�b��9� )#�)̫U�b߯Q�-zʰ|z�Pn+��ri|��431��� 4�;�WՊJb"�(dфƞ�o9��6@̳�4z��d��`"1�ը�.��o^�s�#S�| C��}����&[���ϩ�%؈P��ݶ�V�� �(5�b��9[���>�^���}�8?]��0�$aE�sk4�$��~ւ�6���j0�z�SIX�-C�vDU�;[�O�/�"�WBG���Pؙ��4lN==�lj�靏^U�~{�w������w���-/�$����K�B���{8{'(��)L-�Aۇ��{G�`�k�@�a����R���[Y���� fڮ��M���f��bo���C�ִ�ͅH� �|�uu��k��BC8�@׼۾6]X��o�!O���U��T��q���,�R�^JO7tH�OC��@)�Q�ū-��r,v��i�k�r$"0�%�& ���!�޿P���rA�5����<����#�����h�Jr�ͻ�\~�pf��*2'_�����5 �I���ʃ��ߘ:7{&^�[ ��ĥ��f��8S��T����P5���0�bG#6�7��x��#V>Rb��2E�d�(t��;�.��=�N�[���(h"|���3Tk�����KK��^3-�L�2I�mʚ.EG���`r{UL���·�t(���V�Ήl%Z�5�ϒ�U�E�U�M��q�������S/��l���X� fT �J�S:f�� �d�~��n�%%��]E,�E�Z i�L�9��[��΄-yF�6��+:�2�O�8�$s~��U=�С�љ�� 9q��˘�e��U{ �L3՛���5.�>�(~9ӹ��|���Zɩb`�hZ�~$���φq �� o;t��(ŋ<Ã�Sբ�~����d�g��jc^N�8�_h�g���Bd8ƥk!�S�����n�p�2�A� Ó�[�ï��0'� 애a�F�I\��M3�FB� ��CQ����`��-U�rߏ��5���)��'��V�� ���t�Z1Q� ��� o��U�s��g���o;O�b>��@��4Î�X~�窜I~�Y��y��t�σB�p8ar�F{���1E� ��1^$Jm�M��!�Ǔ�ѽ�(b��ɫ�\���h|3Q��-������G����Z����v�Je����rxp�b6��J�5K���]��Y:dO�t�% ���\�6��[#+(��l���%&��� �tt&D�P;O�5���g����B�P�y�p�gq|%���ǡp�����%��Ͼ�x��*��n͝��5 ��G+�<�.�e�߮u,�˾���\���M���S��N�Es�ѻ��N�����x�*[|'r��3���iΖ��W�i/)���>!��HuBw3Q��?������=ld��dhz�3������ �Ä`m0�c���G�;*@�D�۰B�ͥ�D�<�`OE�8���,N�`k�PTEt*vN`���B *�������*�� ?*L$� �|(6(%�6c�ԝ#x�#�u�,���{�7b��~M�.U���� ���K%�2e��z��Y�4Џ���4{s�c�E£g)i�D�~����Z����QַP'OҴ��_PVHd�x|��L= EV�Q����F Y��'l�G(��)�� MLp|�����|��Mw�>з�~]+�}����T{o���+�D"�f�{"���$��Jֲ��JG��'`7��%E�j��r�Ҕ+�h�||�v�Z�ZKށl��٥���*��]p+D�*P:��Gn��ŪEQz�Pk]s���rTx<�6�s�d��(�n2ٌlR]T.��^F�Zlz-�.�.'��a�^K-��S�y���Ҏ�����-Q��3y�9�ɇ˼N�»��E��_(�P�B��g n�*_���G��! ��Y�6c�r��o��(� ������<ҧ���vO�6�7E� ����'�t��r�Q��C����zڝ��.����`�U+o�#R7̮�2 kQd=>�0h�Q?5}7C�UQ�A�&k��wI�HI��k���<��-�Q9����x�i���r�����1�N�j���n$#�CCi6��{�r�Z��e�IԅD:�7 %݆�����&�\�{u���5P�� -������ ��?L?J2��2�NS[GϺ��̶p�Q1�(�Q �KT%�G����X6>i��Jp��>R�;�ǫ��~O:9b#��~[?w��WG�`(��\�����ꔜ�{� Q1nS&��."1�� �"�g+Y�ק�5J^�e�>9���I��+�~���e�ȳ�U��%<ң[�z�{'M��af+�I�!It-��PU���)����nf�u��i��G���k�* ��3��)��i�3�;?�s�5��*��l����teT�bSJ��I(�q���r #�AP ZGͣN��������W5�Q^0��#�F����b9&/ :5|�7�� E�z�MN���:�.6�5>28_�U���һ“ADž߼���2i��E�r�ҋ�\�7*�u�T�›t��!o1��<@����n}:{�l/@0y�rk��h�΄�6����F^<�OD21�%S#l���Z�i��\�x��N�:�����Ak�4��@M*^ o7�� F y�m��x̿��\ S��C�� AX`���'%|��w��d̒����I:�:k4\��6�gۄ��Xp\����i�Z�4�#.�Ȏ�U�8s63����. r�ɁiE�\��R{��\��룍�Է��΁����zC��pS����P�4�C�_߾�f�QRX��ՂW+��O�ΏK��i]ᝣCg<��eP>���C����7&��z�!�����L ː��!m%U�9�{wO�P?�Lh�RPo��M k ���e0&G���: �I���~��!G��d�"Z�񁺫��w��P���\���h��6�2����3����1,��g��;����nM$pm�G�\�m5���(!�Oa��s5�c[�ǖ���ua�&#����x_�v�[�si')� BT@� �A�2(u���^��ڶ��y��Ҵ� �ү���O��g4<K�Z� � oe�S��(PҺ�ozY��;Wg4@Ҹ"��"�I�wWA.VH@��L j���Z!��Rk�\�Y�H(2N��K�j,��9�D7��/���g�4Te�jx�(S��y"/T`yݲ����$x��e���]�|O�q��Ʋ��X�4F���G9�B͉��;!z<Th���+� \O1}�-̀r$�`����w�S�cj���#��t�(u Vak�l� e��|g ��5�}�elNo�uL�7S�C�H���Q$pi�"��9�5� ��;��3Cj���u��>�|v_���Q ֐J!�I�����e��uU)��2�h����O�_�ۢJs�"].yD�y�X��> 'CT!��+��f/���a�;)��_�t�K��T����:s;�ݮ�~��f��Y��T��a6en&�j���%���R��X�P������*�"f����;c�N�]H��][%wek�٧��h,c�3O#��y�rͿ�Z �/���ԃB�X&�moq��w��r]䓫W����UE��<�<�+SM�bX_õ�+�x��O|��vݚt@��^������3#��I��ק%�zQ&v�ɤ�SsES�q!G�+3�� �ϛ�A���U��{<�rM~�o����#�BA^Q� ����e=�/�ވ?��/Z�f4%'?�wU�U�"�� f��}E΀�Vi���o�|Mۄ�����EE�)���U�ho t+�^��[����U�*��`�Ӡ�S�TM���4�F�r���Î���8~�7:�Í���d����0�����NPPb�c�b���!Q�Śll���A.��v�e�AX�W�x�V�����F!���^"5ָy�0�X/ �Q�(a$}���ڷ�C?B��Y�w�׮��$�c�lu�Ak�Fă+QɃSɏ��[I,&�D��KU����N���K�����1X�H�`tx���2��!�}�s>�L>.g��Y��y��L_�p�\>9�--�$�_cm�5�4�&J�Ywoڗl��p�=��J���Wp$YHk0��h׾.� 6�TJX������p���G�ا��RM��I� � ӗ�����˛϶�.���|P�#<�9�~�&if� ��`�h�玡K�RY�/4vY��$�T5�6�{�&[b���#��uU�ڦP��z��3E��x'y&�tD�9�6������$"�X%j��fK�?��V�P7‚�yV;�"4ͣ<�y!�2{��v�v�Kⲅ��B �����K�3�O�i(vP#l�oL����"A�Бl�iᅟec;Uļ�p[�9�Θ��ӸvȢ�K��Bd|���J�+�]9��"� �-B�:���b��"�l7C���Q/Ì� �y���h�P�. ޿�r�O������� ��^�q�������1ψy9RЕ�~쑬Y� �Q��w1"���[fq��n��`e>�)�']��u@�-DR+��| ���J<3� ��j�\=�..xCa׈-.�Ι�L�e�Dc4�߁ �5�c��W|X �lR�~�8�26�,�iA�m����_�C˜�폪�`���Fu(�k�M0�\�gPY�� k��q"��9�ƻ�t�Fm���9�n� u�IJ$ca�z� ��x��sB�B-;�x���l��X��+ � �kC�ƪ؇V�?A��n�u�0��2ǠA& ��D�/v:= �$��QUmSŹ6E`�ϢJ)S��%��|uB�����Ӹ\��HG}A���殬�@@�=.��d�x_z� NoX���Ĭ�z���b�5�V�@C*�������� 3� jG��Aui)<�/���[��X��htI��s'�v���E��MY��S�w�U١;d��jNZ�!��~�37wLҨv�̻21�Ņ�%�:\$L��K€�ZGP�L�-� ������ 6����<���.�r�2�C��1��J��T& a2�&"�P�}�����sc"���^�\84۾�fҽ�MI�Eu�e�:_d�"�W�ߎ���T��b�E�#:@���Y;8HUian\�����x�_�|�a���!$f}��]t)¥�R����=$^;�s����3�� Q��H=�wd���rb�i���Œ v��~��/�7Lkb��A�a��ˢ���0,]F�y]�XM�ou*a��[�t��g�#\�<�F#��El 7��™�a���Ɏ�iu3&�E<*�*O��U�ӆe�㱟���biٲb��E8�2��{���������?T+0�DHg��[���.�V�� CB�RB�6f�x���\2/�l[�늯��m�R���(��#����O��-�*A�}ȟ��:�������0% ��/��}2�_вV�c[H�O]D�K��Q�~�X����_C��\��V ��-��\�2|�ٶ�]�rB.�։��|b�!�֒_�|y��'×�9"HU���w�k�(� �eH~L��]������I�S{���~�Nc�+I�H�E�-�`���lXƸ��5��6�����25X�8��U&x5�g3U������z��b��,=����2�2Rbf�:pl�����&E���8Gݦ3 �m���X+r���M��R-�MXb�پTf퇕:z���+��h��`:<�1���wTv&��l��.�X ��r��"8L��gJ���u:�yƻ��L��LƢ�i����8��Y�&� D�)x[�]� ��� �d����D�� P�Ɉ�'n��BHӊl���\D���.�K��� ��B�7sV�]��-g�� E�6�r��mVl�����*k����dTk�O�鸎o|�c�C�.=-ak�%��qQ�W���bc�Y��_~ ݉G<�Q�?�'[��_�y�/� ���0�QBhY�.4!μd���������T ���px$qSg7�s�m.�����X�̱��"�宙��!:doHO �MU�4�%S���huN�z�ђ�a�$#�n����[�0i5(+�8��Z��ϫx@[>p33P��:�x��Ou��i B��@���=d�^/�i;^��8/t�� ��~�f/�2� 4`��ћO�[,��6��16��L�М,��1D^��5q����������#LF�OA3�Q���/}��� a��������MI�4��#"��C�[�t ���nM�?"�M5L/mn�uR����V�C��Sww�haU��P��Jz;-I� �����C�����B�v�LR'�KMP,�߫>'��b�'S#u$�b� �No�R��]�? �+��";Yw�L\��K��j]���a��%~pb.�luɼx3�[����ר�'$*®é+� �(4jS����y \V���Mt�ntV�"S�CMr���*ZlΦ�J�<�!��9�8Z�F+� #�o4<'>b���RG�/��2ts@�t����wY���Jľ^_P0��E}�k��ŗKEC� # <������`(SO�>�|��“~�ΩݨC <BF$��Y���h)* 3e��Rx�J1�}�IE�Z�ja��˒]�D�|V`j��\�3�J~hs'�[��k��GAV�^��&��ja#ݰ�U9��݌x�~����`.�<�*.�bj>�>n¹����S�����+N�E�oy��.��[�6P�t��p�2��֔I�K�4��7����@`%��re�Yw{tp��w����c9Y��D����0l�!�x�z8'�m��f^�'�jC >f����ZR;�n��Fz�C��O�_��ۣ��௻q%�����k�3;���X -e����n� �P����N �,��5.�I��1hA�m���`���o�Zb~�<���.�SHj�"m���`ec�������9��6d����5�s�f=�L��J�8S%6h�V4�\���5��P���}֢*��J�Z�fQ�Lz~ s�îpZ��yX���S�p"%��� ������ ��[�ۘd��p��� _��c�l�����.2��9������O�)_e�NFL������|�Ҝ�t��3���;c�}C��]'q/��Wd���4��摪���x�0��Jz5�@��6F�W�P�f���*� �[Ꜽ�6�.�LhGdRV�_qD ���� ?[B��ˁ��Uӝ���ݵx��H�Q!�� �����"���#��8FOŤs��Cbُ��mc�審���IG^n����T8�+�z�c;��fI/�Lp���l��t)d�]m5�GXL�@�K+Y�e�J��.�/*?��A��`�ÆK�q�!T훊 F�KN՛f�ؾW s�"~�f6€=>�������8��*@y*<$� �t�r��A�JfT��� : �k�qVE>���ܹ�`�/.�c���0�M5����Q�������v��RR���j��F$$�z��j^V��&��|w ��q��� ���"��;G�����f�E~# L%��۴�[�= �����n�hɅ�����9��'�� ��>1�Pҿ��G>�Eh�l��FK�d���j�%U}p�b���+������"?/�Y���>e#9o���6�k��:���j�|���5�����1��%�)�̀l�~"+�,{��� �P��,#c;�(�  �s����3J�!ՈpY�ݶ$3�,D&3���!ǡ��gQ9��@���^&N�}��f��sk��!jyu������R1�(uE�ۊЇ�d�� �b��k�a��v���No���+��:�o�����.�� �'Z&�‰��W�Wk k��P�b��G���1�g�Gg���b�Zq�h=�>ۜ@� U[-#�9lQp�܏ő8��D��P'�wN���U���e(�;�wS��&��N�٦�,*��%V�^t빫�̔u�����\E�9�m���vn�4s��puZ?�j�C*�voi���=/Z�7�.�J?�2m��8��q�io<��]��~&��Jl��A���@C�C��e�?������L��M@���0�?kW���y�Fcy�_�F�r�^�1��SR)W�yn��7ತ�A�'����Z��G���<��0���:v����R���v�+�@��8D��a��ΰm��hd! ��m�z���ה߬j�{�����P��G��<���!-����\��\�1�?|�Rƅ����bKq%|jK����3�\8Dd��in4l8}��*�?S�X��!�{�I�n�n���g����ΤXu�:U�S�� =���������;��"%KDl�u�1���p�B�I �W�����1�D��S���܌������]"a����d���F�'9?�w�!���^ �p�Tɾ�ث��6Mñ�ě �߈���5��p�߬��!U5�y[$UM�zM�}�^x�+��L�ǝM����� � �}sE-�.GH�v����):�VF��5�-��\|��Os��$cN�D�˲��e\������W}d�͠���w��m.R��ָq��>��R��_���喑�=�4��O�x �*8� ��h�&K?hE��) Rv{ݿ�����G!G��:��ȍ.V��5k��K#K1}��he������-���W�!�31�T+Ҩע���� ��į��`��)U�Jx�b�mjW(�H��d3�{���A"`�M��oW*��$�"D��m��yT=��� J�y4J,=�!�[ܡ2��\8Go؋Wh�|�t��!<����\��N���%֑���w�Z�=��b��D  �OA�:���d�#�%^�7 ~��k�;2ȓ��]h��&- ,}�2��Ц��v ���h/Vդ�d/e��d��l�{�G���;[�ٵ��?2�r�DK�<��d:4Bi�%Ԅ�S��V�5o�m��et�Y��^Yv*l৵�օ\/FX,Ż��(�\�YpZ���[e��� R��&$���Jz�G��� .b8H���@^�� o+���aYW�<�}�g�}XZ�%��lw�b�R[�n��"?&�7`XQ�U;�K��@S$A�:�����Ec�Gc� �4�����$v%�~ �;X�?UN�R�P�{�h��Kn0 �n�%�O�ٿw�K����H��m%Fņ� Un�N��]�| �0rwe�1�,3�(��7�M=�I`WK�_ *Q�-�g?r�(�܎ʯi��'V���w Ul\�0X������p�^�Pu�r�}���u���ik ���Eѳ3R�í��"�/%̝ N��/�&/��|��c\�l۰>�Vgsc�.�Dy��!�<In5c�I=������G�Y��N�H���a����U{Z����? ��u�]��l��Y���9��Ĺ��l���d���"fS/�k�G4J�,��E:1�`�m�� Q��Js8���r�,b*��� "ل��ģܒ �:6��<.�0MO��,e�v�&͵Q�uo�4���lOdYfp�FHR����eq�S��x�F�Y{Sz�����> {Y^���0 ��ݔ�J�-~�*�o�H� y9VFQ�^ VK����g��{�@ث�M���c���a;�yiC���A<���W���x�.L^Rv�"�ic�Ԡ+'1l�<��� #���<�qr�x��yl�Ŷ� ]l�q����^ �"�t-�6�$�PO���l 02/𼰏�8��,�坜�{@݊���4aSBj��I������if�q������ӟ��"���M��0�͠��ߴ�U�F��x��T�}�$޹YnWP2�{���ڝoN�;㪐�8�f&�[�����?<�L�Ф|y�\����o�%�Kb����׫����8C,LG�{����x��8�wwE������^]zA����A=ppK�)vv����c�p�F�G�g���َ����YH�Ԧ�W�V:���Rc�EI��F�DL���`���u�%��_6Փ�3��������c�g��6Ǻ��F J�v'/�n�1r��"͔qDմ)N.ϲĸ��C�_�C���J������QYu�u)� Jޘ���S��oJ}f��fĹ��Q-&��{�h�4QV@.P<��zͽ\���Q����v]Eu�N��4�C2�c��c�@��{��G���K��;Z"�y�}�(F��8�i��e ~�8v�ٷkJ�iҽ�L��S1S{ܜ��w�I���U-������F��Y/Չ���0^�����,Q �B2>����3��Y(�nC�����mU�옯,�?�r� *L�/�]��y�(��F�-�0��TM��^@�����nq��A�;���m����̠�U�VM!s�]��)aAZ�%����b�X^�˱BwL��C�@Y�i8=��b�e�Dez��N��� �̅5Hh�O;�փ�^U�-��)�΀*� ��hc�Զ#��Op � Θ+� ]�b���eȣ^gw�a�� ���ħ���S�[]��6��B��L�l�$�P'ER�|f����c���a���@�Dg[JL�r��g�@� a,�L��uC̏S�h}�~�,?�����,�r@ܲ��B�f�"�`G�I:����Jז4��g�u���+`���Xt���;�1�r���{1�|�"�R֗���0C��y,�S*I�:��"�8T]NG|%�V!�v�:Kꍧ�_����8Q �.�gβػ#����w��~wԒ!��$`��~��Q %���K3;7�7�;�"��d�a �:�F���'-���iH�$CbsH�N�>��=�K�?o��" ��]S�6H`ɣ�W�q�����d�oRkx�^́7VP6�{���g���lG���0i�Ԛ�E�|���J�U�Ϯ��n����_7n3;�P�=�`d�wj�j�˒�r�h�n�j�FVc^�d��(�1Q�>����������k̾�2���a����#9fR!c2�Q���y�K���!O�hâ�,�� �@��N+��Sb(�6Jf��M�fPH�B��������R<�N��Y��8y������Y-���{T/�&�@����O���+� ?Anm��j��{@�����N��Kg b�嫲�2m�8>,�6�"zY�y4H�!<�[Ҽ�VM�v�_�F����!��A���n�t�Yտ�����/�����Z�ck�DN+�wD@�:��z��s��:./I'�*�Pg��H�����&/�A��(�]�*�s��=z�/��q�hAQ���,t��n�ࡘ.�R���>� B� ������3J�EA����{'����$Y��d?}sqmd̯�+�]���� o�J����R��6�0�:�G��J�]��Jw�������N}J�V��I�����\u"8e4��]{�b��A�O�Wc���K^��Ÿ2�}q7uX��PC�9�l(TA�3_���ti�jXr�+�"@��>&����h�2 ��JwV�Mg^�o����:�gCz���.����I��S�-C��|��ϫ��:�&nqkn��~s��p�'۽x3��z�����"b'��=O��y�>:�'/eV�ԧ���S��� � ȗG�7�u�@3z��$d���a/ l��ƊBX�v˭!�Jsb-���L�R��=�'�Y�֧��&h*��2Y�����#�����[U���=�N�)�W�|t����4����7�%.Ă1�[4� �@��X6�[��? q� �XQ�+�^h!�$H�4�e�p{Ū0g�-�S��|���u�{n���k`Jc��_�sn5��хᨦ�ۼQZ�f��%���cf'"#����{ؾ�Ka��vF��KMxVzj�A�^p/�C/uZ��#�Py��[�ѷ�F7���v��� 3 ���_��<�w_��O���⮠�8��y�d`U�#��W#��X"+�P,�̍�������/���NO�z����M�r��7TUPy�K����=����傕$ �(6��o��<:�v�H糷����K�|x���So-�I���e�R6>`њ؀�j5��q���s�} 90��p���7���r�Ć2�P Yz/OR��fX=����]��e���U� t���c���̒Un��,�P_k;�-�8�'10cm+D���<��\Ӊ6�H_D1����&��>jeSB�E*]�sR֕�EAk��04̤�]����݊2�+H,!Eò[�� �J7`t�\*ȧ�ܮXW6uw�%���QW~�� ���bY�qE���Lh�������pzi���B��Qt��< ��MJ����N�l�X8hB��5�4���g�d�"k�\��2c��XșJ�!����Z��hB6�V}�8G�J��&���I9���mT�}�+��*�s��/(�� �37�e���,G�TP��X!�Ƭ�����{��u��>�L6� p��IϺnW���g� �k[ /e�M����,�;��җy7�s�{]��*�\��@��B�os��7���R`�y6�|H�ɔH�p�͝ȆX�d���\��1�2�2�yپ..� ڝ���6��u���pZfH�o�����:�iR����_^⳻�`V���5@F��9lŔI��X-��h�@��X�a����j\��lSi�H��GJ~� F�u#|P֦Mj�G�½� ��X[�yh��D�����$I��D@픣-�N("΃@>Փ� 愇)��N�f������KK�ԏ4uupW�d�b����y�r�od�Z����j��虩�T���#lKK�2(��e�|_����4�]�H c�6��[OU�KgH�+����5߿[Dž���y;��d��j�.`'����6G-��كS����\@�~��u��:$��Qw �<{�;ɀYٹ�|��K� �ٝ$s �$��Q×��^V���,܃lD�f�>�!O�t���v-�!�i/� ڠl�.���s+(-Z%�MI*C�'$v)���|Dvbo鈂¤ x�k�(I��ؕd/2<{5��jYO��! mҝw���6�!?�O�n�S�a�\�G?�.N\C�9�o Ɇ Rv{=����J�&}Q�U�`� F�T�{H��ɴ�Q�xX¬�����j#��� ����$�z� 9y7vv��څ��m� ������̟��`�w��{Qq�F�yn7�-s�V�?�OD|/!y�O_�Z�:7tv����ǖ���� P9�5��7��v�/~4JqQ�~�M�(�?4-�/ty�Ҏ:�8� $[2P�p�(Y�����n����9�˃ ���?��:z5D��Jp�����8�s~T�^y����� +�t�63���x��ѓ��)��U8�M��3J!PP|a4�<4�{�� Y���v6�����>#�Oc��h8��7��L2!2&h�Q���1T��� ���ɞsHl�/��u^�Q� �.`/� �D7m�Z�o9�-: ���t�����$F9�z�2��^��� ���)�p$V��A�[�-x�#�:R��6� �>Nň6��$��b�]�V�d�Hދ��Hs#V�:�/��JiuSw�GW�"�Wmis�a�J~��!=^�D#lB��5 F ����wɺ}"x��70���}�|�D��>�wbޣmmws�����6(�TQYIk3��Е��k%��낋����Ǹz`���w��k����y�;�;'.:!�ٹ��f�9��M�·���H �����#.�q$si��:��=���݆M�Z7P��������,ާ�y��X������ijY���k�f��qpA&��V��B�%i� ����FBX� �[� 8�O�N \���T��&H �,|��@o�+a�.��@=�8�C�h:����� l��:g>9�S���+��5��@�� �Ǩ��Q�S�qJ8M���v�l��p�o�n��Q��4� ��ek�Z�=�%郡�m�yY3n���,�T��L�7 � endstream endobj 2544 0 obj << /Length1 1821 /Length2 11556 /Length3 0 /Length 12702 /Filter /FlateDecode >> stream xڍ�P�-����wwww ��X�������@��5@p�Gf��̽�W�W]E�ں�9k���BM�Y���(�3��� $�5�9ll�,llH��Z�`�_f$j����H�_��@3�M� ���(�;�9�<�ll66��:� ����<�@��iq��B0Ԯ!��N�ؓy��4��� zf�E����h�����k���#�+[�tWbK�O���M�)��M�4&w>!-|��(>o E$a���{r�� ��n��R��wq�CS+ľ���j�X ��Q߭�QD~��b�ӎ5 *��.0ϙ%xf&E`�:�B�����ʛx!WHbD�?��,��_爿���Q����MHE�O@ }�56I�+����?�[V��:�>��y|��=��>�ώ�ƭ���1 ��!+4�|L�Z�\�c)E2W��š��9o���j�틪o#�2�N�}^��><n�.C�� nj#9��;�2��-�h�z�1�p������6~4Si��ρ��� �A?�(FV���g�|�"=�pN/-���v��, �!S�������:R��c�sHݯ�ۉa��(S�3��9�Ր�L�v��j�? x"�F��©Юx������,F��O��k���wǓ��! �����L^x��b��ʼnQ3�K���:���{l�\�D���xnbc��>�g�R�X�_2H��/�}Q�����9i�5���N(|��vl��^�i �ϴ�}�aQ���(#����#jW�6��B(<�����=2� M�:H��!��ݫf�l6��B�p���cyi��a�܃ӆO ��BH��e�mc�M_�� qjN��YvUB)�A��+��0�\uQ�m yҲ�]�Hy���bd���7i�:��O~'��Lg=��hƤ(_�Ӈ/ �����xR�� �b��T5�q�Q��X��ڽ�o��|�n� ~���\p����VI�E{��@���k�l5g��3�g �d}F�\9a�I��팬^T'�l �k*K�˂����"J��tޕ^Q� �,.�~�����bF�(G�~Zl~��y^�B3�Z�l��7�lEg�m�w�?',I��L��%[��y���l�4�n�0�K�����f9�Me ����U�"�S��2q�篱7a=��������A�ׇ�ˆ6�U�A���|��/q�z��P�R�g�K � &�>��>�x)z�H�Z�ouK!7�Q<�>�[Fe�A?"ܧ*�LR�>�'X�8�+\���my�7m��4Cl�e؉��i��Y� |ة�`�q/��"� �kr h�@M�JA��c���#Q ��qʋU��ت��,8aZ��)�-�)����%�k�i:�8�ƛ�Y��W �U�H*��.P�dI�?�/�e%���Ej�X�׬�9�l��L�d�� r,�5�K$#�_�о��t�T��jCs<혯�!����4Cګ»T��s�5!-kH���H��\��ߔ;�.���k'C�8���N��h��XJ��!�˅,�����.���E�`��4wʆֹjj��+�c\�?�A4f Sv�S�T =ظ%��`:/������y�u�+�q�M��`l��e/v�i2�C.�`l 7�����/�1�|YE����>��/�S9�5��M �n;WȞ�|�`j�kJQ+W�ƒ�'�/�Ӂps;�͸�L2$~� +!����U�f�;�Qh!*�(� (h�a�Iv��fo��D�>O��m �����)��[ݿ�5�%BW�#����& |�D�,�k[quB'j�xBI�޸�r���̐���&�Ӻ�ո�"����s�c'U��+='0B���>7���ވ��M�M���B��p��7U* ��J�Č SU�����"�'X��ɫ�'�Z�K��:恟�]�ǹ�NJl�$8��WS�ё�^z������7�C:T��*.�B��`"����`0fޯ�;$]���^Ц~�\1�g�Bi��)7��C���X`6術�>W��t�2��\)C����vkR��ul��^q�²|'��9}�-��A�N�6�U�s8���@� ��,��ry˼�����ϐ���rmm砟�Jf&N�&�)�Q^<[��!��@�)t�B~�v\�I�Ey͗�|C0S� to�\#�я���Q!}p�{��&��(�!Q��'�3��D4�(�Ү�Ek;�*�`��3�og&ϧ~ G�)��{l�1~�]�F1�W��>���Oi�y���_#���/�q\\Ĭ�5*/G�D���{9w>c���U��L(�}�l�1.���țN�f ���w�M�X�P���W�&�5����{����� �>+ 2���,.�k�7_�f@��~��(ٜ��^�l(�����o� LZ�S�t헫�/aRm��]/!ܘ�t(l$�B } WQ�I�D�e�8�����������B��U������2 �Z���y����;\��(� �)�&n�E���j���ZV2׽�`�}��Z5�/@��Ϯ�n���'�Á�ю���G=�t� ��Nq��������j桱�̠⤈�Z0L�esIԠ�5��4�,�}?͜�{�AU�;�^[�����G�'bzȻ�1*gɬ��CR �1�6�x���%���dU��!���i�l�&[V|C` w��8��Ar$�B&2= Q-��i�Q���s|��� fa�a��OZ��&\��_�� j�-�D�-Vubx�ؤ��L�O8؄�U�����*yc�t7�#�-��3��`h��:�y����ڋHG>� G�j�ȸ ��m��W!�{[PhO�^�)��ܷ��2����n��#]�0atN�[�6���x�;k#u��g��@|� S��LR��W�zcV�zi�+�^F":c��`���ϕ-�[���m��!��@ a,h(w��f{�.�}�l ���ߵ��'����`�+&PV�KW�Y<*� N���\�: �,�YI`/���j�f��l! ]`�;�������m�$8���3ii�� � ��[������ ̦C�T0���k�?I��5�Ѹ��~C��ѥ跦YND�xbn���B-�ӝf��oJMŽ�;q�m ��T�YO2�ڃEᥜ(�e����ڀ�RJ����T�]�zp���*˞4���&T�ۀ�O��\�pEs&��)T��#O���9��ky��r�["v��7k �±3�f�O\a�� E�UIf<�� a~|kn���^�ct�^AM�/K��du=K`>| ���9�x�����Q]��%�]A�#P���o��![dp������9�5l�?��r�� P�Ym&��~��̦y��C<Q�l�Z���_�̚��R�{�w�w_#1+J��N�Vm��bi{�yPp���?9�(��n|[ 3��ɻ4"Ǿwv�ﳓd��vj_k�������X�q�mrA=�tk���əG�rJ��zHg�x�a���G��ME�hSv����QuT��rz步Hh�0�(�X�*�u�xXH�G'������Te���B�� <��ףM+c��ۍ��Ww}���p����$�CWL8V�f쟮p�i�������ɰ%�i����ԭzX;���� �N�r���~�)2���A���W�v�7���S3��i�cJ�5D$I:֔����-�$���<3�h�� �'3_4���p�%���JlUb�T�2bq2n�j��܅p����ι�N†S�b{EO�s����}m= ��.�7+��9G���M���Y�8�}5�7SM �=�z�)O�u�'��$�o��w��r�t|h*���5Vy|2dk��6e+"߅�NRĔ�MO9���T=�1����ն�UqH`Y�8���u<�F���NP:�ń���yc�6)U���bDTb 1(�i��t,��i}�u���U�[��t�]D=[e^V�>�j�&;�:=�Y�7|�}�یܸ��&����K|���ƚ�t䕷j�֊Byzq��,�j���ҳ5��=�=kv��"�.�؃u ?��F�n+HX����j|����ݖ�l�A� ��'�x׉���y.~�g��q�[:��,�Ǩ]<�l8-d���P���`���S�X�gڬ�H/��\��d���B������*��=ck�r��?�r��O܀�uc�c0���� �*����ʕ >��ǹ1XX_�-�s���(���1:���ʯ�/�`�26]�o���Z�ђ��T���P�܍ڊg)�G�a��b#�d��,Jy�U����+���x�պ� ��"!�N{�x�?��7�B�g����5����{<'�nٟ�=��3[���bFd?܍;l��%�^��P�,�w�a1��D>}�Z��r51�V�X|�!�xW���s^gɪ�"�R��v��k̫,�wwE�/<�!�Ոj��ز��[;j�� VF� �ࠀ���-�Nq{��,������fr��H��ֆ���84{e���w���2c� �F9vmM>�K��x����I Y0�M�v�6�2���5��(��w����?�9 �/_�_8v� �3�ht^�-Ι�����/}Yl�&̘�r6i�b� �ثF�t�4וas��m��2��/)slK�d�D� /6��e)�C!���ꘟ�V�el���7�"������~S���̦���(�<���~y}���o����tN��/p3A�D�я�o��5���S�/@Đ?�B�����3qL�q�����Es29 �M��W[� �?nvG�Z�� ԱV�.r ��g~^<�ߺ�ڈ�d��%�ŕ��ѽ��V� oAGj�}됪4) �!'b�����5̏�r��h�+��d��T��q3�����j(od�ެ� lV�=]5�o��t��Na@������3�I�$n�Yj ��ٔ���|�D��.��w#�����y��0>U9���� W�#�ؐ�"� �����3Ҙ��������V�Мc�e\ע4}4}�B�Oʶ��١! 1n��O��3)l�u�Fkm'�#��+�\B�R�v��x*�i����cv�qY�"��A���U�j�JXy��_��`Y�s�^��Q%���ͦ� ��U�� z��i}�`)bҭ�=r��"?r�S�=�n:ō{�iF��F�O޳be���9��%f葷u��B�"e6}ČM�z�t6�DQR��W~����ʃhI�iwS�Y$�먎;��f1e�>Gw� �� D��_7%��wl� ��e�F�z %��qgU��y1����S՝Ae����":�ËN�L�\� _�H�&�Y�����٬��� �L8�a|1���I���F�9�o� ( UVK�q��~�%[%t:$�}�F���Cir�ߗt8�� �ܙ9Rǀ.چH����y�L ���K��(���*ت~&��1���_��´�l�ӃV�"ޕ��N,��w�޹� kd��Mn��4jl��ʆ��D���l�"2�x���A?�G �_@(�=�i�� )�ɧʰ���y>�#|�6�o��u����]�¹��k� $qQ�������L�M��6�u8�+�����ɡ��uć)f�e�}Ⰿ�s�0������jc��9U����B�u7GP�Ob����MJ�UV�g�Bw1‡s��ѣ��/�zE�cb���d)vf?٫>�;vA�U�+x<���+�%ؑm���,~g�ՖB{j�E�Q'*����GR�X��-���{W�J�E�y8�P�Dv:��D9E�!Wq3���9�%� �/�2^��E�X@Y�SAr��n���0&�v������AO��R��UC "��6�q�[���>������,�f/ I����~wl�!8(��,����=0]iq[w,w��;<̐�iq��8���:��A����� �F����QW��K��&�%�FNt{t�(���G�/G'`��ē伒�#��9�cR{�T ��~Yyj.��s��e�_�)1n�֠ѣ�a���r�_ј~g%���4���3L�Cp���Jbt��.�� Ս�7B�fx<~�d����ؐ+��6<�6W�w2]�Ն��쎃�!_qw� i��YbO�v&3��L��ʛ��I#���"ϙ��xti���A+/H��e�#�_�A��\ X'��%�#S�{]1U� �����±sC�͒k�_ XHN;��P�CN6cF~g�J�(���� }��&��Ԙ������w9�������\��y<���H�Ʒ����j(CF#��p�B�(�� ��Y&���[�w�,�x9H�!�����T7�qlC� ���󬨭��ߺ�Qn���ԊZ\���h������n .U��@.pY&��VH��j������AW��Sd�%��|�m_a[|���d)�B�=إb��q��xk<�*C�Q��bE�x�5勎˚i(c���!E��i��{�bZ柒�h� ����$��7�-��-}��U�` V��>�m��ł�.�\̊��"h3�X��q0�H�sv�I��很.��|�G5v_6,��"� ��!Jƽ�ʠ���e] s�8;Y� �f�?�IUa�($��6u��U��$ĺ���-.�"� ��x+R��n�A�O1}/�tu��X�����$Z���㠋#�0��^:K��IM��ބm�|@�p���/<C ������(����R :��M��N�spi���W7n8 j���P#��$� �{q� ���z������u�LG@����簥#���/ˡ�S�OG���1F�e?8�<�]d�t�Ϣ;�_�*�A�l���:���$R�����B����rBH�'�%����k�Z8���Zu�0�\ٚ(&��}��,Rf1��+�ح�=p��[� �YI;l��t`��O�B��{�kx�2!/���Gd{CS�p�����ҳ°��$k�l�#��i��E+R� �|�r�6�9�q�Y}��߿����& ���pM�������rI�&Q{{�EP}��V��A�.D}r��doj��G��u�MAc����2�����DD���s�u���ZΆ�T��������uԄv���#��l�Jգ����<�!nKV��0������ל:%���z�'s�؟��ZL� #�p���E�2Izl��?(�C������|V�p���ט\�}�}(��D�S���W,$��\jo���6 *�p�f8�yW���з��pO�|�Z��M�� z�k�zH�mc �v�'�]/� ��ê�Z� �V3�Zՙ#a�mr�� #�����/̷�խ6m,�E"%M%3hD+�a�x(\z�'�x@��� A,��H.�� ��ꘟ��W�|C��]r��F�4���Y����A�L�'���Y��uZ������9N`�u�#hrBTW��� ���VW�����C�P��"~�E�Z<�8�o���U|:C&�������{���+���Ӹd�P��P8|w@�jQ$�֯HuwlJl�(gqI;ɝg̯�\'v�K-���]jsT䆟T0j�Qu���i��^�n�$��BEjR�> bq��DzD�ѵm9��r�޺ǝR�J�� m�g� ���(=�N�C?�%M<��D Sv>�Vʶ�E�U�+�q���N~]��ϭ�D�s�x&���Z�k���]y�8�� :���t��<�S�D�VA9a�`��%�����ߪQ��HL��ĵr����5�������?]%�l�3����H9�©T���s-�U�$҆���Ca�ݳR�� �������Tu"d�@r�ap�f0�5�!�r�;va:3���f�C-0U{��Ag�!킪K�����r@� -{ P��(���IE!<�.j <���P� �;E��:�+�KA;��`�N�ѵ�w}:_�E�=i������}&f{��G�Tہ�O\��`䊜 .Y�ܸ�fpA���@��7A<-�!gp$�rhra��B,$�!�vN�v����l[0`AU�I��S�ꅵ`�ח��V;�_ ?e�w p�fι�WV�Gl|KK��J�_�ߙ����'���9�I�l]����j�(y۟Mh���Ǫ��alc ����6݊9�M����d۳/7�W/���D���ao��W������eV��Ѯ�`Bw��b�I i2ny�az�v�)��)j,�V�!��'�K�h۷��s)�ƍm�:4������wT7�B�SB��t.��L��0�s)-��fCM�55ߥ_Pm`1 �0��Ee�G>��9�y���Y���xF�M�e�_E�a8�2B�9�HF�[v��㽳��3 z�ܼD."dT��u��6�n¿�1����~�?��� �N�x�\��HAq,0\V%���v:[��5G���w}�@�$� +fH�_ѿ�%�z V�<�ެ�'�r� IVa�z+]mV0��]���G���%��e#y�曩�˜e��w#��1TQ�a�X�l��!v�W/I�aZ���o���x�.��"[�u�E9����~:E�~L�W�T�-E ��G��"����W7,�r�������,t�$i\��/G����at��_�-(��U �!o�i���� ��N-&*����4�6ޟ�UE�媑�������6 N(>i �Y�kΝ���k��l�\j�t���I�d�� J�nǖ_.a'c��y'Ea�e�5���Օ���a�N:�օ\��s�5�#֣ک��� �| f �'D��T�t��/�2E�vo@f/ύ�-|�� �� �8[��.�wk�Y j|)n�v�!����n�v�ۡ� ÷)�{ƺ������0jo�u+8��:�;+�Q��F�~�$� �S����ÂI�^:���x2�\���O {é�B���m�‘����,��ȡ7�sؽ��bA���"Ng��c�oN� �>�a_�p z�h�d��Pj7���"��� l�SUu�G�D� e]� �)�+=X�)Ƚ ��v��/����E�2�Os�A�l�X������Ec���]{4y�܇xl�j}���޸�W� �;�G�1�����b��q9W��Kw*� &Sw��s�Yy)�RY dDE�r���D�o�oJl9�XaVE��͊$u�c�*4��l 9B�kMI���0*%��"�=���l����!��A��9��wTt���A�l�̵*-2��'�7���_��G��4'�������:C��S(���;Z��=�h��P:��l����m;���&��`\!I{v�P8��&r~*�|��'��z@���3bl���X�s��s��)��ӌ�KE��VVZ�6���.�DyҤC�\&c�Y�����h*��q�4�2vr'�y��ېi�A�Ijެ�U����XV0y��D;�ƶ����*P��*�E�$�ip=�5�A�|7���� a�%ߑ���,Di ?�ˍJ er�hid�{ě�����O���:B����Z�������B,P� ��O-l_��?{�J�p&l���`צ)�gZ�>K$��}A_U��F�ׂ�����B,3�����z�0u�'����!n �?7+�-��t�F��h���i1�t�ޥC=���}�?>SI�M#5���������J���P�H-𒀩�q��@�\�U͢��M�3 ��r�h��j��yg��t���_��E�,�E[ F� �Q�jE?��7���\G�/"� a��Z��K+��z��9��N|x�7�ݭO�.WLv���[� �{��-^o�� FC��lG�i�h���j�|l5 Ȫض$�Rq͙�"�l���8fӁ��9�+�ZБ�]���W_e��&5��9'$0�Nt�~.�]l� ��[iP��3|�ܗo�Z��� ���\�����b-�a�S��;^�w�#R9��P�xö1��NP�����> stream xڍ�P��. �%x�`��w���m�Afpw����C X�� Xpw�@��dw����U��T�|O�����]��P�j��[B�A2P�+ +�@��� `g���ΉJC� v��%F��9����H:��\�eRf��v@(��f�x����`gp������,�2s[��(�J# u�r[۸>�G�������w���la�\m@�'Z��4�`������quu`c���`5spa�:[�00<��6u� ��d �]0@���ge��4M�˟r �����3�,�[� .�nK�3��p���@���X�Of�_�p�r��/�߁��?��,,��f/0�`�Td�X]=]�f�߆f�.�g3w3��������d��f��U���3��Յ�l��D��a��, ���:8� �.���;�,��������A����bi��K7G6-�� $/��ɳ��5�������� 9@�6l��kz9��Pr�?W���uX=�[��P}\��AWg7��Ͽ��P98�` W�9� A�'��d�'~�|g�'����{�ߟ�����e ��{�c����)����i3�Y��: �'���� '7;���������(�f࿲`��Ub����s�����_�O��l0�;�2��� �?7d�f�x���f�.�������MH����5������l����3g�\���>O�Mu@�,d vs�_������C���n#�E� �T�Z��I�?�Z��� �B]��� �����tϓea��9\��� �<8�}�4�j�{�8�yf��f^���D����p<��%���X!P�g�sy~+�3���������xl� ^��߈�Y��z��F|�Q��F��:�����,�9l��gW� ���_�����x�|���9� r؜��r�|N���_��psv~�(0������/�d��0 � �� m��'�`�����Ig`�Ypnw�������}��x�n��-i�K�E����uH-�j�w��&��;�����}cE?�?�����h�}�}p����k���@���Ƈ�Z�{��#����li8|vG��'E���I�8�Xà�i�|��BJDWRdF�O��˫)�ܱ'r�D&T���7�>��oog�W*49]:���� I�.q�'h}$��)���~��jb�,xP�6:�B�W��7� ��c;�؅$up�M� o�~臈|�-�&Y��]'LOֳK��A��� ������ߛ�C���L|�y��a����路���P���s����<5拺:N� �{�����K�a�a쯩N���.�a!,�f�v`�du}O1�1A>kk%‰�p�����nލi��^lPm�Mx�˶�X��RhV�n�]�Y�9�g����O���|`���� W;��{�M��3���w��i3ٶ�QO*�����`�P����m�=�����y2���{��J�V�P�k���~�NGl�)���r�~d�U�AM+Db�_����H���aĄ�f� �CI:5b���r��FՏ(��Nd�H�6>c���6�A����$ &5d��>8��;���Ru��s�������h�SZ#>#�ӯ��:A̪Y2���i���̬���ZC�f�5J-��W3��UņW����.Y��-�e,��?�,Z���y%�ʌ�y�a�Cqr�O����`�-����ȷ��x8��8�bMH1XF#F ���޶� �p���{�O���^�\fr�+wE�]J[ZG�D�f�H�"�b���x����l9�`�z$�bH�� ��e����4^~u)�m"�78o(v�}=0��F(-^�L�Q�|��E/�-�D̨��X�!� #?pp��EM��n�eU��U�;����D|�������vHY\9[��XW7q�P �W�a ��`[q|���h�*L�Mވ#�!J �7�2��$�+x���W��(j߿���}L�4�N���#��<|�`JB���AP�^��M֩���\��I�qW#<�.-��^�7��@�#d�1ir�'�`̲�Q���rb�2*"hh�tF5�G������gq�7M�bgd�ۯ�00 �����z���iv���l�R��N�� 0!12O<��c��xq�X��)ƶ�<$^�eV�h�\N�t�lZ�P�����Gw�+�U ��OP�20i6���C�d ���qy���r)[�9Љ��ls¯C`���X$��t� �ϪJ d& �-��&=��-c'�~�N�=�(W�g�p��E�ާ����X���]qH*\3���b�������L�qڶ� "���i����p��*VY 5pZ�V�|��_����n��N8 K�C�Ǖ��� ��U'r��i]A������h�q�xq��%��Q>�8r�ػp�5���БS�L��j#�o�MwP��o�z���Ǎ.gе�ΠvL �%���F �V����\S��`����lfK\�C�W���~5ؼU�nh��q\���_84� ��DEG�hX��1c�qt�"Q�������7!�ZV�2rL�>�����b]+K���:�f_���ꂾ����iO��#��o�z}[���}�s��/���H@K��2�Q…G��A�~� Ɩd� �^��H}�g/%\���xcq����W;T��lG�}c-3��j���������jHWȘ��M��e��]ޥ>�7�8�m����'EB��������]�5�Mn�Q.�z�6��daF�+�BU�\x8���e��1��W9nͺ�����i�����*�ۙ�ŦԸl"� � 9t���D��Q������Vw���0g��Ne!��V�V��`��bR��4C#�jڂA���}�� ��m�G�{�$�${5�i/� �|Ǒ��oz��pg����U�9\��hy?���@�8(3�za�ܗ�P-_��t�(^���/����;Lkd���)u� Ol�KP�)Z��B�3�E�����lB7� ;��O���M��]�-�N���+�pl2��$����D�SQJ;���`�K��y��D�i^Z9娟a9vRh�gQ���W�1��mLd�sǵ�!�L�Dc���f�X�Fr��ʙ��Rg|��AG�/�̵��R.z�ң��ʘ4�\֒ J^�\�4[�Ȗ�Z����`�2o��%�t��+M) a�A�+ʘ5�P;x�Ȇ�� �I��1�[uv?�ެ�|��O��u����s�7�yZ����SC��*N�z!� �˦ah7�����g��p�uh�}���XZGʎD`ޫ�@]��QN���Lۍ_X�[�jr:^��D�gネT�*?�]fЬ�p��]z��v�h���#C�]-9����~����-Y��Z�}QEJ��A=J#z��A�����ʨ3��?z���R��n����K�E��4�N�p��/��� �z��6�$� ӄ*G��/���f�#�Z:N���� _c�Zo���I�{ʹ���l-��A�1 ���n P�}�xp�!� �}`'�/�I��d3�(V{����?2����}I+BU'�p� ��͋u��ִ�k�™׈M�%�pA� 4d�:���8>쎨�3�b��o{U��(�K������Ո�����us��[���D��K�:�e�xD�,[�Ɵ�Aœ,�HpA�i��u��q����#��ԝ���e���j��8�I�� ᫚��Vc�M��R����S�l��׶8*��YP��O��N>̏+9��h^5�R��-|ԭ�V��1;��ͽ)�a���u�1՛�0����b�CL�ff;69SE�BNqx>ggm_����f�l�6��L�.E;Կbt�S�r�HY.�1��e���X�M>IJ�N�A�!�����lC��i���G��e���ot��&p 3�/o-<4G�mGt#�֌���G!�� 1-������t�J�:1�� r�~p V gK���O�������ӦY�d �?��'�6�$pΓ*!������GŖ(�=<���;�=��R/�[���{Q�ĵҊ �ڒ<� ��\�O�0t˫o����q�ܨfy]�]�2� ���1�2 �ݽ�[���M�I���a7B�[����NJID�|Ue��x�H�L�����L����pI�V`gM��.�"���^����kY-.[�ʶϖ|ߤHv U7�]��o6�T���yӮ_pZ���V��r��;�{�B�s{*:3=7���:�A���,м�A�2�6�_����D4���]7�e��6 ��G^�/�!r���t��T�7�BD�2�PC:�c-Xx ���iU눎��1p[ �k�}��i�)>���f�p��}<쓾� �^Y�~��L,�ԅ��!n�� ��T�j߮�7w�$�.���g�����U�[��Yo�������q�;��Y����`W�^{"����aU�/�j 4�;��B�xI�~���tQR��y]�=�^�4��RFH����w�ۆƫ�6he�Smi�U��]r�}�R��5ep��ӊ�d^�}a �Z3�=;P;�5Ju���~��!���� ,�fg����0��T3 G��Pa9�s��rB�h�[ zL�Oz����8e=<�Oy�sf���h%�u�%����+�ǡ�f��f�{�mz�k�9x`���n�0�`���CSzD���o�pJ���X �1G�Bā�(5�A���jv�a��Ji���m�Rp�d�Ku~��6��l~���ַM�ћ&W����a/ ��� #��&�2f7���v�b������e�*�Vsa4����`#W y�#��"=��'�u��k._`z�/I9 X�u�+���xkD�꼌���$�]G�����f�>eW=r�lmza�R~4j�ML���暀L���v�����'�.Zw#�FT�2TOR��oR��A~�S��0�P��W��-o3��/: �L��d��W��-��2M�Ҿ��xj�i��I�;�sA�)�K"��Z�ȐC ^LK#㷧[�T��Dd��6���_�4~�fm{��<� �k56s�n(2�xG���WΓH2 �<�Y��7�N�c"�,|�^���@Ж��U{��=��0� ���M��ʄ�˻<|9t���*�YC�tfU%�W��ײ��]�`%�a����� %�؊~�g���L��ן�!�-ކ~9[�*�ug2��3�: �\ B���D{+�r��@�$��� �ۑL��R����.��3�_��8 �|��2�sR�*u|�.S��t[FE�'F�7�-|$AFaz�pX�a���u��u�iUW ��)�rX<�lxa�&t**H2��(��N�(y��D#J���@l�?�g���v\/Y>}�ٯ{�r�nm;���̦��֛�XZ �p�,��e aĚ�Ǿ�#����AY>ȯ:)��͟���Bܲi�s���*cͬ�z���Vg�U=�˒v:�#%*�LAc�}�xY-��T�HN���.i�g��\�kf��n�h����\5� ��/�ul���8���M�@��ǝ�yK �����|Z'����5z�_1sg~�`��:��������[-�⿾�O�iJb�F�}� /�M�����#ކ����{Z�7ẽ����N$�/z�E����=����X � -�� Q�i��$"O�>2�{�Z ,2��|r�P{u�������v�v���5��)i��q0����l��lJ<:J���K����|�l��*B�ȯSLj�m4��>��d�#��4ofRH�=pz5�hA.��پ�I�z+�/G ����c�3R'Ex+E��XD�V����j��U��)EVA:<7�}���v3���V�O�Qk���)�@����q9�h���~K�{ ��/��'�es4i�|����d���I@��8 \'�3�����bT��aުx�e���;}F u�n�&���� �>�O��#�<&�&iL�k�9�8cԙ��I��p!u�+ 9�C��/#�=W_�;๊����o���.�'��g_�+�?���&������v��_&]( �.M���������IL/�˕%V��o� ~�x�G~�ⴣ�q�tm cv�����QL;�Z���t�B��'E�1���b���wM��;}9;ufRIюNT��̽�'Q�D��7FJr��*��6D���z��#Y�U(���T��Fڗ�����o%�,/��\~ȡ����Z��bM�t�f4|� 'e���j�۰L��j����`��+ͨˠ��5+ g�$�٨���8�^Q�8&���V%a�c����JӨҐ(^ Y8'?��i�Xǵ���m\0���s��Fe���f{��K�E.4�;6*d��M A��+����g��ԏ �@�w���E�j"1ѥb��Q���[G � �59L�7�z�el���M���[���R��;�E�,1�#G���>��5fz�8��d�cп�0�� Ҋl�\�l������8�%g���go�o����S#6�Q�g���ҙ ��C:_�(Hi ������<�ܛ��?�^�L`����7WH'j�LQ�D��z�ИU�'"�s��i��黓!�^F�M����G9^�'��>�y�3S�ti����.�i��C�Si�hg��Ă?e�6�B�T_ݏ*Ѥ� A����Rp��������W��N��EOқcM7�l)]�fx����&�SC'^C_�}���ZbVH�H�b �����Y1�}��S`M�������XG������1�9m"�?P�mL$��wRb7�������+��N�@7s�t1�_n,\�(����JP�Z R����Z��q�@sP��;�̩S�zaꓺ�g��T�S���� <�����ۍ�ek�q��xگQ��C4KZ�[һ���q�1�o��x�Ì���R�2w�ۍ�Փ�ρ��f˥Чm��ykQ���3!k��֥���6�,?àr���CD���v�Ň 1���`0[n~)�Civ���!�#���[�'_��o�Q��i_ ��P��?GV��H��� ~}��%���M��g�� ��/(�_�+r����=2��������7�!d��$�o�1S�M��~��x[j��)�$��.i�qV�X�؁j0'W.e+��vVw��m��YH;�ܥͨK6)Wl�O�w�9缵�lY��\�Tz����ѯ> `]��*����UQt��Y$� :����A�}l�Cҥ��8��$-�4C�[�����λN��\����]7 bg�<+�h=�x��Z�#cW&��ّr�?��S�w!-y[���ں�gH��bB�����ΎeT�-c�`ʇ���;7�Y9X�`�V�ᾢ^�U���bOu��⬡hBG94]J��N^�*�2[�@�a�7ڌ��({ x���U��7^0����)t�d��ib3�1KY%�{���=�V��'�/%}$1���W*����%����Y��܅�վ,���=lk��s(��)������i�R�?(%�in�A�%1}j�u�����N�/�d��b1�|X��y\���T��pد0Q��"�}ټvD� �%=�T.�ŭP@ ��x���T��ش4�A߱�7��=����(vC�~@�K��.�M'������8�5ŸI�ƕ����H7��g���w�/%��|�o}pd&�d� �p������Sh�N݄��t��#�?J*2�y�"�O�e��Dg�b �# K��� ��!�a�a�DӨ�DT��8�x��� � O��~_��x�y�C}��w�+�)�(\���Fq�~(�+��L�O�K���DӁ}*�QU\����>N�}u����SF�Ŭ���7�Lh��1�mTŔ�;@�����9$�4��3A�r�ɤ&-�cׇ���d���l�(N�R;�rH���N3�呃�ԭȃ�ۀ?_ �M��.�����/ .�8���V ��Gn�Լ'��)��B|�#s �3o�(�1D�z�R��;�V�rP����` (�'H$�I3�J�S:��U$D��S�5^D}��2�%����qW��UU>�a��o��� ��6���:�r����J1K�pJ�S"�( I�N]|*ԙd~�`%<�������D�B/l/�h;�ˏvQHO.¨G�~�X5�_���� ��P�o�i�CL���<�)���O�IsA�{��'�;���ʼn�4^̋����4/��c�^� f� �E&hl���X ��'�hG�h|^ݙ��tE��xw��d���<��q@t�r+ CɼY����7FyT�P��(�׎���*�ة� ܍x�ϯ����t_+�.��'snP0L���1����I�=܁9u�26�3D(0�=洤[��ԋ�������0�Ey } 7�=�4D��()�A�Gݮ��B��ܼ��A�W`+��4EFV�Ƣ"�\@�U�^�'9 ޝ��9 ��ڛ���b* k��E߶�ORP)7x��@L�l���y�������V}̀ӄ����]e��4�"������\3���O�����8���ꎁ&V��dK�1�s�<,`J î��C�ự�|�j�sKK~N%�*�V�o|�z���� �3QӞw�'�3?�jg��'�?Oo�?�B�+&������C��!�Yr �� EϡKϋ!O�i�E�k�yt���[�\؏��J�:�j=�z�1�K�?�(k������ S9H��ٍ�g�bN!���+� y#b�%����>t���1>%n�A1�{�R�È��\��}�'v��XP�rYr��򫊷��h� ދ0�qSg���S�����������������j>U�a.}�Ф�d2��`m*�?@!�@pҩ'���r�l�z�Hƽ8R�^��~M���� {S.� ��B)�̭�V_*'ɛ[c������ĖAh#���* ��iI9�P�ag��Ni��nG��V�P$���z+�r�u�� ����u��z�5���*^# ����^�[HOqߒ~E����*a�{~�E�)l��>M��6�A���T���4�����ES�6�=}����)�k�q�t��h���{�Z��p��+�k endstream endobj 2548 0 obj << /Length1 1528 /Length2 7587 /Length3 0 /Length 8615 /Filter /FlateDecode >> stream xڍ�T�6L#((R�� C7�ݩ�0�#0�Cw(�!-�R"R�����4ߨ�s�����o�Z3�~v�;���5Lt�z\2�0K�" ������4t�@ ?7ȇ�ĤA8����L�`� �/� B�0ye��T]��^!1^a1 ����ȃ� � n�* v�g��9y�!�v�-�9X�����œ��2�`8� h�v`GԍV �� Fx�+���$������ rt��m��8��@�������h��� ��g��A\��z0�;���rp�Z����=u����X��'��x�y�����@�og���� ��@m60@KQ��Dp@P�_� ���8�,Q�et T}U�b�8!\�] �*���d���� E����O[�����{��P�;�������U������ V������قA (," ;�H+;�_��=������`T�>^N0'� �������r���+������yy�+�l ����m�Ȩ��!H� E<^�����[�0���?濇�c�T[KI��w��deaH���'����Q�G�A����� ���,�K�I�����l��҄� ��CpS� � ����L��.�����B���G���ᷖ�����9B<�ң��@q_��������������Z�2P[���qQ� ��������� ~-� ֆ�@~=(.^ �t����G=.(>�V�QK��+�V0�_��'(�� |ԈQ� �����`�ox��0��*�`����'ʉ�OI(��ు�H�7��`��a��߀�(���2*�����?����@!(z�-�xvp�] D!���x<��?��z`� ��^��E5�?��� F���g�`V��/j�[Ϋe�ܹև$Ǚ֍Rٸ�f�\/ q�ت2��?d��:,�)��J��^{�4��5'���}e�;��f��{8G���c�K#�1�c�Ӈ�G��d7�UM{,�?�L�}�����깮�{�:z��4,�JA΃I��ܬ�XD�#�y����T9n�t�Ԋ��j9�`���mX�P�=�Y����V�"�/B�+�FJ��;�u�h�%=���Ǯ��S�%gxy��J�I����H�Qj��0�%8��[r4u�g��F�Ļ���N�|��0žu�MN���WM���c�CI�����̈́����칔�MW���=�2NճN��Cc5)E.m_������mu�?�����ɮ�L�s�/���hBW���"�E���+������d�C�w��O����|M[w�U2��'wT.���<�o�o̸yrP1杶�����0W��:�l��U���F��eք�0��)�l�{\}[ �=��*q�`�Jßt���=5N�S�k@����Р%��F���b����3 �iy=�xɛP[(�N�qr�HjVu��8<��FEq�2g�7���irԆ���!�m�������u��`���l?���@�p_�,& ��xT}�j��'�0�)) �:�jx ���S���4�a�D��$�3\<��'ۺ�c�����hr<-Þ��j�4�X��N�)�a��4�� �� M����~�E1ی��'�=�4��9D������R��$j�L��@x?��"q+�x���3jh~����e�V��x;"�M�Wz�{�!X���Ů���� у9n���j��6+����-p_M����jZzVʌ��fu�h�[�N���N�J94���@����q�E$Q�^B(�����M���9wb�"�6f��s1�^]x=˄r��#U>j�T=+�1��xW�խ�I7��@v�������F��x(�"}�<#���6�z��x��/����^���c��� Q� z�*���&���Pl1������E�P���.�E�!���2_ ��Sk!�k�ɬ�˚��Hy]�=�xɜl��m.��z�V���q����a�}�Ɯ��v F��*Uk\�6�ɢ��/o� �qL��Oƪ����M�";��濏����lID�c�er���gr�ۏŽ���2�ĵ��[a�"��x>Ѭ$�����۠+��M� ���E��^ʂ�������@����Z� � {�WF��}ӮkV�vIyk6�%&,��i2C�l�K��� AM�br^����ve]����>��Z�/�N�DH��& �=����v���V�"p�Cr���һ�]L�;�Ըi���M�I�����2BFb��qB^��1�U�Wk�n�j޾6)�aBV/Y�m�cF����� S ~E�m�W�I��� ΩE��Σ ���9���KE�W#�P;o���w���~�e��֦]] +�N��)�����D��S4�hX����wu��,7je�H��萓HjN��D z���c����� �Іj��;�o��c�H���^H��8�I����Q��;�m��!z|ޣuv<�� �,�a+ӓ�]-ګ̢��X���3�şĢ���c�[V����.�i��L��a"‹t5Cհ8��&rKD�=_�<�|m���姶��� ��LC�4q"��I���Ħ�ݓ+ۂy���8�D��)��SQ,6� .� }0[C���n�~��g�YI����/����B���{ �Lo�+��J>�,�Q� �ɵ�����/R(-��Cc��k��M|\�y��ì��ݠ���v&�� Zt �BwTEr2���[�9�)ͼQfə�J��[s���E��&i���G���O!�q�﫬\�>������/W�����ѫDW�l��e����;?s���6�����kͽD�G��ڒ�G�zO�� �-�@/�V w\�Dd�7�g�|#\�~w�� C�kw|G�n�۽���� ����=E÷^L�HL*l�{�#�Z����=�j+����x��:���`�X���/��q#��x�R�X��e���]l�>�$������ҕ�]0=\AXq�2Ͽ��姢,�])��Y��9�\�����Yd�.-��@���N��eB��d�8q,��"���g�E����@����y��oJ������uΑ{iQ&��EZ���8���j� �}l�B�r`+��ˆ���<„A� I&]v��Ab�^4�U������ɩ](cyt��P#O#��1V��_?d��k�����QƑ�� ���,�n�B��4o���������.{g*��4�ۘ9�%�C����� K,�"[j�,�;A`������U�_s|r^�}#�P��:�3s��U5xOB1]x��C��i�N�!wmF ���i>.�%������AJ!��z�\����o�W�oO�Dʛ fK�<���{f �A�=��� 31�� L,�Қ����زAH46@�L���\)Z�������B��5Af� ?7+)>2#�b�r��c�@������ѥ�v+}1'>q�k��N��~��Az��4��-� ��i�KD�� ��f���!�D֜��/�3�P��D}��T�Ȁ��M���B��'���>I��8R��1�9���O&�����^��_M6���x&���͙�[�,��F9{D�y|`=�wp>�C9��rH*=_c$Gf�Oq�#B ��I�5s-l�M����؀Uέ����4� ĭ/�|v>9��r<���v�I/�>Z�8OTMp._C [�(�J]C��l����}Ȑ�� g%��B*ʶ�0�)���h��U��C�g�x;+��+K�R5�m���%y<�B!��-rQ.v�^� ���!�����^�aX�O��ܻ��hu^D63�Y�:E�r��Zd;����0���a��-����j+W�zw���PRԀo�h�KYm�\�u!�q����v�S4��bKQo�����C���y}�P31��&;�Y��\_܀���@1��y��� r�� �F�8p���������yG�)J������j�h}AU:v�s��Gz���46�D��v� �.r<��]���N.������/MN���<�?+K��a��VτRkۑ�4N����'QG���y�uѡ�nn�����] ƻ��_���݂�0��h$���,�����_�Es�@�L����fշ�[#��4cA�mۓ:YOңi�����<�ϲ�i���.��;'�����i�x!J\=K]Q��������l��c��4Z~�(Wd�"�:n Yp� �Y�]�/�W���q���'�p�Z�(a߻b�6��?�:���Q`��ע��v��/Xt<���.��2��DZ�n�۳-L-� �Bjh���V��D�7�qtZ`���a+C��jscz��UށY�9{O���5�p,�� �qn�EaLcJ�+JZ����H>���%�e����`�$K/� �s��%!�����[�i�2ѥ�$�RI{�=Sáo�{$Z�:/v����"�-������ i�Fw����ٓBl���ץ�t�1�y���b|���{�Q-DL�\',�*����n"����.V���3�>O? � $��,<5�|;��?,�+K`����!��2<����j.ތ�V�@����ռ�1S�{ ���^ ��(�,��'n̓B� �Y�n��6�pתaz��N��`}�ic�2���=�5�p;� �oo�tb�66�AɹSV3�ICN�9�yG��w��0Flbe��Oo�p�x���G�a݋��k����s�l��� ͠� /���zF��޸q��_j�e"� X%�n4k����Y���ک03b�m�Z��9�Xʮ/�ƺ���koz���o���DsR:)���ݏ�� vv j���ī�����#p�{SG?N�mR�!_����0h����88ܐ]�$ZNU�*�=��1��$*�¦B��H�5�S|�N��Ϫ�硻�^Gd��Ƃ�� �ūL�‘vp G`��\`��Lu�3ňæ���I���S�1 �8���|�rL�u~�դ|�p���1�<����ع� ��B���o���?}܏���ҋA��ӌ.�e�� �N�a�P}� 7:���}�>l�i�� �=�ѵ��Rn�K����ڜ�^��UE�V ��7�II���-�a����Ƽ�1b�!��x��Wk��Ε����6��_3f�X��٦��h8w��"����ʼ�>�+9Q'D�yO��J�E�z�/�W�`Xn�?ؤ��+r���B��R_kF�_'薔6+�c��@������r��� �p;�`C��E ��S78���h�q�����Z�������Q�;C���xE��Kv�K�/k�i���%��C��ܕ)ŪLJ[��ɳ4\J�U앍Ө��3�3{}d�92�`0R�ˌCBYr�0��v��S ��'�n���Q�1���i����״��ul��F|�әo�c��gܻ]5�r� S�ͬ޺����w�jkf��pX�L���������1F�L�{��vi�V���y&�V��]�N;�̼�i���~C�|�j�")w�� + J���U��[cȃ��g� ����H��w�k��sQ�lC��2�f���+�x#�~7�1�~����Z��}�� (��)͹��g-אJїs9_���ʎn6EF��}Y�^����ۻ��z-��w����!��ULꃍ�0!��l& �H�ٚrw؃GN��0���Z���!�7O8B #&i�w�f*+r�e#C���|�=�c�*T���y-]��nL1Z����T��'\�J(�E3%�� ��\f�u�dmPu� �x˜{��8tt���39�#�%iU7txf�+V.�֑�-p&�����\�B`JR��5�6�Z^�+u��rι����+ylA�%&ߞ����['R5����d:�Ժ�l- ��E��u�Gε��ϥnl��f���e�� ��Zn<��}�:�"�oM���P��Ym?�w�M}���h�& u�z "�s�ړ��w�(9�����b�~���<�@9��� 9��3����"�H� 5�����w�����<�(��5���l����k�E쟙��bc��,�"b��u?2<�Fl���ɦw�A�k9Mݣ!�q�&�8h�}3`����k��!�q��~.J�+*�Y�怢����PG7�s�b���_�|5Mq,��V�w�;��LS=/5�i�<�����3��<�.��@:nG*�u$�,p�,�)ZLMeI�3dO,"2����KX���(�ś����� d��~��Ҡ�~^xU^�4k�%�Y6��S��G�I_PevQ�-E_�3�>ysN���;������>�� Ni�>-W��Ah����|�,Eͧ���_��H�|Zpl��+�0)k�ѽ���}L؍fv;�gtKY5 ���^8��n��v��s�!��W\��w�w��,_��� (�,�i��HL�,��fN�"y$�:gu3�g'8z�L�yt�1K�٫�Im��.VL0��Xݯ��?��R�حn!(�1&u}�VTM��H�o{mZ[��6�0� (�%ǘ~5TƓːqO�}e��XY���^Lv\%���0�c�L=�R�,�{���v�|5���Ɗ�T�Qag��F>��b�K�����WS[.����|��b�8�� |����7|��#��u^�j����::I�|�EfI�{Ǿ,LU���-�6X)�n-fm� Z�p>aH#���?��L�]�*�^�"�)x4����[�r���������*�i��Aㄚ�g�� ����8���]��ҩ�" �*~���z�ʄ�a����VcS�l�b[�\���_��ť?ae�|f3jM4�o���[�,�-�]�o�k�Cwo�cg,M�|6�4?�O� �2�s9�G�>�����O��_�D+�0Q�޾��*;� �R��efs|Yl�+��&O_K�dQg�+�~����ɖ� 1�n��K���`�B2J����R�9z�k2��$LKV���t(��!R����֣��"��+wg'��j ş5�?ntu|���9��[ퟓ����� wX���.�v��N�3vZ��XzW�^�b�xSފ�ӡ�J^L��s������֒[%���8� HK��� �&��r���$Z�D���ڊ�ޖ�%b?S�U���t�JX�c�{<�z��`9�s+��#���S6G�|(��5#ٟ���'{�%�)$�*˓h�Eّ�q�|��b�Z� ,����=~U�.9 ��Z�����6�s��]*��3Y|K��S��a��6��]!�t'Y��������Ȼ��=�4� ��?U� ��ĺ�T�u ھ7�����V�� ��0֮Y>]u� T���`��=M/�Q7[�Y� CãUc��k4��A{��F�CD�;�S~?T�ޠ���{� �+�wf�T��X�ʝ��/���o$��#܈�%y=��bk=��0��O� <��i1�7�Z�;�i��Aѣ!����a�sF_�csW�b�:y-��1W���]+<�R�\wۇ6���a���H���\h��~ҪF��|�+�O���dy5v~����;9��q�]��ȱHqY��P#���HõP�_�E�m�BICZ�m4������#�K����8.E���ǖ��;w|���3ߏu}� @ ��#r3úIb�#)�Y&\fX�3<��&�_9n��H��� ~���W4�V~TЀst� �� endstream endobj 2550 0 obj << /Length1 1528 /Length2 7584 /Length3 0 /Length 8608 /Filter /FlateDecode >> stream xڍ�Tl7NI��a���hP��Sj��� Ii� i �[R���>�������}g�l�����w�g,:�|�vH����K�5�D�`� ?,��0�{����#��DH��^�z�1�'�L��y�!�@��DT  ����1D�$� Po�P���D�<�H7?���}��@N[. D\\���;P����B@M��#�}�-������<���󁣧������u��G���x�>pOG������ Ԃ��~��8�=���H{O( D.p[��������軁��@m7⏱�^�_�B�!����W 8�3����E��@{� �������� �"�~B]<�h�7��A�N T��B���U��- �����w�U!�Wt�v�HWW���+?8 f����X�HD���=ag��;/7�!��SU�� ��`�@a0,*�܁0_[GЯ�~n��J�/�P�� h�.���Po�� �oſ%���zm`p���hf�GFO�>���}�>Y��e�D���c�{� 9%#c������C��D�|�` " E��E �+ �?��{$P�O��.�'a₩���bp�K �f, ������`[�����]����+�����������o-�/��G u�����G����}M$z�kj ����0;����jU=���E8���D���f���u�C�?��s�#`:H�����G��*[g�����o �4��Ra����]�"@( ��G�������|3�G =�.@tyA@{$ �k�h'П���D���I�7 ��^�Q ���o@HB��������0��F?"#BhM�e�鈂�׵`4��'��C���[/ ���(�A��?70�/��e i{����G�N�e�}�ֆ%�9֌3����Z��I�Ҹ���P'�i��d_W9�ef����j�Su[./�R���Zӣw>��ܖ��a$`�3�Y�r4 s�n�lW��s�#�)�<��V���)���Z�]�Q'�,�ė`oV2��o�b��ד������t��d�"w�Y-��� X`�(�x6�?��@�����֌���bp�n��f���Ң�� s��X����S����)bo���Y��~�6 x�c*g�_�_�V�T�a �o\��s�B����)�߲�_��?�}v{Y$6T���NR���S���of�f�#��J�(1�.��fmp�=ȕ��;��3��^�>�*L)E�SxI`�ʫfYQIO��{0bnY�ߠ����MOpX���X6������}����.o꺕t����[&�T��I��qL*WNj��cf��aF�b�����4���� O�@GI�Ą��C�iu�!��x�O׌{�m){)W�t+�ڼ��9��Qe��ӤH�4�u&���ّ�71�Mi��&���zyF�Qv�zaxW���-i3��0�Tw�f�7J��Y��U�H�T��4�g����M.Ʃ�d�]\�~�u��%)��� �"�vh��=y��3�x�0��);��Ey���Ѵ�}���� *���/I�x$����o�<��-R�� ��"/�e� ~<$Q���-���>�V=»�; f������! ������Y���3�Y ����0��G�ľN;�Z� e����#�*2�*%y֧���,�I�ڕ)ǃ��K�ݘ���|� ��Xd�}%��0u��2��:� [�a��{1�yEIcZ���Ow�m&�/IcxQ�a�t]a�d��0Wק�$�S�+�%��6���frm��yTIn�������{��X*;j�1O��\l/r2d${�ⴜ��N�����\3:��7��{���="kҫkۈvټ����g̼-� 1Y�'1;�Sz��ZB��� �T>�YM.�`�3�r�����%sE�8��f�v�ٱ������r�T� �Pr �ʨj�?�x_x��?}�sL�<�Fq�us�0�",���|��[�djż��� ���㘕/�mw|�z���/��6�Db��F;c��w.�=����&dM�f�[�vߔ�4t�}�\�^��A�U#W�>�����x3�#ɔj�="�[m23���Q � �r7�\(����~k�K͖)��D=w����o_ W���D�ܬ��������b��^�{k%�y��C%��*�j�F��B���2]i3d=e�GwNFr]gy$�ˍ�)Up��tF/���\��Y[�� �D7�?���=42��O�/�l�R������k2 �+�����k���q��|�����gS�COC��6��,F[I�O��f}aO���.~\�/U-��^md���m�vFj�2�����Z��� ���ҵe��ܹ"#'R�%a9,�$Wnn �b�{�d�+UZ1�Ȧ�+�<6���" �7����Ns_�)) q��(��g�F^�T����2��Hy������W�ʔ�5�� ��m�5��&NcIQ�������ۉ`���;��+|��U/�������7���;�b ��0��6����; �� ��Ʀ����i��o�Mհ3 :�2��Eο-T����b�1�]4�Xsg@�Kྙt��#�G�Ɛ��D�� tV Ng����jm��iys�ߞH1~�R�˕ֱ���E��P�KKֈ�g[w���q��{���l�)�D�C���A��f �Y�dd��ÈSG��w�=FSsJ<>��s��\z&�l���g�E�B�MbY߲�,��`k��bD)�j���Xr¿��!>O7n"ų��L���� "x��"��}�>-�ܪ���f!���y��ҍ+�"Ɲs�`�!x����%�/7��e(�p�c^����\qz<��˖�hS��˖��lkUdzH� M�8ح Q>�X�<��K��4�h�G+�ݟ��zݱ�#4p�ܓl���<;���m���6c��:*����;M��lQ�ۣ^|E����W�i�L��~��F�v'�!36'��x��s�{V15���G�Ƿ1W�:{���x��D�*�`���7� SI�Kue�e�=;�ʦ:-d���O�'[�#%�=���=)�B��>�I:��M;*����[�*�y�7�����Z�=��U�N�b%���܃e� �mum��ʲ�=��i�6��3�8t�^�@�� ��� "C������ȝ��p��S�C�^-qjo�|Fh �}�Ƣ7��u�ڝU6�P=!�;��;��V��[c+,�D��� ]���O6�o�{��_,�! ��*٣J��cf��a6�HɆ��i�Jؼ�a��s�x�� �\q{��qo��b?1�m���::M���XAlF^����H��Ğl�3�Y��AjZ7�.�>Q�����YTM���'Ǭ%��J/�mI������˛QEr�?���r�4�s����FE�ZA��#� ����Y��2i���ن��].|��$�uƋ^4�: 2��cD�yC€�1ھ�X�e��X��Rۄ�X�5`�c�^��H�iO;wZ�V��+��ϋl/���8��3d�T��M�۵w���U��t(���-�W���Gϗ;���M�2�;D'- �ѽ�5�۾��~�?Ab�?' �ղ�*��z�K"�P�f350��wc�7s�C#� Y(4����/�u�� ���V kN �bR�x��<·|A��=lj�.o�����vT���+��Ņ��3���q�c.�,��{d]�{ Sc,?7��9V�Te��i�2��ڗ��� �:)u�0b�����_w n>ϐ��l���"J�e�%+���K�*N�0x ɩ{ ���GmF�d�����WeR�*�~揄Q�mOY���;&�#�@�w�C���� ~�e��X���-=��[�C�c0[J�����Yͽޯ���IU}��%���w>�w�k�wK{� �H+a��wK��^��Oܛ��1�_�"�;�T@(�=�6R��|����ݨꡓ,�̣�m�MGC�(*��Hb/�Y�6o��V� �(��>c��G7�Ke��=�|N�G�=z:����c� ���s����K�J�����+����9x�{�f��(8��q?" }��&���6|�����!g���ﳒ��%b�M�]Kn�ij��c�Y�;��Ԯw�������Գ��*��I�3��(n`�,Tw��/�xb��vF2H�ȶb�W)~�gBz$�V��> oN�tθQ�0%�7x�B�lgK�𦟤O�*�q�Y\2�_|^'�\*p��q��2,������� � {2��Q��^��G���Cu%,;����O�SͳU�Mԗ ��^<ٗ��=���M�krY. ���ȿ��Q�VH��� ʹ�l�3�-׫$1����$>[�Cܜ�-�VxH�sc�@=���"���,�cE��!<&�Od9��� ޖ�+��<�y;\%����%z����-�?΍�ȋ�Y��Pj��^�d��+��Wԇg/'I*�'��R�M�߃MT�8��y4gU�=}vi����O�s�����y �+����MD�dڌ�Hw�>��F%�RBV��W��Q`;6�9�`t�%=U�ם�L�w�� �.���R�.E��,�Z!��.��~G����|%(%�t�L�Ű�g�6 ���VR����v@S�:��'!00'n�]B�� ��n�ٝ��w�I���E�N �'wå�'I_ڋ����%�����8`}#���P�+�$y�L'��q�C����hp��������S�:��;M�v�U��5�YWX}'kW��d�+f�xj���~���h����z�)�.�LG�E�q-���c��v8��w���TS@�%���������F������T��| �P�7��3��i*�zFgU{�����0z�ܡa�B��ֶ-�����^ *� O�^&Ҵ���v�V�-����dXa�\��(�v]�cǫI-e����֧\D�Я��1Ĝ�{>�1�[��MrVd�ڳB���-�v�S��V"f �\I�9W��v�"8��J����E ȴ��]�: ,[��M�9]�{xezS(��w��B�B�V��f��y+��(��ՎT%�ɱ���a�=���\D�.�[3�(��$Dnq�^k2dOΟx}���hv����|�������N�#�_]άO�? �8���_�����H��i�=t'��*�y�̞(52�����R��D� �UF�H'U����J-{�m�,�!6�''Z�x˶�K��£��ml�� m�/�#��E�9�->���x�J��R�r}ˎ�������`�M�p�~�[��n[�ZW]� �����LZ�=��8� 0�A�U~$�_���x̀�;�����&�׽�y��#�Hv �j�6%��.���� �������U�b���D|_��8fr����� ���P��͚R�t����ߺ���� F���F^A <��r;q��uM5��t�����Qt�:د�����Kw��b'�p���V)�yp�F�,Zߏӽk^�n��m2�ؼ|F�ؐ��r�*w{����b��#c����@���hm��SAAS� E��F>M�j�����2��'���}��xc=��F��֞0����p�԰���<�|��56[��l]z���5�Z�t%�s�e! ��Ґ�_4�Kń4u����,�I̞�w�b ?��T��5��k����S�"��Э�n�~���{r^���pu�� �S0�4ȔS�bjrA���k,���{(�ȩ-MG�_��� ��wf��T~O�8�#�sW���=x�@���UR�JW���E����� �������|+>�(ʾ�?� k�L\ ��ӭQ���[�U>.r �_VYV��� tt|V#yhP�n$�vu�‹O*�G�&u�b�( X�5I�s�e���J��WU1uM�Ϸz"5�����C�o\o��覾sH�aa�M|��UW#kkʴQ��7�,â�k+�3��pgîwm!H�@;»������|L���9䣁X�(��F]J�kn���v�y��i#�Ε�R��}}���,��Dv�~�� r�+��x��13�O�ZVѰ}�t���R�d_5��k�j�zc�h��ჷ�s�$�ǻ�]�ͱXt.�NI���Ld��Ѩ��d[�0�ϩOS�5L�Rpy����_�a��>7�ǎt�'\�n���z.�1����� �d�y�v��vht�.{@��d���&ݐ��N�4�@U� �Ǹ���w�9�^R��N5�_Q�Z�~��~L��G~���m],1=9㗾��@���F� 4���X�� z��$�ja��� ��3���Ǭ=!+;[�a�z�UO�DJ#(2š�lx&�"B�܏=pW��̼5��Ƿt��J�̞�;���lq+��e��*���b�q#���eHv��ҏ0�$�]"�|)������{�u�_W@�\p�#�%�w>����bnaʐo8��E���������Ǘ)=Q���u%ߘ1cO�X��k�WXC�_S`|� ys�eB�VQ���P�*���O��@�#�g���D�܊B �w���"I<��&�[��Ӭ�l�ˏJZ�? ����U� ��M���ˎ�x��d��E+T߉o���[��C�A�h�������Ge������xZ�g��[Y}�t�$>[��e�s٩[);1v�n �o���&���N��'��q��xd�T���~�q�s�$���]w�D�� v"���۟(3����Տd�(2_ɐ�rn��Xg ��N<�f����|y �H;���t,唢�صp�P���B��ߪt�R�}R��jR�.��[a�5���$L�7~=����3Y��7-&NcJ���yP@ ۋ�jCUƖn��"'��RX���KG?��5x<��'�e����w~K}"��O� NXM��1W���aT]�R�<{{1 W�3v(�;�O�� ����7��X �B��j ևC�?�4ٻ��X� G�yM��P n��ݕy1Zhl�bt������ώZ<��hԼ��ۀt��z>������iW�SN~3w�*��F8�� � l5f�:j���+.�0 ޒ�4*q�I���|E��p�̰GWqz3X�˕^�� ����+�����9q���d>Y����t� 괼n��afq�?}6� endstream endobj 2552 0 obj << /Length1 2533 /Length2 19033 /Length3 0 /Length 20486 /Filter /FlateDecode >> stream xڌ�T�k�6Lw��2t7HKw�4C3Cw H�tw��4H�twJw� |��ϻ����k}ߚ���8�8�n��\E�Y� l�����Y���j�66N66jj +g[��Rj-�����/��#��"�0v��)�A9[;'��-?;?����� ��� cW+3�" @ :�P���=�,,�!Q��@gJ`���a�� jt�25��-�v���ƶu�����(�-����YY���X��X����nVΖ5���h�].@���Wa,(� K+����`sg7cG "��2�� . 3�#�.�P���6V�ۀ ���Y������o"+�_�Ʀ�`;{c���`ne (K)�8�;3�Af� �m��cWc+[c��_��DUƐ��S������������ Y�@�, 2��A�N(��r�B�����Xm@`7�����V 3��%��سj��\������P��,��n666>v�t7�d�M��a�K������=�`)�ce�|�x9�Ύ.@�+����̬L�&@ +�v�h�7�L�����Y$c�AH�m�!������d���37�9K��Cz�� ��_jH1��2{���_��b��������� �M�w��LB��v����#'���r��G��b��3�W��! t�S�ot�W��!�N��?�B��dk�d�/ H�@�jVgKG��� g7� .������ Bw��JA���!�����x�I�� t�;�]x�.���;��B�܆�����t��,΁M��k���kD�ݘwƄ��wާ�3{-:����@L������x+�8ԍ��C��Fd���Qs=bH�g��G�'�8�ɝV���W��G�u}��$�"�޿��l`����Q�8��b���޻�J����-�|��Qݭ~+��T6���P�玒ڽ���! �8?!+,�lD�z�L�]1y<W���ܺ��%O���r�Ջ�-O-�Q��d]J��[���n�d�����Jg�z�NYW�p�^������(�B+'�e d��{�2[��2��#t�q*�*C� / �ė�Q����N&kĭ��~���*�`�_)�*�7UU����|�����CA�aW4n(����D@���#��Ӊ�Qf=B��T7�k�w2�!#�JQ���&WKH��Q�=���M�6� ���*��[�c������ N9��k��R���>o^�9��Q���I]�aK����;��^3M���~���H?���NJU���]��BD2�J4�n7�ٞ�/��%�[���`<������\!Ӹ�㑾Z���D �_��0��&YW��u���Rn�V 0��W��r���Ej8��'>5�Dz{� ���P�d�i���j����C-��y��x���O�3!��􊕝���~"�ح�E���%ő�cV�(��誏��S 4媙i�'M�Q KW)ڷ����e��ْ�;H�8[˳GOւj����j(���'ᶒS�){7:� �����A�Ou|�������L����CR��8~R�Y��,�5i' �9V\D�t�@ڑ߼U���5Ψ�H�'��>�C�5�̸����?���+��;v�����)�^�0�&�E% :u��-@�� =�q��@��"�H����z�t��M���!���R���֭��,�gstc1�w���s��EӐP8���Ф9GxS����m����&�~O�]Kt���B�!�z*�&�2���p+�=�����1�l�㶭�YC�/)˟Hb�k�|N� ��{Z;�ZvP�y�;< e��ē����O��i� ^�K5 �$���a� ,�8:9���+���.$�����'Gx6|K�s�xW@�<"�_%��|�L�&�n�|�c�y`|2���'G�����$M�ϣӥD��4�v:�?6E�]=%rp����r*��{E�0�������Z�����w��u�N(���� � ���؛����t��۪o�^�GpE�����"B��;{D�,��+�N���Q��&�-�υ�Ԩ6M ��V(*n/q&s��'��j����ouj�ڶ�Uaa�0�E��z�C��6N=�w�?KL����}�� �$ǡ�%��;n,^� a_u-퓚ܲQO�8h(C( ��w������OV L�*�~�Q�N ��e�+�tD�M�� �1l5��\�C���`*�n|�F1� ���ϒ�"��[�a���S��'��#m��(穥������>_��ȷߊ��>�BԾ�� O��Tv����Zʮ(Ȓ�P{�6�dv"$��!p�4b� �� bzD�i>Î@�0Px�dg}�V����n [��w�;���H�|��k�֓�un2/���Y�5��V[K�6���1\�uF� �U4� N� Ef��}�tƒ�˲m=���i�bh���B���ƹ�����N��b/�E��IWO�-r���������2�7��ޓvw�\��L����R���bD�����wj�&�z����I{��+�/fi��}�����}諬z~2\zo�=�� ��5�g��wW-��T:�< �S�[�<�ȋ����x�M3/��M{$1��H�\�1.�Ȩ ���0��?�> �R;}�BΌR�5ī�>�hO�uk���M�p�l����P��5J"�09���,2m�ڝ*�� �����{|a�.OW��!���w���?�C<\�l/����ک��Ek�+d��]��~��-FN/�.�?i��#��:���G��yS �V�F����a�󢪤�9�{�>�4�*������ ��X� ���b/A�=O��J�/J����f�m'�fgu/�Tm��'������Y��x�?k= Rӂ�\)49��+��mH-�U�c�r��w�-h�r�NɊ��g��6��� �i��K9L�0 2,i�1D�X�ن\��+%�&{9� W�Š l��݃lI��~Q��J\�A���!�q9/k��`��K{������v�$`�h��v����0L�B��v�s� (M{�#�q���>�q�Tlw*Tw- �kq��vd�8B�o>��*t���� �@��S( ß�c�Y ��'@Y������W�T���V4��nvkT�ZWN8�48x�"=/�$Ju �J�y8<������p ��' #I֟o��,�Zj<������ݫ�:��c�]��-'v�d�w�W�����?u�f�_!9�e��; �v!�]g�&ظ �y�R2�Ք��+�|W�$섥�]�����7!�1�W�ž�6!� �[`�8W� ��ǮD���2y��� ���Ô ��{_%��%�dz�J��uKL+翖u7��H�~=�n��? b����c��gJ�����uz�l[�(%��!�#C�!�6�5�#�tG�z��x�Z�SLX������]���Õ��˲�'�\� 1-����T��7:�\I�`�tc��)� �tۢ\N�����B���AK�1� \���>�����7�7�s�(l��?�-.� ��PH�@�߼�TE�A�ť���ee�" %�j0���~}Z�/�;�m\�t!H��?4 t�����4m$�(5 o�(f�����|7j`NӠ���w��$�/�n�N5�#�E�~aqU~��U5�,�_蒖��Ag}��`�wїM�+P~��fEgL���Y�8S�]-���æ�|���Jxd>�&��'�+�~LT�D kM+�3٫�j|^��F5���}n_�JΣH]�����ES8V|�"����eZ4��}�B����#�s��a��D�����-��p�������O���/��TRnĜ�Z���:}m�~$#�9�&K�o�ݒ���L ? �(��e��l�o�v�� Ã�+�[����X����8��c��|�!����;��d�ƨ��he�0�?b�� pG��Y��\)� �F����� ģ{��3�Q�e`�TtD>g�[%�C��e�]���0o%���=���X�ã���"�k��:�F~���ð�_6V}����,�ؑ��Zv�oa�F�J�/��m�-�{lս^�A(�  pk��?�-���5��.եj������ȧ�xv(�ݖ�G��C�J�`�F"I 7Q���� ���g���7�����u�H0��j�z�јO�Am��Nup0�>�6�^��% ���6�A��f��{=�5ޮa��j����(��U�{�'�������>+LEmCQ��� ��N��!.����-�"��x�ݘ&�Z|� `������F��CYͰKw4��$��6�姛��sTV�Җ����Ul9�毬f�ȧ`념O���i�j�;̘Q,o,�J�, �� ��1��}�?��έ: ��P���F�\��o�h�� � �@��5h��<P�"D��ě�n���'��s����㲑k=a�RW.���S� �zz����G%|}���a���{�?]������u����5��h`��:ڥ+��X�u�+�L�Λ�vy� �y(hȡ���2+p�h�.��N�b�?ضce���F �x�~R� hA����ҿ��PWG���P���� �T�"����5���w���O���489�*�!�4#�oժ= u�v���~JA�p�\�G�D�5��X���4���l�:�xx2;��PZɺ,Nf,���c�5�i�{��;ga=Y+2A���|��[����|��@F����>ES F��f��i�t� �'�'F�Gh���Av�O��O|k�wh��1#,^�j�� S���Lcu���8�*�]!�E� R�#u���Dp�z6g^�?ͷ��5��x�����ٕB� �7^<#���R@�2���_��+�;7�kĻw܏��!�oI���D��d�"hc��Emk�,��(+U��p�����p2��͉����NcLF�x��5��l��A�}S�2����vx��p��@��l8�}�.P��v��Wv8.2Վ��]� fz�{�Ӕ�7��0�H%��E���|�]���<ơ���%���Ffvd�y䩵m^B��W�!#�,$�����pN�-��!G���ς�_�M4��`��T:�u;U�zF7��L���[E���]�Wy�j��NS� .G.�~'�6����,jzkw���y�W?����[�]��u�j� >��mEh�N�I���`5��*�� �چM���� �Nju.u�$�3"(cEEp���6��:�B}�֐#J�-�u�AT@vmjQ�!��(]�3߻��xl<��4N�#8�쌦��+��2%�ek�~���)F� Eo�����R���}_��ݶ���/����^H��9��(Τ( ��3*^$��JIV�P�VM��j,��)�[ݩ�߬+ps�$z<|S�B���N�Rwj�f�@��.�n�ܜ{���qt�ɖ�� �[���+`�����qrU��lu��Zc|r��9]1Wy�@./��jZɄ׶۷E�b|ho-��A�4>'#R �܎�>������2��*� �\�Fӣp�a�,�F�v����>k7�c��)��"ߩ_#��R� n�]�PkI\��UDD�����m�8!`{Ul�����1�ve�� ��8�M &&�U�7���x�,� S�]'��'3}�Ky��}��{[o�?��l-���I��t}_[Z�����a��͋���X��o5K�E}O~��Ub�Ƙnyő��'e���4���*|��t@�Q���%X��#Hx5�5��I�Y�������#�{[� �}�~���C���Q� ��g_B��z%g��Ȝ�{!ر���Q�7�2����p��>�`�^�FO5�O�,�>�n�zT�h�r����^�� }�ܐzW�|W�Cܖ#q����U9����D���NB�t�;�mŷ9j������a#EL{��C�z�; �i�F��l�SZ�%�Jhў<����T����i�x��Le��� �K��S���5�Y��� ��Da:���K��w&�|�K���V��j���0����kY���hr��F�O�Œo���W�e䤱2j+]}�S8�Ԑ��� t�yK��aQ�b�����A�kOQ��Y�����%����K��\ҧ����Ԛ_&� �<=~��F��8�Т�_9�މ�8.�D�P�vf�B�A���><�E����K(��Uo��e���l�y�����o�jd��ft燶t���z�V _im�T$�����V�u{�#�P�~͹8�v���u�7(/R�ͨ�]Pi�t�F�H�2�7�8���/�q�+\{���_[���>`�W�������Pw^�r��dR�݆&D�5�g/���xՕv������,�T�?���8�?�^�}�z����9�A:��6��X��4 �m���ɮE��� �G5\ɭ�ַ:@�D��wF�؃UnD{&Q ۗ��Rv�J�v�l�P��GVL�9���m��]PL��lTD�yU_�(���;��ob(n}{M�ݲc�ƌhCH�v{�X�m�RF�6��Xs�]��*?��a?�����u������IJ*�iե��I�M F%��K��|�'��5�e��e�k�umV+/�rC o9ah^�� �al\��b!{�j�&�Ǖ����pB�sS)���R��N���S���'R�Y?���D-TȰ�X�� ���v�=�'�M:�c��*f�C�.�� �T��ۙ�ʡ�8BûzQE��V.�ҏ� ��3��4�v���\��K!��FݯH7% ���{]���.��m�����[�%P��B�v4��k��ȵ��{��t[{������$kh�L�ZK������VX������O����ìV���9_ .�������/�� ¬18�5��7;oW^1)c��2a���^�A�^|�0���^Qq�0�,k�ށ��HT�t�=��էJ �+/i ��٬�'Z���8�'�.�m��s��}������� i9�+g���h�o�Oi����gs���׮ $�+k��/t�5.�(: �V�c%���r����i�=��Ė��|`?��q!����ffОgN���B��UP���H�#&�Ab����rW �""���Y)S 'Kt=����[FŴ����H-%�C��Q��;��W���W���E؊#�@"���.W�.�k�� �r�$ص�F�>lSk3�\Z�B�`ܘ8f)���vJ��,W�y���c�$�ע�Z^M�� ���Y�v�D�6�z?�>����+Z��(#a���QSgq���OtS]ژJ<7y ]|���q� �m=�v� ���ܜXF����ȴ���7D-*�p�##%l&���((ᢎ �}|��(uy��``�{g��La/�������h���N����Fӥк̏�ᄌ���gP��t�FF��#�Kf�U�Ѽd�(.��ࢰ2��G�h��.��������^E��rS> s�aW�5�$&2Qf��/�U�f��Kɍ�6�~c�y���I��l���N����4췽 M�Z��T>>��_B.����A<t�E��!:���&2 �VzBTD���s~�:�i�xzaz���L�eYG��e�5^�.8ѽ�#@Z0�6N�}$T�.���=��K��R���/��œ��dJ��Z��a�X� b�8 �*,n�%��S�|�N���MHP6w��� ���τ�ٰ��%} m� ��~u���|�s�5�cvf:�JJ�O�/�]�J]s[tи��"n��74���cYvdMM�" �Zm��@׾�:���xͯ�����v5�0hC9� N�4,y���k��nĉ�'�����&��۸}�q����a�-�E3�[);s۵0��^�>�"2Z���g^���7�Gy��ӊ�8CWib�y�ku��TZ��eg���4@q�"��Tz�7|-��,1��wB�ʂ��KQKqxK�6�q��D�5�g�x%D��� ը�&��N��W����I-�z�O`�hӧ Qz� ��~�b��YU����r�ϋd�J]B�3�V��'���?=u�������ܹ�:Fn$�]Igmi�F5@����.Cm:����B��s ��ŀ,��{:X��N5$3��5f�� ��z>�g��b���.��kQ�5B(�D�`�~��=T���#먲s칱aw\h�wBP��ǣߝyƯ竃��r5������d��$����O/�Ogs�Č��E�\�C���i�$�a�}�u,1?�b���w�DO���{�).��TaBy�LO��`����z�0*/o�R�9���k�4x�*�� ���1��* /v��u����].n�՟lѹ��d2���(cF/B���qj)搡֨<~����SY��+j�T���n���wEQ.�2M��I rJ�1�φ���gR�r�\>�ݏY��?��P=F���������{�s��K���6�T ��o�b_1�1A5X^�<����:�/u�|+~*�9��/ːr�3yD�����z�Z�=S�X���DF;üq �m"m��R_4D^�1��."!-'$��҆밧\��Y� u�� �j߫� Sҵ�� ����0��o��=����?c*"������Vlg������=��ƛ#���eEM����YAw�>3Sm��4ҋ�+ p6�˩���<�̔f@����=v��+ ���-B�����h�^m(�c/ۯ���i|���uX2�&�3�ktq��.��<�u�a�zL[_�^aO�\�La[njMsH�� E;��&�v��á'�a���Y*�b�=]��o&�<��� �{"���ހEVn?�M�!�n�q�*N��eT ��#=��Y2??�h d`���Q��=�EJ1X���dhlq��x��>���M�M9��<�9����3����������� -D��l}�=e4�����90��Z�osr�GdʗF^\���� 9��uTn�7���;��Ə�*����\ ��J ���I�������p�/*,W�Z��O�����<�$oTZ.˂�8���x� �K�W�#�0�Q�qD���9l �y0�з��>�nU�_uլ(�,[�,U�Nb}�f�0�8hDA�,�8L���o��#�J #��U��o����Y��ϸ^�L}\–DB�W�lh3n���͋C��3��w��S������~,��ʃ�N�$��l�i��Qh뜠����h���V������]"�*�'�|5F�5����$ w��Br��w ސ����ڢG��.}���ۑ��7��H�ҷ*x�LE�M�{j�x��Ljg�i�Z;oҚ?>��>�� ���s�M�;��BtŒ��;_ �Bn�=�����5���:��X"�[S���4��I5ʵ��� �aG/Dn���D�[�2���P�v �j�v*ݓ�-��[Sw���Xmw�B��Zi�b��U%\��OW2�{$��K��Rz����y���':�Pf;�!�+�2������c�J��^q��ZF���DI괏Q�6� �%�㸩�e��V�_I����Q�S��jd�i]��� �:"kW�Ng�熣������i��%��%��߾E�&O;R8�k��$�d b�Ց����Z����9�o�;���=j�V�[��^4GE�G+��q+t(�\�ZO�n<�΀�×��JϓU�"xA�&����e���N�R�Q�\�C��#���ٗ8�Qf�5��y���0Ȗ���,���9�lͧø}��Fi��^|mP�<��L������M�������ZQ� �j��8�[�bt��R����L�@F��l'�:�'��fk��̫��(��}n�Mp�Hn2�����1W�̂�4$u0y��-J�>�Z�Q��� �2`Xu qp�w#|D��^�`��l���ޗb��P�J�Lw�I��w�sG�`�0��ad��x"u�˕*���bwcX�~),�_T��� �wog�I� �&2��ޛDk�+�.S�uM��w#�Hp0����)�W���[��k�,�eLs �p/�6+DH�o*��=�G(���t����y��8X�9Nqߎ� VB)�����΃ �h�|? ���\� ��=�.���9!G��M�U�{�!��Ey���xͯ�Y6'�����}ļd�)��%OС�ÈfsT?І�����U��_�N�r�"��w,��+\�B0!��M����U���R>���]%8�f �J��~#w� {�  -$l�+� |Z-)��`�(a�O�}��S�Ɨ�X�KVg+�w��2 O���޹1�d�����1W/�R� �������rѼ\g2�@L����7�����~+[a�]v�����Po���?!Q�5I����u')�k��Z��_g�'m�>���IxKJY� ��P��T �i_c)��7���v�l�D�1��2t�x#�2U1#�` �y�'�A���9�.:ihFҔj��$ ��VzӾ��������U�kZ\]�߫/���wK2���6�[��X�0';{(�e�w���8,D��Xsm�U�_��D����� ��ҵ��ӂ�=�^�?F��6��3�Cte�X����?�ǹ*��L�-a����ru��2'�,�ʽ��e�x����N�?zE�e��+oq�A��MF�����:[�O�FS�U�*��1����[ff���k��� )���x�P��nI=������Yp��s��sa��s����$����L�Kj���Z�'h�6f�E�Im2hb�:��6x���$�DI*ad���4���3�"A�Ť� ���b�P�3��U(ߍ8(��85D4H�H�����G!��;�[Xd�;k{������L��K8l� wwOr��_F���Eϝ׭�5�m��B{�?4+R'[�� ��h"���I�:���z�R�@�?�g;=�it-]$�Q�5��,z�w6f�LC}�e�����*��q�0\IPT>ؕ�����O �)S� ���ئ�������]VJ��p��w��/ Nb�}��Q�1ُ����~�?s9Te���d��I&�o����.����ۂ�Ӳt��Hг-q��i��u�A"�\Yݞ3�x���?zح�s�Q#ƈt��߹P-t�'���3� ?6�5��%ẋ{�&��L�[n���w+S�r��9�#Л��l�[6�z���/ulr�j�����#�� �U"�e��J�* �?O��%���Tf�+�˜�s;��3�> �t �۞�u�-f�tVb��>Ϗ�=w%n8��q�/t��\�%aa��Đn��E+�����o ��5�[�-B��j\����{�R��4e�%��S$����n>lvr ��8�8���7�D6������Y���8�>��U�n�Z����V�� �3�B�#\�aNw4ߞ��e=SpR���s�At��g��V�0O������#P+�V1���6�m#d �q�c>�%� >}a������� ��3p�z���u��d��\r�:����]��`�fE�T�����zV.�I��o�Q�����5�$� ��w1�T?ѫ��������'�����]E �|)�*p��������*{�UF �����*�{T���q�EE�mY����4v{�J�(h|p �|�{!�dg, K�������.�B���������ŕ!���ל���}���'�V[���^ʧV�#��r�0�}�+�H��aEK�bEh�n����s���[ot�v+� |?m�}?=�-�`c�s��M��� ���]�L0���ַ�J�+�o��>����Ew�c󵆥�� s.�G��~v��N��R��#{A�v�G��9�D�<�a�r-��n>��ܠԠ�@fiVʇ�{?s��Ğ�IRC�w�����q5u�d��ɗ�����d�ɫ��ʳ��&�a��t�D< �q�7���v�0J`��^X�'?QhT�EMmqF�!�9��?� H�Sz�d����w|�F���,ӥi�˂���f���ž �vaM4� -�W���q߻�Ý�D�vz�S�9���� �]�����Q��v�<�"�pLy^]4$��t�%�=�?'D��~��L>Z�:�+�7�)�R(eY�H�vO^gtb�R���ƙ�cp� ��)���S��T6 e�Y��^3&z��h#n=���ٮ%� ${�|D��W��H�a�˳��:h����N�)ɔdQW{�6�-�I6U\�f���4����2�{���T> �f����E�-~+1\b�6������CO��'�}F� �n��eS�7��4����JV�nY+q^��-��.j�����F�+�T�U ��{$g�lfP�X9�Y>s�� �h}��lϰ^;w�g�j۾ /���X�ZS*�2J�xB�T�˽�T�p�^�z~��G�)�'���^rF9�\��$��$ٲC�)�TO=�}~E��!��K�������hD�b�p�����0˽P����_N���+�5��c L�����k�~��.�F������E�� o�rt�Lz�d�U��;��rڿ�/NW�����D���{��j�e���BppM�M��Ȱ�̅�[np���J��� ����8"f�ţ�^i��"��3qC;Vw�k�!�"�E����=S o��%�=g�����S�_��:�V��dn���1E�R��kM�5��Z��6̋�A�ʫի ߈�O8��Up:F�!�@���7��5�t�S�X��Z���j@;R�qn4h@��Y�d���9�s݆YzJ̌�,�}MhCQ�K��whM�(���=��̊+�h�)�$`���!W�R�)�� b��z�E *��=\�Xp�k�%%�q��e��_�i�0ܵ�h/I�*c[PH�I}d0�mBm� �E.w�����,���:d��րm �HA�t��*~��HP[��S�ݬM���W�Zb��<-Y���r�l�Eg��N�$M:�%o�N�!�Vf�\sw���ǀ���O��q� ��j�~'��F$�EL�Oc+o���{Ӄ�C��~��t8�b���M�i��4k<�&'H|��U�ىX�Uι6hg*�:�!$*�%xw�5�Ԅ��5R͏C������2��C0?'rޥ��Z�y�}%M���#AY.����1VW6�C�LB����-<��Ӟ�cD&~j?�=�=�t��[�" ,R���\��j�.*=N8�?v7�M��}� �)�x9��o��>VωX[b�.7���Ōr������`��w�(�"�v4��B��c�H+�����*R�7���ɨv���n��m#��V7�c��� �d��]�%XY� P��m�>iMc��!�8I�ݸy���S�n�5�-�GG=�h�xn� 3'J�h9�"�#�2�G����Ot�# Y$���q���I�g�,��̀��5�"q���uY���{=�b���� ��Y�� ���j���F횧E@z�A ��%���_��A{��JI ���L�\���Қ_�[;*T���sL�:Ů�����A���6��@s2�첌=7�7�.�{�R[� �!���i����fi� ����*��� �J� �]�?g�0P��KlE�D �ٽ)�2^#R�*ѓ'��QD?��Y8x3`�����לoO�X��L���G����%\$�ٞӷ� ��7�L�e' ;��~)��&Ln���gnb��Ö��Z���о�h���LS�{��������:��2ђ�������' "�W�%�&�د譧�Qt��'H;��6�<}_̍Ɉ��i톏������fx��#͂i�Y��ԝEu��<X�@ܩ0^�>�d7T������M��]G��{��@:�N��A����S��qH�iI~�u��E�V�XmA �ᥖ8>�% #�����T�@`������}�WW�7L��5FAhD&�툨jE�/���U ���su��g��h���O4 ���^��)l�I�`v/ ��p�r�j�y�އ� � ��9���^�y�E=u2[��s.;��_�/�MX�/�+=D�^�!�d'�6҇�~��\,*�=4>�����A�#*��pmMB��j�$�� d� Ye��t���bf^�,�XLα��n�uv���l��&����W��-����R�7:W¤� �#>~����Q�C�zj44�uŌ������ԗ�lh�Lf����hV@o���saB`R4Fs��r���E�ê���P P�]�{-���� g��8�F���#!��.%�E��C����X:��9f��������R'�'7u��#�K᷅�om �,�:� ��Hl<�ҏ����SoE�#��ڇ��xb�"�t�ڴf{3!:tޟ;&�W�I��� ~�U� #m*a,��X���� XO0��ј����i?�W#3и�"�o���4��@�:��~�� 5J�j��^���ֱ��h 00�M����Ȯ�����FfQ�M+l�"�e��أ���Ĝ����E��vH� ˽@a* �zH�,)$<�z�P�F�>X�W�v�+h$0�QU%�9���}�%+{'��ʲ�❄D|�Vb7_p���~�L�h��11\ ��� #�q��l!�I����;\�Vݮ��L^N�yp, ��C�Ծ���\^���6K ��{�'oB�ыzB�sbq��,}���u����;�6+��o�e�����{���7U9��.��_Y�40����e91Pu�x� ��w'R�n��_�4���c��7���y?ON���F|�M����W��~�9j��G�l��=���e%u"��Rk�K��>Y�E`��U��4-,&�������]��g���y�g4��"9�"B4r��׉k} �- ^\��)�_q=m/d�؞�k��]纡x��3��XHn� Bd����6s�y��� ���g�_h’�����q��D�|�"#+��oa�6��q�����)��*ګ��o�V�p+�/fg���s&}��;�w���.�X�5��Y�i���!*��ȡ�ɺxA��w���&�1�c���M0!;v_��(C��)�1��X�xnr� �������oޮj4�-�����aG��E ���H5��HI��=��6�.W)�.9;�@?�1-v��c������-�]w�->?hٺ��qE���������N�a��p=i]>��.a4�������Yͷc��y�6j�T�?�Z,{��,({���,ߣq�:�}ɀr�'8���vAMÛ{tLv~\\N�O�m�T@��v#`��b�k�O�����5��f07J�RB7��(huɩm�9� ��?�>��E���{؃Af���ٵ��'��� _o��.4� �O�{: �6��V���&W��v���m �M1F��ޣ�ˑw�c�S��' ��� �w�1j㵵���T���m7�d���u�Z����qe|�a�Y*=~Ud��H�����z����� H��_UO|�jC���&j멃}�S��z&�~��;��\��6$� ��*ܼoh��;1�ޔ�oW2����BX�[7}K B�,��ܬ�.�l .�(Y���`��! V�>Q���7:�|�%�=kC�+g��v?�CU��- �Ir�� R� �T�� R�k}�W��ܮ�s��ܭ���c GjE/��%�,:c�&5f�#�5~��]�I���$9�{���O��ҹ�5��:�M�1���%q��Z.�����,�E��SVN��3�݅S�d��Ư���2��j2q݁�<'�Kf�������6n�V�V+���AS06�"�0�u�������} �D�k�q��@z�pPRHݍ���k8Ճ+Ư-�&�p Nc���I�ɨ��(�����p�ZS���f��9��gL�����O��Sr�O�mwF�3� �c9�D��Y��zf+u�hFP݉^l[��ز��֎�l����.�'C�]������� �f����|��q��>���4�N���?;�~��E���+ T�C��;��ϡ p}Wxw���1R� ��I����PcX��{E�Ff�l}#@��7 J��(2uY$ �nl�A�*��k�QG�'���HR$�2�Q�r��Lv(}-^ ���'�O�k(�&B�4z,Ƞ��X!�;�<����<ݭܔ\|��gF� o����� �P�,�m�|��-�Y��&R85F0|[�o�� .��|�����d��Z�2�uw�������H1�y��`�����b���dH��ݽj��]��U��>J�& ��f��,���p ��C��:q��@)�G�l�9�Q�͒���ܮ�ev��;������O�S|@�o�u�/�':���!u����y�t�l�U���t�c�I.�y�U1��CS��!'�%0 ��{kB<���n-��� r|5�* ��� �9!�1(��1����?��uE���|��\Oq}i}��d��G��D���e����8����yV4 ��@�{�^9�i�`���- �)8�~d� z8%����t��Lt��� 2Q%Q����s9@w��n���F�;Y��S�������/ʼn<�����u0�<�� �%(I5`y�p���5���%5��)���ʿt^���|ݐx�5A J\Z�V0�n���F��႞��'���[/-F >4��`O���g�� ƲIb��E �` ��h^"�b�4"%Џ*xOű[�]�h��*֖{��8CT׃�Ǿ�;���>RE��4��C��.RO����&VKo��u�o���6�B�d_���l��a�ܛ-�Ō�y�����-�W*&��c�����h�f���m��i۾���ӃD�u�/��;��4��G�%A�4��� ���v/$U�?#�@gv/΃�|f^�����\���؉�u�8MC�U�)X6[q��Sㄒ���Ĩ�q�O�rkP6��x02<���Xjl �,�Ϗ �@E�� 1�w_&��>���1(����+|E\S�&0��h��,�n�;�>ӱm *M�>�]W����D�[�W8v<�lA"���Z�:Y0䁶o��lV�'|�܈� rA�H� F��̐�y|���+X����훒��5U�`%�I�<���k|r�4�%ƐlX����8R3/�!{r��� RyT�^�+����g�D��SZ^l�x9�p��=��K�n��.Ҿ��k�)�W��ͻ@��=p���7lż_�#!�)������+W �G�&:Fg/�����#��̿q�Nr���s����))R�4����3�7\;2�,x?W�l�N`󩗰&�S�l��9� (al��_P7�O ����^���(.��r�]�����|��E_��P���_ ������9�;�y!$6'�J�Q������֚��{C J'B�� 5]����1��~�]�.�����*Bά��AM��^"�TV`����C�^���kT�> �P�z.1 ���;U�|"ɏw �{~�:C�*�����.*��A����B_�z�e���`Z��[`!f��„�H ����r�hH���!��^��`=C��Uȉ�}��Ⱥ�M���eEʎ�ؿ��w�LSf� j�0s�H�����ѷ���C�d�2z��Pm�k!˹6��Vi3�����3骲�b�*�h,e�@Kdm�G�D��w�>QI����ㆡ<�IռTU�m��Z~�����bA����9���.Ɛ(+�+B� Y�tg��28��#FTH��p�����n�0� F3�E=���&��������jB�}�9s���}�sY� � ;�cC]m�C�T\�G� ҿ� 8��7��E,�]4�s�Y}�L�$��t#=�f�(O� ,}����'�K�Qگ��Qֺذ��������^]&hLԈ��Փp�3fnLk׸�7�T � �WhI#� ��poH۱����X@�;�! Z����?,�.-_4cf���^e��x��w��./0����!� CxÃD�{�Xi)w;�#��R�����{@b[) �\U�O�^��&:qq�V4�G�/�P,^^���؏�S�J�6�΅q� So�������� ¾AB�*<�Lj€B;7�.)kߏ �"��G��O;�* �i���]|�u+Ï?`��6,���ߵOG�v��2n]P;� ���� L]�ZH���� ��=N��u�yt�CS_������t�}��� ���]G�L� ���܌l�(tz������:���(A/��}�G��e�zk���˳ҪPe,��,.���r��d]�I��F��m�w��-#hD��4��E����#�)�U����̒�������N��o���-� �"nw6F�@�H��ϝX�K����^�d2qt��~&�m�o��0s�U�ˢ#�y������Q{35 endstream endobj 2554 0 obj << /Length1 1912 /Length2 13529 /Length3 0 /Length 14717 /Filter /FlateDecode >> stream xڍ�P\ݶ �������� �'84�H7�����Cp'��k�������s��꽢��c�{���)HUD�!�@I؞���� &��������̊LA� �����Bhk��y�W��-����&n`�(d,,lN^.^ff+33��Bly�� c�#@�!S�A�]lA�f��}��@mD`����; b��r�f@�׎F��h��_%�����y����� ��!���4�'��@h�u� o`�w4Fd ����� �����x5X���`���1����"��` ����z��/����r�f�U�;���bemv�M& K @A�3���==�l�W����5���di`��7u�����u��3�Y��1ځ,����2��Yl,�������'���w�� q��2��M�����I �qJ���jB�c3�8����x�@��Ȍ��.����,�_g�p��XL^�z�L������ �{[����v�7Bfa����@S�O�W3���z�� g�W�W������ϓی!`K�?�1�')9-I�G��ST� pc�d0�r0XXX�\��]G��/���+ 6�x�����������wAh�]K�\ ���е�9��^?X�?����*�������/#IK˿������ �@�.�F�*���u � ������VWh r���^i{��m��*������3�N� 4V���#��j��% T�؁��` ,������cF���ݫ2�v_W��J�� ��+'��������_���u)���k���ؿ�^G��@l��:WN��_�'�I��0��A�&�?��$��� `���XLR�@� 6���`���^���A�\>�A�\���W.��+�� �W.��+�?蕋���E�z���rQ��^���A�\4��W.��+����#a�G4����4�^�1�R2�8������������������ߒ?�uD���l 4�S���_��u|"���A���|�����~ʹ7��/V�� ��қ���k���W1������F� �#>�*���JB'��QVv����KD�- |�%_1�� ���y��ӿ���0X _�-4q�-t�'���,Դ��nһ�c��}v`�-���E� ll�sҠ��t)���e�`�n''���8`�b�S�!�����߇��nXE��/Mzk����q�f ���������(5s�&++��4Y��)�z� O6Y�q�pY���XX��M�{x��?يL��H��~/�.��JNF�C��^�] $�Oo}�^����2�5@�0��P�ܮ�%E�e �\^ZE�Q�9g�wLq+��E�"��;�rT�B�d\�V�҃3%��m+��z��[p��z��7��� M'}E�w����݈'e����"y�����������J�]MC���~(���;H�5�p�/ˁ�M+�<� ���A�Ja����0�/-�2m[>���/V�xi��XN(µ}/� �z1"��[�d‚��D�CX�u�Z�\8 ��ez��U�u9�T2�3}��|W +G��G�(f�9��H�C?�� ���� ����$�d�kW��U�v�%�y+\#f�lR]>k"����H=��; .#�Iz_+Կ�%i D�d;��6o<ח$�v��{\(�t �K������a��i�ecu��Z�l?8����}s:ܯ֘=����@�:I����S Mܮ��#����G;9�5�F�m��ȫ��+��v�\-j�t��W�R<�r���ɵ�1=���1m��wx�iY��u��0�B^U�(���X����)�cۉ�g�C�qȅ9> ��� �BT��-�Vi�%�/���])yS��̕A�>:����w��pQ�lr�����M#�f�6�럑8H�"5�ǡn�xb�^.�(=�z� ��^*h�����D�nwz�)�-Oj�#�3����|�����v!�&Q6����L/T�(T�7�?�R9e��r���;TM‰1�2zވp�� `3i4��KBpK�a�/F�yZ�Z�&Y�1�)��Ud�L��O]�}ޗ2� h=��: �i�0U�yfT���X ��"����U.�Ô������t~H�˜ozCrα�I�]F���Zc�#��y���˦s5\>a#��R�{;NY�ꨄ;�pq���S9�pgj� �eS�j�l+��rY�7��<}�����X;�Z��!��ٓK�V��� N������z�ՄWU�+ϸ{�Ä��>�V�Q �8� ����'{��-~���md�.ٝ��i-�)̗�� }�I޸�cv��T��r��9��cW�#��:X�C�����/0�?p�K����5����TJ@&��9ay�Xj�����.v��I�9R���~�Ǎ~�xb�(N���Cj;��o)]�r���y�XA�hM/�B�����G(]��Ș'γQ^�=�dk���yT�e�S�o�- ��� �����w���6���\y[�E*�gLz7���Mb�t�>�>r�;s�/x�_P����^Y�|ĆN��"��oR���T��6�b�Yp�g7G�ς��,}j����V<Ҫ3iY'vĭG�_��[0��Rjn�ix�%b�v?MD"9VHA�{'����0 d��v��u>#<�V6C��sw���\C�6mU?�bg��L��#�6ӹ"��p���o�ΰ��|6f㭷ޏ��w���6\"d���Ub(�ܚ,�0�n�h�������xH)�V/q�ka�D���98�w�q�`�oāZ �(.~=O�9�<����ض��7�%�V�f%w �,4�=��oQ�ub�svգԑu;?���,��3�t��J�k�nd��*�*����Ξ%�םt*�m��c�����S��������ybs&~%S�"��|���l��$��M�b�o�7� iu�����7$|���A�X0��i�h�@�����W���:�P���μ�j�tN�h�)~��̳Jdb�C�V�׶�bL=�OB���%�\����i�T2k͚�b����w_����PV�#:v֬-����~c4a�ꍮu,�c]�ĸNcn!N�%�,�Ļ��ǗpGuM ��x+&�*����24z�ǯ+X��e%�iw)��% P�V\�t��]��/�o��V�vF�) 8]�E� 9�*����%�w� bs�.����8/D�c�+�N=<3("9h+I��z����.���h��8��b�ڸ��m9��h!����9K~�#8��0�3������;BAd���|�M���B������'��mK�H�����_�E�����t��.�f����\?�E� |��'�5�M�9�E�� ��y�N��x�ۘ��ӇU�����6+C����Huͥ���FLr�z>��#�oĂ���M���S�4���L�0/Z�>D{kN�3!�g���9>�v/(��C�X�� ս��f�e^�D�b����FY.q 4d%��j�C�?�I�(\~x0I�F�^����Z� �} �גq=�]�!� Z���a#���YpH�3~�ϡW��0��P����r|�o�ǟ��cA��פG V��|��{9Hܡڢ����t����G��9/'Мq��� b���~q���w�؁����T�-Í|JL���cݝ���\E���ɛ}s}�I��z�&9��E/�W;�_,�H����\���y75�S��$�p�7=k�P���w�]B�����VِX�N�1au�Cn������F�}:������ҙ8!�Z���zIeQ�t�H'=��n�7�O�|�Đz�s> ��&r��H�w^`�2|Y��[��Yv��XE� "���"8?����g��ܵ ���`�e|0�����,�Va},!�� �5DD�e�/�ؒ!��#��%�2���#� !����b����b�u���P�t�{ul�+���6MZ*� �_=��K;�Bd�f�8ڌ֔~���5I���3H����:��7|^��`�U�MP9k��4i��]g/ �����ᖝ���<iX�3�\&�)N�G�� 4�Y���k��>�ɻ��� Qw.c�����2.�����+M8�FNWf�b�>��s��]���� �6PÒ[H]0%�֢�f�[�%��{���{X������2�1�%�� ��-�\>*����"^o(.�7uP��(��j3�ڃ��zoEB�"G��\���\�d�����hi7z6�խs� ��f����#��RA�Ք��Ʒ-�w{�5�Y��w�����6L�u� ��nŻ(D���W#��:�޽~���7�r1�5�1���l�O��ɣ��������E �>,�3�,�R ���==\�+d� b6@�2u�l �*Ϣ�8�����x�� �����X�Z�Z�1�2���+���4���C����.��� n�t�W7o�}B#^��x���`go SR�}V�H}u�O�yU�4��-��m�y'�69 �� �m�� ��<���E�q<�}�z��Ny�u��Ȟ�5����@�J��$�.�/9�,����?���5؈H�{6���7�~D�����a�,��N�.�c(Ll���WW�q�Nb�:�S��J*��r��m�S�� %2���+�q 7�}��v!}�>:{���Ÿ(�M:���5��Ҁ�6��\�k�\a����*x��������p�N��DIt�"3�2R�������T6�&_��#��ڽ6ς��0<`�N�t�}�s��_ݾ��J=cxWX j���U>�S��>��H�S�s�G:.2N��o�;*�C��r�}��UN�v��z)��X�5��:.�{��*ֱ���&�Ip[�f�^�&�o4�hl)��W� �]:֮��ޝ����x���LR���rfx����Q����j �?>e�~M���M���.G���8׏��O�;�l�] ��Ț�8M6����-t�H�C�a�JSƜHǺ�,� �ި��"� i�������C(�<ė~#��Vv�>��܄�/D��/�-��="�^sV���?�]i��]�4-���iߥHO{��W^n�J?͢�?����؆w8�w�@�]5��Z,�KH�ݕ�ʧ(�U&U�q�}�Nʻ�ɱ�I��H|�oR6��!�f�f'"yDŽan�7� UQ�+/]QL�V����7���5Q�k�F� `��E��SE3d��5M�D��]��=l/����eL=8 �,�݃����$;���*�1_��ď����!���v_��i�a�ce�����?)-�3Bo�~jQ�����#_)&������yB4xZ���+���C�HM���qň �l�fu�5���FkD�̛l���&���2t:��l6��]O�8W j2q�lqe��l�B�B��מU�j����w�V !,>���zb�t>,��j�����3�6с>K��d�������*9�t0���S�L�l���we��ҟ�]���nn79&m~� u+�~ܷ�w"�����Vc�V#�� H�`�NKn�u�/�Jq�)�NI��������H]��X�/,l�ͧ�����3�X��YtЀ��c�nx�R���:N9��t�^�藺� '}7s��G�.,X)���]�X�^c��<� ���@����y�"t�W6އ�JEy�gPb���9C kO|���y�=_��^���i⨖o���/���;m�&��ʈ���?� T�*?�Ȋ��a����ġ��hM��ܞ5�4sF�KU�7������d9�yv����(����� ����l8>7,~��M����X��KA�9�E}t������>*x���+F� 6���\_R��%�!��rFk�zܴ~�R�U�/ҁ]h������3�L�Y' b� ��[��ka�^�!� �)�Y_�CA�E5L ���}g�7��3�s~>�Q{�+^�C����bԿ 5�Y� �I�"wf7�(,2u1��O�(�;���>���#kh�����vC�����s��.��Id��;XPl��b���t�3�1d����2!5�|��>�4��̀�4��+��]�rm�wc�)�R/Y�Y����60yA3�o��ߨ���9��JkھcK�\�OA�i��͋A��/!�8#q �9C��a���~Z3� O�Ǘp�X����x�j��,ύ�6��ވ}�����+M�p�`�s�cy�dǸ�꤯Q���$Fr6L�_���y���l����с*����!����d �� ��fW������%��lJrF}l���oܦ|\J֭�D�`q�c`����>C�@�cUsz�i�d��j�կ���TZ7üx�u��1�M����0� v�T뻂˷�$W�*]�!3Xm.2�j�L�پ�$�a e��j"Mg���#�;�����%�2)�,���~�w�y�-�ԛ���sU��`�䫷>⭥^��)e��e�x����]��v�g��a֞"Ǽ�Q����<��oc ���kMU��>�4G�Zs0@�x�܈.p*�fZa�A�7���YvDRCʉu�q�ZRH�>*���%�-����8���o@1Wo����i�u���2�Z�Ie�~������kƵrP�. ��]�{��(�B֚o�>���{�0f\��!�T:��� T}k���ñn��x�!;��o9������>A�{�,�MqS��؂��K� �~6��T-��+�y ������&���>x;�����ںH�V��uRb�������p����(u�p>�-�ce$H���By}��W #����̳�����^pLzs΅#֕8l�����ʞZ%��54����xgK�i��@O�E%wl-���1Q�����⓫?�� 0JYqTu����%]���`7�m0�''�s��SŒAyP{8:f�((U�=�N�.���ʻtg���`p,]����� D,��T4;�ݔ�Q�{v>�+KY1�oɀ.�~�R�ՓH���ڗ/��U:����@���J�M��S?(^��'{����x���oX�����(}5&�����"O�6���mϥ69����fW˄u�~� | [�,��s�엙p���9��Ý\��x��p�\���������8�; �(I�����?��lЌ� xH��濜u0MU�:����LM�� Ԋ���zO�@(�]$*hgd�\�m�K7��_��!o��$l*���s�͇��s)��ĭ6��+e����z5�S �O�|�]����s����Ɋ�J�&�ѿ���7�6���9��`ڴ�L�]̢sqa�+D`��ʳ�l�?�.����y9�J�y�iS)mx��}�f1�R�8v�J�8'��du�f�V���82��>�}�S�ke =M�����v=�{d��y ~�X�A���a-�g9Ul���R��zu���x$��\ p@c���f#�1t�7O��費a����;�B� >];���i�3R�i�Z�i�le��7�����7�Ÿ% ND�ɯb��6=NZ�o�ڤJd����]�r�2�,K��+�Ngz4��q��bi��.,s���.ҳ��t�R_��>v��&�i�<GH��#H5 {���kf������Y$�} ���g�H�N�2F�a����(�MZ�rY��}χh��&��l`�{�ѿ?�6��65�<� � ��by��J(���aT�jUG��bm�|:" v�֚ؓ����?��zfF�� s��)�XS+U ��>���I���>��j���C�oE��I��=����e���f�Bwri��h�hk��ƴ樑_�A{U���Y�I�\�j��\ ��!Ƀ��!�<��ît�/cj|�ѭ��N@h �k���m��La:e�� ؞d�e�^��J�`�q�����R�W� m#��L�[�+\ӹ8��c�?Z�)�� �y!�sw��k���n�dq��{PHpI�G�>���U�L}˘�V�º;��Qwѷ���Sz�z5��8D��֐� M��)�@b�/1"+M� �tj(�U� *�u5��V(����� V��}��§#_�q6o�n�i�Lg���<$���Q}�Կ%EV/i���.@�,�R��:��M�e��+��Ir&H��Ρ�'�������1��S|-�m m�:u(Г��^ v���f��������7��٢a�|/2�K*A��+�(�y�Pc3�����8�&�r�%y�@���b�F��3=-�ۄ��ԏ@�%s�ט����RLQ���'E9N�x��_V)�(ќ�iA�ߘ�|O�����b8p2,�ƸKɂ?Ԗ����uη�r��� �܎��?���9aNC��U3jM���� [��'�)$��mˋ�K��,�X$��sm��͊�6f��g5l�>��ٌ��@,�Du9��cژ6冊p���'l_��Z<�jO��s��ei�k�-y�L���r�����X2�YғrSh��1,���Fe`��ٴIb��#q����l�eRR�x����~�Gn]�]�O{�PS���� �R����]�B�c�N�qӧ��|������W7��7>1w!��w��@��\��s�H�9D��/p���&��'�2�.��\����P?�{~��� Dz,*޽)��T!���.'��’~�(����V������0RZ���j۫F�R�04 �� ��qE.�i��> ��#M߷) ���.!�ͦ ��2oV?Ɗj07�;�/�8G��U�G/ųB-��� ��� xw;��h er�ns�g"����$�\��~S����P\������閿H�Ub��Ȼ%�.�t?��QOg��mHU�:U�ʭ6��!�%0��o9�:�q�����L��>?)g�����M�!b����'烵��]�OF�U�W�Jc������:���\���C��y 2��R}��aWw�T[D���6�j|�k��������;Z�h]B����G�u-U?��yɋ���X�Q�<0�D磮{�V7��� �jq5�~��[���IP��E!Q��ļR;F����� Q�N�:4��ߞ�X�W�lap݊� �r��h~%]��� �s�ٔ���;�AB�AXy=I�t�Fq'[X>,�뫖�F`ƅ�Б$�n�wJ�Eqǫ a� �kN���0��x�N�#�c�R-��ª��t�g����ʛ���{5�����A���N��M�e�L+գ���Ϗ�����az��l�I�#Lsi\U�IJ$��=�S�� ���f�(C'��b��D8~�i��F'��Di>-B�_�c�)����N��Y����K7���Jk†i���d��B,t��������&(��J�u�9�������?�L��\o{��jv`9��"q� �i�4�a���Ҋ��>�����< m�;�D��(�b��=�Z�r~`�����~�W�^ÝG�;r��">��M_�F2!=�"E�� �C�tQ&�HAPz�#��DGE�&|�{=�悹z��n��l~k�����/B�06�Y�(g���(�A�B�4Da׎H�6���U��R�\Tj<�8����l�+HW'ł�e��0�}�:Ƃ\u#t���ᡔ��SM|L�F��Md�ޡ1�m��ըb��q-��[�A@G.�������鑌O�E��a��@�Vp�w{�P��~� ������A�^H�ʸ���,#=�����c@b��ޕd �J��㯴��(�iv�j�X ��\�q��h����r�L�K6d6]Tw?��\o���>>+D��E7��fM���?̞���;��`�@7��+9f�&�!FNy�U��3�!3�F|D"�{���d5x���I������GN��۹�� ;;�^#z���q �W��u�/Ȱ,#0VS��^�P̫d��VH�*�\`����I?� ���J,a%/p�Œ�f�[��1����������3��!6�ʞ9��췩1�M%��y��w� ����:'S�o��Ms ������#��duiNq�tM:ƴ � +Z�J���A�(�Қ��S��VE�c�Gh���g�΃��Ȧ�o�~)F߳���[���9�`�iw�˶k58`Z%b��Dz�?�4⬗�lI![�J���wG�H��"q�Z��a��;�>����M� >ղ�D-unj�n�2���!ǿll��SR�� ����m��No��.�i�@�*�O�u�:n�f��^:��Ȗ���h����Im��R�$T>��I�a2C���ϛi6� yvi֣+<��M+����(���J4gEy�W���A��ˬ�#9�Rh�!po���~���5�y3���O��N�O���$B������̋:�)%ݭ*���,��\�VJ�3 ��֨("`y�b���H=R�O��Aǹa�}�t����A�a�,�>��֢K�j_�����%~���{L�z�����%5{�*�����:xt��RXkCX� �A�n��W�'M-�v(�B���N�S����BkY����s%$U��@��-_��T.���1��_�R�"������H��E�(����wMAJ(����S� ^>����Q�L�<6$�+���m �K`�+K �0®:L{F��M�k��&����%�����'�ݒm�p2&c.9~�r^�YF�n�Nc�S��� ��c���Ý��} ;�SKޗ<�U/R��g��mO���O(���~�% Ԯ-qt�r�Tg4�uJ�2�[69�5QXQo@ 5"MO�N�<���$���歳����N'D6⥂.++yиa�K�D�ڸ�0�n��p��F�S���Wt�^}w�H$f�- �m�$ }أ���b�Vn���2N@Aw�]���.;�H�0o �Ch��,>} amH^?���\�mY��e��+Ɛ�Y4m�� ��L�z�Qlhk�;?޶���ŜF��*�Ɇ������?���T��Lyo����,.�E��ay��� k�$�l7dH �#} �%\��ϽM"��;Yf3�`��ײKISn� �b�W(�<�R��6�#0�Z+.5����r��8�I�ǟ 禎%'?Q��5�lϏW� �YI�쑳���s-��pQ�<ԭ�y�،@b�[�=:Rs��,�|E���I2������bP���� �˲��! k��M��F��J.$sY�a�)�Ѫ��*��K��S�F�Wr��5H/��R�L�� N��8��:w3�1z�ɂ�ǂ:xRN��>4b�vm^Ó�� rg�d�jW�د'_�J��͖���zl���� �����7�4�{� �;I�y��>�ecՏo�h7��$�"��i�ݓ��?��2U�F�T9�z�~k-6F2Yaq����.M��Z�PW^��:i�R˪�dg�Ȋ8��ًۜȗk�U�OYB�1��;��q � y�@b�����ү�'F������?�r��n��1cC��Y�޳U� �������E���a �~iq�������I����}�e[1������҈5�!{�?,Fݓh ��cR��Z���g�vCtj��`?}����}����E�6) œ�릗�W)�'���.���z�(嘐1�Xb0�x����ơG�`̙�Hmqo/n T��+$T�y��i����&yS>X˛BL��f�1¹�l��YG��������Y����y�"��A0��7�Ȟ�&ݏ ;��:�j��[���Y��Es�)��;��L�~�w^N1�LP:mQ }�:���h3[)l���������2!��e^%"UV�� `Oe���Żn̘���oZw1#����&W7���G�% �`��������_/:}~ `\�z��^�Ѯ��Q���l��� lY���4��(cWa����_�)MPW��*H�g�1�νP��X�O"���ط"䀹x�$Ǻ�@��n�6�o/=?,%r���B'�%�6��x�_����r ��T��� �&��7��������Tt��=��������풺I!�Cltb�S�u��S����������� �=�Aj �A����1�����O&]��!�����>IY�[ ����//g��o3|7,�[g��䕎�s��h��J�[�yI"���1F Zd\tʹn�M�ܿ� ��DƜ� xb�q?b՛��ۢ��wiE�D-:Xk:�*u]�uj* �����N��� � ��g։�(�����è�RU����Aon|�y��]͔��z��ޚ�m��`9QyW�W�!������F�q+ᾌ�zrE7�`�X��V>>���5}B�� y�N=��[�D�#3Y_�P����}�[ޥp�5�l� K(��D����EC�]|T��D��)щ�wy�j'�N�s;z�ܾD_f"����C��O�R��-�*����Q��H�R~�"I�b��3����|���� ����F�M����Hy���p�*���g̼x!bN��= �%�� 5u�,a'`�9{�3 ���OW� K��w�]��?ꃯ�v5*��ז�]-\�� +-х��G�U(�Mj�q NS���.��j�+ �A�ˣH�l9� ąVjDB䡾%s��ėF8rhe!y��6�����c� ���dȳ+t����[�X�{T?�d���}b�����NF���l����U� ��)��Mjuo�k��]��|;k��]���[�iT0)䩈r3B[Vk>t7��G�D(5��z�ea8O�N�������DfQ��KC8ߕZP�b���W���pT�s���� �������S��0�q=�9 2 W f����x�*�U�,�#�[;� ��l����Ċ�R�]}� s���K֎��7��������6��}�!���uxm�t��S#��/�߀���.sz�j'����a6s�_��� ����$ �@���`+,�:U|t�\=��DŽ���|,6$B��x���A��g�4w�U^����#r�@{@�o��V]�^��X���E�6��D�V{�ʈӓ^���A����;>�^�ͯ�3�N����"����̂�)��ٳ���&1��W��Q�'1D郰���[>���kwdC� �7�*Hu�M�����I�[�M��:�⫲���z�q8�X�7�W:� o ���V endstream endobj 2556 0 obj << /Length1 1385 /Length2 5981 /Length3 0 /Length 6931 /Filter /FlateDecode >> stream xڍxTTk�6� ]�H� HK�t��0���0��� )%]��! �J H  ���� ��q����k}ߚ���羯��������&��N(G� ��e�z&V �H��M��/;)�9� G!e� �� c�650 �C!���8$) ��b@��_@��,@ � w�n��P4)�*������������dd��~��ݡ�p �c\��؊0`���������xȊ��������"(Og~!��0�����P'�ϑ�`w��DH��.p�o� ��{BX�"��/����0��x@�����B�?������O��Dp�`0�r�#��Hg �� 4tE0�!��F�Q�x�7�;b�Z4��`��CC<����9���4�mVG:���ݡH ��gjpO(��~�� ��A�����N��c8yy��!�w���j0X��6g( �����wP_�����~�_�_f� A( ;4�b�H�`o(�� �o�?W� � ���p$��ٱf(��{��p_� K?���;[,ÜPH����_G,�lb���&�g��8UTP��a1���$�$RR���1����_��H �]�>�ղ���?����QX�B|�P�^@�g�� ����g������H� ����� ��`w8���\/ Vz(����Z@KW��r��WƪA�e�0���o;���:�1�߬�m7��7 5D��?�0�( �_>�� nاK�_.(VC�������~�MLB����b������t���"3@T��`C��0�'�σ�b�P>�� �#�G~���'Vl���-������P_(�ta��p}�y^���#�~�pe�;&�j Z���Q��.Q���]��ч���Ss�,��}�<� ]��*����9~� ewB1;OH=�Y���l�F�`�oÛj1wq_�W|��f�e7z�Zf�(=���`��+�w��>���ZŌXݡJ����2�6���}O8S�c��n��5��������GE:}��5��Lt��9�GS���so��qxT$NU+ғ8�J�#y������ v$�{59뫆^5���٫%1'�߻|�j��c�E���5%�E��!� w���H�ZqDA>;���{�� ����Jw�9��^����$�C|v2H�6]!=��!��cf�xq+@��Mk������5zCH���x���T��v�Αި�G6���$ˮ����m��W��꒘z�ר{���ę`�||ÎnM9k%��I�Dsq�BS�צ�[8��$V���Cf�(h�>V�=Y��|�H>�U>]:xoi����чD����F�_�=Dň�t ��]��yocn&����.�U��C�� T���Ӗ߻S����y��S��rC�5"&�g:x���K�.����g���xӷ|������:�h�qF� ��%�U��ǘ� �u;OZ�={_šO���l��nn�z�m7���VyWE @C�;_F|�F/�G&�,��Vo�,*\6������!� �� X���Xcl\�i[��A� ^�Si0<���}5����o[������cf,�z^fy)�ݨ��,���j�(7 p��g� ��{�r^z���/~5 Q�4&E�B���fM��c�|y�;�j�]�9���w{���ކ��ri���o�"�˪��pV}iNϾ6e�O�m��>_��k��B�D1�d/�?�0�K��F��Cl)k���V6d�,dӖ:ik���A���}�%���~013�n��W����}���,���������$��6Oɳ��r% ��=����2nd~� MZ)~r�jï���L���I����9�������a�з%>��c��%Ɔ�\�-m�?�^�w%�ߘ�.q��{��"��L�B G�e�}����7������Z� ��"] �g' ��� �nul��Vɫv�7'��������� �^�X���u��\!���{w� ��@�1'�d�=ɝ��<����S:)����ǧ� � ���o�d�l_c�ֶJPCƎ[�Rъ�>��석�<7W���{DN�8�"�=5��C�M&����5�~y�������i> �K*.`�OSo�$�z����7��Z�攍a3�B ��`�ڸ��q�SS2����G��|�&P��gqi��[u|m泇+�����0����g����7M��ʛ���z�R�ƾ���OL��o���u��#�bԮ����� T��h�e�6��z�<�UM��b�i�Uy#��y�]?�uYh�c��+b�o#�� �H,��v���-F1��k�������}�¸�l��C����=441��[҃�=% N?\�L��C���݇6�2�-{�:”|��i�Y{�����Ѫ�����{����e(6���2q���� Q��f�:������"$B�c炎�����d}�95�OF�x�g͆�H�I�Q�I��B����9E\�Th���č�NQ�Ũ��[�J��x$�����Q�83��������ՠ��t|����{� ��h)�D�b���{���t�c�qq�NN����r�}�,uHꨰb�g f��xv:��>BD�N���� O�c�{���ZdZ��Sz��)(r��z��6���� ��V���m��ݘ��=p����� ��m���E��m?`�c��16�7����n�� K����*�\������`�i)��ZL=�� �e�`)��{Ka�3[V`lY� �;O�'��Nq�d ��F��O.*�8����Z���.�7��/X�Tf[�'A~<���0kڙFݗ���;�Bq{��ю���Ҧ�@}+�M�X/�!ݲY������_$�#�`Sf��w C��.���ec���J�n��e���6ާ �� :{(�� =�t���V����8����ly�fQ,{Tq��G�C�+��c�9��ɓ�N�G��e6�o�{;�#�l���'��L��GKD��HPa��՗i-���Ltk�e�A�곓��k��8�]�.0�U)B(��C�c,�Χ��� ۟�ڥԧϣ��0��cK������q���isU���<�Wn�f� n����{��ӈvKʻDJ?�b�K��bO�Zݔ�m����S7�m���X@61��f%�� �%� %�^@�p(�/xZ�o��?<�f�bޯ����P)��� i�UxϏ���V��N���}7n�Q��� �R���O�� ��c�\mi��� � ���C����_�rD���ܽ�hŧ�� -���{x̭�O��{��r���K����vn[B�ŒD���(@=�~���O��j���� 3&��ߍ�͍���^-=��Z����C�"C�h���x��C����G�F�Y1�������W�������֘�Ʒ�>�L�҃ܣ5zE���]'!��_��lO>a��Ѻ \��C�^��C^�˻�!�W�G�[,�qnG�Ċb�L���������յ�s�|�܋�,Te�F칢@�o� lK�J�z���'��O6��Eg�x��\_����1� {����$᧲�dΠ؝e���� �b�c��)ɗSuz��I0����T�s�,Рf�ꉆ�G�a��5y��T�d�{����~ϵ��M]�_?���5��骞^;iSC��Ao��ڑ3Օ���8ͺ��SC��dtg�Dݹa�AἚ�B��5>��rv�GF VuN[uC�h�U|��p'�l�F9g7"��4|V��Iq�'�?�9��om*Ok�6>y�j���JmZ�� h� 2����f�"}ĥQ�*CKm�ȜY���o�a��2��|GX�РJ���i��μ�K�=�F�V|����U�S��i�ɭ������+7���꠹ۼ���o���I)È�P�鋹����(��R�y�T��Gޫ�='�:K�z3�⊯�+�l��Z0��Q{_O�O�I`�&G�r=�$�̒6Q�pU[N��ô8 r������v�Ix���e����)��bC��� t0� zW�b��K-275�"�'�_ZF�r��cˑ�["��#�H6,Q̓�9�l3T�D:��hkl�*�b��M� �!��b��6%� �B�,���Ut�Z��?��VʐKI�{ˬ��k�%i]����5�8U�Y� �Ì) �e�����T���!q�S�t���Q�{[�h���C���� �%N��L�p# �2N�_�AyО�dqd���Ii(�'�] )e֎j8s�;����ō,~L8�S�3J4�H��#�rU�!� ف�ղ�=H����ހ�����L�g+aA�2�F��%���!���χ�w�뚮�S}p����-u<�!���ح���5u>�1(�O���[Yg3�[�t��{��R1�^�v��9��iޛ0���q�D�Ϫ�ǒ|9�s�!.�H� h])ז����s��'�S��NGT�f����o�S��'E�ɭ ��>$�K��k�.�����POU� l�s�� ���}~}���f2Gh�) �˩�Ќ�5~��0�/���;+��d���e�gO��ԉ3����s�H�yD��;^I��uI˧�T=j:�DLϣ`9|�J>��R��^���{{q �/;�v�����$Ck9�ӵ��bW��H���7m]�: \xK�x�4�M���D�,>T��6+���X����}��$y? ���� ��ɵ[~J�?��V��z�Ч%7 �8���(U����Ml? P��z�)�Xة��kc�N��&gf���Ǒ@z�%�o���k}���f��1��f �$���}�2.�m��}��G|=�h���G�y2y����#?��u%"����_��>S�o���k�磻1��nzd-J�J�P�g���3}#1���~n��}�mQ���g���bM^�����s���:t��/31]}[���w[��FO�O�L4���$&f"o&�吵{�"�:�w�� c#�.���w��֡�b���z�P��t¡�!C��e���ĦZ�Aѯ_�rR�Y�? 7��<�|S���[�����Ve�s��f~~�6�î��M�cV�����]!e ���Fl�h����جUr[0Z�Q_`�i{`J&��X���)�4�;�m�{��G��G�No�}1�|.Bj�y9t����ޤc~������; �(|'���'��<�8/����ܨ��O�~>�9L�:%z��Kg�_M!h����g~%;7�!`�����8�@��f�n���Έ�W�w�LX�u��S���2H �\����\�_�1V�)� �c� �����#��A��4��$��Ʀ�D�!��͘X�Ѧ��B:ǁeY�Wӄ V������ ���� �>�L����Č{mCĚϞ/z�ؑ>[M���ۊ��[�9~�C��g�e�H��{��k@��eTDIB��m�Y�/A���Y��?�om� endstream endobj 2558 0 obj << /Length1 2268 /Length2 18442 /Length3 0 /Length 19791 /Filter /FlateDecode >> stream xڌ�t�� Ƕ�+�m۶m�Vc5f��n��Ic������>���q��+뙞�;�\�� ʴ�&�F�b�v.��t \aYIF3 )�������0�j�NΖ�v\��v25t����|����\m��F6.Fv.� 흸"�n�&Y:�����3 ����������G��|PS99�i�rښ:Y�d ],Lm?2���-M]<�'����=���;���3���9% �����d�l��fj��2@�������`H*��+���\� �LKcS;�W;S'�Gv��� @����oc�� h��`�c�o������������������`fic ���s�p�ڙ�64�q���7t3��14�0��tC���"����s6v�tpq�s����#��04�ڙ��ښڹ8���O������wO��������?������w&���v�����"��|�`���M]� LSG������*��)�?z��v�w�}�a�kif����������j���o��"FF���� ������O���������,=� ��`����o�fbog�����'��R�UP�����*���=޴̬Z&V## ������Q0�����Jڙ�8�.�������� P�� ����%g�1���?�����`�����y��r��7忣�����H����/=���?zC[K�,>&���c d�?v�����������&����W+�b�� �v�M��B�����Y����D�������[��{�l,�L�-_�/����X2c�+��1��L?v���ۛ�^6&V6�����'��[ V�7��V��z�5�z:;{��G��3{'������-� �3��� f�������8�r'�^����@��_�����������c�~���HY�>���[:[�q�05��>R������_�p���&��~��H�~�]?���GN�?����_��7������̿�۟������6�wu�W������g�@�7��Ň�_�>Z��� ��_��������Z���Od�W�������w�?�|8������?�`?v6�f�ea�G��?��|T��֖��z��T9�y������� �������T��������A���~#S����a��qO�8|�����D�b�d���������_l�� ~��/���������_ɘ>�{� ~t�����H^�N����6vu� ������������z��,��s�XՅ�?�~r�ݛ`b�����R��v�W �y�f.�^�����r�T��l���`���ͅ���nf�C�3���t�,���K��Kˀ����E���� %&����\֡8YK�}��9$y� �DL4$3HH�`VG�P���l�$����i���c��(���r9 ��V���#x雬#�/�l8�S���^Q��x�����@ #�1e~b�l�ݩ+���I%���MЁ4P��x��Mh�\#�m=n�.���QK)*_��Y��{+*�QyŠa��ŦOB��r��}dj���T�S�gҿҌf�6)(_{/0NC�F;�Z�u���+��@Z-��M�Ԫ��!J��"F]>�����M���sZ棧�=ӷ�ӷ�@I�?�=��3yʳ�g��W���蟇�̩5�s�!r0U~J�--�*0�o �u�j���&K)�Ҝ��6��� �Y)pF��4�ym�� �}�����z�=�|�L�ɾPO{�S�3K�����w��3� ���Q?���w��%��UW�_�vK�\cYODrY'�� � WmI1��h�� ��3[�kp�脁/J��_a];�6~�Na*�m�^_-�,o)����̏��6xq���㲓���Y"i��O(�O���C�t�z�΃ ż�S*P4�~q$4l- ���9 7*���1� `oKvU�o��8_� �5�~��x�Aʦ{�K �v�l!��Z��`�?�me@����XTV?K�`�"�NCu��*4= *�^��y�8e�v���͐�=��y>'-o��YTF�2�,��T�mR��:�].��q'�_�i4�f�}�s�2��d>�U�N�EDMB�:��C��tk�(�]��1��+��L�4Ď�H EŻ�tC�����X(�,&Hz,o���`��� }H�n��u`���P1��s$�F�ݤ:E0��$���u�BI�"3��v� ݴG]��#f&�[��òp5��ie��۲�F��d��C�M gqA���}Ą��4�i��6���X5vv�* ��O�*��Q�.p`2����ٳߕ�^� V|e�} z�R�^��˪u�-��t�=�9���-1�|�Hsw�aᇺ�LʦԶt��� 5K�.�J>'�Ld��Zp�R4�(�7�t��L��I�J�X��d��= e��S'P�)T$���I��(�~C9]l��C3��=������+�_9ɉ���89��Z��s`� �[X������75^]8UL���ݭ4���K8x�>7�5FW+���T���b�}6a�~y �g"�*��Q���������Q���E��� ]�c�� �0���]�n�|�^��q="��r��2���'� �0g�,�*|V\Hi܇��G�%j_�4���+��J��)�Z�~}��m �#t8+��l��l�(A^����t���U�,(?i��T�."Nz���n�4���M`_ ��Y�����pW/`�?��w ���^vI�� Bc��쪐�Il�gЧ �d�� SLA��gz�(�f쵕��͘� �Ai#IyշH$3Ĺf��N)7����4�$7�dE)?�ҩ �@��Lv� Li�p��9�Yg46�{�Wm�cO~!���-�����$z�p�p�n���8��+��.����R�Kf‡HX���W�W�@���*�*f2�k�PE.�!�/�7�v³~n]w�.�@9�A\i��4�A:�ؚXg2罺����j ?L��n����^�b^�~�K��]^�n��i���%�|9֗h�"8���4�$L�D�@�h�f�%�l���J�#FkKVey�l����虍�P�������Ω�ͳ�"��W�:߂x��1�џL�5W&b�9�d#� &R���L귪���z�߄�WAЫձɂ%/σVq%o�oKP-�Z�}4��5}ȟ����j�U�Kՙ����b\���-�xH��U�Kd��\_�n��8���f<_j)���3ծ�݌�.>��Wb�"��9U��)�,0hwfN ����i��o��ŏ�l}H�ua���tX�J:��J1ݭŸ��>N�o�(F���4fi�.QY�vxO,Ck`΋� Ye�F ��T'*���i�)�*�l�/��v�5�Ǚ���<�Zf�{���#ɂ�� �:Kd�7������洺���9�����a5��<��IA�z��~�v��F�_�e1`��0e�s��s�g(�<+��ΨHI2�)�h��x�r���ܔ�~��;��en�|qT�&x��&j&�1����.�aJn)�֌�M)�ƣ���t��P;@������tJ�Pd;\�p�ͻ7Ĩm������1�ʨ�\\4�?�*����#��~�e��S�E�4��}�Ү4�iY�S*s i�"e���<��i�=1��W)H���Q@w=�#%���dD�_��|�$��,���Z���k��U缏�E^�.f�.N�4b�[�G#�vJb� �mv&� �O#�%� ���,����[�*�հc~ko����V�>ӣ�E���U$���k[���Ϛ!���a���1�:��;��b���p��m^�=d�����n�� ��1H��+���ڭ�3G�=Ӕ�7���#[O#A\�-��1HF� �"Ŝ����b��]� ���ͻvJ��ݒw ����c^���I��&�W�7�Q����Rjl�[E�|�./�dL�����Z�$o]��\ ��c�:g���wm��nV-���2)a_�����~�@�����hpC�&�D��G�:� �n([jܗ�L_p�{id��/M�����^af����cFcw�&��`OF�� �M�J� ٰ��kVD�}��s�BJ2��6e�)�z0�bC�}��[af��{�Q'a�y|�Y�c�{[��B�t��ܳ��-�4H 1�+���/�^�S]1�����I S����j��ԉ\'_ɶ7�JN��;N//5����z���.M[�Jz �a���.(��s]��B��Ds%��"f���>щe� 0�;\/�I]��Q}~���1�n�V��#I� ��;�X����w����@�yM=)^GIp*�4$jeӜ�V�g+Z�7q�Hx����۝�%.!s���cU�K�?ŭ�'�μ���}J��?���#�`ꢹ Z� "R��{r�q rp�!2�>!Ԕ����W��'��������6�Ӛ�f��k�f�>Y �1�S��O�C����gi=��$$z�m ���Z�򓥪`̹Z!��L"��D��[�ۗ�lS^3�A�)�=Rt����]sy�᪤["��3��3d��zj�|�<&���ҷ�#�C����=.>A;�'���2�����k�+*�4*�����o�e�عg5�^?�gJ61&��L��@׬�y��.n w% � H0S�X���a&�7Q$������]����_�G^�'\qY��@!�8_䶇Ac�f�}������Va�ٟ�x���}���j0e̎�ct� ��|��1L�"�#�<S�a��a�]���_qp]:�Sb ��o����ҁ����!I�]�ZX<��Q��g��]��$$^�6�^O�5�M�З��WiA�]���/�.�JZ�Q|�7���iX����R ��[�`�ry��=Om�|됊XX��=v���9�-ɿ�2.�m�γ�K�����8��W��?i^���J\�JLB�E&�����nϳ�Ss�N�DaR�k��K��"V�U;�~�j���'��#o8υ�f=� ˠ^h�\��^ �&sh�Eŗ�b�f�c�����| �Wg'��Uˡ�V���1ĂO��F�B{����|�BPj'/���&a�";���W =�ͧ7ȳ�gSEE��sԥ�+!�� P���WĄ������gA�Ó��,��=��A[5n�'�}6T3y�1�J����1�/�H��L �˗u�3�l~b��*���=�R�`�˻4v��b� �O��}�w��o��$14�f�'U�:*o�{����\���~s�,�8��4y_�t$ڛ��?�r���n@}h�eߋ$���E�7��]�!��.�����7��\3œ�o� )H��A(�K���h5-��6\UZ�?O�?�t��������%���mu r��J�����/.�<Ƹs �׀�\fc6�a���!� T,���;E��" �=|��ag����6_��r��غݵ����������j"8�1%�ܻK �9]�h@Y7�d��{�GN26����������O�T'V%,Rs[:w�N ;�uORr�n����2�UǗ])C�F�5�n����I�p( �'�,���D�NJf�UR�WrP'���|�S���Κ$��%��+ߔ��� �n 5�t/��v�Bs�pC=�5��Kd�0\�] �c��po�*��qd�!��P�+�U��� ┗�÷�%�D_cS��{���g�WmV�m�Ȳ��pP"����݅ o��t9�%Y�5u%�PW�:�U����o~����YGi�`�� �\�Z������>Qe����!_�}�y䐵ջ #��V8:�u��(n׈U�+u��f�w=�Zn����{�y�{L��b��ǩ#+� ���ҲU��.�~��ĨLq� T7�v�d��aH���!�T'�S��4�H��� �������� c�4����&2CEF ���]���Z uJ�hR%C>�Y�rX��%�onarSIc [2M�b8[�|:�v��mڵ6X ������`�i]y��@�!S�:��4wZ-d�4� ��#���� vVv\�6}���~q(���}�����i%.™�R�t���,u=:�]i`�@1�5�:X5���r@`�B0]�bC�3��J=�#if�o1'����mG��á�_-�G��.4�6LD%�Uk�yh8�<�z�ʠ��e%2��BX�0�pH[��5�̜��2R���se� {y�H�r� H^���������wM.���� fb�%w�Ыt���„��"F=�P�c��e8KV��-Ӛ����ꯉ�W�1������.�yt���W��<}� XZceP��� _&8�jWU��1����JlbRJH��k�o\G�¶��M��"m� >��&�#LR<�ϊx�/�bb�M���#�!H��u�/ˉ� _�σX:'M_�4�`�E�LVk�p�%'Kk�Z|J��w�șͻ����n��u�äw�'�m���� J����z���Lz3+w�d���c����16,�/~�$�<���5�����7���Ÿs��X��s�j��v#��ܭ�Ѷ�;ؠUT�%���n%L�g��7�<�P3�aJo��F3t��5��@ ��М�H�`!�3���!���<�_!_�۞���d�K�Wx�����.L��u[R$u���ma bӂ4T���Lē��� �|s�Q����Ʊ�~i*I�*& ����=}� _��Jo�s)GZX�y�d�q��c ��n�V�މ�o�^Q�3���ޏ��aN�8;�F��~r�����x���aS�af��R�6d(o"ω� ��Zz#^�e,L(s�St�vE)*�=���^��S�x7�;���H}������<�FJ��I�EC�eZ�ʓ߅�Rǚ�S�5�+�B-W�Ij�y. ���D���>�&/5�4&A��Z�^��?��.���ݜ�h�%K!&Om�|S`S�1�� B�<{w��Wk^vmW��K�\UV u�n+��_�����x�"������f� Bh��%�v�O���n����֮t���ţF�q��(� ��j��x�u�³�dY`cz8K��>.�q��ӽ`vC���Io��`��$��S�cM챪�A����&��w��1[k&�/���%b�� ��b�1��Ҳ�t����ݭH� 3ZT���I8��-xs(�  �2AG� (��QF���^ Pl!���Y�N�~�T͂��$E����;��q% `%!#��;J��I�g� �9䣕�:J¬u��=�ô�9R�:ge��q��t���+^ �IR+� |C$*��e��m�&�wr�{��a��9x�g����-.���'��LqZ(��}ڢ߹l��kߟiw���g��Ά�����TqFX�� �b�&��Va���X�p|c�r�0L[ֽ ���p=ĭ|5�*�0[ɸ_��S[��� ��m'�Ɖ��}}�N�CC%XS�晫_����`�O˛q���1~������{��Pfya �֔�m`Cͷ���F�*߭r��.0p���������9gz<dž��stt�E?�`�<��7*d/�_�I2FB]Uz�h��MqjKXc��*wg�A3VE�}�o�*�����xja�2��V�Y��@_�i�iю����S8�]Hl=��`�'G�'3[�F�z[ւ,�r�;j;JfX�'1�����<#N�,������ �t�"�E�O�?�PT��� Qھ�< iI;�H�v]�t���C� -���L�%������3Y�qM8�CQ� ࣘHt��l*�淂�#8B-l��S�t��ɽ� ��֗�$���]f�u B0�Vq�ɟ{| �F �����/�,�����y8 ��w܀(����%��v�zW���B*��)���C�~�=)cw�>����� Ѿ|�8t�a �����u\N栙��7P��dy�+�T?�}�f���(:��;V���+�^?��C�6� hPk��x1� ��O*<[�����<:U]t��,�0��Rk��E����lĽ�9z�D��(3�P���k�S����n�B�����ٛ�jz�C����(�,se�4n>��[�@f�T�%�]i�0�}n-O��pݸJ��w��)� �Y� V=O^P�(���_!�o��+�3@I����D&-y*�|�#���ҿb��a�/!N��������`�_�v��`-��Y����o�CɦYC�Ա��~��d�� � ��ߧ��� ����C ���\��� y2��@���k}ũrz$����O��CC��Kz��`1�����X�*a�(��-V(.��o�IyU ?��n����`[��F����������F �7�8��}Q��}���%�W��F�m��)SG �2�r��O`��o����r����� ;ϔ���!%�>��sm��2! ,Xq��������WN�g܏ɏ���PvS��H����ض���&~���ET���'ǧ o�bL��������� �]�斖F�"�v�8�������v�}�^'l<�ν�#Lԕy� �|~U$o7��f6����U2M���ܢ8Vw�G �[�POF�� a��nW��@7y���QI����vC�g�:8~�4e���ͅ�� M��C�^K*L<��1����� 4?y����H�Ɏ�x}?K�s 5?��"!P�I]��z~< 6Q%�m}��:F�rg����z5�;�^ɮ�g�pNT�%�&R�pd�_�B�WQ&{����E��@���6��r�KC�6ק��f�m8֞���c����V�M�4#�q��&C��*ߑ�p�ީ�:c1�E�����װ�U# ���[�����e��a�#%����Hڤ��M��ɑ|h v��H��ֵK�[�����O�H,����ݚ�Y(�f�,�{�Ŷ Ŧ/!WJ[5���R�3e&_�](�{Ɗ}1���̷i&�{�꽄�8‡�f�o{h�@�$[Fc@]rr��V�> 0'�ߗ��t�[�ߍ����Ʌ4��>nl�Bc��SAMxT�~y�D�@�E�w���8��<�O�p$h��ȴ�T\�w�zA����N��'X� ��^�.��Y��㘏�bmi�p)�y� �.��f�8�co�T� #OƜ�U�n�~�f�;�����eh��`�xولPe�(�Q�(�h��\q��Z ��s�V�悇�t9��)��–�l���,<R�du��HA�sٗ]�k�����t2&H����ўrn�Y�C,^�N� ID��`��-�R��Fm�!�L�1�f,8+����mX�$�=��[ξ N�g%"��@�)�?7�����T�ˉ�ꍆND�z��z��B���ّ4%Ԣ"�7��$!���UԌE�<�0��|�ɥ�31�&�w��y�� `�G��ɓrгr��(|0q؊�=�g�u�,�0��=� ���o��9y�T�I�O�TTnW��G'��﵎�񦮧LC�K'���Rmh*�3���5 ��)�:�m�(9�3;{�<`$he�R�,�8;5�l>�"΅Q�FU��K� �FF�c�� � e��D��ޱvT/1FVh�ȏ�M����3�?w�_� �D�2^��*&�'Q�TFaX#Eo5�� �7�Z+�9\�6��E޸�>W�Z9��ůE�{�*k Qo���^%k3]#,I3�{w �bR��>�w�*A}�엉�yj���A5�+�� 䈆�D�MUY�����K$��P0`�7��,i���<7��_N�7bd2�T���'Â��X����b",6������ �$�}.#�+��f�O ����� ~��gM�B�ITӈ��wR�'���ޖ��PV ��� �]m�tO�{�k�$U��${wflN��n{_e�̱/(��X�!�k��I�T�V ��` ֕ �����( .f�����$i�6�p  ��*��-��� ����oes� �П�5B{�Ż�7uQ��5��~�!t �āx8������;���B?�O='��g?�8�3tbf���]t��k�fi�N�gTH/�^5F�e����w�|�M�d�N�xr���<IS{�p�%�|ds|�V���/:aS C�Җ3ߟ��R�z���XU2��]6$�D6���#�;s��Ns:(�k�J�l����U���ɛXp����.�s�Z���H����γͱ���$[�;s�*��?�=��1�{��I�OF`Ғ�ϓ�U.k���[q�Q��(��N}���$]�� (�� ��g!ݑݭ��t�xRN��`\0au���V*z��J�*?̾R#��1��T�Dv=�_�M����$=���^�s/ ��J_g������ra͝c](~����~��Xg���(�� q#1u�b�'��-u��D���*�ᗁ����~H�11�;;y©����]jrXg�X&`�Ӻ�X#5��_�h���2�1��/`Y~Q�$��TIj��֯�\յ�8ZȤ����������@R���:��i:� ��� ��?uz ����$�:���Klo��$'�N")�Hl�2��v��VR�]-�3�a�I)&h#%L��,�x�]$>��<�Fm��X祖ՠ�$�d�9վP�6!=��X��T�9�7�2�[�al_L����d��yTu�\~od;-#�G ]q���g�bT��%a"!<�pN�"�MQ=���z�B-/3�b�/��`"P�� ~i\�{O�F��,�I�N��*Y�������·>vӫV�������5f�6���A��X�G֗Tc)�����˰��5�^�u���e-,d�R�F�����Ԫ�j��� 4�I$D�st��U�V��� ����׷4�������j�c: 3u\����odŽ a��E7��]��lf�E>/� �n����S��?\�2�y�hg���ʅ���7r�şsX!a�ՑI�R��C�M/$@��a�^�@��j@ ����SJ�cXҘ&��->g��co��?}w�(��{D��a�$4�?>`hI���%�9�t�\YՏT.���O� I�4�ϻ"�ʅ�rL�A���V�iU�����닒pSJ�+\�;��Ҏ���Ж]5�m����dĤ�q$rf A�ih"�7�xV���YǬ� �>#���q�D�����ִ������hK����Z��L9�U���˽���Y)�,O��~�'|��'��G��T������u*H)�,���N�"��-�MeZ@�������`�w�9�u߳����g��s����� sEWC�o2�j f���O��8��������� �|���D�Kި��D��9��&uh��?�[LT����-�_G1��i< qp!��#�ȖV�F�g�>SkEq��S�qz��b�]��� j+9���` �'��m��op9�ހ �)�S����P�(���m��Gk�8�����:��J!Z�%�M tt��M�v�[3�!~����|�T���fui��,mi!�B:W#�n���`(��}�S��X������:�3�>�\�K��F�=c�0�ؖ�>��>{��Q����m=�����?24�2��l���4dpfp��RM[���&`��~���q���"���p�Ȃ�ӛ�a�,i�I�.�'��z�l�$<�+����'�GSH���+���T��Z/��n�ܚ�L[� XB�pB�d5tO~s�E��?gB��{���"a�&iň4�6����p$J�RmEȍ'�s�vV��G�7�� �֩E (χ�K}UF����CO��� Jف<$��L]�C��e�Z裦�^_鐁�ཱུ��ά����U=@�Wn�!ؚc�a;�Q�!��E�2��ۀ`ל�Ӟ��X��p�"��F ���%��V������ELN�j������.�-����h���bNc�9��L�Kb ���P�e�w���� ��$T|Mdx�5�)�h9�*��9ܾ�����B�v�Xg/�s{DTY��$�'2›��抗��9�O�W�]����Kѹ����#!<0%�>w*�����>?�`�*���Z��y|4ĉG��O�@��%]��Q?�[IQ�!Gz�=(����1��C���h�ևג+vY-%dg��ؚB.�Az5������ xԀ�K[��t�ٵg���e�F�2���񷾮ө$�ʹ�)���L�4��&w�B��mIW� ���]m;��e�����L� �%u�9�ζb��^�NV�R�@=�A���2�_ycW-q��H��no�f�=�@��T�����*P�(e����|�V���$��p��v���t$���Se����`�\��į��}��7��Z��Sm+w����s��������F���61k��']�7�f�Qj������,Ч����:���� #ʾ.II]��󩤔5�<�����:��� ��{DRg�@'����@�|\�Ы�F���YС|��Dǩ줼BD��;X�8�2h��.j\���Leſ<� �Q���D��@ JY]�q�we ?� w…��Ze��/!z�/@��P `'�2����,L��k��qO�5=&;����3�W� ԡמ�d��J��EDz� zFS`��S zm(�`����4ɝ��n9~�Boԅ5�b��v��4A�ڰ!�ui{oәj��o�P8�j��<+���p� ����("�)d m=w��|�0׃�mU4N�����Ct�q����~%�+���Ú�Z�#�e~�7�c�T��L3����n��Ӝ6�� � �_:�\V8X�1NDžYtT�m�-��M �p�_U� qs3h�?q�D'NR /:kF��]sn����D>�S0šű�D�:%jh*�X�����‹�6�dnМJ�>��z�'%)Rck���/�ůL` �i��+lKf�ry��|E:��B��Xc��T�����-$�ڷl��8nά�CVh����l~�v�Ɏ{>���.�U�a�� ����ś �k���v�����c��=���羆��%�kY�E�����t�k2��Zn؂��ܭ*�iF�� ;[S9�=A��¦�s�P�d�-�t��;hDC�'����/:8��� �dd��+N�����e�%D�g+U�@YJuA1Ϙ������֣���}b�;,��3}9Cw�������������T�?�k�m���} ����ڍask�!���WA.��,o�4 �ı��e[i��h��X������xI�@�� �Q< �R�vc ���ɜ-�:#�=t���'�0cm+K��%��v���fyDc����l˧�� 6߰�u�#�}'Ed��x��7�Km�����N}Q%�zMm����m7+�g0ߎ��jw{l�f�K��Uݨ|]�C #�k)��(�6�3�����yE���,�Ȟ<�ZP�(Ж&fsu�#�����������`1��I%���Ɨ2�++� ���漟_����j�/�*�H�T!q棏o0���6�A!���D��0:X���WC1�~���j��D}Y<4ɚo���Z�f��vG���3�,?����Եx���LQ���G{��Go��N�V���w�Y%���V涌�X�I���ݎ���8��͟���ګa�ic�^ӑu���w(� �~����B7������I3�K�௲7�H��#%y��Y{o�N�E\' U@&��jh��C��s�C��zu���e��f������� 6V\'�.�#4���q�q}���8�j\��uI�uے]ɨv&f���pX�Yv����gH����f@!lF�.�I�6�Z�O ��3t��0��b��N� )�a��T�� ��n@��ʱ=.Y�x0e�Yo��1m�i�6|1;�;iͮV��e|(!A��?�U�~n�������2���b��S��P����W,�u��}�{�� l5��E 1^4���s��i�u�hxQ�כ�{� %��&��m�����i{'?W%��P�]�^�3��"�߂�A��V��x��/U��[~%y�\��f�R�Qk�E�F���;E�%(Z�;c\�?�����g�e<��,�v����@�FL%Y">lm&��� �b�o9 ������s�����:��z�j{���й�"���nyD�՗HO��5DK,��g�o;�˜�,{b7�v�����?��R�G��6�8'>��<��5oZ��'�(��i �U8<}�k�3&��X�D_�v��<Xj�s"d�� 4�?�e�æ����"[�I��+ ����@~�K����ٱ�`�W��R���H�R ��\�S�����YԳS��K�y k�˂kը���zk���<؄w�X�� �i?, �'���33��?��F��6�%|�e^'��j�[ XH��38v����!Vxr�����_2~�Ÿ���5�~�3��f����D�B��0I?uD;�9ui�ezk�הF�q��S��E�xc��HYG3�5�q����x!b��+x���I���ƈ��b�f�8a��,�64�-|��9��_��e�>�0r1��& j=�7(͕�b�*�O&a ߦ�#�g&������3��n�'¾�FEo�%p �}�z�@����^$�A�k�u�V4��>B���M�1H�(K��X��}�[�5��]z�m�@�H��-�h�� �Q[�,? ���#�\O��0CޒND ��Gb+ޢ�V,ey=)]�r�I����hʺ]����{��-���4�=�!Ѓ�hi��b��t���$�+�35PM�v�!c����W&D�pN{G�bV�Q�P�G�c�z�4%w>$3�M~����4�O�OY� ��WZ�%�1c�� L|����?"�7�A��e%t�����*fsN�f�A��{���b:��^��&��t��l�l+�k7���J�J�:2y��]�j�d��[��O�6����I|/���J���,�N�����B8�Ș�&I6$���A�[A�jb��bp]�����Pݚ���,�x��� K�+��e� f:�̌�ҽ�t���Ⱥ��� �w;>��;z𺘧e'�إ���ф=��1��X�DU�#���l�F��:�jQi�y|]��Ա0��Υޞ@zD�N�!jEz ��}#/y9 _@.zC��\0�y��!�����%������׵�J?��?��Ц� Z�P_|-?jǧ5�`�+0l��lEu�!��竢Σ��f�"�qUCTƏ �L.*��[��B��P=}����#V$�$��R���t�i�LPv����2؈�׸p������2o΀�jO9g��R�i����|9`�+�T��[�&(6w�� |�d��M�P�HV����UP��k�}sz����-J�R���ʲ�/!h�B>��O� ��I��Z/��z�9�Fh�iz܃�r��8���4�=U�07;�מ�Cb�R����!��#`C�0q$��X��0~�8����:2���ts[%dk��ˋһGY��M)��#�X8}ϡ�6���6q ߳�I���r,D�y��'�� ����i��� �G��xXsRfDZ�|���`�V�f���i����Ѷ��4��η�I�JFX���{����A�Iԯ9'U� � ~��n�I8��y��������ڗ&�H#���.>�ݤ�Ɉ��ɥC3q4^���}pG<�$`v}�1kV�^�Ð��6��&<�\��e���+_�;ݸ�m� �S��#(]�l}}uyFfU��tÈ�K޴��xV�%��B;oY Q���J��C����}��gp�Ϙ�M�w��cy��:�Fe��m�z�&���u�sm)���5�iG�x� K��C��GHx�EU��� ���Wֹ��x�K�G��Γ�{�b3�(����r��<�KQ����%�0�mF�]_��d�/����QӒI��0ة�y�b�Hl͵PCI,��6K ��|�̻eG�/>ٔ��#)��\J�$�o��#��F��OZR)����{��#���� $Eh���b�3A�g�����6bK�P�J��9�l�l�Jx�)��j�N[b��f�_�7�B�t} �\g݅n��ϓ��D yq�u�h���J�V@e�H�F�Ӱ�:Z�.�=t�NY;e]_$yB�d"��w����_C� a�J�Ƿ�4lTM�6EKs+^���P��Ε�ƱS�U��M��(���8��PI�- ��T�o�.�=�H!�M��aK�Y�E �b��d�A=�KC5$5|b>��ҥ?�T���F�;�R,RՄ�­��ͅ���i�BT����i�?�d`I�Wm�ؖ��=?�����L�j�vF�Mf�=����+�����o��?�$Y宺��@�V�mE �&��&c��V�Ƽ`���_F��.�ʾ����ĖC0�-O����+���V�Su�*2� v��[�hg�2/�vZo�[�� ����V��4�����E����j�p���]��i� 2�м�YY�0��Tm�����ٻՂ��g:�V�B� ���?�뀋�pO�y ��R��F]9w�ețMyf��aw�;���9�P=��0+mn�S{L�Jb� `@h���/��H8B5���^K$Z�����s8��mړ�3qA&T�>�l�=��>������5�� ã{\p8=KM4QM���ʑ�6��[�_�M�a��F�2�<*�ߜs�E���)�Y�w����*�����O����_�����'!�����l�-�1�K9�����D//���-���&�։���t��!o]nj`^��M9� -��)cL�8�O�$���zr�:���"��}NK�C ���f4��x�8A*����-]^^�I�Y�W� ����W���R;�g�o@��ި�/� �4�ٲ�� ��ܡ�#J-�.��/�n����m��`� $�7����G���.� �a۔��*u��.Q����x�T����-{=��t�2�A�� W���xi�\�-'�� E��z,0�AVͤ����6�]�;H%���jS �����w[��Iw���5L��?*t���a���C����֗;V�~�w5���;�bM)�+l-xJ�gm|��/&BO�Do����ɐ�:�0�H�s��ݔ���˲���8y�5�,B"�*����b av8�^ũ��K�w���Wt9���*���e���� ��� |�T@f�VE��� �P����.H@��n����>�m�K�����1�P�8���2��OA`?�[r���*�fQ!L2y�3 ��{�RF�u�P��tL��ϊkG����Mh:��È8+O`ɰ����ō4�2��a��,�1�_t���*��{D;��Q(�Bh�C�\Bl��g;�y_�Dt��k߭C��Nx�]W�Fp 5�?�Oq�ڷCQ^wzʗ�/O'� A7JJ@5����M�K�u�Q 7�^�G���U�++����B6�\���E�)��Zk�O�ρFPkh1&"��k����v�-C�L�� �,�e4�W��<���@�YPѯ����s?~N��HS❻=[|��(��>N���8̛Jf��׋�b; B��o쨑�V��\(��.封�LɆ;�)u� ��^W�"{*Ҥ%����D���hQ^ZDʷZ�2�O��G�(>7l+�U��Ӝ��d��I��Ӭ�Wce��^�i|.�h���0�49�^���P�kd�?<�ݘ��#�Rϥ��,8�����9�!����{��X���_f�Z�_�"�H�cW��>��g������M_C�)�9p��|l.���5Å3�p�u�tAW� {� �l�X��m�P�i��t�a�O��,�g�(r8R���+T��Pf���f�����C�HT��s%+˞��y��C�V�7V���� C����?\��)�9��� ���ZR�< endstream endobj 2560 0 obj << /Length1 2860 /Length2 20565 /Length3 0 /Length 22192 /Filter /FlateDecode >> stream xڌ�T�[� S� ������� l`S�n$D@��.A��AA�i�����=������3׌g�Z?i(յX$�  Y��; +� @JE[��������ΉBC� vw�O�B� ruC��Аrݡ2i�;TQ�P�ppp8x9�������S�� ���`+� +@�rC���8���mlݡq��'�ޒ�! ����9@�� �:T�� GhDK�@ b ���������� ���+�э�j#�� ���4An WO��W�U�#��XQhڶ`��� ��^@W*p[��ܠ&NV W4:@KA�� r�[Y�of�?�p�r����_��N--!��@'�� ����*��{�3�NV��n�=�vZ@���Jh�� ����������v��#�/7�2�8YIAAN�n(��I�]A�к����\{'������5����WV�l:N`���?:P�o� �������� �@ޖ�l�h�8��:��%���� qXC���A�_(~n@O������� � l��ـ�P~{��A�ch�]��#v��q����� t¬ N>���j1�������?)�{() ���pX8��<\|^^@��������R����,�J�#������ ���R�@���=���<��8�?�_&��f�����1���d=�:��[����v��G:���P�@7������^\������*��� �d��o!�n�`o��:�������[��k��N u����`�`g�?g�岴��nБ��ݝ�F�q��X�Z2N^�����$N�t�@� 1��� �5@� XC\Q~����&�K�7��I�F|6�߈�&� @��_��`���8lr�'�M�7��)�F�6���E�7�rQ���\T~#(���E�_���A�h�FP.�����o��A���FP.�����o��A����\ #��_��::Cw�ׅ�?)'4�� � +пrn�_b�X���7J���?ԣ�o��Zڻ9�l��M��h rY��!��G������o�=��?�\����4���%�:�����K��������@o9��yC�� �����]<�Wſ��������/��{�jX�=�p������T��w�ͯ��� ���JrC+f��l r�C*��������������/� �6��9��d���~���r���� ���h��n�����a��& � �Ê�����ch g�����������>$l������%C~7�ZXg�?�~5���v����de�GK��7$T���p@���j�r�w�x~�<�hԉ�u��!4���%�<~���[l�?�Z(w/�P���)7K��Ն���w���{���Џ7g��������F��B����n|' � r���� KWh��z͡����_g �7����R(Ԯ.��g���ք�,͖^��g�O�H� �Y!k�W��=X+�2����~� H�5������5���P��& $��ɞ��h�o�?����÷�v*��x�c�����'�]�_�e,laKc��W ��l�%Z�qp�M���y"*Dw2dF�o̹˫Y���' �x&���h�B?�uΘ�y�� mN��/_��_�M��I�(.���[Y�fg`�Y���<4RV�!dwp�, 7�2���-X��y֖��3c���"���������>������LV*��H�>~��>#\\*�M��Yo#�C����k��h���g�`2iq�>� Q ���Q� �_��^.ر�=LD�.��S4�:mG������Ui�e�vl�'�6�J�=\Agu�­�s��c����/���{/d��V�a�?9���XS��p���c�Õ� ��Ja��y�G�>���d�R;I��Ӈ��d�^)��h�I��ܩ�cD� Ŭƽ�a���f �%���۶�7п�Y�(�h��ls�'��^�-/R @p_����)���V>}n��������SoJF��{�v#���ᑔ��w Yb��-Y�?��� B�(4�| P��&�`0UH�i)CL����҃wք�7�ҍ�?��R{�sE*2�x����H� ����i��O��C� /`�#F��`�\"�uV�d�j��Z9��e&Cf�W?��O"�xћ_'k�)���>��YO� A(�i��;8F��ή�/@��i�=��ͬ��'��Q2�!t�ʮ�y"d-E��:87>�#.X���yq�E���� ��Q0 ϊ��i����n��W�����ZtWbmsH��w' >�P#���+�����*���e��K?��N�l�sNNtm�_�VIΗ@f�?��"��N=6,�AD=��D�W���7-����-So(����jV�����S�����H~B�%E8�9��6J��' -qM�f�~E�ɵ�ff�T��i5σ����7&�AɃ�;+� �� u���zt����0���reh/X\ƴ�’� �A�������Kvh�'�e�2=N�>�ߖ��Ş65'�i�O���CtL�%CU��TژE���ΒYWWeT���������5�Yc9�7%Џ� ��{(K��b����ڀ$���!XV�5�Y�J�y�ؼ��b#CE����͌��F*�X�[_���LL�t�EȰ�� �I x ϫ-��i����V����)b��v�B���[����؟��b�{s�qV�6�ӂ�Wt%��k�"���W�osu:�+J��n�i�И�����)� �J�Ǖ>tz����zn���q{��Gl��~�x���|�]l���Cg1j��œ"� PK������\U��ڰO�����8y�`�J\�E���ޜ<+��cߧ�o;0G:Ax�?GQ8�� �AJ0��)?�$���T6����hٍ�/��qβp`pJLg����9:=sT`��$��(u�_����f���?{������󔪎R�n�"�~��3�}����F�U��;�7؛/����/��nΔ:�����\U����|���1��X5n��������@j���A����r��6�Zt'TP�y?��P�:f_���{��� �+;�y������?�Z�^���r�����#�:��!+�$��Pt9�'_��]y�×�o?ä/�L�G���b�E�� ��U+;���e�����k?���:�0]Rp/��-�l��:T���Jحc�$ S��0'W��#�[`Yt��¥c�-��۫= X�7�Y��b]���C���r2��^zBwo�!�]� %�������ml�a���i�I�f�0T����s/�ޒuzR�4���Z���6!���5��;��bN�Op���)��:P��T��Iw�4M��I�i��;�G�~��qm �$��+���wd��c��_ai�H�+Y��Z��0H�b��f]��N�"������O�}F2�z��8k���v��d���h��}�j1*#g���g#��s'�JN�t���&�}�v�v(�����%� �+E U]���=ь�'�^"�\ $�p�l�5�ʐ� _PԤ��5b�f<�̊��1�1�Si|��G�D�>Q�-W����Ҧ�&}G� �N}�/�M���<@5)�T���E@;�e��g�bY��JI�$���x�լ"������c�%�K�总`=�5�-������ZlMC=`�Ty��s"O�Cc�*�z&r@�(�0ZB��52:�Κ�Y���� �5����P[�� !Χ���VM������� ��ITCb����6-$s&'����W��Mf]�a,�Q �i��%g�Z�7��"^.���:�7�֔-,wj��u1����d��H�N��oFh�M`d͖!�V� ގ�� rhߡZ(�祯GA�����Q���� ���_ph]�vH�1�qb_�.���b#�sh�kY=��!�2xy�Ɯ����r��hQ�Y$�qg2� �OM�)Y�*m{�L;�l�D+dVzA���Y����Ri �]:�.D +DM�|����L�-M\37x!U�a���yC_+���W�&�jBS.�&�7/�|Z�%# ʮ�A~"�]M/��?�/_��0Fa�ܖݺ[�} Ȕ�U��lj�(� �{5��Ӓ �sF��Y����Fn�X���u nM�$��E���P��x<�Dɵ�n+�#�a�K �58��NM��ײc���E�v� P�?Lr���P��]�̿84�I��+��߈���~ Ec��^+WwD����yW��0UE���Ǩɳ�\�J��:��ggjv�����֖����@��Sn�*�Q e?�Rλב�O tOG3��8����9�pU��p��3-��4�1Ht�Z[6O��6|�F�qx�#5�ǠZiR$Xk���� E<� � �g^�m=��r`��l�cԘ�.�Ƕ��������c�:n�䩤-��N35��V���l~q��>,V��D���$y��(nq�צN�.�v]7h�/ݤ�!&��{�z`�X8ki�n��j f �=����gѸ/ɦ�l%e(���(Ͳ��̅�!%�l���0���2i������*Ͻt���S�������E��k���%�h� ������>�t��|����-5%�j�F�#m�qt���}��]��� Vm�FC���W�f\���_�"6�pk�QŒ�M5�|��@/��)���u�v����߄�O�+?���R��� uы Ɵ��^�$�t#�A�$g�RC$O��[ܰPU0~�6�m;���b�y�]��b����F͉��~������Xf.�N���  |3,k$���9�p�CZ2[q�wC�7a�=#�B�A�����匵�����݈��,� &�7 ��W9�?d;G�x(c?Ғ��ȶ0(���/����y�-��ƿ+y�X�7u�={)5d4M�\��F������[�"�����f�}����E*?����8{���MV��Q'��X�i�~��W�Z�L%O�U�ޖ��|��q4\�>��U��ͅ[�~ ^Ċ��H��1�`.�w�8\pڙ.<���n��8��^XH� �I'.T֟S�ݹcâ�3���;����_B�������K9��1s����,�1˄�g_�S2���)�R�K�|�q�f]A��\�O4�{Dx�(5�j��� ������fCd�-�HB֏����M_ �71=���Xv�k����a-n�"��+:2�MT(4�i�aK*h7����<�� �ṃx��f���ҿ|}���|� E�f��)�Q���{��������;ּdp Tjq��Q�\���}�O����m���`l۫(�-)��o��.�g�\3H�2'�����Dzf|F�����L�)Y�8^��('}U��V`}$�OR8������Q8�MW��C] �췉Yk�dl�Će*��_��s� S ��4�H�P�o���ر3�Q��1��AV񾓖�Կ��� �E�v$�#:w��x0����[��ic?l'Ï�,���d�Pe3wF,�ܙ����×ܺ�>�g3����*Z�1��n��_���0õKEE���\��8|k`^�c�h&Y�Nn[<�r��ˏF)4�z69H���ש�r]1�c'Ӣ3�HE�E*�������4� i!�!;�J螏����p!�>)��-�܆պ]�(,��!}1/h� EE��6�څ�V�?&�T�Щ�{a�D� 1�z�C�� �o�-�Q�-X�M 4i�c^�v];1�>����m�"��Gl�4B�[�ɵ��45F_Xk3��+�o��<Լi~�i|\��}V�C��(hiW�Ub͉���(�%%'��5�I%H0T/!& �9L�%�û�Um�l�� P�v�x_HT��%G�hl����������W�q��M� ��ݖ���~�˅�3=�WZ��|.…oQ�aNS���Wa�\�5SeY��7�����ٛ*[��=���,�̉�n��gc_R�H&4�1�J dF�e�k=?`�� ��~ �X�����Z�3�|���6yn��3Kw&#a��TU��Pk�Ddښa�w���j��rȨ�Ni8��x���*֞��7����a�HUa������B�����&��wy�4�*�e�?ĂE�1GSsw}C�/�oE�M�v<�|�/>�[��5"�q���;��]h�ƲP �zOM����}<��{� En{|�����L����| � k��Q�zcs��|� ��6WA��a�����MT�]�Oր,��� �B���A>��K;b��4x�2�F�"�N<�Vo�>a#W���r�㷹/��VM��> 昦��� �$�7�M��O�Jn� /�Q��}yΕЃ���dRU�aڛ���:��q&�o�g�W�gR��È���z�N���w z�Qe�cm��\ ��� �`��o,���8�9b��p;.��N��g���?W� ��]x�^�v쎠o�b��e� ���&��",�=�N������7�S���o� B�Bt��c|����b���~�m|fD ?��;a�ߥ�R@@3��n�3V�p5У~l�������@����y/�/Lgm_��.W�D�l��3�*���<@z��sF��k>�vm�Cӝ���u�~���Rߗw�(�9���)���&[��=Ev��H�g����=���7�m�C���j�\`ʟ4R�e�V�J�(o���f��,S�@,�4Rj�?����{��mkֿ�'^�16�]�v�g�?�l15 �RG� ��*h����-q#������P���V�,���~ �~���~[y�����b��Y!>�PmT�� �+Ж肃���%�@�n!�L�����f��W/����]��,���Z5�>�o���ٓ��b�=b����e �".+~g;UwHxU48�%P#aZ$�'\|�"�"ۘ��Z.��7o���O��9������;���i��� �:�ǨC4-�inx ��D�����XD�'�����Go-� ����I�>=���aٷ^8]�f�y�,9���5t����c[���LNm�k�0���g���P��_͚�W���7��EF�������rYSc2}��m�:Q�=ѢC(a�L�Qޓ�׎Q�No�3�֡���%�J[ר|���3�m�C�`a-I�P�������liL�;��W�I�>��� ��t����& �U!� )��{ }��/ўNJ0"F�u=m�p|��_}�!Иe)���e�J��k�����3����^^�i�۴ � ^[~ƺbay����H�0zir�c�H͆t*Ht�r�oS��6�*��w��� �g�L���T4��J;J>��x������.o1W��� h��_+\D,x12FqW$|�( և؅����Am�@��Cp��_��-��Ţ*Ƅpz���l-d]ko��i9�X�ጨ�N����U���������=;���Q��D�w����3z[Z .�`�>�}�Ѝ[���^LKi��ev���$,?�;����zJH9u��U�37e��ӏ���bKNݸ��=������x�E�zx����&,u���;`��I۷ќn>���U'�`$k�0pz�C�|�Qv����$Vm$1La'̶� 1aF����S�Y�\��YT'�'���8%���A~���= qֆb;WʣĬ�'V>�+/�U1�tDw���pu�JhxF���Z�nl뮪��f�T��� �*�:]N��,8�5�W�'Y���_�P��5��0D�ۭ�_�,���1_�;! �)Rΐq�y�$����F��>��'�\˕ {��7Mס�;i1�3��d�PjAǬ�͗�j1u��au�E+��9L�z�\���^_C�� -.w���e�J���V(��g@^���F�*�{��W?M ���m������N�Y�dqR��/H��Vӿu����JS�[���L�)�h7' ��,r< ��Z�O=0��O�p�w��������t��'�T|�����tx£1VK��:Qs���B�'�}��F�bR����ı%�P��u-cY�N9C<�L����Q"M�e�q��v�4y�|�������, �+�O�+�C�$�&� �� ���gs;�>��/�t�/c.E� EPհ�SO����h�!鳁}��@=�2D�t���p�oR�>�^�H�G�$v=b `��OcH�ql�φ)v�-�~��/�1%��b(�<�����bKX�v8}�,�ڶa ��a�q���{[8=���镚����*�٨���T@MϪ�8&sQ��r�\�a ��1�e_����k��HS�B.ȕ^���8���37���=�8h�r�� ��g�|�MgNxx�����`�� ��]^��#�$ ��@��> ;R�ȝ�%�"ܟ�Jzk��(A��7S"$. )��_���.���v���3��:HG�|-CHO�|�[���3h�=�ah�`e�p�ෞ6!/���u�y�!;%�{�{�T�4�ټ�tQ%%�����&��"�q=���������A/�3�3}�€c�.���n�!ƽ���+9�1������Ts�= V��sP��d���UpS�x�{�y���ZsO��Z6��M�� ���j��'?7�)>m������s��Fr#X�3"$>Pڲ�=Wq� �Z�N����ϐ�f�v� ���yt�}2�sE�^?�6���[l�>�M}kp��I`��"�m��B3G�d{+����O.��`�n����"�!g��\��GO*�7�a�J�R���d�B���dzoQ�o50��q��4�i'{�� z�ZN�y2ZF�W"Z+�*U��u�`� )V�� 3*�/�d���X�!j�������c%��x]gJ�B&���`鲢z*��\��ey{���|;�N'�I-��zj‚�1���M��j� FqK��j��{��b�s�Zb!��[ �*dz-������s]si�z�ä݇����@?�������V�:��w�pG�B�%+�c~�Vx�$6-��L�߬����,yTA��;������ �-l�!-�� )��pV�#�퓳1�&���*��}��2,aM7e}Xv� ������Pn�\+�`N��W���K,�/vR��� �1�q>[/X_F���0%���IV��.�w�Ta���3���́��ǝw3����80E�$C��T��0e�Aț-�dT�˛O/�>{�/]��rS,"_���{w6}�`��r�&�ˬ?=�3��o�9�r�:|�T����\/aŪ�{���g�΍�:������62�����Y,\��{��� �<��K�Ȅ� և�"}Yi��3���@O��*Hh��8�Bje[���ϟ���=���.���:l�*�Y�9ל�RQb_��k1m���$2�S=�I��t�/�_^zχ+���N\z\�ty�<1���byR��[�O&�����`�Z��-�">k�Lp�=��v+n6�|G� xwV�"�i)�笧Z#,!&��<���� m��s�����u{R�9:�EDQ�+�fLe��n8|�Z\3��5`�(e�-2-d��E����}z��_ڸ���[2�a��}��V��%���@#������������a�}��D�w���O��9H��#�&�'h^�o�{��r�v`Y)NjGNt�?FGR�$=�ф�s��I,i���������[��H5�>�{@H� h���6��J�,vn��q�x���XɔULe��,kJ/#�r����C�`=2S�`�"���.�s����i0[q{S��V��4�1)@�������t#: ܌��h���y��颪]'�uV��5 _*�#w��(֬F_��tSI�l�T=�v�x����m��*L�M>B}��Q��_�۔��-�4,Ze] F�R �In�zG�$���L�W�}�Ԣ�C�$�����9,q�5˷�ů0�_p�I�����Pj�Vk�OX�K�K8��, �!�Y(|W�&��ov��o����3�j�6��g�S� �V>��JEp%����)['�?��4Jr�����W!�/=G��q�=�$'�� ;�mA�0�2ߦY�J_�4�����0|�X���a�m��R�q%��+I��"�DJ[���"� �Đ��B���?��?����r ��o�գ�M�}�B�ֶP��v��E��R�� fP�9�2�,�l^�Y\h�Ka���K��+ ���0�����]ŏH���_�L��i�8�,��s�L�#����D�!�#�^3[KJo�r�*̫���q�<�.|I���0�E*�����5�4���-�6ӌ��/��2~�K�M�q�~�@�ُZIչ2/��\�Qp�$}�"�f�iF��&�hj1� t�ٻx�Dh�ޖZ�|Br��� lޓx�UpIb%��9�W�d���]�Bg(�������X]�&��tw2셢��k�yA�;G?�!m���w��ֻ��~��D(��!s(���t6�_=��E.������wL;�^�=�ݤ����K�~E���luˆ8��>O��P��TT���m#�O��`�6K�/{&���츺�+�5�/=�P�@��A�z}��/R�: ��� �C�ٛ�<�l��W�{SZ�i�yoNB`�u��K���}k�:X�s?+������'84C���Ф�}^�݃v�â��`����Y��)�LnO�,}��V;���^�Vj���c/����j����y�?�.�*Ŕ��< ��$��Y*�t�h�Y����в]λ6�o��ظ�bj��ӈrc{�>l�}"���4�A뒀C�Ăs��@�,�@)��qM�]�3�Dz�K��5ѷ�u1��/'#C��^�`wT} ""�Jhj7 l��E�q�ߵ��� ۷m�s b�S�v����Q����� �A&@cE��;f��4�s \M���`�^����B��k����r����Z�~gG�b�Q���̀���R�aY��;�Wl�=S�H��ᑹ&$�?V���b��|֖ �_�;� �d����-��4s�+閄���(1ޠ�v#��Y*6V���w�z�%�n>@O��{���8��P��@DU���x���b`2c�B�6G��)��P���N(�P�eS�i[��Ƴ���l�e�;k��PM�;�2� ���󧷄@��_���K���S�{fD-7����P���:� V�#��Mw�3���:��C�~�L�<֫^�~�66��!�WBG��C�����_��i��C�T��-0{�P:�D� ���N����*z��#�f������of�DK[U?�[��y?�h�`��G>mӺ�rz+���&��l��he`�nf��4���w?�5�[��auj�|���jB!{oaT ��ʗ J@�I�it�q���T���F�|7�"�f�)zJwF�h��i�j*�}w?ϣ�p\��Đ�b�E&�@:�Ehɩ_���w��(�Ԯl�B?r��a�fkQxF���qi���X�f���t����"\�#��a��5���lM��ߡ/���U��)!j�FԻ7O9�pn�{D -�O� O"3 �)�&x�����t�����5�=0O��d_�����w*$2�^;��*a!�b�9(@�Mr���m�L������Œ܄=��&�㼆Nj�� E�t�I��� =�Ҏ1�B������ ��|OR��� �&qc�i�Vȕ���`V��Ɲ�l4�|]=��VZ�k������ϻj!��}��=%R�'���B��m ��#���?|gK�o�t����?��o���y}&Bz���>h�:��[���3�j7��(���� WŇ䛟�+���Ot�~>���(^Jl��G��8� ���'HzQ���V��k�������çzǦ3_3�4��YOo2�H��F�i�#����<���e��3Jw8d�fH���>��06��z�f-�p��m��KФ�ԉ�e��D���T��G �nm7�1�!�*#t���`��",9��<� ħ"5fw�h�b!P'8?pD��Νt�|5��T��,gp\D��G����t�`�4a 8w�m�G�ݝ�@ H{���F1-/너�2����Mm �ƫHj�\"n¶g�L}@UÏ��/K�����H�5t魃^@�����^��qb���+�z{?�g�a�a�� s TK %�����_&\�ŕ c[W�,�T�/<����;��H�����Y�g��{�t��%ZDE�C�鎷Y�l�ר����L>r�p� a�v��/� 0�<��G���C�/�r�r H��ۑ( ~���-�Wy�}��ec��&���S��l�|��u8��Z���o��S��jf�/ �I��~�~R/t{�I��˦dccp�7�����+�e�m&��su�~s�B�-U*����Q�����V�8�4����� �<#߰n�����#υœ�_?���)�nS��[�c��N�TE�T�V|�� .��`��(/���c�ڃ��A�\J���t|�w�?��-����8z�(7t�&�F%=?�&�jy~u��Y���!����hG"�2���\��^�������\5ZzR�) �w]�A<�n[#�٧E�$~�u��'Ht^&]����v�~������qZ���������N� 8N�@�G��*ܚ�ݐA��Eb6A�&��o�͕j�oz�qV�_FG�k��5�e��f1�fEr'�K�6#!A����{�%`���P���aٱ�"7�o��� w�K�l��8� I�^�O_����D�u�8_��[�>���P2S�����/��G���S���� ��W��s�7Gܒ�����Ep�\��dg4[�����v �������Yo-��I����K�<7D�+2� �L�ug���=�4�H��/>�O��2]�ۘ��b�Zd��J<��ߒ�(��zؖH皽�+��?qSe���`>g����?|��O�%�#x�(�i���x��n, _'���n���)20ז'N�B��"E���0/�l�I]����K���nˀ�����sވ�;i� $[ճ�yމnCަ�Qݓ4��~�/Y�#O��# ���$��֕H0g����s��<�r�^��~v�����) T/X{�f�/��[Ϯ�ꈶ���S_Gڭ��=h��H��6V{�M�s1Bb]?Q���6�'|���vߨ;we�-3�ARHa+Y��$ԭ�"��Ex'�E2��/�j�Y��N'�L��l���P,�j�X>ܶcY�����P6��F���l�2Pf؛� ��'e��6�6z_4J���†�E�JV�5;w�+��,~�C� w�H�"Ӂ���.Y�7 K�Y���* ��=����}�O��X����!�����ys���+L��b!��{Tj8���C��C���bJ�*� ��l����$[vӲ�by@ V�V�Wʳ�� �1y��cR�Ju����4I�� ��=.rk��iQ'���|a6 ���[��j���GV�q|�Nz����d��T�5C��Z��d� ��g�އu�9��?�����.AdZ ��P)�&���)�e��G��4ޮ� 2cZ�I��O|�aL�k���5�[���B��f�B2���������a���� F��+��S��h^�n��߈u�n�; ղU�I�)\��سG�Elt9�f�>���:,]�T���7 !A��;����>�U��h����E�X}���JN��m� �+'w�-�M���Э�����>|^c=�s�=�6j٠� �^��o*��b�w���$Y� �o�u��x�R�H����ʼnh:�0�� �,��Z8����NѺo�`"Jk� s2]����{�I����ħ����e��ai�b����0��5�С�PIƂ Zn �����㰏�� D�:ʙڬ��f����Ň<���`�S�#L?�o�"8^�.�U�M��ц��׻��ט����rG,�ۢ�'SuƘNݢ��p}�3���sh0��d�Y�FC����Ót�X� � �t��6��*��v �FR������9�?�z�Wo9��Yn���S�����O�� e�K�t����4z�_}dHk��C�챍��~]�,l��wE�@�!ws��8�5"�¥ORCn���j�O�]c_dy�{�������2�0�!*Q)=�[��ג�\�u9���G��"+��I�9q�6zUC�KgV��%�{� ����Q���`]M��] 9�w��K���T�������7�+���w�<����*&z�C +�1w�ذ�է�O�TH�ѡ�����n-ZB�sw�Lެ�4�6�X`E �ğ�P���?���@U�Qՠe�/�O� �`b�� ��:;/Dَq�|v/-V�/�/$���Ј���d�(6�]*rܗ)��"|<۾XZf��-H�h! �As��A .W�*�=+K x�@��7iT|�I��=�-j��+��� �x5�KN�D� :�F�ď$2ٺ$��������V�:VZ�ᛔп�?2A)��V�,��dT,A�͎�v*�MĀ+�����Q��/���n�"%����1���������jӓŌ�QD� �%]x��U�Eׯ�דk��ئ��( G�(�~���e(�?�uJ��P`h���R &��H��S u��L��E�p�,���1�K�t�A_�oo�Q����3�+D���'ӒZ�M;V�{#��{.�$�[��B(@:W��I��w5^~�iQ�.*mf����:� �W����L�<��W_��uaZ�l��UW� �(L���_�A�ƌE����ݯ��>3��W_�$�Q�tf�1�;:9�zg�������_4�6 ��INv������Г!AE��&��k�f��cVI8&���B� �tf,��a��4�bG���M��R��{{� ��pC�}�b��Zߤ(�/�i4h��qK��%����p�|9��{�%�w��1��́?��4����(;�����]��&���Ed��� M�]bۤ�=���9y���Αm���q&�nR-�r����:G�0@;N��Ē��ٙ?��'u��Qp�=�wtd,������i��M�]u>�耲�m��|z�%V�`��b) �_ZX�?CQ%���n�:AT����O/u~�t\�� �nvH�e���o�@f�DEmc#(l�OJ��\�٘����O�%��\F�EYW��5��~߲� �=κ�.�2뙷@}8�K����0��*�|Q��E���Yj(��u�||m�(�=夭#��ms�<�ڦ6��>��)o�؀�P[�|�q]c$7 �Ӄ���_�)5�21�  ��@zf�4X<����^�oOP���a>l( ��i�7�JQ Ve5�20��,�'���c߾;�U�j}�ׄS`���}F�x�Mc���O�fo�:aK2��w~����� OH��[�A!�򚳳=��=�긥4$9��[��7�C�x�<�2k���~I诬nq�VN��N1�7 R��I�4.�5$�q$�-,��g8pY�̯��c��0��_of-�/�)�O^�d�� cEc��������ބ�m��$�)ʗ�gg�K�Lc�Mz�Z�NLB<��z h��:V?n4^���$.����v`#`�t��xѬ� W�*�J� �+$�P�d���Ntτ�'Ӏ)~C2 ���{ �K Ε��/bG��ω`���6�#��j��|��sf��˒�_w��@��u��.�C!yGh&�5ݶ�>�����L+ *B�{hХ�a$�貕P�5�OtRIW�6��_E%$å*��oC� 7��ߎ*�P[�M���+����e`���뫆Cw� ��ܣ���Yg�S�������}�n�ő���v�e����(��nq}#�u.DY���wd�*U������u���]+���W ��mMgU�|�nϔQ��<`��� ��M�}������c�V��ց������ �?�{�uK�Ǜg(yTXQ�mH�4�q�Q���b5o1X�����j�k�4Rt6t��b�f� �7�D��HS ��\bj_}�i�Θ���#tz�>3i�_�&ֲMi=/i7 =� ��9�,y?�9�:i�̫x<�]D����_�V��j����I}n �6+Jf8��i��qZؽ� �'-Pn��G�j`>�`���������R;�|0?��%�,��f{ ��@���c\R��o�t*���tE�0!��vd�%��9�Ϯ-YE��v�]�Yx^&��ľ�I<�q�9H����!� J�`o���M̭� 阏���Q8!' �[L[=�|/�y�f0و�A��\NSD����Z=���ӂ�rW �:=�sBT�չ'D���X���t6#� ��Cet#W�II��Ɠ�4�st�?=MޯB��� c5�^R|�G���8�x�=G�l���leVQ��ݔT�� x��]XX�l`N��[E2�)Sh�;g��3RId�O�����W������� �QV�3DG���]��?���Sa� {ʊ���+�`��W� ��`T��&{ޏ l��쭻Y�档s�=EA;�X��$� �e��*=Y{��ê�~�F+k�z�?�B�){w{�W�,�J��NV4�Ыy�a(j� �7��xt 8�a��֦ F�RE٭E����$O"�H(?p!�?��U��ԟ��B�#��Ե�A�D�9/�o�beڄv�8(�r�bF�c(��2��}q�W!v�y�_]� BG��w9JP[e���@J&8h�o��Ç��5^L��+gO�1w�����%�i��U�*]|�W�H���AQ�EA���Ϊ� #)&������Xh(b�ً�S+ќ�֒J� ���K�e����x�}ʿQ&@] 6��R�E1 �ևɍ�;<у����ܓ���^$�z�D����&�l ���S��nr �������}��s �cp%�d�D�X,u���2�k�]4{'Ot��_�O��v�Xj�n��%θ4����2���F ��}`�|I�f��R+ɧ��q ����h����qz<���.���fLV:[�*���k���?௓��JK�>�� �80O��̥����R�j��'��������S ,x��y��x�e����W"H��)��epS��/B�C�6;x��?�p�1x���W�_�8 Ol�p�KLO�{���N4��A@��Ƚ���������0�m6�n���Qxj��$x���V5�l?z���mH�T~t�3B��� ���ң�Y'x��MRO�}�p^ �w LV�2�Z�*M��YK�a�ǫ �Q��߀��xĜ[r�c�q�<���{���Y����Hdm�PB��1�t�E�[F�]��;��C��Ɇ��~/�GY��X`@#X�Ǎ��H@�*�$���"����!�E|��I#&��+���c.lwo{M����OPr�UH��L_�$����@�����u@�y>OƬb~ �}aJ��P�Q���/�~��Z���Ud�$ �����Cܕ`�kL�pDŽ}��/?ؐ�O-ڈ��bs����Vk�K��Wv�f��p�79��J��8ۆ}�G�aC��]�b�~�,r~] � ��zt�8���&Rܿ&HXt�a:5G[�����o��vo�޿����̨�vq^^d�Pj2��� }��"�W���[}y�_�)�#�t΀l�Ԅ�}{ ��QvE�\�?0$��������o�W��kLw ��/��gd�/sJ��C� �p��h#79wIi�}����8셛4�I�~I���q�V�����5PLy@��/a���a�����p``��Pvͨ�?N���ٓv�8�Af���s`�%q�G���M� !�� ��T�e9>e� #36�Y����{� C���| ����(�Y*DD��Wݏ�� e�*�*:���E�� ����ZB�5毒��p�<�*_�)&��^�O%1v:��wh���9�}�tg�ݖ%�G4HŇ�b�� �s�> �n�m@RJ4 �A ��a;� պi���i��L2����[.� 2����)bȕϫu���͟:�q�lKQ��Qtc�ٷ �{gF��qoQy�м3k�`yQ;c'\ã�>�'����tLN����WZ��3D���ܻ���J�F&������S����䝳H6ܖ� ��� ��0��ݞc|���p�s�� �jqH8�N�7n�����3f2�>k�@�h��yx2䓃�|z�1��a���ڕ�V�d����K;��P+iٹy:V;��8�~���@H3��f��O����杕/=��cX8%�(�_�P�ҁ��P9 ���O�z�B�_��Q�;��F�Qw�S<�D��N�>���~E}��1���z�e�[��O9��A�v*�� �]�^S�~o�H^�hK���ъ����'R.[�,����k�$�����~��i� MY)�0�U���� �Y�V@�!k`�S��Å������TF��[���M8Xyd�(+�D�b����}[�?��tZf{/7fe�Wa3j� �t~�F�k�*�'$��]��{���ƖTc��X����SnTF�(DL��d������w���7޲��(~�zal�^p������8��U�"�s����x�������� 7;�zO��z�vX�[��?ЍdM��I�>��v6C���A��Mu���g�iVn���5^�\�6�p��k0��j�8h=�e����}w�BJw��HLV�~���iph�<���w�l�#�N���_k= �ۓ<�^���5p�(w�;#%�"w�N�@)�l�z�`8�4�ĸڑ�[Zن�U��Q��2n�<�̍�cU嚘Z�F��]�E"NAC"(��A"惇��Q��Շ)�k��d��S`ڊTV�kʵ�b"���_/:�Ylh�H�����p'~�� W�J�R�ZaK�f����P��$Q��Ei�S�m�3�u�Hy���D��#_����U����)tu��hЅdv_�y��$��\}�LK��a�H#�M�L��<�Ð�p�wds�GE-)�(ޥ� f� >8�ުWN쿰��Ax�w�/h(�NF} �� endstream endobj 2562 0 obj << /Length1 2173 /Length2 8760 /Length3 0 /Length 10049 /Filter /FlateDecode >> stream xڍ�T�6,�R�5t3CwIK8 ]2�� 5���H�R��H(Ҡt���������7�s��{���[�3��g�{�/���'���K�2�ѕ��$P����@�| �+�.�����Uꂄ#%�0Pp�B\Q2E�+�N�x�f���H��J�@H�?� �"�n ��������a����G��ơ�Gm��l){X)?1٪Ƃ<��}A���<�k@@x�{�� ��N��E�~��%���Q�Z�b0�������� K� 8 ���328�z� Z���A� ���SN�^>��Q�c���2_rhCF]�*�N�Zp��� (������>Ή�Z.T�}������ƌ���hss��T���u1E�T�_��W�dk*�F�-�>'��&e,,}SI�4-g�;el�O#�+�����ixS�B�%eT��+�0?��S��l��c��r�{�MJ(|�����W�� S�ձ���K��&�3�>t��%��g��&�h�{[�A�۷�����$�r�;OG����ۏTӍ���MI�8�8�M�i���-%�J��� g������=��v�i�<���-���#�ǀ�`�KjTq&��ٸ�s��d��iS?��;��l���Zx!���uQ�y�{Ox�����?Z�����Y�^���]���4����Ķ3���~oMw�¦w]�����0�Y���eʀ�h9h�$�E��a- �w]5�p]�,�����sp/�SrŲw����M��?���*�C�q8��* �)n�i��3�� u�s�$f%���\l��t ��Y�4��u� �H���$.�3�~�o�B8>�?Գ�޽���,�/C�I���j��Q牰<}� $u4�`�`��!����Z"�{*�6��嬉px��b��=�:�{��Zꆏ �W�_U-^1/o���p�o|���n����,�0f(�me��_�{��4�Z�R���j G�%��<��7�1`���l��q�O;�� �����!x�A��a`��^�^L��Q�� �r�="m?���5��!�J ¾'g,}o�l�S�7%V� �U�04����(��͢I��Y3� �=XyAH�ǐ_e��E^lC|Q��FSt���F��cdOF�˩�db�&_�Ɋo��W1�ܦ��vv8]!,��Hx �����j�W0F[��J|�r���)�.�r�uO��=�(+C�����I�7k�=π�\� |�24�?��ü�H{���@o*%��n�.]��1��7�u��K<=��XS��}n)��FU7����m��v>$��#2ӵ�g�s�bfpP^뼟:���N��&W&7�y��U�ӟ6���;�+I$��{I�^�bJm�QO�n�S~�fŜ�r��� ��Hh�P�Uσ�E��� �Tve ��R��� #�\ ��y ��&� �U46�'�+y�d�+��ݡ�u�,h�%P�ׇl��z�Đ�.9]B��B6e���7O�?�_{���p^�E ?5S�rLy/Ϸ�Tk�H;����|������Ѣ�Nh��̞���.�}��ʬ��Z�ͷ"be**�`'�i�<ۖ'j�-�� �J�x�D��U�$c�������^I&=. ��m���_�|����V�]�X������g�;ؖ�������CF���D����������+qڏ���<�j����b��ճpĴuS�~%��q�ɾ̒6�ДX8+�7JE���~�k��z���0�e�ܝ�������C�J�.��*w�>�_F�cMZ�8� �!����{m�Gq1�s��Ӱ�#��F�E\���VWV�ޤF%?�I��d���u�����Z�̼�|;�?��Myr%�4�PdU�&~�Gu:��2rR�v�s��L��Xг��ur���9ї8�ƪ�D���ރ�&,�M���'4����@d[J���o���ˋ�C7�.ASJ{/S�[<[Z�Ҳω������#�IE��-+�|�}��f����Iy�D=I��wr(���#ŝ̛���ѡ�'}z7��� �R�g$#JKc�I���ւ�/B����`@:G�T��z��g �ys��+�b�:���8�L�uǟo����� N��0B�Ɛ�����nR�l�� ���&�Y��Hh�F+��$-��s&ҊI}�Ƃ�N;�1M4=���{g�F�R��f���&ĵ8����䌼%���2�6�NҦ����>�+o�P[)�/���ai/X�ͳ�v�1�jH�Z�~��R����$�����jN��Bi�y���aF~��8���2v/�W��ХyS>� �)urRr>�.��� a��� CQ�Ãʛ��2��>����:�t��)������Z�x2��Y�U#R�@�8h��I3<��<r��9��~��@�?>�'��WHH W�uƲOH�F,���]m���+Z^�,�ʳ�R`˹8"S�<��_��%=�{x%nl����c�Av�/~&�fͿؤ�Ɉ�<�~�����0�E4q�",�R1B�,�_���^��AܝٽZ�k����2�2�� }�,>FO�0���Wӣ�#&�� �zfj�r���H�Y�r��{S�N�\}�����ئ5�4ZH ZR��z�W!]��'Y��_����h�c3 �[�M Ϯ��":���γ�M������̭h�h�6 �=�D���s@}sԕq�`ȗ�K-��>�^g��N ��� �{+�0Y���1�������6�{T��f&E�ى͊T����6�B�wFl����$\Ss���3wy��r�x� 3��gq�,:�~!qa�/�q��4�4� YCS|Z�&�v����J(?O������Y���J�e�]R��8�l�gϜ{��;D��n���ke4�.���l�]o+�G+�꓃c�K͝�b+L����w�W�7 ��>�J&�M���֞�) �êa���v#�0����mS釁%*�lhk���e2 1|J�Q�~h��W��;"�˗u~�܌>T��V�!U_|9y]��S}-o|�*7���}�-�L�hE���V�������H�Y��u޵�U�7�w1Rks-�c�N�f�q0���u�c���E2��^/3��D���~OU�G���#���L�j3��$�¯E��N&4�� (�)2O�Ѝ�ѧ��MD(���K$ 9�k�>���Dh����s�6�F^ ���s����(~;�=;)>�  v� w����*ػ[| V.�}o���,�V{c�O=����ֲ����U��q��W��;b�22�V��iR4ED�|eہc$�^2l���R�j]9 Zf�'� $��^�/��kWRy��Uָ,��-�I���댳 m�(ػl����uMWt�GrXS��e��%>�F}���U¬A�u0��sy̮v#@@���� �ۥh��.��m#],�\ ����0M��\�3�!�;5��X ��~�ƄU��-��P���Z �%�=;&��<�Lnؿ��/���so�NS���k�{��S�-��-`⊄V7�q���/�;�m4޴�*�Z����&I?���p�������#o�B2M�U=<����j)��R@�򾽉z =��՗z�������⌵F/7fp�үv�l͝:r�-�����]ybRpf��ZY�9#��sH�c����GI�\��t�������=��*8������������"��Jsy�T�HxǼTٸ(���ct�@�����9��tlҾ��HH���%�y��]��,���2�L�,���P�\�O�H���� ͧ�4���G4�ҹ�M�8\�>�=(^�,p/d��3���,hBv�S�|��2Ynz �O)0�+�-gڃ��XK�LϘ��ߙ� @�?ޣ|�p7�F&tw"~��<][�"�5iV�B��78f�������'R�fa0me��Ý��Ŧ�A�-�� RJ+^��^D��(���.�|cv�Ɯ�T$R�$/������rZ��<>���bp�� _��W3Զ�T*��wl;���udebW_���hxS^.8PH��4�QBŵ���)L��$���dJ<�+us>��^{ڈu�+J�˒���+18[1R>.���<�;�� 5i��K�ڭOƄ�{�d*��}c��%�X���]��Y�Nlr�rn�[ǃB��F�gʙ>���#�(��L��%��/�����?�p+���; ���;P�i�b���E�ྨ_��DL�q��S�owɩDT�~�=����$�T�ߞʼn��I�,P���%�r ��xܖ"�m��x�ոxh���]����cŃ��3Q[P�]�j��$�� �8���jS�Ma<����������t���H/"yfXvѻ��_\���p,�I��Mی�wW��,��K�Þ��S�� t%z`l�WS(m��e�9f�gPD��,��P�ͫ�y7����Ͱ�X�^���*����}���8K�Ae��s���Y�����?����of,���-4o��0 &b��{��m R�a�mkV�Ҙ�Cٛ�{��x�U��m%��f��}g2\c:88��~��Tu�[X)�ط �Z��%_m3��ݹ*z, E�4N��pPR9\��u�Iv�������:�]�ҫ_>̍�j(�{�Rڝ1���Q &p�ߣҐ�ȝ��>�aJ#i�ʾCi�d� %ٞ�>�'O���<r�Ϊ�錳Iࢢ���[ ʹ�-���!���}e� ��Z�������"h�q�R�H���M�q�D�>����H*���R�jacjl�9+��}��=��;�(H�g�E��h���� z^Ň8U�� ��aG޲�ܞ��t�(s9A�EK" t��*~��+��� �u�#ٲ�{}O���)�.�7?F�4{-<��SN 뙪 ��,�6�:6J��C*J| ɣW4�к���dal/J����=7��?��Vd�P)<`z��60Jo@@��rq��7��� ��Y`a�e�~mޛKӃ���=��sD��)Y�m�&����L��>_w¦���C"�%^��@=���o^���<�� �x�7@���ؚGe����=�&�>��`Dt;�P��M�E�M�nō|cnYMF�R=�`�|D�_�x�X��KW�K�xs�������i�B����ɔ*�*c��k,��^<�dtW�� |iX��/zB,���&��zBex?.��Fa�i���1M���AC���Fq5-Eޏ2�JO�R�g�6n��h��m��eD�0u�8�jd�`+0��# ��9���7/��B�C�q��@|k��׽v�ɻ� O���O��� `��C�$MB�� i��^@���?ø��������h����R'� �Q^u�I9Q2W�E��˻l���e����PU^e�·ъk���~QX.�����c�A���ƛ;��2����p� ���7 ,<�Íӟ<�W�y�ؤ���s�RDZ���4wkU��hS��'����"P�'~0ylOHf+m�x��t��|�Nw��8��%�kMo󃟰Tk�T>����#�R��� 4��ԛ��4��MP��c*[�~���!�_�w��ѡi2=D�w�#�z�𧮴�ܡ�#[�/�:� V���G�X<s��� 4������JR�R욗G40}�Q���H�3s����EJ(�ϝ0��<��ڛ�oB�l�Y�^���{8�v�����#l�y���$4���i4�����Qqv�^9��E�bB����N�s�9%���ќ���s�6���~�a{=��|Ɵ��i9[�<�0a�a"X6���~�%�hlӅP�9�����^�]��C�>�K�C���+uX� Af,�C���E�i:W3��y�����9xB@�ՙ ���֭�C�<��4�7){�|��*���� C1'��"��3zs[�B�CE�<���h�,� _����ѷt�<��2��� k�� ^sY�`1|��M!^C�����E�Ůy��|no���YҮ�8TQ��ǯ\��%�T��w�'=J��]%�s��{˓�j8����]&SY���zd���*�F��$m��2�t�u ��L|�� HR0zJR�ؔ$ �m-��@��� ���L�z��z[c�y���8U�T4�����j��k�\i��7Qy�n�Ƣ$�l`���]��~�v�຤F�w�k[��%��,�Re�Ǥ/f��l��>�x�Xc{�����l�?Ey,�ˆs��+U����1�����S��B̷f^d�+�v�L��WeNo� K�(�k��dw�k�=��!�I�W�<�}r��Y�������#��4�@P o�c��i�U����iBt�����H5����l��d.)���lI:����}���,����G#��k sxC��� k!�0r��+�$/tO;Z�3`�>�P?[]�lb�nRG]]���f;��Ȟ�.����d/ '�׎whI"��SG�Fyq���f�$�cB�7��(����ř갼R��Uze��� y1`�D�4*+�S�k�hc?�a2XI'�,JT�a�� ��կ���������礙�锴-]Q��0���^��]���u���}��O��Y�"I�<ڞ� �XA�� �?Ұ%���Kk;���g��^�m�e8��fHWB d8�b��\������p���h�'N#D{"�н�:�����{K��q�I��G����[z�\� �L��� zO��:�g�ף+Qἰ�Xl���~�Z/e�`�Ƨ��9�ugiUk��������(Mj F���R�)����T���sK���X�N�o��7��0:`of�c�'*��wT>�h�34���8(y��1��L���;U��5k��^���z��pm�m�ʌG��ӓKҲ�U� 2N�7�5�Ah�K�� 4b�� mGVa/����O��A�E�ѓ�+]�Nd���A}��3��-��"c�2�(��}ê�.h���X��~�E�ෳ넀V�2M�2�qSu�ga��Za��*��Te��M�d���̫rtwc��J�l�Q��ZL��h�+] �=IV=�Ҽ�������}�3 ^jn�pl��*��+��vB�4��He/y�zY�.^4:�O�1nKC�_�)�5�zDS,��C��\��؛Aj.[u���(<�k���[��K�����:�J���i�W�=���hN�n��8zJE����E�4�4�@�ZoN6�H* H:O=��r/�Sʌ���:$0($e������ ��֒1� �F�nd��˔���8�܁m�݀Ui��3?R��%�������ߐC�߆Mu���k^��~u�]���� K��Gdj�:�����j~P�4a�i���ͨl��W���15��F�|�u�ӐU��] t�Vn��L/x��Zk�a�J��m�T3p��b���Æ�;���t�8�}#�u��wD`�ET>���k�,x��6����SGFL�����$� ��,�� �l�m��G��tz/^����&�Wk��.Z���$�𴳥�:�� ,�m 9�b�y��K��ȯW�������������grct(�����~�����#Z}��1��������v�A&'Ǘ�ʁ�����1��: �>� �Z��ׄ�����3�/ endstream endobj 2564 0 obj << /Length1 736 /Length2 1143 /Length3 0 /Length 1716 /Filter /FlateDecode >> stream x�mRkTSWF-) �Qʉ%FB�K�b �$y$���Bro���1EE("H-J��G� A�Ҋ�!c��b�a���Z`�PAp@ё �⚵f�?�����|�;ۚ쏡/]3m�t���� 0�$kk C� � D���i� &��0y:��%�QWH�� D����I�D$))){SJ:���k��a$ R�BBq�����0 �)U ��p�*`*H�p �@����IA_���8���c2���� �?��(��5�(�p�T�"�X�n7 V�T����h5��i��d@��d��M�������w)� �F��xH���VJ�� lX�L�$`a��`��TYf8�@3�� ���ߞ?+��>�X�-ӑ�p���I��P��xO�JXKG�� �!D)��k���0����?�Ռ��/8���.�J�a��A8��V�C��J:T�h� 0�_�3��AG�@4���.���ż�����>����� �tp�..G�G�H��0J����]��W0��H�������/n��9�W��է���#h��5]���7 m(n��Y�yy�����B�GS�rf� >� �;: �'c��_~��V|����a��O�>��o�������C�Y��:/�>�& ��s�Y���&����eScv��D�5���LԒ��� �_�6��[���p�zk�䫚���ܨ����՘w��Y�c ^� ���UEv;�'��j ���)$���?�3���p����k4Luw�����n�ԇz�e}�o�wj������=�9�wF&����� *�ϟ�W0�(�kj$t�B�9�]R)8?pi�yO�NdD��vMm �h�NlΎ�:���������ԔU��>�v7#*2�0�}d�Z�j>cNh:�y��YJ�ԓI���c�/��g�U�3�y�Q�,��iJ������CwZۍ[������T�G��u�� ovZs@����~��$���k���*gD�7�U��@_lw��/�_�.�x|r�p�A�.P7�EW�����}�r'��bt�D�u�j�V�뤤�EW��zl�V�ܵE�Ϝ5b�D��`�]! �2q�����U�D�i�C/3Ȣ�;ڥ���d���G�F���H��8d�8���0m���%ջ�����y����>WN\�{�U_�&������&���y ÿ%.� �S�G��}�ށ\�����������!�OE�ޱ��6��%�e���$�b�^�2�2���U��KA�����Զ�����Ea�^��S�@>�{N�3��H�>��m����I��g���1�SU���&��E��Ȗy,} ˄�j�h�滤u%!qJ�uî�޿�1<��^��6: 9���ώ}�kI���i�^f1��1lI���L S����=f���!�l��{���o�9���| �_�KΫ��~-����fq�뜇x����kk���]��#�����ji.#Q7��3/X �r�k'�m��oOM 1��� �Y�\|�ݓ}x�י@�ǟޔ�[�ꗱ�1o�3��/�!� endstream endobj 2566 0 obj << /Length1 721 /Length2 4672 /Length3 0 /Length 5264 /Filter /FlateDecode >> stream x�mrg4j�u� :ѣ ���D��%.�E�13� 3ѣ�N"D'щ5�D�F��^7���]�Z�z����>�쳟�˥�A�!���0HDT`�n� ������`P<�V��2`�p��b�� 2^� ������`�@���D!�c�� �ȹ��*�➋`�+�\7"�=`�tBT��ʹ� �@�F`�N��6NH@ C�qA�- p�'�0h8�oM8�?Ю,�Z�-��A�������� ��t4���x��5â���>�_��/��/���u�'!�p$ �A�!�d��M m�<��?w��t-w� p� ���f?wrCQ�� ����t1p 0����YP������_�z����9� $N醀�#��V�B��-��� ��]��O?�ڏ��c�N��;�z�?��<�5������0 ��⯽�b����P�?��� ��\��"��"���������X��7Oa�#i�����|�����žc�4���׻���9$� #���d��� |�r o �Y ���{��i����gK�X� ��/(���l�o�k�}�� (V�{"�B-�XO�����Ξ��uZj�uӘ����'OM��{$ަ�,}�'O���ίm�E3;1|����KyzI��!TB3`��e��da�0$3�;�6/�3��?��=�Kqr�ytn�E�Gu��2�rH�tn��%Mb����Ԉ��p���s�ڧ��� BJ�� ;`���e�`FX(���8WD"���Q�/�]��*\ұa���R���ƨ�oV@~�CM�…b���ԙe�3'3'>]�����}TJT��!�{��Q��yŦ�r�؞�{� } ���2�%.�E�v�p��z#J�,���� �Jc9u}-�*��;���\��pf4ѫ&�wϯ,����3o���;��!��@ �LG���l��*��* �7��$��WWp�YQ5Ϛ��5#� �o�9�-Ͱ�Eq?s�Hf� �=���R�=]q'b.�"_{�88�  �8i�xx��s=����e2����6R>-M�Ԝ�y$l�$H�r*R���e�K����\�w���:�(_��``�M�:�Ǧ�B�Բ���mhR������@NP� ������>�ѝ���U�%' 13�at�Ljg���t4O��� "�����)�<������u���@V���oYA�38�I��G 4_�?)o~[u�.ᅬp�L��w��$,t�tQ�[ �\6Q��b�})Ŏ�72K@���w�>T�8~5,N�乁c�-T�l�v#$I�2<-�fJ�LZ�����摳l�ru^��P�d<�����=����.m1�MMf+k���m(���=�[�3�/71����,(��m�}!���\�.�·ڔe=D��{�ωM�^� ��E�2�� !���w/�3+���H�6��= ��M�4�A'�Z�,��Dƞ��i�*�s\F.�� O����N���ޜՍ �6 �۹�,���W!�#%X�f�o�߷90 )!Us�*�@��>i}�ޟ|Gv��-��z� C�-d9�D�u1N,t�A���� po%�Ǟ�Mݩ��vI��eʾ�&Ĵ6�����flVk�;���;��v��^�-Yl�M.#&�l��^���D�3 KY��O���h���l��u9�Z��M:IQ�t��f\��j��w��w�ŶLaG|�-;+���q�m��@٧� N�4 8���$ZT�cg��3-K�����V�n�*?�C�������m�Y�;��S^cyס�8'"�R\�R�.E�(/^,j&Ny����[뙧���}����x���0Q;�>vd��JKo���7f>��!ʏ��s�5h�r\T������esn���X��͈����S)lY,����W%!%?��b��<�W��Ӓ�,�c�{rN��=˾�^kNt�*tU"=��I�c����#�� �V#�{7�Y3�2LA�xi��S�����m��h�����N��L����8�����߉�_t�ID��p�/pQ�,gM���ZX�J�X�o�7M2�m�zC-}�q����ӹ���U���m P ��4���=9[�+�wm��+��٢������ڌ��h�)��xVmv�����5ʟ��بD.��mC9��+}���s��#�@�}A���Խ�� t�����1��`Sz�?xU�qe��1J�Ȁ\$�ͩ-wR�x��� �iV���n���$�|3"j�[=ts"$J5�<,_{�c@QēGm�U:�I9;�<���J����2��zt���.��YY�$��m~)��W�Yv\0�c����egs���_��i�o_A|��/��t���7��A���գrډ���Y���"RM��i|#!s�@�i� F�9P��ʛ�����NL�W����N�Nu�����l�Լ����֚EM�do�����#JR����8��Kn�G� 췒')���_�{��KS�m�⹲3,n%K���Gt~����ۍ����ٷ7]���w��y����=��u.G5T�nOM�J��Oi���4�SUA}p�0AxQ�')�ڃb���ـ>D>��b�6�0�*/�꘤���p&8��y��\�/��+5�D 8��ǒܚ��s�ϩ�R�XK���I������Hdݢx����N���� m&�� �V}ih6{�͎��Q�� ��z|y�ń�'���<3�r�eh�;�Xy�3���E� ="���A`�.j�����bZ����_+��2f��%����v�I^ف�7�Ҥz�3�q�|��P�o��_-�g畈�� eWG��ߚ�&P��J/$��/�32�pD�qDwu�&:`��O#4) ��=l���p7��X�\�~\���m�+���r���-]��hQ"�e���G���>x��T�h�� ���"#U������d���5�i\*�!������' ��x��A���E���@}oU��4��gn���ş5�Y,t���l����:��/I��Z�o8�i�o�'�"�v�){�g��d��Xߟ�;��ٺE�+u����7��{<��/&U�i�ѝ�*�v|0l �����������(k�N1����S#�k�><�E�WA);}:;%lo��� �S��˙�=�/ٳ�m6�~���z�����L��+�]qWCo�O�b96ew?�{Y9A��y��|�'?8*�Yf �d�W(��jP ]��~:e�!=�0���iټ౱]���P���E��f-|ѝ�6%�~��R�)�'����ryhz`��v,��z5�b�p�hѵ�1�[���$�1ʪ�{��Jb��~�Կ� ��s�;��_<9|9t��*�ʝ���X�|�Jy~�>�M۩^�L(�ݡ� �֣��K��Hڪ����z��Դ��D�j��t�³��ޘy���&m=�t9����+�r��[�l���S3΄�Q�D�gy+3f^x_��hi�ޠ�d�d��3����57hm �O��ڻ;=�����F��!}�7;����\+�9n"jqK5T������灁��?����"�(�l� ,A�]�Dn,����,fh�a���P��)��Fe�����ɻ3�o���5�2�i@{;H8dg�%������lo V������UÜ�{�#g����Z����#K��� ���2f}�{U�Z�I�ݴ�zEW1�M;7I^�_w󱛍^�1��cŐ=�����!m endstream endobj 2568 0 obj << /Length1 725 /Length2 1144 /Length3 0 /Length 1711 /Filter /FlateDecode >> stream x�mRkTSg" �]� ��S �"!��c�$!�H��y\��p/�܄�8ߊ�(����da���"�`�@^��@�Q�� P��Z��?���:���8� B���Qݨd�7��� P��NN �0�q��! ���u�D�P-�MJ��x)Hb�yDʄ8�@$*C��X |�J�v�\A���Ʀ�q� �0�n� HL�.���W!��b �!D��8���QD�i��� JÍ��04�y��02�y D$ 4�؎�ro#���v�ɄK�h)Z�b� ْJX�#��s���8�`�"i�d$7�$��.@�� ��#L���&&)plTa��>���"U����/�7 ͠#�F�( ,�S! ƍ~�Z����߰! �H\h���U�"���&W���� �.�|9����O!&Y��\!�pA�Z/ P��B�SA�����_���z�MT�-M�"��p�꥙�ZS>}��q^�=�Ƚկn��L4�IA���l���L�S��'J��n������ �����f�0��ݾb�oԍT��E�D<� ��&�����=�O�S���k�mX��L�71����m�6G���%�(o�b��54d��߸^4��n4�'��k�'����Wj�s7n�yJ�+���k��fȆ�s�o-�7�Er���������?��s=�;���1MJÙU��3OI�++����~�N4�:>� &D�>�qj�{S;ڦN)���ܝ����C���iA����}QJmHN ����R�ꢀ_�\m���2a�P�?���8�A���O-=�� �̳�[{%+]S;}'��ʡ�<�#{�$)B]s�jM� ڄ�uK�=)��ՌV���l������z# ��.H?��;� ,X^w���o�rWo���X��*|�fX1{=�¾iO��vo����j�I�$}�gf���N����O[9u��#�c�Z���k���M���#�9Mk/ ���nI�����3%8�x��B?ϊ���z첋9-�Z�e�i�}3[X��T>'�>���[����f��Z�W��:lL�P�h`+� endstream endobj 2570 0 obj << /Length 741 /Filter /FlateDecode >> stream x�mUMo�0��Wx���vHB��!q�mU��^!1�H����_�_��m����y��ݷ��DU��L�G�^͹�t���߷���.k���4�c*S���'�ҵ����>]g��,yݔ�KeF��$m���S��3�&�q�G���R���p����`I_�3[d�E��4ݹn�'&9綐7U�a�L)l:���M� z��!YU��0r��ўo>ν9��},�l�j'�}��4>��2]ݼ��[ivjs9�2V+V���h��� �~���y�8&�X�������-M�m�M��|ŖE� LS�7�Њ�~�&���� U� �2�X�(p�m�������� �XX�(W�8X&�LR4�=z��u�kT��GE��m7h���8K�c`Iu(�!a <#�G�� �>��n-tJ!]O2��`����̏S���#����'��,<ؓL�%q�O8\π��:�� 3ht �,�+�9�u�g�Cw�Ëp�D��|�O�R�ɉ#�ɇ�W �m藒�1N�wH=8!� � �4�DCp&q"p���BCT�/�9�!ɨ~B� }���Rq҉�T��FI��ܨ�ύ�|nT�s���|neEA��;~����<��6O���I��y��s�t��g>O:�yұϓN|����I/|���y���I�>O:�yҹϓ.|�R�� ��T�<��띹_����m�Kz}��K���=���W7��"��V��{�������/@̪X endstream endobj 2571 0 obj << /Length 741 /Filter /FlateDecode >> stream x�mUMo�0��Wx���vHB��!q�mU��^!1�H����_�_��m����y��ݷ��DU��L�G�^͹�t���߷���.k���4�c*S���'�ҵ����>]g��,yݔ�KeF��$m���S��3�&�q�G���R���p����`I_�3[d�E��4ݹn�'&9綐7U�a�L)l:���M� z��!YU��0r��ўo>ν9��},�l�j'�}��4>��2]ݼ��[ivjs9�2V+V���h��� �~���y�8&�X�������-M�m�M��|ŖE� LS�7�Њ�~�&���� U� �2�X�(p�m�������� �XX�(W�8X&�LR4�=z��u�kT��GE��m7h���8K�c`Iu(�!a <#�G�� �>��n-tJ!]O2��`����̏S���#����'��,<ؓL�%q�O8\π��:�� 3ht �,�+�9�u�g�Cw�Ëp�D��|�O�R�ɉ#�ɇ�W �m藒�1N�wH=8!� � �4�DCp&q"p���BCT�/�9�!ɨ~B� }���Rq҉�T��FI��ܨ�ύ�|nT�s���|neEA��;~����<��6O���I��y��s�t��g>O:�yұϓN|����I/|���y���I�>O:�yҹϓ.|�R�� ��T�<��띹_����m�Kz}��K���=���W7��"��V��{�������/zn�b endstream endobj 2572 0 obj << /Length 711 /Filter /FlateDecode >> stream x�mTMo�0��Wx���vHU�d�C�mU��^!1�H��$���3C �z��̼�ï��������g)>��]��Ͳ߻s��w�����չ�����"���ںQ�;4m�_%�= �uS��'��N�%���Fwڴ�.HS1������ʧ`��׮o�/�x�͟m/��с!��Z���K���NN�~������gEʪ�v�yW�~�~� �r-Ҳ\����b��&j�r ���A�C�u ��ad)��Xy� x� &�I)R��V�˘.L�I@�o�_��pi k-c���p� [� ���n��c�X�z3�N�4ִ�W�Yf�����%� �9%b��*ԩB�+��|���A��_F�:C��9�Q�Y�5��K�E�9r���W8�f�a�D>�ϐSG&�x�V�_kU8!��8��0L5#�D� ԏJ� �X�'9Ł�?�: i�YI�WF�܍湛��n endstream endobj 2573 0 obj << /Length 683 /Filter /FlateDecode >> stream x�m�Oo�0����C��@���@�����8l[�j�WHL7$Q���!LU�z�����S����nf���f�onh/}�f��}��emy9�f|v�r��vx�}[��(��m�m�����My�Tnr�l��n����w�wV��qTrv�ԧ�nf���x� �Wŷ���?��y�QJ� yS��N2�k1���ꯑ�J��.����g%м�Fw�6�6X���Ϳ��S>�r}�|��o���ݥ�Nrl6�rG������ى��Ǽ��?;'4>+JV���}��}�Ⴕ��.�M���ۻ�:�ɚx�\�_h�`���:����P���p/ *,}!��$�B -fu[�ǘ6L�����Qe� }�ĭ��Ak���2$mAG�s� �A��I�:ם����J�� "ʔ4�3:K��a�Cg��"� s�� rJ�_i:6dPtk6�9u�̩3ȣ�" ��P݀^R/z0���cP�_Y̰��*�z�~ʟ�''�M�q_ �u��WG�5d��o�9J��O��p���H�+8�Q��hfgBfg"fg�����$��fg,e�@�yɟ1S�3SS0S+��U��jfjCfj#fj�����&��.��]1Sk����Ԧ��f������4��4U�4��4 �K�x�׆_|�0�n������:8�p���w{]�A�p^N3�^��?�'�y endstream endobj 2574 0 obj << /Length 696 /Filter /FlateDecode >> stream x�mTMo�0��Wx���$� !� �8l[�j�WHL7IP�����V=M��̼� s��u;�U����ٛ=w����������]yil;<[[�j<=?�׾+�v`��&ߴ���ț�<^*;�~&�Q���>������MS >�_��P��{=��s�@�d�����k��x�;`�VY�`�s4�Ja�Qܡn�����.�Uu9\��Y6�>���<�ٴ�.Z.�������4>Dӗ��}�~�������r:-d0�V��W����k,��8���y�Lһ�ʮ��Ӯ�����ђ�[�*�m��Lr��?���q��� �5F8@���=�@��)&�� �8�����Rx u�D�\j2H�����V���0CzL]� �b�ct�I �g$`htы0��\F��0���s���� jd< �I�6����zg������ W �qȐ��+��#�����k�� .�b�s��r��������b�m�X���K�7ǵH�7G�����nb�>&j�ؐ��u�������1�V�������ljOu$՟qW�S/%1{\�xB!���K(hH��TЖ枃�J�ρϯv����=k��2��U�Kς_:~�$�������/��� ~�E�+7��ˢ/ �l���(/}�� -+ZXuko��ԝ�E?Z�����K�q�� endstream endobj 2575 0 obj << /Length 739 /Filter /FlateDecode >> stream x�mUMo�0��Wx���vHU�d�C�mU��^!1�H������#x��?��g����x]OT�m�$|��͜�s_�I�ss ���:L;<S�z�==�׾��f`��*_���`ɫ�ڟk3��'i�Ѵ��}����=������M;��7��r��f��nj�-�e�SӵOLg~��8�� ����)ok� �A�8 �$`I\���3`�Af��<�Z]��!��� xNk�y����"�7�� _�㓧�q �H`�����n���ḱ��RONH=CpB:# =�%8��88QA~�!*�zƜ�А�T?!~�> �tw�8��y*�s��ύ }n���FE>7*��Q�ύR>7����G]�;~���<��6O���I��y��k�t��g>O:�yұϓN|����I/|���y���Ig>O:�y҅ϓ.}�2�� ��L�> stream x�mUMo�0��Wx���vHU�d�C�mU��^!1�H������#x��?��g����x]OT�m�$|��͜�s_�I�ss ���:L;<S�z�==�׾��f`��*_���`ɫ�ڟk3��'i�Ѵ��}����=������M;��7��r��f��nj�-�e�SӵOLg~��8�� ����)ok� �A�8 �$`I\���3`�Af��<�Z]��!��� xNk�y����"�7�� _�㓧�q �H`�����n���ḱ��RONH=CpB:# =�%8��88QA~�!*�zƜ�А�T?!~�> �tw�8��y*�s��ύ }n���FE>7*��Q�ύR>7����G]�;~���<��6O���I��y��k�t��g>O:�yұϓN|����I/|���y���Ig>O:�y҅ϓ.}�2�� ��L�> stream x�mUMo�0��Wx���vH U�d�C�mU��^!1�H�DI8�߯��-�@����=���ۙ�ڽ�����١=����?w]pw����d�����V����^���ڑݧ�l���#o��x�����d�G��a�����<�B����8�͌������4s5vSc~�/�u�<1��9w������`~��擲C�T�E ۃ�@HV��x����o?�ў6͡ ������0��^�C0�+�����Q�f��;ZP�x�^��\C��yw�l���+����L��@Ue[١ە��56H8_��(ցm�����&�rT���PG� ���2�w�`24XX�BX8a�� ���J���A�`R�Ј 衡�^]wq�&j9)*����v�`��R���:(�!bx�8�p������ׂN)��&�>0Ni��qF���?��S�ր'��Y��NR��}�{�f�{���x2��A�! �u x�k=�{�����Exo"�}���R�ɑ#���x۠_J�� �B �C쩁b�8!��=�%p&r"�D9� Q���g̑T�u�+�g�G�N���N8O-(7ZRntH�� ʍ�(7:��hE�њr�1+��w��(O:�͓.n�d�m����'#��Ʉ�'��<���dbʓQ�'��<���hʓ1�'�R�LFy29�����S�RAyJ%�)]\�����/�&xG��^y�{� ���?t��Ս���]��*�������"� �s�s endstream endobj 2578 0 obj << /Length 739 /Filter /FlateDecode >> stream x�mUMo�0��Wx���vHU�d�C�۪T��Bb�� A!����Gp��?��g����xYOT�m�$|��՜�s_�I�ss ���:L;�2�6�8{zb/}W����U�j����Wm�?�fd}O��i=���7�gR�x�=7��i'Էf�[�7�̖��s ~���t���s[(�:�0p �l:��5m�_��-tB������}W{X��8 �jw]��l�j'OC���=��6}Ӿ�������|<� D0,��6;�����96��ݕ��q4L�� MUW��qS�~Ӿ� �|�Ҳ\����Kh�v7RK�s|�*Z� -�1 �b[�d��0����8���A �� i��$C#.�C��Z\w��F�|TT����<\`Gc)y ,�<$��g� ��v��1a�粳[ �RHדL�1>g~��8�� ��䔷5��� B���{� �$.� ���� 3�qd���A�EBu<������q� xΛ��_�����S�8q$0�p�JA� �R�5�� a���'��!8!������ID��� ���� =cN|hHr���?G��t��T�t�<��Q��F�>7j�s�"��ܨ��F)�EYQУ.�?�yR�m�Ty�'�o���Oz��>OZ�O�yʄ�S&}������/����6��>zչ��{�Z���kZs}������=��?F�e����y endstream endobj 2579 0 obj << /Length 740 /Filter /FlateDecode >> stream x�mUMo�0��Wx���vH U�d�C�۪T��Bb�� �B8�߯�{ .�@����=��/ۙ�ڽ������s{�K;K���.k���6�/k+[M��'�ҷ���>�d��yӔ�Ke'��$c���S`v�f���S�f�K}�fƁ�VGG�f���\b����u�<1��9w�������|�擬C�T����AW $��rG�]��I����y��Msh�$a�W7y���̟���u���? s�K�-�`�θtJ!�'��c��8���3?Na��O��<�Dg!��;IX� ���0z�)rЃ�@��k�p�BQ]^�Z�7�!�� /��� �U �<��ɉ#��W �m�/%]cX�!��� �g���Ȁ�h��ID�8QN~ACT�/�s��Q����Q��Rs� 穅ύ�>7:��� ������F+��}n4eE�=zG~����<��6O���Ɉ�y2�k�L��d>O&�y2�ϓQ>Of��dV>OF�<��dR�'��<����>O)�yJ��S*}�����𗏿tx���>z���{�O->t��Ս���]��*��3>�c����C�~ endstream endobj 2580 0 obj << /Length 739 /Filter /FlateDecode >> stream x�mUMo�0��Wx���vHU�d�C�۪T��Bb�� A!����Gp��?��g����xYOT�m�$|��՜�s_�I�ss ���:L;�2�6�8{zb/}W����U�j����Wm�?�fd}O��i=���7�gR��d{n�C�N8�oͰ��of�-��%��6����'&9�P�u�`�L/"�t��kں�(a[� �duS �����$�x�q�a�� M���N�����{��}m��}g���ى��x��` �tw�8��y*�s��ύ }n���FE>7*��Q�ύR>7����G]�;~���<��6O���I��y��k�t��g>O:�yұϓN|����I/|���y���Ig>O:�y҅ϓ.}�2�� ��L�> stream x�mUMo�0��Wx���vHB��!qض*�j���n$HP����#x��?��g����x�LT���$|�����+�$��=wwY[������L5��O�kˍ�}���M=�Ƈ`��U���v+�NmΧ��@��j�*������Ѱ����ϓaҍ�*����mi�m�a�%�+�,�U`�꿹�V��#5�T>�W��U����2F�[l � 5�GT�8X���D����2�d����C-��X]��d>**�l��v.�����<�T���3�9pD;p����s�٭�N)��I&��S?^`��q�q���5��� B���{� �$.� ���� S�qd���A�EBu<������q�rxΛ��_�����S�89q$0�p�JA� �R�5f� a���'��!8!������ID��('��� =cN|hH2���?C��t��T�t�<��Q��F�>7j�s�"��ܨ��F)�EYQУ.�?�yR�m�Tq�'�o���Oz��>OZ�O)�yJ��S*}������/����6�%�>{����[��ቫs}�O� ���=��F/E��h�q endstream endobj 2582 0 obj << /Length 900 /Filter /FlateDecode >> stream x�mUMo�:��W����5?$R. �d9�M���� �eC�����k�m�C��p�;;�w�~>�|��3�E�_�?O]�5߶����w�]O�c�c]=~?�}�O�yh���9%?��۹�׬��B|Ɯ�>��)�;�v�w%g����4�3������>\ ��6���� �EJ����7��8� 1��{�~���`W(-��;]���%=����x����e_,�b�+-O�;q�\�L}���U��I--=���B����K������E1�p�[���! Mߊyu�>�.N��5K)Wb�٬�8��i�[�_��uʕM��zQ����)V���(T���x��ޢ��jy���!�����Z��2�P="�Zd�0\ÃG�R\���).�2*�Шa!�U��,����H�`+j��.�5Nα@����VK-�x�%���3�%�A�YӀz�Κ�>kP#�����5m0W�o��þ�j�������.��Z��T$X/�)n)�#W��o(�o�RZ� $K�p4��Z�-b�\�1�ܰJ� �P"G�X�Q��i/8�k�^��Zq�:Zs���9�d���B� �)�sL�-�7��x���J�����`�a�ɽ)f��$���1�� dъc�CZC�<�7�3J�g�z�n��HȰ���Y�ɚ�T��a����,_��-��O�87�}��KԴܗLl�oK��+�g�J��.�GZy�V��c�48������Wt�]�:P~`���rZ�q.n�1]� ��S��/��P���u��7������U������e��:�?���������&�?���!d��&��1y����H��n5���)���y�ғB��x#�1ޞ����]�Go����׏M�?�X� endstream endobj 2583 0 obj << /Length 750 /Filter /FlateDecode >> stream x�mUMo�0��Wx���$�*B��!qض*�j���n$H�$���3C��h<~3~�~�~�ng�j�v�9{�C{�K;K���.k���6㳵����ች�m��#�O7٦���4��\� �=�؏��8�ݿ�߳�4ւ����8�͌�����>sIv�dX���C�6OL�x�9���im�$l��6���D�����l_7�����ڞ��h���z�*{p����ɲ�������2�kA�ʶ�C�+m�k>l�p�fIQ��T���T�?L��A�>J�� ���e .1��Pb��pqH I$\kL�8Hb،Shąr =��z��51X�Q�g�_�s��2���Ē���+� � �s�C:�CQ�}.'c-�BbOE��u��+Xg~��:�?a���j �B�.U �$,����ĨA��A 2���A�%����%�"�� 1�9h�M��_���)ELN 1��s����R�3fg =傸a�C�Yj���V���^�w&L��=�� ��3�nqFy�DŽϠOL��5'�p�Zx?i������^x?���IG�O:�~���I��4���ϼ�t~�3]����[���gF~��Q�gf�}fB�3y�����,������h�3c��L�}f2�3�{����,��g��>K��Y���N�0�`�^�ay�{7)q ���W7�:����*�ሟ�S`�R�̯ endstream endobj 2584 0 obj << /Length 672 /Filter /FlateDecode >> stream x�mT�n�0���C����6�*�d�rضj��^p�H�A@����Cf�����y�'����n���`g�#govh/}eg�羋��򶺜����m=�O�o��ٽ��[׌��u��Rۉ�=Iۏ����w�{V��Q���Ҝ���8�ߛ��Iߞ3d_� �~�~hZ���#�� W�� c ��*��'q����U;��HHV7�x��wu��ɻ�a��;��z��o�p�O���_�����`�_���ݥ�Nd0m6��G_����?[6�v�����L�����C��l�w6Zs�a��D����%!�p�����%�b�l����c�ä ����� ��P�P�[ �u���_�g�_��x�4��$O���<X^\NB8 �\;c���BbM�x� �y�%�P� 3jok�:E q:���/d4�8��Q�4�A�2="\�šY�+�ː���s�(��5$�Y���� r�����~�+A�\Hȕ�Wr��{�N�xo������� ��$�TL~����K����/��/���p�1�s�Q�*�G��G-�G-�G��zA>�|�)��3�Q/�G�"�"�&�!uN>�|�%�h8�h�h$�hb��,n~���ᰏnˣ����+��p]��h���� \�����2� �M�� endstream endobj 2585 0 obj << /Length 672 /Filter /FlateDecode >> stream x�mT�n�0���C����6�*�d�rضj��^p�H�A@����Cf�����y�'����n���`g�#govh/}eg�羋��򶺜����m=�O�o��ٽ��[׌��u��Rۉ�=Iۏ����w�{V��q9;\��ظ�{3�<�c�c�K�a�/�M래x��@�jӞa�!�_u����ظ���a� ���_����2 y�9���u�6Z����c�� ��K_۾q���2��t�ɂ ƣ͆��� �ٟ�g��� x��v�I�AU��v�������Fk�7l]��Ⱥ���$d�5�T��W��M���c�B�{�p��!��Y�� ju��N�3>������2�b�Ʊ��)`�P��k��� �I���c�kg�UPSH���@"7#?�d�� 9aF��m-P��!.@'�1�� c��0�9�S�G��TX3 qxr���y����B��4 ���A�AN8pЏ}%� ��J��x�x����m�_�p?0�䗒䗊�/� �TB~���R����tА3~N>��|T%��9����%��c�Q/�G���:%uF>�%��W�V���6���G]���$ '� �$ML����/�����?��mwT���kW� X����ֵd��pZ���RF ׃� endstream endobj 2586 0 obj << /Length 719 /Filter /FlateDecode >> stream x�}TMo�0��+��J��6��*�ħ�öUS�����Ej9�߯� IV���c�f����͏睟�ݛ��{)^�؝�����}����]u:�vz����yu|�CW��$n�m�m��Α�m�q���5)��M{�`q�j�S�LJJ�WG<�v�Q�9�����ф[_� *��cӵB�;� m�uG�6z�Y�X���f�� �=�E�T��E���LB��s��q�:o���8N�')��OCm��}�_*t�ݩ�?,��m6��W�y�?Z���� ����Bӷb�UW۱�Wvط��[K���x���[[q��a���{I鰷6��f�^Zj0E�p��F ��]�p8]q�p��Rf8�2�uVEgE՟�0k�2��RqFr} yR�90�0����)�?c~ �S'*qXi�Ь"x�Wwi`C���iU^9�u�׬SC�fO4�iء�"�q�r��}5� ��� ���sQ?(8�!��)w�����0|��eΘ8���KƁ��?�Gĉ"���O���}= ���J8���a�S�c���1���&�zg��3��n���6cxdػ{�|� ��!� }1�I�<{��1� P3�;�R�S�%N�O�ij�8��4, ������'8��t��4�)�+�Mg�������������_��3�29��0��B����C���l�Y��P<�f|=��_���� endstream endobj 2587 0 obj << /Length 719 /Filter /FlateDecode >> stream x�}TMo�0��+��J��6��*�ħ�öUS�����Ej9�߯� IV���c�f����͏睟�ݛ��{)^�؝�����}����]u:�vz����yu|�CW��$n�m�m��Α�m�q���5)��M{�`q�j�S5��ү��x���O��%r^���q�� �&�\T�Ʀk��w(�:��m��>�8+>4m=�"�${J��������љ����8��=t�z-/nq��OR|�-���M�.n�T��S�X���lDm����q�b�]���go��o�*���c���o߭��r#�e��l[���⌷�L @ b���aomB��ҽ��$`$���@B)�@�p��@�)��p�2 d�� �Ί�?�a�.e����8����s`�Wg+`�#)�S�%~��8�NT�Ҍ�YE�,� �(��6�*�3FӪ�r44�P#�Y��f͞hhӰCkE8�8�+�j�"7G�9�~Pp�C�+�R�2C���#`�p�˜1q �E�������E�5�=��F]=7�z&`�q�p&b�ð�|� _/�c�S��Mr�Τ� f�/����%�m ��Ȱw ���\ԉC��b֓��x�5c��f�w(�:���K��z�g�qf1iXg���3Np� ����y/hHS>W������#���/�������5f�erT�apC� �������w=�衡x��z*��� endstream endobj 2588 0 obj << /Length 719 /Filter /FlateDecode >> stream x�}TMo�0��+��J��6��*�ħ�öUS�����Ej9�߯� IV���c�f����͏睟�ݛ��{)^�؝�����}����]u:�vz����yu|�CW��$n�m�m��Α�m�q���5)��M{�`q�j�S5MJJ�WG<�v�Q�9�����ф[_� *��cӵB�;� m�uG�6z�Y�X���f�� �=�E�T��E���LB��s��q�:o���8N�')��OCm��}�_*t�ݩ�?,��m6��W�y�?Z���� ����Bӷb�UW۱�Wvط��[K���x���[[q��a���{I鰷6��f�^Zj0E�p��F ��]�p8]q�p��Rf8�2�uVEgE՟�0k�2��RqFr} yR�90�0����)�?c~ �S'*qXi�Ь"x�Wwi`C���iU^9�u�׬SC�fO4�iء�"�q�r��}5� ��� ���sQ?(8�!��)w�����0|��eΘ8���KƁ��?�Gĉ"���O���}= ���J8���a�S�c���1���&�zg��3��n���6cxdػ{�|� ��!� }1�I�<{��1� P3�;�R�S�%N�O�ij�8��4, ������'8��t��4�)�+�Mg�������������_��3�29��0��B����C���l�Y��P<�f|=��_Ӫ�� endstream endobj 2531 0 obj << /Type /ObjStm /N 100 /First 990 /Length 3533 /Filter /FlateDecode >> stream xڵ[YS��~����u*̾U�:U@B ���%[���t����,���n���F 29U`�������E6W�&4�J�D0� ��_1 c������d ��I�p�ĖJ���5�2�k.��W�%B+xD)��>���2�4L`�%�qԡY��WZ$���J�`[&ъ�ϹD.@���WP��M@�J����V&��H!�\Rp�;�#@(�0�V%�� Gˌ �+8�+<�R�-#���0Q���1����Q��"q�:��L�@+�S\'�sڙ�&�p��3쒖%�RP�)� -t Z�P �BK�% �Z�����S��V��(Ȃ9L'�:���1T�,��=�ySPf@ c�m\� ݤlnG�P"�c����$�<�N`>�1I�� �@*X-x����9�0.$� ���`����l��� zH�a�T���-��VA_�=���̧ �v����` L�~L���1!�-���})���V�̠�BC�0`� �*����9�!����&�2��4# p1�� Z� ��=����Cq|��ħ���� ��� Z�$}�N�H����@�S ���H�w -�ƻ����3��;P�ہ�#���>^��wh[ �*Fw\�t�4��Hj� �F=���H�z�K��Z���(�^}&��׭�1�1he�[��?#!��B[};��y��#r��>M��|�z�.���j����wp������?�O��3 7��e"�{{�ɧ'����/F��#���Jg+�<�?�?L��[8�zDP �{����j<ͮvg7�4�g����rDއNR�����,]%�!�d�쓧�9 ��!9"/�19!��krJސ�䌜� rI>�1/W�"[�M��+r5��gdBR�K&���xJ�W���d�}F��5�M�u�R���zAn�-��y��HF�G�&SrGfd��R2's��'����c6����zI����t��@m��-Ȓ,�o n�� ��xyKVdu�HS��>'k�|'?�O����2p�E�����zw/._�����r�� ���u��{������m���3^��iz��E.*p��AH�t1o�!���������ߑL0r�\�0���P���(��d^�B���\D�n���x���������w������.�3��1�$�������D���}�i���n����/=�|_�b_�4�^��ޫ1���)7�t ��L��2g�aYR)f�U:�2�����U%�.�b�m=�����|����f�a���g'πᓣ�q �g�-�o��:�W�*�$�xz;&�t�����d�&�X��-�t��{��N�ҷ]���`(u�1�n��u�]^ձ���֫��� ���٤���M�C{��$�N�!گ�ww�`2��E�̖Ͳ����2�G�l��?[�}����Ҧw"P$R�Bp�?$�6���4�8zy���~q�!�4�Y�{N��3��<�.�a���\y<��U��"��/>~��}c:|#|6:X�����%����d�� �|8Ȃ#��h��a�Q�����ϟ��:n*/ �U��+:� L7Ü��Ƅ�L&6)�z��wxzp���`���|�������A�Λ��{{��|��z3w���|=h�iO�ޅ����ڰRYn���^r����&�C˼T���|8����q��B�M�?*������E3)C9=d����a ����O��?ty�;0w��}Uzܹ�$T��I�b1����0kP���xqr��:�[�M`��4�ֶӬ}��#���D��SN���l��>π�4.=�pv�>��sE�׶���k�q=P!�*�V�t��\�WX��V��]��u����Ѕ@tg���>�����e�� ���ĕ4�_����j?����V��~L;����}H���A�M��nO�Ȍ�v ±��4��:�<������v�2̭`��/`�}����k�����XE;��9�� k �'�/Nރ5oO��a�C����f�9��|Y�4�1�AC�ٳӷ/^�1�=�pj n�܊�-3����j>�f7�,�����*]&����Z������*?ŋ��{�e�w��j^�/� 9��O���,���v s�9�_̠�M��Q��@5_v�@�(� �D@��Z;�-T�� gsT��JFP��Z��-T��J�*UA�T������%YoT�1�&9Sc���W�n���&5Sc7����RwcrLz��0��7�JL��I�&3S}����RT ���b�d����R�b�"7Q}O��H )���u�� ��z+�uUL��d�)�u} S+�E�:<)KS���-�xsQ��� �,2��-jxs)��[1.�����-�xc��ԊrQ+N�U)�v�"ޞ�`��\T븨z��)_�a� t��ޞŷ����Ր�:T�0�[���� �~��8p:�I�0e��q-<�����o�^f��s_�/C���觿�����?o�D���%���-8z��o&�/!�Tb���XQ돞�$�7�W]�W��w��^�����`��h����Tb��`bh8�bG�܈GXb��|b���AIPj}�� � Q�hU� �M��N����QG���ߠ%�o $΄�Ґ�64��^ ��c �~x�A�����6���x�*�l.�S�c����sV4�#Tq?W�a��iCC��c��J�w�[���� S4\hH �b�*VS% 2D�!�� �����>BU����xy��7]hвh�Ǩ�!G�.T��2 �#�#TU�1!Ƌ����:9��Ȅ3�K�d�*���H‹�����x��}�E�^ۼ��pS�U*C}���~��wJ�a��EΆʔ�8������dj�@���m�H�  �%�EE�ɺ��!��z5�f(#��$a�Ӗ���Y�6]�� �e*��o��fia�5�.�o�/���]��Yo�bj�*�Q�j�aŜ�K�� �! ۷�0�+�֐i�7ŠeS!���e�U�X5}}�t�b}�d� ��S� �J�Z� EEp�ʒ�K���`b4��KCx\ȊѠKt_�3UsE�Uf�U�������U�$E�x�;�����o�-k$(�� ��DY:^꾪T�F�KWWɫE�� !�M�%A�A��9U��"KJ���-jY#cY#J���� �cHDI��T8� E�p���#eߨ�x�o$�)���� endstream endobj 2594 0 obj << /Type /ObjStm /N 100 /First 959 /Length 3797 /Filter /FlateDecode >> stream xڅZێ$� }߯�G��Y�JI�a��8��޼~�̎�Iv.�� ��ᡪj�[ ��R)��.��b�̒h������u�sy�&/��7,>�0c��Rh�1,�-��%�%��.�%E��2V+ċ�b�慰ˈ��������� ����i���X�@h <�<-�?�LY<�K������m�?�3��`�7���ؐ�8[��S O�������)-.��'^�����4b��+Ov�6�8��<�I��)0X#��gd.�.�SZ�s���I�qe��ɚ��@k-�-xbra��Ls�l��c���J %����*�i��k�$O�CP,?!����KJ+;��a�q�lvl����K�$��br]��.&�*��/����h�ʛ��k�.��8D�8#B�L�x$�H#�,�D��:6�X�s�m��� rT�"3,#�#�ݖk������9W��!�8�d[���#[s)�VY�I��5_]�8X�<�D��}���(�լ�Ps�[� Qb�l0����NT<2;� l-� ���ql(�_��J�0E6zq��Z�cy��������W��?}�c��7����n�ǿ_�O�m��/w���.�t��8���o��쾖ͳ�8�ڵ����V��庵���[���2�]kEٯ��o[��t�Э崵޸7����ƶ��.=ٹ�Q:z���_�_^Oo<������>�*7��W���>Eq��s[�(�\�� 5ж?Vd�7����>"YI��s���L�����,9O��AI}P�8��u�2-��\�-d����K{TR�̀XKJ���dԙ-){�v��f>�6���� �����3k{��ض|�S����"��3C�.)w�cOqh)� �q�8u�، �a�8� ���8�-�q�i�9 n�vOP����+m�5fm���� �V��D���a�P{�%3�of �6N^�����[��a�J���a7�HW��"���)�] V+�[����_���U�)�݉�p�v�LS���=����J=�ډ?�^�~����͇���t`������>=��Nw��a��RsX�/��G�p,�'e'�>A��_x��?ܟ���9G�h�m�`!B�1����N�X�F��q����������h��6����O�4s������󐧁D>�����\��ڈ�D9�m�g��v"�!�؅P���>� b�!��2aй4C:ĥ@�F寧�l*��.��u�W�NVH͚^$�� ��H!M#!��>���?����{~�bE6����M��[>U��� �t�%Ù�;WFo?>��^���g#tB|/bD�α����M� �ү Ùy&љ��^��{����>0�-�E������1�;��nc?bƀ�ǧ����$hl _?�*{.5��OO�w/7O�Pyۨ���r�pH�Ҋ?�ol)��ɻF�p|}bT8�j;/z`g3t?�r��f������������ַ�~���ϧ��g������[_2N��������R;������������I�B`)'>��������� �3�y�kP� �s���u��|?S�Q1�9���q��;�X�T�*�%n�:S�n ����M�S�ĉw+�a����Q�l�4�?:uN�F�S�� ��F}ݾ�Z<(�f�a���4�h3��V�I���:�7lTu�s8���+�q�/kB:\iD�b��"�Ќ�L�.�N�WP@M�t���m��tg��gnb�tިf�7�o�~���/�+7V*'�Qa���k�1>h1~� W��4͹fNO�Elϭ�5؞>klO_4 �gP��� N�G9̚:&�ǠPi��5 H�i@SH�4��i@S�/9&(�YW�Qa҉ˤkP�*�J�,0����F=Sz�ì�oN@N3���4M�P�4��H� O��v@9̺����,��4����u���Q4�h���ܱrgM���4��X��ˊ�Tᓦ�I��Yű,� (;�@S�W5�)���H��(��YJ�lzh����O!M�{��4 ^J�4��)ӳQP��8&̓1��"�1��1N 5�\cv;��F�[U4w.�i3眜��n�LJ�g����ώ��|ꬪ���F� 7K� v�6��W'��L�.h*�A]�T҂:�Tҁ���$���@�X�iWܓtJ B �R�\\UASI���b�R)p.V*��b�Mݣ��U�J��UZ ��ʑ��*�Jl3s�λ.�6u/W��j&���4�$�r��J�S9�Y%ɩ�®��Lg��!9˵�e�5V;ϊt��S���!M%w�&i*�,5YSɭ��U��0r�j�fS�ƭ�Tr=�U�ZP�c+�jPREN�P��7: �f��Q�C�mƈ�Z׬RI��U*�75�J%�Z?�.�#SfM=��w�E��D{[�Ky���f���J�Cy��懟��0�{�\ʋ��=��^U�VU��w�V%}���� �N���g=K�7���s�rR�J8H'@���$ JA�NHU* t�e�l��ljWܬ�@A�*~6�1� ?��y�fR�%~6���S�{�ʼkNJ��/��I�W��1��?@f5^��/��.�x��x�]q�^$f5\�&0��7�Y ��Y ��peu�x!|�r�"'^sS��xy�WQ�%h��I��Su���&�؊劋t�]�P�T'$�h̹PK7) )�IQH�͊B����N�p��r������R�n덐�7*&( �Rd��z;cg[N�ϙ9$]~T��rUDE��K���Qy��=�1D�^������µV��+�5�����'U��yb7�ﺸu�U&?m�V�L3���d<� $l��E�nP� �z4�/�a�{�nܝ���ح�.�]I��"ag\im����$�rs-R�M�Z�*a�����F�PO)u���B��G��|w`: ~�w��_�� V�Q:0��5�Y� ��'mmI�8|�bGqJ�E���ƣk3����ɶM ���w6���m���e����J�����6H�� ���ի�$� -�� ���W�E(�$\�f���}�`rK�� �n��� �Y�P�v��F�r�����}��-֛�6ic}�o���qm ��=T7Q���&FD_�LP���>��$���!�YD�\���`KӉ� I�o�tp��ϱ�D�܉@�� Q���@��F�$��£�P�D�ر�|w8��;۲�@���d��`[p ����a:��B.����X'�#"��ؕ��������#�/�G\�T���4�|�ئ{Q���DQ��3��\���=��z�/ի ��E�f>�����0�JwD���EDzu�{�ʗ����α�Rhc]@T�-��Rj. *uU���bt�v�ʥQ�sCۡ�׆ֵ�]�'>N�]������.l��ߦ��ݞ�����G���|7r@�(Q����o�n#F��Xo�(��g ��s�G�������3����o��h���:�88 ���A �b����� ~+��^4�����퍳�i������2 ��~��0M��� L�QN40-�( ��>=�4�ilFzH�� ~4�)ܡ�Oy��t��~A+��@��������ԏ�9��H��Cb���`i������eH7i�� zH�� ~yq(���a`z*��n`F��`F�`&S?~��0�����W����KD6�[x��fH �Nd3I @��O��U$�!'�>�͐@h�����F��x�� ����S?^�?�~  endstream endobj 2665 0 obj << /Type /ObjStm /N 100 /First 1040 /Length 4146 /Filter /FlateDecode >> stream x�}���%�q���zXC�?�����Ppف��0��5 ����~p9Cv�g�~�93ӟ�����=pP�����D�S�uf��Nt���T���U��0v�g�����8�<#�9���t��g�g�^8�����y�O���[8���f�e�������rV���h�z�}�vyO�����r\���z{>1 ��=�s�?��c�k��|򝉣zrN^e=����d�s�z��D�p4��/p4���qdO�xq�G���QG�Z/�����ճ��9Zϲ���g�|ֹ�����}&~�����ڳ�Hr��ٱ�q�� �[#���5��(^f�C+^g��(L��x+�<����EO�c �J��&.;���5�ڏ q�cfuD�� �hӜ�=���2��9�G���v���f�UvF33���h���f�v�h�'�{N>&�{Fs���Y��1��pD�!����-�̙���3Z��3�I�X�sxF��bf'�F���=���A�'����3Z"����$:��gU1��e]p��Mt��v�{r��ъ�G9�zq�@�qғ�=�-�m{���v>�g��pC�Y��_ʗ����z�(=���ÿ�������?�����������6�ǓG�����[��.��[��$�4��4;�'��������~��L����_���o�\�d�D�οЬ�.4�4o4�g�t�՗����n� �O�����$���&Q%t6�*�����cNw�.m�6 B�$JBh�D)=��y�>��ݿ�Ai��)(�tAi� J�(]P�% �E�t���ҡ@���tH J�5� kA�hS��7�_P:$��I��ShA�ZP:%�$K��t����)J/(�����yC��7�NI� ɪ����ѿ���ҥS�ҥ�ҥ3�ҥ3��%��!Y��`Nw�.(�>s�h���?��!�� i��kJ3�_��������� ��� ��L!�Ji�����o�fȿ�k��ݿ �o���2���6C�-�Pz/i�d{7���o�?����� ٯ���������X/i^h���S`��=����0��h�T߯(�u���l�h��Qz kB��$���D�n�Z�z��!���C����WU�f��L�rp�M���}�Ag�Ӡ�x�i�Y^����,�cPl6�c�]Z�T�КV�ŰN��&8���Y�>v98�o��PZ��t(-�w:�6 ˡtj3��7�����e��'t/�:-���o�Kr�7P��� �r�ݚ .�� ��`~��.� <�@���.K�\Hcų�m��(� ����HͅQ�J]���.�'5ܘI�I��,Nh�Hj�PI�C�Kj5 ����A񢹳�v�:���B+x�&NQ��vj�PEͅ� bRs!��\�&5ƱI�e��&57 ��Y� �8� ����A�t�o)vό��'6����(�5 u��pB�Qsyk�Qs��f�\v�ͨ���F�Cãx���͙�'taPs1v�"�J�Ss�{��\�95��fs���3�.�� ����3��b���i��Qs�n6���~��-��r��qBS�"F�4�g#bZ��dE�jdE+�>�kl�]�ڒ��0Ml��0�4 J^%/���� �]���pѾ+�&6��&6��&6�H�&6�H�&��FR�դ�]=��zhL��k#`�:8��;5��� )J]�H�����K�֖��ij������ij�H������Cm$E�W�]H���hLW�G�t�|LW�R�������")��$�]M���hLuxc�hN��W4'*�Z>��˶�}|/��]S���h$LW�G�t�| L��dEW�GVtٜ6��7_f�]X���hDLW�G�t�|DLW�GVt١6������ٝ���hmyш�.��ĔF �k+BL�]|���w�����1]|��1]|��1�4 .�k\A',z�߅Fo �N�tq|0v)&�ɘ��N��',��,���^M�Z��F'c�ܫN�tM2��$�C�A��� ���V#��⥝�C�����S��6ś�wp��Fz[�t2f�kFZ���Ș!��NX 1�NX 1�NX��c����V#��⥝�⥝��aPs�0��iϚ0�j���H<�R�3�2�d�P�KX ����P�KX o�-�j�1C]33d3ى�����jtɊ�F��Y���n: 3�4�0C>(pf�NT ����������Ho��N� 5�$�P�@� }�C�g�!�)�����jdt�#�!O� `F��\�u�b�%�b�%�b��u��m52�!N:�Qס4 ���bx�� H�Q�q/E[� f��f��f���bȶs�C�r�c}:�]�������̐f؝f �b�W�b�&��jd��� `�X� `�|f��5�:]j�5<���C^���h��A� 1�A� �I��M��Ȋ!�8Ȋ)�8Ȋ��/�]���D�+D�+D̔�� +�x� +�aC�Mw52�jd1S�4"�����b�����A���xAV��S�����n3�N����"f���b�s�S�r���a������>剘�s� b�o���� ����!ȊiM����$�4�-%7�-%7�-%7�-%��g����}W0S�t0S�t0��� )�+AR��+����7?��FF[� ������⤃���� )j +�� H���0�jd��� `�X� `�>y0u/7H�)�8H���$��7|~�]���L����v0� qW�z.�b��%)v�<�jd��� `��q0��?ysS�/Q1�����`���h��A���0��f4S�,Y1e/7Ȋ�F�����/�jd��� b��S"f�%b��ਹZJ�b��$+f�;w52�jd1S�h��96~)���Ӛ�Ŕ��$,�&��{d[�L2fn�B�i�1K�iK�l��X�����}!�Ff[�L2f�=�+/Β�YbZ��XbZ��X�Ck�&�{-�jd�1K�i�1khp�|h�|h�|ho|Y�]�̶ ;�wp�1KLk�1KLkKLkK�r��X�I��!�m52��55 J.�4��%�4Ɋ%;�IV,�\��v���lӉ�Y�Y��Y�Y��Y����k*.�+������Ff[�LfI�>I�%5�$a���*��%��p��I�b5>0�jd���$a���$a���$a���$*��$*Vjp��`λ�m52I��5O ����)��T��Xb���X�$�]�̶�$̒�`��Y�l�0�Ds�b�N����G�*}���l��I�,}�1K��%�\�����J�� ��ͯ��D�<`Y�O� ���v0�z9L�� �J ������U��hS�S� +�K��UJ�%HuMw��-�-H�9�W��\x��H@)%�zR�v��f}�I[�m��k��i������Ԏ��� e?������_��]��[�w����J�v�G��������2�� endstream endobj 2815 0 obj << /Producer (pdfTeX-1.40.24) /Author()/Title()/Subject()/Creator(LaTeX with hyperref)/Keywords() /CreationDate (D:20220523085650+02'00') /ModDate (D:20220523085650+02'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/MacPorts 2022.62882_0) kpathsea version 6.3.4) >> endobj 2766 0 obj << /Type /ObjStm /N 49 /First 482 /Length 1633 /Filter /FlateDecode >> stream xڕYM�7���1c�T�RI` &��|��k{0���YC��Sսϙn�g KM���^�Z��MZ$�@Z4�����N��N�wǻ�g�VvAs���-�eճi����u�y��}ڧ��^'ig�<�������C�eq񛫗/G�m�w��0�15�����L�_Yy��+[Z' �mQ�y,.ޤ����;d�~v&I�l�� ��ic�ֲ�sHE�Y���1b>�Y\��<�ŗ�5��V��uNj����n��ٶ̊W�m��,��$.^/���V/bZg���,+���I�cj�5�~6l��,��y��h����Հu��w�p��$ G�Qd8����~G����2��X��p,�Z�������CH�p�O"yBZ� �]��3d��|:5�L�Q�<�;>�ph��4�-M��=2��]��SK�6���*�P�����c�vn�!�>{Φ@����K�\�$=�<�L�6�ά��!�U��ȌE� ���+^���'Tf�"�Щ�G|�C9��P���\�*�����T8��9$����"��2�Iە��ݻ�?�|~0�������������H%&�BAF :uX}�ʠ>�>O��V��y�X�"���Po}��eF��������yJv�u� b�$�yl8 �*�����Bl������%&���o ��Y��6h�BPDPDPD�3�� ��~\B��׭�dhbhbhbT����L��L�3�;�0$1$1$e:�T� �:�7{�h�� :2�A&w3�+@(�� . . .�����!B���W۴E�Z�Z�ZPB�ͧ5_;.��z��� �T�����>�b^``�|yE44���JY`�K]�� �(�B��� >��B�����=T�� "*jYA��&�b���`AD�� Em���6VYl��v5�hPѠ&W`r�m���v1 n,Xc�5j�B��L���{_Qx��5��"�� .����o��֨ "`o {Ӵ��ە)���� *`l cS�n�L���~�v��C%���),Mi�5�,�+�D��!N�p2����m�]B�S)�O��S���vk�K���7*�g)—( �'o���b��� �p?�PGS8��vkH]lW<^(|P�*P_S���vk�E �gP3��5��i�n ��s��(X�������c05�mG>���� �F��:����Z�ߗ��+���� -�6��i�K�,O>~*,Qa�Z!�07����ϋ� WT��6(��)�M[��g������x�S؛��j��j,�ӣ�+L��ݯ��*����~����p� g�x���ҥ���x}8��Ӈ��������77�>\]�j��'u�/��勽P��)�S�ǂ� ��>姻���?O\n����÷����� endstream endobj 2816 0 obj << /Type /XRef /Index [0 2817] /Size 2817 /W [1 3 1] /Root 2814 0 R /Info 2815 0 R /ID [<7CE18B0B82C766451281EAC122FDB581> <7CE18B0B82C766451281EAC122FDB581>] /Length 6492 /Filter /FlateDecode >> stream x�%�i�+mz�q?���S}�}���g�������k�� L�+�C^��"��� �ƊF��A !��Cy40X�J$���D�����ߝ/W������U��]�Z����Z�^K���ZU�Mo߬����Zm���S[��Ѱ�j;�6N�|��j� 3�Vۥ��p,Tۭ��p,Vۣ��p ,U۫��p,W;���p�T����0�X�vY-^ ]�vEm�a���jO�b��a6�=U[j_�f�gj�ֶ��qm��n��j�j�v�N�j w�n�j�쁽j+զ ��~��(��pP��|�&R;�Q�#�Z��&�IãpL-r��� ��m��I8�����~���Y8�v@-�9��� /�%��;��0� W�N�}6� ��N�}2�7Ƶ�e���7�V�61��>ކ�q�}E����vU��=��vM���ծ��>�Gj7��>�'j��^>����j� �� �uj/ ��֫�0��Q۠�+�vV�a���j��b��?��U{b_�g�{j�v}���ƾ�5O�x�&�~]��ۗt�����bsC��'��j��>������7dgZ-��s����j����*���v�ɨo��/U;�6chk�/W�/B�}[r�Z|� m���j�ոѷ������R��6��z�ej�����Ֆ�]3���7�mV�d���ߪ�㊡��?���BV>�m���v4�[�v����� 6���T������^��u!��͹ ������Ӿm�l��c`��[m��V�g��?����5���{��2>~|/��7_q|�J�1F�|��C!�����o�賽o;��h�#> ���|���� �6�>��6�>��~�D�����W9vc b�5��j@쨦 vO�NiĮh�h �ng��f�Q�_�ڢ����&՞�8j�'�������_m��.�6�N��vK�!\�8�������a8�j'�?�p��q8'���3p��y���><�n‘T;�#�q�;����*\��?�;aџ���� �<��p+����X�cx/�%����~Y?x�J�-�I��V�۬Uڹ~�ޥ��_�'��'� �F�S��;/�1���=dH��U�M�o}��1b��ڻ�C� �1�ƐCn L �������A�p�u�n[2CZ %8g��y��%C� �=��P��8�`�0�#v@=�8f�wG � VD�apc�2�� ���ː/C� �2$Ȑ CZ /��}x>վ�G�o��2\2 �0$��0gx x5$Ð C2 y0�ڐkC� 2����*��'�(5$Ȑ C� 1$�� �:H�%�{��Kk�o�%Ï��!7�_x] �a�A&a ��4,����X �`9���� V�X �`=l���{�j��� �-��k��� v�!؛j��{�l����{���C�9� �O�|�ٔ��~ W�DJ;o�p4`�`>d0 `!,�Ű��2X+`%��)��Xka�� �6�f�[al��v�n8 {S:�2���8M8���cpN@�o�J��?�E��3p��y��\�+p��u�7�~�vJ��Ē��M��nS�� ��p�6���M=�dSO����sp�5�^��lGdoR��NJf����;p�5��VM}'SSTi��v�L� `D��ɔ�������=?���Cn����F�mn����F�mn����F�m��W-ڴhӢ-����l�up�͍67��hs�͍67��hs�͍67��k�Z�iѦE�m����~��mn����F�mn�y����g���h3�͈6#ڌh3�}Φ��]�� m�o �m0λ)Ў3u���<^�mF�E�^[�화>N���iю3�8��F��%ǿ9 o�Ѧ��6F�/R��7�#ڌh��̓��ƿH��v�O�q�R��o�0Χ�1�ƈ#�#��Z�1bĈ#F�1���#�;�hIJ�p9ύ-F��bD�FQ`D�FQ`D�FQ`D�FQ`t����d>��H�#��d>��� �S �G��G͔��9�37F<�`�W`�W`�W`�W`$��ߗ7F~F1r)�_��X Fd�aă��G�N%=�(fb1��q�b�Eܣ�k��#>e m�w)�Fl��f"��)�揣�`�'j01KҀ�����`:���xq�t��F�e�E)}���� bc ���Yf+f6�9��M`fbf �����a�%� ��~8M��c������8 ��8���p N�8�����~8��]��p �� � ��6��� ��><��#x O�ˣ�� �� x ��5��Yx � ���|�v��n�:�+䮐�B� �;?�W~#^��nu�ܕew��*�Y)tyϾخ|�+S���̻1C%�n�K�D�h�kƯ�a�N�ݘZ�X��+���T����P��v�kߏ�gaO�O���Q���c�]Zty�= d��{&C� ]2t��%C� ]2tE�=����8��Ҭ{ �ZtiѥE�]ZtiѥE�]ZtiѥE7�1�mȭ� ���XA���K���F�������F�]nt���F�]ntߛȋ?�����u�K����A�:L�{��xO���U,���Sp��Y��S���i��\�Q��� \�k�tcQ/�f�����6��� ��><����>�����������Z��*�����u��70 o!y�u�~�O��$3&����F�=n����dz a*տ����ǒKz,��7>���3^��[���Q#H� =���#H� =��⸓ =��bښ =�����~�{��m@�Azq)� =���#H/.���q�S�=A����>ˋـ8W�J������Kz��q�G��y`D� =2��л7A�=q���wO(��Q˯��� �'��z1�ɦ�z�鑦ǒ^\�cO�=1��1N�D��2A&`4`�`>d0 `!,�Ű��2X+`%��հ��:X`#l�Ͱ��6�;`'�ݰ��>�� 4��#p��q8'���3p��y��\�+p��u�7�܆�w�܇��Cx�� ���SC�S���"����ϲx� ^����������3H���J���+�Wү�_I��~%�J���+�Wү�_I��~%�J���+�Wү�_I��~%�J���+�Wү�_I��~%�J���+�Wү�_I��~%�J���+�Wү�_I��~%�J���+�Wү�_I��~%�J���+�Wү�_I��~%�J���+�Wү�_I��~%�J���+�Wү�_I��~%�J������ �*2T2�d^ɼ�y%�J��+�W���?��#���w���S���5�&��̃L�̇ �a,�E���RX�a��U���ZX�al�M���V��a�]���^����&��p��18'�$���p��98�"\��p��5�7�&܂�0w�.܃��rx��1<��� �� x ��5��Yx ��=|�H�|��?�U����s!�B�c��"Շ�ώO�c6>-�?C ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �@N��9r ��)�S �����%J�}i�/m�%#JF�2/e^ʼ�y)�R楐��|^���by1�x&M��N )PR��@I��%J �()PR��@I��%J �()PR��@I��%J �()PR��@I��%J �()PR��@I��%J �()PR��@I��%J �()PR��@I��%J �()PR��@I��%J �()PR��@I��%J �()PR��@I��%J �()PR�+�5k���a���90 S02���ͅ ��b�E����Գ�Ԥ�\Z��k!�_���*ֻ2M���x����״i���ǰ�נ�ˬ���5��4��5��5uv5u96�g6��^�s���!{S;o���l��p �������)8 g@WgSgS�f�h:k^;M3@M��M��MgrM�g͛�ra�6��� �t�߼@�k�!<GM��OA�a�9�����q�5���o�����������)}�&�v�L�I��$�n�u���%�H_�I��$�d�i2�4�d�L2M&�&�LoJ֑���LI��$�_��/���d�K2�%���LI��$��m$Y'2_�&��R���ib��x$}�%���LI��$�!�iK�:��_��/���d�K2�%���LI��$�_��/���d�K2�%�~��#}�%�֒L�I֑�&�LWI���M���5�dJ2 %���LCI��$�P�i(�4�dJ2 %���LCI��$ӥ�u���m��C��ה��$�֒LkI��$�Z�i-ɴ�dZK2�%�֒LkI��$�Z�Ek�~��C�%�\-M=>XK���UΥ4���Q=M��d<�H���x4/�{��x�H�~�}<�L�~��x4�˻�h~j���x����?�M�����т����x�0Mf��Ѣ4���hq���?������ɻZ�&����G�����s��Ԣ��V������У7���������;_��篍���c4��G�q�'�8��1�}�K�:���q�wǸ��1���1���h����h�&���4��'kn!�[al��!nX�;K�6��w$n�q�Bܗ7"4!n9 G�(��pNB�Z�R���p���q�I�c7�\�kpn�M��a��]������c�[S�^����9���� ^����������3��n��R�t�-,�:L� " + value.printObject()); } \end{listing-java} \subsubsection{Introspecting a LispObject} \label{topic:Introspecting a LispObject} We present various patterns for introspecting an arbitrary \code{LispObject} which can hold the result of every Lisp evaluation into semantics that Java can meaningfully deal with. \paragraph{LispObject as \code{boolean}} If the \code{LispObject} is to be interpreted as a generalized boolean value, one can use \code{getBooleanValue()} to convert to Java: \begin{listing-java} LispObject object = Symbol.NIL; boolean javaValue = object.getBooleanValue(); \end{listing-java} Since in Lisp any value other than \code{NIL} means "true", Java equality can also be used, which is a bit easier to type and better in terms of information it conveys to the compiler: \begin{listing-java} boolean javaValue = (object != Symbol.NIL); \end{listing-java} \paragraph{LispObject as a list} If \code{LispObject} is a list, it will have the type \code{Cons}. One can then use the \code{copyToArray} method to make things a bit more suitable for Java iteration. \begin{listing-java} LispObject result = interpreter.eval("'(1 2 4 5)"); if (result instanceof Cons) { LispObject array[] = ((Cons)result.copyToArray()); ... } \end{listing-java} A more Lispy way to iterate down a list is to use the \code{cdr()} access function just as like one would traverse a list in Lisp:; \begin{listing-java} LispObject result = interpreter.eval("'(1 2 4 5)"); while (result != Symbol.NIL) { doSomething(result.car()); result = result.cdr(); } \end{listing-java} \section{Java Scripting API (JSR-223)} \label{section:java-scripting-api} ABCL can be built with support for JSR-223~\cite{jsr-223}, which offers a language-agnostic API to invoke other languages from Java. The binary distribution download-able from ABCL's homepage is built with JSR-223 support. If you're building ABCL from source on a pre-1.6 JVM, you need to have a JSR-223 implementation in your classpath (such as Apache Commons BSF 3.x or greater) in order to build ABCL with JSR-223 support; otherwise, this feature will not be built. This section describes the design decisions behind the ABCL JSR-223 support. It is not a description of what JSR-223 is or a tutorial on how to use it. See \url{http://abcl.org/trac/browser/trunk/abcl/examples/jsr-223} for example usage. \subsection{Conversions} In general, ABCL's implementation of the JSR-223 API performs implicit conversion from Java objects to Lisp objects when invoking Lisp from Java, and the opposite when returning values from Java to Lisp. This potentially reduces coupling between user code and ABCL. To avoid such conversions, wrap the relevant objects in \code{JavaObject} instances. \subsection{Implemented JSR-223 interfaces} JSR-223 defines three main interfaces, of which two (\code{Invocable} and \code{Compilable}) are optional. ABCL implements all the three interfaces - \code{ScriptEngine} and the two optional ones - almost completely. While the JSR-223 API is not specific to a single scripting language, it was designed with languages with a more or less Java-like object model in mind: languages such as JavaScript, Python, Ruby, which have a concept of "class" or "object" with "fields" and "methods". Lisp is a bit different, so certain adaptations were made, and in one case a method has been left unimplemented since it does not map at all to Lisp. \subsubsection{The ScriptEngine} The main interface defined by JSR-223, \code{javax.script.ScriptEngine}, is implemented by the class \code{org.armedbear.lisp.scripting.AbclScriptEngine}. \code{AbclScriptEngine} is a singleton, reflecting the fact that ABCL is a singleton as well. You can obtain an instance of \code{AbclScriptEngine} using the \code{AbclScriptEngineFactory} or by using the service provider mechanism through \code{ScriptEngineManager} (refer to the \texttt{javax.script} documentation). \subsection{Start-up and configuration file} At start-up (i.e. when its constructor is invoked, as part of the static initialization phase of \code{AbclScriptEngineFactory}) the ABCL script engine attempts to load an "init file" from the classpath (\texttt{/abcl-script-config.lisp}). If present, this file can be used to customize the behavior of the engine, by setting a number of variables in the \code{ABCL-SCRIPT} package. Here is a list of the available variables: \begin{description} \item[\texttt{*use-throwing-debugger*}] controls whether ABCL uses a non-standard debugging hook function to throw a Java exception instead of dropping into the debugger in case of unhandled error conditions. \begin{itemize} \item Default value: \texttt{T} \item Rationale: it is more convenient for Java programmers using Lisp as a scripting language to have it return exceptions to Java instead of handling them in the Lisp world. \item Known Issues: the non-standard debugger hook has been reported to misbehave in certain circumstances, so consider disabling it if it doesn't work for you. \end{itemize} \item[\texttt{*launch-swank-at-startup*}] If true, Swank will be launched at startup. See \texttt{*swank-dir*} and \texttt{*swank-port*}. \begin{itemize} \item Default value: \texttt{NIL} \end{itemize} \item[\texttt{*swank-dir*}] The directory where Swank is installed. Must be set if \texttt{*launch-swank-at-startup*} is true. \item[\texttt{*swank-port*}] The port where Swank will listen for connections. Must be set if \texttt{*launch-swank-at-startup*} is true. \begin{itemize} \item Default value: 4005 \end{itemize} \end{description} Additionally, at startup the AbclScriptEngine will \code{(require 'asdf)} - in fact, it uses asdf to load Swank. \subsection{Evaluation} Code is read and evaluated in the package \code{ABCL-SCRIPT-USER}. This packages \texttt{USE}s the \code{COMMON-LISP}, \code{JAVA} and \code{ABCL-SCRIPT} packages. Future versions of the script engine might make this default package configurable. The \code{CL:LOAD} function is used under the hood for evaluating code, and thus the behavior of \code{LOAD} is guaranteed. This allows, among other things, \code{IN-PACKAGE} forms to change the package in which the loaded code is read. It is possible to evaluate code in what JSR-223 calls a ``ScriptContext'' (basically a flat environment of name$\rightarrow$value pairs). This context is used to establish special bindings for all the variables defined in it; since variable names are strings from Java's point of view, they are first interned using \code{READ-FROM-STRING} with, as usual, \code{ABCL-SCRIPT-USER} as the default package. Variables are declared special because CL's \code{LOAD}, \code{EVAL} and \code{COMPILE} functions work in a null lexical environment and would ignore non-special bindings. Contrary to what the function \code{LOAD} does, evaluation of a series of forms returns the value of the last form instead of T, so the evaluation of short scripts does the Right Thing. \subsection{Compilation} \code{AbclScriptEngine} implements the \code{javax.script.Compilable} interface. Currently it only supports compilation using temporary files. Compiled code, returned as an instance of \texttt{javax.script.CompiledScript}, is read, compiled and executed by default in the \code{abcl-script-user} package, just like evaluated code. In contrast to evaluated code, though, due to the way the \textsc{ABCL} compiler works, compiled code contains no reference to top-level self-evaluating objects (like numbers or strings). Thus, when evaluated, a piece of compiled code will return the value of the last non-self-evaluating form: for example the code ``\code{(do-something) 42}'' will return 42 when interpreted, but will return the result of (do-something) when compiled and later evaluated. To ensure consistency of behavior between interpreted and compiled code, make sure the last form is always a compound form - at least \code{(identity some-literal-object)}. Note that this issue should not matter in real code, where it is unlikely that a top-level self-evaluating form will appear as the last form in a file (in fact, the Common Lisp load function always returns \code{t} upon success; with \textsc{JSR-223} this policy has been changed to make evaluation of small code snippets work as intended). \subsection{Invocation of functions and methods} AbclScriptEngine implements the \code{javax.script.Invocable} interface, which allows to directly call Lisp functions and methods, and to obtain Lisp implementations of Java interfaces. This is only partially possible with Lisp since it has functions, but not methods - not in the traditional Object Oriented sense, at least, since Lisp methods are not attached to objects but belong to generic functions. Thus, the method \code{invokeMethod()} is not implemented and throws an \texttt{UnsupportedOperationException} when called. The \code{invokeFunction()} method should be used to call both regular and generic functions. \subsection{Implementation of Java interfaces in Lisp} ABCL can use the Java reflection-based proxy feature to implement Java interfaces in Lisp. It has several built-in ways to implement an interface, and supports definition of new ones. The \code{JAVA:JMAKE-PROXY} generic function is used to make such proxies. It has the following signature: \code{jmake-proxy interface implementation \&optional lisp-this ==> proxy} \code{interface} is a Java interface metaobject (e.g. obtained by invoking \code{jclass}) or a string naming a Java interface. \code{implementation} is the object used to implement the interface - several built-in methods of jmake-proxy exist for various types of implementations. \code{lisp-this} is an object passed to the closures implementing the Lisp "methods" of the interface, and defaults to \code{NIL}. The returned proxy is an instance of the interface, with methods implemented with Lisp functions. Built-in interface-implementation types include: \begin{itemize} \item a single Lisp function which, upon invocation of any method in the interface, will be passed the method name, the Lisp-this object, and all the parameters. Useful for interfaces with a single method, or to implement custom interface-implementation strategies. \item a hash-map of method-name $\rightarrow$ Lisp function mappings. Function signature is \code{(lisp-this \&rest args)}. \item a Lisp package. The name of the Java method to invoke is first transformed in an idiomatic Lisp name (\code{javaMethodName} becomes \code{JAVA-METHOD-NAME}) and a symbol with that name is searched in the package. If it exists and is \code{FBOUND}, the corresponding function will be called. Function signature is as the hash-table case. \end{itemize} This functionality is exposed by the class \code{AbclScriptEngine} via the two methods \code{getInterface(Class)} and \code{getInterface(Object, Class)}. The former returns an interface implemented with the current Lisp package, the latter allows the programmer to pass an interface-implementation object which will in turn be passed to the \code{jmake-proxy} generic function. \section{Implementation Extension Dictionaries} As outlined by the \textsc{CLHS} \textsc{ANSI} conformance guidelines, we document the extensions to the Armed Bear Common Lisp implementation made accessible to the user by virtue of being an exported symbol in the \code{java}, \code{threads}, or \code{extensions} packages. Additional, higher-level information about the extensions afforded by the implementation can be found in \ref{chapter:beyond-ansi} on page \pageref{chapter:beyond-ansi}. \subsection{The JAVA Dictionary} The symbols exported from the the \code{JAVA} package constitute the primary mechanism to interact with Java language constructs within the hosting virtual machine. \subsubsection{Modifying the JVM CLASSPATH} The \code{JAVA:ADD-TO-CLASSPATH} generic functions allows one to add the specified pathname or list of pathnames to the current classpath used by \textsc{ABCL}, allowing the dynamic loading of \textsc{JVM} objects: \begin{listing-lisp} CL-USER> (add-to-classpath "/path/to/some.jar") \end{listing-lisp} N.b \code{ADD-TO-CLASSPATH} only affects the classloader used by \textsc{ABCL} (the value of the special variable \code{JAVA:*CLASSLOADER*}. It has no effect on \textsc{Java} code outside \textsc{ABCL}. \subsubsection{Creating a synthetic Java Class at Runtime} For details on the mechanism available to create a fully synthetic Java class at runtime can be found in \code{JAVA:JNEW-RUNTIME-CLASS} on \ref{JAVA:JNEW-RUNTIME-CLASS}. % include autogen docs for the JAVA package. \include{java} \subsection{The THREADS Dictionary} The extensions for handling multi-threaded execution are collected in the \code{THREADS} package. Most of the abstractions in Doug Lea's excellent \code{java.util.concurrent} packages may be manipulated directly via the JSS contrib to great effect \cite{lea-1998} % include autogen docs for the THREADS package. \include{threads} \subsection{The EXTENSIONS Dictionary} The symbols in the \code{extensions} package (often referenced by its shorter nickname \code{ext}) constitutes extensions to the \textsc{ANSI} standard that are potentially useful to the user. They include functions for manipulating network sockets, running external programs, registering object finalizers, constructing reference weakly held by the garbage collector and others. See \cite{RHODES2007} for a generic function interface to the native \textsc{JVM} contract for \code{java.util.List}. % include autogen docs for the EXTENSIONS package. \include{extensions} \chapter{Beyond ANSI} \label{chapter:beyond-ansi} Naturally, in striving to be a useful contemporary \textsc{Common Lisp} implementation, \textsc{ABCL} endeavors to include extensions beyond the ANSI specification which are either widely adopted or are especially useful in working with the hosting \textsc{JVM}. This chapter documents such extensions beyond ANSI conformation. \section{Compiler to Java Virtual Machine Bytecode} The \code{CL:COMPILE-FILE} interface emits a packed fasl \footnote{The term ``fasl'' is short for ``fast loader'', which in \textsc{Common Lisp} implementations refers} format whose \code{CL:PATHNAME} has the \code{TYPE} ``abcl''. Structurally, \textsc{ABCL}'s fasls are operating system neutral byte archives packaged in the zip compression format which contain artifacts whose loading \code{CL:LOAD} understands. Internally, our fasls contain a piece of Lisp that \code{CL:LOAD} interprets as instructions to load the Java classes emitted by the \textsc{ABCL} Lisp compiler. The classes emitted by the \textsc{ABCL} compiler have a JVM class file version of ``49.0''. % TODO check on what the compiler is currently emitting \subsection{Compiler Diagnostics} By default, the interface to the compiler does not signal warnings that result in its invocation, outputing diagnostics to the standard reporting stream. The generalized boolean \code{JVM:*RESIGNAL-COMPILER-WARNINGS*} provides the interface to enabling the compiler to signal all warnings. \subsection{Decompilation} \label{CL:DISASSEMBLE} Since \textsc{ABCL} compiles to JVM bytecode, the \code{CL:DISASSEMBLE} function provides introspection for the result of that compilation. By default the implementation attempts to find and use the \code{javap} command line tool shipped as part of the Java Development Kit to disassemble the results. Code for the use of additional JVM bytecode introspection tools is packaged as part of the ABCL-INTROSPECT contrib. After loading one of these tools via ASDF, the \code{SYS:CHOOSE-DISASSEMBLER} function can be used to select the tool used by \code{CL:DISASSEMBLE}. See \ref{abcl-introspect-disassemblers} on \pageref{abcl-introspect-disassemblers} for further details. \section{Pathname} \index{PATHNAME} \textsc{ABCL} extends its implementation of \textsc{ANSI} \code{PATHNAME} objects in order to allow read-only access to sources of bytes available via URIs \footnote{A \textsc{URI} is essentially a super-set of what is commonly understood as a \textsc{URL}. We sometimes use the term URL as shorthand in describing the URL Pathnames, even though the corresponding encoding is more akin to a URI as described in RFC3986 \cite{rfc3986}.} and to enable the addressing of arbitrarily recursive entries within \textsc{ZIP} archives. These implementation decisions are encapsulated by the specialization of \code{CL:PATHNAME} as the \code{EXT:URL-PATHNAME} and the \code{EXT:JAR-PATHNAME} types. % RDF description of type hierarchy % TODO Render via some LaTeX mode for graphviz? \begin{verbatim} @prefix rdfs: . @prefix ext: . @prefix cl: . rdfs:subClassOf . rdfs:subClassOf . rdfs:subClassOf . \end{verbatim} The \code{EXT:URL-PATHAME} object utilizes the standard \textsc{JVM} implementation of \code{java.net.URL} to access resources named by the ``file'', ``http'', ``https'', ``jar'', and ``ftp'' schemes. Additional protocol handlers for other may be installed at runtime by having \textsc{JVM} symbols present in the \code{sun.net.protocol.dynamic}\footnote{See \cite{maso2000} for more details. \url{https://stackoverflow.com/questions/41784555/print-all-supported-url-schemes-in-java8} contains a more up-to-date description.} The namestring of a \code{EXT:URL-PATHNAME} object is equivalent to the string serialization of its representation encoded via the ``percent encoding'' rules of URIs\footnote{See \url{https://url.spec.whatwg.org/\#percent-encoded-bytes} for a description of this process.}. The \code{EXT:JAR-PATHNAME} extension utilizes the specialization of \code{EXT:URL-PATHNAME} to provide access to components of \textsc{ZIP} archives, of which the \textsc{JAR} (Java ARchive) format is a super-set. \footnote{JAR archive utilize the ZIP format for packing and compression adding procedures to add supporting metadata in a manifest which is standardized text file stored at a canonical location within the archive.} \textsc{JAR} archives are typically used to aggregate many Java class files and associated metadata and resources (text, images, etc.) into one file for distribution. \textsc{ABCL} is typically packaged as a \textsc{JAR} archive and emits its fasls as \textsc{ZIP} files. Both the \code{EXT:URL-PATHNAME} and \code{EXT:JAR-PATHNAME} specializations may be broadly used anywhere a \code{CL:PATHNAME} is accepted with the general caveat that stream obtained via \code{CL:OPEN} on either sub-type cannot be the target of write operations. \subsubsection{URL-PATHNAME} \label{EXTENSIONS:URL-PATHNAME} \index{URL-PATHNAME} A \code{URL-PATHNAME} denotes a source of bytes addressable by its corresponding namestring interpreted as a \textsc{URI}. A \code{EXT:URL-PATHNAME} always has a \code{HOST} component that is a property list. The values of the \code{HOST} property list are always character strings. The allowed keys have the following meanings: \begin{description} \item[:SCHEME] Scheme of URI ("http", "ftp", "bundle", etc.) \item[:AUTHORITY] Valid authority according to the URI scheme. For "http" this could be "example.org:8080". \item[:QUERY] The query of the \textsc{URI} \item[:FRAGMENT] The fragment portion of the \textsc{URI} \end{description} If the \textsc{:SCHEME} property is missing, it is assumed to be ``file'' denoting a reference to a file on the local file-system and will be normalized as such in any pathname subjected to \code{TRUENAME} resolution. In order to encapsulate the implementation decisions for these meanings, the following functions provide a SETF-able API for reading and writing such values: \code{URL-PATHNAME-QUERY}, \code{URL-PATHNAME-FRAGMENT}, \code{URL-PATHNAME-AUTHORITY}, and \code{URL-PATHNAME-SCHEME}. The specific sub-type of a Pathname may be determined with the predicates \code{PATHNAME-URL-P} and \code{PATHNAME-JAR-P}. \label{EXTENSIONS:URL-PATHNAME-SCHEME} \index{URL-PATHNAME-SCHEME} \label{EXTENSIONS:URL-PATHNAME-FRAGMENT} \index{URL-PATHNAME-FRAGMENT} \label{EXTENSIONS:URL-PATHNAME-AUTHORITY} \index{URL-PATHNAME-AUTHORITY} \label{EXTENSIONS:PATHNAME-URL-P} \index{PATHNAME-URL-P} \label{EXTENSIONS:URL-PATHNAME-QUERY} \index{URL-PATHNAME-QUERY} Any results of canonicalization procedures performed on a object of type \code{EXT:URL-PATHNAME} via local or network resolutions discarded between attempts (i.e. the implementation does not attempt to cache the results of current name resolution of the URI for underlying resource unless it is requested to be resolved.) Upon resolution, any canonicalization procedures followed in resolving the resource (e.g. following redirects) are discarded. Users may programatically initiate a new, local computation of the resolution of the resource by applying the \code{CL:TRUENAME} function to a \code{EXT:URL-PATHNAME} object. Depending on the reliability and properties of your local \textsc{REST} infrastructure, these results may not necessarily be idempotent over time\footnote {See \cite{uri-pathname} for the design and implementation notes for the technical details}. A future implementation may attempt to expose an API to observer/customize the content negotiation initiated during retrieval of the representation of a given resource, which is currently handled at the application level. The implementation of \code{EXT:URL-PATHNAME} allows the \textsc{ABCL} user to dynamically load code from the network. For example, \textsc{Quicklisp} (\cite{quicklisp}) may be completely installed from the \textsc{REPL} to download and execute the Quicklisp setup code via: \begin{listing-lisp} CL-USER> (load "https://beta.quicklisp.org/quicklisp.lisp") \end{listing-lisp} \label{section:jar-pathname} \subsubsection{JAR-PATHNAME} \label{section:JAR-PATHNAME} \index{JAR-PATHNAME} In \textsc{ABCL}, the \code{DEVICE} can be either a string either denoting a drive letter or a UNC mount under \textsc{DOS} or a list of one or more elements. If \code{DEVICE} is a list, it denotes a \code{EXT:JAR-PATHNAME}. The implementation extends the \textsc{ANSI} specification with \textsc{EXT:JAR-PATHNAME} by utilizing its \code{DEVICE} to contain a list of pathnames denoting the location of and relative address within a \textsc{ZIP} archive. The first member of this list will be a \code{EXT:URL-PATHNAME} designates the root source of bytes encoded via the \textsc{ZIP} compression algorithm. This reference can either be to a file located on the local file-system or as a remote source via an stream-oriented messaging protocol such as \textsc{https}. The remainder of the \code{DEVICE} list contains ``traditional'' \code{CL:PATHNAME} objects denoting successive relative archive paths. This allows pathnames to reference an entry in an arbitrarily nested ZIP archives, which is the case when the an ABCL fasl is included in in a jar archive. In order to implement useful behavior of merging with pathname defaults, the implementation will contain the \code{:UNSPECIFIC} keyword in any TRUENAME that wasn't explicitly merging with a \code{EXT:JAR-PATHNAME}. Therefore, the implementation extends the semantics for the usual merge semantics when \code{*DEFAULT-PATHNAME-DEFAULTS*} contains a \code{EXT:JAR-PATHNAME} with the ``do what I mean'' algorithm described in \ref{section:conformance} on page \pageref{section:conformance}. The namestring representation of \code{EXT:JAR-PATHNAME} references use successive ``jar'' prefixes and corresponding ``!'' suffixes to encapsulate successive locations. Described broadly, a \code{EXT:JAR-PATHNAME} encapsulates the \textsc{URL} describing the location of the archive and a possible entry within that archive. \begin{verbatim} jar:!/[] \end{verbatim} The \textsc{URL} usually has the ``file'' scheme, but remote locations expressed in the ``https'' or ``http'' are also allowed. Subsequent entries within an archive are denoted via prefixing additional ``jar'' schemes and suffixing the associated path. \begin{verbatim} jar:jar:!/!/[] jar:jar:jar:!/!/!/[] \end{verbatim} \section{Package-Local Nicknames} \label{section:package-local-nicknames} ABCL allows giving packages local nicknames which allow short and easy-to-use names to be used without fear of name conflict associated with normal nicknames.\footnote{Package-local nicknames were originally developed in SBCL.} A local nickname is valid only when inside the package for which it has been specified. Different packages can use same local nickname for different global names, or different local nickname for same global name. Symbol \code{:package-local-nicknames} in \code{*features*} denotes the support for this feature. \index{DEFPACKAGE} The options to \code{defpackage} are extended with a new option \code{:local-nicknames (local-nickname actual-package-name)*}. The new package has the specified local nicknames for the corresponding actual packages. Example: \begin{listing-lisp} (defpackage :bar (:intern "X")) (defpackage :foo (:intern "X")) (defpackage :quux (:use :cl) (:local-nicknames (:bar :foo) (:foo :bar))) (find-symbol "X" :foo) ; => FOO::X (find-symbol "X" :bar) ; => BAR::X (let ((*package* (find-package :quux))) (find-symbol "X" :foo)) ; => BAR::X (let ((*package* (find-package :quux))) (find-symbol "X" :bar)) ; => FOO::X \end{listing-lisp} \index{PACKAGE-LOCAL-NICKNAMES} --- Function: \textbf{package-local-nicknames} [\textbf{ext}] \textit{package-designator} \begin{adjustwidth}{5em}{5em} Returns an ALIST of \code{(local-nickname . actual-package)} describing the nicknames local to the designated package. When in the designated package, calls to \code{find-package} with any of the local-nicknames will return the corresponding actual-package instead. This also affects all implied calls to \code{find-package}, including those performed by the reader. When printing a package prefix for a symbol with a package local nickname, the local nickname is used instead of the real name in order to preserve print-read consistency. \end{adjustwidth} \index{PACKAGE-LOCALLY-NICKNAMED-BY-LIST} --- Function: \textbf{package-locally-nicknamed-by-list} [\textbf{ext}] \textit{package-designator} \begin{adjustwidth}{5em}{5em} Returns a list of packages which have a local nickname for the designated package. \end{adjustwidth} \index{ADD-PACKAGE-LOCAL-NICKNAME} --- Function: \textbf{add-package-local-nickname} [\textbf{ext}] \textit{local-nickname actual-package \&optional package-designator} \begin{adjustwidth}{5em}{5em} Adds \code{local-nickname} for \code{actual-package} in the designated package, defaulting to current package. \code{local-nickname} must be a string designator, and \code{actual-package} must be a package designator. Returns the designated package. Signals an error if \code{local-nickname} is already a package local nickname for a different package, or if \code{local-nickname} is one of "CL", "COMMON-LISP", or, "KEYWORD", or if \code{local-nickname} is a global name or nickname for the package to which the nickname would be added. When in the designated package, calls to \code{find-package} with the \code{local-nickname} will return the package the designated \code{actual-package} instead. This also affects all implied calls to \code{find-package}, including those performed by the reader. When printing a package prefix for a symbol with a package local nickname, local nickname is used instead of the real name in order to preserve print-read consistency. \end{adjustwidth} \index{REMOVE-PACKAGE-LOCAL-NICKNAME} --- Function: \textbf{remove-package-local-nickname} [\textbf{ext}] \textit{old-nickname \&optional package-designator} \begin{adjustwidth}{5em}{5em} If the designated package had \code{old-nickname} as a local nickname for another package, it is removed. Returns true if the nickname existed and was removed, and \code{nil} otherwise. \end{adjustwidth} \section{Extensible Sequences} The SEQUENCE package fully implements Christopher Rhodes' proposal for extensible sequences. These user extensible sequences are used directly in \code{java-collections.lisp} provide these CLOS abstractions on the standard Java collection classes as defined by the \code{java.util.List} contract. %% an Example of using java.util.Lisp in Lisp would be nice This extension is not automatically loaded by the implementation. It may be loaded via: \begin{listing-lisp} CL-USER> (require :java-collections) \end{listing-lisp} if both extensible sequences and their application to Java collections is required, or \begin{listing-lisp} CL-USER> (require :extensible-sequences) \end{listing-lisp} if only the extensible sequences API as specified in \cite{RHODES2007} is required. Note that \code{(require :java-collections)} must be issued before \code{java.util.List} or any subclass is used as a specializer in a \textsc{CLOS} method definition (see the section below). See Rhodes2007 \cite{RHODES2007} for the an overview of the abstractions of the \code{java.util.collection} package afforded by \code{JAVA-COLLECTIONS}. \section{Extensions to CLOS} \subsection{Metaobject Protocol} \textsc{ABCL} implements the metaobject protocol for \textsc{CLOS} as specified in \textsc{(A)MOP}. The symbols are exported from the package \code{MOP}. Contrary to the AMOP specification and following \textsc{SBCL}'s lead, the metaclass \code{funcallable-standard-object} has \code{funcallable-standard-class} as metaclass instead of \code{standard-class}. \textsc{ABCL}'s fidelity to the AMOP specification is codified as part of Pascal Costanza's \code{closer-mop} \ref{closer-mop} \cite{closer-mop}. \subsection{Specializing on Java classes} There is an additional syntax for specializing the parameter of a generic function on a java class, viz. \code{(java:jclass CLASS-STRING)} where \code{CLASS-STRING} is a string naming a Java class in dotted package form. For instance the following specialization would perhaps allow one to print more information about the contents of a \code{java.util.Collection} object \begin{listing-lisp} (defmethod print-object ((coll (java:jclass "java.util.Collection")) stream) ;;; ... ) \end{listing-lisp} If the class had been loaded via a classloader other than the original the class you wish to specialize on, one needs to specify the classloader as an optional third argument. \begin{listing-lisp} (defparameter *other-classloader* (jcall "getBaseLoader" cl-user::*classpath-manager*)) (defmethod print-object ((device-id (java:jclass "dto.nbi.service.hdm.alcatel.com.NBIDeviceID" *other-classloader*)) stream) ;;; ... ) \end{listing-lisp} \section{Extensions to the Reader} We implement a special hexadecimal escape sequence for specifying 32 bit characters to the Lisp reader\footnote{This represents a compromise with contemporary in 2011 32bit hosting architectures for which we wish to make text processing efficient. Should the User require more control over \textsc{UNICODE} processing we recommend Edi Weisz' excellent work with \textsc|{FLEXI-STREAMS} which we fully support}, namely we allow a sequences of the form \verb~#\U~\emph{\texttt{xxxx}} to be processed by the reader as character whose code is specified by the hexadecimal digits \emph{\texttt{xxxx}}. The hexadecimal sequence may be one to four digits long. % Why doesn't ALEXANDRIA work? Good question: Alexandria from % Quicklisp 2010-10-07 fails a number of tests: %% Form: (ALEXANDRIA.0.DEV:TYPE= 'LIST '(OR NULL CONS)) %% Expected values: T %% T %% Actual values: NIL %% T. %% Test ALEXANDRIA-TESTS::TYPE=.3 failed %% Form: (ALEXANDRIA.0.DEV:TYPE= 'NULL '(AND SYMBOL LIST)) %% Expected values: T %% T %% Actual values: NIL %% NIL. Note that that the reader escaped sequence is never output by the implementation. Instead, the implementation emits the bytes corresponding Unicode character is output for characters whose code is greater than \code{0x00ff}. \section{Overloading of the CL:REQUIRE Mechanism} The \code{CL:REQUIRE} mechanism is overloaded by attaching the following behavior to the execution of \code{REQUIRE} on these symbols: \begin{description}[style=nextline] \item[\code{ASDF}] Loads the \textsc{ASDF} version shipped with the implementation. After the evaluation of this symbols, symbols passed to \code{CL:REQUIRE} which are otherwise unresolved, are passed to ASDF for a chance for resolution. This means, for instance if \code{CL-PPCRE} can be located as a loadable \textsc{ASDF} system \code{(require :cl-ppcre)} is equivalent to \code{(asdf:load-system :cl-ppcre)}. \item[\code{ABCL-CONTRIB}] Locates and pushes the top-level contents of ``abcl-contrib.jar'' into the \textsc{ASDF} central registry. \begin{description}[style=nextline] \item[\code{abcl-asdf}] Functions for loading \textsc{JVM} artifacts dynamically by extending \textsc{ASDF}. See \ref{section:abcl-asdf} on page \pageref{section:abcl-asdf}. \item[\code{asdf-jar}] Package addressable \textsc{JVM} artifacts via \code{abcl-asdf} descriptions as a single binary artifact including recursive dependencies. See \ref{sec:asdf-jar} on page \pageref{section:asdf-jar}. \item[\code{jna}] Allows the Java Native Interface (\textsc{JNI}) facility to provide C-style linkage to other operating system shared objects by dynamically loading the 'jna.jar' artifact via Maven\footnote{This loading can be inhibited if, at runtime, the Java class corresponding ``:classname'' clause of the system definition is present.} \item[\code{quicklisp-abcl}] Loads \textsc{Quicklisp} by possibly initiating a network download via \code{EXT:URL-PATHMAME}. \item[\code{jfli}] A descendant of Rich Hickey's pre-Clojure work on the JVM. \item[\code{jss}] Introduces dynamic inspection of present symbols via the \code{SHARPSIGN-QUOTATION\_MARK} macros as Java Syntax Sucks. See \ref{section:jss} on page \pageref{sections:jss} for more details. \item[\code{abcl-introspect}] Provides a framework for introspecting runtime Java and Lisp object values. Include packaging for installing and using java decompilation tools for use with \code{CL:DISASSEMBLE}. See \ref{section:abcl-introspect} on \pageref{section:abcl-introspect} for further information. \item[\code{abcl-build}] Provides a toolkit for building ABCL from source, as well as installing the necessary tools for such builds. See \ref{section:abcl-build} on page \pageref{section:abcl-build}. \item[\code{named-readtables}] Provides a namespace for readtables akin to the already-existing namespace of packages. See \ref{section:named-readtables} on \pageref{section:named-readtables} for further information. \end{description} \end{description} The user may extend the \code{CL:REQUIRE} mechanism by pushing function hooks into \code{SYSTEM:*MODULE-PROVIDER-FUNCTIONS*}. Each such hook function takes a single argument containing the symbol passed to \code{CL:REQUIRE} and returns a non-\code{NIL} value if it can successful resolve the symbol. \section{JSS extension of the Reader by SHARPSIGN-DOUBLE-QUOTE} The JSS contrib constitutes an additional, optional extension to the reader in the definition of the \code{SHARPSIGN-DOUBLE-QUOTE} (``\#\"'') reader macro. See section \ref{section:jss} on page \pageref{section:jss} for more information. \section{ASDF} asdf-3.3.5.7 (see \cite{asdf}) is packaged as core component of \textsc{ABCL}, but not loaded by default, as it relies on the \textsc{CLOS} subsystem which can take a bit of time to start \footnote{While this time is ``merely'' on the order of seconds for contemporary 2011 machines, for applications that need to initialize quickly, for example a web server, this time might be unnecessarily long}. The packaged \textsc{ASDF} may be loaded by the \textsc{ANSI} \code{REQUIRE} mechanism as follows: \begin{listing-lisp} CL-USER> (require :asdf) \end{listing-lisp} \section{Extension to CL:MAKE-ARRAY} \label{section:make-array} \index{MAKE-ARRAY} With the \code{:nio} feature is present\footnote{Available starting in the Eighth Edition (aka abcl-1.7.0) and indicated by the presence of \code{:nio} in \code{cl:*features*}}, the implementation adds two keyword arguments to \code{cl:make-array}, viz. \code{:nio-buffer} and \code{:nio-direct}. With the \code{:nio-buffer} keyword, the user is able to pass instances of of \code{java.nio.ByteBuffer} and its subclasses for the storage of vectors and arrays specialized on the byte-vector types satisfying \begin{listing-lisp} (or (unsigned-byte 8) (unsigned-byte 16) (unsigned-byte 32)) \end{listing-lisp} As an example, the following would use the \code{:nio-buffer} as follows to create a 16 byte vector using the created byte-buffer for storage: \begin{listing-lisp} (let* ((length 16) (byte-buffer (java:jstatic "allocate" "java.nio.ByteBuffer" length))) (make-array length :element-type '(unsigned-byte 8) :nio-buffer byte-buffer)) \end{listing-lisp} This feature is available in CFFI\footnote{Available at runtime via \textsc{Quicklisp}} via \code{CFFI-SYS:MAKE-SHAREABLE-BYTE-VECTOR}\footnote{Implemented in \url{https://github.com/cffi/cffi/commit/47136ad9a97c2df98dbcd13a068e14489ced5b03}} \begin{description}[style=nextline] \item[\code{:nio-buffer NIO-BUFFER}] Initializes the contents of the new vector or array with the contents of \code{NIO-BUFFER} which needs to be a reference to a \code{java-object} of class \code{java.nio.ByteBuffer}. \item[\code{:nio-direct NIO-DIRECT-P}] When \code{NIO-DIRECT-P} is non-\code{nil}, constructs a java.nio.Buffer as a ``direct'' buffer. The buffers returned by this method typically have somewhat higher allocation and deallocation costs than non-direct buffers. The contents of direct buffers may reside outside of the normal garbage-collected heap, and so their impact upon the memory footprint of an application might not be obvious. It is therefore recommended that direct buffers be allocated primarily for large, long-lived buffers that are subject to the underlying system's native I/O operations. In general it is best to allocate direct buffers only when they yield a measurable gain in program performance. \end{description} \chapter{Contrib} The \textsc{ABCL} contrib is packaged as a separate jar archive usually named \code{abcl-contrib.jar} or possibly something like \code{abcl-contrib-1.9.0.jar}. The contrib jar is not loaded by the implementation by default, and must be first initialized by the \code{REQUIRE} mechanism before using any specific contrib: \begin{listing-lisp} CL-USER> (require :abcl-contrib) \end{listing-lisp} \section{abcl-asdf} \label{section:abcl-asdf} \index{ABCL-ASDF} This contrib enables an additional syntax for \textsc{ASDF} system definition which dynamically loads \textsc{JVM} artifacts such as jar archives via encapsulation by the Maven build tool. The Maven Aether component can also be directly manipulated by the function associated with the \code{ABCL-ASDF:RESOLVE-DEPENDENCIES} symbol. %ABCL specific contributions to ASDF system definition mainly %concerned with finding JVM artifacts such as jar archives to be %dynamically loaded. When loaded, \textsc{ABCL-ASDF} adds the following objects to \textsc{ASDF}: \code{JAR-FILE}, \code{JAR-DIRECTORY}, \code{CLASS-FILE-DIRECTORY} and \code{MVN}, exporting them (and others) as public symbols. \subsection{Referencing Maven Artifacts via ASDF} Maven artifacts may be referenced within \textsc{ASDF} system definitions, as the following example references the \code{log4j-1.4.9.jar} JVM artifact which provides a widely-used abstraction for handling logging systems: \begin{listing-lisp} ;;;; -*- Mode: LISP -*- (require :asdf) (in-package :cl-user) (asdf:defsystem :log4j :defsystem-depends-on (abcl-asdf) :components ((:mvn "log4j/log4j" :version "1.4.9"))) \end{listing-lisp} \subsection{API} We define an API for \textsc{ABCL-ASDF} as consisting of the following \textsc{ASDF} classes: \code{JAR-DIRECTORY}, \code{JAR-FILE}, and \code{CLASS-FILE-DIRECTORY} for JVM artifacts that have a currently valid pathname representation. Both the \code{MVN} and \code{IRI} classes descend from \code{ASDF-COMPONENT}, but do not directly have a file-system location. For use outside of ASDF system definitions, we currently define one method, \code{ABCL-ASDF:RESOLVE-DEPENDENCIES} which locates, downloads, caches, and then loads into the currently executing JVM process all recursive dependencies annotated in the Maven pom.xml graph. \subsection{Directly Instructing Maven to Download JVM Artifacts} Bypassing \textsc{ASDF}, one can directly issue requests for the Maven artifacts to be downloaded \begin{listing-lisp} CL-USER> (abcl-asdf:resolve-dependencies "com.google.gwt" "gwt-user") WARNING: Using LATEST for unspecified version. "/Users/evenson/.m2/repository/com/google/gwt/gwt-user/2.9.0/gwt-user-2.9 .0.jar:/Users/evenson/.m2/repository/com/google/jsinterop/jsinterop-annot ations/2.0.0/jsinterop-annotations-2.0.0.jar:/Users/evenson/.m2/repositor y/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar:/U sers/evenson/.m2/repository/javax/validation/validation-api/1.0.0.GA/vali dation-api-1.0.0.GA-sources.jar:/Users/evenson/.m2/repository/javax/servl et/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar:/Users/evenson/.m2 /repository/org/w3c/css/sac/1.3/sac-1.3.jar" \end{listing-lisp} To actually load the dependency into the current process, use the \code{JAVA:ADD-TO-CLASSPATH} generic function: \begin{listing-lisp} CL-USER> (java:add-to-classpath (abcl-asdf:resolve-dependencies "com.google.gwt" "gwt-user")) \end{listing-lisp} Notice that all recursive dependencies have been located and installed locally from the network as well. More extensive documentations and examples can be found at \url{http://abcl.org/svn/tags/1.9.0/contrib/abcl-asdf/README.markdown}. \section{asdf-jar} \label{section:asdf-jar} \index{ASDF-JAR} The asdf-jar contrib provides a system for packaging \textsc{ASDF} systems into jar archives for \textsc{ABCL}. Given a running \textsc{ABCL} image with loadable \textsc{ASDF} systems the code in this package will recursively package all the required source and fasls in a jar archive. The documentation for this contrib can be found at \url{http://abcl.org/svn/tags/1.9.0/contrib/asdf-jar/README.markdown}. \section{jss} \label{section:jss} \index{JSS} To one used to the more universal syntax of s-expr pairs upon which the definition of read and compile time macros is quite natural \footnote{See Graham's ``On Lisp'' http://lib.store.yahoo.net/lib/paulgraham/onlisp.pdf.}, the syntax available to the \textsc{Java} programmer may be said to suck. To alleviate this situation, the \textsc{JSS} contrib introduces the \code{SHARPSIGN-DOUBLE-QUOTE} (\code{\#"}) reader macro, which allows the the specification of the name of invoking function as the first element of the relevant s-expr which tends to be more congruent to how Lisp programmers seem to be wired to think. While quite useful, we don't expect that the \textsc{JSS} contrib will be the last experiment in wrangling \textsc{Java} from \textsc{Common Lisp}. \subsection{JSS usage} An example of using \textsc{JSS} to enumerate the \textsc{Java} runtime system properties: \begin{listing-lisp} CL-USER> (require :abcl-contrib) ==> ("ABCL-CONTRIB") CL-USER> (require :jss) ==> ("JSS") CL-USER) (#"getProperties" 'java.lang.System) ==> # CL-USER) (#"propertyNames" (#"getProperties" 'java.lang.System)) ==> # \end{listing-lisp} %$ <-- un-confuse Emacs font-lock Some more information on jss can be found in its documentation at \url{http://abcl.org/svn/tags/1.9.0/contrib/jss/README.markdown} \section{jfli} \label{section:jfli} The contrib contains a pure-Java version of \textsc{JFLI}, apparently a descendant of Rich Hickey's early experimentations with using Java from Common Lisp. \url{http://abcl.org/svn/tags/1.9.0/contrib/jfli/README}. \section{abcl-introspect} \label{section:abcl-introspect} \index{ABCL-INTROSPECT} \textsc{ABCL-INTROSPECT} offers more extensive functionality for inspecting the state of the implementation, most notably in integration with \textsc{SLIME}, where the backtrace mechanism is augmented to the point that local variables are inspectable. A compiled function is an instance of a class, which has multiple instances if it represents a closure, or a single instance if it represents a non-closed-over function. The \textsc{ABCL} compiler stores constants that are used in function execution as private java fields. This includes symbols used to invoke function, locally-defined functions (such as via \code{LABEL} or \code{flet}) and string and other literal objects. \textsc{ABCL-INTROSPECT} implements a ``do what I mean'' API for introspecting these constants. \textsc{ABCL-INTROSPECT} provides access to those internal values, and uses them in at least two ways. First, to annotate locally defined functions with the top-level function they are defined within, and second to search for callers of a give function \footnote{ Since \textsc{Java} functions are strings, local fields also have these strings. In the context of looking for callers of a function you can also give a string that names a java method. Same caveat re: false positives.} . This may yield some false positives, such as when a symbol that names a function is also used for some other purpose. It can also have false negatives, as when a function is inlined. Still, it's pretty useful. The second use to to find source locations for frames in the debugger. If the source location for a local function is asked for the location of its 'owner' is instead returns. In order to record information about local functions, \textsc{ABCL} defines a function-plist, which is for the most part unused, but is used here with set of keys indicating where the local function was defined and in what manner, i.e. as normal local function, as a method function, or as an initarg function. There may be other places functions are stashed away (defstructs come to mind) and this file should be added to to take them into account as they are discovered. \textsc{ABCL-INTROSPECT} does not depend on \textsc{JSS}, but provides a bit of jss-specific functionality if \textsc{JSS} *is* loaded. \subsection{Implementations for CL:DISASSEMBLE} \label{abcl-introspect-disassemblers} \index{CL:DISASSEMBLE} The following \textsc{ASDF} systems packages various external tools that may be selected by the \code{SYS:CHOOSE-DISASSEMBLER} interface: \begin{enumerate} \item \code{objectweb} \item \code{jad} \item \code{javap} \item \code{fernweb} \item \code{cfr} \item \code{procyon} \end{enumerate} To use one of these tools, first load the system via \textsc{ASDF} (and/or \textsc{Quicklisp}), then use the \code{SYS:CHOOSE-DISASSEMBLER} function to select the keyword that appears in \code{SYS:*DISASSEMBLERS*}. \begin{listing-lisp} CL-USER> (require :abcl-contrib)(asdf:load-system :objectweb) CL-USER> sys:*disassemblers* ((:OBJECTWEB . ABCL-INTROSPECT/JVM/TOOLS/OBJECTWEB:DISASSEMBLE-CLASS-BYTES) (:SYSTEM-JAVAP . SYSTEM:DISASSEMBLE-CLASS-BYTES)) CL-USER> (sys:choose-disassembler :objectweb) ABCL-INTROSPECT/JVM/TOOLS/OBJECTWEB:DISASSEMBLE-CLASS-BYTES CL-USER> (disassemble 'cons) ; // class version 52.0 (52) ; // access flags 0x30 ; final class org/armedbear/lisp/Primitives$pf_cons extends org/armedbear/lisp/Primitive { ; ; // access flags 0x1A ; private final static INNERCLASS org/armedbear/lisp/Primitives$pf_cons org/armedbear/lisp/Primitives pf_cons ; ; // access flags 0x0 ; ()V ; ALOAD 0 ; GETSTATIC org/armedbear/lisp/Symbol.CONS : Lorg/armedbear/lisp/Symbol; ; LDC "object-1 object-2" ; INVOKESPECIAL org/armedbear/lisp/Primitive. (Lorg/armedbear/lisp/Symbol;Ljava/lang/String;)V ; RETURN ; MAXSTACK = 3 ; MAXLOCALS = 1 ; ; // access flags 0x1 ; public execute(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject; ; NEW org/armedbear/lisp/Cons ; DUP ; ALOAD 1 ; ALOAD 2 ; INVOKESPECIAL org/armedbear/lisp/Cons. (Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)V ; ARETURN ; MAXSTACK = 4 ; MAXLOCALS = 3 ; } NIL \end{listing-lisp} \url{http://abcl.org/svn/tags/1.9.0/contrib/abcl-introspect/}. \section{abcl-build} \label{section:abcl-build} \index{ABCL-BUILD} \textsc{ABCL-BUILD} constitutes a new implementation for the original Lisp-hosted \textsc{ABCL} build system API in the package \code{ABCL-BUILD} that uses the same build artifacts as all of the other current builds. \subsection{ABCL-BUILD Utilities} \textsc{ABCL-BUILD} consolidates various utilities that are useful for system construction, namely \begin{itemize} \item The ability to introspect the invocation of given executable in the current implementation process PATH. \item Downloading and unpackaging selected JVM artifacts, namely the Ant and Maven build tools. The \code{ABCL-BUILD:WITH-ANT} and \code{ABCL-BUILD:WITH-MVN} macros abstracts this installation procedure conveniently away from the User. \item The beginnings of a generic framework to download arbitrary archives from the network. \end{itemize} \url{http://abcl.org/svn/tags/1.9.0/contrib/abcl-build/}. \section{named-readtables} \label{section:named-readtables} \index{NAMED-READTABLES} \code{NAMED-READTABLES} is a library that provides a namespace for readtables akin to the already-existing namespace of packages. This contrib was included from the source available from \url{https://github.com/melisgl/named-readtables/}. See \url{http://abcl.org/svn/tags/1.9.0/contrib/named-readtables/} for more information. \chapter{History} \index{History} \textsc{ABCL} was originally the extension language for the J editor, which was started in 1998 by Peter Graves. Sometime in 2003, a whole lot of code that had previously not been released publicly was suddenly committed that enabled ABCL to be plausibly termed an emergent ANSI Common Lisp implementation candidate. From 2006 to 2008, Peter manned the development lists, incorporating patches as made sense. After a suitable search, Peter nominated Erik H\"{u}lsmann to take over the project. In 2008, the implementation was transferred to the current maintainers, who have striven to improve its usability as a contemporary Common Lisp implementation. On October 22, 2011, with the publication of this Manual explicitly stating the conformance of Armed Bear Common Lisp to \textsc{ANSI}, we released abcl-1.0.0. We released abcl-1.0.1 as a maintenance release on January 10, 2012. In December 2012, we revised the implementation by adding \textsc{(A)MOP} with the release of abcl-1.1.0. We released abcl-1.1.1 as a maintenance release on February 14, 2013. At the beginning of June 2013, we enhanced the stability of the implementation with the release of abcl-1.2.1. In March 2014, we introduced the Fourth Edition of the implementation with abcl-1.3.0. At the end of April 2014, we released abcl-1.3.1 as a maintenance release. In October 2016 we blessed the current \textsc{svn} trunk \url{http://abcl.org/svn/trunk/} as 1.4.0, which includes the community contributions from Vihbu, Olof, Pipping, and Cyrus. We gingerly stepped into current century by establishing \textsc{git} bridges to the source repositories available via the URIs \url{https://github.com/armedbear/abcl/} and \url{https://gitlab.common-lisp.net/abcl/abcl/} so that pull requests for enhancements to the implementation many be more easily facilitated. In June 2017, we released ABCL 1.5.0 which dropped support for running upon Java 5. Against the falling canvas of 2019 we released ABCL 1.6.0 which provided compatibility with Java 11 while skipping Java 9 and 10. In April 2020, we offered abcl-1.6.1 as a maintenance release for usage around ELS2020. With the overhaul the implementation of arrays specialized on \code{(or (unsigned-byte 8) (unsigned-byte 16) (unsigned-byte 32))} to using \code{java.nio.Buffer} objects, we deemed the implementation worthy to bless with release as abcl-1.7.0 in June 2020. We released abcl-1.7.1 as a maintenance release in July 2020. We released abcl-1.8.0 under the darkening storms of October 2020. Halfway through the $\pi$ $\alpha$ $\nu$ $\delta$ $\eta$ $\mu$ o $\zeta$ \cite{pandemos}, we dyslexic worker bears untied abcl-1.9.0 into the future. \appendix \chapter{The MOP Dictionary} \include{mop} \chapter{The SYSTEM Dictionary} The public interfaces in this package are subject to change with \textsc{ABCL} 1.9 \include{system} \chapter{The JSS Dictionary} These public interfaces are provided by the JSS contrib. \include{jss} \bibliography{abcl} \bibliographystyle{alpha} \printindex \end{document} abcl-src-1.9.0/doc/manual/abcl.texi0100644 0000000 0000000 00000174577 14202767264 015613 0ustar000000000 0000000 \input texinfo @setfilename abcl.info @settitle Armed Bear Common Lisp User Manual @afourpaper @set EDITION 1.1.0 @c Editing Hints @c @c Use emacs. Use M-x texinfo-all-menus-update to update menus. @c Some index prettification helper macros, for tricking the texindex @c collation "engine" (from sbcl's manual) @macro earmuffs{name} *\name\* @end macro @macro setf{name} (setf \name\) @end macro @c for install-info @dircategory Software development @direntry * abcl: (abcl). Armed Bear Common Lisp @end direntry @copying @quotation This manual is part of ABCL. ABCL is licensed under the terms of the GPL v2 of June 1991 with the ``classpath-exception'' (see the file @file{COPYING} in the source distribution for the license, term 13 in the same file for the classpath exception). This license broadly means that you must distribute the sources to ABCL, including any changes you make, together with a program that includes ABCL, but that you are not required to distribute the sources of the whole program. Submitting your changes upstream to the ABCL development team is actively encouraged and very much appreciated, of course. @end quotation @end copying @titlepage @title Armed Bear Common Lisp User Manual @subtitle Version 1.1.0 @subtitle December 5, 2012 @author Mark Evenson @author Erik H@"ulsmann @author Rudolf Schlatte @author Alessio Stalla @author Ville Voutilainen @page @vskip 0pt plus 1filll @insertcopying @end titlepage @ifnottex @node Top @top abcl @menu * Introduction:: * Running ABCL:: * Interaction with Java:: * Implementation Dependent Extensions:: * Beyond ANSI:: * Contrib:: * History:: * Concept Index:: * Function Index:: * Variable Index:: * Type Index:: * Colophon:: @end menu @end ifnottex @contents @node Introduction @chapter Introduction Armed Bear Common Lisp (ABCL) is an implementation of Common Lisp that runs on the Java Virtual Machine. It compiles Common Lisp to Java 5 bytecode, providing the following integration methods for interfacing with Java code and libraries: @itemize @item Lisp code can create Java objects and call their methods. @xref{Calling from Lisp to Java}. @item Java code can call Lisp functions and generic functions, either directly (@pxref{Calling from Java to Lisp}) or via @t{JSR-223} (@pxref{Java Scripting API (JSR-223)}). @item @code{jinterface-implementation} creates Lisp-side implementations of Java interfaces that can be used as listeners for Swing classes and similar. @end itemize ABCL is supported by the Lisp library manager QuickLisp (@url{http://quicklisp.org/}) and can run many of the programs and libraries provided therein out-of-the-box. @menu * Conformance:: * Contributors:: @end menu @node Conformance @section Conformance ABCL aims to be be a fully conforming ANSI Common Lisp implementation. Any other behavior should be reported as a bug. ABCL is currently a (non)-conforming ANSI Common Lisp implementation due to the following known issues: @itemize @item The generic function signatures of the @code{DOCUMENTATION} symbol do not match the specification. @item The @code{TIME} form does not return a proper @code{VALUES} environment to its caller. @item When merging pathnames and the defaults point to a @code{JAR-PATHNAME}, we set the @code{DEVICE} of the result to @code{:UNSPECIFIC} if the pathname to be be merged does not contain a specified @code{DEVICE}, does not contain a specified @code{HOST}, does contain a relative @code{DIRECTORY}, and we are not running on a MSFT Windows platform.@footnote{The intent of this rather arcane sounding deviation from conformance is so that the result of a merge won't fill in a @code{DEVICE} with the wrong "default device for the host" in the sense of the fourth paragraph in the CLHS description of @code{MERGE-PATHNAMES} (see the paragraph beginning "If the @code{PATHNAME} explicitly specifies a host and not a device@dots{}"). A future version of the implementation may return to conformance by using the @code{HOST} value to reflect the type explicitly.} @end itemize Somewhat confusingly, this statement of non-conformance in the accompanying user documentation fulfills the requirements that ABCL is a conforming ANSI Common Lisp implementation according to the Common Lisp HyperSpec. Clarifications to this point are solicited. @menu * Contemporary Common Lisp:: @end menu @node Contemporary Common Lisp @subsection Contemporary Common Lisp In addition to ANSI conformance, ABCL strives to implement features expected of a contemporary Common Lisp, i.e. a Lisp of the post-2005 Renaissance. The following known problems detract from ABCL being a proper contemporary Common Lisp. @itemize @item An incomplete implementation of interactive debugging mechanisms, namely a no-op version of @code{STEP}, no support for inspecting local variables in a given call frame, and no support for resuming a halted computation at an arbitrarily selected call frame. @item Incomplete streams abstraction, in that ABCL needs suitable abstraction between ANSI and Gray streams. The streams could be optimized to the JVM NIO abstractions at great profit for binary byte-level manipulations. @item Incomplete documentation (missing docstrings from exported symbols and the draft status of this user manual). @end itemize @node Contributors @section Contributors @itemize @item Philipp Marek (Thanks for the markup) @item Douglas Miles (Thanks for the whacky IKVM stuff and for keeping the flame alive in the dark years) @item Alan Ruttenberg (Thanks for JSS) @item and of course @emph{Peter Graves} @end itemize @node Running ABCL @chapter Running ABCL ABCL is packaged as a single jar file usually named either @file{abcl.jar} or possibly something like @file{abcl-1.1.0.jar} if using a versioned package on the local filesystem from your system vendor. This jar file can be executed from the command line to obtain a REPL@footnote{Read-Eval Print Loop, a Lisp command-line}, viz: @example cmd$ java -jar abcl.jar @end example @emph{N.b.} for the proceeding command to work, the @code{java} executable needs to be in your path. To facilitate the use of ABCL in tool chains such as SLIME, the Superior Lisp Interaction Mode for Emacs, we provide both a Bourne shell script and a @code{DOS} batch file. If you or your administrator adjusted the path properly, ABCL may be executed simply as: @example cmd$ abcl @end example Probably the easiest way of setting up an editing environment using the Emacs editor is to use QuickLisp and follow the instructions at @url{http://www.quicklisp.org/beta/#slime}. @menu * Options:: * Initialization:: @end menu @node Options @section Options ABCL supports the following command line options: @table @option @item --help displays a help message. @item --noinform Suppresses the printing of startup information and banner. @item --noinit suppresses the loading of the @file{~/.abclrc} startup file. @item --nosystem suppresses loading the @file{system.lisp} customization file. @item --eval FORM evaluates @var{FORM} before initializing the REPL. @item --load FILE loads the file @var{FILE} before initializing the REPL. @item --load-system-file FILE loads the system file @var{FILE} before initializing the REPL. @item --batch evaluates forms specified by arguments and in the initialization file @file{~/.abclrc}, and then exits without starting a REPL. @end table All other command line arguments, as well as all arguments following the occurrence of a double hyphen (@option{--}) are passed unprocessed into a list of strings accessible via the variable @var{ext:*command-line-argument-list*} from within ABCL. @defvar @earmuffs{command-line-argument-list} This variable contains a (possibly empty) list of command-line arguments. Any arguments that were processed already (e.g., @option{--load FILE}) are removed from this list. @end defvar @node Initialization @section Initialization If the ABCL process is started without the @samp{--noinit} flag, it attempts to load a file named @file{.abclrc} in the user's home directory and then interpret its contents. The user's home directory is determined by the value of the JVM system property @code{user.home}. This value may or may not correspond to the value of the @env{HOME} system environment variable, at the discretion of the JVM implementation that ABCL finds itself hosted upon. @node Interaction with Java @chapter Interaction with Java ABCL is a Common Lisp implementation hosted on a Java Virtual Machine. This chapter describes the mechanisms by which the implementation interacts with that hosting mechanism. This interactions can go in two directions: Lisp-to-Java and Java-to-Lisp. @menu * Calling from Lisp to Java:: * Calling from Java to Lisp:: * Java Scripting API (JSR-223):: @end menu @node Calling from Lisp to Java @section Calling from Lisp to Java ABCL offers a number of mechanisms to interact with Java from its Lisp environment. It allows calling both instance and static methods of Java objects, manipulation of instance and static fields on Java objects, and construction of new Java objects. When calling Java routines, some values are automatically converted from Lisp values to Java values. These conversions apply to strings, integers and floats. Other values need to be converted to their Java equivalents by the programmer before calling the Java object method. Java values returned to Lisp are also converted back to their Lisp counterparts. If this conversion is not desired, certain Lisp-to-Java functions have ``raw'' counterparts which do not perform any conversion. These are recognizable by their name ending with @code{-RAW}. This section covers the low-level Lisp-to-Java API of ABCL. Functions in this section are available after evaluating @code{(require 'JAVA)}. A higher level Java API, developed by Alan Ruttenberg, is available in the @file{contrib/} directory and described later in this document, @pxref{JSS}. @menu * Creating Java objects:: * Accessing Java object and class fields:: * Calling Java Methods:: * Calling Java Static Methods:: * Parameter matching for FFI dynamic dispatch:: * Implementating Java interfaces in Lisp:: * Implementation of Java classes in Lisp:: @end menu @node Creating Java objects @subsection Creating Java objects Java objects can be created from Lisp by calling a constructor from the class of the object to be created. The @code{JAVA:JCONSTRUCTOR} primitive is used to acquire a constructor reference. @defun jconstructor (class-ref &rest parameter-class-refs) Returns a reference to the Java constructor of @var{CLASS-REF} accepting the given @var{PARAMETER-CLASS-REFS}. If @var{PARAMETER-CLASS-REFS} is a single integer, the first method with the given number of parameters is returned instead. @end defun The obtained constructor can be passed as an argument to @code{JAVA:JNEW}, together with any arguments. @code{JAVA:JNEW} can also be invoked with a string naming the class as its first argument. @defun jnew (constructor &rest args) Creates a new Java object by invoking @var{CONSTRUCTOR} with arguments @var{ARGS}. @var{CONSTRUCTOR} can be a constructor reference or a string naming a class. @end defun @node Accessing Java object and class fields @subsection Accessing Java object and class fields Fields in Java objects can be accessed using the getter and setter functions @code{JAVA:JFIELD} and @code{(SETF JAVA:JFIELD)}. Static (class) fields are accessed the same way, but with a class object or string naming a class as first argument. Like @code{JAVA:JCALL} and friends, values returned from these accessors carry an intended class around, and values which can be converted to Lisp values will be converted. @defun jfield (class-ref-or-field field-or-instance @ &optional instance value) Retrieves or modifies a field in a Java class or instance. Supported argument patterns: @table @code @item class-ref field-name Retrieve the value of static field @var{field-name} of class @var{class-ref}. @item class-ref field-name instance-ref Retrieves the value of a class field of the instance. @item class-ref field-name primitive-value: Stores @var{primitive-value} in static field @var{field-name}. @item class-ref field-name instance-ref value Stores @var{value} in a class field of the instance. @item class-ref field-name nil value Stores value in a static field (when value may be confused with an instance-ref). @item field-name instance Retrieves the value of a field of the instance. The class is derived from the instance. @item field-name instance value Stores value in a field of the instance. The class is derived from the instance. @end table @end defun @node Calling Java Methods @subsection Calling Java Methods Methods on a java object method in the low-level (basic) API can be called in two ways: @itemize @item Calling a specific method reference (which was previously acquired) @item Dynamic dispatch using the method name and the call-specific arguments provided by finding the best match (@pxref{Parameter matching for FFI dynamic dispatch}). @end itemize @defun jmethod (class-ref method-name &rest parameter-class-refs) Returns a reference to the Java method @var{method-name} of @var{class-ref} accepting the given @var{parameter-class-refs}. If @var{parameter-class-refs} is a single integer, the first method with the given number of parameters is returned instead. The function @code{java:jmethod} is used to acquire a specific method reference. Its first argument is a Java class designator (a @code{java:java-class} object returned by @code{java:jclass} or a string naming a Java class). The second argument is a string naming the method. Any arguments beyond the first two should be strings naming Java classes, with one exception as listed in the next paragraph. These classes specify the types of the arguments for the method. When @code{java:jmethod} is called with three parameters and the last parameter is an integer, the first method by that name and matching number of parameters is returned. @end defun Once a method reference has been acquired, it can be invoked using @code{java:jcall}, which takes the method as the first argument. The second argument is the object instance to call the method on, or @code{NIL} in case of a static method. Any remaining parameters are used as the remaining arguments for the call. @defun jcall (method instance &rest args) @defunx jcall-raw (method instance &rest args) Invokes the Java method @var{method} on @var{instance} with arguments @var{args}. @var{Method} can be a method reference acquired via @code{jmethod} or a string naming a method. The @code{-raw} version does not attempt to coerce the arguments or result into a Lisp object. @end defun @node Calling Java Static Methods @subsection Calling Java Static Methods Like non-static methods, references to static (class) methods can be acquired by using the @code{java:jmethod} primitive. Static methods are called with @code{java:jstatic} instead of @code{java:jcall}. @defun jstatic (method class &rest args) @defunx jstatic-raw (method class &rest args) Invoke the static method @var{method} on class @var{class} with @var{args}. The @code{-raw} version does not attempt to coerce the arguments or result into a Lisp object. @end defun Like @code{java:jcall}, @code{java:jstatic} supports dynamic dispatch by passing the name of the method as a string instead of passing a method reference. The parameter values should be values to pass in the function call instead of a specification of classes for each parameter. @node Parameter matching for FFI dynamic dispatch @subsection Parameter matching for FFI dynamic dispatch The algorithm used to resolve the best matching method given the name and the arguments' types is the same as described in the Java Language Specification. Any deviation should be reported as a bug. @c % ###TODO reference to correct JLS section @menu * Dynamic dispatch Caveats:: @end menu @node Dynamic dispatch Caveats @subsubsection Dynamic dispatch: Caveats Dynamic dispatch, i.e., invoking a Java method via method name instead of method reference, is performed by using the Java reflection API. Generally the dispatch works fine, but there are corner cases where the API does not correctly reflect all the details involved in calling a Java method. An example is the following Java code: @example ZipFile jar = new ZipFile("/path/to/some.jar"); Object els = jar.entries(); Method method = els.getClass().getMethod("hasMoreElements"); method.invoke(els); @end example Even though the method @code{hasMoreElements()} is public in @code{Enumeration}, the above code fails with @example java.lang.IllegalAccessException: Class ... can not access a member of class java.util.zip.ZipFile\$2 with modifiers "public" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65) at java.lang.reflect.Method.invoke(Method.java:583) at ... @end example This is because the method has been overridden by a non-public class and the reflection API, unlike @code{javac}, is not able to handle such a case. While code like that is uncommon in Java, it is typical of ABCL's FFI calls. The code above corresponds to the following Lisp code: @lisp (let* ((jar (jnew "java.util.zip.ZipFile" "/path/to/some.jar")) (els (jcall "entries" jar))) (jcall "hasMoreElements" els)) @end lisp @noindent except that the dynamic dispatch part is not shown. To avoid such pitfalls, all Java objects in ABCL carry an extra field representing the ``intended class'' of the object. That class is used first by @code{JAVA:JCALL} and similar to resolve methods; the actual class of the object is only tried if the method is not found in the intended class. Of course, the intended class is always a super-class of the actual class -- in the worst case, they coincide. The intended class is deduced by the return type of the method that originally returned the Java object; in the case above, the intended class of @code{ELS} is @code{java.util.Enumeration} because that is the return type of the @code{entries} method. While this strategy is generally effective, there are cases where the intended class becomes too broad to be useful. The typical example is the extraction of an element from a collection, since methods in the collection API erase all types to @code{Object}. The user can always force a more specific intended class by using the @code{JAVA:JCOERCE} operator. @c % \begin{itemize} @c % \item Java values are accessible as objects of type JAVA:JAVA-OBJECT. @c % \item The Java FFI presents a Lisp package (JAVA) with many useful @c % symbols for manipulating the artifacts of expectation on the JVM, @c % including creation of new objects \ref{JAVA:JNEW}, \ref{JAVA:JMETHOD}), the @c % introspection of values \ref{JAVA:JFIELD}, the execution of methods @c % (\ref{JAVA:JCALL}, \ref{JAVA:JCALL-RAW}, \ref{JAVA:JSTATIC}) @c % \item The JSS package (\ref{JSS}) in contrib introduces a convenient macro @c % syntax \ref{JSS:SHARPSIGN_DOUBLEQUOTE_MACRO} for accessing Java @c % methods, and additional convenience functions. @c % \item Java classes and libraries may be dynamically added to the @c % classpath at runtime (JAVA:ADD-TO-CLASSPATH). @c % \end{itemize} @node Implementating Java interfaces in Lisp @subsection Implementating Java interfaces in Lisp ABCL can use the Java reflection-based proxy feature to implement Java interfaces in Lisp. It has several built-in ways to implement an interface, and supports definition of new ones. The @code{JAVA:JMAKE-PROXY} generic function is used to make such proxies. @deffn {Generic Function} jmake-proxy interface implementation @ &optional lisp-this Returns a proxy Java object implementing the provided interface(s) using methods implemented in Lisp - typically closures, but implementations are free to provide other mechanisms. @code{interface} is a Java interface metaobject (e.g. obtained by invoking @code{jclass}), or a string naming a Java interface. @code{implementation} is the object used to implement the interface -- several built-in methods of jmake-proxy exist for various types of implementations. @code{lisp-this} is an object passed as first argument to the functions implementing the Lisp ``methods'' of the interface, and defaults to @code{NIL}. The @var{implementation} argument can be of type: @table @code @item function The given function will be called with two or more arguments (method name, @var{lisp-this}, method arguments if applicable) upon any method invocation on the proxy object. Useful for interfaces with a single method, or to implement custom interface-implementation strategies. @item hash-table The Java interface method names are used as keys in the given hash table to obtain the functions implementing them. Functions will be called with one or more arguments (@var{lisp-this}, method arguments if applicable). @item package The Java interface method names are mapped to symbols in @code{package}. A method called @code{javaMethodName} is mapped to a Lisp symbol @code{JAVA-METHOD-NAME}. An error is signaled if no such symbol exists in the package, or if the symbol exists but does not name a function. Functions will be called with one or more arguments (@var{lisp-this}, method arguments if applicable). @end table @end deffn The returned proxy is an instance of the interface, with methods implemented with Lisp functions, and can be passed to Java methods expecting an instance of the given interface. @node Implementation of Java classes in Lisp @subsection Implementation of Java classes in Lisp @defun jnew-runtime-class (class-name &rest args @ &key (superclass @code{java.lang.Object}) interfaces @ constructors methods fields (access-flags @code{'(public)}) @ annotations) Creates and loads a Java class with methods calling Lisp closures as given in @var{methods}. @var{class-name} and @var{super-name} are strings, @var{interfaces} is a list of strings, @var{constructors}, @var{methods} and @var{fields} are lists of constructor, method and field definitions, respectively. Constructor definitions - currently NOT supported - are lists of the form @code{(argument-types function &optional super-invocation-arguments)} where @var{argument-types} is a list of strings and @var{function} is a lisp function of @code{(1+ (length argument-types))} arguments; the instance (@code{this}) is passed in as the last argument. The optional @var{super-invocation-arguments} is a list of numbers between 1 and @code{(length argument-types)}, where the number @var{k} stands for the @var{k}th argument to the just defined constructor. If present, the constructor of the superclass will be called with the appropriate arguments. E.g., if the constructor definition is @code{(("java.lang.String" "int") #'(lambda (string i this) ...) (2 1))} then the constructor of the superclass with argument types @code{(int, java.lang.String)} will be called with the second and first arguments. Method definitions are lists of the form @code{(method-name return-type argument-types function &key modifiers annotations)} where @var{method-name} is a string, @var{return-type} and @var{argument-types} are strings or keywords for primitive types (@code{:void}, @code{:int}, etc.), and @var{function} is a Lisp function of minimum arity @code{(1+ (length argument-types))}; the instance (@code{this}) is passed in as the first argument. Field definitions are lists of the form @code{(field-name type &key modifiers annotations)}. @end defun @node Calling from Java to Lisp @section Calling from Java to Lisp This section describes the various ways that one interacts with Lisp from Java code. In order to access the Lisp world from Java, one needs to be aware of a few things, the most important ones being listed below: @itemize @item All Lisp values are descendants of @code{LispObject}. @item Lisp symbols are accessible either via static members of the @code{Symbol} class, or by dynamically introspecting a @code{Package} object. @item The Lisp dynamic environment may be saved via @code{LispThread.bindSpecial(Binding)} and restored via @code{LispThread.resetSpecialBindings(Mark)}. @item Functions can be executed by invoking @code{LispObject.execute(args [...])} @end itemize @menu * Acquiring an Interpreter Object:: * Evaluating Lisp Forms:: * Calling Common Lisp Functions Directly:: * Introspecting a Lisp Object:: @end menu @node Acquiring an Interpreter Object @subsection Acquiring an Interpreter Object The entire ABCL Lisp system resides in the @code{org.armedbear.lisp} package, but the following code snippets do not show the relevant import statements in the interest of brevity. An example of the import statement would be @example import org.armedbear.lisp.*; @end example to potentially import all the JVM symbol from the @code{org.armedbear.lisp} namespace. There can only ever be a single Lisp interpreter per JVM instance. A reference to this interpreter is obtained by calling the static method @code{Interpreter.createInstance()}. @example Interpreter interpreter = Interpreter.createInstance(); @end example If this method has already been invoked in the lifetime of the current Java process it will return @code{null}, so if you are writing Java whose life-cycle is a bit out of your control (like in a Java servlet), a safer invocation pattern might be: @example Interpreter interpreter = Interpreter.getInstance(); if (interpreter == null) @{ interpreter = Interpreter.createInstance(); @} @end example @node Evaluating Lisp Forms @subsection Evaluating Lisp Forms The Lisp @code{eval} primitive may simply be passed strings for evaluation: @example String line = "(load \"file.lisp\")"; LispObject result = interpreter.eval(line); @end example Notice that all possible return values from an arbitrary Lisp computation are collapsed into a single return value. Doing useful further computation on the @code{LispObject} depends on knowing what the result of the computation might be. This usually involves some amount of @code{instanceof} introspection, and forms a whole topic to itself (@pxref{Introspecting a Lisp Object}). Using @code{eval} involves the Lisp interpreter. Lisp functions may also be directly invoked by Java method calls as follows. One simply locates the package containing the symbol, obtains a reference to the symbol, and then invokes the @code{execute()} method with the desired parameters. @example interpreter.eval("(defun foo (msg)" + "(format nil \"You told me '~A'~%\" msg))"); Package pkg = Packages.findPackage("CL-USER"); Symbol foo = pkg.findAccessibleSymbol("FOO"); Function fooFunction = (Function)foo.getSymbolFunction(); JavaObject parameter = new JavaObject("Lisp is fun!"); LispObject result = fooFunction.execute(parameter); // How to get the "naked string value"? System.out.println("The result was " + result.writeToString()); @end example @node Calling Common Lisp Functions Directly @subsection Calling Common Lisp Functions Directly If one is calling a function in the @var{CL} package, the syntax can become considerably simpler. If we can locate the instance of definition in the ABCL Java source, we can invoke the symbol directly. For instance, to tell if a @code{LispObject} is (Lisp) @code{NIL}, we can invoke the CL function @code{NULL} in the following way: @example boolean nullp(LispObject object) @{ LispObject result = Primitives.NULL.execute(object); if (result == NIL) @{ // the symbol 'NIL' is explicitly named in the Java // namespace at ``Symbol.NIL'' // but is always present in the // local namespace in its unadorned form for // the convenience of the User. return false; @} return true; @} @end example @node Introspecting a Lisp Object @subsection Introspecting a Lisp Object We present various patterns for introspecting an arbitrary @code{LispObject} which can hold the result of every Lisp evaluation into semantics that Java can meaningfully deal with. @menu * LispObject as boolean:: * LispObject as a list:: @end menu @node LispObject as boolean @subsubsection LispObject as @code{boolean} If the @code{LispObject} is to be interpreted as a generalized boolean value, one can use @code{getBooleanValue()} to convert to Java: @example LispObject object = Symbol.NIL; boolean javaValue = object.getBooleanValue(); @end example Since in Lisp any value other than @code{NIL} means "true", Java equality can also be used, which is a bit easier to type and better in terms of information it conveys to the compiler: @example boolean javaValue = (object != Symbol.NIL); @end example @node LispObject as a list @subsubsection LispObject as a list If @code{LispObject} is a list, it will have the Java type @code{Cons}. One can then use the @code{copyToArray} method to make things a bit more suitable for Java iteration. @example LispObject result = interpreter.eval("'(1 2 4 5)"); if (result instanceof Cons) @{ LispObject array[] = ((Cons)result.copyToArray()); ... @} @end example A more Lispy way to iterate down a list is to use the @code{cdr()} access function just as like one would traverse a list in Lisp:; @example LispObject result = interpreter.eval("'(1 2 4 5)"); while (result != Symbol.NIL) @{ doSomething(result.car()); result = result.cdr(); @} @end example @node Java Scripting API (JSR-223) @section Java Scripting API (JSR-223) ABCL can be built with support for JSR-223, which offers a language-agnostic API to invoke other languages from Java. The binary distribution from ABCL's homepage is built with JSR-223 support. If you are building ABCL from source on a pre-1.6 JVM, you need to have a JSR-223 implementation in your classpath (such as Apache Commons BSF 3.x or greater) in order to build ABCL with JSR-223 support; otherwise, this feature will not be built. This section describes the design decisions behind the ABCL JSR-223 support. It is not a description of what JSR-223 is or a tutorial on how to use it. See @url{http://abcl.org/svn/trunk/abcl/examples/jsr-223} for example usage. @menu * Conversions:: * Implemented JSR-223 interfaces:: * Start-up and configuration file:: * Evaluation:: * Compilation:: * Invocation of functions and methods:: * Creating Lisp interface proxies:: @end menu @node Conversions @subsection Conversions In general, ABCL's implementation of the JSR-223 API performs implicit conversion from Java objects to Lisp objects when invoking Lisp from Java, and the opposite when returning values from Java to Lisp. This potentially reduces coupling between user code and ABCL. To avoid such conversions, wrap the relevant objects in @code{JavaObject} instances. @node Implemented JSR-223 interfaces @subsection Implemented JSR-223 interfaces JSR-223 defines three main interfaces, of which two (@code{Invocable} and @code{Compilable}) are optional. ABCL implements all three interfaces - @code{ScriptEngine} and the two optional ones - almost completely. While the JSR-223 API is not specific to a single scripting language, it was designed with languages with a more or less Java-like object model in mind: languages such as Javascript, Python, Ruby, which have a concept of "class" or "object" with "fields" and "methods". Lisp is a bit different, so certain adaptations were made, and in one case a method has been left unimplemented since it does not map at all to Lisp. @menu * The ScriptEngine object:: @end menu @node The ScriptEngine object @subsubsection The ScriptEngine object The main interface defined by JSR-223, @code{javax.script.ScriptEngine}, is implemented by the class @code{org.armedbear.lisp.scripting.AbclScriptEngine}. @code{AbclScriptEngine} is a singleton, reflecting the fact that ABCL is a singleton as well. You can obtain an instance of @code{AbclScriptEngine} using @code{AbclScriptEngineFactory} or by using the service provider mechanism through @code{ScriptEngineManager} (refer to the @code{javax.script} documentation). @node Start-up and configuration file @subsection Start-up and configuration file At start-up (i.e. when its constructor is invoked, as part of the static initialization phase of @code{AbclScriptEngineFactory}), the ABCL script engine attempts to load an "init file" from the classpath (@file{/abcl-script-config.lisp}). If present, this file can be used to customize the behavior of the engine, by setting a number of variables in the @code{ABCL-SCRIPT} package. Here is a list of the available variables: @defvar @earmuffs{use-throwing-debugger} controls whether ABCL uses a non-standard debugging hook function to throw a Java exception instead of dropping into the debugger in case of unhandled error conditions. Its default value is @code{T}, since it is more convenient for Java programmers using Lisp as a scripting language to have it return exceptions to Java instead of handling them in the Lisp world. Known issues: the non-standard debugger hook has been reported to misbehave in certain circumstances, so consider disabling it if it doesn't work for you. @end defvar @defvar @earmuffs{launch-swank-at-startup} If true, Swank will be launched at startup. See @code{*swank-dir*} and @code{*swank-port*}. Default value: @code{NIL}. @end defvar @defvar @earmuffs{swank-dir} The directory where Swank is installed. Must be set if @code{*launch-swank-at-startup*} is true. @end defvar @defvar @earmuffs{swank-port} The port where Swank will listen for connections. Must be set if @code{*launch-swank-at-startup*} is true. Default value: 4005 @end defvar Additionally, at startup the @code{AbclScriptEngine} will execute @code{(require 'asdf)} - in fact, it uses asdf to load Swank. @node Evaluation @subsection Evaluation Code is read and evaluated in the package @code{ABCL-SCRIPT-USER}. This package uses the @code{COMMON-LISP}, @code{JAVA} and @code{ABCL-SCRIPT} packages. Future versions of the script engine might make thisf default package configurable. The @code{CL:LOAD} function is used under the hood for evaluating code, and thus the behavior of @code{LOAD} is guaranteed. This allows, among other things, @code{IN-PACKAGE} forms to change the package in which the loaded code is read. It is possible to evaluate code in what JSR-223 calls a ``ScriptContext'' (basically a flat environment of name-to-value pairs). This context is used to establish special bindings for all the variables defined in it; since variable names are strings from Java's point of view, they are first interned using @code{READ-FROM-STRING} with, as usual, @code{ABCL-SCRIPT-USER} as the default package. Variables are declared special because CL's @code{LOAD}, @code{EVAL} and @code{COMPILE} functions work in a null lexical environment and would ignore non-special bindings. Contrary to what the function @code{LOAD} does, evaluation of a series of forms returns the value of the last form instead of @code{T}, so the evaluation of short scripts does the Right Thing. @node Compilation @subsection Compilation @code{AbclScriptEngine} implements the @code{javax.script.Compilable} interface. Currently it only supports compilation using temporary files. Compiled code, returned as an instance of @code{javax.script.CompiledScript}, is read, compiled and executed by default in the @code{ABCL-SCRIPT-USER} package, just like evaluated code. In contrast to evaluated code, though, due to the way the ABCL compiler works, compiled code contains no reference to top-level self-evaluating objects (like numbers or strings). Thus, when evaluated, a piece of compiled code will return the value of the last non-self-evaluating form: for example the code @code{(do-something) 42} will return 42 when interpreted, but will return the result of @code{(do-something)} when compiled and later executed. To ensure consistency of behavior between interpreted and compiled code, make sure the last form is always a compound form -- at least @code{(identity some-literal-object)}. Note that this issue should not matter in real code, where it is unlikely a top-level self-evaluating form will appear as the last form in a file (in fact, the Common Lisp load function always returns @code{T} upon success; with JSR-223 this policy has been changed to make evaluation of small code snippets work as intended). @node Invocation of functions and methods @subsection Invocation of functions and methods @code{AbclScriptEngine} implements the @code{javax.script.Invocable} interface, which allows to directly call Lisp functions and methods, and to obtain Lisp implementations of Java interfaces. This is only partially possible with Lisp since it has functions, but not methods -- not in the traditional OO sense, at least, since Lisp methods belong to generic functions. Thus, the method @code{invokeMethod()} is not implemented and throws an @code{UnsupportedOperationException} when called. The @code{invokeFunction()} method is used to call both regular and generic functions. @node Creating Lisp interface proxies @subsection Creating Lisp interface proxies The functionality of @code{jmake-proxy} is exposed by the class @code{AbclScriptEngine} via the two methods @code{getInterface(Class)} and @code{getInterface(Object, Class)}. The former returns an interface implemented with the current Lisp package, the latter allows the programmer to pass an interface-implementation object which will in turn be passed to the @code{jmake-proxy} generic function. @node Implementation Dependent Extensions @chapter Implementation Dependent Extensions As outlined by the CLHS ANSI conformance guidelines, we document the extensions to the Armed Bear Lisp implementation made accessible to the user by virtue of being an exported symbol in the @code{JAVA}, @code{THREADS}, or @code{EXTENSIONS} packages. @menu * Extensions in the JAVA package:: * Extensions in the THREADS package:: * Extensions in the EXT package:: @end menu @node Extensions in the JAVA package @section Extensions in the JAVA package @c % include autogen docs for the JAVA package. @c \include{java} @node Extensions in the THREADS package @section Extensions in the THREADS package The extensions for handling multithreaded execution are collected in the @code{THREADS} package. Most of the abstractions in Doug Lea's excellent @code{java.util.concurrent} packages may be manipulated directly via the JSS contrib to great effect. @c % include autogen docs for the THREADS package. @c \include{threads} @node Extensions in the EXT package @section Extensions in the EXT package The symbols in the @code{EXTENSIONS} package (nicknamed @code{EXT}) constitutes extensions to the ANSI standard that are potentially useful to the user. They include functions for manipulating network sockets, running external programs, registering object finalizers, constructing reference weakly held by the garbage collector and others. For a generic function interface to the native JVM contract for @code{java.util.List}, @pxref{Extensible Sequences}. @c % include autogen docs for the EXTENSIONS package. @c \include{extensions} @node Beyond ANSI @chapter Beyond ANSI Naturally, in striving to be a useful contemporary Common Lisp implementation, ABCL endeavors to include extensions beyond the ANSI specification which are either widely adopted or are especially useful in working with the hosting JVM. @menu * Modifying the JVM Classpath:: * Compiler to Java 5 Bytecode:: * Pathnames:: * Extensible Sequences:: * Extensions to CLOS:: * Extensions to the Reader:: * Overloading of the REQUIRE Mechanism:: * JSS optionally extends the Reader:: * ASDF:: @end menu @node Modifying the JVM Classpath @section Modifying the JVM Classpath @deffn {Generic Function} add-to-classpath jar-or-jars @ &optional classloader The @code{add-to-classpath} generic functions allows one to add a pathname or list of pathnames to the current classpath used by ABCL, allowing the dynamic loading of JVM objects: @lisp (add-to-classpath "/path/to/some.jar") @end lisp N.b @code{add-to-classpath} only affects the classloader used by ABCL (the value of the special variable @code{java::*classloader*}). It has no effect on Java code outside ABCL. @end deffn @node Compiler to Java 5 Bytecode @section Compiler to Java 5 Bytecode The @code{CL:COMPILE-FILE} interface emits a packed fasl format whose Pathname has the type @file{abcl}. These fasls are operating system neutral byte archives packaged by the zip compression format which contain artifacts that are understood by @code{CL:LOAD}. @node Pathnames @section Pathnames We implement an extension to the @code{CL:PATHNAME} that allows for the description and retrieval of resources named in a URI@footnote{A URI is essentially a superset of what is commonly understood as a URL. We sometimes use the term URL as shorthand in describing the URL Pathnames, even though the corresponding encoding is more akin to a URI as described in RFC3986.} scheme that the JVM ``understands''. By definition, support is built-in into the JVM to access the @code{http://} and @code{https://} schemes but additional protocol handlers may be installed at runtime by having JVM symbols present in the @code{sun.net.protocol.dynamic} package (see @url{http://java.sun.com/developer/onlineTraining/protocolhandlers/} for more details). ABCL has created specializations of the ANSI @code{PATHNAME} object to enable to use of URIs to address dynamically loaded resources for the JVM. The @code{EXT:URL-PATHNAME} specialization has a corresponding URI whose canonical representation is defined to be the @code{NAMESTRING} of the Pathname. The @code{EXT:JAR-PATHNAME} extension further specializes the the @code{EXT:URL-PATHNAME} to provide access to components of zip and jar archives. @c % RDF description of type hierarchy @c % TODO Render via some LaTeX mode for graphviz? @example @@prefix ext: . @@prefix cl: . a . a . a . @end example @deftp {Built-In Class} url-pathname @deftpx {Built-In Class} jar-pathname @code{url-pathname} and @code{jar-pathname} are subclasses of the @code{pathname} built-in class. Objects of type @code{Ext:url-pathname} and @code{ext:jar-pathname} may be used anywhere a @code{cl:pathname} is accepted with the following caveats: @itemize @item A stream obtained via @code{cl:open} on a @code{ext:url-pathname} cannot be the target of write operations. @item Any results of canonicalization procesures performed on the underlying URI are discarded between resolutions (i.e. the implementation does not attempt to cache the results of current name resolution of the representing resource unless it is requested to be resolved). Upon resolution, any canoicalization procedures followed in resolving the resource (e.g., following redirects) are discarded. Users may programatically initiate a new, local computation by applying the @code{cl:truename} function to a @code{ext:url-pathname} object. Depending on the reliablity and properties of your local REST infrastructure, these results may not necessarily be idempotent over time.@footnote {See @url{http://code.google.com/p/abcl-dynamic-install/source/browse/doc/design/pathnames/pathnames.tex} for the draft of the publication of the technical details} @end itemize @end deftp The implementation of @code{ext:url-pathname} allows the ABCL user to dynamically load code from the network. For example, Quicklisp may be completely installed from the REPL as the single form: @lisp CL-USER> (load "http://beta.quicklisp.org/quicklisp.lisp") @end lisp The implementation currently breaks ANSI conformance by allowing the types able to be @code{cl:read} for the @var{device} to return a possible @code{cons} of @code{cl:pathname} objects. @c %% citation from CLHS needed. In order to ``smooth over'' the bit about types being @code{cl:read} from @code{cl:pathname} components, we extend the semantics for the usual PATHNAME merge semantics when @code{*default-pathname-defaults*} contains a @code{ext:jar-pathname}. @menu * Implementation of Pathname Extensions:: @end menu @node Implementation of Pathname Extensions @subsection Implementation of Pathname Extensions The implementation of these extensions stores all the additional information in the @code{CL:PATHNAME} object itself in ways that while strictly speaking are conformant, nonetheless may trip up libraries that don't expect the following: @itemize @item @code{DEVICE} can be either a string denoting a drive letter under DOS, or a list of exactly one or two elements. If @code{DEVICE} is a list, it denotes a @code{EXT:JAR-PATHNAME}, with the entries containing @code{CL:PATHNAME} objects which describe the outer and (possibly inner) locations of the jar archive.@footnote{The case of inner and outer @code{EXT:EJAR-PATHNAME} arises when zip archives themselves contain zip archives, which is the case when the ABCL fasl is included in the @file{abcl.jar} zip archive.} @item An @code{EXT:URL-PATHNAME} always has a @code{HOST} component that is a property list. The values of the @code{HOST} property list are always character strings. The allowed keys have the following meanings: @table @code @item :SCHEME Scheme of URI ("http", "ftp", "bundle", etc.) @item :AUTHORITY Valid authority according to the URI scheme. For "http" this could be "example.org:8080". @item :QUERY The query portion of the URI @item :FRAGMENT The fragment portion of the URI @end table @end itemize In order to encapsulate the implementation decisions for these meanings, the following functions provide a @code{setf}-able API for reading and writing such values. @deffn {Accessor} url-pathname-scheme @deffnx {Accessor} url-pathname-fragment @deffnx {Accessor} url-pathname-authority @deffnx {Accessor} url-pathname-query These functions and their @code{setf} form provide read and write access to the components of a @code{url-pathname} object. @end deffn The specific subtype of a Pathname may be determined with the predicates @code{pathname-url-p} and @code{pathname-jar-p}. @defun pathname-url-p object @defunx pathname-jar-p object These predicates return @code{T} if @var{object} is a designator for a pathname of the specific type. E.g.: @lisp (pathname-url-p "http://google.com/") @result{} T @end lisp @end defun @node Package-Local Nicknames @section Package-Local Nicknames ABCL allows giving packages local nicknames: they allow short and easy-to-use names to be used without fear of name conflict associated with normal nicknames.@footnote{Package-local nicknames were originally developed in SBCL.} A local nickname is valid only when inside the package for which it has been specified. Different packages can use same local nickname for different global names, or different local nickname for same global name. Symbol @code{:package-local-nicknames} in @code{*features*} denotes the support for this feature. @defmac defpackage name [[option]]* @result{} package Options are extended to include @itemize @item @code{:local-nicknames} @var{(local-nickname actual-package-name)}* The package has the specified local nicknames for the corresponding actual packages. @end itemize Example: @lisp (defpackage :bar (:intern "X")) (defpackage :foo (:intern "X")) (defpackage :quux (:use :cl) (:local-nicknames (:bar :foo) (:foo :bar))) (find-symbol "X" :foo) ; => FOO::X (find-symbol "X" :bar) ; => BAR::X (let ((*package* (find-package :quux))) (find-symbol "X" :foo)) ; => BAR::X (let ((*package* (find-package :quux))) (find-symbol "X" :bar)) ; => FOO::X @end lisp @end defmac @defun package-local-nicknames (package-designator) Returns an alist of (local-nickname . actual-package) describing the nicknames local to the designated package. When in the designated package, calls to @code{find-package} with any of the local-nicknames will return the corresponding actual-package instead. This also affects all implied calls to @code{find-package}, including those performed by the reader. When printing a package prefix for a symbol with a package local nickname, the local nickname is used instead of the real name in order to preserve print-read consistency. @end defun @defun package-locally-nicknamed-by-list (package-designator) Returns a list of packages which have a local nickname for the designated package. @end defun @defun add-package-local-nickname (local-nickname actual-package &optional package-designator) Adds @code{local-nickname} for @code{actual-package} in the designated package, defaulting to current package. @code{local-nickname} must be a string designator, and @code{actual-package} must be a package designator. Returns the designated package. Signals an error if @code{local-nickname} is already a package local nickname for a different package, or if @code{local-nickname} is one of "CL", "COMMON-LISP", or, "KEYWORD", or if @code{local-nickname} is a global name or nickname for the package to which the nickname would be added. When in the designated package, calls to @code{find-package} with the @code{local-nickname} will return the package the designated @code{actual-package} instead. This also affects all implied calls to @code{find-package}, including those performed by the reader. When printing a package prefix for a symbol with a package local nickname, local nickname is used instead of the real name in order to preserve print-read consistency. @end defun @defun remove-package-local-nickname (old-nickname &optional package-designator) If the designated package had @code{old-nickname} as a local nickname for another package, it is removed. Returns true if the nickname existed and was removed, and @code{nil} otherwise. @end defun @node Extensible Sequences @section Extensible Sequences See @url{http://doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf} for the design. The @code{SEQUENCE} package fully implements Christophe Rhodes' proposal for extensible sequences. These user extensible sequences are used directly in @code{java-collections.lisp} to provide these CLOS abstractions on the standard Java collection classes as defined by the @code{java.util.List} contract. @c %% an Example of using java.util.Lisp in Lisp would be nice This extension is not automatically loaded by the implementation. It may be loaded via: @lisp CL-USER> (require 'java-collections) @end lisp if both extensible sequences and their application to Java collections is required, or @lisp CL-USER> (require 'extensible-sequences) @end lisp if only the extensible sequences API is required. Note that @code{(require 'java-collections)} must be issued before @code{java.util.List} or any subclass is used as a specializer in a CLOS method definition (see the section below). @node Extensions to CLOS @section Extensions to CLOS @menu * Metaobject Protocol:: * Specializing on Java classes:: @end menu @node Metaobject Protocol @subsection Metaobject Protocol ABCL implements the metaobject protocol for CLOS as specified in AMOP. The symbols are exported from the package @code{MOP}. Contrary to the AMOP specification and following SBCL's lead, the metaclass @code{funcallable-standard-object} has @code{funcallable-standard-class} as metaclass instead of @code{standard-class}. @node Specializing on Java classes @subsection Specializing on Java classes There is an additional syntax for specializing the parameter of a generic function on a java class, viz. @code{(java:jclass CLASS-STRING)} where @code{CLASS-STRING} is a string naming a Java class in dotted package form. For instance, the following specialization would perhaps allow one to print more information about the contents of a @code{java.util.Collection} object: @lisp (defmethod print-object ((coll (java:jclass "java.util.Collection")) stream) ;;; ... ) @end lisp If the class had been loaded via a classloader other than the original the class you wish to specialize on, one needs to specify the classloader as an optional third argument. @lisp (defparameter *other-classloader* (jcall "getBaseLoader" cl-user::*classpath-manager*)) (defmethod print-object ((device-id (java:jclass "dto.nbi.service.hdm.alcatel.com.NBIDeviceID" *other-classloader*)) stream) ;;; ... ) @end lisp @node Extensions to the Reader @section Extensions to the Reader We implement a special hexadecimal escape sequence for specifying 32-bit characters to the Lisp reader,@footnote{This represents a compromise with contemporary in 2011 32bit hosting architecures for which we wish to make text processing efficient. Should the User require more control over UNICODE processing we recommend Edi Weiz's excellent work with FLEXI-STREAMS which we fully support} namely we allow a sequences of the form @code{#\Uxxxx} to be processed by the reader as character whose code is specified by the hexadecimal digits @code{xxxx}. The hexadecimal sequence may be one to four digits long. Note that this sequence is never output by the implementation. Instead, the corresponding Unicode character is output for characters whose code is greater than @code{0x00ff}. @node Overloading of the REQUIRE Mechanism @section Overloading of the CL:REQUIRE Mechanism The @code{CL:REQUIRE} mechanism is overloaded by attaching the following semantic to the execution of @code{REQUIRE} on the following symbols: @table @code @item ASDF Loads the ASDF implementation shipped with ABCL. After ASDF has been loaded in this manner, symbols passed to @code{CL:REQUIRE} which are otherwise unresolved are passed to ASDF for a chance for resolution. This means, for instance, if @code{CL-PPCRE} can be located as a loadable ASDF system, @code{(require 'cl-ppcre)} is equivalent to @code{(asdf:load-system 'cl-ppcre)}. @item ABCL-CONTRIB Locates and pushes the toplevel contents of @file{abcl-contrib.jar} into the ASDF central registry, namely: @table @code @item abcl-asdf Functions for loading JVM artifacts dynamically, hooking into ASDF objects where possible. @xref{abcl-asdf}. @item asdf-jar Package addressable JVM artifacts via @code{abcl-asdf} descriptions as a single binary artifact including recursive dependencies. @item mvn These systems name common JVM artifacts from the distributed pom.xml graph of Maven Aether, at the moment @code{jna} dynamically loads @code{jna.jar} version 3.5.1 from the network.@footnote{This loading can be inhibited if, at runtime, the Java class corresponding @code{:classname} clause of the system definition is present.} @end table @end table @defvar @earmuffs{module-provider-functions} The user may extend the @code{cl:require} mechanism by pushing function hooks onto this variable. Each such hook function must take a single argument containing the symbol passed to @code{cl:require} and return a non-@code{NIL} value if it successfully resolved the symbol. @end defvar @node JSS optionally extends the Reader @section JSS optionally extends the Reader The JSS contrib consitutes an additional, optional extension to the reader in the definition of the @code{SHARPSIGN-DOUBLE-QUOTE} (@code{#"}) reader macro. @xref{JSS}. @node ASDF @section ASDF ASDF is packaged as a core component of ABCL, but not initialized by default as it relies on the CLOS subsystem which can take a bit of time to start.@footnote{While this time is ``merely'' on the order of seconds for contemporary 2011 machines, for applications that need to initialize quickly, for example a web server, this time might be unnecessarily long} The packaged ASDF may be loaded by the ANSI @code{REQUIRE} mechanism as follows: @lisp CL-USER> (require 'asdf) @end lisp @node Contrib @chapter Contrib The ABCL contrib is packaged as a separate jar archive usually named @file{abcl-contrib.jar} or possibly something like @file{abcl-contrib-1.1.0.jar}. The contrib jar is not loaded by the implementation by default, and must be first intialized by the @code{REQUIRE} mechanism before using any specific contrib: @lisp CL-USER> (require 'abcl-contrib) @end lisp @menu * abcl-asdf:: * asdf-jar:: * JSS:: * jfli:: * asdf-install:: @end menu @node abcl-asdf @section abcl-asdf This contrib enables an additional syntax for ASDF system definition which dynamically loads JVM artifacts such as @file{jar} archives via encapsulation of the Maven build tool. The Maven Aether component can also be directly manipulated by the function associated with the @code{ABCL-ASDF:RESOLVE-DEPENDENCIES} symbol. @c %ABCL specific contributions to ASDF system definition mainly @c %concerned with finding JVM artifacts such as jar archives to be @c %dynamically loaded. When loaded, abcl-asdf adds the following objects to ASDF: @code{JAR-FILE}, @code{JAR-DIRECTORY}, @code{CLASS-FILE-DIRECTORY} and @code{MVN}, exporting them (and others) as public symbols from the @code{ASDF} package. @menu * Referencing Maven Artifacts via ASDF:: * The abcl-asdf API:: * Directly Instructing Maven to Download JVM Artifacts:: @end menu @node Referencing Maven Artifacts via ASDF @subsection Referencing Maven Artifacts via ASDF Maven artifacts may be referenced within ASDF system definitions. The following example references the @code{log4j-1.4.9.jar} JVM artifact which provides a widely-used abstraction for handling logging systems: @lisp (in-package :asdf) (defsystem :log4j :components ((:mvn "log4j/log4j" :version "1.4.9"))) @end lisp @node The abcl-asdf API @subsection The abcl-asdf API We define an API for abcl-asdf as consisting of the following ASDF classes: @code{JAR-DIRECTORY}, @code{JAR-FILE}, and @code{CLASS-FILE-DIRECTORY} for JVM artifacts that have a currently valid pathname representation. Both the @code{MVN} and @code{IRI} classes descend from @code{ASDF-COMPONENT}, but do not directly have a filesystem location. For use outside of ASDF system definitions, we currently define one method, @code{ABCL-ASDF:RESOLVE-DEPENDENCIES} which locates, downloads, caches, and then loads into the currently executing JVM process all recursive dependencies annotated in the Maven @file{pom.xml} graph. @node Directly Instructing Maven to Download JVM Artifacts @subsection Directly Instructing Maven to Download JVM Artifacts Bypassing ASDF, one can directly issue requests for the Maven artifacts to be downloaded: @lisp CL-USER> (abcl-asdf:resolve-dependencies "com.google.gwt" "gwt-user") @print{} WARNING: Using LATEST for unspecified version. @print{} "/Users/evenson/.m2/repository/com/google/gwt/gwt-user/2.4.0-rc1 @print{} /gwt-user-2.4.0-rc1.jar:/Users/evenson/.m2/repository/javax/vali @print{} dation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar:/User @print{} s/evenson/.m2/repository/javax/validation/validation-api/1.0.0.G @print{} A/validation-api-1.0.0.GA-sources.jar" @end lisp To actually load the dependency, use the @code{JAVA:ADD-TO-CLASSPATH} generic function: @lisp CL-USER> (java:add-to-classpath (abcl-asdf:resolve-dependencies "com.google.gwt" "gwt-user")) @end lisp Notice that all recursive dependencies have been located and installed locally from the network as well. @node asdf-jar @section asdf-jar The asdf-jar contrib provides a system for packaging ASDF systems into jar archives for ABCL. Given a running ABCL image with loadable ASDF systems the code in this package will recursively package all the required source and fasls in a jar archive. The documentation for this contrib can be found at @url{http://abcl.org/svn/trunk/abcl/contrib/asdf-jar/README.markdown}. @node JSS @section JSS To one used to the more universal syntax of Lisp pairs upon which the definition of read and compile time macros is quite natural,@footnote{See Graham's ``On Lisp'' @url{http://lib.store.yahoo.net/lib/paulgraham/onlisp.pdf}.} the Java syntax available to the Java programmer may be said to suck. To alleviate this situation, the JSS contrib introduces the @code{SHARPSIGN-DOUBLE-QUOTE} (@code{#"}) reader macro, which allows the specification of the name of invoking function as the first element of the relevant s-expr which tends to be more congruent to how Lisp programmers seem to be wired to think. While quite useful, we don't expect that the JSS contrib will be the last experiment in wrangling Java from Common Lisp. @menu * JSS usage:: @end menu @node JSS usage @subsection JSS usage Example: @lisp CL-USER> (require 'abcl-contrib) @result{} ("ABCL-CONTRIB") CL-USER> (require 'jss) @result{} ("JSS") CL-USER) (#"getProperties" 'java.lang.System) @result{} # CL-USER) (#"propertyNames" (#"getProperties" 'java.lang.System)) @result{} # @end lisp Some more information on jss can be found in its documentation at @url{http://abcl.org/svn/trunk/abcl/contrib/jss/README.markdown} @node jfli @section jfli This contrib contains a pure-Java version of JFLI. @node asdf-install @section asdf-install The asdf-install contrib provides an implementation of ASDF-INSTALL. This method of installing Lisp libraries is superseded by Quicklisp, which can be installed via @code{(load "http://beta.quicklisp.org/quicklisp.lisp")}. @node History @chapter History ABCL was originally the extension language for the J editor, which was started in 1998 by Peter Graves. Sometime in 2003, a whole lot of code that had previously not been released publically was suddenly committed that enabled ABCL to be plausibly termed an emergent ANSI Common Lisp implementation candidate. From 2006 to 2008, Peter manned the development lists, incorporating patches as made sense. After a suitable search, Peter nominated Erik H@"ulsmann to take over the project. In 2008, the implementation was transferred to the current maintainers, who have strived to improve its usability as a contemporary Common Lisp implementation. On October 22, 2011, with the publication of this Manual explicitly stating the conformance of Armed Bear Common Lisp to ANSI, we released abcl-1.0.0. We released abcl-1.0.1 as a maintainence release on January 10, 2012. In December 2012, we revised the implementation by adding (A)MOP with the release of abcl-1.1.0. @node Concept Index @appendix Concept Index @printindex cp @node Function Index @appendix Function Index @printindex fn @node Variable Index @appendix Variable Index @printindex vr @node Type Index @appendix Type Index @printindex tp @node Colophon @unnumbered Colophon This manual is maintained in Texinfo, and automatically translated into other forms (e.g. HTML or pdf). If you're @emph{reading} this manual in one of these non-Texinfo translated forms, that's fine, but if you want to @emph{modify} this manual, you are strongly advised to seek out a Texinfo version and modify that instead of modifying a translated version. Even better might be to seek out @emph{the} Texinfo version (maintained at the time of this writing as part of the ABCL project at @uref{http://abcl.org/}) and submit a patch. @bye abcl-src-1.9.0/doc/manual/abcl.toc0100644 0000000 0000000 00000110662 14242630063 015376 0ustar000000000 0000000 \contentsline {subsection}{\numberline {0.0.1}Preface to the First Edition}{4}{subsection.0.0.1}% \contentsline {subsection}{\numberline {0.0.2}Preface to the Second Edition}{4}{subsection.0.0.2}% \contentsline {subsection}{\numberline {0.0.3}Preface to the Third Edition}{4}{subsection.0.0.3}% \contentsline {subsection}{\numberline {0.0.4}Preface to the Fourth Edition}{5}{subsection.0.0.4}% \contentsline {subsection}{\numberline {0.0.5}Preface to the Fifth Edition}{5}{subsection.0.0.5}% \contentsline {subsection}{\numberline {0.0.6}Preface to the Sixth Edition}{5}{subsection.0.0.6}% \contentsline {subsection}{\numberline {0.0.7}Preface to the Seventh Edition}{5}{subsection.0.0.7}% \contentsline {subsection}{\numberline {0.0.8}Preface to the Eighth Edition}{5}{subsection.0.0.8}% \contentsline {subsection}{\numberline {0.0.9}Preface to the Ninth Edition}{5}{subsection.0.0.9}% \contentsline {subsection}{\numberline {0.0.10}Preface to the Tenth Edition}{6}{subsection.0.0.10}% \contentsline {chapter}{\numberline {1}Introduction}{7}{chapter.1}% \contentsline {section}{\numberline {1.1}Conformance}{7}{section.1.1}% \contentsline {subsection}{\numberline {1.1.1}ANSI Common Lisp}{7}{subsection.1.1.1}% \contentsline {subsection}{\numberline {1.1.2}Contemporary Common Lisp}{8}{subsection.1.1.2}% \contentsline {section}{\numberline {1.2}License}{8}{section.1.2}% \contentsline {section}{\numberline {1.3}Contributors}{8}{section.1.3}% \contentsline {chapter}{\numberline {2}Running ABCL}{11}{chapter.2}% \contentsline {section}{\numberline {2.1}Options}{11}{section.2.1}% \contentsline {section}{\numberline {2.2}Initialization}{12}{section.2.2}% \contentsline {chapter}{\numberline {3}Interaction with the Hosting JVM}{13}{chapter.3}% \contentsline {section}{\numberline {3.1}Lisp to Java}{13}{section.3.1}% \contentsline {subsection}{\numberline {3.1.1}Low-level Java API}{13}{subsection.3.1.1}% \contentsline {subsubsection}{Calling Java Object Methods}{13}{section*.2}% \contentsline {subsubsection}{Calling Java object methods: dynamic dispatch}{14}{section*.3}% \contentsline {subsubsection}{Dynamic dispatch: Caveats}{14}{section*.4}% \contentsline {subsubsection}{Calling Java class static methods}{15}{section*.5}% \contentsline {subsubsection}{Parameter matching for FFI dynamic dispatch}{15}{section*.6}% \contentsline {subsubsection}{Instantiating Java objects}{15}{section*.7}% \contentsline {subsubsection}{Accessing Java object and class fields}{15}{section*.8}% \contentsline {section}{\numberline {3.2}Java to Lisp}{15}{section.3.2}% \contentsline {subsection}{\numberline {3.2.1}Calling Lisp from Java}{15}{subsection.3.2.1}% \contentsline {subsubsection}{Multiple Values}{16}{section*.9}% \contentsline {subsubsection}{Introspecting a LispObject}{17}{section*.10}% \contentsline {paragraph}{LispObject as \texttt {boolean}}{17}{section*.11}% \contentsline {paragraph}{LispObject as a list}{17}{section*.12}% \contentsline {section}{\numberline {3.3}Java Scripting API (JSR-223)}{17}{section.3.3}% \contentsline {subsection}{\numberline {3.3.1}Conversions}{18}{subsection.3.3.1}% \contentsline {subsection}{\numberline {3.3.2}Implemented JSR-223 interfaces}{18}{subsection.3.3.2}% \contentsline {subsubsection}{The ScriptEngine}{18}{section*.13}% \contentsline {subsection}{\numberline {3.3.3}Start-up and configuration file}{18}{subsection.3.3.3}% \contentsline {subsection}{\numberline {3.3.4}Evaluation}{19}{subsection.3.3.4}% \contentsline {subsection}{\numberline {3.3.5}Compilation}{19}{subsection.3.3.5}% \contentsline {subsection}{\numberline {3.3.6}Invocation of functions and methods}{19}{subsection.3.3.6}% \contentsline {subsection}{\numberline {3.3.7}Implementation of Java interfaces in Lisp}{19}{subsection.3.3.7}% \contentsline {section}{\numberline {3.4}Implementation Extension Dictionaries}{20}{section.3.4}% \contentsline {subsection}{\numberline {3.4.1}The JAVA Dictionary}{20}{subsection.3.4.1}% \contentsline {subsubsection}{Modifying the JVM CLASSPATH}{20}{section*.14}% \contentsline {subsubsection}{Creating a synthetic Java Class at Runtime}{20}{section*.15}% \contentsline {paragraph}{}{21}{section*.16}% \contentsline {paragraph}{}{21}{section*.17}% \contentsline {paragraph}{}{21}{section*.18}% \contentsline {paragraph}{}{21}{section*.19}% \contentsline {paragraph}{}{21}{section*.20}% \contentsline {paragraph}{}{21}{section*.21}% \contentsline {paragraph}{}{21}{section*.22}% \contentsline {paragraph}{}{21}{section*.23}% \contentsline {paragraph}{}{21}{section*.24}% \contentsline {paragraph}{}{21}{section*.25}% \contentsline {paragraph}{}{21}{section*.26}% \contentsline {paragraph}{}{22}{section*.27}% \contentsline {paragraph}{}{22}{section*.28}% \contentsline {paragraph}{}{22}{section*.29}% \contentsline {paragraph}{}{22}{section*.30}% \contentsline {paragraph}{}{22}{section*.31}% \contentsline {paragraph}{}{22}{section*.32}% \contentsline {paragraph}{}{22}{section*.33}% \contentsline {paragraph}{}{22}{section*.34}% \contentsline {paragraph}{}{22}{section*.35}% \contentsline {paragraph}{}{22}{section*.36}% \contentsline {paragraph}{}{22}{section*.37}% \contentsline {paragraph}{}{22}{section*.38}% \contentsline {paragraph}{}{22}{section*.39}% \contentsline {paragraph}{}{22}{section*.40}% \contentsline {paragraph}{}{23}{section*.41}% \contentsline {paragraph}{}{23}{section*.42}% \contentsline {paragraph}{}{23}{section*.43}% \contentsline {paragraph}{}{23}{section*.44}% \contentsline {paragraph}{}{23}{section*.45}% \contentsline {paragraph}{}{23}{section*.46}% \contentsline {paragraph}{}{23}{section*.47}% \contentsline {paragraph}{}{23}{section*.48}% \contentsline {paragraph}{}{23}{section*.49}% \contentsline {paragraph}{}{23}{section*.50}% \contentsline {paragraph}{}{23}{section*.51}% \contentsline {paragraph}{}{23}{section*.52}% \contentsline {paragraph}{}{23}{section*.53}% \contentsline {paragraph}{}{23}{section*.54}% \contentsline {paragraph}{}{24}{section*.55}% \contentsline {paragraph}{}{24}{section*.56}% \contentsline {paragraph}{}{24}{section*.57}% \contentsline {paragraph}{}{24}{section*.58}% \contentsline {paragraph}{}{24}{section*.59}% \contentsline {paragraph}{}{24}{section*.60}% \contentsline {paragraph}{}{24}{section*.61}% \contentsline {paragraph}{}{25}{section*.62}% \contentsline {paragraph}{}{25}{section*.63}% \contentsline {paragraph}{}{25}{section*.64}% \contentsline {paragraph}{}{25}{section*.65}% \contentsline {paragraph}{}{25}{section*.66}% \contentsline {paragraph}{}{25}{section*.67}% \contentsline {paragraph}{}{25}{section*.68}% \contentsline {paragraph}{}{25}{section*.69}% \contentsline {paragraph}{}{25}{section*.70}% \contentsline {paragraph}{}{25}{section*.71}% \contentsline {paragraph}{}{25}{section*.72}% \contentsline {paragraph}{}{26}{section*.73}% \contentsline {paragraph}{}{26}{section*.74}% \contentsline {paragraph}{}{26}{section*.75}% \contentsline {paragraph}{}{26}{section*.76}% \contentsline {paragraph}{}{26}{section*.77}% \contentsline {paragraph}{}{26}{section*.78}% \contentsline {paragraph}{}{26}{section*.79}% \contentsline {paragraph}{}{27}{section*.80}% \contentsline {paragraph}{}{27}{section*.81}% \contentsline {paragraph}{}{27}{section*.82}% \contentsline {paragraph}{}{27}{section*.83}% \contentsline {paragraph}{}{27}{section*.84}% \contentsline {paragraph}{}{27}{section*.85}% \contentsline {paragraph}{}{27}{section*.86}% \contentsline {paragraph}{}{27}{section*.87}% \contentsline {paragraph}{}{27}{section*.88}% \contentsline {paragraph}{}{27}{section*.89}% \contentsline {paragraph}{}{27}{section*.90}% \contentsline {paragraph}{}{27}{section*.91}% \contentsline {paragraph}{}{28}{section*.92}% \contentsline {subsection}{\numberline {3.4.2}The THREADS Dictionary}{29}{subsection.3.4.2}% \contentsline {paragraph}{}{30}{section*.93}% \contentsline {paragraph}{}{30}{section*.94}% \contentsline {paragraph}{}{30}{section*.95}% \contentsline {paragraph}{}{30}{section*.96}% \contentsline {paragraph}{}{30}{section*.97}% \contentsline {paragraph}{}{30}{section*.98}% \contentsline {paragraph}{}{30}{section*.99}% \contentsline {paragraph}{}{30}{section*.100}% \contentsline {paragraph}{}{30}{section*.101}% \contentsline {paragraph}{}{30}{section*.102}% \contentsline {paragraph}{}{30}{section*.103}% \contentsline {paragraph}{}{30}{section*.104}% \contentsline {paragraph}{}{30}{section*.105}% \contentsline {paragraph}{}{30}{section*.106}% \contentsline {paragraph}{}{31}{section*.107}% \contentsline {paragraph}{}{31}{section*.108}% \contentsline {paragraph}{}{31}{section*.109}% \contentsline {paragraph}{}{31}{section*.110}% \contentsline {paragraph}{}{31}{section*.111}% \contentsline {paragraph}{}{31}{section*.112}% \contentsline {paragraph}{}{31}{section*.113}% \contentsline {paragraph}{}{31}{section*.114}% \contentsline {paragraph}{}{31}{section*.115}% \contentsline {paragraph}{}{31}{section*.116}% \contentsline {paragraph}{}{31}{section*.117}% \contentsline {paragraph}{}{31}{section*.118}% \contentsline {paragraph}{}{31}{section*.119}% \contentsline {subsection}{\numberline {3.4.3}The EXTENSIONS Dictionary}{32}{subsection.3.4.3}% \contentsline {paragraph}{}{33}{section*.120}% \contentsline {paragraph}{}{33}{section*.121}% \contentsline {paragraph}{}{33}{section*.122}% \contentsline {paragraph}{}{33}{section*.123}% \contentsline {paragraph}{}{33}{section*.124}% \contentsline {paragraph}{}{33}{section*.125}% \contentsline {paragraph}{}{33}{section*.126}% \contentsline {paragraph}{}{33}{section*.127}% \contentsline {paragraph}{}{33}{section*.128}% \contentsline {paragraph}{}{33}{section*.129}% \contentsline {paragraph}{}{33}{section*.130}% \contentsline {paragraph}{}{33}{section*.131}% \contentsline {paragraph}{}{33}{section*.132}% \contentsline {paragraph}{}{33}{section*.133}% \contentsline {paragraph}{}{33}{section*.134}% \contentsline {paragraph}{}{33}{section*.135}% \contentsline {paragraph}{}{34}{section*.136}% \contentsline {paragraph}{}{34}{section*.137}% \contentsline {paragraph}{}{34}{section*.138}% \contentsline {paragraph}{}{34}{section*.139}% \contentsline {paragraph}{}{34}{section*.140}% \contentsline {paragraph}{}{34}{section*.141}% \contentsline {paragraph}{}{34}{section*.142}% \contentsline {paragraph}{}{34}{section*.143}% \contentsline {paragraph}{}{34}{section*.144}% \contentsline {paragraph}{}{34}{section*.145}% \contentsline {paragraph}{}{34}{section*.146}% \contentsline {paragraph}{}{34}{section*.147}% \contentsline {paragraph}{}{34}{section*.148}% \contentsline {paragraph}{}{34}{section*.149}% \contentsline {paragraph}{}{34}{section*.150}% \contentsline {paragraph}{}{35}{section*.151}% \contentsline {paragraph}{}{35}{section*.152}% \contentsline {paragraph}{}{35}{section*.153}% \contentsline {paragraph}{}{35}{section*.154}% \contentsline {paragraph}{}{35}{section*.155}% \contentsline {paragraph}{}{35}{section*.156}% \contentsline {paragraph}{}{35}{section*.157}% \contentsline {paragraph}{}{35}{section*.158}% \contentsline {paragraph}{}{35}{section*.159}% \contentsline {paragraph}{}{35}{section*.160}% \contentsline {paragraph}{}{35}{section*.161}% \contentsline {paragraph}{}{36}{section*.162}% \contentsline {paragraph}{}{36}{section*.163}% \contentsline {paragraph}{}{36}{section*.164}% \contentsline {paragraph}{}{36}{section*.165}% \contentsline {paragraph}{}{36}{section*.166}% \contentsline {paragraph}{}{36}{section*.167}% \contentsline {paragraph}{}{36}{section*.168}% \contentsline {paragraph}{}{36}{section*.169}% \contentsline {paragraph}{}{36}{section*.170}% \contentsline {paragraph}{}{36}{section*.171}% \contentsline {paragraph}{}{36}{section*.172}% \contentsline {paragraph}{}{36}{section*.173}% \contentsline {paragraph}{}{36}{section*.174}% \contentsline {paragraph}{}{36}{section*.175}% \contentsline {paragraph}{}{37}{section*.176}% \contentsline {paragraph}{}{37}{section*.177}% \contentsline {paragraph}{}{37}{section*.178}% \contentsline {paragraph}{}{37}{section*.179}% \contentsline {paragraph}{}{37}{section*.180}% \contentsline {paragraph}{}{37}{section*.181}% \contentsline {paragraph}{}{37}{section*.182}% \contentsline {paragraph}{}{37}{section*.183}% \contentsline {paragraph}{}{37}{section*.184}% \contentsline {paragraph}{}{37}{section*.185}% \contentsline {paragraph}{}{37}{section*.186}% \contentsline {paragraph}{}{37}{section*.187}% \contentsline {paragraph}{}{37}{section*.188}% \contentsline {paragraph}{}{37}{section*.189}% \contentsline {paragraph}{}{37}{section*.190}% \contentsline {paragraph}{}{37}{section*.191}% \contentsline {paragraph}{}{38}{section*.192}% \contentsline {paragraph}{}{38}{section*.193}% \contentsline {paragraph}{}{38}{section*.194}% \contentsline {paragraph}{}{38}{section*.195}% \contentsline {paragraph}{}{38}{section*.196}% \contentsline {paragraph}{}{38}{section*.197}% \contentsline {paragraph}{}{38}{section*.198}% \contentsline {paragraph}{}{38}{section*.199}% \contentsline {paragraph}{}{38}{section*.200}% \contentsline {paragraph}{}{38}{section*.201}% \contentsline {paragraph}{}{38}{section*.202}% \contentsline {paragraph}{}{38}{section*.203}% \contentsline {paragraph}{}{38}{section*.204}% \contentsline {paragraph}{}{38}{section*.205}% \contentsline {paragraph}{}{38}{section*.206}% \contentsline {paragraph}{}{39}{section*.207}% \contentsline {paragraph}{}{39}{section*.208}% \contentsline {paragraph}{}{39}{section*.209}% \contentsline {paragraph}{}{39}{section*.210}% \contentsline {paragraph}{}{39}{section*.211}% \contentsline {paragraph}{}{39}{section*.212}% \contentsline {paragraph}{}{39}{section*.213}% \contentsline {paragraph}{}{39}{section*.214}% \contentsline {paragraph}{}{39}{section*.215}% \contentsline {paragraph}{}{39}{section*.216}% \contentsline {paragraph}{}{39}{section*.217}% \contentsline {paragraph}{}{39}{section*.218}% \contentsline {paragraph}{}{39}{section*.219}% \contentsline {paragraph}{}{39}{section*.220}% \contentsline {paragraph}{}{39}{section*.221}% \contentsline {paragraph}{}{39}{section*.222}% \contentsline {paragraph}{}{40}{section*.223}% \contentsline {paragraph}{}{40}{section*.224}% \contentsline {paragraph}{}{40}{section*.225}% \contentsline {paragraph}{}{40}{section*.226}% \contentsline {paragraph}{}{40}{section*.227}% \contentsline {paragraph}{}{40}{section*.228}% \contentsline {paragraph}{}{40}{section*.229}% \contentsline {paragraph}{}{40}{section*.230}% \contentsline {paragraph}{}{40}{section*.231}% \contentsline {paragraph}{}{40}{section*.232}% \contentsline {paragraph}{}{40}{section*.233}% \contentsline {paragraph}{}{40}{section*.234}% \contentsline {paragraph}{}{40}{section*.235}% \contentsline {paragraph}{}{40}{section*.236}% \contentsline {paragraph}{}{40}{section*.237}% \contentsline {paragraph}{}{40}{section*.238}% \contentsline {paragraph}{}{41}{section*.239}% \contentsline {paragraph}{}{41}{section*.240}% \contentsline {paragraph}{}{41}{section*.241}% \contentsline {paragraph}{}{41}{section*.242}% \contentsline {paragraph}{}{41}{section*.243}% \contentsline {chapter}{\numberline {4}Beyond ANSI}{43}{chapter.4}% \contentsline {section}{\numberline {4.1}Compiler to Java Virtual Machine Bytecode}{43}{section.4.1}% \contentsline {subsection}{\numberline {4.1.1}Compiler Diagnostics}{43}{subsection.4.1.1}% \contentsline {subsection}{\numberline {4.1.2}Decompilation}{43}{subsection.4.1.2}% \contentsline {section}{\numberline {4.2}Pathname}{43}{section.4.2}% \contentsline {subsubsection}{URL-PATHNAME}{44}{section*.244}% \contentsline {subsubsection}{JAR-PATHNAME}{45}{section*.245}% \contentsline {section}{\numberline {4.3}Package-Local Nicknames}{45}{section.4.3}% \contentsline {section}{\numberline {4.4}Extensible Sequences}{47}{section.4.4}% \contentsline {section}{\numberline {4.5}Extensions to CLOS}{47}{section.4.5}% \contentsline {subsection}{\numberline {4.5.1}Metaobject Protocol}{47}{subsection.4.5.1}% \contentsline {subsection}{\numberline {4.5.2}Specializing on Java classes}{47}{subsection.4.5.2}% \contentsline {section}{\numberline {4.6}Extensions to the Reader}{48}{section.4.6}% \contentsline {section}{\numberline {4.7}Overloading of the CL:REQUIRE Mechanism}{48}{section.4.7}% \contentsline {section}{\numberline {4.8}JSS extension of the Reader by SHARPSIGN-DOUBLE-QUOTE}{49}{section.4.8}% \contentsline {section}{\numberline {4.9}ASDF}{49}{section.4.9}% \contentsline {section}{\numberline {4.10}Extension to CL:MAKE-ARRAY}{49}{section.4.10}% \contentsline {chapter}{\numberline {5}Contrib}{51}{chapter.5}% \contentsline {section}{\numberline {5.1}abcl-asdf}{51}{section.5.1}% \contentsline {subsection}{\numberline {5.1.1}Referencing Maven Artifacts via ASDF}{51}{subsection.5.1.1}% \contentsline {subsection}{\numberline {5.1.2}API}{51}{subsection.5.1.2}% \contentsline {subsection}{\numberline {5.1.3}Directly Instructing Maven to Download JVM Artifacts}{52}{subsection.5.1.3}% \contentsline {section}{\numberline {5.2}asdf-jar}{52}{section.5.2}% \contentsline {section}{\numberline {5.3}jss}{52}{section.5.3}% \contentsline {subsection}{\numberline {5.3.1}JSS usage}{53}{subsection.5.3.1}% \contentsline {section}{\numberline {5.4}jfli}{53}{section.5.4}% \contentsline {section}{\numberline {5.5}abcl-introspect}{53}{section.5.5}% \contentsline {subsection}{\numberline {5.5.1}Implementations for CL:DISASSEMBLE}{53}{subsection.5.5.1}% \contentsline {section}{\numberline {5.6}abcl-build}{55}{section.5.6}% \contentsline {subsection}{\numberline {5.6.1}ABCL-BUILD Utilities}{55}{subsection.5.6.1}% \contentsline {section}{\numberline {5.7}named-readtables}{55}{section.5.7}% \contentsline {chapter}{\numberline {6}History}{57}{chapter.6}% \contentsline {chapter}{\numberline {A}The MOP Dictionary}{59}{appendix.A}% \contentsline {paragraph}{}{60}{section*.246}% \contentsline {paragraph}{}{60}{section*.247}% \contentsline {paragraph}{}{60}{section*.248}% \contentsline {paragraph}{}{60}{section*.249}% \contentsline {paragraph}{}{60}{section*.250}% \contentsline {paragraph}{}{60}{section*.251}% \contentsline {paragraph}{}{60}{section*.252}% \contentsline {paragraph}{}{60}{section*.253}% \contentsline {paragraph}{}{60}{section*.254}% \contentsline {paragraph}{}{60}{section*.255}% \contentsline {paragraph}{}{60}{section*.256}% \contentsline {paragraph}{}{60}{section*.257}% \contentsline {paragraph}{}{60}{section*.258}% \contentsline {paragraph}{}{60}{section*.259}% \contentsline {paragraph}{}{60}{section*.260}% \contentsline {paragraph}{}{60}{section*.261}% \contentsline {paragraph}{}{61}{section*.262}% \contentsline {paragraph}{}{61}{section*.263}% \contentsline {paragraph}{}{61}{section*.264}% \contentsline {paragraph}{}{61}{section*.265}% \contentsline {paragraph}{}{61}{section*.266}% \contentsline {paragraph}{}{61}{section*.267}% \contentsline {paragraph}{}{61}{section*.268}% \contentsline {paragraph}{}{61}{section*.269}% \contentsline {paragraph}{}{61}{section*.270}% \contentsline {paragraph}{}{61}{section*.271}% \contentsline {paragraph}{}{61}{section*.272}% \contentsline {paragraph}{}{61}{section*.273}% \contentsline {paragraph}{}{61}{section*.274}% \contentsline {paragraph}{}{61}{section*.275}% \contentsline {paragraph}{}{61}{section*.276}% \contentsline {paragraph}{}{61}{section*.277}% \contentsline {paragraph}{}{62}{section*.278}% \contentsline {paragraph}{}{62}{section*.279}% \contentsline {paragraph}{}{62}{section*.280}% \contentsline {paragraph}{}{62}{section*.281}% \contentsline {paragraph}{}{62}{section*.282}% \contentsline {paragraph}{}{62}{section*.283}% \contentsline {paragraph}{}{62}{section*.284}% \contentsline {paragraph}{}{62}{section*.285}% \contentsline {paragraph}{}{62}{section*.286}% \contentsline {paragraph}{}{62}{section*.287}% \contentsline {paragraph}{}{62}{section*.288}% \contentsline {paragraph}{}{62}{section*.289}% \contentsline {paragraph}{}{62}{section*.290}% \contentsline {paragraph}{}{62}{section*.291}% \contentsline {paragraph}{}{62}{section*.292}% \contentsline {paragraph}{}{62}{section*.293}% \contentsline {paragraph}{}{63}{section*.294}% \contentsline {paragraph}{}{63}{section*.295}% \contentsline {paragraph}{}{63}{section*.296}% \contentsline {paragraph}{}{63}{section*.297}% \contentsline {paragraph}{}{63}{section*.298}% \contentsline {paragraph}{}{63}{section*.299}% \contentsline {paragraph}{}{63}{section*.300}% \contentsline {paragraph}{}{63}{section*.301}% \contentsline {paragraph}{}{63}{section*.302}% \contentsline {paragraph}{}{63}{section*.303}% \contentsline {paragraph}{}{63}{section*.304}% \contentsline {paragraph}{}{63}{section*.305}% \contentsline {paragraph}{}{63}{section*.306}% \contentsline {paragraph}{}{63}{section*.307}% \contentsline {paragraph}{}{63}{section*.308}% \contentsline {paragraph}{}{63}{section*.309}% \contentsline {paragraph}{}{64}{section*.310}% \contentsline {paragraph}{}{64}{section*.311}% \contentsline {paragraph}{}{64}{section*.312}% \contentsline {paragraph}{}{64}{section*.313}% \contentsline {paragraph}{}{64}{section*.314}% \contentsline {paragraph}{}{64}{section*.315}% \contentsline {paragraph}{}{64}{section*.316}% \contentsline {paragraph}{}{64}{section*.317}% \contentsline {paragraph}{}{64}{section*.318}% \contentsline {paragraph}{}{64}{section*.319}% \contentsline {paragraph}{}{64}{section*.320}% \contentsline {paragraph}{}{64}{section*.321}% \contentsline {paragraph}{}{64}{section*.322}% \contentsline {paragraph}{}{64}{section*.323}% \contentsline {paragraph}{}{64}{section*.324}% \contentsline {paragraph}{}{64}{section*.325}% \contentsline {paragraph}{}{65}{section*.326}% \contentsline {paragraph}{}{65}{section*.327}% \contentsline {paragraph}{}{65}{section*.328}% \contentsline {paragraph}{}{65}{section*.329}% \contentsline {paragraph}{}{65}{section*.330}% \contentsline {paragraph}{}{65}{section*.331}% \contentsline {paragraph}{}{65}{section*.332}% \contentsline {paragraph}{}{65}{section*.333}% \contentsline {paragraph}{}{65}{section*.334}% \contentsline {paragraph}{}{65}{section*.335}% \contentsline {paragraph}{}{65}{section*.336}% \contentsline {chapter}{\numberline {B}The SYSTEM Dictionary}{67}{appendix.B}% \contentsline {paragraph}{}{68}{section*.337}% \contentsline {paragraph}{}{68}{section*.338}% \contentsline {paragraph}{}{68}{section*.339}% \contentsline {paragraph}{}{68}{section*.340}% \contentsline {paragraph}{}{68}{section*.341}% \contentsline {paragraph}{}{68}{section*.342}% \contentsline {paragraph}{}{68}{section*.343}% \contentsline {paragraph}{}{68}{section*.344}% \contentsline {paragraph}{}{68}{section*.345}% \contentsline {paragraph}{}{68}{section*.346}% \contentsline {paragraph}{}{68}{section*.347}% \contentsline {paragraph}{}{68}{section*.348}% \contentsline {paragraph}{}{68}{section*.349}% \contentsline {paragraph}{}{68}{section*.350}% \contentsline {paragraph}{}{68}{section*.351}% \contentsline {paragraph}{}{68}{section*.352}% \contentsline {paragraph}{}{69}{section*.353}% \contentsline {paragraph}{}{69}{section*.354}% \contentsline {paragraph}{}{69}{section*.355}% \contentsline {paragraph}{}{69}{section*.356}% \contentsline {paragraph}{}{69}{section*.357}% \contentsline {paragraph}{}{69}{section*.358}% \contentsline {paragraph}{}{69}{section*.359}% \contentsline {paragraph}{}{69}{section*.360}% \contentsline {paragraph}{}{69}{section*.361}% \contentsline {paragraph}{}{69}{section*.362}% \contentsline {paragraph}{}{69}{section*.363}% \contentsline {paragraph}{}{69}{section*.364}% \contentsline {paragraph}{}{69}{section*.365}% \contentsline {paragraph}{}{69}{section*.366}% \contentsline {paragraph}{}{69}{section*.367}% \contentsline {paragraph}{}{69}{section*.368}% \contentsline {paragraph}{}{70}{section*.369}% \contentsline {paragraph}{}{70}{section*.370}% \contentsline {paragraph}{}{70}{section*.371}% \contentsline {paragraph}{}{70}{section*.372}% \contentsline {paragraph}{}{70}{section*.373}% \contentsline {paragraph}{}{70}{section*.374}% \contentsline {paragraph}{}{70}{section*.375}% \contentsline {paragraph}{}{70}{section*.376}% \contentsline {paragraph}{}{70}{section*.377}% \contentsline {paragraph}{}{70}{section*.378}% \contentsline {paragraph}{}{70}{section*.379}% \contentsline {paragraph}{}{70}{section*.380}% \contentsline {paragraph}{}{70}{section*.381}% \contentsline {paragraph}{}{70}{section*.382}% \contentsline {paragraph}{}{70}{section*.383}% \contentsline {paragraph}{}{70}{section*.384}% \contentsline {paragraph}{}{71}{section*.385}% \contentsline {paragraph}{}{71}{section*.386}% \contentsline {paragraph}{}{71}{section*.387}% \contentsline {paragraph}{}{71}{section*.388}% \contentsline {paragraph}{}{71}{section*.389}% \contentsline {paragraph}{}{71}{section*.390}% \contentsline {paragraph}{}{71}{section*.391}% \contentsline {paragraph}{}{71}{section*.392}% \contentsline {paragraph}{}{71}{section*.393}% \contentsline {paragraph}{}{71}{section*.394}% \contentsline {paragraph}{}{71}{section*.395}% \contentsline {paragraph}{}{71}{section*.396}% \contentsline {paragraph}{}{71}{section*.397}% \contentsline {paragraph}{}{71}{section*.398}% \contentsline {paragraph}{}{71}{section*.399}% \contentsline {paragraph}{}{71}{section*.400}% \contentsline {paragraph}{}{72}{section*.401}% \contentsline {paragraph}{}{72}{section*.402}% \contentsline {paragraph}{}{72}{section*.403}% \contentsline {paragraph}{}{72}{section*.404}% \contentsline {paragraph}{}{72}{section*.405}% \contentsline {paragraph}{}{72}{section*.406}% \contentsline {paragraph}{}{72}{section*.407}% \contentsline {paragraph}{}{72}{section*.408}% \contentsline {paragraph}{}{72}{section*.409}% \contentsline {paragraph}{}{72}{section*.410}% \contentsline {paragraph}{}{72}{section*.411}% \contentsline {paragraph}{}{72}{section*.412}% \contentsline {paragraph}{}{72}{section*.413}% \contentsline {paragraph}{}{72}{section*.414}% \contentsline {paragraph}{}{72}{section*.415}% \contentsline {paragraph}{}{73}{section*.416}% \contentsline {paragraph}{}{73}{section*.417}% \contentsline {paragraph}{}{73}{section*.418}% \contentsline {paragraph}{}{73}{section*.419}% \contentsline {paragraph}{}{73}{section*.420}% \contentsline {paragraph}{}{73}{section*.421}% \contentsline {paragraph}{}{73}{section*.422}% \contentsline {paragraph}{}{73}{section*.423}% \contentsline {paragraph}{}{73}{section*.424}% \contentsline {paragraph}{}{73}{section*.425}% \contentsline {paragraph}{}{73}{section*.426}% \contentsline {paragraph}{}{73}{section*.427}% \contentsline {paragraph}{}{73}{section*.428}% \contentsline {paragraph}{}{73}{section*.429}% \contentsline {paragraph}{}{74}{section*.430}% \contentsline {paragraph}{}{74}{section*.431}% \contentsline {paragraph}{}{74}{section*.432}% \contentsline {paragraph}{}{74}{section*.433}% \contentsline {paragraph}{}{74}{section*.434}% \contentsline {paragraph}{}{74}{section*.435}% \contentsline {paragraph}{}{74}{section*.436}% \contentsline {paragraph}{}{74}{section*.437}% \contentsline {paragraph}{}{74}{section*.438}% \contentsline {paragraph}{}{74}{section*.439}% \contentsline {paragraph}{}{74}{section*.440}% \contentsline {paragraph}{}{74}{section*.441}% \contentsline {paragraph}{}{74}{section*.442}% \contentsline {paragraph}{}{74}{section*.443}% \contentsline {paragraph}{}{74}{section*.444}% \contentsline {paragraph}{}{74}{section*.445}% \contentsline {paragraph}{}{75}{section*.446}% \contentsline {paragraph}{}{75}{section*.447}% \contentsline {paragraph}{}{75}{section*.448}% \contentsline {paragraph}{}{75}{section*.449}% \contentsline {paragraph}{}{75}{section*.450}% \contentsline {paragraph}{}{75}{section*.451}% \contentsline {paragraph}{}{75}{section*.452}% \contentsline {paragraph}{}{75}{section*.453}% \contentsline {paragraph}{}{75}{section*.454}% \contentsline {paragraph}{}{75}{section*.455}% \contentsline {paragraph}{}{75}{section*.456}% \contentsline {paragraph}{}{75}{section*.457}% \contentsline {paragraph}{}{75}{section*.458}% \contentsline {paragraph}{}{75}{section*.459}% \contentsline {paragraph}{}{76}{section*.460}% \contentsline {paragraph}{}{76}{section*.461}% \contentsline {paragraph}{}{76}{section*.462}% \contentsline {paragraph}{}{76}{section*.463}% \contentsline {paragraph}{}{76}{section*.464}% \contentsline {paragraph}{}{76}{section*.465}% \contentsline {paragraph}{}{76}{section*.466}% \contentsline {paragraph}{}{76}{section*.467}% \contentsline {paragraph}{}{76}{section*.468}% \contentsline {paragraph}{}{76}{section*.469}% \contentsline {paragraph}{}{76}{section*.470}% \contentsline {paragraph}{}{76}{section*.471}% \contentsline {paragraph}{}{76}{section*.472}% \contentsline {paragraph}{}{76}{section*.473}% \contentsline {paragraph}{}{76}{section*.474}% \contentsline {paragraph}{}{76}{section*.475}% \contentsline {paragraph}{}{77}{section*.476}% \contentsline {paragraph}{}{77}{section*.477}% \contentsline {paragraph}{}{77}{section*.478}% \contentsline {paragraph}{}{77}{section*.479}% \contentsline {paragraph}{}{77}{section*.480}% \contentsline {paragraph}{}{77}{section*.481}% \contentsline {paragraph}{}{77}{section*.482}% \contentsline {paragraph}{}{77}{section*.483}% \contentsline {paragraph}{}{77}{section*.484}% \contentsline {paragraph}{}{77}{section*.485}% \contentsline {paragraph}{}{77}{section*.486}% \contentsline {paragraph}{}{77}{section*.487}% \contentsline {paragraph}{}{77}{section*.488}% \contentsline {paragraph}{}{77}{section*.489}% \contentsline {paragraph}{}{77}{section*.490}% \contentsline {paragraph}{}{78}{section*.491}% \contentsline {paragraph}{}{78}{section*.492}% \contentsline {paragraph}{}{78}{section*.493}% \contentsline {paragraph}{}{78}{section*.494}% \contentsline {paragraph}{}{78}{section*.495}% \contentsline {paragraph}{}{78}{section*.496}% \contentsline {paragraph}{}{78}{section*.497}% \contentsline {paragraph}{}{78}{section*.498}% \contentsline {paragraph}{}{78}{section*.499}% \contentsline {paragraph}{}{78}{section*.500}% \contentsline {paragraph}{}{78}{section*.501}% \contentsline {paragraph}{}{78}{section*.502}% \contentsline {paragraph}{}{78}{section*.503}% \contentsline {paragraph}{}{78}{section*.504}% \contentsline {paragraph}{}{78}{section*.505}% \contentsline {paragraph}{}{78}{section*.506}% \contentsline {paragraph}{}{79}{section*.507}% \contentsline {paragraph}{}{79}{section*.508}% \contentsline {paragraph}{}{79}{section*.509}% \contentsline {paragraph}{}{79}{section*.510}% \contentsline {paragraph}{}{79}{section*.511}% \contentsline {paragraph}{}{79}{section*.512}% \contentsline {paragraph}{}{79}{section*.513}% \contentsline {paragraph}{}{79}{section*.514}% \contentsline {paragraph}{}{79}{section*.515}% \contentsline {paragraph}{}{79}{section*.516}% \contentsline {paragraph}{}{79}{section*.517}% \contentsline {paragraph}{}{79}{section*.518}% \contentsline {paragraph}{}{79}{section*.519}% \contentsline {paragraph}{}{79}{section*.520}% \contentsline {paragraph}{}{79}{section*.521}% \contentsline {paragraph}{}{79}{section*.522}% \contentsline {paragraph}{}{80}{section*.523}% \contentsline {paragraph}{}{80}{section*.524}% \contentsline {paragraph}{}{80}{section*.525}% \contentsline {paragraph}{}{80}{section*.526}% \contentsline {paragraph}{}{80}{section*.527}% \contentsline {paragraph}{}{80}{section*.528}% \contentsline {paragraph}{}{80}{section*.529}% \contentsline {paragraph}{}{80}{section*.530}% \contentsline {paragraph}{}{80}{section*.531}% \contentsline {paragraph}{}{80}{section*.532}% \contentsline {paragraph}{}{80}{section*.533}% \contentsline {paragraph}{}{80}{section*.534}% \contentsline {paragraph}{}{80}{section*.535}% \contentsline {paragraph}{}{80}{section*.536}% \contentsline {paragraph}{}{80}{section*.537}% \contentsline {paragraph}{}{81}{section*.538}% \contentsline {paragraph}{}{81}{section*.539}% \contentsline {paragraph}{}{81}{section*.540}% \contentsline {paragraph}{}{81}{section*.541}% \contentsline {paragraph}{}{81}{section*.542}% \contentsline {paragraph}{}{81}{section*.543}% \contentsline {paragraph}{}{81}{section*.544}% \contentsline {paragraph}{}{81}{section*.545}% \contentsline {paragraph}{}{81}{section*.546}% \contentsline {paragraph}{}{81}{section*.547}% \contentsline {paragraph}{}{81}{section*.548}% \contentsline {paragraph}{}{81}{section*.549}% \contentsline {paragraph}{}{81}{section*.550}% \contentsline {paragraph}{}{81}{section*.551}% \contentsline {paragraph}{}{81}{section*.552}% \contentsline {paragraph}{}{81}{section*.553}% \contentsline {paragraph}{}{82}{section*.554}% \contentsline {paragraph}{}{82}{section*.555}% \contentsline {paragraph}{}{82}{section*.556}% \contentsline {paragraph}{}{82}{section*.557}% \contentsline {paragraph}{}{82}{section*.558}% \contentsline {paragraph}{}{82}{section*.559}% \contentsline {paragraph}{}{82}{section*.560}% \contentsline {paragraph}{}{82}{section*.561}% \contentsline {paragraph}{}{82}{section*.562}% \contentsline {paragraph}{}{82}{section*.563}% \contentsline {paragraph}{}{82}{section*.564}% \contentsline {paragraph}{}{82}{section*.565}% \contentsline {paragraph}{}{82}{section*.566}% \contentsline {paragraph}{}{82}{section*.567}% \contentsline {paragraph}{}{82}{section*.568}% \contentsline {paragraph}{}{82}{section*.569}% \contentsline {paragraph}{}{83}{section*.570}% \contentsline {paragraph}{}{83}{section*.571}% \contentsline {paragraph}{}{83}{section*.572}% \contentsline {paragraph}{}{83}{section*.573}% \contentsline {paragraph}{}{83}{section*.574}% \contentsline {paragraph}{}{83}{section*.575}% \contentsline {paragraph}{}{83}{section*.576}% \contentsline {paragraph}{}{83}{section*.577}% \contentsline {paragraph}{}{83}{section*.578}% \contentsline {paragraph}{}{83}{section*.579}% \contentsline {paragraph}{}{83}{section*.580}% \contentsline {paragraph}{}{83}{section*.581}% \contentsline {paragraph}{}{83}{section*.582}% \contentsline {paragraph}{}{83}{section*.583}% \contentsline {paragraph}{}{83}{section*.584}% \contentsline {paragraph}{}{84}{section*.585}% \contentsline {paragraph}{}{84}{section*.586}% \contentsline {paragraph}{}{84}{section*.587}% \contentsline {paragraph}{}{84}{section*.588}% \contentsline {paragraph}{}{84}{section*.589}% \contentsline {paragraph}{}{85}{section*.590}% \contentsline {paragraph}{}{85}{section*.591}% \contentsline {paragraph}{}{85}{section*.592}% \contentsline {paragraph}{}{85}{section*.593}% \contentsline {paragraph}{}{85}{section*.594}% \contentsline {paragraph}{}{85}{section*.595}% \contentsline {paragraph}{}{85}{section*.596}% \contentsline {paragraph}{}{86}{section*.597}% \contentsline {paragraph}{}{86}{section*.598}% \contentsline {paragraph}{}{86}{section*.599}% \contentsline {paragraph}{}{86}{section*.600}% \contentsline {paragraph}{}{86}{section*.601}% \contentsline {paragraph}{}{86}{section*.602}% \contentsline {paragraph}{}{86}{section*.603}% \contentsline {paragraph}{}{86}{section*.604}% \contentsline {paragraph}{}{86}{section*.605}% \contentsline {paragraph}{}{86}{section*.606}% \contentsline {paragraph}{}{86}{section*.607}% \contentsline {paragraph}{}{86}{section*.608}% \contentsline {paragraph}{}{86}{section*.609}% \contentsline {paragraph}{}{86}{section*.610}% \contentsline {paragraph}{}{86}{section*.611}% \contentsline {paragraph}{}{86}{section*.612}% \contentsline {paragraph}{}{87}{section*.613}% \contentsline {paragraph}{}{87}{section*.614}% \contentsline {paragraph}{}{87}{section*.615}% \contentsline {paragraph}{}{87}{section*.616}% \contentsline {paragraph}{}{87}{section*.617}% \contentsline {paragraph}{}{87}{section*.618}% \contentsline {paragraph}{}{87}{section*.619}% \contentsline {paragraph}{}{87}{section*.620}% \contentsline {paragraph}{}{87}{section*.621}% \contentsline {paragraph}{}{87}{section*.622}% \contentsline {paragraph}{}{87}{section*.623}% \contentsline {paragraph}{}{87}{section*.624}% \contentsline {paragraph}{}{87}{section*.625}% \contentsline {paragraph}{}{87}{section*.626}% \contentsline {paragraph}{}{87}{section*.627}% \contentsline {paragraph}{}{87}{section*.628}% \contentsline {paragraph}{}{88}{section*.629}% \contentsline {paragraph}{}{88}{section*.630}% \contentsline {paragraph}{}{88}{section*.631}% \contentsline {chapter}{\numberline {C}The JSS Dictionary}{89}{appendix.C}% \contentsline {paragraph}{}{90}{section*.632}% \contentsline {paragraph}{}{90}{section*.633}% \contentsline {paragraph}{}{90}{section*.634}% \contentsline {paragraph}{}{90}{section*.635}% \contentsline {paragraph}{}{90}{section*.636}% \contentsline {paragraph}{}{90}{section*.637}% \contentsline {paragraph}{}{90}{section*.638}% \contentsline {paragraph}{}{90}{section*.639}% \contentsline {paragraph}{}{90}{section*.640}% \contentsline {paragraph}{}{90}{section*.641}% \contentsline {paragraph}{}{90}{section*.642}% \contentsline {paragraph}{}{90}{section*.643}% \contentsline {paragraph}{}{91}{section*.644}% \contentsline {paragraph}{}{91}{section*.645}% \contentsline {paragraph}{}{91}{section*.646}% \contentsline {paragraph}{}{91}{section*.647}% \contentsline {paragraph}{}{91}{section*.648}% \contentsline {paragraph}{}{91}{section*.649}% \contentsline {paragraph}{}{91}{section*.650}% \contentsline {paragraph}{}{91}{section*.651}% \contentsline {paragraph}{}{91}{section*.652}% \contentsline {paragraph}{}{91}{section*.653}% \contentsline {paragraph}{}{91}{section*.654}% \contentsline {paragraph}{}{92}{section*.655}% \contentsline {paragraph}{}{92}{section*.656}% \contentsline {paragraph}{}{92}{section*.657}% \contentsline {paragraph}{}{92}{section*.658}% \contentsline {paragraph}{}{92}{section*.659}% \contentsline {paragraph}{}{92}{section*.660}% abcl-src-1.9.0/doc/manual/extensions.aux0100644 0000000 0000000 00000047234 14242630063 016710 0ustar000000000 0000000 \relax \providecommand\hyper@newdestlabel[2]{} \newlabel{EXTENSIONS:CADDR}{{3.4.3}{33}{}{section*.120}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.120}\protected@file@percent } \newlabel{EXTENSIONS:CADR}{{3.4.3}{33}{}{section*.121}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.121}\protected@file@percent } \newlabel{EXTENSIONS:CAR}{{3.4.3}{33}{}{section*.122}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.122}\protected@file@percent } \newlabel{EXTENSIONS:CDR}{{3.4.3}{33}{}{section*.123}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.123}\protected@file@percent } \newlabel{EXTENSIONS:*AUTOLOAD-VERBOSE*}{{3.4.3}{33}{}{section*.124}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.124}\protected@file@percent } \newlabel{EXTENSIONS:*BATCH-MODE*}{{3.4.3}{33}{}{section*.125}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.125}\protected@file@percent } \newlabel{EXTENSIONS:*COMMAND-LINE-ARGUMENT-LIST*}{{3.4.3}{33}{}{section*.126}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.126}\protected@file@percent } \newlabel{EXTENSIONS:*DEBUG-CONDITION*}{{3.4.3}{33}{}{section*.127}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.127}\protected@file@percent } \newlabel{EXTENSIONS:*DEBUG-LEVEL*}{{3.4.3}{33}{}{section*.128}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.128}\protected@file@percent } \newlabel{EXTENSIONS:*DISASSEMBLER*}{{3.4.3}{33}{}{section*.129}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.129}\protected@file@percent } \newlabel{EXTENSIONS:*ED-FUNCTIONS*}{{3.4.3}{33}{}{section*.130}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.130}\protected@file@percent } \newlabel{EXTENSIONS:*ENABLE-INLINE-EXPANSION*}{{3.4.3}{33}{}{section*.131}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.131}\protected@file@percent } \newlabel{EXTENSIONS:*INSPECTOR-HOOK*}{{3.4.3}{33}{}{section*.132}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.132}\protected@file@percent } \newlabel{EXTENSIONS:*LISP-HOME*}{{3.4.3}{33}{}{section*.133}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.133}\protected@file@percent } \newlabel{EXTENSIONS:*LOAD-TRUENAME-FASL*}{{3.4.3}{33}{}{section*.134}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.134}\protected@file@percent } \newlabel{EXTENSIONS:*PRINT-STRUCTURE*}{{3.4.3}{33}{}{section*.135}{}} \@writefile{toc}{\contentsline {paragraph}{}{33}{section*.135}\protected@file@percent } \newlabel{EXTENSIONS:*REQUIRE-STACK-FRAME*}{{3.4.3}{34}{}{section*.136}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.136}\protected@file@percent } \newlabel{EXTENSIONS:*SAVED-BACKTRACE*}{{3.4.3}{34}{}{section*.137}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.137}\protected@file@percent } \newlabel{EXTENSIONS:*SUPPRESS-COMPILER-WARNINGS*}{{3.4.3}{34}{}{section*.138}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.138}\protected@file@percent } \newlabel{EXTENSIONS:*WARN-ON-REDEFINITION*}{{3.4.3}{34}{}{section*.139}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.139}\protected@file@percent } \newlabel{EXTENSIONS:ADD-PACKAGE-LOCAL-NICKNAME}{{3.4.3}{34}{}{section*.140}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.140}\protected@file@percent } \newlabel{EXTENSIONS:ADJOIN-EQL}{{3.4.3}{34}{}{section*.141}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.141}\protected@file@percent } \newlabel{EXTENSIONS:ARGLIST}{{3.4.3}{34}{}{section*.142}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.142}\protected@file@percent } \newlabel{EXTENSIONS:AS-JAR-PATHNAME-ARCHIVE}{{3.4.3}{34}{}{section*.143}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.143}\protected@file@percent } \newlabel{EXTENSIONS:ASSQ}{{3.4.3}{34}{}{section*.144}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.144}\protected@file@percent } \newlabel{EXTENSIONS:ASSQL}{{3.4.3}{34}{}{section*.145}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.145}\protected@file@percent } \newlabel{EXTENSIONS:AUTOLOAD}{{3.4.3}{34}{}{section*.146}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.146}\protected@file@percent } \newlabel{EXTENSIONS:AUTOLOAD-MACRO}{{3.4.3}{34}{}{section*.147}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.147}\protected@file@percent } \newlabel{EXTENSIONS:AUTOLOAD-REF-P}{{3.4.3}{34}{}{section*.148}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.148}\protected@file@percent } \newlabel{EXTENSIONS:AUTOLOAD-SETF-EXPANDER}{{3.4.3}{34}{}{section*.149}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.149}\protected@file@percent } \newlabel{EXTENSIONS:AUTOLOAD-SETF-FUNCTION}{{3.4.3}{34}{}{section*.150}{}} \@writefile{toc}{\contentsline {paragraph}{}{34}{section*.150}\protected@file@percent } \newlabel{EXTENSIONS:AUTOLOADP}{{3.4.3}{35}{}{section*.151}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.151}\protected@file@percent } \newlabel{EXTENSIONS:CANCEL-FINALIZATION}{{3.4.3}{35}{}{section*.152}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.152}\protected@file@percent } \newlabel{EXTENSIONS:CHAR-TO-UTF8}{{3.4.3}{35}{}{section*.153}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.153}\protected@file@percent } \newlabel{EXTENSIONS:CHARPOS}{{3.4.3}{35}{}{section*.154}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.154}\protected@file@percent } \newlabel{EXTENSIONS:CLASSP}{{3.4.3}{35}{}{section*.155}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.155}\protected@file@percent } \newlabel{EXTENSIONS:COLLECT}{{3.4.3}{35}{}{section*.156}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.156}\protected@file@percent } \newlabel{EXTENSIONS:COMPILE-SYSTEM}{{3.4.3}{35}{}{section*.157}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.157}\protected@file@percent } \newlabel{EXTENSIONS:DOUBLE-FLOAT-NEGATIVE-INFINITY}{{3.4.3}{35}{}{section*.158}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.158}\protected@file@percent } \newlabel{EXTENSIONS:DOUBLE-FLOAT-POSITIVE-INFINITY}{{3.4.3}{35}{}{section*.159}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.159}\protected@file@percent } \newlabel{EXTENSIONS:DUMP-JAVA-STACK}{{3.4.3}{35}{}{section*.160}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.160}\protected@file@percent } \newlabel{EXTENSIONS:EXIT}{{3.4.3}{35}{}{section*.161}{}} \@writefile{toc}{\contentsline {paragraph}{}{35}{section*.161}\protected@file@percent } \newlabel{EXTENSIONS:FEATUREP}{{3.4.3}{36}{}{section*.162}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.162}\protected@file@percent } \newlabel{EXTENSIONS:FILE-DIRECTORY-P}{{3.4.3}{36}{}{section*.163}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.163}\protected@file@percent } \newlabel{EXTENSIONS:FINALIZE}{{3.4.3}{36}{}{section*.164}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.164}\protected@file@percent } \newlabel{EXTENSIONS:FIXNUMP}{{3.4.3}{36}{}{section*.165}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.165}\protected@file@percent } \newlabel{EXTENSIONS:GC}{{3.4.3}{36}{}{section*.166}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.166}\protected@file@percent } \newlabel{EXTENSIONS:GET-FLOATING-POINT-MODES}{{3.4.3}{36}{}{section*.167}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.167}\protected@file@percent } \newlabel{EXTENSIONS:GET-PID}{{3.4.3}{36}{}{section*.168}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.168}\protected@file@percent } \newlabel{EXTENSIONS:GET-SOCKET-STREAM}{{3.4.3}{36}{}{section*.169}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.169}\protected@file@percent } \newlabel{EXTENSIONS:GET-TIME-ZONE}{{3.4.3}{36}{}{section*.170}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.170}\protected@file@percent } \newlabel{EXTENSIONS:GETENV}{{3.4.3}{36}{}{section*.171}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.171}\protected@file@percent } \newlabel{EXTENSIONS:GETENV-ALL}{{3.4.3}{36}{}{section*.172}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.172}\protected@file@percent } \newlabel{EXTENSIONS:INIT-GUI}{{3.4.3}{36}{}{section*.173}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.173}\protected@file@percent } \newlabel{EXTENSIONS:INTERRUPT-LISP}{{3.4.3}{36}{}{section*.174}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.174}\protected@file@percent } \newlabel{EXTENSIONS:JAR-PATHNAME}{{3.4.3}{36}{}{section*.175}{}} \@writefile{toc}{\contentsline {paragraph}{}{36}{section*.175}\protected@file@percent } \newlabel{EXTENSIONS:MACROEXPAND-ALL}{{3.4.3}{37}{}{section*.176}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.176}\protected@file@percent } \newlabel{EXTENSIONS:MAILBOX}{{3.4.3}{37}{}{section*.177}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.177}\protected@file@percent } \newlabel{EXTENSIONS:MAKE-DIALOG-PROMPT-STREAM}{{3.4.3}{37}{}{section*.178}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.178}\protected@file@percent } \newlabel{EXTENSIONS:MAKE-SERVER-SOCKET}{{3.4.3}{37}{}{section*.179}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.179}\protected@file@percent } \newlabel{EXTENSIONS:MAKE-SLIME-INPUT-STREAM}{{3.4.3}{37}{}{section*.180}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.180}\protected@file@percent } \newlabel{EXTENSIONS:MAKE-SLIME-OUTPUT-STREAM}{{3.4.3}{37}{}{section*.181}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.181}\protected@file@percent } \newlabel{EXTENSIONS:MAKE-SOCKET}{{3.4.3}{37}{}{section*.182}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.182}\protected@file@percent } \newlabel{EXTENSIONS:MAKE-TEMP-DIRECTORY}{{3.4.3}{37}{}{section*.183}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.183}\protected@file@percent } \newlabel{EXTENSIONS:MAKE-TEMP-FILE}{{3.4.3}{37}{}{section*.184}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.184}\protected@file@percent } \newlabel{EXTENSIONS:MAKE-WEAK-REFERENCE}{{3.4.3}{37}{}{section*.185}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.185}\protected@file@percent } \newlabel{EXTENSIONS:MEMQ}{{3.4.3}{37}{}{section*.186}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.186}\protected@file@percent } \newlabel{EXTENSIONS:MEMQL}{{3.4.3}{37}{}{section*.187}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.187}\protected@file@percent } \newlabel{EXTENSIONS:MOST-NEGATIVE-JAVA-LONG}{{3.4.3}{37}{}{section*.188}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.188}\protected@file@percent } \newlabel{EXTENSIONS:MOST-POSITIVE-JAVA-LONG}{{3.4.3}{37}{}{section*.189}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.189}\protected@file@percent } \newlabel{EXTENSIONS:MUTEX}{{3.4.3}{37}{}{section*.190}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.190}\protected@file@percent } \newlabel{EXTENSIONS:NEQ}{{3.4.3}{37}{}{section*.191}{}} \@writefile{toc}{\contentsline {paragraph}{}{37}{section*.191}\protected@file@percent } \newlabel{EXTENSIONS:NIL-VECTOR}{{3.4.3}{38}{}{section*.192}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.192}\protected@file@percent } \newlabel{EXTENSIONS:OS-UNIX-P}{{3.4.3}{38}{}{section*.193}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.193}\protected@file@percent } \newlabel{EXTENSIONS:OS-WINDOWS-P}{{3.4.3}{38}{}{section*.194}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.194}\protected@file@percent } \newlabel{EXTENSIONS:PACKAGE-LOCAL-NICKNAMES}{{3.4.3}{38}{}{section*.195}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.195}\protected@file@percent } \newlabel{EXTENSIONS:PACKAGE-LOCALLY-NICKNAMED-BY-LIST}{{3.4.3}{38}{}{section*.196}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.196}\protected@file@percent } \newlabel{EXTENSIONS:PATHNAME-JAR-P}{{3.4.3}{38}{}{section*.197}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.197}\protected@file@percent } \newlabel{EXTENSIONS:PATHNAME-URL-P}{{3.4.3}{38}{}{section*.198}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.198}\protected@file@percent } \newlabel{EXTENSIONS:PRECOMPILE}{{3.4.3}{38}{}{section*.199}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.199}\protected@file@percent } \newlabel{EXTENSIONS:PROBE-DIRECTORY}{{3.4.3}{38}{}{section*.200}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.200}\protected@file@percent } \newlabel{EXTENSIONS:QUIT}{{3.4.3}{38}{}{section*.201}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.201}\protected@file@percent } \newlabel{EXTENSIONS:READ-CLASS}{{3.4.3}{38}{}{section*.202}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.202}\protected@file@percent } \newlabel{EXTENSIONS:READ-TIMEOUT}{{3.4.3}{38}{}{section*.203}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.203}\protected@file@percent } \newlabel{EXTENSIONS:REMOVE-PACKAGE-LOCAL-NICKNAME}{{3.4.3}{38}{}{section*.204}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.204}\protected@file@percent } \newlabel{EXTENSIONS:RESOLVE}{{3.4.3}{38}{}{section*.205}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.205}\protected@file@percent } \newlabel{EXTENSIONS:RUN-SHELL-COMMAND}{{3.4.3}{38}{}{section*.206}{}} \@writefile{toc}{\contentsline {paragraph}{}{38}{section*.206}\protected@file@percent } \newlabel{EXTENSIONS:SERVER-SOCKET-CLOSE}{{3.4.3}{39}{}{section*.207}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.207}\protected@file@percent } \newlabel{EXTENSIONS:SET-FLOATING-POINT-MODES}{{3.4.3}{39}{}{section*.208}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.208}\protected@file@percent } \newlabel{EXTENSIONS:SHOW-RESTARTS}{{3.4.3}{39}{}{section*.209}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.209}\protected@file@percent } \newlabel{EXTENSIONS:SIMPLE-STRING-FILL}{{3.4.3}{39}{}{section*.210}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.210}\protected@file@percent } \newlabel{EXTENSIONS:SIMPLE-STRING-SEARCH}{{3.4.3}{39}{}{section*.211}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.211}\protected@file@percent } \newlabel{EXTENSIONS:SINGLE-FLOAT-NEGATIVE-INFINITY}{{3.4.3}{39}{}{section*.212}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.212}\protected@file@percent } \newlabel{EXTENSIONS:SINGLE-FLOAT-POSITIVE-INFINITY}{{3.4.3}{39}{}{section*.213}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.213}\protected@file@percent } \newlabel{EXTENSIONS:SLIME-INPUT-STREAM}{{3.4.3}{39}{}{section*.214}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.214}\protected@file@percent } \newlabel{EXTENSIONS:SLIME-OUTPUT-STREAM}{{3.4.3}{39}{}{section*.215}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.215}\protected@file@percent } \newlabel{EXTENSIONS:SOCKET-ACCEPT}{{3.4.3}{39}{}{section*.216}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.216}\protected@file@percent } \newlabel{EXTENSIONS:SOCKET-CLOSE}{{3.4.3}{39}{}{section*.217}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.217}\protected@file@percent } \newlabel{EXTENSIONS:SOCKET-LOCAL-ADDRESS}{{3.4.3}{39}{}{section*.218}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.218}\protected@file@percent } \newlabel{EXTENSIONS:SOCKET-LOCAL-PORT}{{3.4.3}{39}{}{section*.219}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.219}\protected@file@percent } \newlabel{EXTENSIONS:SOCKET-PEER-ADDRESS}{{3.4.3}{39}{}{section*.220}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.220}\protected@file@percent } \newlabel{EXTENSIONS:SOCKET-PEER-PORT}{{3.4.3}{39}{}{section*.221}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.221}\protected@file@percent } \newlabel{EXTENSIONS:SOURCE}{{3.4.3}{39}{}{section*.222}{}} \@writefile{toc}{\contentsline {paragraph}{}{39}{section*.222}\protected@file@percent } \newlabel{EXTENSIONS:SOURCE-FILE-POSITION}{{3.4.3}{40}{}{section*.223}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.223}\protected@file@percent } \newlabel{EXTENSIONS:SOURCE-PATHNAME}{{3.4.3}{40}{}{section*.224}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.224}\protected@file@percent } \newlabel{EXTENSIONS:SPECIAL-VARIABLE-P}{{3.4.3}{40}{}{section*.225}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.225}\protected@file@percent } \newlabel{EXTENSIONS:STREAM-UNIX-FD}{{3.4.3}{40}{}{section*.226}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.226}\protected@file@percent } \newlabel{EXTENSIONS:STRING-FIND}{{3.4.3}{40}{}{section*.227}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.227}\protected@file@percent } \newlabel{EXTENSIONS:STRING-INPUT-STREAM-CURRENT}{{3.4.3}{40}{}{section*.228}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.228}\protected@file@percent } \newlabel{EXTENSIONS:STRING-POSITION}{{3.4.3}{40}{}{section*.229}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.229}\protected@file@percent } \newlabel{EXTENSIONS:STYLE-WARN}{{3.4.3}{40}{}{section*.230}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.230}\protected@file@percent } \newlabel{EXTENSIONS:TRULY-THE}{{3.4.3}{40}{}{section*.231}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.231}\protected@file@percent } \newlabel{EXTENSIONS:UPTIME}{{3.4.3}{40}{}{section*.232}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.232}\protected@file@percent } \newlabel{EXTENSIONS:URI-DECODE}{{3.4.3}{40}{}{section*.233}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.233}\protected@file@percent } \newlabel{EXTENSIONS:URI-ENCODE}{{3.4.3}{40}{}{section*.234}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.234}\protected@file@percent } \newlabel{EXTENSIONS:URL-PATHNAME}{{3.4.3}{40}{}{section*.235}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.235}\protected@file@percent } \newlabel{EXTENSIONS:URL-PATHNAME-AUTHORITY}{{3.4.3}{40}{}{section*.236}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.236}\protected@file@percent } \newlabel{EXTENSIONS:URL-PATHNAME-FRAGMENT}{{3.4.3}{40}{}{section*.237}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.237}\protected@file@percent } \newlabel{EXTENSIONS:URL-PATHNAME-QUERY}{{3.4.3}{40}{}{section*.238}{}} \@writefile{toc}{\contentsline {paragraph}{}{40}{section*.238}\protected@file@percent } \newlabel{EXTENSIONS:URL-PATHNAME-SCHEME}{{3.4.3}{41}{}{section*.239}{}} \@writefile{toc}{\contentsline {paragraph}{}{41}{section*.239}\protected@file@percent } \newlabel{EXTENSIONS:WEAK-REFERENCE}{{3.4.3}{41}{}{section*.240}{}} \@writefile{toc}{\contentsline {paragraph}{}{41}{section*.240}\protected@file@percent } \newlabel{EXTENSIONS:WEAK-REFERENCE-VALUE}{{3.4.3}{41}{}{section*.241}{}} \@writefile{toc}{\contentsline {paragraph}{}{41}{section*.241}\protected@file@percent } \newlabel{EXTENSIONS:WRITE-CLASS}{{3.4.3}{41}{}{section*.242}{}} \@writefile{toc}{\contentsline {paragraph}{}{41}{section*.242}\protected@file@percent } \newlabel{EXTENSIONS:WRITE-TIMEOUT}{{3.4.3}{41}{}{section*.243}{}} \@writefile{toc}{\contentsline {paragraph}{}{41}{section*.243}\protected@file@percent } \@setckpt{extensions}{ \setcounter{page}{42} \setcounter{equation}{0} \setcounter{enumi}{0} \setcounter{enumii}{0} \setcounter{enumiii}{0} \setcounter{enumiv}{0} \setcounter{footnote}{2} \setcounter{mpfootnote}{0} \setcounter{part}{0} \setcounter{chapter}{3} \setcounter{section}{4} \setcounter{subsection}{3} \setcounter{subsubsection}{0} \setcounter{paragraph}{0} \setcounter{subparagraph}{0} \setcounter{figure}{0} \setcounter{table}{0} \setcounter{Item}{0} \setcounter{Hfootnote}{13} \setcounter{bookmark@seq@number}{36} \setcounter{lstnumber}{2} \setcounter{cp@cntr}{0} \setcounter{section@level}{4} \setcounter{lstlisting}{0} } abcl-src-1.9.0/doc/manual/extensions.tex0100644 0000000 0000000 00000072514 14242627550 016721 0ustar000000000 0000000 \paragraph{} \label{EXTENSIONS:CADDR} \index{CADDR} --- Macro: \textbf{\%caddr} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:CADR} \index{CADR} --- Macro: \textbf{\%cadr} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:CAR} \index{CAR} --- Macro: \textbf{\%car} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:CDR} \index{CDR} --- Macro: \textbf{\%cdr} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*AUTOLOAD-VERBOSE*} \index{*AUTOLOAD-VERBOSE*} --- Variable: \textbf{*autoload-verbose*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*BATCH-MODE*} \index{*BATCH-MODE*} --- Variable: \textbf{*batch-mode*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*COMMAND-LINE-ARGUMENT-LIST*} \index{*COMMAND-LINE-ARGUMENT-LIST*} --- Variable: \textbf{*command-line-argument-list*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*DEBUG-CONDITION*} \index{*DEBUG-CONDITION*} --- Variable: \textbf{*debug-condition*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*DEBUG-LEVEL*} \index{*DEBUG-LEVEL*} --- Variable: \textbf{*debug-level*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*DISASSEMBLER*} \index{*DISASSEMBLER*} --- Variable: \textbf{*disassembler*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*ED-FUNCTIONS*} \index{*ED-FUNCTIONS*} --- Variable: \textbf{*ed-functions*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*ENABLE-INLINE-EXPANSION*} \index{*ENABLE-INLINE-EXPANSION*} --- Variable: \textbf{*enable-inline-expansion*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*INSPECTOR-HOOK*} \index{*INSPECTOR-HOOK*} --- Variable: \textbf{*inspector-hook*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*LISP-HOME*} \index{*LISP-HOME*} --- Variable: \textbf{*lisp-home*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*LOAD-TRUENAME-FASL*} \index{*LOAD-TRUENAME-FASL*} --- Variable: \textbf{*load-truename-fasl*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*PRINT-STRUCTURE*} \index{*PRINT-STRUCTURE*} --- Variable: \textbf{*print-structure*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*REQUIRE-STACK-FRAME*} \index{*REQUIRE-STACK-FRAME*} --- Variable: \textbf{*require-stack-frame*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*SAVED-BACKTRACE*} \index{*SAVED-BACKTRACE*} --- Variable: \textbf{*saved-backtrace*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*SUPPRESS-COMPILER-WARNINGS*} \index{*SUPPRESS-COMPILER-WARNINGS*} --- Variable: \textbf{*suppress-compiler-warnings*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:*WARN-ON-REDEFINITION*} \index{*WARN-ON-REDEFINITION*} --- Variable: \textbf{*warn-on-redefinition*} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:ADD-PACKAGE-LOCAL-NICKNAME} \index{ADD-PACKAGE-LOCAL-NICKNAME} --- Function: \textbf{add-package-local-nickname} [\textbf{extensions}] \textit{local-nickname actual-package \&optional (package-designator *package*)} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:ADJOIN-EQL} \index{ADJOIN-EQL} --- Function: \textbf{adjoin-eql} [\textbf{extensions}] \textit{item list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:ARGLIST} \index{ARGLIST} --- Function: \textbf{arglist} [\textbf{extensions}] \textit{extended-function-designator} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:AS-JAR-PATHNAME-ARCHIVE} \index{AS-JAR-PATHNAME-ARCHIVE} --- Function: \textbf{as-jar-pathname-archive} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:ASSQ} \index{ASSQ} --- Function: \textbf{assq} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:ASSQL} \index{ASSQL} --- Function: \textbf{assql} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:AUTOLOAD} \index{AUTOLOAD} --- Function: \textbf{autoload} [\textbf{extensions}] \textit{symbol-or-symbols \&optional filename} \begin{adjustwidth}{5em}{5em} Setup the autoload for SYMBOL-OR-SYMBOLS optionally corresponding to FILENAME. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:AUTOLOAD-MACRO} \index{AUTOLOAD-MACRO} --- Function: \textbf{autoload-macro} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:AUTOLOAD-REF-P} \index{AUTOLOAD-REF-P} --- Function: \textbf{autoload-ref-p} [\textbf{extensions}] \textit{symbol} \begin{adjustwidth}{5em}{5em} Boolean predicate for whether SYMBOL has generalized reference functions which need to be resolved. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:AUTOLOAD-SETF-EXPANDER} \index{AUTOLOAD-SETF-EXPANDER} --- Function: \textbf{autoload-setf-expander} [\textbf{extensions}] \textit{symbol-or-symbols filename} \begin{adjustwidth}{5em}{5em} Setup the autoload for SYMBOL-OR-SYMBOLS on the setf-expander from FILENAME. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:AUTOLOAD-SETF-FUNCTION} \index{AUTOLOAD-SETF-FUNCTION} --- Function: \textbf{autoload-setf-function} [\textbf{extensions}] \textit{symbol-or-symbols filename} \begin{adjustwidth}{5em}{5em} Setup the autoload for SYMBOL-OR-SYMBOLS on the setf-function from FILENAME. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:AUTOLOADP} \index{AUTOLOADP} --- Function: \textbf{autoloadp} [\textbf{extensions}] \textit{symbol} \begin{adjustwidth}{5em}{5em} Boolean predicate for whether SYMBOL stands for a function that currently needs to be autoloaded. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:CANCEL-FINALIZATION} \index{CANCEL-FINALIZATION} --- Function: \textbf{cancel-finalization} [\textbf{extensions}] \textit{object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:CHAR-TO-UTF8} \index{CHAR-TO-UTF8} --- Function: \textbf{char-to-utf8} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:CHARPOS} \index{CHARPOS} --- Function: \textbf{charpos} [\textbf{extensions}] \textit{stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:CLASSP} \index{CLASSP} --- Function: \textbf{classp} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:COLLECT} \index{COLLECT} --- Macro: \textbf{collect} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} Collect ({(Name [Initial-Value] [Function])}*) {Form}* Collect some values somehow. Each of the collections specifies a bunch of things which collected during the evaluation of the body of the form. The name of the collection is used to define a local macro, a la MACROLET. Within the body, this macro will evaluate each of its arguments and collect the result, returning the current value after the collection is done. The body is evaluated as a PROGN; to get the final values when you are done, just call the collection macro with no arguments. Initial-Value is the value that the collection starts out with, which defaults to NIL. Function is the function which does the collection. It is a function which will accept two arguments: the value to be collected and the current collection. The result of the function is made the new value for the collection. As a totally magical special-case, the Function may be Collect, which tells us to build a list in forward order; this is the default. If an Initial-Value is supplied for Collect, the stuff will be rplacd'd onto the end. Note that Function may be anything that can appear in the functional position, including macros and lambdas. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:COMPILE-SYSTEM} \index{COMPILE-SYSTEM} --- Function: \textbf{compile-system} [\textbf{extensions}] \textit{\&key quit (zip t) (cls-ext *compile-file-class-extension*) (abcl-ext *compile-file-type*) output-path} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:DOUBLE-FLOAT-NEGATIVE-INFINITY} \index{DOUBLE-FLOAT-NEGATIVE-INFINITY} --- Variable: \textbf{double-float-negative-infinity} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:DOUBLE-FLOAT-POSITIVE-INFINITY} \index{DOUBLE-FLOAT-POSITIVE-INFINITY} --- Variable: \textbf{double-float-positive-infinity} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:DUMP-JAVA-STACK} \index{DUMP-JAVA-STACK} --- Function: \textbf{dump-java-stack} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:EXIT} \index{EXIT} --- Function: \textbf{exit} [\textbf{extensions}] \textit{\&key status} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:FEATUREP} \index{FEATUREP} --- Function: \textbf{featurep} [\textbf{extensions}] \textit{form} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:FILE-DIRECTORY-P} \index{FILE-DIRECTORY-P} --- Function: \textbf{file-directory-p} [\textbf{extensions}] \textit{pathspec \&key (wild-error-p t)} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:FINALIZE} \index{FINALIZE} --- Function: \textbf{finalize} [\textbf{extensions}] \textit{object function} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:FIXNUMP} \index{FIXNUMP} --- Function: \textbf{fixnump} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:GC} \index{GC} --- Function: \textbf{gc} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:GET-FLOATING-POINT-MODES} \index{GET-FLOATING-POINT-MODES} --- Function: \textbf{get-floating-point-modes} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:GET-PID} \index{GET-PID} --- Function: \textbf{get-pid} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} Get the process identifier of this lisp process. Used to be in SLIME but generally useful, so now back in ABCL proper. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:GET-SOCKET-STREAM} \index{GET-SOCKET-STREAM} --- Function: \textbf{get-socket-stream} [\textbf{extensions}] \textit{socket \&key (element-type (quote character)) (external-format default)} \begin{adjustwidth}{5em}{5em} :ELEMENT-TYPE must be CHARACTER or (UNSIGNED-BYTE 8); the default is CHARACTER. EXTERNAL-FORMAT must be of the same format as specified for OPEN. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:GET-TIME-ZONE} \index{GET-TIME-ZONE} --- Function: \textbf{get-time-zone} [\textbf{extensions}] \textit{time-in-millis} \begin{adjustwidth}{5em}{5em} Returns as the first value the timezone difference in hours from the Greenwich meridian for TIME-IN-MILLIS via the Daylight Savings Time assumptions that were in place at the instant's occurance. Returns as the second value a boolean as to whether daylight savings time was in effect at the occurance. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:GETENV} \index{GETENV} --- Function: \textbf{getenv} [\textbf{extensions}] \textit{variable} \begin{adjustwidth}{5em}{5em} Return the value of the environment VARIABLE if it exists, otherwise return NIL. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:GETENV-ALL} \index{GETENV-ALL} --- Function: \textbf{getenv-all} [\textbf{extensions}] \textit{variable} \begin{adjustwidth}{5em}{5em} Returns all environment variables as an alist containing (name . value) \end{adjustwidth} \paragraph{} \label{EXTENSIONS:INIT-GUI} \index{INIT-GUI} --- Function: \textbf{init-gui} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:INTERRUPT-LISP} \index{INTERRUPT-LISP} --- Function: \textbf{interrupt-lisp} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:JAR-PATHNAME} \index{JAR-PATHNAME} --- Class: \textbf{jar-pathname} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MACROEXPAND-ALL} \index{MACROEXPAND-ALL} --- Function: \textbf{macroexpand-all} [\textbf{extensions}] \textit{form \&optional env} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAILBOX} \index{MAILBOX} --- Class: \textbf{mailbox} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAKE-DIALOG-PROMPT-STREAM} \index{MAKE-DIALOG-PROMPT-STREAM} --- Function: \textbf{make-dialog-prompt-stream} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAKE-SERVER-SOCKET} \index{MAKE-SERVER-SOCKET} --- Function: \textbf{make-server-socket} [\textbf{extensions}] \textit{port} \begin{adjustwidth}{5em}{5em} Create a TCP server socket listening for clients on PORT. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAKE-SLIME-INPUT-STREAM} \index{MAKE-SLIME-INPUT-STREAM} --- Function: \textbf{make-slime-input-stream} [\textbf{extensions}] \textit{function output-stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAKE-SLIME-OUTPUT-STREAM} \index{MAKE-SLIME-OUTPUT-STREAM} --- Function: \textbf{make-slime-output-stream} [\textbf{extensions}] \textit{function} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAKE-SOCKET} \index{MAKE-SOCKET} --- Function: \textbf{make-socket} [\textbf{extensions}] \textit{host port} \begin{adjustwidth}{5em}{5em} Create a TCP socket for client communication to HOST on PORT. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAKE-TEMP-DIRECTORY} \index{MAKE-TEMP-DIRECTORY} --- Function: \textbf{make-temp-directory} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} Create and return the pathname of a previously non-existent directory. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAKE-TEMP-FILE} \index{MAKE-TEMP-FILE} --- Function: \textbf{make-temp-file} [\textbf{extensions}] \textit{\&key prefix suffix} \begin{adjustwidth}{5em}{5em} Create and return the pathname of a previously non-existent file. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MAKE-WEAK-REFERENCE} \index{MAKE-WEAK-REFERENCE} --- Function: \textbf{make-weak-reference} [\textbf{extensions}] \textit{obj} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MEMQ} \index{MEMQ} --- Function: \textbf{memq} [\textbf{extensions}] \textit{item list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MEMQL} \index{MEMQL} --- Function: \textbf{memql} [\textbf{extensions}] \textit{item list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MOST-NEGATIVE-JAVA-LONG} \index{MOST-NEGATIVE-JAVA-LONG} --- Variable: \textbf{most-negative-java-long} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MOST-POSITIVE-JAVA-LONG} \index{MOST-POSITIVE-JAVA-LONG} --- Variable: \textbf{most-positive-java-long} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:MUTEX} \index{MUTEX} --- Class: \textbf{mutex} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:NEQ} \index{NEQ} --- Function: \textbf{neq} [\textbf{extensions}] \textit{obj1 obj2} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:NIL-VECTOR} \index{NIL-VECTOR} --- Class: \textbf{nil-vector} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:OS-UNIX-P} \index{OS-UNIX-P} --- Function: \textbf{os-unix-p} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} Is the underlying operating system some Unix variant? \end{adjustwidth} \paragraph{} \label{EXTENSIONS:OS-WINDOWS-P} \index{OS-WINDOWS-P} --- Function: \textbf{os-windows-p} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} Is the underlying operating system Microsoft Windows? \end{adjustwidth} \paragraph{} \label{EXTENSIONS:PACKAGE-LOCAL-NICKNAMES} \index{PACKAGE-LOCAL-NICKNAMES} --- Function: \textbf{package-local-nicknames} [\textbf{extensions}] \textit{package} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:PACKAGE-LOCALLY-NICKNAMED-BY-LIST} \index{PACKAGE-LOCALLY-NICKNAMED-BY-LIST} --- Function: \textbf{package-locally-nicknamed-by-list} [\textbf{extensions}] \textit{package} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:PATHNAME-JAR-P} \index{PATHNAME-JAR-P} --- Function: \textbf{pathname-jar-p} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:PATHNAME-URL-P} \index{PATHNAME-URL-P} --- Function: \textbf{pathname-url-p} [\textbf{extensions}] \textit{pathname} \begin{adjustwidth}{5em}{5em} Predicate for whether PATHNAME references a URL. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:PRECOMPILE} \index{PRECOMPILE} --- Function: \textbf{precompile} [\textbf{extensions}] \textit{name \&optional definition} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:PROBE-DIRECTORY} \index{PROBE-DIRECTORY} --- Function: \textbf{probe-directory} [\textbf{extensions}] \textit{pathspec} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:QUIT} \index{QUIT} --- Function: \textbf{quit} [\textbf{extensions}] \textit{\&key status} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:READ-CLASS} \index{READ-CLASS} --- Function: \textbf{read-class} [\textbf{extensions}] \textit{pathname} \begin{adjustwidth}{5em}{5em} Read the file at PATHNAME as a Java byte[] array \end{adjustwidth} \paragraph{} \label{EXTENSIONS:READ-TIMEOUT} \index{READ-TIMEOUT} --- Function: \textbf{read-timeout} [\textbf{extensions}] \textit{socket seconds} \begin{adjustwidth}{5em}{5em} Time in SECONDS to set local implementation of 'SO\_RCVTIMEO' on SOCKET. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:REMOVE-PACKAGE-LOCAL-NICKNAME} \index{REMOVE-PACKAGE-LOCAL-NICKNAME} --- Function: \textbf{remove-package-local-nickname} [\textbf{extensions}] \textit{old-nickname \&optional package-designator} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:RESOLVE} \index{RESOLVE} --- Function: \textbf{resolve} [\textbf{extensions}] \textit{symbol} \begin{adjustwidth}{5em}{5em} Resolve the function named by SYMBOL via the autoloader mechanism. Returns either the function or NIL if no resolution was possible. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:RUN-SHELL-COMMAND} \index{RUN-SHELL-COMMAND} --- Function: \textbf{run-shell-command} [\textbf{extensions}] \textit{command \&key directory (output *standard-output*)} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SERVER-SOCKET-CLOSE} \index{SERVER-SOCKET-CLOSE} --- Function: \textbf{server-socket-close} [\textbf{extensions}] \textit{socket} \begin{adjustwidth}{5em}{5em} Close the server SOCKET. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SET-FLOATING-POINT-MODES} \index{SET-FLOATING-POINT-MODES} --- Function: \textbf{set-floating-point-modes} [\textbf{extensions}] \textit{\&key traps} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SHOW-RESTARTS} \index{SHOW-RESTARTS} --- Function: \textbf{show-restarts} [\textbf{extensions}] \textit{restarts stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SIMPLE-STRING-FILL} \index{SIMPLE-STRING-FILL} --- Function: \textbf{simple-string-fill} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SIMPLE-STRING-SEARCH} \index{SIMPLE-STRING-SEARCH} --- Function: \textbf{simple-string-search} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SINGLE-FLOAT-NEGATIVE-INFINITY} \index{SINGLE-FLOAT-NEGATIVE-INFINITY} --- Variable: \textbf{single-float-negative-infinity} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SINGLE-FLOAT-POSITIVE-INFINITY} \index{SINGLE-FLOAT-POSITIVE-INFINITY} --- Variable: \textbf{single-float-positive-infinity} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SLIME-INPUT-STREAM} \index{SLIME-INPUT-STREAM} --- Class: \textbf{slime-input-stream} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SLIME-OUTPUT-STREAM} \index{SLIME-OUTPUT-STREAM} --- Class: \textbf{slime-output-stream} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOCKET-ACCEPT} \index{SOCKET-ACCEPT} --- Function: \textbf{socket-accept} [\textbf{extensions}] \textit{socket} \begin{adjustwidth}{5em}{5em} Block until able to return a new socket for handling a incoming request to the specified server SOCKET. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOCKET-CLOSE} \index{SOCKET-CLOSE} --- Function: \textbf{socket-close} [\textbf{extensions}] \textit{socket} \begin{adjustwidth}{5em}{5em} Close the client SOCKET. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOCKET-LOCAL-ADDRESS} \index{SOCKET-LOCAL-ADDRESS} --- Function: \textbf{socket-local-address} [\textbf{extensions}] \textit{socket} \begin{adjustwidth}{5em}{5em} Returns the local address of the SOCKET as a dotted quad string. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOCKET-LOCAL-PORT} \index{SOCKET-LOCAL-PORT} --- Function: \textbf{socket-local-port} [\textbf{extensions}] \textit{socket} \begin{adjustwidth}{5em}{5em} Returns the local port number of the SOCKET. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOCKET-PEER-ADDRESS} \index{SOCKET-PEER-ADDRESS} --- Function: \textbf{socket-peer-address} [\textbf{extensions}] \textit{socket} \begin{adjustwidth}{5em}{5em} Returns the peer address of the SOCKET as a dotted quad string. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOCKET-PEER-PORT} \index{SOCKET-PEER-PORT} --- Function: \textbf{socket-peer-port} [\textbf{extensions}] \textit{socket} \begin{adjustwidth}{5em}{5em} Returns the peer port number of the given SOCKET. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOURCE} \index{SOURCE} --- Function: \textbf{source} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOURCE-FILE-POSITION} \index{SOURCE-FILE-POSITION} --- Function: \textbf{source-file-position} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SOURCE-PATHNAME} \index{SOURCE-PATHNAME} --- Function: \textbf{source-pathname} [\textbf{extensions}] \textit{symbol} \begin{adjustwidth}{5em}{5em} Returns either the pathname corresponding to the file from which this symbol was compiled,or the keyword :TOP-LEVEL. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:SPECIAL-VARIABLE-P} \index{SPECIAL-VARIABLE-P} --- Function: \textbf{special-variable-p} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:STREAM-UNIX-FD} \index{STREAM-UNIX-FD} --- Function: \textbf{stream-unix-fd} [\textbf{extensions}] \textit{stream} \begin{adjustwidth}{5em}{5em} Return the integer of the underlying unix file descriptor for STREAM Added by ABCL-INTROSPECT. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:STRING-FIND} \index{STRING-FIND} --- Function: \textbf{string-find} [\textbf{extensions}] \textit{char string} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:STRING-INPUT-STREAM-CURRENT} \index{STRING-INPUT-STREAM-CURRENT} --- Function: \textbf{string-input-stream-current} [\textbf{extensions}] \textit{stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:STRING-POSITION} \index{STRING-POSITION} --- Function: \textbf{string-position} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:STYLE-WARN} \index{STYLE-WARN} --- Function: \textbf{style-warn} [\textbf{extensions}] \textit{format-control \&rest format-arguments} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:TRULY-THE} \index{TRULY-THE} --- Macro: \textbf{truly-the} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:UPTIME} \index{UPTIME} --- Function: \textbf{uptime} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:URI-DECODE} \index{URI-DECODE} --- Function: \textbf{uri-decode} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:URI-ENCODE} \index{URI-ENCODE} --- Function: \textbf{uri-encode} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:URL-PATHNAME} \index{URL-PATHNAME} --- Class: \textbf{url-pathname} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:URL-PATHNAME-AUTHORITY} \index{URL-PATHNAME-AUTHORITY} --- Function: \textbf{url-pathname-authority} [\textbf{extensions}] \textit{p} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:URL-PATHNAME-FRAGMENT} \index{URL-PATHNAME-FRAGMENT} --- Function: \textbf{url-pathname-fragment} [\textbf{extensions}] \textit{p} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:URL-PATHNAME-QUERY} \index{URL-PATHNAME-QUERY} --- Function: \textbf{url-pathname-query} [\textbf{extensions}] \textit{p} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:URL-PATHNAME-SCHEME} \index{URL-PATHNAME-SCHEME} --- Function: \textbf{url-pathname-scheme} [\textbf{extensions}] \textit{p} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:WEAK-REFERENCE} \index{WEAK-REFERENCE} --- Class: \textbf{weak-reference} [\textbf{extensions}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:WEAK-REFERENCE-VALUE} \index{WEAK-REFERENCE-VALUE} --- Function: \textbf{weak-reference-value} [\textbf{extensions}] \textit{obj} \begin{adjustwidth}{5em}{5em} Returns two values, the first being the value of the weak ref,the second T if the reference is valid, or NIL if it hasbeen cleared. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:WRITE-CLASS} \index{WRITE-CLASS} --- Function: \textbf{write-class} [\textbf{extensions}] \textit{class-bytes pathname} \begin{adjustwidth}{5em}{5em} Write the Java byte[] array CLASS-BYTES to PATHNAME. \end{adjustwidth} \paragraph{} \label{EXTENSIONS:WRITE-TIMEOUT} \index{WRITE-TIMEOUT} --- Function: \textbf{write-timeout} [\textbf{extensions}] \textit{socket seconds} \begin{adjustwidth}{5em}{5em} No-op setting of write timeout to SECONDS on SOCKET. \end{adjustwidth} abcl-src-1.9.0/doc/manual/grovel.lisp0100644 0000000 0000000 00000010230 14202767264 016155 0ustar000000000 0000000 (in-package :abcl/documentation) (defun grovel-docstrings-as-tex (&key (package (find-package :java)) (directory (asdf:component-pathname (asdf:find-component :abcl/documentation 'grovel)))) "Transform exported symbols documentation in PACKAGE to DIRECTORY." (let ((output-file (merge-pathnames (format nil "~A.tex" (string-downcase (package-name package))) directory)) (symbols (loop :for symbol :being :each :external-symbol :of package :collecting symbol))) (with-open-file (stream output-file :direction :output) (format t "Writing output to '~A'.~%" output-file) (loop :for symbol :in (sort symbols (lambda (a b) (string-lessp (symbol-name a) (symbol-name b)))) :doing (let ((documentation (symbol-as-tex symbol))) (when documentation (format stream "~&~A~%~%" documentation))))))) (defun texify-string (string &optional remove) (with-output-to-string (s) (loop for char across string do (if (find char '(#\& #\% #\# #\_)) (unless remove (write-char #\\ s) (write-char char s)) (write-char char s))))) (defun texify (thing) "Return STRING with LaTeX-sensitive characters escaped. Downcase symbol names but leave strings alone." (cond ((listp thing) (format nil "~A" (mapcar #'texify thing))) ((stringp thing) (texify-string thing)) ((symbolp thing) (texify-string (string-downcase (symbol-name thing)))))) (defun arglist-as-tex (symbol) (handler-case (loop :for arg :in (ext:arglist symbol) :collecting (texify arg)) (t (e) (progn (warn "Failed to form arglist for ~A: ~A" symbol e) (list ""))))) (defvar *type-alist* '((:function . "Function") (:macro . "Macro") (:variable . "Variable") (:class . "Class") (:special-operator . "Special Operator") (:generic-function . "Generic Function"))) (defun symbol-as-tex (symbol) "Return the TeX representation of a SYMBOL as Tex." (let (type documentation arglist doc symbol-name package-name) (when (setf doc (swank-backend:describe-symbol-for-emacs symbol)) (cond ((find :function doc) (setf type :function documentation (second doc) arglist (format nil "~{~A~^ ~}" (arglist-as-tex symbol)))) ((find :variable doc) (setf type :variable documentation (second doc))) ((find :macro doc) (setf type :macro documentation (second doc))) ((find :generic-function doc) (setf type :generic-function documentation (second doc))) ((find :class doc) (setf type :class documentation (second doc))) ((find :special-operator doc) (setf type :special-operator documentation (second doc))) (t (warn "Unknown type of documentation for symbol ~A: ~A" symbol doc))) (setf symbol-name (string-downcase symbol) package-name (string-downcase (package-name (find-package (symbol-package symbol))))) (format nil "~&\\paragraph{} \\label{~A:~A} \\index{~A} --- ~A: \\textbf{~A} [\\textbf{~A}] \\textit{~A} \\begin{adjustwidth}{5em}{5em} ~A \\end{adjustwidth}" (texify-string (package-name (find-package (symbol-package symbol))) t) (texify-string (symbol-name symbol) t) (texify-string (symbol-name symbol) t) (cdr (assoc type *type-alist*)) (texify symbol-name) (texify package-name) (if arglist arglist "") (if documentation (texify documentation) ""))))) abcl-src-1.9.0/doc/manual/index.lisp0100644 0000000 0000000 00000000567 14202767264 016002 0ustar000000000 0000000 (in-package abcl/documentation) #+elisp ;; huh? (slime-apropos-package "JAVA") (defun index () "Regenerate TeX markup from symbol introspection." (dolist (package '(:extensions :system :threads :mop :java :jss )) (grovel-docstrings-as-tex :package package))) abcl-src-1.9.0/doc/manual/java.aux0100644 0000000 0000000 00000027507 14242630063 015433 0ustar000000000 0000000 \relax \providecommand\hyper@newdestlabel[2]{} \newlabel{JAVA:*JAVA-OBJECT-TO-STRING-LENGTH*}{{3.4.1}{21}{}{section*.16}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.16}\protected@file@percent } \newlabel{JAVA:+FALSE+}{{3.4.1}{21}{}{section*.17}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.17}\protected@file@percent } \newlabel{JAVA:+NULL+}{{3.4.1}{21}{}{section*.18}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.18}\protected@file@percent } \newlabel{JAVA:+TRUE+}{{3.4.1}{21}{}{section*.19}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.19}\protected@file@percent } \newlabel{JAVA:ADD-TO-CLASSPATH}{{3.4.1}{21}{}{section*.20}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.20}\protected@file@percent } \newlabel{JAVA:CHAIN}{{3.4.1}{21}{}{section*.21}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.21}\protected@file@percent } \newlabel{JAVA:DEFINE-JAVA-CLASS}{{3.4.1}{21}{}{section*.22}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.22}\protected@file@percent } \newlabel{JAVA:DESCRIBE-JAVA-OBJECT}{{3.4.1}{21}{}{section*.23}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.23}\protected@file@percent } \newlabel{JAVA:DUMP-CLASSPATH}{{3.4.1}{21}{}{section*.24}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.24}\protected@file@percent } \newlabel{JAVA:ENSURE-JAVA-CLASS}{{3.4.1}{21}{}{section*.25}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.25}\protected@file@percent } \newlabel{JAVA:ENSURE-JAVA-OBJECT}{{3.4.1}{21}{}{section*.26}{}} \@writefile{toc}{\contentsline {paragraph}{}{21}{section*.26}\protected@file@percent } \newlabel{JAVA:GET-CURRENT-CLASSLOADER}{{3.4.1}{22}{}{section*.27}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.27}\protected@file@percent } \newlabel{JAVA:GET-DEFAULT-CLASSLOADER}{{3.4.1}{22}{}{section*.28}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.28}\protected@file@percent } \newlabel{JAVA:JARRAY-COMPONENT-TYPE}{{3.4.1}{22}{}{section*.29}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.29}\protected@file@percent } \newlabel{JAVA:JARRAY-FROM-LIST}{{3.4.1}{22}{}{section*.30}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.30}\protected@file@percent } \newlabel{JAVA:JARRAY-LENGTH}{{3.4.1}{22}{}{section*.31}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.31}\protected@file@percent } \newlabel{JAVA:JARRAY-REF}{{3.4.1}{22}{}{section*.32}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.32}\protected@file@percent } \newlabel{JAVA:JARRAY-REF-RAW}{{3.4.1}{22}{}{section*.33}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.33}\protected@file@percent } \newlabel{JAVA:JARRAY-SET}{{3.4.1}{22}{}{section*.34}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.34}\protected@file@percent } \newlabel{JAVA:JAVA-CLASS}{{3.4.1}{22}{}{section*.35}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.35}\protected@file@percent } \newlabel{JAVA:JAVA-EXCEPTION}{{3.4.1}{22}{}{section*.36}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.36}\protected@file@percent } \newlabel{JAVA:JAVA-EXCEPTION-CAUSE}{{3.4.1}{22}{}{section*.37}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.37}\protected@file@percent } \newlabel{JAVA:JAVA-OBJECT}{{3.4.1}{22}{}{section*.38}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.38}\protected@file@percent } \newlabel{JAVA:JAVA-OBJECT-P}{{3.4.1}{22}{}{section*.39}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.39}\protected@file@percent } \newlabel{JAVA:JCALL}{{3.4.1}{22}{}{section*.40}{}} \@writefile{toc}{\contentsline {paragraph}{}{22}{section*.40}\protected@file@percent } \newlabel{JAVA:JCALL-RAW}{{3.4.1}{23}{}{section*.41}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.41}\protected@file@percent } \newlabel{JAVA:JCLASS}{{3.4.1}{23}{}{section*.42}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.42}\protected@file@percent } \newlabel{JAVA:JCLASS-ARRAY-P}{{3.4.1}{23}{}{section*.43}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.43}\protected@file@percent } \newlabel{JAVA:JCLASS-CONSTRUCTORS}{{3.4.1}{23}{}{section*.44}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.44}\protected@file@percent } \newlabel{JAVA:JCLASS-FIELD}{{3.4.1}{23}{}{section*.45}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.45}\protected@file@percent } \newlabel{JAVA:JCLASS-FIELDS}{{3.4.1}{23}{}{section*.46}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.46}\protected@file@percent } \newlabel{JAVA:JCLASS-INTERFACE-P}{{3.4.1}{23}{}{section*.47}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.47}\protected@file@percent } \newlabel{JAVA:JCLASS-INTERFACES}{{3.4.1}{23}{}{section*.48}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.48}\protected@file@percent } \newlabel{JAVA:JCLASS-METHODS}{{3.4.1}{23}{}{section*.49}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.49}\protected@file@percent } \newlabel{JAVA:JCLASS-NAME}{{3.4.1}{23}{}{section*.50}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.50}\protected@file@percent } \newlabel{JAVA:JCLASS-OF}{{3.4.1}{23}{}{section*.51}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.51}\protected@file@percent } \newlabel{JAVA:JCLASS-SUPERCLASS}{{3.4.1}{23}{}{section*.52}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.52}\protected@file@percent } \newlabel{JAVA:JCLASS-SUPERCLASS-P}{{3.4.1}{23}{}{section*.53}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.53}\protected@file@percent } \newlabel{JAVA:JCOERCE}{{3.4.1}{23}{}{section*.54}{}} \@writefile{toc}{\contentsline {paragraph}{}{23}{section*.54}\protected@file@percent } \newlabel{JAVA:JCONSTRUCTOR}{{3.4.1}{24}{}{section*.55}{}} \@writefile{toc}{\contentsline {paragraph}{}{24}{section*.55}\protected@file@percent } \newlabel{JAVA:JCONSTRUCTOR-PARAMS}{{3.4.1}{24}{}{section*.56}{}} \@writefile{toc}{\contentsline {paragraph}{}{24}{section*.56}\protected@file@percent } \newlabel{JAVA:JEQUAL}{{3.4.1}{24}{}{section*.57}{}} \@writefile{toc}{\contentsline {paragraph}{}{24}{section*.57}\protected@file@percent } \newlabel{JAVA:JFIELD}{{3.4.1}{24}{}{section*.58}{}} \@writefile{toc}{\contentsline {paragraph}{}{24}{section*.58}\protected@file@percent } \newlabel{JAVA:JFIELD-NAME}{{3.4.1}{24}{}{section*.59}{}} \@writefile{toc}{\contentsline {paragraph}{}{24}{section*.59}\protected@file@percent } \newlabel{JAVA:JFIELD-RAW}{{3.4.1}{24}{}{section*.60}{}} \@writefile{toc}{\contentsline {paragraph}{}{24}{section*.60}\protected@file@percent } \newlabel{JAVA:JFIELD-TYPE}{{3.4.1}{24}{}{section*.61}{}} \@writefile{toc}{\contentsline {paragraph}{}{24}{section*.61}\protected@file@percent } \newlabel{JAVA:JINPUT-STREAM}{{3.4.1}{25}{}{section*.62}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.62}\protected@file@percent } \newlabel{JAVA:JINSTANCE-OF-P}{{3.4.1}{25}{}{section*.63}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.63}\protected@file@percent } \newlabel{JAVA:JINTERFACE-IMPLEMENTATION}{{3.4.1}{25}{}{section*.64}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.64}\protected@file@percent } \newlabel{JAVA:JMAKE-INVOCATION-HANDLER}{{3.4.1}{25}{}{section*.65}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.65}\protected@file@percent } \newlabel{JAVA:JMAKE-PROXY}{{3.4.1}{25}{}{section*.66}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.66}\protected@file@percent } \newlabel{JAVA:JMEMBER-PROTECTED-P}{{3.4.1}{25}{}{section*.67}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.67}\protected@file@percent } \newlabel{JAVA:JMEMBER-PUBLIC-P}{{3.4.1}{25}{}{section*.68}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.68}\protected@file@percent } \newlabel{JAVA:JMEMBER-STATIC-P}{{3.4.1}{25}{}{section*.69}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.69}\protected@file@percent } \newlabel{JAVA:JMETHOD}{{3.4.1}{25}{}{section*.70}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.70}\protected@file@percent } \newlabel{JAVA:JMETHOD-LET}{{3.4.1}{25}{}{section*.71}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.71}\protected@file@percent } \newlabel{JAVA:JMETHOD-NAME}{{3.4.1}{25}{}{section*.72}{}} \@writefile{toc}{\contentsline {paragraph}{}{25}{section*.72}\protected@file@percent } \newlabel{JAVA:JMETHOD-PARAMS}{{3.4.1}{26}{}{section*.73}{}} \@writefile{toc}{\contentsline {paragraph}{}{26}{section*.73}\protected@file@percent } \newlabel{JAVA:JMETHOD-RETURN-TYPE}{{3.4.1}{26}{}{section*.74}{}} \@writefile{toc}{\contentsline {paragraph}{}{26}{section*.74}\protected@file@percent } \newlabel{JAVA:JNEW}{{3.4.1}{26}{}{section*.75}{}} \@writefile{toc}{\contentsline {paragraph}{}{26}{section*.75}\protected@file@percent } \newlabel{JAVA:JNEW-ARRAY}{{3.4.1}{26}{}{section*.76}{}} \@writefile{toc}{\contentsline {paragraph}{}{26}{section*.76}\protected@file@percent } \newlabel{JAVA:JNEW-ARRAY-FROM-ARRAY}{{3.4.1}{26}{}{section*.77}{}} \@writefile{toc}{\contentsline {paragraph}{}{26}{section*.77}\protected@file@percent } \newlabel{JAVA:JNEW-ARRAY-FROM-LIST}{{3.4.1}{26}{}{section*.78}{}} \@writefile{toc}{\contentsline {paragraph}{}{26}{section*.78}\protected@file@percent } \newlabel{JAVA:JNEW-RUNTIME-CLASS}{{3.4.1}{26}{}{section*.79}{}} \@writefile{toc}{\contentsline {paragraph}{}{26}{section*.79}\protected@file@percent } \newlabel{JAVA:JNULL-REF-P}{{3.4.1}{27}{}{section*.80}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.80}\protected@file@percent } \newlabel{JAVA:JOBJECT-CLASS}{{3.4.1}{27}{}{section*.81}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.81}\protected@file@percent } \newlabel{JAVA:JOBJECT-LISP-VALUE}{{3.4.1}{27}{}{section*.82}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.82}\protected@file@percent } \newlabel{JAVA:JPROPERTY-VALUE}{{3.4.1}{27}{}{section*.83}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.83}\protected@file@percent } \newlabel{JAVA:JREGISTER-HANDLER}{{3.4.1}{27}{}{section*.84}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.84}\protected@file@percent } \newlabel{JAVA:JRESOLVE-METHOD}{{3.4.1}{27}{}{section*.85}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.85}\protected@file@percent } \newlabel{JAVA:JRUN-EXCEPTION-PROTECTED}{{3.4.1}{27}{}{section*.86}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.86}\protected@file@percent } \newlabel{JAVA:JSTATIC}{{3.4.1}{27}{}{section*.87}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.87}\protected@file@percent } \newlabel{JAVA:JSTATIC-RAW}{{3.4.1}{27}{}{section*.88}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.88}\protected@file@percent } \newlabel{JAVA:MAKE-CLASSLOADER}{{3.4.1}{27}{}{section*.89}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.89}\protected@file@percent } \newlabel{JAVA:MAKE-IMMEDIATE-OBJECT}{{3.4.1}{27}{}{section*.90}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.90}\protected@file@percent } \newlabel{JAVA:REGISTER-JAVA-EXCEPTION}{{3.4.1}{27}{}{section*.91}{}} \@writefile{toc}{\contentsline {paragraph}{}{27}{section*.91}\protected@file@percent } \newlabel{JAVA:UNREGISTER-JAVA-EXCEPTION}{{3.4.1}{28}{}{section*.92}{}} \@writefile{toc}{\contentsline {paragraph}{}{28}{section*.92}\protected@file@percent } \@setckpt{java}{ \setcounter{page}{29} \setcounter{equation}{0} \setcounter{enumi}{0} \setcounter{enumii}{0} \setcounter{enumiii}{0} \setcounter{enumiv}{0} \setcounter{footnote}{2} \setcounter{mpfootnote}{0} \setcounter{part}{0} \setcounter{chapter}{3} \setcounter{section}{4} \setcounter{subsection}{1} \setcounter{subsubsection}{0} \setcounter{paragraph}{0} \setcounter{subparagraph}{0} \setcounter{figure}{0} \setcounter{table}{0} \setcounter{Item}{0} \setcounter{Hfootnote}{13} \setcounter{bookmark@seq@number}{34} \setcounter{lstnumber}{2} \setcounter{cp@cntr}{0} \setcounter{section@level}{4} \setcounter{lstlisting}{0} } abcl-src-1.9.0/doc/manual/java.tex0100644 0000000 0000000 00000063474 14202767264 015453 0ustar000000000 0000000 \paragraph{} \label{JAVA:*JAVA-OBJECT-TO-STRING-LENGTH*} \index{*JAVA-OBJECT-TO-STRING-LENGTH*} --- Variable: \textbf{*java-object-to-string-length*} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} Length to truncate toString() PRINT-OBJECT output for an otherwise unspecialized JAVA-OBJECT. Can be set to NIL to indicate no limit. \end{adjustwidth} \paragraph{} \label{JAVA:+FALSE+} \index{+FALSE+} --- Variable: \textbf{+false+} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} The JVM primitive value for boolean false. \end{adjustwidth} \paragraph{} \label{JAVA:+NULL+} \index{+NULL+} --- Variable: \textbf{+null+} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} The JVM null object reference. \end{adjustwidth} \paragraph{} \label{JAVA:+TRUE+} \index{+TRUE+} --- Variable: \textbf{+true+} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} The JVM primitive value for boolean true. \end{adjustwidth} \paragraph{} \label{JAVA:ADD-TO-CLASSPATH} \index{ADD-TO-CLASSPATH} --- Generic Function: \textbf{add-to-classpath} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} Add JAR-OR-JARS to the JVM classpath optionally specifying the CLASSLOADER to add. JAR-OR-JARS is either a pathname designating a jar archive or the root directory to search for classes or a list of such values. \end{adjustwidth} \paragraph{} \label{JAVA:CHAIN} \index{CHAIN} --- Macro: \textbf{chain} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} Performs chained method invocations. TARGET is either the receiver object when the first call is a virtual method call or a list in the form (:static ) when the first method call is a static method call. OP and each of the OPS are either method designators or lists in the form ( \&rest args), where a method designator is either a string naming a method, or a jmethod object. CHAIN will perform the method call specified by OP on TARGET; then, for each of the OPS, CHAIN will perform the specified method call using the object returned by the previous method call as the receiver, and will ultimately return the result of the last method call. For example, the form: (chain (:static "java.lang.Runtime") "getRuntime" ("exec" "ls")) is equivalent to the following Java code: java.lang.Runtime.getRuntime().exec("ls"); \end{adjustwidth} \paragraph{} \label{JAVA:DEFINE-JAVA-CLASS} \index{DEFINE-JAVA-CLASS} --- Macro: \textbf{define-java-class} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:DESCRIBE-JAVA-OBJECT} \index{DESCRIBE-JAVA-OBJECT} --- Function: \textbf{describe-java-object} [\textbf{java}] \textit{object stream} \begin{adjustwidth}{5em}{5em} Print a human friendly description of Java OBJECT to STREAM. \end{adjustwidth} \paragraph{} \label{JAVA:DUMP-CLASSPATH} \index{DUMP-CLASSPATH} --- Function: \textbf{dump-classpath} [\textbf{java}] \textit{\&optional classloader} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:ENSURE-JAVA-CLASS} \index{ENSURE-JAVA-CLASS} --- Function: \textbf{ensure-java-class} [\textbf{java}] \textit{jclass} \begin{adjustwidth}{5em}{5em} Attempt to ensure that the Java class referenced by JCLASS exists in the current process of the implementation. \end{adjustwidth} \paragraph{} \label{JAVA:ENSURE-JAVA-OBJECT} \index{ENSURE-JAVA-OBJECT} --- Function: \textbf{ensure-java-object} [\textbf{java}] \textit{obj} \begin{adjustwidth}{5em}{5em} Ensures OBJ is wrapped in a JAVA-OBJECT, wrapping it if necessary. \end{adjustwidth} \paragraph{} \label{JAVA:GET-CURRENT-CLASSLOADER} \index{GET-CURRENT-CLASSLOADER} --- Function: \textbf{get-current-classloader} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:GET-DEFAULT-CLASSLOADER} \index{GET-DEFAULT-CLASSLOADER} --- Function: \textbf{get-default-classloader} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:JARRAY-COMPONENT-TYPE} \index{JARRAY-COMPONENT-TYPE} --- Function: \textbf{jarray-component-type} [\textbf{java}] \textit{atype} \begin{adjustwidth}{5em}{5em} Returns the component type of the array type ATYPE \end{adjustwidth} \paragraph{} \label{JAVA:JARRAY-FROM-LIST} \index{JARRAY-FROM-LIST} --- Function: \textbf{jarray-from-list} [\textbf{java}] \textit{list} \begin{adjustwidth}{5em}{5em} Return a Java array from LIST whose type is inferred from the first element. For more control over the type of the array, use JNEW-ARRAY-FROM-LIST. \end{adjustwidth} \paragraph{} \label{JAVA:JARRAY-LENGTH} \index{JARRAY-LENGTH} --- Function: \textbf{jarray-length} [\textbf{java}] \textit{java-array} \begin{adjustwidth}{5em}{5em} Returns the length of a Java primitive array. \end{adjustwidth} \paragraph{} \label{JAVA:JARRAY-REF} \index{JARRAY-REF} --- Function: \textbf{jarray-ref} [\textbf{java}] \textit{java-array \&rest indices} \begin{adjustwidth}{5em}{5em} Dereferences the Java array JAVA-ARRAY using the given INDICES, coercing the result into a Lisp object, if possible. \end{adjustwidth} \paragraph{} \label{JAVA:JARRAY-REF-RAW} \index{JARRAY-REF-RAW} --- Function: \textbf{jarray-ref-raw} [\textbf{java}] \textit{java-array \&rest indices} \begin{adjustwidth}{5em}{5em} Dereference the Java array JAVA-ARRAY using the given INDICES. Does not attempt to coerce the result into a Lisp object. \end{adjustwidth} \paragraph{} \label{JAVA:JARRAY-SET} \index{JARRAY-SET} --- Function: \textbf{jarray-set} [\textbf{java}] \textit{java-array new-value \&rest indices} \begin{adjustwidth}{5em}{5em} Stores NEW-VALUE at the given INDICES in JAVA-ARRAY. \end{adjustwidth} \paragraph{} \label{JAVA:JAVA-CLASS} \index{JAVA-CLASS} --- Class: \textbf{java-class} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:JAVA-EXCEPTION} \index{JAVA-EXCEPTION} --- Class: \textbf{java-exception} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:JAVA-EXCEPTION-CAUSE} \index{JAVA-EXCEPTION-CAUSE} --- Function: \textbf{java-exception-cause} [\textbf{java}] \textit{java-exception} \begin{adjustwidth}{5em}{5em} Returns the cause of JAVA-EXCEPTION. (The cause is the Java Throwable object that caused JAVA-EXCEPTION to be signalled.) \end{adjustwidth} \paragraph{} \label{JAVA:JAVA-OBJECT} \index{JAVA-OBJECT} --- Class: \textbf{java-object} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:JAVA-OBJECT-P} \index{JAVA-OBJECT-P} --- Function: \textbf{java-object-p} [\textbf{java}] \textit{object} \begin{adjustwidth}{5em}{5em} Returns T if OBJECT is a JAVA-OBJECT. \end{adjustwidth} \paragraph{} \label{JAVA:JCALL} \index{JCALL} --- Function: \textbf{jcall} [\textbf{java}] \textit{method-ref instance \&rest args} \begin{adjustwidth}{5em}{5em} Invokes the Java method METHOD-REF on INSTANCE with arguments ARGS, coercing the result into a Lisp object, if possible. \end{adjustwidth} \paragraph{} \label{JAVA:JCALL-RAW} \index{JCALL-RAW} --- Function: \textbf{jcall-raw} [\textbf{java}] \textit{method-ref instance \&rest args} \begin{adjustwidth}{5em}{5em} Invokes the Java method METHOD-REF on INSTANCE with arguments ARGS. Does not attempt to coerce the result into a Lisp object. \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS} \index{JCLASS} --- Function: \textbf{jclass} [\textbf{java}] \textit{name-or-class-ref \&optional class-loader} \begin{adjustwidth}{5em}{5em} Returns a reference to the Java class designated by NAME-OR-CLASS-REF. If the CLASS-LOADER parameter is passed, the class is resolved with respect to the given ClassLoader. \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-ARRAY-P} \index{JCLASS-ARRAY-P} --- Function: \textbf{jclass-array-p} [\textbf{java}] \textit{class} \begin{adjustwidth}{5em}{5em} Returns T if CLASS is an array class \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-CONSTRUCTORS} \index{JCLASS-CONSTRUCTORS} --- Function: \textbf{jclass-constructors} [\textbf{java}] \textit{class} \begin{adjustwidth}{5em}{5em} Returns a vector of constructors for CLASS \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-FIELD} \index{JCLASS-FIELD} --- Function: \textbf{jclass-field} [\textbf{java}] \textit{class field-name} \begin{adjustwidth}{5em}{5em} Returns the field named FIELD-NAME of CLASS \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-FIELDS} \index{JCLASS-FIELDS} --- Function: \textbf{jclass-fields} [\textbf{java}] \textit{class \&key declared public} \begin{adjustwidth}{5em}{5em} Returns a vector of all (or just the declared/public, if DECLARED/PUBLIC is true) fields of CLASS \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-INTERFACE-P} \index{JCLASS-INTERFACE-P} --- Function: \textbf{jclass-interface-p} [\textbf{java}] \textit{class} \begin{adjustwidth}{5em}{5em} Returns T if CLASS is an interface \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-INTERFACES} \index{JCLASS-INTERFACES} --- Function: \textbf{jclass-interfaces} [\textbf{java}] \textit{class} \begin{adjustwidth}{5em}{5em} Returns the vector of interfaces of CLASS \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-METHODS} \index{JCLASS-METHODS} --- Function: \textbf{jclass-methods} [\textbf{java}] \textit{class \&key declared public} \begin{adjustwidth}{5em}{5em} Return a vector of all (or just the declared/public, if DECLARED/PUBLIC is true) methods of CLASS \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-NAME} \index{JCLASS-NAME} --- Function: \textbf{jclass-name} [\textbf{java}] \textit{class-ref \&optional name} \begin{adjustwidth}{5em}{5em} When called with one argument, returns the name of the Java class designated by CLASS-REF. When called with two arguments, tests whether CLASS-REF matches NAME. \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-OF} \index{JCLASS-OF} --- Function: \textbf{jclass-of} [\textbf{java}] \textit{object \&optional name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-SUPERCLASS} \index{JCLASS-SUPERCLASS} --- Function: \textbf{jclass-superclass} [\textbf{java}] \textit{class} \begin{adjustwidth}{5em}{5em} Returns the superclass of CLASS, or NIL if it hasn't got one \end{adjustwidth} \paragraph{} \label{JAVA:JCLASS-SUPERCLASS-P} \index{JCLASS-SUPERCLASS-P} --- Function: \textbf{jclass-superclass-p} [\textbf{java}] \textit{class-1 class-2} \begin{adjustwidth}{5em}{5em} Returns T if CLASS-1 is a superclass or interface of CLASS-2 \end{adjustwidth} \paragraph{} \label{JAVA:JCOERCE} \index{JCOERCE} --- Function: \textbf{jcoerce} [\textbf{java}] \textit{object intended-class} \begin{adjustwidth}{5em}{5em} Attempts to coerce OBJECT into a JavaObject of class INTENDED-CLASS. Raises a TYPE-ERROR if no conversion is possible. \end{adjustwidth} \paragraph{} \label{JAVA:JCONSTRUCTOR} \index{JCONSTRUCTOR} --- Function: \textbf{jconstructor} [\textbf{java}] \textit{class-ref \&rest parameter-class-refs} \begin{adjustwidth}{5em}{5em} Returns a reference to the Java constructor of CLASS-REF with the given PARAMETER-CLASS-REFS. \end{adjustwidth} \paragraph{} \label{JAVA:JCONSTRUCTOR-PARAMS} \index{JCONSTRUCTOR-PARAMS} --- Function: \textbf{jconstructor-params} [\textbf{java}] \textit{constructor} \begin{adjustwidth}{5em}{5em} Returns a vector of parameter types (Java classes) for CONSTRUCTOR \end{adjustwidth} \paragraph{} \label{JAVA:JEQUAL} \index{JEQUAL} --- Function: \textbf{jequal} [\textbf{java}] \textit{obj1 obj2} \begin{adjustwidth}{5em}{5em} Compares obj1 with obj2 using java.lang.Object.equals() \end{adjustwidth} \paragraph{} \label{JAVA:JFIELD} \index{JFIELD} --- Function: \textbf{jfield} [\textbf{java}] \textit{class-ref-or-field field-or-instance \&optional instance value} \begin{adjustwidth}{5em}{5em} Retrieves or modifies a field in a Java class or instance. Supported argument patterns: Case 1: class-ref field-name: Retrieves the value of a static field. Case 2: class-ref field-name instance-ref: Retrieves the value of a class field of the instance. Case 3: class-ref field-name primitive-value: Stores a primitive-value in a static field. Case 4: class-ref field-name instance-ref value: Stores value in a class field of the instance. Case 5: class-ref field-name nil value: Stores value in a static field (when value may be confused with an instance-ref). Case 6: field-name instance: Retrieves the value of a field of the instance. The class is derived from the instance. Case 7: field-name instance value: Stores value in a field of the instance. The class is derived from the instance. \end{adjustwidth} \paragraph{} \label{JAVA:JFIELD-NAME} \index{JFIELD-NAME} --- Function: \textbf{jfield-name} [\textbf{java}] \textit{field} \begin{adjustwidth}{5em}{5em} Returns the name of FIELD as a Lisp string \end{adjustwidth} \paragraph{} \label{JAVA:JFIELD-RAW} \index{JFIELD-RAW} --- Function: \textbf{jfield-raw} [\textbf{java}] \textit{class-ref-or-field field-or-instance \&optional instance value} \begin{adjustwidth}{5em}{5em} Retrieves or modifies a field in a Java class or instance. Does not attempt to coerce its value or the result into a Lisp object. Supported argument patterns: Case 1: class-ref field-name: Retrieves the value of a static field. Case 2: class-ref field-name instance-ref: Retrieves the value of a class field of the instance. Case 3: class-ref field-name primitive-value: Stores a primitive-value in a static field. Case 4: class-ref field-name instance-ref value: Stores value in a class field of the instance. Case 5: class-ref field-name nil value: Stores value in a static field (when value may be confused with an instance-ref). Case 6: field-name instance: Retrieves the value of a field of the instance. The class is derived from the instance. Case 7: field-name instance value: Stores value in a field of the instance. The class is derived from the instance. \end{adjustwidth} \paragraph{} \label{JAVA:JFIELD-TYPE} \index{JFIELD-TYPE} --- Function: \textbf{jfield-type} [\textbf{java}] \textit{field} \begin{adjustwidth}{5em}{5em} Returns the type (Java class) of FIELD \end{adjustwidth} \paragraph{} \label{JAVA:JINPUT-STREAM} \index{JINPUT-STREAM} --- Function: \textbf{jinput-stream} [\textbf{java}] \textit{pathname} \begin{adjustwidth}{5em}{5em} Returns a java.io.InputStream for resource denoted by PATHNAME. \end{adjustwidth} \paragraph{} \label{JAVA:JINSTANCE-OF-P} \index{JINSTANCE-OF-P} --- Function: \textbf{jinstance-of-p} [\textbf{java}] \textit{obj class} \begin{adjustwidth}{5em}{5em} OBJ is an instance of CLASS (or one of its subclasses) \end{adjustwidth} \paragraph{} \label{JAVA:JINTERFACE-IMPLEMENTATION} \index{JINTERFACE-IMPLEMENTATION} --- Function: \textbf{jinterface-implementation} [\textbf{java}] \textit{interface \&rest method-names-and-defs} \begin{adjustwidth}{5em}{5em} Creates and returns an implementation of a Java interface with methods calling Lisp closures as given in METHOD-NAMES-AND-DEFS. INTERFACE is either a Java interface or a string naming one. METHOD-NAMES-AND-DEFS is an alternating list of method names (strings) and method definitions (closures). For missing methods, a dummy implementation is provided that returns nothing or null depending on whether the return type is void or not. This is for convenience only, and a warning is issued for each undefined method. \end{adjustwidth} \paragraph{} \label{JAVA:JMAKE-INVOCATION-HANDLER} \index{JMAKE-INVOCATION-HANDLER} --- Function: \textbf{jmake-invocation-handler} [\textbf{java}] \textit{function} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:JMAKE-PROXY} \index{JMAKE-PROXY} --- Generic Function: \textbf{jmake-proxy} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} Returns a proxy Java object implementing the provided interface(s) using methods implemented in Lisp - typically closures, but implementations are free to provide other mechanisms. You can pass an optional 'lisp-this' object that will be passed to the implementing methods as their first argument. If you don't provide this object, NIL will be used. The second argument of the Lisp methods is the name of the Java method being implemented. This has the implication that overloaded methods are merged, so you have to manually discriminate them if you want to. The remaining arguments are java-objects wrapping the method's parameters. \end{adjustwidth} \paragraph{} \label{JAVA:JMEMBER-PROTECTED-P} \index{JMEMBER-PROTECTED-P} --- Function: \textbf{jmember-protected-p} [\textbf{java}] \textit{member} \begin{adjustwidth}{5em}{5em} MEMBER is a protected member of its declaring class \end{adjustwidth} \paragraph{} \label{JAVA:JMEMBER-PUBLIC-P} \index{JMEMBER-PUBLIC-P} --- Function: \textbf{jmember-public-p} [\textbf{java}] \textit{member} \begin{adjustwidth}{5em}{5em} MEMBER is a public member of its declaring class \end{adjustwidth} \paragraph{} \label{JAVA:JMEMBER-STATIC-P} \index{JMEMBER-STATIC-P} --- Function: \textbf{jmember-static-p} [\textbf{java}] \textit{member} \begin{adjustwidth}{5em}{5em} MEMBER is a static member of its declaring class \end{adjustwidth} \paragraph{} \label{JAVA:JMETHOD} \index{JMETHOD} --- Function: \textbf{jmethod} [\textbf{java}] \textit{class-ref method-name \&rest parameter-class-refs} \begin{adjustwidth}{5em}{5em} Returns a reference to the Java method METHOD-NAME of CLASS-REF with the given PARAMETER-CLASS-REFS. \end{adjustwidth} \paragraph{} \label{JAVA:JMETHOD-LET} \index{JMETHOD-LET} --- Macro: \textbf{jmethod-let} [\textbf{java}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:JMETHOD-NAME} \index{JMETHOD-NAME} --- Function: \textbf{jmethod-name} [\textbf{java}] \textit{method} \begin{adjustwidth}{5em}{5em} Returns the name of METHOD as a Lisp string \end{adjustwidth} \paragraph{} \label{JAVA:JMETHOD-PARAMS} \index{JMETHOD-PARAMS} --- Function: \textbf{jmethod-params} [\textbf{java}] \textit{method} \begin{adjustwidth}{5em}{5em} Returns a vector of parameter types (Java classes) for METHOD \end{adjustwidth} \paragraph{} \label{JAVA:JMETHOD-RETURN-TYPE} \index{JMETHOD-RETURN-TYPE} --- Function: \textbf{jmethod-return-type} [\textbf{java}] \textit{method} \begin{adjustwidth}{5em}{5em} Returns the result type (Java class) of the METHOD \end{adjustwidth} \paragraph{} \label{JAVA:JNEW} \index{JNEW} --- Function: \textbf{jnew} [\textbf{java}] \textit{constructor \&rest args} \begin{adjustwidth}{5em}{5em} Invokes the Java constructor CONSTRUCTOR with the arguments ARGS. \end{adjustwidth} \paragraph{} \label{JAVA:JNEW-ARRAY} \index{JNEW-ARRAY} --- Function: \textbf{jnew-array} [\textbf{java}] \textit{element-type \&rest dimensions} \begin{adjustwidth}{5em}{5em} Creates a new Java array of type ELEMENT-TYPE, with the given DIMENSIONS. \end{adjustwidth} \paragraph{} \label{JAVA:JNEW-ARRAY-FROM-ARRAY} \index{JNEW-ARRAY-FROM-ARRAY} --- Function: \textbf{jnew-array-from-array} [\textbf{java}] \textit{element-type array} \begin{adjustwidth}{5em}{5em} Returns a new Java array with base type ELEMENT-TYPE (a string or a class-ref) initialized from ARRAY. \end{adjustwidth} \paragraph{} \label{JAVA:JNEW-ARRAY-FROM-LIST} \index{JNEW-ARRAY-FROM-LIST} --- Function: \textbf{jnew-array-from-list} [\textbf{java}] \textit{element-type list} \begin{adjustwidth}{5em}{5em} Returns a new Java array with base type ELEMENT-TYPE (a string or a class-ref) initialized from a Lisp list. \end{adjustwidth} \paragraph{} \label{JAVA:JNEW-RUNTIME-CLASS} \index{JNEW-RUNTIME-CLASS} --- Function: \textbf{jnew-runtime-class} [\textbf{java}] \textit{class-name \&rest args \&key (superclass java.lang.Object) interfaces constructors methods fields (access-flags (quote (public))) annotations (class-loader (make-memory-class-loader))} \begin{adjustwidth}{5em}{5em} Creates and loads a Java class with methods calling Lisp closures as given in METHODS. CLASS-NAME and SUPER-NAME are strings, INTERFACES is a list of strings, CONSTRUCTORS, METHODS and FIELDS are lists of constructor, method and field definitions. Constructor definitions - currently NOT supported - are lists of the form (argument-types function \&optional super-invocation-arguments) where argument-types is a list of strings and function is a lisp function of (1+ (length argument-types)) arguments; the instance (`this') is passed in as the last argument. The optional super-invocation-arguments is a list of numbers between 1 and (length argument-types), where the number k stands for the kth argument to the just defined constructor. If present, the constructor of the superclass will be called with the appropriate arguments. E.g., if the constructor definition is (("java.lang.String" "int") \#'(lambda (string i this) ...) (2 1)) then the constructor of the superclass with argument types (int, java.lang.String) will be called with the second and first arguments. Method definitions are lists of the form (METHOD-NAME RETURN-TYPE ARGUMENT-TYPES FUNCTION \&key MODIFIERS ANNOTATIONS) where METHOD-NAME is a string RETURN-TYPE denotes the type of the object returned by the method ARGUMENT-TYPES is a list of parameters to the method The types are either strings naming fully qualified java classes or Lisp keywords referring to primitive types (:void, :int, etc.). FUNCTION is a Lisp function of minimum arity (1+ (length argument-types)). The instance (`this') is passed as the first argument. Field definitions are lists of the form (field-name type \&key modifiers annotations). \end{adjustwidth} \paragraph{} \label{JAVA:JNULL-REF-P} \index{JNULL-REF-P} --- Function: \textbf{jnull-ref-p} [\textbf{java}] \textit{object} \begin{adjustwidth}{5em}{5em} Returns a non-NIL value when the JAVA-OBJECT `object` is `null`, or signals a TYPE-ERROR condition if the object isn't of the right type. \end{adjustwidth} \paragraph{} \label{JAVA:JOBJECT-CLASS} \index{JOBJECT-CLASS} --- Function: \textbf{jobject-class} [\textbf{java}] \textit{obj} \begin{adjustwidth}{5em}{5em} Returns the Java class that OBJ belongs to \end{adjustwidth} \paragraph{} \label{JAVA:JOBJECT-LISP-VALUE} \index{JOBJECT-LISP-VALUE} --- Function: \textbf{jobject-lisp-value} [\textbf{java}] \textit{java-object} \begin{adjustwidth}{5em}{5em} Attempts to coerce JAVA-OBJECT into a Lisp object. \end{adjustwidth} \paragraph{} \label{JAVA:JPROPERTY-VALUE} \index{JPROPERTY-VALUE} --- Function: \textbf{jproperty-value} [\textbf{java}] \textit{object property} \begin{adjustwidth}{5em}{5em} setf-able access on the Java Beans notion of property named PROPETRY on OBJECT. \end{adjustwidth} \paragraph{} \label{JAVA:JREGISTER-HANDLER} \index{JREGISTER-HANDLER} --- Function: \textbf{jregister-handler} [\textbf{java}] \textit{object event handler \&key data count} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:JRESOLVE-METHOD} \index{JRESOLVE-METHOD} --- Function: \textbf{jresolve-method} [\textbf{java}] \textit{method-name instance \&rest args} \begin{adjustwidth}{5em}{5em} Finds the most specific Java method METHOD-NAME on INSTANCE applicable to arguments ARGS. Returns NIL if no suitable method is found. The algorithm used for resolution is the same used by JCALL when it is called with a string as the first parameter (METHOD-REF). \end{adjustwidth} \paragraph{} \label{JAVA:JRUN-EXCEPTION-PROTECTED} \index{JRUN-EXCEPTION-PROTECTED} --- Function: \textbf{jrun-exception-protected} [\textbf{java}] \textit{closure} \begin{adjustwidth}{5em}{5em} Invokes the function CLOSURE and returns the result. Signals an error if stack or heap exhaustion occurs. \end{adjustwidth} \paragraph{} \label{JAVA:JSTATIC} \index{JSTATIC} --- Function: \textbf{jstatic} [\textbf{java}] \textit{method class \&rest args} \begin{adjustwidth}{5em}{5em} Invokes the static method METHOD on class CLASS with ARGS. \end{adjustwidth} \paragraph{} \label{JAVA:JSTATIC-RAW} \index{JSTATIC-RAW} --- Function: \textbf{jstatic-raw} [\textbf{java}] \textit{method class \&rest args} \begin{adjustwidth}{5em}{5em} Invokes the static method METHOD on class CLASS with ARGS. Does not attempt to coerce the arguments or result into a Lisp object. \end{adjustwidth} \paragraph{} \label{JAVA:MAKE-CLASSLOADER} \index{MAKE-CLASSLOADER} --- Function: \textbf{make-classloader} [\textbf{java}] \textit{\&optional parent} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JAVA:MAKE-IMMEDIATE-OBJECT} \index{MAKE-IMMEDIATE-OBJECT} --- Function: \textbf{make-immediate-object} [\textbf{java}] \textit{object \&optional type} \begin{adjustwidth}{5em}{5em} Attempts to coerce a given Lisp object into a java-object of the given type. If type is not provided, works as jobject-lisp-value. Currently, type may be :BOOLEAN, treating the object as a truth value, or :REF, which returns Java null if NIL is provided. Deprecated. Please use JAVA:+NULL+, JAVA:+TRUE+, and JAVA:+FALSE+ for constructing wrapped primitive types, JAVA:JOBJECT-LISP-VALUE for converting a JAVA:JAVA-OBJECT to a Lisp value, or JAVA:JNULL-REF-P to distinguish a wrapped null JAVA-OBJECT from NIL. \end{adjustwidth} \paragraph{} \label{JAVA:REGISTER-JAVA-EXCEPTION} \index{REGISTER-JAVA-EXCEPTION} --- Function: \textbf{register-java-exception} [\textbf{java}] \textit{exception-name condition-symbol} \begin{adjustwidth}{5em}{5em} Registers the Java Throwable named by the symbol EXCEPTION-NAME as the condition designated by CONDITION-SYMBOL. Returns T if successful, NIL if not. \end{adjustwidth} \paragraph{} \label{JAVA:UNREGISTER-JAVA-EXCEPTION} \index{UNREGISTER-JAVA-EXCEPTION} --- Function: \textbf{unregister-java-exception} [\textbf{java}] \textit{exception-name} \begin{adjustwidth}{5em}{5em} Unregisters the Java Throwable EXCEPTION-NAME previously registered by REGISTER-JAVA-EXCEPTION. \end{adjustwidth} abcl-src-1.9.0/doc/manual/jss.aux0100644 0000000 0000000 00000011410 14242630063 015273 0ustar000000000 0000000 \relax \providecommand\hyper@newdestlabel[2]{} \newlabel{JSS:*CL-USER-COMPATIBILITY*}{{C}{90}{}{section*.632}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.632}\protected@file@percent } \newlabel{JSS:*DO-AUTO-IMPORTS*}{{C}{90}{}{section*.633}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.633}\protected@file@percent } \newlabel{JSS:*MUFFLE-WARNINGS*}{{C}{90}{}{section*.634}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.634}\protected@file@percent } \newlabel{JSS:CLASSFILES-IMPORT}{{C}{90}{}{section*.635}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.635}\protected@file@percent } \newlabel{JSS:ENSURE-COMPATIBILITY}{{C}{90}{}{section*.636}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.636}\protected@file@percent } \newlabel{JSS:FIND-JAVA-CLASS}{{C}{90}{}{section*.637}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.637}\protected@file@percent } \newlabel{JSS:GET-JAVA-FIELD}{{C}{90}{}{section*.638}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.638}\protected@file@percent } \newlabel{JSS:HASHMAP-TO-HASHTABLE}{{C}{90}{}{section*.639}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.639}\protected@file@percent } \newlabel{JSS:INVOKE-ADD-IMPORTS}{{C}{90}{}{section*.640}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.640}\protected@file@percent } \newlabel{JSS:INVOKE-RESTARGS}{{C}{90}{}{section*.641}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.641}\protected@file@percent } \newlabel{JSS:ITERABLE-TO-LIST}{{C}{90}{}{section*.642}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.642}\protected@file@percent } \newlabel{JSS:J2LIST}{{C}{90}{}{section*.643}{}} \@writefile{toc}{\contentsline {paragraph}{}{90}{section*.643}\protected@file@percent } \newlabel{JSS:JAPROPOS}{{C}{91}{}{section*.644}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.644}\protected@file@percent } \newlabel{JSS:JAR-IMPORT}{{C}{91}{}{section*.645}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.645}\protected@file@percent } \newlabel{JSS:JARRAY-TO-LIST}{{C}{91}{}{section*.646}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.646}\protected@file@percent } \newlabel{JSS:JAVA-CLASS-METHOD-NAMES}{{C}{91}{}{section*.647}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.647}\protected@file@percent } \newlabel{JSS:JCLASS-ALL-INTERFACES}{{C}{91}{}{section*.648}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.648}\protected@file@percent } \newlabel{JSS:JCMN}{{C}{91}{}{section*.649}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.649}\protected@file@percent } \newlabel{JSS:JLIST-TO-LIST}{{C}{91}{}{section*.650}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.650}\protected@file@percent } \newlabel{JSS:JMAP}{{C}{91}{}{section*.651}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.651}\protected@file@percent } \newlabel{JSS:JTYPECASE}{{C}{91}{}{section*.652}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.652}\protected@file@percent } \newlabel{JSS:JTYPEP}{{C}{91}{}{section*.653}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.653}\protected@file@percent } \newlabel{JSS:LIST-TO-LIST}{{C}{91}{}{section*.654}{}} \@writefile{toc}{\contentsline {paragraph}{}{91}{section*.654}\protected@file@percent } \newlabel{JSS:NEW}{{C}{92}{}{section*.655}{}} \@writefile{toc}{\contentsline {paragraph}{}{92}{section*.655}\protected@file@percent } \newlabel{JSS:SET-JAVA-FIELD}{{C}{92}{}{section*.656}{}} \@writefile{toc}{\contentsline {paragraph}{}{92}{section*.656}\protected@file@percent } \newlabel{JSS:SET-TO-LIST}{{C}{92}{}{section*.657}{}} \@writefile{toc}{\contentsline {paragraph}{}{92}{section*.657}\protected@file@percent } \newlabel{JSS:TO-HASHSET}{{C}{92}{}{section*.658}{}} \@writefile{toc}{\contentsline {paragraph}{}{92}{section*.658}\protected@file@percent } \newlabel{JSS:VECTOR-TO-LIST}{{C}{92}{}{section*.659}{}} \@writefile{toc}{\contentsline {paragraph}{}{92}{section*.659}\protected@file@percent } \newlabel{JSS:WITH-CONSTANT-SIGNATURE}{{C}{92}{}{section*.660}{}} \@writefile{toc}{\contentsline {paragraph}{}{92}{section*.660}\protected@file@percent } \@setckpt{jss}{ \setcounter{page}{93} \setcounter{equation}{0} \setcounter{enumi}{6} \setcounter{enumii}{0} \setcounter{enumiii}{0} \setcounter{enumiv}{0} \setcounter{footnote}{0} \setcounter{mpfootnote}{0} \setcounter{part}{0} \setcounter{chapter}{3} \setcounter{section}{0} \setcounter{subsection}{0} \setcounter{subsubsection}{0} \setcounter{paragraph}{0} \setcounter{subparagraph}{0} \setcounter{figure}{0} \setcounter{table}{0} \setcounter{Item}{6} \setcounter{Hfootnote}{28} \setcounter{bookmark@seq@number}{69} \setcounter{lstnumber}{38} \setcounter{cp@cntr}{0} \setcounter{section@level}{4} \setcounter{lstlisting}{0} } abcl-src-1.9.0/doc/manual/jss.tex0100644 0000000 0000000 00000021717 14242627550 015320 0ustar000000000 0000000 \paragraph{} \label{JSS:*CL-USER-COMPATIBILITY*} \index{*CL-USER-COMPATIBILITY*} --- Variable: \textbf{*cl-user-compatibility*} [\textbf{jss}] \textit{} \begin{adjustwidth}{5em}{5em} Whether backwards compatibility with JSS's use of CL-USER has been enabled. \end{adjustwidth} \paragraph{} \label{JSS:*DO-AUTO-IMPORTS*} \index{*DO-AUTO-IMPORTS*} --- Variable: \textbf{*do-auto-imports*} [\textbf{jss}] \textit{} \begin{adjustwidth}{5em}{5em} Whether to automatically introspect all Java classes on the classpath when JSS is loaded. \end{adjustwidth} \paragraph{} \label{JSS:*MUFFLE-WARNINGS*} \index{*MUFFLE-WARNINGS*} --- Variable: \textbf{*muffle-warnings*} [\textbf{jss}] \textit{} \begin{adjustwidth}{5em}{5em} Attempt to make JSS less chatting about how things are going. \end{adjustwidth} \paragraph{} \label{JSS:CLASSFILES-IMPORT} \index{CLASSFILES-IMPORT} --- Function: \textbf{classfiles-import} [\textbf{jss}] \textit{directory} \begin{adjustwidth}{5em}{5em} Load all Java classes recursively contained under DIRECTORY in the current process. \end{adjustwidth} \paragraph{} \label{JSS:ENSURE-COMPATIBILITY} \index{ENSURE-COMPATIBILITY} --- Function: \textbf{ensure-compatibility} [\textbf{jss}] \textit{} \begin{adjustwidth}{5em}{5em} Ensure backwards compatibility with JSS's use of CL-USER. \end{adjustwidth} \paragraph{} \label{JSS:FIND-JAVA-CLASS} \index{FIND-JAVA-CLASS} --- Function: \textbf{find-java-class} [\textbf{jss}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JSS:GET-JAVA-FIELD} \index{GET-JAVA-FIELD} --- Function: \textbf{get-java-field} [\textbf{jss}] \textit{object field \&optional (try-harder *running-in-osgi*)} \begin{adjustwidth}{5em}{5em} Get the value of the FIELD contained in OBJECT. If OBJECT is a symbol it names a dot qualified static FIELD. \end{adjustwidth} \paragraph{} \label{JSS:HASHMAP-TO-HASHTABLE} \index{HASHMAP-TO-HASHTABLE} --- Function: \textbf{hashmap-to-hashtable} [\textbf{jss}] \textit{hashmap \&rest rest \&key (keyfun (function identity)) (valfun (function identity)) (invert? NIL) table \&allow-other-keys} \begin{adjustwidth}{5em}{5em} Converts the a HASHMAP reference to a java.util.HashMap object to a Lisp hashtable. The REST paramter specifies arguments to the underlying MAKE-HASH-TABLE call. KEYFUN and VALFUN specifies functions to be run on the keys and values of the HASHMAP right before they are placed in the hashtable. If INVERT? is non-nil than reverse the keys and values in the resulting hashtable. \end{adjustwidth} \paragraph{} \label{JSS:INVOKE-ADD-IMPORTS} \index{INVOKE-ADD-IMPORTS} --- Macro: \textbf{invoke-add-imports} [\textbf{jss}] \textit{} \begin{adjustwidth}{5em}{5em} Push these imports onto the search path. If multiple, earlier in list take precedence \end{adjustwidth} \paragraph{} \label{JSS:INVOKE-RESTARGS} \index{INVOKE-RESTARGS} --- Function: \textbf{invoke-restargs} [\textbf{jss}] \textit{method object args \&optional (raw? NIL)} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JSS:ITERABLE-TO-LIST} \index{ITERABLE-TO-LIST} --- Function: \textbf{iterable-to-list} [\textbf{jss}] \textit{iterable} \begin{adjustwidth}{5em}{5em} Return the items contained the java.lang.Iterable ITERABLE as a list. \end{adjustwidth} \paragraph{} \label{JSS:J2LIST} \index{J2LIST} --- Function: \textbf{j2list} [\textbf{jss}] \textit{thing} \begin{adjustwidth}{5em}{5em} Attempt to construct a Lisp list out of a Java THING. THING may be a wide range of Java collection types, their common iterators or a Java array. \end{adjustwidth} \paragraph{} \label{JSS:JAPROPOS} \index{JAPROPOS} --- Function: \textbf{japropos} [\textbf{jss}] \textit{string} \begin{adjustwidth}{5em}{5em} Output the names of all Java class names loaded in the current process which match STRING.. \end{adjustwidth} \paragraph{} \label{JSS:JAR-IMPORT} \index{JAR-IMPORT} --- Function: \textbf{jar-import} [\textbf{jss}] \textit{file} \begin{adjustwidth}{5em}{5em} Import all the Java classes contained in the pathname FILE into the JSS dynamic lookup cache. \end{adjustwidth} \paragraph{} \label{JSS:JARRAY-TO-LIST} \index{JARRAY-TO-LIST} --- Function: \textbf{jarray-to-list} [\textbf{jss}] \textit{jarray} \begin{adjustwidth}{5em}{5em} Convert the Java array named by JARRARY into a Lisp list. \end{adjustwidth} \paragraph{} \label{JSS:JAVA-CLASS-METHOD-NAMES} \index{JAVA-CLASS-METHOD-NAMES} --- Function: \textbf{java-class-method-names} [\textbf{jss}] \textit{class \&optional stream} \begin{adjustwidth}{5em}{5em} Return a list of the public methods encapsulated by the JVM CLASS. If STREAM non-nil, output a verbose description to the named output stream. CLASS may either be a string naming a fully qualified JVM class in dot notation, or a symbol resolved against all class entries in the current classpath. \end{adjustwidth} \paragraph{} \label{JSS:JCLASS-ALL-INTERFACES} \index{JCLASS-ALL-INTERFACES} --- Function: \textbf{jclass-all-interfaces} [\textbf{jss}] \textit{class} \begin{adjustwidth}{5em}{5em} Return a list of interfaces the class implements \end{adjustwidth} \paragraph{} \label{JSS:JCMN} \index{JCMN} --- Function: \textbf{jcmn} [\textbf{jss}] \textit{class \&optional stream} \begin{adjustwidth}{5em}{5em} Return a list of the public methods encapsulated by the JVM CLASS. If STREAM non-nil, output a verbose description to the named output stream. CLASS may either be a string naming a fully qualified JVM class in dot notation, or a symbol resolved against all class entries in the current classpath. \end{adjustwidth} \paragraph{} \label{JSS:JLIST-TO-LIST} \index{JLIST-TO-LIST} --- Function: \textbf{jlist-to-list} [\textbf{jss}] \textit{list} \begin{adjustwidth}{5em}{5em} Convert a LIST implementing java.util.List to a Lisp list. \end{adjustwidth} \paragraph{} \label{JSS:JMAP} \index{JMAP} --- Function: \textbf{jmap} [\textbf{jss}] \textit{function thing} \begin{adjustwidth}{5em}{5em} Call FUNCTION for every element in the THING. Returns NIL. THING may be a wide range of Java collection types, their common iterators or a Java array. In case the THING is a map-like object, FUNCTION will be called with two arguments, key and value. \end{adjustwidth} \paragraph{} \label{JSS:JTYPECASE} \index{JTYPECASE} --- Macro: \textbf{jtypecase} [\textbf{jss}] \textit{} \begin{adjustwidth}{5em}{5em} JTYPECASE Keyform {(Type Form*)}* Evaluates the Forms in the first clause for which Type names a class that Keyform isInstance of is true. \end{adjustwidth} \paragraph{} \label{JSS:JTYPEP} \index{JTYPEP} --- Function: \textbf{jtypep} [\textbf{jss}] \textit{object type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JSS:LIST-TO-LIST} \index{LIST-TO-LIST} --- Function: \textbf{list-to-list} [\textbf{jss}] \textit{list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{JSS:NEW} \index{NEW} --- Function: \textbf{new} [\textbf{jss}] \textit{class-name \&rest args} \begin{adjustwidth}{5em}{5em} Invoke the Java constructor for CLASS-NAME with ARGS. CLASS-NAME may either be a symbol or a string according to the usual JSS conventions. \end{adjustwidth} \paragraph{} \label{JSS:SET-JAVA-FIELD} \index{SET-JAVA-FIELD} --- Function: \textbf{set-java-field} [\textbf{jss}] \textit{object field value \&optional (try-harder *running-in-osgi*)} \begin{adjustwidth}{5em}{5em} Set the FIELD of OBJECT to VALUE. If OBJECT is a symbol, it names a dot qualified Java class to look for a static FIELD. If OBJECT is an instance of java:java-object, the associated is used to look up the static FIELD. \end{adjustwidth} \paragraph{} \label{JSS:SET-TO-LIST} \index{SET-TO-LIST} --- Function: \textbf{set-to-list} [\textbf{jss}] \textit{set} \begin{adjustwidth}{5em}{5em} Convert the java.util.Set named in SET to a Lisp list. \end{adjustwidth} \paragraph{} \label{JSS:TO-HASHSET} \index{TO-HASHSET} --- Function: \textbf{to-hashset} [\textbf{jss}] \textit{list} \begin{adjustwidth}{5em}{5em} Convert LIST to the java.util.HashSet contract \end{adjustwidth} \paragraph{} \label{JSS:VECTOR-TO-LIST} \index{VECTOR-TO-LIST} --- Function: \textbf{vector-to-list} [\textbf{jss}] \textit{vector} \begin{adjustwidth}{5em}{5em} Return the elements of java.lang.Vector VECTOR as a list. \end{adjustwidth} \paragraph{} \label{JSS:WITH-CONSTANT-SIGNATURE} \index{WITH-CONSTANT-SIGNATURE} --- Macro: \textbf{with-constant-signature} [\textbf{jss}] \textit{} \begin{adjustwidth}{5em}{5em} Expand all references to FNAME-JNAME-PAIRS in BODY into static function calls promising that the same function bound in the FNAME-JNAME-PAIRS will be invoked with the same argument signature. FNAME-JNAME-PAIRS is a list of (symbol function \&optional raw) elements where symbol will be the symbol bound to the method named by the string function. If the optional parameter raw is non-nil, the result will be the raw JVM object, uncoerced by the usual conventions. Use this macro if you are making a lot of calls and want to avoid the overhead of the dynamic dispatch. \end{adjustwidth} abcl-src-1.9.0/doc/manual/mop.aux0100644 0000000 0000000 00000034613 14242630063 015301 0ustar000000000 0000000 \relax \providecommand\hyper@newdestlabel[2]{} \newlabel{MOP:DEFGENERIC}{{A}{60}{}{section*.246}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.246}\protected@file@percent } \newlabel{MOP:ACCESSOR-METHOD-SLOT-DEFINITION}{{A}{60}{}{section*.247}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.247}\protected@file@percent } \newlabel{MOP:ADD-DEPENDENT}{{A}{60}{}{section*.248}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.248}\protected@file@percent } \newlabel{MOP:ADD-DIRECT-METHOD}{{A}{60}{}{section*.249}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.249}\protected@file@percent } \newlabel{MOP:ADD-DIRECT-SUBCLASS}{{A}{60}{}{section*.250}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.250}\protected@file@percent } \newlabel{MOP:CANONICALIZE-DIRECT-SUPERCLASSES}{{A}{60}{}{section*.251}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.251}\protected@file@percent } \newlabel{MOP:CLASS-DEFAULT-INITARGS}{{A}{60}{}{section*.252}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.252}\protected@file@percent } \newlabel{MOP:CLASS-DIRECT-DEFAULT-INITARGS}{{A}{60}{}{section*.253}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.253}\protected@file@percent } \newlabel{MOP:CLASS-DIRECT-METHODS}{{A}{60}{}{section*.254}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.254}\protected@file@percent } \newlabel{MOP:CLASS-DIRECT-SLOTS}{{A}{60}{}{section*.255}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.255}\protected@file@percent } \newlabel{MOP:CLASS-DIRECT-SUBCLASSES}{{A}{60}{}{section*.256}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.256}\protected@file@percent } \newlabel{MOP:CLASS-DIRECT-SUPERCLASSES}{{A}{60}{}{section*.257}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.257}\protected@file@percent } \newlabel{MOP:CLASS-DOCUMENTATION}{{A}{60}{}{section*.258}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.258}\protected@file@percent } \newlabel{MOP:CLASS-FINALIZED-P}{{A}{60}{}{section*.259}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.259}\protected@file@percent } \newlabel{MOP:CLASS-PRECEDENCE-LIST}{{A}{60}{}{section*.260}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.260}\protected@file@percent } \newlabel{MOP:CLASS-PROTOTYPE}{{A}{60}{}{section*.261}{}} \@writefile{toc}{\contentsline {paragraph}{}{60}{section*.261}\protected@file@percent } \newlabel{MOP:CLASS-SLOTS}{{A}{61}{}{section*.262}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.262}\protected@file@percent } \newlabel{COMMON-LISP:COMPUTE-APPLICABLE-METHODS}{{A}{61}{}{section*.263}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.263}\protected@file@percent } \newlabel{MOP:COMPUTE-APPLICABLE-METHODS-USING-CLASSES}{{A}{61}{}{section*.264}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.264}\protected@file@percent } \newlabel{MOP:COMPUTE-CLASS-PRECEDENCE-LIST}{{A}{61}{}{section*.265}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.265}\protected@file@percent } \newlabel{MOP:COMPUTE-DEFAULT-INITARGS}{{A}{61}{}{section*.266}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.266}\protected@file@percent } \newlabel{MOP:COMPUTE-DISCRIMINATING-FUNCTION}{{A}{61}{}{section*.267}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.267}\protected@file@percent } \newlabel{MOP:COMPUTE-EFFECTIVE-METHOD}{{A}{61}{}{section*.268}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.268}\protected@file@percent } \newlabel{MOP:COMPUTE-EFFECTIVE-SLOT-DEFINITION}{{A}{61}{}{section*.269}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.269}\protected@file@percent } \newlabel{MOP:COMPUTE-SLOTS}{{A}{61}{}{section*.270}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.270}\protected@file@percent } \newlabel{MOP:DIRECT-SLOT-DEFINITION}{{A}{61}{}{section*.271}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.271}\protected@file@percent } \newlabel{MOP:DIRECT-SLOT-DEFINITION-CLASS}{{A}{61}{}{section*.272}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.272}\protected@file@percent } \newlabel{MOP:EFFECTIVE-SLOT-DEFINITION}{{A}{61}{}{section*.273}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.273}\protected@file@percent } \newlabel{MOP:EFFECTIVE-SLOT-DEFINITION-CLASS}{{A}{61}{}{section*.274}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.274}\protected@file@percent } \newlabel{MOP:ENSURE-CLASS}{{A}{61}{}{section*.275}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.275}\protected@file@percent } \newlabel{MOP:ENSURE-CLASS-USING-CLASS}{{A}{61}{}{section*.276}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.276}\protected@file@percent } \newlabel{MOP:ENSURE-GENERIC-FUNCTION-USING-CLASS}{{A}{61}{}{section*.277}{}} \@writefile{toc}{\contentsline {paragraph}{}{61}{section*.277}\protected@file@percent } \newlabel{MOP:EQL-SPECIALIZER}{{A}{62}{}{section*.278}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.278}\protected@file@percent } \newlabel{MOP:EQL-SPECIALIZER-OBJECT}{{A}{62}{}{section*.279}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.279}\protected@file@percent } \newlabel{MOP:EXTRACT-LAMBDA-LIST}{{A}{62}{}{section*.280}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.280}\protected@file@percent } \newlabel{MOP:EXTRACT-SPECIALIZER-NAMES}{{A}{62}{}{section*.281}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.281}\protected@file@percent } \newlabel{MOP:FINALIZE-INHERITANCE}{{A}{62}{}{section*.282}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.282}\protected@file@percent } \newlabel{MOP:FIND-METHOD-COMBINATION}{{A}{62}{}{section*.283}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.283}\protected@file@percent } \newlabel{SYSTEM:FORWARD-REFERENCED-CLASS}{{A}{62}{}{section*.284}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.284}\protected@file@percent } \newlabel{MOP:FUNCALLABLE-STANDARD-CLASS}{{A}{62}{}{section*.285}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.285}\protected@file@percent } \newlabel{MOP:FUNCALLABLE-STANDARD-INSTANCE-ACCESS}{{A}{62}{}{section*.286}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.286}\protected@file@percent } \newlabel{MOP:FUNCALLABLE-STANDARD-OBJECT}{{A}{62}{}{section*.287}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.287}\protected@file@percent } \newlabel{MOP:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER}{{A}{62}{}{section*.288}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.288}\protected@file@percent } \newlabel{MOP:GENERIC-FUNCTION-DECLARATIONS}{{A}{62}{}{section*.289}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.289}\protected@file@percent } \newlabel{MOP:GENERIC-FUNCTION-LAMBDA-LIST}{{A}{62}{}{section*.290}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.290}\protected@file@percent } \newlabel{MOP:GENERIC-FUNCTION-METHOD-CLASS}{{A}{62}{}{section*.291}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.291}\protected@file@percent } \newlabel{MOP:GENERIC-FUNCTION-METHOD-COMBINATION}{{A}{62}{}{section*.292}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.292}\protected@file@percent } \newlabel{MOP:GENERIC-FUNCTION-METHODS}{{A}{62}{}{section*.293}{}} \@writefile{toc}{\contentsline {paragraph}{}{62}{section*.293}\protected@file@percent } \newlabel{MOP:GENERIC-FUNCTION-NAME}{{A}{63}{}{section*.294}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.294}\protected@file@percent } \newlabel{MOP:INTERN-EQL-SPECIALIZER}{{A}{63}{}{section*.295}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.295}\protected@file@percent } \newlabel{MOP:MAKE-METHOD-LAMBDA}{{A}{63}{}{section*.296}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.296}\protected@file@percent } \newlabel{MOP:MAP-DEPENDENTS}{{A}{63}{}{section*.297}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.297}\protected@file@percent } \newlabel{MOP:METAOBJECT}{{A}{63}{}{section*.298}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.298}\protected@file@percent } \newlabel{MOP:METHOD-FUNCTION}{{A}{63}{}{section*.299}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.299}\protected@file@percent } \newlabel{MOP:METHOD-GENERIC-FUNCTION}{{A}{63}{}{section*.300}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.300}\protected@file@percent } \newlabel{MOP:METHOD-LAMBDA-LIST}{{A}{63}{}{section*.301}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.301}\protected@file@percent } \newlabel{COMMON-LISP:METHOD-QUALIFIERS}{{A}{63}{}{section*.302}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.302}\protected@file@percent } \newlabel{MOP:METHOD-SPECIALIZERS}{{A}{63}{}{section*.303}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.303}\protected@file@percent } \newlabel{MOP:READER-METHOD-CLASS}{{A}{63}{}{section*.304}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.304}\protected@file@percent } \newlabel{MOP:REMOVE-DEPENDENT}{{A}{63}{}{section*.305}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.305}\protected@file@percent } \newlabel{MOP:REMOVE-DIRECT-METHOD}{{A}{63}{}{section*.306}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.306}\protected@file@percent } \newlabel{MOP:REMOVE-DIRECT-SUBCLASS}{{A}{63}{}{section*.307}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.307}\protected@file@percent } \newlabel{MOP:SET-FUNCALLABLE-INSTANCE-FUNCTION}{{A}{63}{}{section*.308}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.308}\protected@file@percent } \newlabel{MOP:SLOT-BOUNDP-USING-CLASS}{{A}{63}{}{section*.309}{}} \@writefile{toc}{\contentsline {paragraph}{}{63}{section*.309}\protected@file@percent } \newlabel{SYSTEM:SLOT-DEFINITION}{{A}{64}{}{section*.310}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.310}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-ALLOCATION}{{A}{64}{}{section*.311}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.311}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-DOCUMENTATION}{{A}{64}{}{section*.312}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.312}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-INITARGS}{{A}{64}{}{section*.313}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.313}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-INITFORM}{{A}{64}{}{section*.314}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.314}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-INITFUNCTION}{{A}{64}{}{section*.315}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.315}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-LOCATION}{{A}{64}{}{section*.316}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.316}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-NAME}{{A}{64}{}{section*.317}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.317}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-READERS}{{A}{64}{}{section*.318}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.318}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-TYPE}{{A}{64}{}{section*.319}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.319}\protected@file@percent } \newlabel{MOP:SLOT-DEFINITION-WRITERS}{{A}{64}{}{section*.320}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.320}\protected@file@percent } \newlabel{MOP:SLOT-MAKUNBOUND-USING-CLASS}{{A}{64}{}{section*.321}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.321}\protected@file@percent } \newlabel{MOP:SLOT-VALUE-USING-CLASS}{{A}{64}{}{section*.322}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.322}\protected@file@percent } \newlabel{MOP:SPECIALIZER}{{A}{64}{}{section*.323}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.323}\protected@file@percent } \newlabel{MOP:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS}{{A}{64}{}{section*.324}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.324}\protected@file@percent } \newlabel{MOP:SPECIALIZER-DIRECT-METHODS}{{A}{64}{}{section*.325}{}} \@writefile{toc}{\contentsline {paragraph}{}{64}{section*.325}\protected@file@percent } \newlabel{MOP:STANDARD-ACCESSOR-METHOD}{{A}{65}{}{section*.326}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.326}\protected@file@percent } \newlabel{MOP:STANDARD-DIRECT-SLOT-DEFINITION}{{A}{65}{}{section*.327}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.327}\protected@file@percent } \newlabel{MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION}{{A}{65}{}{section*.328}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.328}\protected@file@percent } \newlabel{SYSTEM:STANDARD-INSTANCE-ACCESS}{{A}{65}{}{section*.329}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.329}\protected@file@percent } \newlabel{COMMON-LISP:STANDARD-METHOD}{{A}{65}{}{section*.330}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.330}\protected@file@percent } \newlabel{MOP:STANDARD-READER-METHOD}{{A}{65}{}{section*.331}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.331}\protected@file@percent } \newlabel{MOP:STANDARD-SLOT-DEFINITION}{{A}{65}{}{section*.332}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.332}\protected@file@percent } \newlabel{MOP:STANDARD-WRITER-METHOD}{{A}{65}{}{section*.333}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.333}\protected@file@percent } \newlabel{MOP:UPDATE-DEPENDENT}{{A}{65}{}{section*.334}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.334}\protected@file@percent } \newlabel{MOP:VALIDATE-SUPERCLASS}{{A}{65}{}{section*.335}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.335}\protected@file@percent } \newlabel{MOP:WRITER-METHOD-CLASS}{{A}{65}{}{section*.336}{}} \@writefile{toc}{\contentsline {paragraph}{}{65}{section*.336}\protected@file@percent } \@setckpt{mop}{ \setcounter{page}{66} \setcounter{equation}{0} \setcounter{enumi}{6} \setcounter{enumii}{0} \setcounter{enumiii}{0} \setcounter{enumiv}{0} \setcounter{footnote}{0} \setcounter{mpfootnote}{0} \setcounter{part}{0} \setcounter{chapter}{1} \setcounter{section}{0} \setcounter{subsection}{0} \setcounter{subsubsection}{0} \setcounter{paragraph}{0} \setcounter{subparagraph}{0} \setcounter{figure}{0} \setcounter{table}{0} \setcounter{Item}{6} \setcounter{Hfootnote}{28} \setcounter{bookmark@seq@number}{67} \setcounter{lstnumber}{38} \setcounter{cp@cntr}{0} \setcounter{section@level}{4} \setcounter{lstlisting}{0} } abcl-src-1.9.0/doc/manual/mop.tex0100644 0000000 0000000 00000050364 14202767264 015317 0ustar000000000 0000000 \paragraph{} \label{MOP:DEFGENERIC} \index{DEFGENERIC} --- Function: \textbf{\%defgeneric} [\textbf{mop}] \textit{function-name \&rest all-keys} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:ACCESSOR-METHOD-SLOT-DEFINITION} \index{ACCESSOR-METHOD-SLOT-DEFINITION} --- Generic Function: \textbf{accessor-method-slot-definition} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:ADD-DEPENDENT} \index{ADD-DEPENDENT} --- Generic Function: \textbf{add-dependent} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:ADD-DIRECT-METHOD} \index{ADD-DIRECT-METHOD} --- Generic Function: \textbf{add-direct-method} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:ADD-DIRECT-SUBCLASS} \index{ADD-DIRECT-SUBCLASS} --- Generic Function: \textbf{add-direct-subclass} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CANONICALIZE-DIRECT-SUPERCLASSES} \index{CANONICALIZE-DIRECT-SUPERCLASSES} --- Function: \textbf{canonicalize-direct-superclasses} [\textbf{mop}] \textit{direct-superclasses} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-DEFAULT-INITARGS} \index{CLASS-DEFAULT-INITARGS} --- Generic Function: \textbf{class-default-initargs} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-DIRECT-DEFAULT-INITARGS} \index{CLASS-DIRECT-DEFAULT-INITARGS} --- Generic Function: \textbf{class-direct-default-initargs} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-DIRECT-METHODS} \index{CLASS-DIRECT-METHODS} --- Generic Function: \textbf{class-direct-methods} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-DIRECT-SLOTS} \index{CLASS-DIRECT-SLOTS} --- Generic Function: \textbf{class-direct-slots} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-DIRECT-SUBCLASSES} \index{CLASS-DIRECT-SUBCLASSES} --- Generic Function: \textbf{class-direct-subclasses} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-DIRECT-SUPERCLASSES} \index{CLASS-DIRECT-SUPERCLASSES} --- Generic Function: \textbf{class-direct-superclasses} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-DOCUMENTATION} \index{CLASS-DOCUMENTATION} --- Function: \textbf{class-documentation} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-FINALIZED-P} \index{CLASS-FINALIZED-P} --- Generic Function: \textbf{class-finalized-p} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-PRECEDENCE-LIST} \index{CLASS-PRECEDENCE-LIST} --- Generic Function: \textbf{class-precedence-list} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-PROTOTYPE} \index{CLASS-PROTOTYPE} --- Generic Function: \textbf{class-prototype} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:CLASS-SLOTS} \index{CLASS-SLOTS} --- Generic Function: \textbf{class-slots} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{COMMON-LISP:COMPUTE-APPLICABLE-METHODS} \index{COMPUTE-APPLICABLE-METHODS} --- Generic Function: \textbf{compute-applicable-methods} [\textbf{common-lisp}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:COMPUTE-APPLICABLE-METHODS-USING-CLASSES} \index{COMPUTE-APPLICABLE-METHODS-USING-CLASSES} --- Generic Function: \textbf{compute-applicable-methods-using-classes} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:COMPUTE-CLASS-PRECEDENCE-LIST} \index{COMPUTE-CLASS-PRECEDENCE-LIST} --- Generic Function: \textbf{compute-class-precedence-list} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:COMPUTE-DEFAULT-INITARGS} \index{COMPUTE-DEFAULT-INITARGS} --- Generic Function: \textbf{compute-default-initargs} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:COMPUTE-DISCRIMINATING-FUNCTION} \index{COMPUTE-DISCRIMINATING-FUNCTION} --- Generic Function: \textbf{compute-discriminating-function} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:COMPUTE-EFFECTIVE-METHOD} \index{COMPUTE-EFFECTIVE-METHOD} --- Generic Function: \textbf{compute-effective-method} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:COMPUTE-EFFECTIVE-SLOT-DEFINITION} \index{COMPUTE-EFFECTIVE-SLOT-DEFINITION} --- Generic Function: \textbf{compute-effective-slot-definition} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:COMPUTE-SLOTS} \index{COMPUTE-SLOTS} --- Generic Function: \textbf{compute-slots} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:DIRECT-SLOT-DEFINITION} \index{DIRECT-SLOT-DEFINITION} --- Class: \textbf{direct-slot-definition} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:DIRECT-SLOT-DEFINITION-CLASS} \index{DIRECT-SLOT-DEFINITION-CLASS} --- Generic Function: \textbf{direct-slot-definition-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:EFFECTIVE-SLOT-DEFINITION} \index{EFFECTIVE-SLOT-DEFINITION} --- Class: \textbf{effective-slot-definition} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:EFFECTIVE-SLOT-DEFINITION-CLASS} \index{EFFECTIVE-SLOT-DEFINITION-CLASS} --- Generic Function: \textbf{effective-slot-definition-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:ENSURE-CLASS} \index{ENSURE-CLASS} --- Function: \textbf{ensure-class} [\textbf{mop}] \textit{name \&rest all-keys \&key \&allow-other-keys} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:ENSURE-CLASS-USING-CLASS} \index{ENSURE-CLASS-USING-CLASS} --- Generic Function: \textbf{ensure-class-using-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:ENSURE-GENERIC-FUNCTION-USING-CLASS} \index{ENSURE-GENERIC-FUNCTION-USING-CLASS} --- Generic Function: \textbf{ensure-generic-function-using-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:EQL-SPECIALIZER} \index{EQL-SPECIALIZER} --- Class: \textbf{eql-specializer} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:EQL-SPECIALIZER-OBJECT} \index{EQL-SPECIALIZER-OBJECT} --- Function: \textbf{eql-specializer-object} [\textbf{mop}] \textit{eql-specializer} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:EXTRACT-LAMBDA-LIST} \index{EXTRACT-LAMBDA-LIST} --- Function: \textbf{extract-lambda-list} [\textbf{mop}] \textit{specialized-lambda-list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:EXTRACT-SPECIALIZER-NAMES} \index{EXTRACT-SPECIALIZER-NAMES} --- Function: \textbf{extract-specializer-names} [\textbf{mop}] \textit{specialized-lambda-list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:FINALIZE-INHERITANCE} \index{FINALIZE-INHERITANCE} --- Generic Function: \textbf{finalize-inheritance} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:FIND-METHOD-COMBINATION} \index{FIND-METHOD-COMBINATION} --- Generic Function: \textbf{find-method-combination} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FORWARD-REFERENCED-CLASS} \index{FORWARD-REFERENCED-CLASS} --- Class: \textbf{forward-referenced-class} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:FUNCALLABLE-STANDARD-CLASS} \index{FUNCALLABLE-STANDARD-CLASS} --- Class: \textbf{funcallable-standard-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:FUNCALLABLE-STANDARD-INSTANCE-ACCESS} \index{FUNCALLABLE-STANDARD-INSTANCE-ACCESS} --- Function: \textbf{funcallable-standard-instance-access} [\textbf{mop}] \textit{instance location} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:FUNCALLABLE-STANDARD-OBJECT} \index{FUNCALLABLE-STANDARD-OBJECT} --- Class: \textbf{funcallable-standard-object} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER} \index{GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER} --- Generic Function: \textbf{generic-function-argument-precedence-order} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:GENERIC-FUNCTION-DECLARATIONS} \index{GENERIC-FUNCTION-DECLARATIONS} --- Generic Function: \textbf{generic-function-declarations} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:GENERIC-FUNCTION-LAMBDA-LIST} \index{GENERIC-FUNCTION-LAMBDA-LIST} --- Generic Function: \textbf{generic-function-lambda-list} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:GENERIC-FUNCTION-METHOD-CLASS} \index{GENERIC-FUNCTION-METHOD-CLASS} --- Generic Function: \textbf{generic-function-method-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:GENERIC-FUNCTION-METHOD-COMBINATION} \index{GENERIC-FUNCTION-METHOD-COMBINATION} --- Generic Function: \textbf{generic-function-method-combination} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:GENERIC-FUNCTION-METHODS} \index{GENERIC-FUNCTION-METHODS} --- Generic Function: \textbf{generic-function-methods} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:GENERIC-FUNCTION-NAME} \index{GENERIC-FUNCTION-NAME} --- Generic Function: \textbf{generic-function-name} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:INTERN-EQL-SPECIALIZER} \index{INTERN-EQL-SPECIALIZER} --- Function: \textbf{intern-eql-specializer} [\textbf{mop}] \textit{object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:MAKE-METHOD-LAMBDA} \index{MAKE-METHOD-LAMBDA} --- Generic Function: \textbf{make-method-lambda} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:MAP-DEPENDENTS} \index{MAP-DEPENDENTS} --- Generic Function: \textbf{map-dependents} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:METAOBJECT} \index{METAOBJECT} --- Class: \textbf{metaobject} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:METHOD-FUNCTION} \index{METHOD-FUNCTION} --- Generic Function: \textbf{method-function} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:METHOD-GENERIC-FUNCTION} \index{METHOD-GENERIC-FUNCTION} --- Generic Function: \textbf{method-generic-function} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:METHOD-LAMBDA-LIST} \index{METHOD-LAMBDA-LIST} --- Generic Function: \textbf{method-lambda-list} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{COMMON-LISP:METHOD-QUALIFIERS} \index{METHOD-QUALIFIERS} --- Generic Function: \textbf{method-qualifiers} [\textbf{common-lisp}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:METHOD-SPECIALIZERS} \index{METHOD-SPECIALIZERS} --- Generic Function: \textbf{method-specializers} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:READER-METHOD-CLASS} \index{READER-METHOD-CLASS} --- Generic Function: \textbf{reader-method-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:REMOVE-DEPENDENT} \index{REMOVE-DEPENDENT} --- Generic Function: \textbf{remove-dependent} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:REMOVE-DIRECT-METHOD} \index{REMOVE-DIRECT-METHOD} --- Generic Function: \textbf{remove-direct-method} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:REMOVE-DIRECT-SUBCLASS} \index{REMOVE-DIRECT-SUBCLASS} --- Generic Function: \textbf{remove-direct-subclass} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SET-FUNCALLABLE-INSTANCE-FUNCTION} \index{SET-FUNCALLABLE-INSTANCE-FUNCTION} --- Function: \textbf{set-funcallable-instance-function} [\textbf{mop}] \textit{funcallable-instance function} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-BOUNDP-USING-CLASS} \index{SLOT-BOUNDP-USING-CLASS} --- Generic Function: \textbf{slot-boundp-using-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SLOT-DEFINITION} \index{SLOT-DEFINITION} --- Class: \textbf{slot-definition} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-ALLOCATION} \index{SLOT-DEFINITION-ALLOCATION} --- Generic Function: \textbf{slot-definition-allocation} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-DOCUMENTATION} \index{SLOT-DEFINITION-DOCUMENTATION} --- Generic Function: \textbf{slot-definition-documentation} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-INITARGS} \index{SLOT-DEFINITION-INITARGS} --- Generic Function: \textbf{slot-definition-initargs} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-INITFORM} \index{SLOT-DEFINITION-INITFORM} --- Generic Function: \textbf{slot-definition-initform} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-INITFUNCTION} \index{SLOT-DEFINITION-INITFUNCTION} --- Generic Function: \textbf{slot-definition-initfunction} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-LOCATION} \index{SLOT-DEFINITION-LOCATION} --- Generic Function: \textbf{slot-definition-location} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-NAME} \index{SLOT-DEFINITION-NAME} --- Generic Function: \textbf{slot-definition-name} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-READERS} \index{SLOT-DEFINITION-READERS} --- Generic Function: \textbf{slot-definition-readers} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-TYPE} \index{SLOT-DEFINITION-TYPE} --- Generic Function: \textbf{slot-definition-type} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-DEFINITION-WRITERS} \index{SLOT-DEFINITION-WRITERS} --- Generic Function: \textbf{slot-definition-writers} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-MAKUNBOUND-USING-CLASS} \index{SLOT-MAKUNBOUND-USING-CLASS} --- Generic Function: \textbf{slot-makunbound-using-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SLOT-VALUE-USING-CLASS} \index{SLOT-VALUE-USING-CLASS} --- Generic Function: \textbf{slot-value-using-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SPECIALIZER} \index{SPECIALIZER} --- Class: \textbf{specializer} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS} \index{SPECIALIZER-DIRECT-GENERIC-FUNCTIONS} --- Generic Function: \textbf{specializer-direct-generic-functions} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:SPECIALIZER-DIRECT-METHODS} \index{SPECIALIZER-DIRECT-METHODS} --- Generic Function: \textbf{specializer-direct-methods} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:STANDARD-ACCESSOR-METHOD} \index{STANDARD-ACCESSOR-METHOD} --- Class: \textbf{standard-accessor-method} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:STANDARD-DIRECT-SLOT-DEFINITION} \index{STANDARD-DIRECT-SLOT-DEFINITION} --- Class: \textbf{standard-direct-slot-definition} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION} \index{STANDARD-EFFECTIVE-SLOT-DEFINITION} --- Class: \textbf{standard-effective-slot-definition} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STANDARD-INSTANCE-ACCESS} \index{STANDARD-INSTANCE-ACCESS} --- Function: \textbf{standard-instance-access} [\textbf{system}] \textit{instance location} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{COMMON-LISP:STANDARD-METHOD} \index{STANDARD-METHOD} --- Class: \textbf{standard-method} [\textbf{common-lisp}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:STANDARD-READER-METHOD} \index{STANDARD-READER-METHOD} --- Class: \textbf{standard-reader-method} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:STANDARD-SLOT-DEFINITION} \index{STANDARD-SLOT-DEFINITION} --- Class: \textbf{standard-slot-definition} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:STANDARD-WRITER-METHOD} \index{STANDARD-WRITER-METHOD} --- Class: \textbf{standard-writer-method} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:UPDATE-DEPENDENT} \index{UPDATE-DEPENDENT} --- Generic Function: \textbf{update-dependent} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{MOP:VALIDATE-SUPERCLASS} \index{VALIDATE-SUPERCLASS} --- Generic Function: \textbf{validate-superclass} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} This generic function is called to determine whether the class superclass is suitable for use as a superclass of class. \end{adjustwidth} \paragraph{} \label{MOP:WRITER-METHOD-CLASS} \index{WRITER-METHOD-CLASS} --- Generic Function: \textbf{writer-method-class} [\textbf{mop}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} abcl-src-1.9.0/doc/manual/package.lisp0100644 0000000 0000000 00000000172 14202767264 016256 0ustar000000000 0000000 (in-package :cl-user) (defpackage abcl/documentation (:use :cl) (:export #:index #:grovel-docstrings-as-tex)) abcl-src-1.9.0/doc/manual/system.aux0100644 0000000 0000000 00000127710 14242630063 016033 0ustar000000000 0000000 \relax \providecommand\hyper@newdestlabel[2]{} \newlabel{SYSTEM:ALLOCATE-FUNCALLABLE-INSTANCE}{{B}{68}{}{section*.337}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.337}\protected@file@percent } \newlabel{SYSTEM:CLASS-DEFAULT-INITARGS}{{B}{68}{}{section*.338}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.338}\protected@file@percent } \newlabel{SYSTEM:CLASS-DIRECT-DEFAULT-INITARGS}{{B}{68}{}{section*.339}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.339}\protected@file@percent } \newlabel{SYSTEM:CLASS-DIRECT-METHODS}{{B}{68}{}{section*.340}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.340}\protected@file@percent } \newlabel{SYSTEM:CLASS-DIRECT-SLOTS}{{B}{68}{}{section*.341}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.341}\protected@file@percent } \newlabel{SYSTEM:CLASS-DIRECT-SUBCLASSES}{{B}{68}{}{section*.342}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.342}\protected@file@percent } \newlabel{SYSTEM:CLASS-DIRECT-SUPERCLASSES}{{B}{68}{}{section*.343}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.343}\protected@file@percent } \newlabel{SYSTEM:CLASS-FINALIZED-P}{{B}{68}{}{section*.344}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.344}\protected@file@percent } \newlabel{SYSTEM:CLASS-LAYOUT}{{B}{68}{}{section*.345}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.345}\protected@file@percent } \newlabel{SYSTEM:CLASS-NAME}{{B}{68}{}{section*.346}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.346}\protected@file@percent } \newlabel{SYSTEM:CLASS-PRECEDENCE-LIST}{{B}{68}{}{section*.347}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.347}\protected@file@percent } \newlabel{SYSTEM:CLASS-SLOTS}{{B}{68}{}{section*.348}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.348}\protected@file@percent } \newlabel{SYSTEM:DEFUN}{{B}{68}{}{section*.349}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.349}\protected@file@percent } \newlabel{SYSTEM:DOCUMENTATION}{{B}{68}{}{section*.350}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.350}\protected@file@percent } \newlabel{SYSTEM:FLOAT-BITS}{{B}{68}{}{section*.351}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.351}\protected@file@percent } \newlabel{SYSTEM:IN-PACKAGE}{{B}{68}{}{section*.352}{}} \@writefile{toc}{\contentsline {paragraph}{}{68}{section*.352}\protected@file@percent } \newlabel{SYSTEM:MAKE-CONDITION}{{B}{69}{}{section*.353}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.353}\protected@file@percent } \newlabel{SYSTEM:MAKE-EMF-CACHE}{{B}{69}{}{section*.354}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.354}\protected@file@percent } \newlabel{SYSTEM:MAKE-INSTANCES-OBSOLETE}{{B}{69}{}{section*.355}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.355}\protected@file@percent } \newlabel{SYSTEM:MAKE-INTEGER-TYPE}{{B}{69}{}{section*.356}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.356}\protected@file@percent } \newlabel{SYSTEM:MAKE-LIST}{{B}{69}{}{section*.357}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.357}\protected@file@percent } \newlabel{SYSTEM:MAKE-LOGICAL-PATHNAME}{{B}{69}{}{section*.358}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.358}\protected@file@percent } \newlabel{SYSTEM:MAKE-SLOT-DEFINITION}{{B}{69}{}{section*.359}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.359}\protected@file@percent } \newlabel{SYSTEM:MAKE-STRUCTURE}{{B}{69}{}{section*.360}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.360}\protected@file@percent } \newlabel{SYSTEM:MEMBER}{{B}{69}{}{section*.361}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.361}\protected@file@percent } \newlabel{SYSTEM:NSTRING-CAPITALIZE}{{B}{69}{}{section*.362}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.362}\protected@file@percent } \newlabel{SYSTEM:NSTRING-DOWNCASE}{{B}{69}{}{section*.363}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.363}\protected@file@percent } \newlabel{SYSTEM:NSTRING-UPCASE}{{B}{69}{}{section*.364}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.364}\protected@file@percent } \newlabel{SYSTEM:OUTPUT-OBJECT}{{B}{69}{}{section*.365}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.365}\protected@file@percent } \newlabel{SYSTEM:PUTF}{{B}{69}{}{section*.366}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.366}\protected@file@percent } \newlabel{SYSTEM:REINIT-EMF-CACHE}{{B}{69}{}{section*.367}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.367}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-DEFAULT-INITARGS}{{B}{69}{}{section*.368}{}} \@writefile{toc}{\contentsline {paragraph}{}{69}{section*.368}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-DIRECT-DEFAULT-INITARGS}{{B}{70}{}{section*.369}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.369}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-DIRECT-METHODS}{{B}{70}{}{section*.370}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.370}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-DIRECT-SLOTS}{{B}{70}{}{section*.371}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.371}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-DIRECT-SUBCLASSES}{{B}{70}{}{section*.372}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.372}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-DIRECT-SUPERCLASSES}{{B}{70}{}{section*.373}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.373}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-DOCUMENTATION}{{B}{70}{}{section*.374}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.374}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-FINALIZED-P}{{B}{70}{}{section*.375}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.375}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-LAYOUT}{{B}{70}{}{section*.376}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.376}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-NAME}{{B}{70}{}{section*.377}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.377}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-PRECEDENCE-LIST}{{B}{70}{}{section*.378}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.378}\protected@file@percent } \newlabel{SYSTEM:SET-CLASS-SLOTS}{{B}{70}{}{section*.379}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.379}\protected@file@percent } \newlabel{SYSTEM:SET-DOCUMENTATION}{{B}{70}{}{section*.380}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.380}\protected@file@percent } \newlabel{SYSTEM:SET-FILL-POINTER}{{B}{70}{}{section*.381}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.381}\protected@file@percent } \newlabel{SYSTEM:SET-FIND-CLASS}{{B}{70}{}{section*.382}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.382}\protected@file@percent } \newlabel{SYSTEM:SET-STANDARD-INSTANCE-ACCESS}{{B}{70}{}{section*.383}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.383}\protected@file@percent } \newlabel{SYSTEM:SET-STD-INSTANCE-LAYOUT}{{B}{70}{}{section*.384}{}} \@writefile{toc}{\contentsline {paragraph}{}{70}{section*.384}\protected@file@percent } \newlabel{SYSTEM:STD-ALLOCATE-INSTANCE}{{B}{71}{}{section*.385}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.385}\protected@file@percent } \newlabel{SYSTEM:STREAM-OUTPUT-OBJECT}{{B}{71}{}{section*.386}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.386}\protected@file@percent } \newlabel{SYSTEM:STREAM-TERPRI}{{B}{71}{}{section*.387}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.387}\protected@file@percent } \newlabel{SYSTEM:STREAM-WRITE-CHAR}{{B}{71}{}{section*.388}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.388}\protected@file@percent } \newlabel{SYSTEM:STRING-CAPITALIZE}{{B}{71}{}{section*.389}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.389}\protected@file@percent } \newlabel{SYSTEM:STRING-DOWNCASE}{{B}{71}{}{section*.390}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.390}\protected@file@percent } \newlabel{SYSTEM:STRING-EQUAL}{{B}{71}{}{section*.391}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.391}\protected@file@percent } \newlabel{SYSTEM:STRING-GREATERP}{{B}{71}{}{section*.392}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.392}\protected@file@percent } \newlabel{SYSTEM:STRING-LESSP}{{B}{71}{}{section*.393}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.393}\protected@file@percent } \newlabel{SYSTEM:STRING-NOT-EQUAL}{{B}{71}{}{section*.394}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.394}\protected@file@percent } \newlabel{SYSTEM:STRING-NOT-GREATERP}{{B}{71}{}{section*.395}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.395}\protected@file@percent } \newlabel{SYSTEM:STRING-NOT-LESSP}{{B}{71}{}{section*.396}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.396}\protected@file@percent } \newlabel{SYSTEM:STRING-UPCASE}{{B}{71}{}{section*.397}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.397}\protected@file@percent } \newlabel{SYSTEM:STRING/=}{{B}{71}{}{section*.398}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.398}\protected@file@percent } \newlabel{SYSTEM:STRING<}{{B}{71}{}{section*.399}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.399}\protected@file@percent } \newlabel{SYSTEM:STRING<=}{{B}{71}{}{section*.400}{}} \@writefile{toc}{\contentsline {paragraph}{}{71}{section*.400}\protected@file@percent } \newlabel{SYSTEM:STRING>}{{B}{72}{}{section*.401}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.401}\protected@file@percent } \newlabel{SYSTEM:STRING>=}{{B}{72}{}{section*.402}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.402}\protected@file@percent } \newlabel{SYSTEM:TYPE-ERROR}{{B}{72}{}{section*.403}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.403}\protected@file@percent } \newlabel{SYSTEM:WILD-PATHNAME-P}{{B}{72}{}{section*.404}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.404}\protected@file@percent } \newlabel{SYSTEM:*ABCL-CONTRIB*}{{B}{72}{}{section*.405}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.405}\protected@file@percent } \newlabel{SYSTEM:*COMPILE-FILE-CLASS-EXTENSION*}{{B}{72}{}{section*.406}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.406}\protected@file@percent } \newlabel{SYSTEM:*COMPILE-FILE-ENVIRONMENT*}{{B}{72}{}{section*.407}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.407}\protected@file@percent } \newlabel{SYSTEM:*COMPILE-FILE-TYPE*}{{B}{72}{}{section*.408}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.408}\protected@file@percent } \newlabel{SYSTEM:*COMPILE-FILE-ZIP*}{{B}{72}{}{section*.409}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.409}\protected@file@percent } \newlabel{SYSTEM:*COMPILER-DIAGNOSTIC*}{{B}{72}{}{section*.410}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.410}\protected@file@percent } \newlabel{SYSTEM:*COMPILER-ERROR-CONTEXT*}{{B}{72}{}{section*.411}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.411}\protected@file@percent } \newlabel{SYSTEM:*CURRENT-PRINT-LENGTH*}{{B}{72}{}{section*.412}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.412}\protected@file@percent } \newlabel{SYSTEM:*CURRENT-PRINT-LEVEL*}{{B}{72}{}{section*.413}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.413}\protected@file@percent } \newlabel{SYSTEM:*DEBUG*}{{B}{72}{}{section*.414}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.414}\protected@file@percent } \newlabel{ABCL-INTROSPECT/SYSTEM:*DEBUGGING-LOCALS-P*}{{B}{72}{}{section*.415}{}} \@writefile{toc}{\contentsline {paragraph}{}{72}{section*.415}\protected@file@percent } \newlabel{SYSTEM:*DISASSEMBLERS*}{{B}{73}{}{section*.416}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.416}\protected@file@percent } \newlabel{SYSTEM:*ENABLE-AUTOCOMPILE*}{{B}{73}{}{section*.417}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.417}\protected@file@percent } \newlabel{SYSTEM:*EXPLAIN*}{{B}{73}{}{section*.418}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.418}\protected@file@percent } \newlabel{SYSTEM:*FASL-LOADER*}{{B}{73}{}{section*.419}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.419}\protected@file@percent } \newlabel{SYSTEM:*FASL-VERSION*}{{B}{73}{}{section*.420}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.420}\protected@file@percent } \newlabel{SYSTEM:*INLINE-DECLARATIONS*}{{B}{73}{}{section*.421}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.421}\protected@file@percent } \newlabel{SYSTEM:*LOGICAL-PATHNAME-TRANSLATIONS*}{{B}{73}{}{section*.422}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.422}\protected@file@percent } \newlabel{SYSTEM:*NOINFORM*}{{B}{73}{}{section*.423}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.423}\protected@file@percent } \newlabel{SYSTEM:*SAFETY*}{{B}{73}{}{section*.424}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.424}\protected@file@percent } \newlabel{SYSTEM:*SOURCE*}{{B}{73}{}{section*.425}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.425}\protected@file@percent } \newlabel{SYSTEM:*SOURCE-POSITION*}{{B}{73}{}{section*.426}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.426}\protected@file@percent } \newlabel{SYSTEM:*SPACE*}{{B}{73}{}{section*.427}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.427}\protected@file@percent } \newlabel{SYSTEM:*SPEED*}{{B}{73}{}{section*.428}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.428}\protected@file@percent } \newlabel{SYSTEM:*TRACED-NAMES*}{{B}{73}{}{section*.429}{}} \@writefile{toc}{\contentsline {paragraph}{}{73}{section*.429}\protected@file@percent } \newlabel{SYSTEM:+CL-PACKAGE+}{{B}{74}{}{section*.430}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.430}\protected@file@percent } \newlabel{SYSTEM:+FALSE-TYPE+}{{B}{74}{}{section*.431}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.431}\protected@file@percent } \newlabel{SYSTEM:+FIXNUM-TYPE+}{{B}{74}{}{section*.432}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.432}\protected@file@percent } \newlabel{SYSTEM:+INTEGER-TYPE+}{{B}{74}{}{section*.433}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.433}\protected@file@percent } \newlabel{SYSTEM:+KEYWORD-PACKAGE+}{{B}{74}{}{section*.434}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.434}\protected@file@percent } \newlabel{SYSTEM:+SLOT-UNBOUND+}{{B}{74}{}{section*.435}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.435}\protected@file@percent } \newlabel{SYSTEM:+TRUE-TYPE+}{{B}{74}{}{section*.436}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.436}\protected@file@percent } \newlabel{SYSTEM:ASET}{{B}{74}{}{section*.437}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.437}\protected@file@percent } \newlabel{SYSTEM:AUTOCOMPILE}{{B}{74}{}{section*.438}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.438}\protected@file@percent } \newlabel{SYSTEM:AVAILABLE-ENCODINGS}{{B}{74}{}{section*.439}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.439}\protected@file@percent } \newlabel{SYSTEM:AVER}{{B}{74}{}{section*.440}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.440}\protected@file@percent } \newlabel{SYSTEM:BACKTRACE}{{B}{74}{}{section*.441}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.441}\protected@file@percent } \newlabel{SYSTEM:BUILT-IN-FUNCTION-P}{{B}{74}{}{section*.442}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.442}\protected@file@percent } \newlabel{SYSTEM:CACHE-EMF}{{B}{74}{}{section*.443}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.443}\protected@file@percent } \newlabel{SYSTEM:CALL-COUNT}{{B}{74}{}{section*.444}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.444}\protected@file@percent } \newlabel{SYSTEM:CALL-REGISTERS-LIMIT}{{B}{74}{}{section*.445}{}} \@writefile{toc}{\contentsline {paragraph}{}{74}{section*.445}\protected@file@percent } \newlabel{SYSTEM:CANONICALIZE-LOGICAL-HOST}{{B}{75}{}{section*.446}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.446}\protected@file@percent } \newlabel{SYSTEM:CHECK-DECLARATION-TYPE}{{B}{75}{}{section*.447}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.447}\protected@file@percent } \newlabel{SYSTEM:CHECK-SEQUENCE-BOUNDS}{{B}{75}{}{section*.448}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.448}\protected@file@percent } \newlabel{SYSTEM:CHOOSE-DISASSEMBLER}{{B}{75}{}{section*.449}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.449}\protected@file@percent } \newlabel{SYSTEM:CLASS-BYTES}{{B}{75}{}{section*.450}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.450}\protected@file@percent } \newlabel{SYSTEM:CLEAR-ZIP-CACHE}{{B}{75}{}{section*.451}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.451}\protected@file@percent } \newlabel{SYSTEM:COERCE-TO-CONDITION}{{B}{75}{}{section*.452}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.452}\protected@file@percent } \newlabel{SYSTEM:COERCE-TO-FUNCTION}{{B}{75}{}{section*.453}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.453}\protected@file@percent } \newlabel{SYSTEM:COMPILE-FILE-IF-NEEDED}{{B}{75}{}{section*.454}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.454}\protected@file@percent } \newlabel{EXTENSIONS:COMPILE-SYSTEM}{{B}{75}{}{section*.455}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.455}\protected@file@percent } \newlabel{SYSTEM:COMPILED-LISP-FUNCTION-P}{{B}{75}{}{section*.456}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.456}\protected@file@percent } \newlabel{SYSTEM:COMPILER-DEFSTRUCT}{{B}{75}{}{section*.457}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.457}\protected@file@percent } \newlabel{SYSTEM:COMPILER-ERROR}{{B}{75}{}{section*.458}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.458}\protected@file@percent } \newlabel{SYSTEM:COMPILER-MACROEXPAND}{{B}{75}{}{section*.459}{}} \@writefile{toc}{\contentsline {paragraph}{}{75}{section*.459}\protected@file@percent } \newlabel{SYSTEM:COMPILER-STYLE-WARN}{{B}{76}{}{section*.460}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.460}\protected@file@percent } \newlabel{SYSTEM:COMPILER-SUBTYPEP}{{B}{76}{}{section*.461}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.461}\protected@file@percent } \newlabel{SYSTEM:COMPILER-UNSUPPORTED}{{B}{76}{}{section*.462}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.462}\protected@file@percent } \newlabel{SYSTEM:COMPILER-WARN}{{B}{76}{}{section*.463}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.463}\protected@file@percent } \newlabel{SYSTEM:CONCATENATE-FASLS}{{B}{76}{}{section*.464}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.464}\protected@file@percent } \newlabel{SYSTEM:DEFCONST}{{B}{76}{}{section*.465}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.465}\protected@file@percent } \newlabel{SYSTEM:DEFINE-SOURCE-TRANSFORM}{{B}{76}{}{section*.466}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.466}\protected@file@percent } \newlabel{SYSTEM:DEFKNOWN}{{B}{76}{}{section*.467}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.467}\protected@file@percent } \newlabel{SYSTEM:DELETE-EQ}{{B}{76}{}{section*.468}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.468}\protected@file@percent } \newlabel{SYSTEM:DELETE-EQL}{{B}{76}{}{section*.469}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.469}\protected@file@percent } \newlabel{SYSTEM:DESCRIBE-COMPILER-POLICY}{{B}{76}{}{section*.470}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.470}\protected@file@percent } \newlabel{SYSTEM:DISABLE-ZIP-CACHE}{{B}{76}{}{section*.471}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.471}\protected@file@percent } \newlabel{SYSTEM:DISASSEMBLE-CLASS-BYTES}{{B}{76}{}{section*.472}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.472}\protected@file@percent } \newlabel{SYSTEM:DOUBLE-FLOAT-HIGH-BITS}{{B}{76}{}{section*.473}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.473}\protected@file@percent } \newlabel{SYSTEM:DOUBLE-FLOAT-LOW-BITS}{{B}{76}{}{section*.474}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.474}\protected@file@percent } \newlabel{SYSTEM:DUMP-FORM}{{B}{76}{}{section*.475}{}} \@writefile{toc}{\contentsline {paragraph}{}{76}{section*.475}\protected@file@percent } \newlabel{SYSTEM:DUMP-UNINTERNED-SYMBOL-INDEX}{{B}{77}{}{section*.476}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.476}\protected@file@percent } \newlabel{SYSTEM:EMPTY-ENVIRONMENT-P}{{B}{77}{}{section*.477}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.477}\protected@file@percent } \newlabel{SYSTEM:ENVIRONMENT}{{B}{77}{}{section*.478}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.478}\protected@file@percent } \newlabel{SYSTEM:ENVIRONMENT-ADD-FUNCTION-DEFINITION}{{B}{77}{}{section*.479}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.479}\protected@file@percent } \newlabel{SYSTEM:ENVIRONMENT-ADD-MACRO-DEFINITION}{{B}{77}{}{section*.480}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.480}\protected@file@percent } \newlabel{SYSTEM:ENVIRONMENT-ADD-SYMBOL-BINDING}{{B}{77}{}{section*.481}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.481}\protected@file@percent } \newlabel{SYSTEM:ENVIRONMENT-ALL-FUNCTIONS}{{B}{77}{}{section*.482}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.482}\protected@file@percent } \newlabel{SYSTEM:ENVIRONMENT-ALL-VARIABLES}{{B}{77}{}{section*.483}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.483}\protected@file@percent } \newlabel{SYSTEM:ENVIRONMENT-VARIABLES}{{B}{77}{}{section*.484}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.484}\protected@file@percent } \newlabel{SYSTEM:EXPAND-INLINE}{{B}{77}{}{section*.485}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.485}\protected@file@percent } \newlabel{SYSTEM:EXPAND-SOURCE-TRANSFORM}{{B}{77}{}{section*.486}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.486}\protected@file@percent } \newlabel{SYSTEM:FDEFINITION-BLOCK-NAME}{{B}{77}{}{section*.487}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.487}\protected@file@percent } \newlabel{SYSTEM:FIND-CONTRIB}{{B}{77}{}{section*.488}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.488}\protected@file@percent } \newlabel{ABCL-INTROSPECT/SYSTEM:FIND-LOCALS}{{B}{77}{}{section*.489}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.489}\protected@file@percent } \newlabel{SYSTEM:FIND-SYSTEM}{{B}{77}{}{section*.490}{}} \@writefile{toc}{\contentsline {paragraph}{}{77}{section*.490}\protected@file@percent } \newlabel{SYSTEM:FIXNUM-CONSTANT-VALUE}{{B}{78}{}{section*.491}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.491}\protected@file@percent } \newlabel{SYSTEM:FIXNUM-TYPE-P}{{B}{78}{}{section*.492}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.492}\protected@file@percent } \newlabel{SYSTEM:FLOAT-INFINITY-P}{{B}{78}{}{section*.493}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.493}\protected@file@percent } \newlabel{SYSTEM:FLOAT-NAN-P}{{B}{78}{}{section*.494}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.494}\protected@file@percent } \newlabel{SYSTEM:FLOAT-OVERFLOW-MODE}{{B}{78}{}{section*.495}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.495}\protected@file@percent } \newlabel{SYSTEM:FLOAT-STRING}{{B}{78}{}{section*.496}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.496}\protected@file@percent } \newlabel{SYSTEM:FLOAT-UNDERFLOW-MODE}{{B}{78}{}{section*.497}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.497}\protected@file@percent } \newlabel{SYSTEM:FORWARD-REFERENCED-CLASS}{{B}{78}{}{section*.498}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.498}\protected@file@percent } \newlabel{SYSTEM:FRAME-TO-LIST}{{B}{78}{}{section*.499}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.499}\protected@file@percent } \newlabel{SYSTEM:FRAME-TO-STRING}{{B}{78}{}{section*.500}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.500}\protected@file@percent } \newlabel{SYSTEM:FSET}{{B}{78}{}{section*.501}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.501}\protected@file@percent } \newlabel{SYSTEM:FTYPE-RESULT-TYPE}{{B}{78}{}{section*.502}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.502}\protected@file@percent } \newlabel{SYSTEM:FUNCTION-PLIST}{{B}{78}{}{section*.503}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.503}\protected@file@percent } \newlabel{SYSTEM:FUNCTION-RESULT-TYPE}{{B}{78}{}{section*.504}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.504}\protected@file@percent } \newlabel{SYSTEM:GET-CACHED-EMF}{{B}{78}{}{section*.505}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.505}\protected@file@percent } \newlabel{SYSTEM:GET-FUNCTION-INFO-VALUE}{{B}{78}{}{section*.506}{}} \@writefile{toc}{\contentsline {paragraph}{}{78}{section*.506}\protected@file@percent } \newlabel{SYSTEM:GET-INPUT-STREAM}{{B}{79}{}{section*.507}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.507}\protected@file@percent } \newlabel{SYSTEM:GETHASH1}{{B}{79}{}{section*.508}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.508}\protected@file@percent } \newlabel{SYSTEM:GROVEL-JAVA-DEFINITIONS-IN-FILE}{{B}{79}{}{section*.509}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.509}\protected@file@percent } \newlabel{SYSTEM:HASH-TABLE-WEAKNESS}{{B}{79}{}{section*.510}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.510}\protected@file@percent } \newlabel{SYSTEM:HOT-COUNT}{{B}{79}{}{section*.511}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.511}\protected@file@percent } \newlabel{SYSTEM:IDENTITY-HASH-CODE}{{B}{79}{}{section*.512}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.512}\protected@file@percent } \newlabel{SYSTEM:INIT-FASL}{{B}{79}{}{section*.513}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.513}\protected@file@percent } \newlabel{SYSTEM:INLINE-EXPANSION}{{B}{79}{}{section*.514}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.514}\protected@file@percent } \newlabel{SYSTEM:INLINE-P}{{B}{79}{}{section*.515}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.515}\protected@file@percent } \newlabel{SYSTEM:INSPECTED-PARTS}{{B}{79}{}{section*.516}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.516}\protected@file@percent } \newlabel{SYSTEM:INTEGER-CONSTANT-VALUE}{{B}{79}{}{section*.517}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.517}\protected@file@percent } \newlabel{SYSTEM:INTEGER-TYPE-HIGH}{{B}{79}{}{section*.518}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.518}\protected@file@percent } \newlabel{SYSTEM:INTEGER-TYPE-LOW}{{B}{79}{}{section*.519}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.519}\protected@file@percent } \newlabel{SYSTEM:INTEGER-TYPE-P}{{B}{79}{}{section*.520}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.520}\protected@file@percent } \newlabel{SYSTEM:INTERACTIVE-EVAL}{{B}{79}{}{section*.521}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.521}\protected@file@percent } \newlabel{SYSTEM:INTERNAL-COMPILER-ERROR}{{B}{79}{}{section*.522}{}} \@writefile{toc}{\contentsline {paragraph}{}{79}{section*.522}\protected@file@percent } \newlabel{SYSTEM:JAR-STREAM}{{B}{80}{}{section*.523}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.523}\protected@file@percent } \newlabel{SYSTEM:JAVA-LONG-TYPE-P}{{B}{80}{}{section*.524}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.524}\protected@file@percent } \newlabel{SYSTEM:JAVA.CLASS.PATH}{{B}{80}{}{section*.525}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.525}\protected@file@percent } \newlabel{SYSTEM:LAMBDA-NAME}{{B}{80}{}{section*.526}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.526}\protected@file@percent } \newlabel{SYSTEM:LAYOUT-CLASS}{{B}{80}{}{section*.527}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.527}\protected@file@percent } \newlabel{SYSTEM:LAYOUT-LENGTH}{{B}{80}{}{section*.528}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.528}\protected@file@percent } \newlabel{SYSTEM:LAYOUT-SLOT-INDEX}{{B}{80}{}{section*.529}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.529}\protected@file@percent } \newlabel{SYSTEM:LAYOUT-SLOT-LOCATION}{{B}{80}{}{section*.530}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.530}\protected@file@percent } \newlabel{SYSTEM:LIST-DELETE-EQ}{{B}{80}{}{section*.531}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.531}\protected@file@percent } \newlabel{SYSTEM:LIST-DELETE-EQL}{{B}{80}{}{section*.532}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.532}\protected@file@percent } \newlabel{SYSTEM:LIST-DIRECTORY}{{B}{80}{}{section*.533}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.533}\protected@file@percent } \newlabel{SYSTEM:LOAD-COMPILED-FUNCTION}{{B}{80}{}{section*.534}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.534}\protected@file@percent } \newlabel{SYSTEM:LOAD-SYSTEM-FILE}{{B}{80}{}{section*.535}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.535}\protected@file@percent } \newlabel{SYSTEM:LOGICAL-HOST-P}{{B}{80}{}{section*.536}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.536}\protected@file@percent } \newlabel{SYSTEM:LOGICAL-PATHNAME-P}{{B}{80}{}{section*.537}{}} \@writefile{toc}{\contentsline {paragraph}{}{80}{section*.537}\protected@file@percent } \newlabel{SYSTEM:LOOKUP-KNOWN-SYMBOL}{{B}{81}{}{section*.538}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.538}\protected@file@percent } \newlabel{SYSTEM:MACRO-FUNCTION-P}{{B}{81}{}{section*.539}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.539}\protected@file@percent } \newlabel{SYSTEM:MAKE-CLOSURE}{{B}{81}{}{section*.540}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.540}\protected@file@percent } \newlabel{SYSTEM:MAKE-COMPILER-TYPE}{{B}{81}{}{section*.541}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.541}\protected@file@percent } \newlabel{SYSTEM:MAKE-DOUBLE-FLOAT}{{B}{81}{}{section*.542}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.542}\protected@file@percent } \newlabel{SYSTEM:MAKE-ENVIRONMENT}{{B}{81}{}{section*.543}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.543}\protected@file@percent } \newlabel{SYSTEM:MAKE-FILE-STREAM}{{B}{81}{}{section*.544}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.544}\protected@file@percent } \newlabel{SYSTEM:MAKE-FILL-POINTER-OUTPUT-STREAM}{{B}{81}{}{section*.545}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.545}\protected@file@percent } \newlabel{SYSTEM:MAKE-INTEGER-TYPE}{{B}{81}{}{section*.546}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.546}\protected@file@percent } \newlabel{SYSTEM:MAKE-KEYWORD}{{B}{81}{}{section*.547}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.547}\protected@file@percent } \newlabel{SYSTEM:MAKE-LAYOUT}{{B}{81}{}{section*.548}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.548}\protected@file@percent } \newlabel{SYSTEM:MAKE-MACRO}{{B}{81}{}{section*.549}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.549}\protected@file@percent } \newlabel{SYSTEM:MAKE-MACRO-EXPANDER}{{B}{81}{}{section*.550}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.550}\protected@file@percent } \newlabel{SYSTEM:MAKE-SINGLE-FLOAT}{{B}{81}{}{section*.551}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.551}\protected@file@percent } \newlabel{SYSTEM:MAKE-STRUCTURE}{{B}{81}{}{section*.552}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.552}\protected@file@percent } \newlabel{SYSTEM:MAKE-SYMBOL-MACRO}{{B}{81}{}{section*.553}{}} \@writefile{toc}{\contentsline {paragraph}{}{81}{section*.553}\protected@file@percent } \newlabel{SYSTEM:MATCH-WILD-JAR-PATHNAME}{{B}{82}{}{section*.554}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.554}\protected@file@percent } \newlabel{SYSTEM:NAMED-LAMBDA}{{B}{82}{}{section*.555}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.555}\protected@file@percent } \newlabel{SYSTEM:NORMALIZE-TYPE}{{B}{82}{}{section*.556}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.556}\protected@file@percent } \newlabel{SYSTEM:NOTE-NAME-DEFINED}{{B}{82}{}{section*.557}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.557}\protected@file@percent } \newlabel{SYSTEM:NOTINLINE-P}{{B}{82}{}{section*.558}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.558}\protected@file@percent } \newlabel{SYSTEM:OUT-SYNONYM-OF}{{B}{82}{}{section*.559}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.559}\protected@file@percent } \newlabel{SYSTEM:OUTPUT-OBJECT}{{B}{82}{}{section*.560}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.560}\protected@file@percent } \newlabel{SYSTEM:PACKAGE-EXTERNAL-SYMBOLS}{{B}{82}{}{section*.561}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.561}\protected@file@percent } \newlabel{SYSTEM:PACKAGE-INHERITED-SYMBOLS}{{B}{82}{}{section*.562}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.562}\protected@file@percent } \newlabel{SYSTEM:PACKAGE-INTERNAL-SYMBOLS}{{B}{82}{}{section*.563}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.563}\protected@file@percent } \newlabel{SYSTEM:PACKAGE-SYMBOLS}{{B}{82}{}{section*.564}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.564}\protected@file@percent } \newlabel{SYSTEM:PARSE-BODY}{{B}{82}{}{section*.565}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.565}\protected@file@percent } \newlabel{EXTENSIONS:PRECOMPILE}{{B}{82}{}{section*.566}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.566}\protected@file@percent } \newlabel{SYSTEM:PROCESS-ALIVE-P}{{B}{82}{}{section*.567}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.567}\protected@file@percent } \newlabel{SYSTEM:PROCESS-ERROR}{{B}{82}{}{section*.568}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.568}\protected@file@percent } \newlabel{SYSTEM:PROCESS-EXIT-CODE}{{B}{82}{}{section*.569}{}} \@writefile{toc}{\contentsline {paragraph}{}{82}{section*.569}\protected@file@percent } \newlabel{SYSTEM:PROCESS-INPUT}{{B}{83}{}{section*.570}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.570}\protected@file@percent } \newlabel{SYSTEM:PROCESS-KILL}{{B}{83}{}{section*.571}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.571}\protected@file@percent } \newlabel{SYSTEM:PROCESS-OPTIMIZATION-DECLARATIONS}{{B}{83}{}{section*.572}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.572}\protected@file@percent } \newlabel{SYSTEM:PROCESS-OUTPUT}{{B}{83}{}{section*.573}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.573}\protected@file@percent } \newlabel{SYSTEM:PROCESS-P}{{B}{83}{}{section*.574}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.574}\protected@file@percent } \newlabel{SYSTEM:PROCESS-PID}{{B}{83}{}{section*.575}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.575}\protected@file@percent } \newlabel{SYSTEM:PROCESS-WAIT}{{B}{83}{}{section*.576}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.576}\protected@file@percent } \newlabel{SYSTEM:PROCLAIMED-FTYPE}{{B}{83}{}{section*.577}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.577}\protected@file@percent } \newlabel{SYSTEM:PROCLAIMED-TYPE}{{B}{83}{}{section*.578}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.578}\protected@file@percent } \newlabel{SYSTEM:PSXHASH}{{B}{83}{}{section*.579}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.579}\protected@file@percent } \newlabel{SYSTEM:PUT}{{B}{83}{}{section*.580}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.580}\protected@file@percent } \newlabel{SYSTEM:PUTHASH}{{B}{83}{}{section*.581}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.581}\protected@file@percent } \newlabel{SYSTEM:READ-8-BITS}{{B}{83}{}{section*.582}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.582}\protected@file@percent } \newlabel{SYSTEM:READ-VECTOR-UNSIGNED-BYTE-8}{{B}{83}{}{section*.583}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.583}\protected@file@percent } \newlabel{SYSTEM:RECORD-SOURCE-INFORMATION}{{B}{83}{}{section*.584}{}} \@writefile{toc}{\contentsline {paragraph}{}{83}{section*.584}\protected@file@percent } \newlabel{SYSTEM:RECORD-SOURCE-INFORMATION-FOR-TYPE}{{B}{84}{}{section*.585}{}} \@writefile{toc}{\contentsline {paragraph}{}{84}{section*.585}\protected@file@percent } \newlabel{SYSTEM:REMEMBER}{{B}{84}{}{section*.586}{}} \@writefile{toc}{\contentsline {paragraph}{}{84}{section*.586}\protected@file@percent } \newlabel{SYSTEM:REMOVE-ZIP-CACHE-ENTRY}{{B}{84}{}{section*.587}{}} \@writefile{toc}{\contentsline {paragraph}{}{84}{section*.587}\protected@file@percent } \newlabel{SYSTEM:REQUIRE-TYPE}{{B}{84}{}{section*.588}{}} \@writefile{toc}{\contentsline {paragraph}{}{84}{section*.588}\protected@file@percent } \newlabel{SYSTEM:RUN-PROGRAM}{{B}{84}{}{section*.589}{}} \@writefile{toc}{\contentsline {paragraph}{}{84}{section*.589}\protected@file@percent } \newlabel{SYSTEM:SET-CALL-COUNT}{{B}{85}{}{section*.590}{}} \@writefile{toc}{\contentsline {paragraph}{}{85}{section*.590}\protected@file@percent } \newlabel{SYSTEM:SET-CAR}{{B}{85}{}{section*.591}{}} \@writefile{toc}{\contentsline {paragraph}{}{85}{section*.591}\protected@file@percent } \newlabel{SYSTEM:SET-CDR}{{B}{85}{}{section*.592}{}} \@writefile{toc}{\contentsline {paragraph}{}{85}{section*.592}\protected@file@percent } \newlabel{SYSTEM:SET-CHAR}{{B}{85}{}{section*.593}{}} \@writefile{toc}{\contentsline {paragraph}{}{85}{section*.593}\protected@file@percent } \newlabel{SYSTEM:SET-FUNCTION-INFO-VALUE}{{B}{85}{}{section*.594}{}} \@writefile{toc}{\contentsline {paragraph}{}{85}{section*.594}\protected@file@percent } \newlabel{SYSTEM:SET-HOT-COUNT}{{B}{85}{}{section*.595}{}} \@writefile{toc}{\contentsline {paragraph}{}{85}{section*.595}\protected@file@percent } \newlabel{SYSTEM:SET-SCHAR}{{B}{85}{}{section*.596}{}} \@writefile{toc}{\contentsline {paragraph}{}{85}{section*.596}\protected@file@percent } \newlabel{SYSTEM:SET-STD-SLOT-VALUE}{{B}{86}{}{section*.597}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.597}\protected@file@percent } \newlabel{SYSTEM:SETF-FUNCTION-NAME-P}{{B}{86}{}{section*.598}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.598}\protected@file@percent } \newlabel{SYSTEM:SHA256}{{B}{86}{}{section*.599}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.599}\protected@file@percent } \newlabel{SYSTEM:SHRINK-VECTOR}{{B}{86}{}{section*.600}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.600}\protected@file@percent } \newlabel{SYSTEM:SIMPLE-FORMAT}{{B}{86}{}{section*.601}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.601}\protected@file@percent } \newlabel{SYSTEM:SIMPLE-SEARCH}{{B}{86}{}{section*.602}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.602}\protected@file@percent } \newlabel{SYSTEM:SIMPLE-TYPEP}{{B}{86}{}{section*.603}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.603}\protected@file@percent } \newlabel{SYSTEM:SINGLE-FLOAT-BITS}{{B}{86}{}{section*.604}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.604}\protected@file@percent } \newlabel{SYSTEM:SLOT-DEFINITION}{{B}{86}{}{section*.605}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.605}\protected@file@percent } \newlabel{SYSTEM:SOURCE-TRANSFORM}{{B}{86}{}{section*.606}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.606}\protected@file@percent } \newlabel{SYSTEM:STANDARD-INSTANCE-ACCESS}{{B}{86}{}{section*.607}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.607}\protected@file@percent } \newlabel{SYSTEM:STANDARD-OBJECT-P}{{B}{86}{}{section*.608}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.608}\protected@file@percent } \newlabel{SYSTEM:STD-INSTANCE-CLASS}{{B}{86}{}{section*.609}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.609}\protected@file@percent } \newlabel{SYSTEM:STD-INSTANCE-LAYOUT}{{B}{86}{}{section*.610}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.610}\protected@file@percent } \newlabel{SYSTEM:STD-SLOT-BOUNDP}{{B}{86}{}{section*.611}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.611}\protected@file@percent } \newlabel{SYSTEM:STD-SLOT-VALUE}{{B}{86}{}{section*.612}{}} \@writefile{toc}{\contentsline {paragraph}{}{86}{section*.612}\protected@file@percent } \newlabel{SYSTEM:STRUCTURE-LENGTH}{{B}{87}{}{section*.613}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.613}\protected@file@percent } \newlabel{SYSTEM:STRUCTURE-OBJECT-P}{{B}{87}{}{section*.614}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.614}\protected@file@percent } \newlabel{SYSTEM:STRUCTURE-REF}{{B}{87}{}{section*.615}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.615}\protected@file@percent } \newlabel{SYSTEM:STRUCTURE-SET}{{B}{87}{}{section*.616}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.616}\protected@file@percent } \newlabel{SYSTEM:SUBCLASSP}{{B}{87}{}{section*.617}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.617}\protected@file@percent } \newlabel{SYSTEM:SVSET}{{B}{87}{}{section*.618}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.618}\protected@file@percent } \newlabel{SYSTEM:SWAP-SLOTS}{{B}{87}{}{section*.619}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.619}\protected@file@percent } \newlabel{SYSTEM:SYMBOL-MACRO-P}{{B}{87}{}{section*.620}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.620}\protected@file@percent } \newlabel{SYSTEM:SYSTEM-ARTIFACTS-ARE-JARS-P}{{B}{87}{}{section*.621}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.621}\protected@file@percent } \newlabel{SYSTEM:UNDEFINED-FUNCTION-CALLED}{{B}{87}{}{section*.622}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.622}\protected@file@percent } \newlabel{SYSTEM:UNTRACED-FUNCTION}{{B}{87}{}{section*.623}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.623}\protected@file@percent } \newlabel{SYSTEM:UNZIP}{{B}{87}{}{section*.624}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.624}\protected@file@percent } \newlabel{SYSTEM:URL-STREAM}{{B}{87}{}{section*.625}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.625}\protected@file@percent } \newlabel{SYSTEM:VECTOR-DELETE-EQ}{{B}{87}{}{section*.626}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.626}\protected@file@percent } \newlabel{SYSTEM:VECTOR-DELETE-EQL}{{B}{87}{}{section*.627}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.627}\protected@file@percent } \newlabel{SYSTEM:WHITESPACEP}{{B}{87}{}{section*.628}{}} \@writefile{toc}{\contentsline {paragraph}{}{87}{section*.628}\protected@file@percent } \newlabel{SYSTEM:WRITE-8-BITS}{{B}{88}{}{section*.629}{}} \@writefile{toc}{\contentsline {paragraph}{}{88}{section*.629}\protected@file@percent } \newlabel{SYSTEM:WRITE-VECTOR-UNSIGNED-BYTE-8}{{B}{88}{}{section*.630}{}} \@writefile{toc}{\contentsline {paragraph}{}{88}{section*.630}\protected@file@percent } \newlabel{SYSTEM:ZIP}{{B}{88}{}{section*.631}{}} \@writefile{toc}{\contentsline {paragraph}{}{88}{section*.631}\protected@file@percent } \@setckpt{system}{ \setcounter{page}{89} \setcounter{equation}{0} \setcounter{enumi}{6} \setcounter{enumii}{0} \setcounter{enumiii}{0} \setcounter{enumiv}{0} \setcounter{footnote}{0} \setcounter{mpfootnote}{0} \setcounter{part}{0} \setcounter{chapter}{2} \setcounter{section}{0} \setcounter{subsection}{0} \setcounter{subsubsection}{0} \setcounter{paragraph}{0} \setcounter{subparagraph}{0} \setcounter{figure}{0} \setcounter{table}{0} \setcounter{Item}{6} \setcounter{Hfootnote}{28} \setcounter{bookmark@seq@number}{68} \setcounter{lstnumber}{38} \setcounter{cp@cntr}{0} \setcounter{section@level}{4} \setcounter{lstlisting}{0} } abcl-src-1.9.0/doc/manual/system.tex0100644 0000000 0000000 00000207642 14242627550 016050 0ustar000000000 0000000 \paragraph{} \label{SYSTEM:ALLOCATE-FUNCALLABLE-INSTANCE} \index{ALLOCATE-FUNCALLABLE-INSTANCE} --- Function: \textbf{\%allocate-funcallable-instance} [\textbf{system}] \textit{class} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-DEFAULT-INITARGS} \index{CLASS-DEFAULT-INITARGS} --- Function: \textbf{\%class-default-initargs} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-DIRECT-DEFAULT-INITARGS} \index{CLASS-DIRECT-DEFAULT-INITARGS} --- Function: \textbf{\%class-direct-default-initargs} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-DIRECT-METHODS} \index{CLASS-DIRECT-METHODS} --- Function: \textbf{\%class-direct-methods} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-DIRECT-SLOTS} \index{CLASS-DIRECT-SLOTS} --- Function: \textbf{\%class-direct-slots} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-DIRECT-SUBCLASSES} \index{CLASS-DIRECT-SUBCLASSES} --- Function: \textbf{\%class-direct-subclasses} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-DIRECT-SUPERCLASSES} \index{CLASS-DIRECT-SUPERCLASSES} --- Function: \textbf{\%class-direct-superclasses} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-FINALIZED-P} \index{CLASS-FINALIZED-P} --- Function: \textbf{\%class-finalized-p} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-LAYOUT} \index{CLASS-LAYOUT} --- Function: \textbf{\%class-layout} [\textbf{system}] \textit{class} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-NAME} \index{CLASS-NAME} --- Function: \textbf{\%class-name} [\textbf{system}] \textit{class} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-PRECEDENCE-LIST} \index{CLASS-PRECEDENCE-LIST} --- Function: \textbf{\%class-precedence-list} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-SLOTS} \index{CLASS-SLOTS} --- Function: \textbf{\%class-slots} [\textbf{system}] \textit{class} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DEFUN} \index{DEFUN} --- Function: \textbf{\%defun} [\textbf{system}] \textit{name definition} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DOCUMENTATION} \index{DOCUMENTATION} --- Function: \textbf{\%documentation} [\textbf{system}] \textit{object doc-type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FLOAT-BITS} \index{FLOAT-BITS} --- Function: \textbf{\%float-bits} [\textbf{system}] \textit{integer} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:IN-PACKAGE} \index{IN-PACKAGE} --- Function: \textbf{\%in-package} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-CONDITION} \index{MAKE-CONDITION} --- Function: \textbf{\%make-condition} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-EMF-CACHE} \index{MAKE-EMF-CACHE} --- Function: \textbf{\%make-emf-cache} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-INSTANCES-OBSOLETE} \index{MAKE-INSTANCES-OBSOLETE} --- Function: \textbf{\%make-instances-obsolete} [\textbf{system}] \textit{class} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-INTEGER-TYPE} \index{MAKE-INTEGER-TYPE} --- Function: \textbf{\%make-integer-type} [\textbf{system}] \textit{low high} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-LIST} \index{MAKE-LIST} --- Function: \textbf{\%make-list} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-LOGICAL-PATHNAME} \index{MAKE-LOGICAL-PATHNAME} --- Function: \textbf{\%make-logical-pathname} [\textbf{system}] \textit{namestring} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-SLOT-DEFINITION} \index{MAKE-SLOT-DEFINITION} --- Function: \textbf{\%make-slot-definition} [\textbf{system}] \textit{slot-class} \begin{adjustwidth}{5em}{5em} Argument must be a subclass of standard-slot-definition \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-STRUCTURE} \index{MAKE-STRUCTURE} --- Function: \textbf{\%make-structure} [\textbf{system}] \textit{name slot-values} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MEMBER} \index{MEMBER} --- Function: \textbf{\%member} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:NSTRING-CAPITALIZE} \index{NSTRING-CAPITALIZE} --- Function: \textbf{\%nstring-capitalize} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:NSTRING-DOWNCASE} \index{NSTRING-DOWNCASE} --- Function: \textbf{\%nstring-downcase} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:NSTRING-UPCASE} \index{NSTRING-UPCASE} --- Function: \textbf{\%nstring-upcase} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:OUTPUT-OBJECT} \index{OUTPUT-OBJECT} --- Function: \textbf{\%output-object} [\textbf{system}] \textit{object stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PUTF} \index{PUTF} --- Function: \textbf{\%putf} [\textbf{system}] \textit{plist indicator new-value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:REINIT-EMF-CACHE} \index{REINIT-EMF-CACHE} --- Function: \textbf{\%reinit-emf-cache} [\textbf{system}] \textit{generic-function eql-specilizer-objects-list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-DEFAULT-INITARGS} \index{SET-CLASS-DEFAULT-INITARGS} --- Function: \textbf{\%set-class-default-initargs} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-DIRECT-DEFAULT-INITARGS} \index{SET-CLASS-DIRECT-DEFAULT-INITARGS} --- Function: \textbf{\%set-class-direct-default-initargs} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-DIRECT-METHODS} \index{SET-CLASS-DIRECT-METHODS} --- Function: \textbf{\%set-class-direct-methods} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-DIRECT-SLOTS} \index{SET-CLASS-DIRECT-SLOTS} --- Function: \textbf{\%set-class-direct-slots} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-DIRECT-SUBCLASSES} \index{SET-CLASS-DIRECT-SUBCLASSES} --- Function: \textbf{\%set-class-direct-subclasses} [\textbf{system}] \textit{class direct-subclasses} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-DIRECT-SUPERCLASSES} \index{SET-CLASS-DIRECT-SUPERCLASSES} --- Function: \textbf{\%set-class-direct-superclasses} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-DOCUMENTATION} \index{SET-CLASS-DOCUMENTATION} --- Function: \textbf{\%set-class-documentation} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-FINALIZED-P} \index{SET-CLASS-FINALIZED-P} --- Function: \textbf{\%set-class-finalized-p} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-LAYOUT} \index{SET-CLASS-LAYOUT} --- Function: \textbf{\%set-class-layout} [\textbf{system}] \textit{class layout} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-NAME} \index{SET-CLASS-NAME} --- Function: \textbf{\%set-class-name} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-PRECEDENCE-LIST} \index{SET-CLASS-PRECEDENCE-LIST} --- Function: \textbf{\%set-class-precedence-list} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CLASS-SLOTS} \index{SET-CLASS-SLOTS} --- Function: \textbf{\%set-class-slots} [\textbf{system}] \textit{class slot-definitions} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-DOCUMENTATION} \index{SET-DOCUMENTATION} --- Function: \textbf{\%set-documentation} [\textbf{system}] \textit{object doc-type documentation} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-FILL-POINTER} \index{SET-FILL-POINTER} --- Function: \textbf{\%set-fill-pointer} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-FIND-CLASS} \index{SET-FIND-CLASS} --- Function: \textbf{\%set-find-class} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-STANDARD-INSTANCE-ACCESS} \index{SET-STANDARD-INSTANCE-ACCESS} --- Function: \textbf{\%set-standard-instance-access} [\textbf{system}] \textit{instance location new-value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-STD-INSTANCE-LAYOUT} \index{SET-STD-INSTANCE-LAYOUT} --- Function: \textbf{\%set-std-instance-layout} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STD-ALLOCATE-INSTANCE} \index{STD-ALLOCATE-INSTANCE} --- Function: \textbf{\%std-allocate-instance} [\textbf{system}] \textit{class} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STREAM-OUTPUT-OBJECT} \index{STREAM-OUTPUT-OBJECT} --- Function: \textbf{\%stream-output-object} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STREAM-TERPRI} \index{STREAM-TERPRI} --- Function: \textbf{\%stream-terpri} [\textbf{system}] \textit{output-stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STREAM-WRITE-CHAR} \index{STREAM-WRITE-CHAR} --- Function: \textbf{\%stream-write-char} [\textbf{system}] \textit{character output-stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-CAPITALIZE} \index{STRING-CAPITALIZE} --- Function: \textbf{\%string-capitalize} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-DOWNCASE} \index{STRING-DOWNCASE} --- Function: \textbf{\%string-downcase} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-EQUAL} \index{STRING-EQUAL} --- Function: \textbf{\%string-equal} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-GREATERP} \index{STRING-GREATERP} --- Function: \textbf{\%string-greaterp} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-LESSP} \index{STRING-LESSP} --- Function: \textbf{\%string-lessp} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-NOT-EQUAL} \index{STRING-NOT-EQUAL} --- Function: \textbf{\%string-not-equal} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-NOT-GREATERP} \index{STRING-NOT-GREATERP} --- Function: \textbf{\%string-not-greaterp} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-NOT-LESSP} \index{STRING-NOT-LESSP} --- Function: \textbf{\%string-not-lessp} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING-UPCASE} \index{STRING-UPCASE} --- Function: \textbf{\%string-upcase} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING/=} \index{STRING/=} --- Function: \textbf{\%string/=} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING<} \index{STRING<} --- Function: \textbf{\%string<} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING<=} \index{STRING<=} --- Function: \textbf{\%string<=} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING>} \index{STRING>} --- Function: \textbf{\%string>} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRING>=} \index{STRING>=} --- Function: \textbf{\%string>=} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:TYPE-ERROR} \index{TYPE-ERROR} --- Function: \textbf{\%type-error} [\textbf{system}] \textit{datum expected-type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:WILD-PATHNAME-P} \index{WILD-PATHNAME-P} --- Function: \textbf{\%wild-pathname-p} [\textbf{system}] \textit{pathname keyword} \begin{adjustwidth}{5em}{5em} Predicate for determing whether PATHNAME contains wild components. KEYWORD, if non-nil, should be one of :directory, :host, :device, :name, :type, or :version indicating that only the specified component should be checked for wildness. \end{adjustwidth} \paragraph{} \label{SYSTEM:*ABCL-CONTRIB*} \index{*ABCL-CONTRIB*} --- Variable: \textbf{*abcl-contrib*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Pathname of the abcl-contrib artifact. Initialized via SYSTEM:FIND-CONTRIB. \end{adjustwidth} \paragraph{} \label{SYSTEM:*COMPILE-FILE-CLASS-EXTENSION*} \index{*COMPILE-FILE-CLASS-EXTENSION*} --- Variable: \textbf{*compile-file-class-extension*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*COMPILE-FILE-ENVIRONMENT*} \index{*COMPILE-FILE-ENVIRONMENT*} --- Variable: \textbf{*compile-file-environment*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*COMPILE-FILE-TYPE*} \index{*COMPILE-FILE-TYPE*} --- Variable: \textbf{*compile-file-type*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*COMPILE-FILE-ZIP*} \index{*COMPILE-FILE-ZIP*} --- Variable: \textbf{*compile-file-zip*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*COMPILER-DIAGNOSTIC*} \index{*COMPILER-DIAGNOSTIC*} --- Variable: \textbf{*compiler-diagnostic*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} The stream to emit compiler diagnostic messages to, or nil to muffle output. \end{adjustwidth} \paragraph{} \label{SYSTEM:*COMPILER-ERROR-CONTEXT*} \index{*COMPILER-ERROR-CONTEXT*} --- Variable: \textbf{*compiler-error-context*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*CURRENT-PRINT-LENGTH*} \index{*CURRENT-PRINT-LENGTH*} --- Variable: \textbf{*current-print-length*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*CURRENT-PRINT-LEVEL*} \index{*CURRENT-PRINT-LEVEL*} --- Variable: \textbf{*current-print-level*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*DEBUG*} \index{*DEBUG*} --- Variable: \textbf{*debug*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{ABCL-INTROSPECT/SYSTEM:*DEBUGGING-LOCALS-P*} \index{*DEBUGGING-LOCALS-P*} --- Variable: \textbf{*debugging-locals-p*} [\textbf{abcl-introspect/system}] \textit{} \begin{adjustwidth}{5em}{5em} Whether SYS:FIND-LOCALS should be looking for local variables \end{adjustwidth} \paragraph{} \label{SYSTEM:*DISASSEMBLERS*} \index{*DISASSEMBLERS*} --- Variable: \textbf{*disassemblers*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Methods of invoking CL:DISASSEMBLE consisting of a enumeration of (keyword function) pairs The pairs (keyword function) contain a keyword identifying this particulat disassembler, and a symbol designating function takes a object to disassemble. Use SYS:CHOOSE-DISASSEMBLER to install a given disassembler as the one used by CL:DISASSEMBLE. Additional disassemblers/decompilers are packaged in the ABCL-INTROSPECT contrib. The intial default is :javap using the javap command line tool which is part of the Java Developement Kit. \end{adjustwidth} \paragraph{} \label{SYSTEM:*ENABLE-AUTOCOMPILE*} \index{*ENABLE-AUTOCOMPILE*} --- Variable: \textbf{*enable-autocompile*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*EXPLAIN*} \index{*EXPLAIN*} --- Variable: \textbf{*explain*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*FASL-LOADER*} \index{*FASL-LOADER*} --- Variable: \textbf{*fasl-loader*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*FASL-VERSION*} \index{*FASL-VERSION*} --- Variable: \textbf{*fasl-version*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*INLINE-DECLARATIONS*} \index{*INLINE-DECLARATIONS*} --- Variable: \textbf{*inline-declarations*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*LOGICAL-PATHNAME-TRANSLATIONS*} \index{*LOGICAL-PATHNAME-TRANSLATIONS*} --- Variable: \textbf{*logical-pathname-translations*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*NOINFORM*} \index{*NOINFORM*} --- Variable: \textbf{*noinform*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*SAFETY*} \index{*SAFETY*} --- Variable: \textbf{*safety*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*SOURCE*} \index{*SOURCE*} --- Variable: \textbf{*source*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*SOURCE-POSITION*} \index{*SOURCE-POSITION*} --- Variable: \textbf{*source-position*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*SPACE*} \index{*SPACE*} --- Variable: \textbf{*space*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*SPEED*} \index{*SPEED*} --- Variable: \textbf{*speed*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:*TRACED-NAMES*} \index{*TRACED-NAMES*} --- Variable: \textbf{*traced-names*} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:+CL-PACKAGE+} \index{+CL-PACKAGE+} --- Variable: \textbf{+cl-package+} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:+FALSE-TYPE+} \index{+FALSE-TYPE+} --- Variable: \textbf{+false-type+} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:+FIXNUM-TYPE+} \index{+FIXNUM-TYPE+} --- Variable: \textbf{+fixnum-type+} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:+INTEGER-TYPE+} \index{+INTEGER-TYPE+} --- Variable: \textbf{+integer-type+} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:+KEYWORD-PACKAGE+} \index{+KEYWORD-PACKAGE+} --- Variable: \textbf{+keyword-package+} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:+SLOT-UNBOUND+} \index{+SLOT-UNBOUND+} --- Variable: \textbf{+slot-unbound+} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:+TRUE-TYPE+} \index{+TRUE-TYPE+} --- Variable: \textbf{+true-type+} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ASET} \index{ASET} --- Function: \textbf{aset} [\textbf{system}] \textit{array subscripts new-element} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:AUTOCOMPILE} \index{AUTOCOMPILE} --- Function: \textbf{autocompile} [\textbf{system}] \textit{function} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:AVAILABLE-ENCODINGS} \index{AVAILABLE-ENCODINGS} --- Function: \textbf{available-encodings} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Returns all charset encodings suitable for passing to a stream constructor available at runtime. \end{adjustwidth} \paragraph{} \label{SYSTEM:AVER} \index{AVER} --- Macro: \textbf{aver} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Signal simple-error when EXPR is non-NIL. \end{adjustwidth} \paragraph{} \label{SYSTEM:BACKTRACE} \index{BACKTRACE} --- Function: \textbf{backtrace} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Returns a Java backtrace of the invoking thread. \end{adjustwidth} \paragraph{} \label{SYSTEM:BUILT-IN-FUNCTION-P} \index{BUILT-IN-FUNCTION-P} --- Function: \textbf{built-in-function-p} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CACHE-EMF} \index{CACHE-EMF} --- Function: \textbf{cache-emf} [\textbf{system}] \textit{generic-function args emf} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CALL-COUNT} \index{CALL-COUNT} --- Function: \textbf{call-count} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CALL-REGISTERS-LIMIT} \index{CALL-REGISTERS-LIMIT} --- Variable: \textbf{call-registers-limit} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CANONICALIZE-LOGICAL-HOST} \index{CANONICALIZE-LOGICAL-HOST} --- Function: \textbf{canonicalize-logical-host} [\textbf{system}] \textit{host} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CHECK-DECLARATION-TYPE} \index{CHECK-DECLARATION-TYPE} --- Function: \textbf{check-declaration-type} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CHECK-SEQUENCE-BOUNDS} \index{CHECK-SEQUENCE-BOUNDS} --- Function: \textbf{check-sequence-bounds} [\textbf{system}] \textit{sequence start end} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CHOOSE-DISASSEMBLER} \index{CHOOSE-DISASSEMBLER} --- Function: \textbf{choose-disassembler} [\textbf{system}] \textit{\&optional name} \begin{adjustwidth}{5em}{5em} Report current disassembler that would be used by CL:DISASSEMBLE With optional keyword NAME, select the associated disassembler from SYS:*DISASSEMBLERS*. \end{adjustwidth} \paragraph{} \label{SYSTEM:CLASS-BYTES} \index{CLASS-BYTES} --- Function: \textbf{class-bytes} [\textbf{system}] \textit{class} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CLEAR-ZIP-CACHE} \index{CLEAR-ZIP-CACHE} --- Function: \textbf{clear-zip-cache} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COERCE-TO-CONDITION} \index{COERCE-TO-CONDITION} --- Function: \textbf{coerce-to-condition} [\textbf{system}] \textit{datum arguments default-type fun-name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COERCE-TO-FUNCTION} \index{COERCE-TO-FUNCTION} --- Function: \textbf{coerce-to-function} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILE-FILE-IF-NEEDED} \index{COMPILE-FILE-IF-NEEDED} --- Function: \textbf{compile-file-if-needed} [\textbf{system}] \textit{input-file \&rest allargs \&key force-compile \&allow-other-keys} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:COMPILE-SYSTEM} \index{COMPILE-SYSTEM} --- Function: \textbf{compile-system} [\textbf{extensions}] \textit{\&key quit (zip t) (cls-ext *compile-file-class-extension*) (abcl-ext *compile-file-type*) output-path} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILED-LISP-FUNCTION-P} \index{COMPILED-LISP-FUNCTION-P} --- Function: \textbf{compiled-lisp-function-p} [\textbf{system}] \textit{object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILER-DEFSTRUCT} \index{COMPILER-DEFSTRUCT} --- Function: \textbf{compiler-defstruct} [\textbf{system}] \textit{name \&key conc-name default-constructor constructors copier include type named initial-offset predicate print-function print-object direct-slots slots inherited-accessors documentation} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILER-ERROR} \index{COMPILER-ERROR} --- Function: \textbf{compiler-error} [\textbf{system}] \textit{format-control \&rest format-arguments} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILER-MACROEXPAND} \index{COMPILER-MACROEXPAND} --- Function: \textbf{compiler-macroexpand} [\textbf{system}] \textit{form \&optional env} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILER-STYLE-WARN} \index{COMPILER-STYLE-WARN} --- Function: \textbf{compiler-style-warn} [\textbf{system}] \textit{format-control \&rest format-arguments} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILER-SUBTYPEP} \index{COMPILER-SUBTYPEP} --- Function: \textbf{compiler-subtypep} [\textbf{system}] \textit{compiler-type typespec} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILER-UNSUPPORTED} \index{COMPILER-UNSUPPORTED} --- Function: \textbf{compiler-unsupported} [\textbf{system}] \textit{format-control \&rest format-arguments} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:COMPILER-WARN} \index{COMPILER-WARN} --- Function: \textbf{compiler-warn} [\textbf{system}] \textit{format-control \&rest format-arguments} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:CONCATENATE-FASLS} \index{CONCATENATE-FASLS} --- Function: \textbf{concatenate-fasls} [\textbf{system}] \textit{inputs output} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DEFCONST} \index{DEFCONST} --- Macro: \textbf{defconst} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DEFINE-SOURCE-TRANSFORM} \index{DEFINE-SOURCE-TRANSFORM} --- Macro: \textbf{define-source-transform} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DEFKNOWN} \index{DEFKNOWN} --- Macro: \textbf{defknown} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DELETE-EQ} \index{DELETE-EQ} --- Function: \textbf{delete-eq} [\textbf{system}] \textit{item sequence} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DELETE-EQL} \index{DELETE-EQL} --- Function: \textbf{delete-eql} [\textbf{system}] \textit{item sequence} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DESCRIBE-COMPILER-POLICY} \index{DESCRIBE-COMPILER-POLICY} --- Function: \textbf{describe-compiler-policy} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DISABLE-ZIP-CACHE} \index{DISABLE-ZIP-CACHE} --- Function: \textbf{disable-zip-cache} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Not currently implemented \end{adjustwidth} \paragraph{} \label{SYSTEM:DISASSEMBLE-CLASS-BYTES} \index{DISASSEMBLE-CLASS-BYTES} --- Function: \textbf{disassemble-class-bytes} [\textbf{system}] \textit{java-object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DOUBLE-FLOAT-HIGH-BITS} \index{DOUBLE-FLOAT-HIGH-BITS} --- Function: \textbf{double-float-high-bits} [\textbf{system}] \textit{float} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DOUBLE-FLOAT-LOW-BITS} \index{DOUBLE-FLOAT-LOW-BITS} --- Function: \textbf{double-float-low-bits} [\textbf{system}] \textit{float} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DUMP-FORM} \index{DUMP-FORM} --- Function: \textbf{dump-form} [\textbf{system}] \textit{form stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:DUMP-UNINTERNED-SYMBOL-INDEX} \index{DUMP-UNINTERNED-SYMBOL-INDEX} --- Function: \textbf{dump-uninterned-symbol-index} [\textbf{system}] \textit{symbol} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:EMPTY-ENVIRONMENT-P} \index{EMPTY-ENVIRONMENT-P} --- Function: \textbf{empty-environment-p} [\textbf{system}] \textit{environment} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ENVIRONMENT} \index{ENVIRONMENT} --- Class: \textbf{environment} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ENVIRONMENT-ADD-FUNCTION-DEFINITION} \index{ENVIRONMENT-ADD-FUNCTION-DEFINITION} --- Function: \textbf{environment-add-function-definition} [\textbf{system}] \textit{environment name lambda-expression} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ENVIRONMENT-ADD-MACRO-DEFINITION} \index{ENVIRONMENT-ADD-MACRO-DEFINITION} --- Function: \textbf{environment-add-macro-definition} [\textbf{system}] \textit{environment name expander} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ENVIRONMENT-ADD-SYMBOL-BINDING} \index{ENVIRONMENT-ADD-SYMBOL-BINDING} --- Function: \textbf{environment-add-symbol-binding} [\textbf{system}] \textit{environment symbol value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ENVIRONMENT-ALL-FUNCTIONS} \index{ENVIRONMENT-ALL-FUNCTIONS} --- Function: \textbf{environment-all-functions} [\textbf{system}] \textit{environment} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ENVIRONMENT-ALL-VARIABLES} \index{ENVIRONMENT-ALL-VARIABLES} --- Function: \textbf{environment-all-variables} [\textbf{system}] \textit{environment} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ENVIRONMENT-VARIABLES} \index{ENVIRONMENT-VARIABLES} --- Function: \textbf{environment-variables} [\textbf{system}] \textit{environment} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:EXPAND-INLINE} \index{EXPAND-INLINE} --- Function: \textbf{expand-inline} [\textbf{system}] \textit{form expansion} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:EXPAND-SOURCE-TRANSFORM} \index{EXPAND-SOURCE-TRANSFORM} --- Function: \textbf{expand-source-transform} [\textbf{system}] \textit{form} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FDEFINITION-BLOCK-NAME} \index{FDEFINITION-BLOCK-NAME} --- Function: \textbf{fdefinition-block-name} [\textbf{system}] \textit{function-name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FIND-CONTRIB} \index{FIND-CONTRIB} --- Function: \textbf{find-contrib} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Introspect runtime classpaths to return a pathname containing subdirectories containing ASDF definitions. \end{adjustwidth} \paragraph{} \label{ABCL-INTROSPECT/SYSTEM:FIND-LOCALS} \index{FIND-LOCALS} --- Function: \textbf{find-locals} [\textbf{abcl-introspect/system}] \textit{index backtrace} \begin{adjustwidth}{5em}{5em} Return local variable bindings at INDEX in BACKTRACE Added by ABCL-INTROSPECT. \end{adjustwidth} \paragraph{} \label{SYSTEM:FIND-SYSTEM} \index{FIND-SYSTEM} --- Function: \textbf{find-system} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Find the location of the Armed Bear system implementation Used to determine relative pathname to find 'abcl-contrib.jar'. \end{adjustwidth} \paragraph{} \label{SYSTEM:FIXNUM-CONSTANT-VALUE} \index{FIXNUM-CONSTANT-VALUE} --- Function: \textbf{fixnum-constant-value} [\textbf{system}] \textit{compiler-type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FIXNUM-TYPE-P} \index{FIXNUM-TYPE-P} --- Function: \textbf{fixnum-type-p} [\textbf{system}] \textit{compiler-type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FLOAT-INFINITY-P} \index{FLOAT-INFINITY-P} --- Function: \textbf{float-infinity-p} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FLOAT-NAN-P} \index{FLOAT-NAN-P} --- Function: \textbf{float-nan-p} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FLOAT-OVERFLOW-MODE} \index{FLOAT-OVERFLOW-MODE} --- Function: \textbf{float-overflow-mode} [\textbf{system}] \textit{\&optional boolean} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FLOAT-STRING} \index{FLOAT-STRING} --- Function: \textbf{float-string} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FLOAT-UNDERFLOW-MODE} \index{FLOAT-UNDERFLOW-MODE} --- Function: \textbf{float-underflow-mode} [\textbf{system}] \textit{\&optional boolean} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FORWARD-REFERENCED-CLASS} \index{FORWARD-REFERENCED-CLASS} --- Class: \textbf{forward-referenced-class} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FRAME-TO-LIST} \index{FRAME-TO-LIST} --- Function: \textbf{frame-to-list} [\textbf{system}] \textit{frame} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FRAME-TO-STRING} \index{FRAME-TO-STRING} --- Function: \textbf{frame-to-string} [\textbf{system}] \textit{frame} \begin{adjustwidth}{5em}{5em} Convert stack FRAME to a (potentially) readable string. \end{adjustwidth} \paragraph{} \label{SYSTEM:FSET} \index{FSET} --- Function: \textbf{fset} [\textbf{system}] \textit{name function \&optional source-position arglist documentation} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FTYPE-RESULT-TYPE} \index{FTYPE-RESULT-TYPE} --- Function: \textbf{ftype-result-type} [\textbf{system}] \textit{ftype} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FUNCTION-PLIST} \index{FUNCTION-PLIST} --- Function: \textbf{function-plist} [\textbf{system}] \textit{function} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:FUNCTION-RESULT-TYPE} \index{FUNCTION-RESULT-TYPE} --- Function: \textbf{function-result-type} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:GET-CACHED-EMF} \index{GET-CACHED-EMF} --- Function: \textbf{get-cached-emf} [\textbf{system}] \textit{generic-function args} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:GET-FUNCTION-INFO-VALUE} \index{GET-FUNCTION-INFO-VALUE} --- Function: \textbf{get-function-info-value} [\textbf{system}] \textit{name indicator} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:GET-INPUT-STREAM} \index{GET-INPUT-STREAM} --- Function: \textbf{get-input-stream} [\textbf{system}] \textit{pathname} \begin{adjustwidth}{5em}{5em} Returns a java.io.InputStream for resource denoted by PATHNAME. \end{adjustwidth} \paragraph{} \label{SYSTEM:GETHASH1} \index{GETHASH1} --- Function: \textbf{gethash1} [\textbf{system}] \textit{key hash-table} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:GROVEL-JAVA-DEFINITIONS-IN-FILE} \index{GROVEL-JAVA-DEFINITIONS-IN-FILE} --- Function: \textbf{grovel-java-definitions-in-file} [\textbf{system}] \textit{file out} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:HASH-TABLE-WEAKNESS} \index{HASH-TABLE-WEAKNESS} --- Function: \textbf{hash-table-weakness} [\textbf{system}] \textit{hash-table} \begin{adjustwidth}{5em}{5em} Return weakness property of HASH-TABLE, or NIL if it has none. \end{adjustwidth} \paragraph{} \label{SYSTEM:HOT-COUNT} \index{HOT-COUNT} --- Function: \textbf{hot-count} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:IDENTITY-HASH-CODE} \index{IDENTITY-HASH-CODE} --- Function: \textbf{identity-hash-code} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INIT-FASL} \index{INIT-FASL} --- Function: \textbf{init-fasl} [\textbf{system}] \textit{\&key version} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INLINE-EXPANSION} \index{INLINE-EXPANSION} --- Function: \textbf{inline-expansion} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INLINE-P} \index{INLINE-P} --- Function: \textbf{inline-p} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INSPECTED-PARTS} \index{INSPECTED-PARTS} --- Function: \textbf{inspected-parts} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INTEGER-CONSTANT-VALUE} \index{INTEGER-CONSTANT-VALUE} --- Function: \textbf{integer-constant-value} [\textbf{system}] \textit{compiler-type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INTEGER-TYPE-HIGH} \index{INTEGER-TYPE-HIGH} --- Function: \textbf{integer-type-high} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INTEGER-TYPE-LOW} \index{INTEGER-TYPE-LOW} --- Function: \textbf{integer-type-low} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INTEGER-TYPE-P} \index{INTEGER-TYPE-P} --- Function: \textbf{integer-type-p} [\textbf{system}] \textit{object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INTERACTIVE-EVAL} \index{INTERACTIVE-EVAL} --- Function: \textbf{interactive-eval} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:INTERNAL-COMPILER-ERROR} \index{INTERNAL-COMPILER-ERROR} --- Function: \textbf{internal-compiler-error} [\textbf{system}] \textit{format-control \&rest format-arguments} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:JAR-STREAM} \index{JAR-STREAM} --- Class: \textbf{jar-stream} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:JAVA-LONG-TYPE-P} \index{JAVA-LONG-TYPE-P} --- Function: \textbf{java-long-type-p} [\textbf{system}] \textit{compiler-type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:JAVA.CLASS.PATH} \index{JAVA.CLASS.PATH} --- Function: \textbf{java.class.path} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} Return a list of the directories as pathnames referenced in the JVM classpath. \end{adjustwidth} \paragraph{} \label{SYSTEM:LAMBDA-NAME} \index{LAMBDA-NAME} --- Function: \textbf{lambda-name} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LAYOUT-CLASS} \index{LAYOUT-CLASS} --- Function: \textbf{layout-class} [\textbf{system}] \textit{layout} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LAYOUT-LENGTH} \index{LAYOUT-LENGTH} --- Function: \textbf{layout-length} [\textbf{system}] \textit{layout} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LAYOUT-SLOT-INDEX} \index{LAYOUT-SLOT-INDEX} --- Function: \textbf{layout-slot-index} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LAYOUT-SLOT-LOCATION} \index{LAYOUT-SLOT-LOCATION} --- Function: \textbf{layout-slot-location} [\textbf{system}] \textit{layout slot-name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LIST-DELETE-EQ} \index{LIST-DELETE-EQ} --- Function: \textbf{list-delete-eq} [\textbf{system}] \textit{item list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LIST-DELETE-EQL} \index{LIST-DELETE-EQL} --- Function: \textbf{list-delete-eql} [\textbf{system}] \textit{item list} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LIST-DIRECTORY} \index{LIST-DIRECTORY} --- Function: \textbf{list-directory} [\textbf{system}] \textit{directory \&optional (resolve-symlinks nil)} \begin{adjustwidth}{5em}{5em} Lists the contents of DIRECTORY, optionally resolving symbolic links. \end{adjustwidth} \paragraph{} \label{SYSTEM:LOAD-COMPILED-FUNCTION} \index{LOAD-COMPILED-FUNCTION} --- Function: \textbf{load-compiled-function} [\textbf{system}] \textit{source} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LOAD-SYSTEM-FILE} \index{LOAD-SYSTEM-FILE} --- Function: \textbf{load-system-file} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LOGICAL-HOST-P} \index{LOGICAL-HOST-P} --- Function: \textbf{logical-host-p} [\textbf{system}] \textit{canonical-host} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:LOGICAL-PATHNAME-P} \index{LOGICAL-PATHNAME-P} --- Function: \textbf{logical-pathname-p} [\textbf{system}] \textit{object} \begin{adjustwidth}{5em}{5em} Returns true if OBJECT is of type logical-pathname; otherwise, returns false. \end{adjustwidth} \paragraph{} \label{SYSTEM:LOOKUP-KNOWN-SYMBOL} \index{LOOKUP-KNOWN-SYMBOL} --- Function: \textbf{lookup-known-symbol} [\textbf{system}] \textit{symbol} \begin{adjustwidth}{5em}{5em} Returns the name of the field and its class designator which stores the Java object `symbol'. \end{adjustwidth} \paragraph{} \label{SYSTEM:MACRO-FUNCTION-P} \index{MACRO-FUNCTION-P} --- Function: \textbf{macro-function-p} [\textbf{system}] \textit{value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-CLOSURE} \index{MAKE-CLOSURE} --- Function: \textbf{make-closure} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-COMPILER-TYPE} \index{MAKE-COMPILER-TYPE} --- Function: \textbf{make-compiler-type} [\textbf{system}] \textit{typespec} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-DOUBLE-FLOAT} \index{MAKE-DOUBLE-FLOAT} --- Function: \textbf{make-double-float} [\textbf{system}] \textit{bits} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-ENVIRONMENT} \index{MAKE-ENVIRONMENT} --- Function: \textbf{make-environment} [\textbf{system}] \textit{\&optional parent-environment} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-FILE-STREAM} \index{MAKE-FILE-STREAM} --- Function: \textbf{make-file-stream} [\textbf{system}] \textit{pathname element-type direction if-exists external-format} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-FILL-POINTER-OUTPUT-STREAM} \index{MAKE-FILL-POINTER-OUTPUT-STREAM} --- Function: \textbf{make-fill-pointer-output-stream} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-INTEGER-TYPE} \index{MAKE-INTEGER-TYPE} --- Function: \textbf{make-integer-type} [\textbf{system}] \textit{type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-KEYWORD} \index{MAKE-KEYWORD} --- Function: \textbf{make-keyword} [\textbf{system}] \textit{symbol} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-LAYOUT} \index{MAKE-LAYOUT} --- Function: \textbf{make-layout} [\textbf{system}] \textit{class instance-slots class-slots} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-MACRO} \index{MAKE-MACRO} --- Function: \textbf{make-macro} [\textbf{system}] \textit{name expansion-function} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-MACRO-EXPANDER} \index{MAKE-MACRO-EXPANDER} --- Function: \textbf{make-macro-expander} [\textbf{system}] \textit{definition} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-SINGLE-FLOAT} \index{MAKE-SINGLE-FLOAT} --- Function: \textbf{make-single-float} [\textbf{system}] \textit{bits} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-STRUCTURE} \index{MAKE-STRUCTURE} --- Function: \textbf{make-structure} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MAKE-SYMBOL-MACRO} \index{MAKE-SYMBOL-MACRO} --- Function: \textbf{make-symbol-macro} [\textbf{system}] \textit{expansion} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:MATCH-WILD-JAR-PATHNAME} \index{MATCH-WILD-JAR-PATHNAME} --- Function: \textbf{match-wild-jar-pathname} [\textbf{system}] \textit{wild-jar-pathname} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:NAMED-LAMBDA} \index{NAMED-LAMBDA} --- Macro: \textbf{named-lambda} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:NORMALIZE-TYPE} \index{NORMALIZE-TYPE} --- Function: \textbf{normalize-type} [\textbf{system}] \textit{type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:NOTE-NAME-DEFINED} \index{NOTE-NAME-DEFINED} --- Function: \textbf{note-name-defined} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:NOTINLINE-P} \index{NOTINLINE-P} --- Function: \textbf{notinline-p} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:OUT-SYNONYM-OF} \index{OUT-SYNONYM-OF} --- Function: \textbf{out-synonym-of} [\textbf{system}] \textit{stream-designator} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:OUTPUT-OBJECT} \index{OUTPUT-OBJECT} --- Function: \textbf{output-object} [\textbf{system}] \textit{object stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PACKAGE-EXTERNAL-SYMBOLS} \index{PACKAGE-EXTERNAL-SYMBOLS} --- Function: \textbf{package-external-symbols} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PACKAGE-INHERITED-SYMBOLS} \index{PACKAGE-INHERITED-SYMBOLS} --- Function: \textbf{package-inherited-symbols} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PACKAGE-INTERNAL-SYMBOLS} \index{PACKAGE-INTERNAL-SYMBOLS} --- Function: \textbf{package-internal-symbols} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PACKAGE-SYMBOLS} \index{PACKAGE-SYMBOLS} --- Function: \textbf{package-symbols} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PARSE-BODY} \index{PARSE-BODY} --- Function: \textbf{parse-body} [\textbf{system}] \textit{body \&optional (doc-string-allowed t)} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{EXTENSIONS:PRECOMPILE} \index{PRECOMPILE} --- Function: \textbf{precompile} [\textbf{extensions}] \textit{name \&optional definition} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-ALIVE-P} \index{PROCESS-ALIVE-P} --- Function: \textbf{process-alive-p} [\textbf{system}] \textit{process} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-ERROR} \index{PROCESS-ERROR} --- Function: \textbf{process-error} [\textbf{system}] \textit{process} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-EXIT-CODE} \index{PROCESS-EXIT-CODE} --- Function: \textbf{process-exit-code} [\textbf{system}] \textit{instance} \begin{adjustwidth}{5em}{5em} The exit code of a process. \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-INPUT} \index{PROCESS-INPUT} --- Function: \textbf{process-input} [\textbf{system}] \textit{process} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-KILL} \index{PROCESS-KILL} --- Function: \textbf{process-kill} [\textbf{system}] \textit{process} \begin{adjustwidth}{5em}{5em} Kills the process. \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-OPTIMIZATION-DECLARATIONS} \index{PROCESS-OPTIMIZATION-DECLARATIONS} --- Function: \textbf{process-optimization-declarations} [\textbf{system}] \textit{forms} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-OUTPUT} \index{PROCESS-OUTPUT} --- Function: \textbf{process-output} [\textbf{system}] \textit{process} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-P} \index{PROCESS-P} --- Function: \textbf{process-p} [\textbf{system}] \textit{object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-PID} \index{PROCESS-PID} --- Function: \textbf{process-pid} [\textbf{system}] \textit{process} \begin{adjustwidth}{5em}{5em} Return the process ID. \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCESS-WAIT} \index{PROCESS-WAIT} --- Function: \textbf{process-wait} [\textbf{system}] \textit{process} \begin{adjustwidth}{5em}{5em} Wait for process to quit running for some reason. \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCLAIMED-FTYPE} \index{PROCLAIMED-FTYPE} --- Function: \textbf{proclaimed-ftype} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PROCLAIMED-TYPE} \index{PROCLAIMED-TYPE} --- Function: \textbf{proclaimed-type} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PSXHASH} \index{PSXHASH} --- Function: \textbf{psxhash} [\textbf{system}] \textit{object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PUT} \index{PUT} --- Function: \textbf{put} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:PUTHASH} \index{PUTHASH} --- Function: \textbf{puthash} [\textbf{system}] \textit{key hash-table new-value \&optional default} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:READ-8-BITS} \index{READ-8-BITS} --- Function: \textbf{read-8-bits} [\textbf{system}] \textit{stream \&optional eof-error-p eof-value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:READ-VECTOR-UNSIGNED-BYTE-8} \index{READ-VECTOR-UNSIGNED-BYTE-8} --- Function: \textbf{read-vector-unsigned-byte-8} [\textbf{system}] \textit{vector stream start end} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:RECORD-SOURCE-INFORMATION} \index{RECORD-SOURCE-INFORMATION} --- Function: \textbf{record-source-information} [\textbf{system}] \textit{name \&optional source-pathname source-position} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:RECORD-SOURCE-INFORMATION-FOR-TYPE} \index{RECORD-SOURCE-INFORMATION-FOR-TYPE} --- Function: \textbf{record-source-information-for-type} [\textbf{system}] \textit{name type \&optional source-pathname source-position} \begin{adjustwidth}{5em}{5em} Record source information on the SYS:SOURCE property for symbol with NAME TYPE is either a symbol or list. Source information for functions, methods, and generic functions are represented as lists of the following form: (:generic-function function-name) (:function function-name) (:method method-name qualifiers specializers) Where FUNCTION-NAME or METHOD-NAME can be a either be of the form 'symbol or '(setf symbol). Source information for all other forms have a symbol for TYPE which is one of the following: :class, :variable, :condition, :constant, :compiler-macro, :macro :package, :structure, :type, :setf-expander, :source-transform These values follow SBCL'S implemenation in SLIME c.f. \end{adjustwidth} \paragraph{} \label{SYSTEM:REMEMBER} \index{REMEMBER} --- Function: \textbf{remember} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:REMOVE-ZIP-CACHE-ENTRY} \index{REMOVE-ZIP-CACHE-ENTRY} --- Function: \textbf{remove-zip-cache-entry} [\textbf{system}] \textit{pathname} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:REQUIRE-TYPE} \index{REQUIRE-TYPE} --- Function: \textbf{require-type} [\textbf{system}] \textit{arg type} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:RUN-PROGRAM} \index{RUN-PROGRAM} --- Function: \textbf{run-program} [\textbf{system}] \textit{program args \&key environment (wait t) clear-environment (input stream) (output stream) (error stream) if-input-does-not-exist (if-output-exists error) (if-error-exists error) directory} \begin{adjustwidth}{5em}{5em} Run PROGRAM with ARGS in with ENVIRONMENT variables. Possibly WAIT for subprocess to exit. Optionally CLEAR-ENVIRONMENT of the subprocess of any non specified values. Creates a new process running the the PROGRAM. ARGS are a list of strings to be passed to the program as arguments. For no arguments, use nil which means that just the name of the program is passed as arg 0. Returns a process structure containing the JAVA-OBJECT wrapped Process object, and the PROCESS-INPUT, PROCESS-OUTPUT, and PROCESS-ERROR streams. c.f. http://download.oracle.com/javase/6/docs/api/java/lang/Process.html Notes about Unix environments (as in the :environment): * The ABCL implementation of run-program, like SBCL, Perl and many other programs, copies the Unix environment by default. * Running Unix programs from a setuid process, or in any other situation where the Unix environment is under the control of someone else, is a mother lode of security problems. If you are contemplating doing this, read about it first. (The Perl community has a lot of good documentation about this and other security issues in script-like programs. The \&key arguments have the following meanings: :environment An alist of STRINGs (name . value) describing new environment values that replace existing ones. :clear-environment If non-NIL, the current environment is cleared before the values supplied by :environment are inserted. :wait If non-NIL, which is the default, wait until the created process finishes. If NIL, continue running Lisp until the program finishes. :input If T, I/O is inherited from the Java process. If NIL, /dev/null is used (nul on Windows). If a PATHNAME designator other than a stream is supplied, input will be read from that file. If set to :STREAM, a stream will be available via PROCESS-INPUT to read from. Defaults to :STREAM. :if-input-does-not-exist If :input points to a non-existing file, this may be set to :ERROR in order to signal an error, :CREATE to create and read from an empty file, or NIL to immediately NIL instead of creating the process. Defaults to NIL. :output If T, I/O is inherited from the Java process. If NIL, /dev/null is used (nul on Windows). If a PATHNAME designator other than a stream is supplied, output will be redirect to that file. If set to :STREAM, a stream will be available via PROCESS-OUTPUT to write to. Defaults to :STREAM. :if-output-exists If :output points to a non-existing file, this may be set to :ERROR in order to signal an error, :SUPERSEDE to supersede the existing file, :APPEND to append to it instead, or NIL to immediately NIL instead of creating the process. Defaults to :ERROR. :error Same as :output, but can also be :output, in which case the error stream is redirected to wherever the standard output stream goes. Defaults to :STREAM. :if-error-exists Same as :if-output-exists, but for the :error target. :directory If set will become the working directory for the new process, otherwise the working directory will be unchanged from the current Java process. Defaults to NIL. \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CALL-COUNT} \index{SET-CALL-COUNT} --- Function: \textbf{set-call-count} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CAR} \index{SET-CAR} --- Function: \textbf{set-car} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CDR} \index{SET-CDR} --- Function: \textbf{set-cdr} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-CHAR} \index{SET-CHAR} --- Function: \textbf{set-char} [\textbf{system}] \textit{string index character} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-FUNCTION-INFO-VALUE} \index{SET-FUNCTION-INFO-VALUE} --- Function: \textbf{set-function-info-value} [\textbf{system}] \textit{name indicator value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-HOT-COUNT} \index{SET-HOT-COUNT} --- Function: \textbf{set-hot-count} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-SCHAR} \index{SET-SCHAR} --- Function: \textbf{set-schar} [\textbf{system}] \textit{string index character} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SET-STD-SLOT-VALUE} \index{SET-STD-SLOT-VALUE} --- Function: \textbf{set-std-slot-value} [\textbf{system}] \textit{instance slot-name new-value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SETF-FUNCTION-NAME-P} \index{SETF-FUNCTION-NAME-P} --- Function: \textbf{setf-function-name-p} [\textbf{system}] \textit{thing} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SHA256} \index{SHA256} --- Function: \textbf{sha256} [\textbf{system}] \textit{\&rest paths-or-strings} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SHRINK-VECTOR} \index{SHRINK-VECTOR} --- Function: \textbf{shrink-vector} [\textbf{system}] \textit{vector new-size} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SIMPLE-FORMAT} \index{SIMPLE-FORMAT} --- Function: \textbf{simple-format} [\textbf{system}] \textit{destination control-string \&rest format-arguments} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SIMPLE-SEARCH} \index{SIMPLE-SEARCH} --- Function: \textbf{simple-search} [\textbf{system}] \textit{sequence1 sequence2} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SIMPLE-TYPEP} \index{SIMPLE-TYPEP} --- Function: \textbf{simple-typep} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SINGLE-FLOAT-BITS} \index{SINGLE-FLOAT-BITS} --- Function: \textbf{single-float-bits} [\textbf{system}] \textit{float} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SLOT-DEFINITION} \index{SLOT-DEFINITION} --- Class: \textbf{slot-definition} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SOURCE-TRANSFORM} \index{SOURCE-TRANSFORM} --- Function: \textbf{source-transform} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STANDARD-INSTANCE-ACCESS} \index{STANDARD-INSTANCE-ACCESS} --- Function: \textbf{standard-instance-access} [\textbf{system}] \textit{instance location} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STANDARD-OBJECT-P} \index{STANDARD-OBJECT-P} --- Function: \textbf{standard-object-p} [\textbf{system}] \textit{object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STD-INSTANCE-CLASS} \index{STD-INSTANCE-CLASS} --- Function: \textbf{std-instance-class} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STD-INSTANCE-LAYOUT} \index{STD-INSTANCE-LAYOUT} --- Function: \textbf{std-instance-layout} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STD-SLOT-BOUNDP} \index{STD-SLOT-BOUNDP} --- Function: \textbf{std-slot-boundp} [\textbf{system}] \textit{instance slot-name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STD-SLOT-VALUE} \index{STD-SLOT-VALUE} --- Function: \textbf{std-slot-value} [\textbf{system}] \textit{instance slot-name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRUCTURE-LENGTH} \index{STRUCTURE-LENGTH} --- Function: \textbf{structure-length} [\textbf{system}] \textit{instance} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRUCTURE-OBJECT-P} \index{STRUCTURE-OBJECT-P} --- Function: \textbf{structure-object-p} [\textbf{system}] \textit{object} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRUCTURE-REF} \index{STRUCTURE-REF} --- Function: \textbf{structure-ref} [\textbf{system}] \textit{instance index} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:STRUCTURE-SET} \index{STRUCTURE-SET} --- Function: \textbf{structure-set} [\textbf{system}] \textit{instance index new-value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SUBCLASSP} \index{SUBCLASSP} --- Function: \textbf{subclassp} [\textbf{system}] \textit{class} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SVSET} \index{SVSET} --- Function: \textbf{svset} [\textbf{system}] \textit{simple-vector index new-value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SWAP-SLOTS} \index{SWAP-SLOTS} --- Function: \textbf{swap-slots} [\textbf{system}] \textit{instance-1 instance-2} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SYMBOL-MACRO-P} \index{SYMBOL-MACRO-P} --- Function: \textbf{symbol-macro-p} [\textbf{system}] \textit{value} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:SYSTEM-ARTIFACTS-ARE-JARS-P} \index{SYSTEM-ARTIFACTS-ARE-JARS-P} --- Function: \textbf{system-artifacts-are-jars-p} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:UNDEFINED-FUNCTION-CALLED} \index{UNDEFINED-FUNCTION-CALLED} --- Function: \textbf{undefined-function-called} [\textbf{system}] \textit{name arguments} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:UNTRACED-FUNCTION} \index{UNTRACED-FUNCTION} --- Function: \textbf{untraced-function} [\textbf{system}] \textit{name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:UNZIP} \index{UNZIP} --- Function: \textbf{unzip} [\textbf{system}] \textit{pathname \&optional directory => unzipped\_pathnames} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:URL-STREAM} \index{URL-STREAM} --- Class: \textbf{url-stream} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:VECTOR-DELETE-EQ} \index{VECTOR-DELETE-EQ} --- Function: \textbf{vector-delete-eq} [\textbf{system}] \textit{item vector} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:VECTOR-DELETE-EQL} \index{VECTOR-DELETE-EQL} --- Function: \textbf{vector-delete-eql} [\textbf{system}] \textit{item vector} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:WHITESPACEP} \index{WHITESPACEP} --- Function: \textbf{whitespacep} [\textbf{system}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:WRITE-8-BITS} \index{WRITE-8-BITS} --- Function: \textbf{write-8-bits} [\textbf{system}] \textit{byte stream} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:WRITE-VECTOR-UNSIGNED-BYTE-8} \index{WRITE-VECTOR-UNSIGNED-BYTE-8} --- Function: \textbf{write-vector-unsigned-byte-8} [\textbf{system}] \textit{vector stream start end} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{SYSTEM:ZIP} \index{ZIP} --- Function: \textbf{zip} [\textbf{system}] \textit{pathname pathnames \&optional topdir} \begin{adjustwidth}{5em}{5em} Creates a zip archive at PATHNAME whose entries enumerated via the list of PATHNAMES. If the optional TOPDIR argument is specified, the archive will preserve the hierarchy of PATHNAMES relative to TOPDIR. Without TOPDIR, there will be no sub-directories in the archive, i.e. it will be flat. \end{adjustwidth} abcl-src-1.9.0/doc/manual/threads.aux0100644 0000000 0000000 00000011217 14242630063 016133 0ustar000000000 0000000 \relax \providecommand\hyper@newdestlabel[2]{} \newlabel{THREADS:*THREADING-MODEL*}{{3.4.2}{30}{}{section*.93}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.93}\protected@file@percent } \newlabel{THREADS:CURRENT-THREAD}{{3.4.2}{30}{}{section*.94}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.94}\protected@file@percent } \newlabel{THREADS:DESTROY-THREAD}{{3.4.2}{30}{}{section*.95}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.95}\protected@file@percent } \newlabel{THREADS:GET-MUTEX}{{3.4.2}{30}{}{section*.96}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.96}\protected@file@percent } \newlabel{THREADS:INTERRUPT-THREAD}{{3.4.2}{30}{}{section*.97}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.97}\protected@file@percent } \newlabel{THREADS:MAILBOX-EMPTY-P}{{3.4.2}{30}{}{section*.98}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.98}\protected@file@percent } \newlabel{THREADS:MAILBOX-PEEK}{{3.4.2}{30}{}{section*.99}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.99}\protected@file@percent } \newlabel{THREADS:MAILBOX-READ}{{3.4.2}{30}{}{section*.100}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.100}\protected@file@percent } \newlabel{THREADS:MAILBOX-SEND}{{3.4.2}{30}{}{section*.101}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.101}\protected@file@percent } \newlabel{THREADS:MAKE-MAILBOX}{{3.4.2}{30}{}{section*.102}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.102}\protected@file@percent } \newlabel{THREADS:MAKE-MUTEX}{{3.4.2}{30}{}{section*.103}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.103}\protected@file@percent } \newlabel{THREADS:MAKE-THREAD}{{3.4.2}{30}{}{section*.104}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.104}\protected@file@percent } \newlabel{THREADS:MAKE-THREAD-LOCK}{{3.4.2}{30}{}{section*.105}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.105}\protected@file@percent } \newlabel{THREADS:MAPCAR-THREADS}{{3.4.2}{30}{}{section*.106}{}} \@writefile{toc}{\contentsline {paragraph}{}{30}{section*.106}\protected@file@percent } \newlabel{THREADS:OBJECT-NOTIFY}{{3.4.2}{31}{}{section*.107}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.107}\protected@file@percent } \newlabel{THREADS:OBJECT-NOTIFY-ALL}{{3.4.2}{31}{}{section*.108}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.108}\protected@file@percent } \newlabel{THREADS:OBJECT-WAIT}{{3.4.2}{31}{}{section*.109}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.109}\protected@file@percent } \newlabel{THREADS:RELEASE-MUTEX}{{3.4.2}{31}{}{section*.110}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.110}\protected@file@percent } \newlabel{THREADS:SYNCHRONIZED-ON}{{3.4.2}{31}{}{section*.111}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.111}\protected@file@percent } \newlabel{THREADS:THREAD}{{3.4.2}{31}{}{section*.112}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.112}\protected@file@percent } \newlabel{THREADS:THREAD-ALIVE-P}{{3.4.2}{31}{}{section*.113}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.113}\protected@file@percent } \newlabel{THREADS:THREAD-JOIN}{{3.4.2}{31}{}{section*.114}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.114}\protected@file@percent } \newlabel{THREADS:THREAD-NAME}{{3.4.2}{31}{}{section*.115}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.115}\protected@file@percent } \newlabel{THREADS:THREADP}{{3.4.2}{31}{}{section*.116}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.116}\protected@file@percent } \newlabel{THREADS:WITH-MUTEX}{{3.4.2}{31}{}{section*.117}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.117}\protected@file@percent } \newlabel{THREADS:WITH-THREAD-LOCK}{{3.4.2}{31}{}{section*.118}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.118}\protected@file@percent } \newlabel{THREADS:YIELD}{{3.4.2}{31}{}{section*.119}{}} \@writefile{toc}{\contentsline {paragraph}{}{31}{section*.119}\protected@file@percent } \@setckpt{threads}{ \setcounter{page}{32} \setcounter{equation}{0} \setcounter{enumi}{0} \setcounter{enumii}{0} \setcounter{enumiii}{0} \setcounter{enumiv}{0} \setcounter{footnote}{2} \setcounter{mpfootnote}{0} \setcounter{part}{0} \setcounter{chapter}{3} \setcounter{section}{4} \setcounter{subsection}{2} \setcounter{subsubsection}{0} \setcounter{paragraph}{0} \setcounter{subparagraph}{0} \setcounter{figure}{0} \setcounter{table}{0} \setcounter{Item}{0} \setcounter{Hfootnote}{13} \setcounter{bookmark@seq@number}{35} \setcounter{lstnumber}{2} \setcounter{cp@cntr}{0} \setcounter{section@level}{4} \setcounter{lstlisting}{0} } abcl-src-1.9.0/doc/manual/threads.tex0100644 0000000 0000000 00000016426 14242627550 016154 0ustar000000000 0000000 \paragraph{} \label{THREADS:*THREADING-MODEL*} \index{*THREADING-MODEL*} --- Variable: \textbf{*threading-model*} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:CURRENT-THREAD} \index{CURRENT-THREAD} --- Function: \textbf{current-thread} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} Returns a reference to invoking thread. \end{adjustwidth} \paragraph{} \label{THREADS:DESTROY-THREAD} \index{DESTROY-THREAD} --- Function: \textbf{destroy-thread} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:GET-MUTEX} \index{GET-MUTEX} --- Function: \textbf{get-mutex} [\textbf{threads}] \textit{mutex} \begin{adjustwidth}{5em}{5em} Acquires the lock associated with the MUTEX \end{adjustwidth} \paragraph{} \label{THREADS:INTERRUPT-THREAD} \index{INTERRUPT-THREAD} --- Function: \textbf{interrupt-thread} [\textbf{threads}] \textit{thread function \&rest args} \begin{adjustwidth}{5em}{5em} Interrupts THREAD and forces it to apply FUNCTION to ARGS. When the function returns, the thread's original computation continues. If multiple interrupts are queued for a thread, they are all run, but the order is not guaranteed. \end{adjustwidth} \paragraph{} \label{THREADS:MAILBOX-EMPTY-P} \index{MAILBOX-EMPTY-P} --- Function: \textbf{mailbox-empty-p} [\textbf{threads}] \textit{mailbox} \begin{adjustwidth}{5em}{5em} Returns non-NIL if the mailbox can be read from, NIL otherwise. \end{adjustwidth} \paragraph{} \label{THREADS:MAILBOX-PEEK} \index{MAILBOX-PEEK} --- Function: \textbf{mailbox-peek} [\textbf{threads}] \textit{mailbox} \begin{adjustwidth}{5em}{5em} Returns two values. The second returns non-NIL when the mailbox is empty. The first is the next item to be read from the mailbox. Note that due to multi-threading, the first value returned upon peek, may be different from the one returned upon next read in the calling thread. \end{adjustwidth} \paragraph{} \label{THREADS:MAILBOX-READ} \index{MAILBOX-READ} --- Function: \textbf{mailbox-read} [\textbf{threads}] \textit{mailbox} \begin{adjustwidth}{5em}{5em} Blocks on the mailbox until an item is available for reading. When an item is available, it is returned. \end{adjustwidth} \paragraph{} \label{THREADS:MAILBOX-SEND} \index{MAILBOX-SEND} --- Function: \textbf{mailbox-send} [\textbf{threads}] \textit{mailbox item} \begin{adjustwidth}{5em}{5em} Sends an item into the mailbox, notifying 1 waiter to wake up for retrieval of that object. \end{adjustwidth} \paragraph{} \label{THREADS:MAKE-MAILBOX} \index{MAKE-MAILBOX} --- Function: \textbf{make-mailbox} [\textbf{threads}] \textit{\&key ((queue g305426) NIL)} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:MAKE-MUTEX} \index{MAKE-MUTEX} --- Function: \textbf{make-mutex} [\textbf{threads}] \textit{\&key ((in-use g305689) NIL)} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:MAKE-THREAD} \index{MAKE-THREAD} --- Function: \textbf{make-thread} [\textbf{threads}] \textit{function \&key name} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:MAKE-THREAD-LOCK} \index{MAKE-THREAD-LOCK} --- Function: \textbf{make-thread-lock} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} Returns an object to be used with the WITH-THREAD-LOCK macro. \end{adjustwidth} \paragraph{} \label{THREADS:MAPCAR-THREADS} \index{MAPCAR-THREADS} --- Function: \textbf{mapcar-threads} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:OBJECT-NOTIFY} \index{OBJECT-NOTIFY} --- Function: \textbf{object-notify} [\textbf{threads}] \textit{object} \begin{adjustwidth}{5em}{5em} Wakes up a single thread that is waiting on OBJECT's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods. \end{adjustwidth} \paragraph{} \label{THREADS:OBJECT-NOTIFY-ALL} \index{OBJECT-NOTIFY-ALL} --- Function: \textbf{object-notify-all} [\textbf{threads}] \textit{object} \begin{adjustwidth}{5em}{5em} Wakes up all threads that are waiting on this OBJECT's monitor. A thread waits on an object's monitor by calling one of the wait methods. \end{adjustwidth} \paragraph{} \label{THREADS:OBJECT-WAIT} \index{OBJECT-WAIT} --- Function: \textbf{object-wait} [\textbf{threads}] \textit{object \&optional timeout} \begin{adjustwidth}{5em}{5em} Causes the current thread to block until object-notify or object-notify-all is called on OBJECT. Optionally unblock execution after TIMEOUT seconds. A TIMEOUT of zero means to wait indefinitely. A non-zero TIMEOUT of less than a nanosecond is interpolated as a nanosecond wait. See the documentation of java.lang.Object.wait() for further information. \end{adjustwidth} \paragraph{} \label{THREADS:RELEASE-MUTEX} \index{RELEASE-MUTEX} --- Function: \textbf{release-mutex} [\textbf{threads}] \textit{mutex} \begin{adjustwidth}{5em}{5em} Releases a lock associated with MUTEX \end{adjustwidth} \paragraph{} \label{THREADS:SYNCHRONIZED-ON} \index{SYNCHRONIZED-ON} --- Special Operator: \textbf{synchronized-on} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:THREAD} \index{THREAD} --- Class: \textbf{thread} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:THREAD-ALIVE-P} \index{THREAD-ALIVE-P} --- Function: \textbf{thread-alive-p} [\textbf{threads}] \textit{thread} \begin{adjustwidth}{5em}{5em} Boolean predicate whether THREAD is alive. \end{adjustwidth} \paragraph{} \label{THREADS:THREAD-JOIN} \index{THREAD-JOIN} --- Function: \textbf{thread-join} [\textbf{threads}] \textit{thread} \begin{adjustwidth}{5em}{5em} Waits for THREAD to die before resuming execution Returns the result of the joined thread as its primary value. Returns T if the joined thread finishes normally or NIL if it was interrupted. \end{adjustwidth} \paragraph{} \label{THREADS:THREAD-NAME} \index{THREAD-NAME} --- Function: \textbf{thread-name} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:THREADP} \index{THREADP} --- Function: \textbf{threadp} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} not-documented \end{adjustwidth} \paragraph{} \label{THREADS:WITH-MUTEX} \index{WITH-MUTEX} --- Macro: \textbf{with-mutex} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} Acquires a lock on MUTEX, executes BODY, and then releases the lock \end{adjustwidth} \paragraph{} \label{THREADS:WITH-THREAD-LOCK} \index{WITH-THREAD-LOCK} --- Macro: \textbf{with-thread-lock} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} Acquires the LOCK, executes BODY and releases the LOCK \end{adjustwidth} \paragraph{} \label{THREADS:YIELD} \index{YIELD} --- Function: \textbf{yield} [\textbf{threads}] \textit{} \begin{adjustwidth}{5em}{5em} A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint. See java.lang.Thread.yield(). \end{adjustwidth} abcl-src-1.9.0/doc/packaging-abcl.org0100644 0000000 0000000 00000006635 14202767264 016063 0ustar000000000 0000000 #+TITLE: Notes Packaging ABCL for Distribution * abcl-aio The standard ABCL build process as described in the ~build.xml~ file and executed by the Ant build tool results in two artifacts: ~abcl.jar~ and ~abcl-contrib.jar~. ~abcl.jar~ contains all the Java and Common Lisp code necessary that constitute the ANSI conforming implementation runtime. The ~abcl-contrib.jar~ (aka "contrib") artifact contains additional Common Lisp-only code that extends the implementation in useful manners. We create two separate jar artifacts in order to: 1. To place an upper bound of size of ~abcl.jar~ regardless of what we package in ~abcl-contrib.jar~. 2. Clearly mark which parts of the code-base are covered under GPLv2+classpath from those that may have other licensing terms. By making the loading of "contrib" a dynamic operation, we defer possible infringement to the User who redistributes the resulting jar artifact. Users often want to simply package both artifacts in a single jar for deployment convenience. abcl-1.5.0 introduced the build machinery to create such an "all-in-one" artifact via the [[https://github.com/armedbear/abcl/blob/master/build.xml#L517][~abcl-aio.jar~]] target. Upon invoking the ~abcl-aio.jar~ target #+begin_src shell ant -f build.xml abcl-aio.jar #+end_src the resulting artifact contains both the core implementation and the ABCL contrib which may be run as usual via #+begin_src shell java -jar dist/abcl-aio.jar #+end_src * abcl-jar contrib The ABCL-JAR contrib provides a mechanism for package ASDF systems and their recursive dependencies in a jar archive. An example of using this to package the CL-PPCRE system from Quicklisp #+begin_src lisp ;; (require :abcl-contrib) (require :quicklisp-abcl) (ql:quickload :cl-ppcre) (require :asdf-jar) (asdf-jar:package :cl-ppcre) #+end_src results in a jar archive at something like ~#P"/var/tmp/cl-ppcre-all-2.1.1.jar"~. This jar archive may be loaded in a version of the implementation via #+begin_src lisp (require :abcl-contrib) (require :asdf-jar) (setf *load-verbose* t) ;; so we can verify where the load is coming from (asdf-jar:add-to-asdf #P"/var/tmp/cl-ppcre-all-2.1.1.jar") (asdf:load-system :cl-ppcre) #+end_src =asdf-jar= uses all items declared in the ASDF definitions so it won't work well for: 1. An ASDF system which depends on artifacts that are not declared as existing on the file-system via an explicit reference within the ASDF source reference mechanism. 2. Libraries such as CFFI which depend on items to be have been make available via an operating system packaging mechanism. * Current hack Ideally, we would like allow the AIO mechanism to include additional ASDF systems in the single jar artifact. Currently one can hack this together by: 1. Manually extracting the ~abcl-aio.jar~ artifact to a file-system. 2. Placing the necessary ASDF systems in the resulting "contrib" directory. 3. Recreating the single archive from the file-system contents. * TODO Future directions Obviously, we could packaging ABCL applications as single archives much more convenient. Rather than mucking around in the Ant build system, I would rather that we add the necessary machinery =ABCL-BUILD= contrib as it will make customization much easier for those who know Common Lisp. * Colophon #+begin_example Mark Created: <2019-11-25 Mon> Revised: <2019-11-25 Mon 14:07> #+end_example abcl-src-1.9.0/doc/profiling-org.armedbear.lisp.asdf_642.class0100644 0000000 0000000 00000013177 14202767264 022531 0ustar000000000 0000000 ����1REGISTER-SYSTEMASDF/FIND-SYSTEMorg/armedbear/lisp/LispinternInPackageA(Ljava/lang/String;Ljava/lang/String;)Lorg/armedbear/lisp/Symbol;   (SYSTEM) readObjectFromString3(Ljava/lang/String;)Lorg/armedbear/lisp/LispObject;  $org/armedbear/lisp/CompiledPrimitiveA(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)V  !org/armedbear/lisp/ClosureBinding"(Lorg/armedbear/lisp/LispObject;)V  %TYPEPSYSTEMorg/armedbear/lisp/asdf_642  SYM1035450Lorg/armedbear/lisp/Symbol; "# !$ ASDF/SYSTEM& SYM1035451 (# !)org/armedbear/lisp/LispThread+execute~(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject; -. ,/org/armedbear/lisp/Nil1NIL 3# 4CHECK-TYPE-ERROR6 SYM1035452 8# !9�(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject; -; ,< interruptedZ >? @handleInterrupt()V BC DCOMPONENT-NAMEFASDF/COMPONENTH SYM1035454 J# !K_(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject; -M ,N!org/armedbear/lisp/AbstractStringPNAMER SYM1035463 T# !Uorg/armedbear/lisp/SymbolWSTRING Y# XZ SYM1035464 \# !] ASDF-MESSAGE_ ASDF/UPGRADEa SYM1035466 c# !dorg/armedbear/lisp/SimpleStringf#~&~@<; ~@;Registering ~3i~_~A~@:>~%h(Ljava/lang/String;)V j gk STR1035467#Lorg/armedbear/lisp/AbstractString; mn !oGETHASH q# Xr SYM1035470 t# !u*DEFINED-SYSTEMS*w SYM1035471 y# !zW symbolValue@(Lorg/armedbear/lisp/LispThread;)Lorg/armedbear/lisp/LispObject; }~ |org/armedbear/lisp/LispObject�cdr!()Lorg/armedbear/lisp/LispObject; �� ��PUTHASH �# X� SYM1035472 �# !�org/armedbear/lisp/Cons� C ��markSpecialBindings*()Lorg/armedbear/lisp/SpecialBindingsMark; �� ,�ERROR �# X� SYM1035479 �# !� LFUN1035439Lorg/armedbear/lisp/LispObject; �� !�"org/armedbear/lisp/CompiledClosure�java/lang/System� arraycopy*(Ljava/lang/Object;ILjava/lang/Object;II)V �� ��makeCompiledClosured(Lorg/armedbear/lisp/LispObject;[Lorg/armedbear/lisp/ClosureBinding;)Lorg/armedbear/lisp/LispObject; �� � �  ��*HANDLER-CLUSTERS*� SYM1035490 �# !� bindSpecial_(Lorg/armedbear/lisp/Symbol;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/SpecialBinding; �� ,�SYSTEM-SOURCE-FILE� SYM1035496 �# !�resetSpecialBindings+(Lorg/armedbear/lisp/SpecialBindingsMark;)V �� ,� stackError �� � memoryError=(Ljava/lang/OutOfMemoryError;)Lorg/armedbear/lisp/LispObject; �� �value �� � setValues �M ,�org/armedbear/lisp/Go�tagbody �� ��tag �� ��org/armedbear/lisp/Load�getUninternedSymbol"(I)Lorg/armedbear/lisp/LispObject; �� �� SYM1035499 �# !�GET-FILE-STAMP� ASDF/CACHE� SYM1035502 �# !��(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject; -� ,�org/armedbear/lisp/asdf_643� �� currentThread!()Lorg/armedbear/lisp/LispThread; �� ,�@(Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject;Code_values [Lorg/armedbear/lisp/LispObject; �� ,�java/lang/OutOfMemoryError�java/lang/StackOverflowError�LineNumberTable SourceFile asdf.lisp(Ljava/lang/Object;C)V(C)V;org/netbeans/lib/profiler/server/ProfilerRuntimeObjLiveness � � traceObjAlloc � �profilePointHit!���#�#�#�#�#�#y#t#mnc#\#T#J#8#(#"#-������M�Y-�Y�Y�Y.�SY�Y�Y.�SN+:,�%�*�0�2�� ,���',�:�*�*�5�=,��L�A��ƸE���,�L+�O:,��:�Q� ,���(,�:�V�^�5�=,��:�A��иE���,�e�p+�0W,��+,�v�{,���0,������,��:::�{,��:��Y:  : �5�Z_�Y.�-__S��Y��Y���Z_�Y.�-__S,��: ,��:��Y��Y��Y������-�Y-�Y:������Y���Y���,����Y�,_��_��:,��,��+�O,���pW�°�ư,��-2��:,�5�̧N�;Y:��-2�ɦ��:, ���ݥ��-2_�ɿ-2_�ɿ-2_��,���5: ,�� �5�,�� �O��5: +: ,��   ��� :  �簲5���������S���S�&��C�*�  ��� �C���� �%'� �*7� �:GI� �LSI� �V�[�^`b� �e�gYi�lY���p�s�vx� �{���������� ���'� ��h���|���� ���Y��Y������� abcl-src-1.9.0/doc/profiling.markdown0100644 0000000 0000000 00000000263 14202767264 016253 0ustar000000000 0000000 # org.armedbear.lisp.asdf_642.class From Netbeans 7.3.1 profiling on ("1.3.0-dev" "Java_HotSpot(TM)_64-Bit_Server_VM-Oracle_Corporation-1.7.0_25-b15" "x86_64-Mac_OS_X-10.8.4"). abcl-src-1.9.0/doc/releng.org0100644 0000000 0000000 00000013037 14242627550 014503 0ustar000000000 0000000 * ABCL Release Engineering See also . ** Signing binary release #+begin_src bash gpg --default-key YOUR-KEY --detach-sign --armor FILE #+end_src #+begin_src bash key="evenson.not.org@gmail.com" for file in *; do gpg --default-key ${key} --detach-sign --armor ${file} ; done #+end_src ** Maven Artifacts Instructions for releasing ABCL on Sonatype's OSS Maven repository. You need a Sonatype account, see . This will result in providing you with a "JIRA username and a password". **** settings.xml Enter your "JIRA username and a password" in a . This will be used for authentication when the =mvn= tool uploads artifacts to the Sonatype snapshot and staging infrastructure. #+BEGIN_SRC xml sonatype-nexus-snapshots sonatype-jira-username sonatype-jira-password sonatype-nexus-staging sonatype-jira-username sonatype-jira-password #+END_SRC **** Process Ensure that the artifacts you wish to upload are present by building them. #+begin_src ant abcl.release abcl.source.jar abcl.javadoc.jar abcl.contrib.javadoc.jar abcl.contrib.source.jar #+end_src #+BEGIN_SRC ant abcl.jar abcl.source.jar abcl.javadoc.jar abcl.contrib #+END_SRC And maybe test it as well #+BEGIN_SRC ant abcl.test #+END_SRC **** Snapshots For snapshots (aka development versions) the version in the POM should be of the form ~x.y.z-SNAPSHOT~. #+BEGIN_SRC bash keyname='' mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl.jar -DpomFile=pom.xml -Durl=https://oss.sonatype.org/content/repositories/snapshots/ -DrepositoryId=sonatype-nexus-snapshots mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl-sources.jar -DpomFile=pom.xml -Durl=https://oss.sonatype.org/content/repositories/snapshots/ -DrepositoryId=sonatype-nexus-snapshots -Dclassifier=sources mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl-javadoc.jar -DpomFile=pom.xml -Durl=https://oss.sonatype.org/content/repositories/snapshots/ -DrepositoryId=sonatype-nexus-snapshots -Dclassifier=javadoc mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl-contrib.jar -DpomFile=contrib/pom.xml -Durl=https://oss.sonatype.org/content/repositories/snapshots/ -DrepositoryId=sonatype-nexus-snapshots #+END_SRC **** Release For releases the version in the POM should be of the form ~x.y.z~ #+BEGIN_SRC bash #keyname='' #abcl_version=1.9.0 mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl.jar -DpomFile=pom.xml -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl-${abcl_version}-sources.jar -DpomFile=pom.xml -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -Dclassifier=sources mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl-${abcl_version}-javadoc.jar -DpomFile=pom.xml -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -Dclassifier=javadoc #+END_SRC abcl-contrib release #+BEGIN_SRC bash keyname='' abcl_version=1.9.0 mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl-contrib.jar -DpomFile=contrib/pom.xml -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl-contrib-${abcl_version}-sources.jar -DpomFile=contrib/pom.xml -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -Dclassifier=sources mvn gpg:sign-and-deploy-file -Dgpg.keyname=${keyname} -Dfile=dist/abcl-contrib-${abcl_version}-javadoc.jar -DpomFile=contrib/pom.xml -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -Dclassifier=javadoc #+END_SRC **** Releasing through Sonatype interface 1. "Close" the repo 2. wait 3. "Release" the repo **** Testing downloads #+BEGIN_SRC mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:get -DrepoUrl=https://oss.sonatype.org/content/repositories/snapshots -Dartifact=org.abcl:abcl-contrib:1.5.0-SNAPSHOT:jar #+END_SRC **** Specifying GPG executable For specifying the =gpg= executable used via =mvn= use a property specified via the =gpg.executable= property (e.g. '-Dgpg.executable=gpg2'.) ** Update CLiki page Roswell parses it for release information? ** Update MacPorts lang/abcl * Notes #+caption: Push locally built 1.9.0 artifacts to abcl.org #+begin_src bash rsync -avzP ~/work/abcl/dist/ mevenson@abcl.org:/project/armedbear/public_html/releases/1.9.0/ #+end_src #+caption: Remote hg+git URIs #+begin_example alanruttenberg = git+https://github.com/alanruttenberg/abcl default = git@github.com:easye/abcl upstream = git+https://github.com/armedbear/abcl #+end_example * Colophon #+begin_example Created: 2019-10-31 Revised: <2022-04-30 Sat 09:10Z> #+end_example abcl-src-1.9.0/doc/slime.markdown0100644 0000000 0000000 00000007573 14202767264 015406 0ustar000000000 0000000 SLIME ===== Author: Mark Evenson Created: 16-MAR-2010 Modified: 18-MAR-2010 SLIME is divided conceptually in two parts: the "swank" server process which runs in the native Lisp and the "slime" client process running in Emacs Lisp. These instructions were were written to accompany ABCL, but there is nothing ABCL specific in the instructions ## Obtaining SLIME SLIME does not follow a release process in the standard sense with centrally versioned releases, so you are best off with obtaining the [latest version from CVS][1]. [Daily snapshots as gzipped tarballs are also available][2]. Your local OS packaging system (i.e. MacPorts on OSX) may have a version as well. [1]: http://common-lisp.net/project/slime/#downloading [2]: http://common-lisp.net/project/slime/snapshots/slime-current.tgz ## Starting SLIME One first locates the SLIME directory on the filesystem. In the code that follows, the SLIME top level directory is assumed to be `"~/work/slime"`, so adjust this value to your local value as you see fit. Then one configures Emacs with the proper initialization hooks by adding code something like the following to "~/.emacs": :::common-lisp (add-to-list 'load-path "~/work/slime") (setq slime-lisp-implementations '((abcl ("~/work/abcl/abcl")) (abcl.svn ("~/work/abcl.svn/abcl")) (sbcl ("/opt/local/bin/sbcl")))) (require 'slime) (slime-setup '(slime-fancy slime-asdf slime-banner)) One further need to customize the setting of `SLIME-LISP-IMPLEMENTATIONS` to the location(s) of the Lisp(s) you wish to invoke via SLIME. The value is list of lists of the form (SYMBOL ("/path/to/lisp")) where SYMBOL is a mnemonic for the Lisp implementation, and the string `"/path/to/lisp"` is the absolute path of the Lisp implementation that SLIME will associate with this symbol. In the example above, I have defined three implementations, the main abcl implementation, a version that corresponds to the latest version from SVN invoked by `"~/work/abcl.svn/abcl"`, and a version of SBCL. To start SLIME one simply issues `M-x slime` from Emacs. This will start the first entry in the SLIME-LISP-IMPLEMENTATIONS list. If you wish to start a subsequent Lisp, prefix the Emacs invocation with a negative argument (i.e. `C-- M-x slime`). This will present an interactive chooser over all symbols contained in `SLIME-LISP-IMPLEMENTATIONS`. After you invoke SLIME, you'll see a buffer open up named `*inferior-lisp*` where the Lisp image is started up, the required swank code is complied and then loaded, finally, you'll see the "flying letters" resolving itself to a `"CL-USER>"` prompt with an inspiration message in the minibuffer. Your initiation to SLIME has begun... ## Starting swank on its own In debugging, one may wish to start the swank server by itself without connection to Emacs. The following code will both load and start the swank server from a Lisp image. One merely needs to change *SLIME-DIRECTORY* to point to the top directory of the server process. :::commmon-lisp (defvar *slime-directory* #p"~/work/slime/") ;; Don't forget trailing slash (load (merge-pathnames "swank-loader.lisp" *slime-directory*) :verbose t) (swank-loader:init) (swank:start-server "/tmp/swank.port") ;; remove if you don't want ;; swank to start listening for connections. When this code finishes executing, an integer representing the port on which the server starts will be written to `'/tmp/swank.port'` and also returned as the result of evaluating `SWANK:START-SERVER`. One may connect to this port via issuing `M-x slime-connect` in Emacs. ## M$FT Windows See for instructions specific to installing SLIME under Windows. ### Historivia Luke Gorrie inherited a server implementation known as "Skank" which he rejected on the grounds of pure taste. abcl-src-1.9.0/etc/ant/build-maven.xml0100644 0000000 0000000 00000001615 14202767264 016235 0ustar000000000 0000000 abcl-src-1.9.0/etc/ant/build-snapshot.xml0100644 0000000 0000000 00000003641 14202767264 016767 0ustar000000000 0000000 abcl.version: ${abcl.version} abcl.version.hg: ${abcl.version.hg} abcl.src.version: ${abcl.src.version} abcl-src-1.9.0/etc/ant/netbeans-build.xml0100644 0000000 0000000 00000001217 14202767264 016724 0ustar000000000 0000000 abcl-src-1.9.0/examples/README0100644 0000000 0000000 00000001610 14202767264 014444 0ustar000000000 0000000 ABCL Examples ============= Contributions from: Ville Voutilainen, Alex Muscar, Blake McBride, and Mark Evenson google-app-engine This example shows how to run a ABCL in a Java Servlet context in general and in Google App Engine (GAE) in particular. gui Examples of how to interact with Swing/AWT GUI elements. java-exception Handling Java exceptions with the Lisp condition system. java-interface Implementing a Java interface with Lisp. java-to-lisp-1 Simple examples of calling Lisp from Java. java-to-lisp-2 More involved example of calling Lisp from Java including parameters and return values. jsr-223 Using the implementation of the JSR-223 interface to use Common Lisp as a pluggable scripting language on the JVM. lisp-to-java Calling Java code from Lisp. misc Code snippets currently without documentation. abcl-src-1.9.0/examples/google-app-engine/README0100644 0000000 0000000 00000002772 14202767264 017753 0ustar000000000 0000000 Google App Engine ================= Alex Muscar Running ABCL in a Google App Engine container. This example shows how to run your Java servlet off ABCL in general and in Google App Engine (GAE) in particular. When uploading your code to the server, be sure to put abcl.jar in war/WEB-INF/lib. Running Locally --------------- 1. Download the [Google App Engine SDK for Java][1], unzipping the distribution somewhere on your filesystem (e.g. "~/work/appengine-java-sdk-1.4.3"). [1]: http://googleappengine.googlecode.com/files/appengine-java-sdk-1.4.3.zip 2. Simply invoke Ant on the `build.xml' in this directory with the `runserver' target, setting the `sdk.dir' JVM property to specify the location of the SDK. unix$ ant -Dsdk.dir=$HOME/work/appengine-java-sdk-1.4.3/ runserver 3. Visit `http://localhost:8080/hello' in a web browser to see the example run. Deploying to GAE ---------------- 1. To deploy the included example to GAE, you need to first obtain a GAE account, and pick a GAE application id to use with the application. 2. Then you need to edit 'war/WEB-INF/appengine-web.xml' to specify this application. Just replace the contents of the tag (initially 'GAE-APPLICATION-ID-GOES-HERE') in the file with your GAE ID. 3. Then the Ant task 'update' should upload your application to GAE: unix$ ant update You will be prompted for the Google Account credentials associated with the application ID. abcl-src-1.9.0/examples/google-app-engine/build.xml0100644 0000000 0000000 00000006064 14202767264 020712 0ustar000000000 0000000 abcl-src-1.9.0/examples/google-app-engine/src/abcl_ae/AbclInit.java0100644 0000000 0000000 00000001163 14202767264 023551 0ustar000000000 0000000 package abcl_ae; import java.io.FileInputStream; import java.io.IOException; import org.armedbear.lisp.Lisp; import org.armedbear.lisp.Load; import org.armedbear.lisp.Interpreter; import org.armedbear.lisp.Symbol; import org.armedbear.lisp.Pathname; public final class AbclInit { static private Object lock = new Object(); static private boolean initialized = false; // package access level static void init() { if (initialized) return; synchronized (lock) { if (initialized) return; Interpreter.initializeLisp(); Load.load("fasls/first-servlet.abcl"); initialized = true; } } } abcl-src-1.9.0/examples/google-app-engine/src/abcl_ae/HelloWorldServlet.java0100644 0000000 0000000 00000002150 14202767264 025501 0ustar000000000 0000000 package abcl_ae; import java.io.IOException; import javax.servlet.http.*; import javax.servlet.*; import org.armedbear.lisp.Interpreter; import org.armedbear.lisp.LispThread; import org.armedbear.lisp.Lisp; import org.armedbear.lisp.Symbol; import org.armedbear.lisp.SpecialBinding; import org.armedbear.lisp.SpecialBindingsMark; import org.armedbear.lisp.Load; import org.armedbear.lisp.Stream; public class HelloWorldServlet extends HttpServlet { static private Symbol doGet = null; public void init() throws ServletException { AbclInit.init(); doGet = Lisp.internInPackage("DO-GET", "FIRST-SERVLET"); } public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { LispThread currentThread = LispThread.currentThread(); SpecialBindingsMark mark = currentThread.markSpecialBindings(); currentThread.bindSpecial( Symbol.STANDARD_OUTPUT, new Stream(Symbol.SYSTEM_STREAM, resp.getOutputStream(), Symbol.CHARACTER, false)); try { currentThread.execute(doGet); } finally { currentThread.resetSpecialBindings(mark); } } } abcl-src-1.9.0/examples/google-app-engine/src/first-servlet.lisp0100644 0000000 0000000 00000000217 14202767264 023354 0ustar000000000 0000000 (defpackage #:first-servlet (:use :cl) (:export #:do-get)) (in-package #:first-servlet) (defun do-get () (format t "Hello, World!~%")) abcl-src-1.9.0/examples/google-app-engine/war/WEB-INF/appengine-web.xml0100644 0000000 0000000 00000000314 14202767264 024144 0ustar000000000 0000000 GAE-APPLICATION-ID-GOES-HERE 1 abcl-src-1.9.0/examples/google-app-engine/war/WEB-INF/web.xml0100644 0000000 0000000 00000001060 14202767264 022177 0ustar000000000 0000000 hello abcl_ae.HelloWorldServlet hello /hello index.html abcl-src-1.9.0/examples/gui/README0100644 0000000 0000000 00000001127 14202767264 015233 0ustar000000000 0000000 Graphical User Interface ======================== abcl.DialogPromptStream swing.SwingDialogPromptStream awt.AwtDialogPromptStream Provides an example of a GUI abstraction that serves as a drop-in replacement for *DEBUG-IO*. The concrete classes SwingDialogPromptStream and AwtDialogPromptStream provide implemntations in Swing and AWT respectively. awt.ActionListener awt.ComponentAdapter awt.KeyAdaptor awt.MouseAdaptor awt.MotionMouseAdaptor awt.WindowAdaptor How to map standard AWT listeners and adaptors to Lisp by using the org.armedbear.lisp.JHandler callback mechanism. abcl-src-1.9.0/examples/gui/abcl/DialogPromptStream.java0100644 0000000 0000000 00000004357 14202767264 021704 0ustar000000000 0000000 package abcl; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import org.armedbear.lisp.Stream; /** * A bidirectional stream that captures input from a modal dialog. The * dialog reports a label (prompt line) which shows to the user * everything that has been printed to the stream up to the moment * when the dialog became visible. It is usable as a drop-in * replacement for e.g. *debug-io*.
This is an abstract class * that does not depend on any GUI library. Subclasses are expected to * provide the actual code to show the dialog and read input from the * user. * * @author Alessio Stalla * */ public abstract class DialogPromptStream extends Stream { StringWriter writtenSoFar = new StringWriter(); private Reader reader = new Reader() { private StringReader stringReader = null; private int inputSize = 0; public void close() throws IOException { closeDialog(); } public int read(char[] cbuf, int off, int len) throws IOException { if(stringReader == null) { writtenSoFar.flush(); String promptText = writtenSoFar.toString(); writtenSoFar.getBuffer().delete(0, Integer.MAX_VALUE); String inputStr = readInputFromModalDialog(promptText) + System.getProperty("line.separator", "\n"); stringReader = new StringReader(inputStr); inputSize = inputStr.length(); } int read = stringReader.read(cbuf, off, len); if(read != -1) { inputSize -= read; } if(read == -1 || inputSize == 0) { inputSize = 0; stringReader = null; } return read; } }; /** * Inits this stream. Should be called by subclasses' constructors. */ protected DialogPromptStream() { super(org.armedbear.lisp.Symbol.SYSTEM_STREAM); initAsCharacterOutputStream(writtenSoFar); initAsCharacterInputStream(reader); } /** * Closes the dialog when this stream is closed, aborting the read operation. */ protected abstract void closeDialog(); /** * Shows the dialog and blocks the calling thread until the user has closed the dialog. * @param promptText the text to be shown to the user (the prompt). * @return a string holding input from the user. */ protected abstract String readInputFromModalDialog(String promptText); } abcl-src-1.9.0/examples/gui/awt/ActionListener.java0100644 0000000 0000000 00000005471 14202767264 020742 0ustar000000000 0000000 /* * ActionListener.java * * Copyright (C) 2003 Peter Graves * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package awt; import org.armedbear.lisp.JHandler; import java.awt.event.ActionEvent; import java.awt.Button; import java.awt.List; import java.awt.MenuItem; import java.awt.TextField; import javax.swing.AbstractButton; import javax.swing.JTextField; public class ActionListener implements java.awt.event.ActionListener { public void actionPerformed(ActionEvent actionevent) { String as[] = { actionevent.paramString(), actionevent.getActionCommand() }; int ai[] = { actionevent.getModifiers() }; long al[] = { actionevent.getWhen() }; // not yet used JHandler.callLisp("ACTIONPERFORMED", handle, as, ai); } //AWT public static synchronized void addTo(Button button) { ActionListener actionlistener = new ActionListener(); actionlistener.handle = button; button.addActionListener(actionlistener); } public static synchronized void addTo(List list) { ActionListener actionlistener = new ActionListener(); actionlistener.handle = list; list.addActionListener(actionlistener); } public static synchronized void addTo(MenuItem menuitem) { ActionListener actionlistener = new ActionListener(); actionlistener.handle = menuitem; menuitem.addActionListener(actionlistener); } public static synchronized void addTo(TextField textfield) { ActionListener actionlistener = new ActionListener(); actionlistener.handle = textfield; textfield.addActionListener(actionlistener); } //Swing //takes care of JButton, JMenuItem, JToggleButton etc. public static synchronized void addTo(AbstractButton ab) { ActionListener actionlistener = new ActionListener(); actionlistener.handle = ab; ab.addActionListener(actionlistener); } public static synchronized void addTo(JTextField textfield) { ActionListener actionlistener = new ActionListener(); actionlistener.handle = textfield; textfield.addActionListener(actionlistener); } private Object handle; } abcl-src-1.9.0/examples/gui/awt/AwtDialogPromptStream.java0100644 0000000 0000000 00000002500 14202767264 022236 0ustar000000000 0000000 // $Id$ package awt; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Label; import java.awt.Panel; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import abcl.DialogPromptStream; import javax.swing.JButton; public class AwtDialogPromptStream extends DialogPromptStream { Dialog dialog = new Dialog((Frame)null, true); private Label prompt = new Label(); private TextField input = new TextField(32); public AwtDialogPromptStream() { this("Prompt"); } public AwtDialogPromptStream(String title) { super(); dialog.setTitle(title); Panel tmpPanel = new Panel(); tmpPanel.add(prompt); tmpPanel.add(input); dialog.add(tmpPanel); JButton okBtn = new JButton("Ok"); okBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { synchronized(dialog) { dialog.dispose(); } } }); tmpPanel = new Panel(new FlowLayout()); tmpPanel.add(okBtn); dialog.add(tmpPanel, BorderLayout.SOUTH); } @Override protected void closeDialog() { dialog.dispose(); } @Override protected String readInputFromModalDialog(String promptText) { prompt.setText(promptText); dialog.pack(); dialog.setVisible(true); return input.getText(); } } abcl-src-1.9.0/examples/gui/awt/ComponentAdapter.java0100644 0000000 0000000 00000003340 14202767264 021253 0ustar000000000 0000000 /* * ComponentAdapter.java * * Copyright (C) 2003 Peter Graves * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package awt; import org.armedbear.lisp.JHandler; import java.awt.Component; import java.awt.event.ComponentEvent; public class ComponentAdapter extends java.awt.event.ComponentAdapter { public static synchronized void addTo(Component component) { component.addComponentListener(new ComponentAdapter()); } private void call(String s, ComponentEvent componentevent) { JHandler.callLisp(s, componentevent.getComponent(), componentevent.paramString()); } public void componentHidden(ComponentEvent componentevent) { call("COMPONENTHIDDEN", componentevent); } public void componentMoved(ComponentEvent componentevent) { call("COMPONENTMOVED", componentevent); } public void componentResized(ComponentEvent componentevent) { call("COMPONENTRESIZED", componentevent); } public void componentShown(ComponentEvent componentevent) { call("COMPONENTSHOWN", componentevent); } } abcl-src-1.9.0/examples/gui/awt/ItemListener.java0100644 0000000 0000000 00000007061 14202767264 020420 0ustar000000000 0000000 /* * ItemListener.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package awt; import java.awt.Checkbox; import java.awt.CheckboxMenuItem; import java.awt.Choice; import java.awt.ItemSelectable; import java.awt.List; import java.awt.event.ItemEvent; import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.DefaultButtonModel; import javax.swing.JComboBox; import org.armedbear.lisp.JHandler; public class ItemListener implements java.awt.event.ItemListener { public void itemStateChanged(ItemEvent itemevent) { String as[] = { itemevent.paramString(), itemevent.getItem().toString() }; int ai[] = { itemevent.getStateChange() != ItemEvent.SELECTED ? 0 : 1 }; JHandler.callLisp("ITEMSTATECHANGED", handle, as, ai); } public static synchronized void addTo(Checkbox checkbox) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = checkbox; checkbox.addItemListener(itemlistener); } public static synchronized void addTo(CheckboxMenuItem checkboxmenuitem) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = checkboxmenuitem; checkboxmenuitem.addItemListener(itemlistener); } public static synchronized void addTo(Choice choice) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = choice; choice.addItemListener(itemlistener); } public static synchronized void addTo(ItemSelectable itemselectable) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = itemselectable; itemselectable.addItemListener(itemlistener); } public static synchronized void addTo(List list) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = list; list.addItemListener(itemlistener); } //Swing public static synchronized void addTo(AbstractButton abstractbutton) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = abstractbutton; abstractbutton.addItemListener(itemlistener); } public static synchronized void addTo(ButtonModel buttonmodel) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = buttonmodel; buttonmodel.addItemListener(itemlistener); } public static synchronized void addTo(DefaultButtonModel defaultbuttonmodel) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = defaultbuttonmodel; defaultbuttonmodel.addItemListener(itemlistener); } public static synchronized void addTo(JComboBox jcombobox) { ItemListener itemlistener = new ItemListener(); itemlistener.handle = jcombobox; jcombobox.addItemListener(itemlistener); } private Object handle; } abcl-src-1.9.0/examples/gui/awt/KeyAdapter.java0100644 0000000 0000000 00000003142 14202767264 020041 0ustar000000000 0000000 /* * KeyAdapter.java * * Copyright (C) 2003 Peter Graves * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package awt; import org.armedbear.lisp.JHandler; import java.awt.Component; import java.awt.event.KeyEvent; public class KeyAdapter extends java.awt.event.KeyAdapter { public static synchronized void addTo(Component component) { component.addKeyListener(new KeyAdapter()); } private void call(String s, KeyEvent keyevent) { int ai[] = { keyevent.getModifiers(), keyevent.isActionKey() ? 1 : 0, keyevent.getKeyCode() }; JHandler.callLisp(s, keyevent.getComponent(), keyevent.paramString(), ai); } public void keyPressed(KeyEvent keyevent) { call("KEYPRESSED", keyevent); } public void keyReleased(KeyEvent keyevent) { call("KEYRELEASED", keyevent); } public void keyTyped(KeyEvent keyevent) { call("KEYTYPED", keyevent); } } abcl-src-1.9.0/examples/gui/awt/MouseAdapter.java0100644 0000000 0000000 00000003642 14202767264 020406 0ustar000000000 0000000 /* * MouseAdapter.java * * Copyright (C) 2003 Peter Graves * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package awt; import org.armedbear.lisp.JHandler; import java.awt.Component; import java.awt.event.MouseEvent; public class MouseAdapter extends java.awt.event.MouseAdapter { public static synchronized void addTo(Component component) { component.addMouseListener(new MouseAdapter()); } private void call(String s, MouseEvent mouseevent) { int ai[] = { mouseevent.getModifiers(), mouseevent.isPopupTrigger() ? 1 : 0, mouseevent.getClickCount(), mouseevent.getX(), mouseevent.getY() }; JHandler.callLisp(s, mouseevent.getComponent(), mouseevent.paramString(), ai); } public void mouseClicked(MouseEvent mouseevent) { call("MOUSECLICKED", mouseevent); } public void mousePressed(MouseEvent mouseevent) { call("MOUSEPRESSED", mouseevent); } public void mouseReleased(MouseEvent mouseevent) { call("MOUSERELEASED", mouseevent); } public void mouseEntered(MouseEvent mouseevent) { call("MOUSEENTERED", mouseevent); } public void mouseExited(MouseEvent mouseevent) { call("MOUSEEXITED", mouseevent); } } abcl-src-1.9.0/examples/gui/awt/MouseMotionAdapter.java0100644 0000000 0000000 00000003352 14202767264 021572 0ustar000000000 0000000 /* * MouseMotionAdapter.java * * Copyright (C) 2003 Peter Graves * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package awt; import org.armedbear.lisp.JHandler; import java.awt.Component; import java.awt.event.MouseEvent; public class MouseMotionAdapter extends java.awt.event.MouseMotionAdapter { public static synchronized void addTo(Component component) { component.addMouseMotionListener(new MouseMotionAdapter()); } private void call(String s, MouseEvent mouseevent) { int ai[] = { mouseevent.getModifiers(), mouseevent.isPopupTrigger() ? 1 : 0, mouseevent.getClickCount(), mouseevent.getX(), mouseevent.getY() }; JHandler.callLisp(s, mouseevent.getComponent(), mouseevent.paramString(), ai); } public void mouseDragged(MouseEvent mouseevent) { call("MOUSEDRAGGED", mouseevent); } public void mouseMoved(MouseEvent mouseevent) { call("MOUSEMOVED", mouseevent); } public void mouseWheel(MouseEvent mouseevent) { call("MOUSEWHEEL", mouseevent); } } abcl-src-1.9.0/examples/gui/awt/WindowAdapter.java0100644 0000000 0000000 00000004242 14202767264 020562 0ustar000000000 0000000 /* * WindowAdapter.java * * Copyright (C) 2003 Peter Graves * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package awt; import org.armedbear.lisp.JHandler; import java.awt.Window; import java.awt.event.WindowEvent; public class WindowAdapter extends java.awt.event.WindowAdapter { private void call(String s, WindowEvent windowevent) { JHandler.callLisp(s, windowevent.getWindow()); } public static synchronized void addTo(Window window) { window.addWindowListener(new WindowAdapter()); } public void windowOpened(WindowEvent windowevent) { call("WINDOWOPENED", windowevent); } public void windowClosed(WindowEvent windowevent) { call("WINDOWCLOSED", windowevent); } public void windowClosing(WindowEvent windowevent) { call("WINDOWCLOSING", windowevent); } public void windowActivated(WindowEvent windowevent) { call("WINDOWACTIVATED", windowevent); } public void windowDeactivated(WindowEvent windowevent) { call("WINDOWDEACTIVATED", windowevent); } public void windowIconified(WindowEvent windowevent) { call("WINDOWICONIFIED", windowevent); } public void windowDeiconified(WindowEvent windowevent) { call("WINDOWDEICONIFIED", windowevent); } public void windowGainedFocus(WindowEvent windowevent) { call("WINDOWGAINEDFOCUS", windowevent); } public void windowLostFocus(WindowEvent windowevent) { call("WINDOWLOSTFOCUS", windowevent); } } abcl-src-1.9.0/examples/gui/build.xml0100644 0000000 0000000 00000000663 14202767264 016200 0ustar000000000 0000000 abcl-src-1.9.0/examples/gui/swing/SwingDialogPromptStream.java0100644 0000000 0000000 00000002530 14202767264 023131 0ustar000000000 0000000 package swing; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import abcl.DialogPromptStream; public class SwingDialogPromptStream extends DialogPromptStream { JDialog dialog = new JDialog((Frame)null, true); private JLabel prompt = new JLabel(); private JTextField input = new JTextField(32); public SwingDialogPromptStream() { this("Prompt"); } public SwingDialogPromptStream(String title) { super(); dialog.setTitle(title); JPanel tmpPanel = new JPanel(); tmpPanel.add(prompt); tmpPanel.add(input); dialog.add(tmpPanel); JButton okBtn = new JButton("Ok"); okBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { synchronized(dialog) { dialog.dispose(); } } }); tmpPanel = new JPanel(new FlowLayout()); tmpPanel.add(okBtn); dialog.add(tmpPanel, BorderLayout.SOUTH); } @Override protected void closeDialog() { dialog.dispose(); } @Override protected String readInputFromModalDialog(String promptText) { prompt.setText(promptText); dialog.pack(); dialog.setVisible(true); return input.getText(); } } abcl-src-1.9.0/examples/java-exception/Main.java0100644 0000000 0000000 00000004102 14202767264 020227 0ustar000000000 0000000 /* * Main.java * * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import org.armedbear.lisp.*; public class Main { /** * This example creates an Interpreter instance, loads our * lisp code from a file and then looks up a function defined * in the loaded lisp file and executes the function. * * The function takes a single parameter and invokes a java method * on the object provided. We provide our Main object as the parameter. * */ public static void main(String[] argv) { try { Main thisObject = new Main(); Interpreter interpreter = Interpreter.createInstance(); interpreter.eval("(load \"lispfunctions.lisp\")"); // the function is not in a separate package, thus the // correct package is CL-USER. Symbol names are // upper case. Package needs the prefix, because java // also has a class named Package. org.armedbear.lisp.Package defaultPackage = Packages.findPackage("CL-USER"); Symbol voidsym = defaultPackage.findAccessibleSymbol("VOID-FUNCTION"); Function voidFunction = (Function) voidsym.getSymbolFunction(); voidFunction.execute(new JavaObject(thisObject)); } catch (Throwable t) { System.out.println("exception!"); t.printStackTrace(); } } public int addTwoNumbers(int a, int b) { throw new RuntimeException("Exception from java code"); } } abcl-src-1.9.0/examples/java-exception/README0100644 0000000 0000000 00000001642 14202767264 017366 0ustar000000000 0000000 ABCL Examples Building and Running Instructions =============================================== To compile cmd$ javac -cp ../../dist/abcl.jar Main.java where the "../../../dist/abcl.jar" represents the path to your abcl.jar file, which is built via the Ant based build. This path could be slightly different depending on how the system was constructed, and possibly due to operating system conventions for specifying relative paths. However you resolve this locally, we'll refer to this as '$ABCL_ROOT/dist/abcl.jar' for the rest of these instructions. This compiles the Java source file "Main.java" into a JVM runtime or class file named "Main.class". To run the example (Main.class for example) from a Unix-like OS use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar:. Main or in Windows use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar;. Main where "Main" is the initial class to run in your Java program. abcl-src-1.9.0/examples/java-exception/lispfunctions.lisp0100644 0000000 0000000 00000002701 14202767264 022274 0ustar000000000 0000000 ;;; lispfunctions.lisp ;;; ;;; Copyright (C) 2008 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; we need to get the ; 1) class (Main) ; 2) classes of the parameters (int) ; 3) method reference (getting that requires the class ; of our object and the classes of the parameters ; After that we can invoke the function with jcall, ; giving the method reference, the object and the parameters. ; The function throws an exception, so we wrap the call in ; handler-case. (defun void-function (param) (let* ((class (jclass "Main")) (intclass (jclass "int")) (method (jmethod class "addTwoNumbers" intclass intclass))) (handler-case (jcall method param 2 4) (java-exception (exception) (format t "Caught a java exception in void-function~%"))))) abcl-src-1.9.0/examples/java-interface/BankAccount.java0100644 0000000 0000000 00000000203 14202767264 021473 0ustar000000000 0000000 public interface BankAccount { public int getBalance(); public void deposit(int amount); public void withdraw(int amount); } abcl-src-1.9.0/examples/java-interface/BankExampleMain.java0100644 0000000 0000000 00000001605 14202767264 022306 0ustar000000000 0000000 import org.armedbear.lisp.Interpreter; import org.armedbear.lisp.Symbol; import org.armedbear.lisp.Packages; import org.armedbear.lisp.JavaObject; import org.armedbear.lisp.LispObject; public class BankExampleMain { static public void main(String argv[]) { Interpreter interpreter = Interpreter.createInstance(); interpreter.eval("(load \"bank-account.lisp\")"); org.armedbear.lisp.Package defaultPackage = Packages.findPackage("CL-USER"); Symbol bankAccountImplSymbol = defaultPackage.findAccessibleSymbol("*BANK-ACCOUNT-IMPL*"); LispObject value = bankAccountImplSymbol.symbolValue(); Object object = ((JavaObject) value).getObject(); BankAccount account = (BankAccount) object; System.out.println("Initial balance: " + account.getBalance()); account.withdraw(500); System.out.println("After withdrawing 500: " + account.getBalance()); } } abcl-src-1.9.0/examples/java-interface/Main.java0100644 0000000 0000000 00000004543 14202767264 020202 0ustar000000000 0000000 /* * Main.java * * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import org.armedbear.lisp.*; public class Main { /** * This example loads a lisp file and gets two function symbols * from it. The functions return implementations of MyInterface. * The example gets two separate implementations and invokes * the functions in the interface for both implementations. */ public static void main(String[] argv) { try { Interpreter interpreter = Interpreter.createInstance(); interpreter.eval("(load \"interface_implementation.lisp\")"); // the function is not in a separate package, thus the // correct package is CL-USER. Symbol names are // upper case. Package needs the prefix, because java // also has a class named Package. org.armedbear.lisp.Package defaultPackage = Packages.findPackage("CL-USER"); Symbol interfacesym = defaultPackage.findAccessibleSymbol("GET-INTERFACE"); Function interfaceFunction = (Function) interfacesym.getSymbolFunction(); LispObject myinterface = interfaceFunction.execute(); MyInterface x = (MyInterface) JavaObject.getObject(myinterface); x.firstFunction(); x.secondFunction(); Symbol interfacesym2 = defaultPackage. findAccessibleSymbol("GET-ANOTHER-INTERFACE"); Function interfaceFunction2 = (Function) interfacesym2.getSymbolFunction(); LispObject myInterface2 = interfaceFunction2.execute(); MyInterface y = (MyInterface) JavaObject.getObject(myInterface2); y.firstFunction(); y.secondFunction(); } catch (Throwable t) { System.out.println("exception!"); t.printStackTrace(); } } } abcl-src-1.9.0/examples/java-interface/MyInterface.java0100644 0000000 0000000 00000001661 14202767264 021522 0ustar000000000 0000000 /* * MyInterface.java * * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * Example interface, with two methods. */ public interface MyInterface { public void firstFunction(); public void secondFunction(); } abcl-src-1.9.0/examples/java-interface/README0100644 0000000 0000000 00000001670 14202767264 017331 0ustar000000000 0000000 ABCL Examples Building and Running Instructions =============================================== To compile cmd$ javac -cp ../../dist/abcl.jar Main.java BankAccountMain.java where the "../../../dist/abcl.jar" represents the path to your abcl.jar file, which is built via the Ant based build. This path could be slightly different depending on how the system was constructed, and possibly due to operating system conventions for specifying relative paths. However you resolve this locally, we'll refer to this as '$ABCL_ROOT/dist/abcl.jar' for the rest of these instructions. This compiles the Java source file "Main.java" into a JVM runtime or class file named "Main.class". To run the example (Main.class for example) from a Unix-like OS use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar:. Main or in Windows use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar;. Main where "Main" is the initial class to run in your Java program. abcl-src-1.9.0/examples/java-interface/bank-account.lisp0100644 0000000 0000000 00000000775 14202767264 021714 0ustar000000000 0000000 (defparameter *bank-account-impl* (let ((balance 1000)) (jinterface-implementation "BankAccount" "getBalance" (lambda () balance) "deposit" (lambda (amount) (let ((amount (jobject-lisp-value amount))) (setf balance (+ balance amount)))) "withdraw" (lambda (amount) (let ((amount (jobject-lisp-value amount))) (setf balance (- balance amount))))))) (defun get-bank-account-impl () *bank-account-impl*) abcl-src-1.9.0/examples/java-interface/build.xml0100644 0000000 0000000 00000000562 14202767264 020271 0ustar000000000 0000000 abcl-src-1.9.0/examples/java-interface/interface_implementation.lisp0100644 0000000 0000000 00000005254 14202767264 024411 0ustar000000000 0000000 ;;; interface_implementation.lisp ;;; ;;; Copyright (C) 2008 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; first we define a class hierarchy. No slots defined, ; we don't need them in the example. (defclass base ()) (defclass derived1 (base)) (defclass derived2 (base)) ; then a couple of generic methods (defgeneric invoke (param) (:documentation "Sample generic function")) (defgeneric invoke2 (param) (:documentation "Sample generic function")) ; and their methods, for different classes (defmethod invoke ((param derived1)) (format t "in derived1 invoke~%")) (defmethod invoke ((param derived2)) (format t "in derived2 invoke~%")) (defmethod invoke2 ((param derived1)) (format t "in derived1 invoke2~%")) (defmethod invoke2 ((param derived2)) (format t "in derived2 invoke2~%")) ; closure for interface implementation, closes ; over a provided object and calls the invoke ; method with the object. Thus the firstFunction() ; in MyInterface will call the invoke method. (defun make-first-function (object) (lambda () (invoke object))) ; closure for interface implementation, closes ; over a provided object and invokes the invoke2 ; method with the object. Thus the secondFunction() ; in MyInterface will call the invoke2 method. (defun make-second-function (object) (lambda () (invoke2 object))) ; gets an interface implementation, uses an instance of ; class derived1 (defun get-interface () (let ((firstobject (make-instance 'derived1))) (jinterface-implementation "MyInterface" "firstFunction" (make-first-function firstobject) "secondFunction" (make-second-function firstobject)))) ; gets an interface implementation, uses an instance of ; class derived2 (defun get-another-interface () (let ((secondobject (make-instance 'derived2))) (jinterface-implementation "MyInterface" "firstFunction" (make-first-function secondobject) "secondFunction" (make-second-function secondobject)))) abcl-src-1.9.0/examples/java-to-lisp-1/Main.java0100644 0000000 0000000 00000002522 14202767264 017762 0ustar000000000 0000000 /* * Main.java * * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import org.armedbear.lisp.*; public class Main { /** * This example creates an Interpreter instance, loads our * lisp code from a file and then evaluates a function defined * in the loaded lisp file. */ public static void main(String[] argv) { try { Interpreter interpreter = Interpreter.createInstance(); interpreter.eval("(load \"lispfunction.lisp\")"); LispObject myInterface = interpreter.eval("(lispfunction)"); } catch (Throwable t) { System.out.println("exception!"); t.printStackTrace(); } } } abcl-src-1.9.0/examples/java-to-lisp-1/MainAlternative.java0100644 0000000 0000000 00000003525 14202767264 022165 0ustar000000000 0000000 /* * MainAlternative.java * * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import org.armedbear.lisp.Function; import org.armedbear.lisp.Interpreter; import org.armedbear.lisp.Package; import org.armedbear.lisp.Packages; import org.armedbear.lisp.Symbol; public class MainAlternative { /** * This example creates an Interpreter instance, loads our * lisp code from a file and then looks up a function defined * in the loaded lisp file and executes the function. */ public static void main(String[] argv) { try { Interpreter interpreter = Interpreter.createInstance(); interpreter.eval("(load \"lispfunction.lisp\")"); // the function is not in a separate package, thus the // correct package is CL-USER. Symbol names are // (usually) upper case. Package defaultPackage = Packages.findPackage("CL-USER"); Symbol sym = defaultPackage.findAccessibleSymbol("LISPFUNCTION"); Function function = (Function) sym.getSymbolFunction(); function.execute(); } catch (Throwable t) { System.out.println("exception!"); t.printStackTrace(); } } } abcl-src-1.9.0/examples/java-to-lisp-1/README0100644 0000000 0000000 00000001642 14202767264 017115 0ustar000000000 0000000 ABCL Examples Building and Running Instructions =============================================== To compile cmd$ javac -cp ../../dist/abcl.jar Main.java where the "../../../dist/abcl.jar" represents the path to your abcl.jar file, which is built via the Ant based build. This path could be slightly different depending on how the system was constructed, and possibly due to operating system conventions for specifying relative paths. However you resolve this locally, we'll refer to this as '$ABCL_ROOT/dist/abcl.jar' for the rest of these instructions. This compiles the Java source file "Main.java" into a JVM runtime or class file named "Main.class". To run the example (Main.class for example) from a Unix-like OS use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar:. Main or in Windows use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar;. Main where "Main" is the initial class to run in your Java program. abcl-src-1.9.0/examples/java-to-lisp-1/lispfunction.lisp0100644 0000000 0000000 00000001542 14202767264 021642 0ustar000000000 0000000 ;;; lispfunction.lisp ;;; ;;; Copyright (C) 2008 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (defun lispfunction () (format t "in lispfunction~%")) abcl-src-1.9.0/examples/java-to-lisp-2/Main.java0100644 0000000 0000000 00000004742 14202767264 017771 0ustar000000000 0000000 /* * Main.java * * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import org.armedbear.lisp.*; public class Main { /** * This example creates an Interpreter instance, loads our * lisp code from a file and then looks up two functions defined * in the loaded lisp file and executes the functions. * * The first function takes a single parameter and prints its value, * so we can provide any Object, so we use a String. * * The second function takes two numbers, adds them together, prints * the parameters and the result, and returns the result. * We use two integers as parameters and just print the result * from java side. */ public static void main(String[] argv) { try { Interpreter interpreter = Interpreter.createInstance(); interpreter.eval("(load \"lispfunctions.lisp\")"); // the function is not in a separate package, thus the // correct package is CL-USER. Symbol names are // upper case. Package needs the prefix, because java // also has a class named Package. org.armedbear.lisp.Package defaultPackage = Packages.findPackage("CL-USER"); Symbol voidsym = defaultPackage.findAccessibleSymbol("VOID-FUNCTION"); Function voidFunction = (Function) voidsym.getSymbolFunction(); voidFunction.execute(new JavaObject("String given from java")); Symbol intsym = defaultPackage.findAccessibleSymbol("INT-FUNCTION"); Function intFunction = (Function) intsym.getSymbolFunction(); LispObject result = intFunction.execute(new JavaObject(1), new JavaObject(6)); System.out.print("The result on the java side: "); System.out.println(result.intValue()); } catch (Throwable t) { System.out.println("exception!"); t.printStackTrace(); } } } abcl-src-1.9.0/examples/java-to-lisp-2/README0100644 0000000 0000000 00000001642 14202767264 017116 0ustar000000000 0000000 ABCL Examples Building and Running Instructions =============================================== To compile cmd$ javac -cp ../../dist/abcl.jar Main.java where the "../../../dist/abcl.jar" represents the path to your abcl.jar file, which is built via the Ant based build. This path could be slightly different depending on how the system was constructed, and possibly due to operating system conventions for specifying relative paths. However you resolve this locally, we'll refer to this as '$ABCL_ROOT/dist/abcl.jar' for the rest of these instructions. This compiles the Java source file "Main.java" into a JVM runtime or class file named "Main.class". To run the example (Main.class for example) from a Unix-like OS use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar:. Main or in Windows use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar;. Main where "Main" is the initial class to run in your Java program. abcl-src-1.9.0/examples/java-to-lisp-2/lispfunctions.lisp0100644 0000000 0000000 00000002477 14202767264 022036 0ustar000000000 0000000 ;;; lispfunctions.lisp ;;; ;;; Copyright (C) 2008 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; param comes from java, so accessing it require ; calling jobject-lisp-value on it (defun void-function (param) (format t "in void-function, param: ~a~%" (jobject-lisp-value param))) ; params come from java, so accessing them require ; calling jobject-lisp-value on them (defun int-function (jparam1 jparam2) (let* ((param1 (jobject-lisp-value jparam1)) (param2 (jobject-lisp-value jparam2)) (result (+ param1 param2))) (format t "in int-function, params: ~a ~a~%result: ~a~%" param1 param2 result) result)) abcl-src-1.9.0/examples/jsr-223/JSR223Example.java0100644 0000000 0000000 00000004764 14202767264 017747 0ustar000000000 0000000 import javax.script.*; public class JSR223Example { public static void main(String[] args) { //Script Engine instantiation using ServiceProvider - this will //look in the classpath for a file // /META-INF/services/javax.script.ScriptEngineFactory //where the AbclScriptEngineFactory is registered ScriptEngine lispEngine = new ScriptEngineManager().getEngineByExtension("lisp"); //Alternatively, you can directly instantiate the script engine: //ScriptEngineManager scriptManager = new ScriptEngineManager(); //scriptManager.registerEngineExtension("lisp", new AbclScriptEngineFactory()); //ScriptEngine lispEngine = scriptManager.getEngineByExtension("lisp"); //(thanks to Peter Tsenter for suggesting this) //Accessing variables System.out.println(); System.out.println("*package* = " + lispEngine.get("*package*")); Object someValue = new Object(); lispEngine.put("someVariable", someValue); System.out.println("someVariable = " + lispEngine.get("someVariable")); try { //Interpretation (also from streams) lispEngine.eval("(defun hello (arg) (print (list arg someVariable)) (terpri))"); //Direct function invocation ((Invocable) lispEngine).invokeFunction("hello", "world"); //Implementing a Java interface in Lisp lispEngine.eval("(defun compare-to (&rest args) 42)"); Comparable c = ((Invocable) lispEngine).getInterface(java.lang.Comparable.class); System.out.println("compareTo: " + c.compareTo(null)); //Compilation! lispEngine.eval("(defmacro slow-compiling-macro (arg) (dotimes (i 1000000) (incf i)) `(print ,arg))"); long millis = System.currentTimeMillis(); lispEngine.eval("(slow-compiling-macro 42)"); millis = System.currentTimeMillis() - millis; System.out.println("interpretation took " + millis); millis = System.currentTimeMillis(); CompiledScript cs = ((Compilable) lispEngine).compile("(slow-compiling-macro 42)"); millis = System.currentTimeMillis() - millis; System.out.println("compilation took " + millis); millis = System.currentTimeMillis(); cs.eval(); millis = System.currentTimeMillis() - millis; System.out.println("evaluation took " + millis); millis = System.currentTimeMillis(); cs.eval(); millis = System.currentTimeMillis() - millis; System.out.println("evaluation took " + millis); //Ecc. ecc. } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (ScriptException e) { e.printStackTrace(); } } } abcl-src-1.9.0/examples/jsr-223/README0100644 0000000 0000000 00000001660 14202767264 015553 0ustar000000000 0000000 ABCL Examples Building and Running Instructions =============================================== To compile: cmd$ javac -cp ../../dist/abcl.jar JSR223Example.java where the "../../dist/abcl.jar" represents the path to your abcl.jar file, which is built via the Ant based build. This path could be slightly different depending on how the system was constructed, and possibly due to operating system conventions for specifying relative paths. However you resolve this locally, we'll refer to this as '$ABCL_ROOT/dist/abcl.jar' for the rest of these instructions. This compiles the Java source file "Main.java" into a JVM runtime or class file named "Main.class". To run the example (Main.class for example) from a Unix-like OS use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar:. JSR223Example or in Windows use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar;. JSR223Example where "Main" is the initial class to run in your Java program. abcl-src-1.9.0/examples/lisp-to-java/Main.java0100644 0000000 0000000 00000004030 14202767264 017620 0ustar000000000 0000000 /* * Main.java * * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import org.armedbear.lisp.*; public class Main { /** * This example creates an Interpreter instance, loads our * lisp code from a file and then looks up a function defined * in the loaded lisp file and executes the function. * * The function takes a single parameter and invokes a java method * on the object provided. We provide our Main object as the parameter. * */ public static void main(String[] argv) { try { Main thisObject = new Main(); Interpreter interpreter = Interpreter.createInstance(); interpreter.eval("(load \"lispfunctions.lisp\")"); // the function is not in a separate package, thus the // correct package is CL-USER. Symbol names are // upper case. Package needs the prefix, because java // also has a class named Package. org.armedbear.lisp.Package defaultPackage = Packages.findPackage("CL-USER"); Symbol voidsym = defaultPackage.findAccessibleSymbol("VOID-FUNCTION"); Function voidFunction = (Function) voidsym.getSymbolFunction(); voidFunction.execute(new JavaObject(thisObject)); } catch (Throwable t) { System.out.println("exception!"); t.printStackTrace(); } } public int addTwoNumbers(int a, int b) { return a + b; } } abcl-src-1.9.0/examples/lisp-to-java/README0100644 0000000 0000000 00000001642 14202767264 016757 0ustar000000000 0000000 ABCL Examples Building and Running Instructions =============================================== To compile cmd$ javac -cp ../../dist/abcl.jar Main.java where the "../../../dist/abcl.jar" represents the path to your abcl.jar file, which is built via the Ant based build. This path could be slightly different depending on how the system was constructed, and possibly due to operating system conventions for specifying relative paths. However you resolve this locally, we'll refer to this as '$ABCL_ROOT/dist/abcl.jar' for the rest of these instructions. This compiles the Java source file "Main.java" into a JVM runtime or class file named "Main.class". To run the example (Main.class for example) from a Unix-like OS use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar:. Main or in Windows use: cmd$ java -cp $ABCL_ROOT/dist/abcl.jar;. Main where "Main" is the initial class to run in your Java program. abcl-src-1.9.0/examples/lisp-to-java/lispfunctions.lisp0100644 0000000 0000000 00000002733 14202767264 021672 0ustar000000000 0000000 ;;; lispfunctions.lisp ;;; ;;; Copyright (C) 2008 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; we need to get the ; 1) class (Main) ; 2) classes of the parameters (int) ; 3) method reference (getting that requires the class ; of our object and the classes of the parameters ; After that we can invoke the function with jcall, ; giving the method reference, the object and the parameters. ; The result is a lisp object (no need to do jobject-lisp-value), ; unless we invoke the method ; with jcall-raw. (defun void-function (param) (let* ((class (jclass "Main")) (intclass (jclass "int")) (method (jmethod class "addTwoNumbers" intclass intclass)) (result (jcall method param 2 4))) (format t "in void-function, result of calling addTwoNumbers(2, 4): ~a~%" result))) abcl-src-1.9.0/examples/misc/dotabclrc0100644 0000000 0000000 00000010063 14202767264 016401 0ustar000000000 0000000 ;;; -*- Mode: Lisp -*- ;;; Possible code for inclusion in the Armed Bear startup file ;;; #p"~/.abclrc" ;;; Some commonly useful customizations to ABCL output (setf ;; Truncate the output of java.lang.String object after this many ;; characters, outputing "...." afterwards. ;; The default is 32. Is this too small? *java-object-to-string-length* 8192 ;; Show what is being loaded and the loading time. ;; Helpful on slower systems to figure out what is taking the time. *load-verbose* t ;; Emit warnings from debug code sys:*debug-warn* t ;; Bring some order to the forms output by the REPL ;; Not currently the default, but it probably should be after we ;; rework the pretty printer and/or streams to properly work with ;; GRAY-STREAMS: *print-pretty* t) #-quicklisp (let ((quicklisp-local #P"~/quicklisp/setup.lisp") (quicklisp-remote #p"http://beta.quicklisp.org/quicklisp.lisp")) (unless (probe-file quicklisp-local) (when (probe-file quicklisp-remote) ;;; XXX possibly search for a proxy÷ (load quicklisp-remote) (funcall (intern (symbol-name 'install) :quicklisp-quickstart)))) (when (probe-file quicklisp-local) (load quicklisp-local))) ;; (require :asdf) (require :abcl-contrib) (require :abcl-asdf) (setf abcl-asdf::*maven-http-proxy* "http://localhost:3128/") ;;; Customize the procedure used by CL:DISASSEMBLE (setf *disassembler* (let ((strategies (list (lambda (p) (let ((class (make-pathname :name (pathname-name p))) (path (directory-namestring p))) (format nil "javap -c -l -verbose -classpath ~A ~A" path class))) "/Users/evenson/bin/jad -a -p" (lambda (p) (format nil "java -jar ~ /Users/evenson/work/classfileanalyzer/classfileanalyzer.jar ~A" p))))) (first strategies))) (defparameter *ansi-tests-directory* #-(or windows mswindows win32) #p"/home/peter/xcl/x/ansi-tests/" #+(or windows mswindows win32) #p"c:\\msys\\1.0\\home\\peter\\xcl\\x\ansi-tests\\") (defun run-ansi-tests (&optional (compile-tests t)) (format t "COMPILE-TESTS is ~A~%" compile-tests) (let ((*default-pathname-defaults* *ansi-tests-directory*)) #+(and abcl unix) (run-shell-command "make clean" :directory *default-pathname-defaults*) (time (load (if compile-tests "compileit.lsp" "doit.lsp"))))) (defun run-random-tests (size nvars count) (let ((*default-pathname-defaults* *ansi-tests-directory*)) (load "gclload1.lsp") (load "random-int-form.lsp") (let ((f (find-symbol "TEST-RANDOM-INTEGER-FORMS" "CL-TEST"))) (when f (let (#+abcl (*suppress-compiler-warnings* t) (*random-state* (make-random-state t))) (time (funcall f size nvars count))))))) #+(or abcl sbcl clisp) (defun test-cl-ppcre () #+abcl (require "JVM") (let ((*default-pathname-defaults* #-(or windows mswindows win32) #p"/home/peter/cl-ppcre-1.2.19/" #+(or windows mswindows win32) #p"c:\\cygwin\\home\\peter\\cl-ppcre-1.2.19\\")) #+abcl (map nil #'delete-file (directory "*.abcl")) #+sbcl (map nil #'delete-file (directory "*.fasl")) (load "load.lisp") (let ((f (find-symbol "TEST" "CL-PPCRE-TEST"))) (when f #+abcl (gc) (time (funcall f)) #+abcl (gc) (time (funcall f)))))) #+abcl (defun run-other-tests () (test-cl-ppcre) (let ((*default-pathname-defaults* "/home/peter/salza-0.7.2/")) (map nil #'delete-file (directory "*.abcl")) (load "/home/peter/test-salza.lisp") (gc) (test-salza) (gc) (test-salza))) #+abcl (autoload 'do-tests "rt.lisp") #+allegro (top-level:alias "ap" (arg) (apropos arg nil nil t)) #+allegro (top-level:alias "de" (arg) (describe (eval arg))) #+cmu (setf *gc-verbose* nil) ;; #+sbcl ;; (require '#:asdf) ;; #+sbcl ;; (require '#:sb-aclrepl) abcl-src-1.9.0/examples/misc/dynamic-interfaces.lisp0100644 0000000 0000000 00000013205 14202767264 021160 0ustar000000000 0000000 (in-package :cl-user) ;;;; Copyright (C) 2010 by Mark Evenson #| A tour of the ABCL Java FFI by defining a Java interface at return, creating a Java proxy implementation that provides a Lisp implementation, and then use of the Java Reflection API to actually invoke the Lisp implementation. This needs abcl-0.24.0-dev or later. |# (defun define-java-interface (name package methods &optional (superinterfaces nil)) "Define a class for a Java interface called NAME in PACKAGE with METHODS. METHODS is a list of (NAME RETURN-TYPE (ARG-TYPES)) entries. NAME is a string. The values of RETURN-TYPE and the list of ARG-TYPES for the defined method follow the are either references to Java objects as created by JVM::MAKE-JVM-CLASS-NAME, or keywords representing Java primtive types as contained in JVM::MAP-PRIMITIVE-TYPE. SUPERINTERFACES optionally contains a list of interfaces that this interface extends specified as fully qualifed dotted Java names." (let* ((class-name-string (format nil "~A/~A" package name)) (class-name (jvm::make-jvm-class-name class-name-string)) (class (jvm::make-class-interface-file class-name))) (dolist (superinterface superinterfaces) (jvm::class-add-superinterface class (if (type-of superinterface 'jvm::jvm-class-name) superinterface (jvm::make-jvm-class-name superinterface)))) (dolist (method methods) (let ((name (first method)) (returns (second method)) (args (third method))) (jvm::class-add-method class (jvm::make-jvm-method name returns args :flags '(:public :abstract))))) (jvm::finalize-class-file class) (let ((s (sys::%make-byte-array-output-stream))) (jvm::write-class-file class s) (sys::%get-output-stream-bytes s)))) (defun load-class (class-bytes) "Load the Java byte[] array CLASS-BYTES as a Java class." (let ((load-class-method (jmethod "org.armedbear.lisp.JavaClassLoader" "loadClassFromByteArray" "[B"))) (jcall load-class-method java::*classloader* class-bytes))) ;;; Unused in the interface example, but useful to get at the class ;;; definition with javap or jad (defun write-class (class-bytes pathname) "Write the Java byte[] array CLASS-BYTES to PATHNAME." (with-open-file (stream pathname :direction :output :element-type '(signed-byte 8)) (dotimes (i (jarray-length class-bytes)) (write-byte (jarray-ref class-bytes i) stream)))) ;;;; The example begins here. We store all the intermediate values as ;;;; parameters so they may be inspected by those that follow this example. ;;; Construct a Java interface as an array of bytes containing the ;;; Java class ;;; ;;; This corresponds to the Java source: ;;; ;;; package org.not.tmp; ;;; public interface Foo { ;;; public int add(int a, int b); ;;; } (defparameter *foo-bytes* (define-java-interface "Foo" "org/not/tmp" '(("add" :int (:int :int))))) ;;; Load the class definition into the JVM (defparameter *foo-interface-class* (load-class *foo-bytes*)) ;;; Create an implementation of the interface in Lisp. (defparameter *foo* (jinterface-implementation "org.not.tmp.Foo" "add" (lambda (a b) (reduce #'+ (mapcar (lambda (n) (jcall "intValue" n)) (list a b)))))) ;;; To get the class of what we just defined, we have to use Proxy.getProxyClass() (defparameter *foo-class* ;; XXX would prettier if something like ;; (jarray-from-array-raw `#(,*foo-class*)) ;; existed. (let ((interface-array (jnew-array "java.lang.Class" 1))) (setf (jarray-ref interface-array 0) *foo-interface-class*) (jstatic-raw "getProxyClass" "java.lang.reflect.Proxy" java::*classloader* interface-array))) ;;; Get a reference to the callable instance of this method. (defparameter *callable-foo* (jstatic-raw "getInvocationHandler" "java.lang.reflect.Proxy" *foo*)) ;;; In order to use *callable-foo* we need to reflect the method we are ;;; going to invoke. ;;; First we construct a Java array of classes for the parameters (defparameter *add-parameters* ;; XXX again a jnew-array-from-array-raw would help here. (let ((parameters (jnew-array "java.lang.Class" 2))) (setf (jarray-ref parameters 0) (jfield-raw "java.lang.Integer" "TYPE") (jarray-ref parameters 1) (jfield-raw "java.lang.Integer" "TYPE")) parameters)) ;;; Then we get the reflected instance of the method. (defparameter *add-method* (jcall "getMethod" *foo-class* "add" *add-parameters*)) ;;; Now we construct the actual arguments we are going to call with (defparameter *add-args* (let ((args (jnew-array "java.lang.Integer" 2))) (setf (jarray-ref args 0) (jnew "java.lang.Integer" 2) (jarray-ref args 1) (jnew "java.lang.Integer" 2)) args)) ;;; It isn't strictly necessary to define the method parameter to ;;; JCALL in this manner, but it is more efficient in that the runtime ;;; does not have to dynamically introspect for the correct method. (defconstant +invocation-handler-invoke+ (jmethod "java.lang.reflect.InvocationHandler" "invoke" "java.lang.Object" "java.lang.reflect.Method" "[Ljava.lang.Object;")) ;; And finally we can make the call #| (jcall +invocation-handler-invoke+ *callable-foo* *foo* *add-method* *add-args*) |# abcl-src-1.9.0/examples/misc/hello.java0100644 0000000 0000000 00000000632 14202767264 016470 0ustar000000000 0000000 import org.armedbear.lisp.*; public class hello { public static void main(String[] args) { try { Interpreter interpreter = Interpreter.createInstance(); interpreter.eval("(format t \"Hello, world!~%\")"); } catch (Throwable t) { t.printStackTrace(); } } } // cd ~/j/examples // cp hello.java ../src // cd ../src // javac hello.java // java hello abcl-src-1.9.0/examples/misc/update-check-enabled.lisp0100644 0000000 0000000 00000003145 14202767264 021342 0ustar000000000 0000000 ;;; update-check-enabled.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id: update-check-enabled.lisp,v 1.2 2006-03-03 14:26:59 piso Exp $ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (in-package "CL-USER") ;; In minutes. (defparameter check-enabled-timeout 5) ;; Don't resolve autoloads in the background thread! (sys::resolve 'get-internal-real-time) (defun update-check-enabled () (loop (sleep 60) ; 1 minute (let* ((last-event-time (get-last-event-internal-time)) (current-time (get-internal-real-time)) (timeout (* check-enabled-timeout 60 internal-time-units-per-second)) (enable (if (> current-time (+ last-event-time timeout)) nil t))) (unless (eq (get-global-property 'check-enabled) enable) (set-global-property 'check-enabled enable) (log-debug "check-enabled => ~A" (get-global-property 'check-enabled)))))) ;; Fire it up. (make-thread #'update-check-enabled) abcl-src-1.9.0/examples/pure-lisp-to-java/Main.java0100644 0000000 0000000 00000001627 14202767264 020602 0ustar000000000 0000000 /* * Main.java * * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import org.armedbear.lisp.*; public class Main { public static int addTwoNumbers(int a, int b) { return a + b; } } abcl-src-1.9.0/examples/pure-lisp-to-java/README0100644 0000000 0000000 00000002150 14202767264 017723 0ustar000000000 0000000 ABCL Examples Building and Running Instructions =============================================== To compile cmd$ javac -cp ../../dist/abcl.jar Main.java where the "../../../dist/abcl.jar" represents the path to your abcl.jar file, which is built via the Ant based build. This path could be slightly different depending on how the system was constructed, and possibly due to operating system conventions for specifying relative paths. However you resolve this locally, we'll refer to this as '$ABCL_ROOT/dist/abcl.jar' for the rest of these instructions. This compiles the Java source file "Main.java" into a JVM runtime or class file named "Main.class". To run the example (Main.class for example) from a Unix-like OS use: cmd$ export CLASSPATH=. cmd$ $ABCL_ROOT/abcl then, in abcl repl, use: (load "lispfunctions") (void-function) or in Windows use: cmd$ set CLASSPATH=. cmd$ $ABCL_ROOT/abcl then, in abcl repl, use: (load "lispfunctions") (void-function) This will result in the Main class being found from the CLASSPATH, and you can invoke the functions of the Main class from lisp code. abcl-src-1.9.0/examples/pure-lisp-to-java/lispfunctions.lisp0100644 0000000 0000000 00000002256 14202767264 022643 0ustar000000000 0000000 ;;; lispfunctions.lisp ;;; ;;; Copyright (C) 2008 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; When the java class is in CLASSPATH, we can invoke its functions with ; for example jstatic. In this example the Main class is to be found ; in CLASSPATH, so we can just use it without having to load it ; separately. (defun void-function () (let* ((result (jstatic "addTwoNumbers" "Main" 2 4))) (format t "in void-function, result of calling addTwoNumbers(2, 4): ~a~%" result))) abcl-src-1.9.0/nbproject/build-impl.xml0100644 0000000 0000000 00000301012 14202767264 016513 0ustar000000000 0000000 Must set src.dir Must set test.src.dir Must set build.dir Must set dist.dir Must set build.classes.dir Must set dist.javadoc.dir Must set build.test.classes.dir Must set build.test.results.dir Must set build.classes.excludes Must set dist.jar Must set javac.includes No tests executed. Must set JVM to use for profiling in profiler.info.jvm Must set profiler agent JVM arguments in profiler.info.jvmargs.agent Must select some files in the IDE or set javac.includes To run this application from the command line without Ant, try: java -jar "${dist.jar.resolved}" Must select one file in the IDE or set run.class Must select one file in the IDE or set run.class Must select one file in the IDE or set debug.class Must select one file in the IDE or set debug.class Must set fix.includes This target only works when run from inside the NetBeans IDE. Must select one file in the IDE or set profile.class This target only works when run from inside the NetBeans IDE. This target only works when run from inside the NetBeans IDE. This target only works when run from inside the NetBeans IDE. Must select one file in the IDE or set run.class Must select some files in the IDE or set test.includes Must select one file in the IDE or set run.class Must select one file in the IDE or set applet.url Must select some files in the IDE or set javac.includes Some tests failed; see details above. Must select some files in the IDE or set test.includes Some tests failed; see details above. Must select some files in the IDE or set test.class Must select some method in the IDE or set test.method Some tests failed; see details above. Must select one file in the IDE or set test.class Must select one file in the IDE or set test.class Must select some method in the IDE or set test.method Must select one file in the IDE or set applet.url Must select one file in the IDE or set applet.url abcl-src-1.9.0/nbproject/configs/slime.properties0100644 0000000 0000000 00000000001 14202767264 020604 0ustar000000000 0000000 abcl-src-1.9.0/nbproject/genfiles.properties0100644 0000000 0000000 00000001163 14202767264 017651 0ustar000000000 0000000 build.xml.data.CRC32=71623fcd build.xml.script.CRC32=33676845 build.xml.stylesheet.CRC32=be360661 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=742204ce nbproject/build-impl.xml.script.CRC32=022245a1 nbproject/build-impl.xml.stylesheet.CRC32=f89f7d21@1.93.0.48 nbproject/profiler-build-impl.xml.data.CRC32=71623fcd nbproject/profiler-build-impl.xml.script.CRC32=abda56ed nbproject/profiler-build-impl.xml.stylesheet.CRC32=42cb6bcf abcl-src-1.9.0/nbproject/netbeans-older/README0100644 0000000 0000000 00000000674 14202767264 017527 0ustar000000000 0000000 At the time this writing, in October 2020, current release of the Netbeans IDE available from [Apache][netbeans] is Netbeans 12.1 When working with ABCL on older version of Netbeans in may be necessary to use the artifacts contained in this directory. Simply copy the three files in this directory to its the parent directory, and then ABCL may be opened as a project in older versions of Netbeans. [netbeans]: https://netbeans.apache.org/ abcl-src-1.9.0/nbproject/netbeans-older/build-impl.xml0100644 0000000 0000000 00000231143 14202767264 021424 0ustar000000000 0000000 Must set src.dir Must set test.src.dir Must set build.dir Must set dist.dir Must set build.classes.dir Must set dist.javadoc.dir Must set build.test.classes.dir Must set build.test.results.dir Must set build.classes.excludes Must set dist.jar Must set javac.includes No tests executed. Must set JVM to use for profiling in profiler.info.jvm Must set profiler agent JVM arguments in profiler.info.jvmargs.agent Must select some files in the IDE or set javac.includes To run this application from the command line without Ant, try: java -jar "${dist.jar.resolved}" Must select one file in the IDE or set run.class Must select one file in the IDE or set run.class Must select one file in the IDE or set debug.class Must select one file in the IDE or set debug.class Must set fix.includes This target only works when run from inside the NetBeans IDE. Must select one file in the IDE or set profile.class This target only works when run from inside the NetBeans IDE. This target only works when run from inside the NetBeans IDE. This target only works when run from inside the NetBeans IDE. Must select one file in the IDE or set run.class Must select some files in the IDE or set test.includes Must select one file in the IDE or set run.class Must select one file in the IDE or set applet.url Must select some files in the IDE or set javac.includes Some tests failed; see details above. Must select some files in the IDE or set test.includes Some tests failed; see details above. Must select some files in the IDE or set test.class Must select some method in the IDE or set test.method Some tests failed; see details above. Must select one file in the IDE or set test.class Must select one file in the IDE or set test.class Must select some method in the IDE or set test.method Must select one file in the IDE or set applet.url Must select one file in the IDE or set applet.url abcl-src-1.9.0/nbproject/netbeans-older/genfiles.properties0100644 0000000 0000000 00000001163 14202767264 022553 0ustar000000000 0000000 build.xml.data.CRC32=71623fcd build.xml.script.CRC32=33676845 build.xml.stylesheet.CRC32=be360661 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=742204ce nbproject/build-impl.xml.script.CRC32=dc81b4ba nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48 nbproject/profiler-build-impl.xml.data.CRC32=71623fcd nbproject/profiler-build-impl.xml.script.CRC32=abda56ed nbproject/profiler-build-impl.xml.stylesheet.CRC32=42cb6bcf abcl-src-1.9.0/nbproject/netbeans-older/project.properties0100644 0000000 0000000 00000004134 14202767264 022426 0ustar000000000 0000000 #Fri Oct 07 19:23:08 CEST 2016 excludes= javac.deprecation=false jnlp.enabled=false build.test.results.dir=${build.dir}/test/results run.classpath=${build.classes.dir}\:${javac.classpath}\:${file.reference.abcl-contrib.jar} javadoc.nonavbar=false run.test.classpath=${build.test.classes.dir}\:${javac.test.classpath} javac.processorpath=${javac.classpath} jnlp.signed=false javac.target=1.6 annotation.processing.processors.list= javadoc.noindex=false src.themes.dir=themes javadoc.additionalparam= includes=org/armedbear/lisp/**/*.java,org/armedbear/lisp/**/*.lisp build.classes.dir=${build.dir}/classes source.encoding=UTF-8 javadoc.author=false test.src.dir=test/src build.dir=build build.test.classes.dir=${build.dir}/test/classes platform.active=default_platform javac.compilerargs= main.class=org.armedbear.lisp.Main dist.jar=${dist.dir}/abcl.jar jnlp.codebase.url=file\:/Users/evenson/work/abcl/dist/ javadoc.use=true build.sysclasspath=ignore debug.test.classpath=${run.test.classpath} dist.dir=dist build.classes.excludes=**/*.java,**/*.form,**/*.lisp javadoc.splitindex=true javadoc.encoding=${source.encoding} javac.source=1.6 application.vendor= junit.selected.version=4 debug.classpath=${run.classpath} run.jvmargs= jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api" build.generated.dir=${build.dir}/generated jar.compress=true javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir}:\ ${libs.junit_4.classpath}:\ ${libs.hamcrest.classpath} javadoc.private=false file.reference.abcl-contrib.jar=dist/abcl-contrib.jar annotation.processing.run.all.processors=true application.title=abcl meta.inf.dir=${src.dir}/META-INF manifest.file=src/manifest-abcl annotation.processing.enabled=true dist.javadoc.dir=${dist.dir}/javadoc src.dir=${file.reference.abcl-src} mkdist.disabled=false jnlp.offline-allowed=false endorsed.classpath= javac.classpath= annotation.processing.enabled.in.editor=false build.generated.sources.dir=${build.dir}/generated-sources javadoc.version=false javadoc.windowtitle= src.doc.dir=doc javadoc.notree=false jnlp.codebase.type=local file.reference.abcl-src=src abcl-src-1.9.0/nbproject/private/configs/slime.properties0100644 0000000 0000000 00000000163 14202767264 022267 0ustar000000000 0000000 application.args=--eval "(require (quote asdf))" --eval "(asdf:load-system :swank)" --eval "(swank:create-server)" abcl-src-1.9.0/nbproject/project.properties0100644 0000000 0000000 00000004754 14202767264 017534 0ustar000000000 0000000 debug.modulepath=\ ${run.modulepath} debug.test.modulepath=\ ${run.test.modulepath} #Fri Oct 07 19:23:08 CEST 2016 excludes= javac.deprecation=false javac.external.vm=false javac.modulepath= javac.processormodulepath= javac.test.modulepath=\ ${javac.modulepath} javadoc.html5=false jlink.launcher=false jlink.launcher.name=abcl jnlp.enabled=false build.test.results.dir=${build.dir}/test/results run.classpath=\ ${build.classes.dir}:\ ${javac.classpath}:\ ${file.reference.abcl-contrib.jar} javadoc.nonavbar=false run.modulepath=\ ${javac.modulepath} run.test.classpath=\ ${build.test.classes.dir}:\ ${javac.test.classpath} javac.processorpath=\ ${javac.classpath} jnlp.signed=false javac.target=1.6 annotation.processing.processors.list= javadoc.noindex=false run.test.modulepath=\ ${javac.test.modulepath} src.themes.dir=themes javadoc.additionalparam= includes=org/armedbear/lisp/**/*.java,org/armedbear/lisp/**/*.lisp build.classes.dir=${build.dir}/classes source.encoding=UTF-8 javadoc.author=false test.src.dir=test/src build.dir=build build.test.classes.dir=${build.dir}/test/classes platform.active=default_platform javac.compilerargs= main.class=org.armedbear.lisp.Main dist.jar=${dist.dir}/abcl.jar jnlp.codebase.url=file\:/Users/evenson/work/abcl/dist/ javadoc.use=true build.sysclasspath=ignore debug.test.classpath=${run.test.classpath} dist.dir=dist build.classes.excludes=**/*.java,**/*.form,**/*.lisp javadoc.splitindex=true javadoc.encoding=${source.encoding} javac.source=1.6 application.vendor= junit.selected.version=4 debug.classpath=${run.classpath} run.jvmargs= jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api" build.generated.dir=${build.dir}/generated jar.compress=true javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir}:\ ${libs.junit_4.classpath}:\ ${libs.hamcrest.classpath} javadoc.private=false file.reference.abcl-contrib.jar=dist/abcl-contrib.jar annotation.processing.run.all.processors=true application.title=abcl meta.inf.dir=${src.dir}/META-INF manifest.file=src/manifest-abcl annotation.processing.enabled=true dist.javadoc.dir=${dist.dir}/javadoc src.dir=${file.reference.abcl-src} mkdist.disabled=false jnlp.offline-allowed=false endorsed.classpath= javac.classpath= annotation.processing.enabled.in.editor=false build.generated.sources.dir=${build.dir}/generated-sources javadoc.version=false javadoc.windowtitle= src.doc.dir=doc javadoc.notree=false jnlp.codebase.type=local file.reference.abcl-src=src abcl-src-1.9.0/nbproject/project.xml0100644 0000000 0000000 00000001076 14202767264 016132 0ustar000000000 0000000 org.netbeans.modules.java.j2seproject abcl 1.6.5 abcl-src-1.9.0/src/META-INF/services/javax.script.ScriptEngineFactory0100644 0000000 0000000 00000000065 14202767264 024003 0ustar000000000 0000000 org.armedbear.lisp.scripting.AbclScriptEngineFactory abcl-src-1.9.0/src/manifest-abcl0100644 0000000 0000000 00000000044 14202767264 015165 0ustar000000000 0000000 Main-Class: org.armedbear.lisp.Main abcl-src-1.9.0/src/org/armedbear/lisp/AbstractArray.java0100644 0000000 0000000 00000026175 14212440004 021614 0ustar000000000 0000000 /* * AbstractArray.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class AbstractArray extends LispObject implements java.io.Serializable { @Override public LispObject typep(LispObject type) { if (type == Symbol.ARRAY) return T; if (type == BuiltInClass.ARRAY) return T; return super.typep(type); } @Override public boolean equalp(LispObject obj) { if (obj instanceof AbstractArray) { AbstractArray a = (AbstractArray) obj; if (getRank() != a.getRank()) return false; for (int i = getRank(); i-- > 0;) { if (getDimension(i) != a.getDimension(i)) return false; } for (int i = getTotalSize(); i--> 0;) { if (!AREF(i).equalp(a.AREF(i))) return false; } return true; } return false; } public boolean isDisplaced() { return false; } public LispObject arrayDisplacement() { return LispThread.currentThread().setValues(NIL, Fixnum.ZERO); } public boolean hasFillPointer() { return false; } public int getFillPointer() { noFillPointer(); return -1; // Not reached. } public void setFillPointer(LispObject fillPointer) { setFillPointer(fillPointer.intValue()); } public void setFillPointer(int fillPointer) { noFillPointer(); } public boolean isAdjustable() { return true; } public abstract int getRank(); public abstract LispObject getDimensions(); public abstract int getDimension(int n); public abstract LispObject getElementType(); public abstract int getTotalSize(); @Override public abstract void aset(int index, LispObject newValue) ; // FIXME Detect overflow! protected static final int computeTotalSize(int[] dimensions) { int size = 1; for (int i = dimensions.length; i-- > 0;) size *= dimensions[i]; return size; } public int getRowMajorIndex(LispObject[] subscripts) { int[] subs = new int[subscripts.length]; for (int i = 0; i < subscripts.length; i++) { LispObject subscript = subscripts[i]; if (subscript instanceof Fixnum) subs[i] = ((Fixnum)subscript).value; else type_error(subscript, Symbol.FIXNUM); } return getRowMajorIndex(subs); } public int getRowMajorIndex(int[] subscripts) { final int rank = getRank(); if (rank != subscripts.length) { // ### i18n final String errorMsg = "Wrong number of subscripts (%d) for array of rank %d."; program_error(String.format(errorMsg, subscripts.length, rank)); } int sum = 0; int size = 1; for (int i = rank; i-- > 0;) { final int dim = getDimension(i); final int lastSize = size; size *= dim; final int n = subscripts[i]; if (n < 0 || n >= dim) { // ### i18n final String errorMsg = "Invalid index %d for array %s."; program_error(String.format(errorMsg, n, printObject())); } sum += n * lastSize; } return sum; } public LispObject get(int[] subscripts) { return AREF(getRowMajorIndex(subscripts)); } public void set(int[] subscripts, LispObject newValue) { aset(getRowMajorIndex(subscripts), newValue); } public abstract void fill(LispObject obj); public String printObject(int[] dimv) { StringBuilder sb = new StringBuilder(); LispThread thread = LispThread.currentThread(); LispObject printReadably = Symbol.PRINT_READABLY.symbolValue(thread); if (printReadably != NIL || Symbol.PRINT_ARRAY.symbolValue(thread) != NIL) { int maxLevel = Integer.MAX_VALUE; if (printReadably != NIL) { for (int i = 0; i < dimv.length - 1; i++) { if (dimv[i] == 0) { for (int j = i + 1; j < dimv.length; j++) { if (dimv[j] != 0) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); return null; // Not reached. } } } } } else { LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread); if (printLevel instanceof Fixnum) maxLevel = ((Fixnum)printLevel).value; } LispObject currentPrintLevel = _CURRENT_PRINT_LEVEL_.symbolValue(thread); int currentLevel = Fixnum.getValue(currentPrintLevel); if (currentLevel >= maxLevel) return "#"; sb.append('#'); sb.append(dimv.length); sb.append('A'); appendContents(dimv, 0, sb, thread); return sb.toString(); } sb.append('('); if (this instanceof SimpleArray_T) sb.append("SIMPLE-"); sb.append("ARRAY " + getElementType().printObject() + " ("); for (int i = 0; i < dimv.length; i++) { sb.append(dimv[i]); if (i < dimv.length - 1) sb.append(' '); } sb.append("))"); return unreadableString(sb.toString()); } // Helper for printObject(). private void appendContents(int[] dimensions, int index, StringBuilder sb, LispThread thread) { if (dimensions.length == 0) { if (Symbol.PRINT_CIRCLE.symbolValue(thread) != NIL) { StringOutputStream stream = new StringOutputStream(); thread.execute(Symbol.OUTPUT_OBJECT.getSymbolFunction(), AREF(index), stream); sb.append(stream.getString().getStringValue()); } else sb.append(AREF(index).printObject()); } else { final LispObject printReadably = Symbol.PRINT_READABLY.symbolValue(thread); int maxLength = Integer.MAX_VALUE; int maxLevel = Integer.MAX_VALUE; if (printReadably == NIL) { final LispObject printLength = Symbol.PRINT_LENGTH.symbolValue(thread); if (printLength instanceof Fixnum) maxLength = ((Fixnum)printLength).value; final LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread); if (printLevel instanceof Fixnum) maxLevel = ((Fixnum)printLevel).value; } LispObject currentPrintLevel = _CURRENT_PRINT_LEVEL_.symbolValue(thread); int currentLevel = Fixnum.getValue(currentPrintLevel); if (currentLevel < maxLevel) { final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(_CURRENT_PRINT_LEVEL_, currentPrintLevel.incr()); try { sb.append('('); int[] dims = new int[dimensions.length - 1]; for (int i = 1; i < dimensions.length; i++) dims[i-1] = dimensions[i]; int count = 1; for (int i = 0; i < dims.length; i++) count *= dims[i]; final int length = dimensions[0]; final int limit = Math.min(length, maxLength); for (int i = 0; i < limit; i++) { appendContents(dims, index, sb, thread); if (i < limit - 1 || limit < length) sb.append(' '); index += count; } if (limit < length) sb.append("..."); sb.append(')'); } finally { thread.resetSpecialBindings(mark); } } else sb.append('#'); } } // For EQUALP hash tables. @Override public int psxhash() { long result = 128387; // Chosen at random. final int rank = getRank(); int limit = rank < 4 ? rank : 4; for (int i = 0; i < limit; i++) result = mix(result, getDimension(i)); final int length = getTotalSize(); limit = length < 4 ? length : 4; for (int i = 0; i < length; i++) result = mix(result, AREF(i).psxhash()); return (int) (result & 0x7fffffff); } /** Returns a newly allocated array or the current array with * adjusted dimensions. * * @param dims * @param initialElement @c null if none * @param initialContents @c null if none * @return @c this or a new array */ public abstract AbstractArray adjustArray(int[] dims, LispObject initialElement, LispObject initialContents); /** * * @param dims * @param displacedTo * @param displacement * @return */ public abstract AbstractArray adjustArray(int[] dims, AbstractArray displacedTo, int displacement); } abcl-src-1.9.0/src/org/armedbear/lisp/AbstractBitVector.java0100644 0000000 0000000 00000014562 14202767264 022457 0ustar000000000 0000000 /* * AbstractBitVector.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class AbstractBitVector extends AbstractVector { protected static final int LONG_MASK = 0x3f; protected int capacity; // For non-displaced bit-vectors. protected long[] bits; @Override public LispObject typep(LispObject type) { if (type == Symbol.BIT_VECTOR) return T; if (type == BuiltInClass.BIT_VECTOR) return T; return super.typep(type); } @Override public LispObject classOf() { return BuiltInClass.BIT_VECTOR; } @Override public final int capacity() { return capacity; } @Override public final LispObject getElementType() { return Symbol.BIT; } @Override public boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof AbstractBitVector) { AbstractBitVector v = (AbstractBitVector) obj; if (length() != v.length()) return false; for (int i = length(); i-- > 0;) { if (getBit(i) != v.getBit(i)) return false; } return true; } return false; } @Override public boolean equalp(LispObject obj) { if (this == obj) return true; if (obj instanceof AbstractBitVector) { AbstractBitVector v = (AbstractBitVector) obj; if (length() != v.length()) return false; for (int i = length(); i-- > 0;) { if (getBit(i) != v.getBit(i)) return false; } return true; } if (obj instanceof AbstractString) return false; if (obj instanceof AbstractVector) return ((AbstractVector)obj).equalp(this); return false; } @Override public void fill(LispObject obj) { if (obj instanceof Fixnum) { switch (((Fixnum)obj).value) { case 0: if (bits != null) { for (int i = bits.length; i-- > 0;) bits[i] = 0; } else { for (int i = capacity; i-- > 0;) clearBit(i); } return; case 1: if (bits != null) { for (int i = bits.length; i-- > 0;) bits[i] = -1L; } else { for (int i = capacity; i-- > 0;) setBit(i); } return; } // Fall through... } type_error(obj, Symbol.BIT); } @Override public LispObject subseq(int start, int end) { SimpleBitVector v = new SimpleBitVector(end - start); int i = start, j = 0; try { while (i < end) { if (getBit(i++) == 0) v.clearBit(j++); else v.setBit(j++); } return v; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public int hashCode() { int hashCode = 1; // Consider first 64 bits only. final int limit = Math.min(length(), 64); for (int i = 0; i < limit; i++) hashCode = hashCode * 31 + getBit(i); return hashCode; } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); final int length = length(); if (Symbol.PRINT_READABLY.symbolValue(thread) != NIL || Symbol.PRINT_ARRAY.symbolValue(thread) != NIL) { StringBuilder sb = new StringBuilder(length + 2); sb.append("#*"); for (int i = 0; i < length; i++) sb.append(getBit(i) == 1 ? '1' : '0'); return sb.toString(); } else { final String str = "(%sBIT-VECTOR %d)"; final String pre = (this instanceof SimpleBitVector) ? "SIMPLE-" : ""; return unreadableString(String.format(str, pre, length)); } } @Override public LispObject reverse() { int length = length(); SimpleBitVector result = new SimpleBitVector(length); int i, j; for (i = 0, j = length - 1; i < length; i++, j--) { if (getBit(j) == 1) result.setBit(i); else result.clearBit(i); } return result; } protected abstract int getBit(int index); protected abstract void setBit(int index); protected abstract void clearBit(int index); } abcl-src-1.9.0/src/org/armedbear/lisp/AbstractString.java0100644 0000000 0000000 00000007370 14223403213 022003 0ustar000000000 0000000 /* * AbstractString.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class AbstractString extends AbstractVector { @Override public LispObject typep(LispObject type) { if (type instanceof Symbol) { if (type == Symbol.STRING) return T; if (type == Symbol.BASE_STRING) return T; } if (type == BuiltInClass.STRING) return T; if (type == BuiltInClass.BASE_STRING) return T; return super.typep(type); } @Override public final boolean stringp() { return true; } @Override public LispObject getElementType() { return Symbol.CHARACTER; } @Override public final boolean isSimpleVector() { return false; } @Override public final LispObject STRING() { return this; } public abstract void fill(char c); public abstract char charAt(int index); public abstract void setCharAt(int index, char c); public final String printObject(int beginIndex, int endIndex) { if (beginIndex < 0) beginIndex = 0; final int limit; limit = length(); if (endIndex > limit) endIndex = limit; final LispThread thread = LispThread.currentThread(); if (Symbol.PRINT_ESCAPE.symbolValue(thread) != NIL || Symbol.PRINT_READABLY.symbolValue(thread) != NIL) { StringBuilder sb = new StringBuilder("\""); for (int i = beginIndex; i < endIndex; i++) { char c = charAt(i); if (c == '\"' || c == '\\') sb.append('\\'); sb.append(c); } sb.append('"'); return sb.toString(); } else return getStringValue().substring(beginIndex, endIndex); } @Override public String printObject() { return printObject(0, length()); } public String toString() { int length = length(); StringBuilder sb = new StringBuilder(length); for(int i = 0; i < length; ++i) { sb.append(charAt(i)); } return sb.toString(); } } abcl-src-1.9.0/src/org/armedbear/lisp/AbstractVector.java0100644 0000000 0000000 00000020513 14202767264 022011 0ustar000000000 0000000 /* * AbstractVector.java * * Copyright (C) 2003-2006 Peter Graves * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class AbstractVector extends AbstractArray { @Override public LispObject typep(LispObject type) { if (type == Symbol.VECTOR) return T; if (type == BuiltInClass.VECTOR) return T; if (type == Symbol.SEQUENCE) return T; if (type == BuiltInClass.SEQUENCE) return T; return super.typep(type); } @Override public final boolean vectorp() { return true; } @Override public boolean equalp(LispObject obj) { if (obj instanceof AbstractVector) { if (length() != obj.length()) return false; AbstractVector v = (AbstractVector) obj; for (int i = length(); i-- > 0;) if (!AREF(i).equalp(v.AREF(i))) return false; return true; } return false; } @Override public final int getRank() { return 1; } @Override public final LispObject getDimensions() { return new Cons(Fixnum.getInstance(capacity())); } @Override public final int getDimension(int n) { if (n != 0) { error(new TypeError("bad dimension for vector")); // Not reached. return 0; } return capacity(); } @Override public final int getTotalSize() { return capacity(); } public abstract int capacity(); public abstract LispObject subseq(int start, int end); public LispObject deleteEq(LispObject item) { final int limit = length(); int i = 0; int j = 0; while (i < limit) { LispObject obj = AREF(i++); if (obj != item) aset(j++, obj); } final int newLength = j; if (newLength < capacity()) shrink(newLength); return this; } public LispObject deleteEql(LispObject item) { final int limit = length(); int i = 0; int j = 0; while (i < limit) { LispObject obj = AREF(i++); if (!obj.eql(item)) aset(j++, obj); } final int newLength = j; if (newLength < capacity()) shrink(newLength); return this; } public abstract void shrink(int n); public int checkIndex(int index) { if (index < 0 || index >= capacity()) badIndex(index, capacity()); return index; } protected void badIndex(int index, int limit) { StringBuilder sb = new StringBuilder("Invalid array index "); sb.append(index); sb.append(" for "); sb.append(princToString()); if (limit > 0) { sb.append(" (should be >= 0 and < "); sb.append(limit); sb.append(")."); } error(new TypeError(sb.toString(), Fixnum.getInstance(index), list(Symbol.INTEGER, Fixnum.ZERO, Fixnum.getInstance(limit - 1)))); } public void setFillPointer(int n) { noFillPointer(); } public void setFillPointer(LispObject obj) { noFillPointer(); } public boolean isSimpleVector() { return false; } @Override public abstract LispObject reverse(); @Override public LispObject nreverse() { int i = 0; int j = length() - 1; while (i < j) { LispObject temp = AREF(i); aset(i, AREF(j)); aset(j, temp); ++i; --j; } return this; } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); if (Symbol.PRINT_READABLY.symbolValue(thread) != NIL) { StringBuilder sb = new StringBuilder("#("); final int limit = length(); for (int i = 0; i < limit; i++) { if (i > 0) sb.append(' '); sb.append(AREF(i).printObject()); } sb.append(')'); return sb.toString(); } else if (Symbol.PRINT_ARRAY.symbolValue(thread) != NIL) { int maxLevel = Integer.MAX_VALUE; final LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread); if (printLevel instanceof Fixnum) maxLevel = ((Fixnum)printLevel).value; LispObject currentPrintLevel = _CURRENT_PRINT_LEVEL_.symbolValue(thread); int currentLevel = Fixnum.getValue(currentPrintLevel); if (currentLevel < maxLevel) { StringBuffer sb = new StringBuffer("#("); int maxLength = Integer.MAX_VALUE; final LispObject printLength = Symbol.PRINT_LENGTH.symbolValue(thread); if (printLength instanceof Fixnum) maxLength = ((Fixnum)printLength).value; final int length = length(); final int limit = Math.min(length, maxLength); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(_CURRENT_PRINT_LEVEL_, currentPrintLevel.incr()); try { for (int i = 0; i < limit; i++) { if (i > 0) sb.append(' '); sb.append(AREF(i).printObject()); } } finally { thread.resetSpecialBindings(mark); } if (limit < length) sb.append(limit > 0 ? " ..." : "..."); sb.append(')'); return sb.toString(); } else return "#"; } else { StringBuffer sb = new StringBuffer(); sb.append(isSimpleVector() ? "SIMPLE-VECTOR " : "VECTOR "); sb.append(capacity()); return unreadableString(sb.toString()); } } // For EQUALP hash tables. @Override public int psxhash() { final int length = length(); final int limit = length < 4 ? length : 4; long result = 48920713; // Chosen at random. for (int i = 0; i < limit; i++) result = mix(result, AREF(i).psxhash()); return (int) (result & 0x7fffffff); } public abstract AbstractArray adjustArray(int size, LispObject initialElement, LispObject initialContents) ; public abstract AbstractArray adjustArray(int size, AbstractArray displacedTo, int displacement) ; public AbstractArray adjustArray(int[] dims, LispObject initialElement, LispObject initialContents) { return adjustArray(dims[0], initialElement, initialContents); } public AbstractArray adjustArray(int[] dims, AbstractArray displacedTo, int displacement) { return adjustArray(dims[0], displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/ArgumentListProcessor.java0100644 0000000 0000000 00000111660 14202767264 023405 0ustar000000000 0000000 /* * ArgumentListProcessor.java * * Copyright (C) 2012 Erik Huelsmann * Copyright (C) 2002-2008 Peter Graves * Copyright (C) 2008 Ville Voutilainen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.Serializable; import java.util.List; import java.util.ArrayList; import static org.armedbear.lisp.Lisp.*; /** A class to parse a lambda list and match function call arguments with it. * * The lambda list may either be of type ORDINARY or MACRO lambda list. * All other lambda lists are parsed elsewhere in our code base. */ public class ArgumentListProcessor implements Serializable { public enum LambdaListType { ORDINARY, MACRO } // States. private static final int STATE_REQUIRED = 0; private static final int STATE_OPTIONAL = 1; private static final int STATE_KEYWORD = 2; private static final int STATE_REST = 3; private static final int STATE_AUX = 4; private Param[] requiredParameters = new Param[0]; private Param[] optionalParameters = requiredParameters; private KeywordParam[] keywordParameters = new KeywordParam[0]; private Param[] auxVars = requiredParameters; private Param[] positionalParameters = requiredParameters; private Symbol restVar; private Param restParam; private Symbol envVar; private Param envParam; private int arity; private int minArgs; private int maxArgs; /** The variables in the lambda list, including &aux and 'supplied-p' */ private Symbol[] variables = new Symbol[0]; /** Array of booleans of value 'true' if the associated variable in the * variables array is a special variable */ private boolean[] specials = new boolean[0]; private boolean andKey; private boolean allowOtherKeys; /** The parser to be used to match function call arguments with the lambda list */ final private ArgumentMatcher matcher; /** Holds the value 'true' if the matcher needs an evaluation environment to * evaluate the initforms of variales in the &optional, &key or &aux categories */ private boolean matcherNeedsEnv; /** Used when generating errors during function call argument matching */ private Operator function; /** Constructor to be used from compiled code * * The compiler hands in pre-parsed lambda lists. The process of matching * function call arguments with lambda lists which are constructed this * way don't support non-constant initforms for &optional, &key and &aux * parameters. As a result, there's no need to create an evaluation * environment which in turn eliminates the need to know which variables * are special. * * @param fun The function to report function call argument matching errors on * @param required The list of required arguments * @param optional The list of optional arguments * @param keyword The list of keyword parameters * @param key Indicates whether &key was specified (optionally without naming keys) * @param moreKeys Indicates whether &allow-other-keys was specified * @param rest Specifies the &rest variable name, if one was specified, or 'null' if none */ public ArgumentListProcessor(Operator fun, int requiredCount, OptionalParam[] optional, KeywordParam[] keyword, boolean key, boolean moreKeys, Symbol rest) { function = fun; requiredParameters = new RequiredParam[requiredCount]; positionalParameters = new Param[requiredCount + optional.length + ((rest != null) ? 1 : 0)]; // the same anonymous required parameter can be used any number of times RequiredParam r = new RequiredParam(); for (int i = 0; i < requiredCount; i++) { requiredParameters[i] = r; positionalParameters[i] = r; } optionalParameters = optional; System.arraycopy(optional, 0, positionalParameters, requiredCount, optional.length); restVar = rest; if (restVar != null) positionalParameters[requiredCount + optional.length] = restParam = new RestParam(rest, false); andKey = key; allowOtherKeys = moreKeys; keywordParameters = keyword; auxVars = new Param[0]; variables = extractVariables(); specials = new boolean[variables.length]; // default values 'false' -- leave that way minArgs = requiredParameters.length; maxArgs = (rest == null && ! allowOtherKeys) ? minArgs + optionalParameters.length + 2*keywordParameters.length : -1; arity = (rest == null && ! allowOtherKeys && ! andKey && optionalParameters.length == 0) ? maxArgs : -1; if (keyword.length == 0) matcher = new FastMatcher(); else matcher = new SlowMatcher(); } /** Instantiates an ArgumentListProcessor by parsing the lambda list specified * in 'lambdaList'. * * This constructor sets up the object to support evaluation of non-constant * initforms. * * @param fun Function to use when reporting errors * @param lambdaList Lambda list to parse and use for function call * @param specials A list of symbols specifying which variables to * bind as specials during initform evaluation */ public ArgumentListProcessor(Operator fun, LispObject lambdaList, LispObject specials, LambdaListType type) { function = fun; boolean _andKey = false; boolean _allowOtherKeys = false; if (lambdaList instanceof Cons) { final int length = lambdaList.length(); ArrayList required = null; ArrayList optional = null; ArrayList keywords = null; ArrayList aux = null; int state = STATE_REQUIRED; LispObject remaining = lambdaList; if (remaining.car() == Symbol.AND_WHOLE) { if (type == LambdaListType.ORDINARY) { program_error("&WHOLE not allowed in ordinary lambda lists."); } else { // skip the &WHOLE part of the lambda list remaining = remaining.cdr().cdr(); } } while (remaining != NIL) { LispObject obj = remaining.car(); if (obj instanceof Symbol) { if (obj == Symbol.AND_WHOLE) { if (type == LambdaListType.ORDINARY) program_error("&WHOLE not allowed in ordinary lambda lists."); else program_error("&WHOLE must appear first in macro lambda list."); } if (state == STATE_AUX) { if (aux == null) aux = new ArrayList(); aux.add(new AuxParam((Symbol)obj, isSpecial((Symbol)obj, specials), NIL)); } else if (obj == Symbol.AND_OPTIONAL) { state = STATE_OPTIONAL; arity = -1; } else if (obj == Symbol.AND_REST || obj == Symbol.AND_BODY) { if (_andKey) { program_error("&REST/&BODY must precede &KEY."); } if (type == LambdaListType.ORDINARY && obj == Symbol.AND_BODY) program_error("&BODY not allowed in ordinary lambda lists."); state = STATE_REST; arity = -1; maxArgs = -1; remaining = remaining.cdr(); if (remaining == NIL) { program_error("&REST/&BODY must be followed by a variable."); } if (restVar != null) { program_error("&REST/&BODY may occur only once."); } final LispObject remainingcar = remaining.car(); if (remainingcar instanceof Symbol) { restVar = (Symbol) remainingcar; restParam = new RestParam(restVar, isSpecial(restVar, specials)); } else { program_error("&REST/&BODY must be followed by a variable."); } } else if (obj == Symbol.AND_ENVIRONMENT) { if (type == LambdaListType.ORDINARY) program_error("&ENVIRONMENT not allowed in ordinary lambda lists."); remaining = remaining.cdr(); envVar = (Symbol) remaining.car(); envParam = new EnvironmentParam(envVar, isSpecial(envVar, specials)); arity = -1; // FIXME } else if (obj == Symbol.AND_KEY) { state = STATE_KEYWORD; _andKey = true; arity = -1; } else if (obj == Symbol.AND_ALLOW_OTHER_KEYS) { _allowOtherKeys = true; maxArgs = -1; } else if (obj == Symbol.AND_AUX) { // All remaining specifiers are aux variable specifiers. state = STATE_AUX; arity = -1; // FIXME } else { if (state == STATE_OPTIONAL) { if (optional == null) optional = new ArrayList(); optional.add(new OptionalParam((Symbol)obj, isSpecial((Symbol)obj, specials), null, false, NIL)); if (maxArgs >= 0) ++maxArgs; } else if (state == STATE_KEYWORD) { if (keywords == null) keywords = new ArrayList(); keywords.add(new KeywordParam((Symbol)obj, isSpecial((Symbol)obj, specials), null, false, NIL, null)); if (maxArgs >= 0) maxArgs += 2; } else { if (state != STATE_REQUIRED) { program_error("required parameters cannot appear after &REST/&BODY."); } if (required == null) required = new ArrayList(); required.add(new RequiredParam((Symbol)obj, isSpecial((Symbol)obj, specials))); if (maxArgs >= 0) ++maxArgs; } } } else if (obj instanceof Cons) { if (state == STATE_AUX) { Symbol sym = checkSymbol(obj.car()); LispObject initForm = obj.cadr(); Debug.assertTrue(initForm != null); if (aux == null) aux = new ArrayList(); aux.add(new AuxParam(sym, isSpecial(sym, specials), initForm)); } else if (state == STATE_OPTIONAL) { Symbol sym = checkSymbol(obj.car()); LispObject initForm = obj.cadr(); Symbol svar = checkSymbol(obj.cdr().cdr().car()); if (optional == null) optional = new ArrayList(); optional.add(new OptionalParam(sym, isSpecial(sym, specials), svar == NIL ? null : svar, isSpecial(svar, specials), initForm)); if (maxArgs >= 0) ++maxArgs; } else if (state == STATE_KEYWORD) { Symbol keyword; Symbol var; LispObject initForm = NIL; Symbol svar = NIL; LispObject first = obj.car(); if (first instanceof Cons) { keyword = checkSymbol(first.car()); var = checkSymbol(first.cadr()); } else { var = checkSymbol(first); keyword = PACKAGE_KEYWORD.intern(var.name); } obj = obj.cdr(); if (obj != NIL) { initForm = obj.car(); obj = obj.cdr(); if (obj != NIL) svar = checkSymbol(obj.car()); } if (keywords == null) keywords = new ArrayList(); keywords.add(new KeywordParam(var, isSpecial(var, specials), svar == NIL ? null : svar, isSpecial(svar, specials), initForm, keyword)); if (maxArgs >= 0) maxArgs += 2; } else invalidParameter(obj); } else invalidParameter(obj); remaining = remaining.cdr(); } if (arity == 0) arity = length; ArrayList positional = new ArrayList(); if (envParam != null) positional.add(envParam); if (required != null) { requiredParameters = new Param[required.size()]; required.toArray(requiredParameters); positional.addAll(required); } if (optional != null) { optionalParameters = new Param[optional.size()]; optional.toArray(optionalParameters); positional.addAll(optional); } if (restParam != null) positional.add(restParam); if (keywords != null) { keywordParameters = new KeywordParam[keywords.size()]; keywords.toArray(keywordParameters); } if (aux != null) { auxVars = new Param[aux.size()]; auxVars = aux.toArray(auxVars); } positionalParameters = positional.toArray(positionalParameters); } else { // Lambda list is empty. Debug.assertTrue(lambdaList == NIL); arity = 0; maxArgs = 0; } this.andKey = _andKey; this.allowOtherKeys = _allowOtherKeys; minArgs = requiredParameters.length; if (arity >= 0) Debug.assertTrue(arity == minArgs); variables = extractVariables(); this.specials = new boolean[variables.length]; for (int i = 0; i < variables.length; i++) this.specials[i] = isSpecial(variables[i], specials); for (Param p : positionalParameters) if (p.needsEnvironment()) { matcherNeedsEnv = true; break; } if (! matcherNeedsEnv) for (Param p : keywordParameters) if (p.needsEnvironment()) { matcherNeedsEnv = true; break; } if (! matcherNeedsEnv) for (Param p : auxVars) if (p.needsEnvironment()) { matcherNeedsEnv = true; break; } if (keywordParameters.length == 0) { matcher = new FastMatcher(); } else { matcher = new SlowMatcher(); } } public void setFunction(Operator fun) { function = fun; } /** Matches the function call arguments 'args' with the lambda list, * returning an array with variable values to be used. The array is sorted * the same way as the variables returned by the 'extractVariables' function. * * @param args Funcion call arguments to be matched * @param _environment Environment to be used for the &environment variable * @param env Environment to evaluate initforms in * @param thread Thread to be used for binding special variables * -- must be LispThread.currentThread() * @return An array of LispObjects corresponding to the values to be bound * to the variables in the lambda list */ public LispObject[] match(LispObject[] args, Environment _environment, Environment env, LispThread thread) { if (matcherNeedsEnv) { if (thread == null) thread = LispThread.currentThread(); env = new Environment((env == null) ? _environment : env); } LispObject[] rv = matcher.match(args, _environment, env, thread); for (int i = 0; i < rv.length; i++) Debug.assertTrue(rv[i] != null); return rv; } /** Binds the variable values returned from 'match' to their corresponding * variables in the environment 'env', with specials bound in thread 'thread'. * * @param values Values to be bound * @param env * @param thread */ public void bindVars(LispObject[] values, Environment env, LispThread thread) { for (int i = 0; i < variables.length; i++) { Symbol var = variables[i]; // If a symbol is declared special after a function is defined, // the interpreter binds a lexical variable instead of a dynamic // one if we don't check isSpecialVariable() bindArg(specials[i] || var.isSpecialVariable(), var, values[i], env, thread); } } public Symbol[] freeSpecials(LispObject specials) { ArrayList list = new ArrayList(); next_special: while (specials != NIL) { Symbol special = (Symbol)specials.car(); specials = specials.cdr(); for (Symbol v : variables) if (v == special) continue next_special; list.add(special); } Symbol[] rv = new Symbol[list.size()]; return list.toArray(rv); } public int getArity() { return arity; } public int getMinArgs() { return minArgs; } public int getMaxArgs() { return maxArgs; } public Symbol[] getVariables() { return variables; } private static void invalidParameter(LispObject obj) { program_error(obj.princToString() + " may not be used as a variable in a lambda list."); } private Symbol[] extractVariables() { ArrayList vars = new ArrayList(); for (Param parameter : positionalParameters) parameter.addVars(vars); for (Param parameter : keywordParameters) parameter.addVars(vars); for (Param parameter : auxVars) parameter.addVars(vars); Symbol[] array = new Symbol[vars.size()]; vars.toArray(array); return array; } /** Internal class implementing the argument list to lambda list matcher. * Because we have two implementations - a fast one and a slower one - we * need this abstract super class */ private static abstract class ArgumentMatcher implements Serializable { abstract LispObject[] match(LispObject[] args, Environment _environment, Environment env, LispThread thread); } /** ArgumentMatcher class which implements full-blown argument matching, * including validation of the keywords passed. */ private class SlowMatcher extends ArgumentMatcher { private LispObject[] _match(LispObject[] args, Environment _environment, Environment env, LispThread thread) { final ArgList argslist = new ArgList(_environment, args); final LispObject[] array = new LispObject[variables.length]; int index = 0; for (Param p : positionalParameters) index = p.assign(index, array, argslist, env, thread); if (andKey) { argslist.assertRemainderKeywords(); for (Param p : keywordParameters) index = p.assign(index, array, argslist, env, thread); } for (Param p : auxVars) index = p.assign(index, array, argslist, env, thread); if (andKey) { if (allowOtherKeys) return array; if (!argslist.consumed()) // verify keywords { LispObject allowOtherKeysValue = argslist.findKeywordArg(Keyword.ALLOW_OTHER_KEYS, NIL); if (allowOtherKeysValue != NIL) return array; // verify keywords next_key: while (! argslist.consumed()) { LispObject key = argslist.consume(); argslist.consume(); // consume value if (key == Keyword.ALLOW_OTHER_KEYS) continue next_key; for (KeywordParam k : keywordParameters) if (k.keyword == key) continue next_key; program_error("Unrecognized keyword argument " + key.printObject() + "."); } } } if (restVar == null && !argslist.consumed()) error(new WrongNumberOfArgumentsException(function)); return array; } @Override LispObject[] match(LispObject[] args, Environment _environment, Environment env, LispThread thread) { if (arity >= 0) { // Fixed arity. if (args.length != arity) error(new WrongNumberOfArgumentsException(function, list(args), arity)); return args; } // Not fixed arity. if (args.length < minArgs) error(new WrongNumberOfArgumentsException(function, minArgs, -1)); if (thread == null) return _match(args, _environment, env, thread); final SpecialBindingsMark mark = thread.markSpecialBindings(); try { return _match(args, _environment, env, thread); } finally { thread.resetSpecialBindings(mark); } } } /** Slimmed down ArgumentMatcher which doesn't implement keyword verification. */ private class FastMatcher extends ArgumentMatcher { @Override LispObject[] match(LispObject[] args, Environment _environment, Environment env, LispThread thread) { final int argsLength = args.length; if (arity >= 0) { // Fixed arity. if (argsLength != arity) error(new WrongNumberOfArgumentsException(function, list(args), arity)); return args; } // Not fixed arity. if (argsLength < minArgs) error(new WrongNumberOfArgumentsException(function, minArgs, -1)); final ArgList arglist = new ArgList(_environment, args); final LispObject[] array = new LispObject[variables.length]; int index = 0; // Required parameters. for (Param p : positionalParameters) index = p.assign(index, array, arglist, env, thread); for (Param p : auxVars) index = p.assign(index, array, arglist, env, thread); if (andKey && !arglist.consumed()) { // remaining arguments must be keyword/value pairs arglist.assertRemainderKeywords(); if (allowOtherKeys) return array; LispObject allowOtherKeysValue = arglist.findKeywordArg(Keyword.ALLOW_OTHER_KEYS, null); if (allowOtherKeysValue == NIL) { // the argument is there. LispObject key = arglist.consume(); arglist.consume(); if (key != Keyword.ALLOW_OTHER_KEYS) program_error("Invalid keyword argument " + key.printObject() + "."); allowOtherKeysValue = null; } if (allowOtherKeysValue != null) return array; } if (!arglist.consumed()) { if (restVar == null) error(new WrongNumberOfArgumentsException(function)); } return array; } } /** Function which creates initform instances. * * @param form * @return Either a ConstantInitform or NonConstantInitForm instance */ private static InitForm createInitForm(LispObject form) { if (form.constantp()) { if (form instanceof Symbol) return new ConstantInitForm(form.getSymbolValue()); if (form instanceof Cons) { Debug.assertTrue(form.car() == Symbol.QUOTE); return new ConstantInitForm(form.cadr()); } return new ConstantInitForm(form); } return new NonConstantInitForm(form); } /** Class to be passed around, allowing arguments to be 'consumed' from it. */ final private static class ArgList { final LispObject[] args; int argsConsumed = 0; final int len; final Environment env; ArgList(Environment environment, LispObject[] args) { this.args = args; len = args.length; env = environment; } /** Asserts the number of remaining arguments is even. */ void assertRemainderKeywords() { if (((len - argsConsumed) & 1) == 1) program_error("Odd number of keyword arguments."); } /** Returns the next unconsumed value from the argument set, or 'null' * if all arguments have been consumed. */ LispObject consume() { return (argsConsumed < len) ? args[argsConsumed++] : null; } /** Returns 'true' if all arguments have been consumed, false otherwise. */ boolean consumed() { return (len == argsConsumed); } /** Returns the value associated with 'keyword', or 'def' if the keyword * isn't in the remaining arguments. Assumes the remainder is a valid property list. */ LispObject findKeywordArg(Symbol keyword, LispObject def) { int i = argsConsumed; while (i < len) { if (args[i] == keyword) return args[i+1]; i += 2; } return def; } Environment getEnvironment() { // ### here to satisfy the need of the EnvironmentParam, but this // is a slight abuse of the abstraction. Don't want to solve more complex, // but don't really like it this way... return env; } /** Returns a list of all values not consumed so far. */ LispObject rest() { LispObject rest = NIL; for (int j = len; j-- > argsConsumed;) rest = new Cons(args[j], rest); return rest; } } /** Abstract parent of the classes used to represent the different argument types: * * - EnvironmentParam * - RequiredParam * - OptionalParam * - RestParam * - KeywordParam * - AuxParam * */ public static abstract class Param implements Serializable { /** Assigns values to be bound to the correcsponding variables to the * array, using 'index' as the next free slot, consuming any required * values from 'args'. Uses 'ext' both as the evaluation environment * for initforms. * * The environment 'ext' is prepared for evaluating any initforms of * further arguments by binding the variables to their values in it. * * The environment 'ext' may be null, indicating none of the arguments * need an evaluation environment. No attempt should be made to bind * any variables in this case. * * Returns the index of the next-unused slot in the 'array'. */ abstract int assign(int index, LispObject[] array, ArgList args, Environment ext, LispThread thread); /** Returns 'true' if the parameter requires an evaluation environment * in order to be able to determine the value of its initform. */ boolean needsEnvironment() { return false; } /** Adds the variables to be bound to 'vars' in the same order as they * will be assigned to the output array by the 'assign' method. */ abstract void addVars(List vars); } /** Abstract super class representing initforms. */ private static abstract class InitForm { abstract LispObject getValue(Environment ext, LispThread thread); boolean needsEnvironment() { return false; } } /** Constant init forms will be represented using this class. */ private static class ConstantInitForm extends InitForm { LispObject value; ConstantInitForm(LispObject value) { this.value = value; } LispObject getValue(Environment ext, LispThread thread) { return value; } } /** Non-constant initforms will be represented using this class. * Callers need to know these need an evaluation environment. */ private static class NonConstantInitForm extends InitForm { LispObject form; NonConstantInitForm(LispObject form) { this.form = form; } LispObject getValue(Environment ext, LispThread thread) { return eval(form, ext, thread); } @Override boolean needsEnvironment() { return true; } } /** Class used to match &environment arguments */ private static class EnvironmentParam extends Param { Symbol var; boolean special; EnvironmentParam(Symbol var, boolean special) { this.var = var; this.special = special; } @Override void addVars(List vars) { vars.add(var); } @Override int assign(int index, LispObject[] array, ArgList args, Environment ext, LispThread thread) { array[index++] = args.getEnvironment(); if (ext != null) bindArg(special, var, args.getEnvironment(), ext, thread); return index; } } /** Class used to match required parameters */ public static class RequiredParam extends Param { Symbol var; boolean special; // Used above to create anonymous required parameters public RequiredParam() { this(T, false); } public RequiredParam(Symbol var, boolean special) { this.var = var; this.special = special; } @Override int assign(int index, LispObject[] array, ArgList args, Environment ext, LispThread thread) { LispObject value = args.consume(); if (ext != null) bindArg(special, var, value, ext, thread); array[index++] = value; return index; } void addVars(List vars) { vars.add(var); } } /** Class used to match optional parameters, or, if not provided, * evaluate the initform. Also assigns the 'supplied-p' parameter if requested. */ public static class OptionalParam extends Param { Symbol var; boolean special; Symbol suppliedVar; boolean suppliedSpecial; InitForm initForm; public OptionalParam(boolean suppliedVar, LispObject form) { this(T, false, suppliedVar ? T : null, false, form); } public OptionalParam(Symbol var, boolean special, Symbol suppliedVar, boolean suppliedSpecial, LispObject form) { this.var = var; this.special = special; this.suppliedVar = suppliedVar; this.suppliedSpecial = suppliedSpecial; initForm = createInitForm(form); } @Override int assign(int index, LispObject[] array, ArgList args, Environment ext, LispThread thread) { LispObject value = args.consume(); return assign(index, array, value, ext, thread); } int assign(int index, LispObject[] array, LispObject value, Environment ext, LispThread thread) { if (value == null) { value = array[index++] = initForm.getValue(ext, thread); if (suppliedVar != null) array[index++] = NIL; } else { array[index++] = value; if (suppliedVar != null) array[index++] = T; } if (ext != null) { bindArg(special, var, value, ext, thread); if (suppliedVar != null) bindArg(suppliedSpecial, suppliedVar, array[index-1], ext, thread); } return index; } @Override boolean needsEnvironment() { return initForm.needsEnvironment(); } void addVars(List vars) { vars.add(var); if (suppliedVar != null) vars.add(suppliedVar); } } /** Class used to model the &rest parameter */ private static class RestParam extends Param { Symbol var; boolean special; RestParam(Symbol var, boolean special) { this.var = var; this.special = special; } @Override int assign(int index, LispObject[] array, ArgList args, Environment ext, LispThread thread) { array[index++] = args.rest(); if (ext != null) bindArg(special, var, array[index-1], ext, thread); return index; } @Override void addVars(List vars) { vars.add(var); } } /** Class used to represent optional parameters and their initforms */ public static class KeywordParam extends OptionalParam { public Symbol keyword; public KeywordParam(boolean suppliedVar, LispObject form, Symbol keyword) { this(T, false, suppliedVar ? T : null, false, form, keyword); } public KeywordParam(Symbol var, boolean special, Symbol suppliedVar, boolean suppliedSpecial, LispObject form, Symbol keyword) { super(var, special, suppliedVar, suppliedSpecial, form); this.keyword = (keyword == null) ? PACKAGE_KEYWORD.intern(var.getName()) : keyword; } @Override int assign(int index, LispObject[] array, ArgList args, Environment ext, LispThread thread) { return super.assign(index, array, args.findKeywordArg(keyword, null), ext, thread); } } /** Class used to represent &aux parameters and their initforms */ private static class AuxParam extends Param { Symbol var; boolean special; InitForm initform; AuxParam(Symbol var, boolean special, LispObject form) { this.var = var; this.special = special; initform = createInitForm(form); } @Override void addVars(List vars) { vars.add(var); } @Override int assign(int index, LispObject[] array, ArgList args, Environment ext, LispThread thread) { array[index++] = initform.getValue(ext, thread); if (ext != null) bindArg(special, var, array[index-1], ext, thread); return index; } @Override boolean needsEnvironment() { return initform.needsEnvironment(); } } } abcl-src-1.9.0/src/org/armedbear/lisp/ArithmeticError.java0100644 0000000 0000000 00000011217 14202767264 022167 0ustar000000000 0000000 /* * ArithmeticError.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class ArithmeticError extends LispError { protected ArithmeticError(LispClass cls) { super(cls); } public ArithmeticError(LispObject initArgs) { super(StandardClass.ARITHMETIC_ERROR); initialize(initArgs); } @Override protected void initialize(LispObject initArgs) { super.initialize(initArgs); LispObject operation = NIL; LispObject operands = NIL; LispObject first, second; while (initArgs != NIL) { first = initArgs.car(); initArgs = initArgs.cdr(); second = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.OPERATION) operation = second; else if (first == Keyword.OPERANDS) operands = second; } setOperation(operation); setOperands(operands); } public ArithmeticError(String message) { super(StandardClass.ARITHMETIC_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); setOperation(NIL); setOperands(NIL); } @Override public LispObject typeOf() { return Symbol.ARITHMETIC_ERROR; } @Override public LispObject classOf() { return StandardClass.ARITHMETIC_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.ARITHMETIC_ERROR) return T; if (type == StandardClass.ARITHMETIC_ERROR) return T; return super.typep(type); } final LispObject getOperation() { return getInstanceSlotValue(Symbol.OPERATION); } private final void setOperation(LispObject operation) { setInstanceSlotValue(Symbol.OPERATION, operation); } final LispObject getOperands() { return getInstanceSlotValue(Symbol.OPERANDS); } private final void setOperands(LispObject operands) { setInstanceSlotValue(Symbol.OPERANDS, operands); } // ### arithmetic-error-operation private static final Primitive ARITHMETIC_ERROR_OPERATION = new Primitive("arithmetic-error-operation", "condition") { @Override public LispObject execute(LispObject arg) { if (arg.typep(Symbol.ARITHMETIC_ERROR) == NIL) { return type_error(arg, Symbol.ARITHMETIC_ERROR); } final StandardObject obj = (StandardObject) arg; return obj.getInstanceSlotValue(Symbol.OPERATION); } }; // ### arithmetic-error-operands private static final Primitive ARITHMETIC_ERROR_OPERANDS = new Primitive("arithmetic-error-operands", "condition") { @Override public LispObject execute(LispObject arg) { if (arg.typep(Symbol.ARITHMETIC_ERROR) == NIL) { return type_error(arg, Symbol.ARITHMETIC_ERROR); } final StandardObject obj = (StandardObject) arg; return obj.getInstanceSlotValue(Symbol.OPERANDS); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Autoload.java0100644 0000000 0000000 00000076464 14223403213 020633 0ustar000000000 0000000 /* * Autoload.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; /** See autoloads.lisp for a general explanation of what we're * trying to achieve here. */ public class Autoload extends Function { protected final String fileName; protected final String className; protected final Symbol symbol; protected Autoload(Symbol symbol) { super(); fileName = null; className = null; this.symbol = symbol; symbol.setBuiltInFunction(false); } protected Autoload(Symbol symbol, String fileName, String className) { super(); this.fileName = fileName; this.className = className; this.symbol = symbol; symbol.setBuiltInFunction(false); } protected final Symbol getSymbol() { return symbol; } public static void autoload(String symbolName, String className) { autoload(PACKAGE_CL, symbolName, className); } public static void autoload(Package pkg, String symbolName, String className) { autoload(pkg, symbolName, className, false); } public static void autoload(Package pkg, String symbolName, String className, boolean exported) { Symbol symbol = intern(symbolName.toUpperCase(), pkg); if (pkg != PACKAGE_CL && exported) { pkg.export(symbol); } if (symbol.getSymbolFunction() == null) symbol.setSymbolFunction(new Autoload(symbol, null, "org.armedbear.lisp.".concat(className))); } public static void autoload(Symbol symbol, String className) { if (symbol.getSymbolFunction() == null) symbol.setSymbolFunction(new Autoload(symbol, null, "org.armedbear.lisp.".concat(className))); } private static void effectiveLoad(String className, String fileName) { if (className != null) { try { Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } } else { Load.loadSystemFile(fileName, true); } } private static void loadVerbose(Symbol sym, int loadDepth, String className, String fileName) { final String prefix = Load.getLoadVerbosePrefix(loadDepth); Stream out = getStandardOutput(); out._writeString(prefix); out._writeString(sym.getQualifiedName() + " triggers autoloading of "); out._writeString(className == null ? fileName : className); out._writeLine(" ..."); out._finishOutput(); long start = System.currentTimeMillis(); effectiveLoad(className, fileName); long elapsed = System.currentTimeMillis() - start; out._writeString(prefix); out._writeString(" Autoloaded "); out._writeString(className == null ? fileName : className); out._writeString(" ("); out._writeString(String.valueOf(((float)elapsed)/1000)); out._writeLine(" seconds)"); out._finishOutput(); } public void load() { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); int loadDepth = Fixnum.getValue(_LOAD_DEPTH_.symbolValue()); thread.bindSpecial(_LOAD_DEPTH_, Fixnum.getInstance(++loadDepth)); try { if (_AUTOLOAD_VERBOSE_.symbolValue(thread) != NIL || "Y".equals(System.getProperty("abcl.autoload.verbose"))) { loadVerbose(symbol, loadDepth, className, getFileName()); } else effectiveLoad(className, getFileName()); } finally { thread.resetSpecialBindings(mark); } // if (debug) { if (symbol != null) { if (symbol.getSymbolFunction() instanceof Autoload) { simple_error("Unable to autoload " + symbol.princToString(), symbol, fileName, className); } } // end if (debug) } protected final String getFileName() { if (fileName != null) return fileName; return symbol.getName().toLowerCase(); } @Override public LispObject execute() { load(); return symbol.execute(); } @Override public LispObject execute(LispObject arg) { load(); return symbol.execute(arg); } @Override public LispObject execute(LispObject first, LispObject second) { load(); return symbol.execute(first, second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { load(); return symbol.execute(first, second, third); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { load(); return symbol.execute(first, second, third, fourth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { load(); return symbol.execute(first, second, third, fourth, fifth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { load(); return symbol.execute(first, second, third, fourth, fifth, sixth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { load(); return symbol.execute(first, second, third, fourth, fifth, sixth, seventh); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { load(); return symbol.execute(first, second, third, fourth, fifth, sixth, seventh, eighth); } @Override public LispObject execute(LispObject[] args) { load(); return symbol.execute(args); } @Override public String printObject() { StringBuilder sb = new StringBuilder(); sb.append(symbol.princToString()); sb.append(" stub to be autoloaded from \""); if (className != null) { int index = className.lastIndexOf('.'); if (index >= 0) sb.append(className.substring(index + 1)); else sb.append(className); sb.append(".class"); } else sb.append(getFileName()); sb.append("\""); return unreadableString(sb.toString()); } public static final Primitive AUTOLOAD = new pf_autoload(); @DocString(name="autoload", args="symbol-or-symbols &optional filename", doc="Setup the autoload for SYMBOL-OR-SYMBOLS optionally corresponding to FILENAME.") private static final class pf_autoload extends Primitive { pf_autoload() { super("autoload", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject first) { if (first instanceof Symbol) { Symbol symbol = (Symbol) first; symbol.setSymbolFunction(new Autoload(symbol)); return T; } if (first instanceof Cons) { for (LispObject list = first; list != NIL; list = list.cdr()) { Symbol symbol = checkSymbol(list.car()); symbol.setSymbolFunction(new Autoload(symbol)); } return T; } return error(new TypeError(first)); } @Override public LispObject execute(LispObject first, LispObject second) { final String fileName = second.getStringValue(); if (first instanceof Symbol) { Symbol symbol = (Symbol) first; symbol.setSymbolFunction(new Autoload(symbol, fileName, null)); return T; } if (first instanceof Cons) { for (LispObject list = first; list != NIL; list = list.cdr()) { Symbol symbol = checkSymbol(list.car()); symbol.setSymbolFunction(new Autoload(symbol, fileName, null)); } return T; } return error(new TypeError(first)); } }; public static final Primitive RESOLVE = new pf_resolve(); @DocString(name="resolve", args="symbol", doc="Resolve the function named by SYMBOL via the autoloader mechanism.\n" + "Returns either the function or NIL if no resolution was possible.") private static final class pf_resolve extends Primitive { pf_resolve() { super("resolve", PACKAGE_EXT, true, "symbol"); } @Override public LispObject execute(LispObject arg) { Symbol symbol = checkSymbol(arg); LispObject fun = symbol.getSymbolFunction(); if (fun instanceof Autoload) { Autoload autoload = (Autoload) fun; autoload.load(); return symbol.getSymbolFunction(); } return ((fun == null) ? NIL : fun); } } public static final Primitive AUTOLOADP = new pf_autoloadp(); @DocString(name="autoloadp", args="symbol", doc="Boolean predicate for whether SYMBOL stands for a function that currently needs to be autoloaded.") private static final class pf_autoloadp extends Primitive { pf_autoloadp() { super("autoloadp", PACKAGE_EXT, true, "symbol"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Symbol) { if (arg.getSymbolFunction() instanceof Autoload) return T; } return NIL; } }; static { autoload("acos", "MathFunctions"); autoload("acosh", "MathFunctions"); autoload("arithmetic-error-operands", "ArithmeticError"); autoload("arithmetic-error-operation", "ArithmeticError"); autoload("ash", "ash"); autoload("asin", "MathFunctions"); autoload("asinh", "MathFunctions"); autoload("atan", "MathFunctions"); autoload("atanh", "MathFunctions"); autoload("broadcast-stream-streams", "BroadcastStream"); autoload("ceiling", "ceiling"); autoload("char", "StringFunctions"); autoload("char-equal", "CharacterFunctions"); autoload("char-greaterp", "CharacterFunctions"); autoload("char-lessp", "CharacterFunctions"); autoload("char-not-greaterp", "CharacterFunctions"); autoload("char-not-lessp", "CharacterFunctions"); autoload("char<", "CharacterFunctions"); autoload("char<=", "CharacterFunctions"); autoload("char=", "CharacterFunctions"); autoload("cis", "MathFunctions"); autoload("clrhash", "HashTableFunctions"); autoload("clrhash", "HashTableFunctions"); autoload("concatenated-stream-streams", "ConcatenatedStream"); autoload("cos", "MathFunctions"); autoload("cosh", "MathFunctions"); autoload("delete-file", "delete_file"); autoload(PACKAGE_SYS, "%delete-package", "PackageFunctions"); autoload("echo-stream-input-stream", "EchoStream"); autoload("echo-stream-output-stream", "EchoStream"); autoload("exp", "MathFunctions"); autoload("expt", "MathFunctions"); autoload("file-author", "file_author"); autoload("file-length", "file_length"); autoload("file-string-length", "file_string_length"); autoload("file-write-date", "file_write_date"); autoload("float", "FloatFunctions"); autoload("float-digits", "FloatFunctions"); autoload("float-radix", "FloatFunctions"); autoload("float-sign", "float_sign"); autoload("floatp", "FloatFunctions"); autoload("floor", "floor"); autoload("ftruncate", "ftruncate"); autoload("get-internal-real-time", "Time"); autoload("get-internal-run-time", "Time"); autoload("get-output-stream-string", "StringOutputStream"); autoload("get-properties", "get_properties"); autoload("get-universal-time", "Time"); autoload("gethash", "HashTableFunctions"); autoload("gethash", "HashTableFunctions"); autoload("hash-table-count", "HashTableFunctions"); autoload("hash-table-count", "HashTableFunctions"); autoload("hash-table-p", "HashTableFunctions"); autoload("hash-table-p", "HashTableFunctions"); autoload("hash-table-rehash-size", "HashTableFunctions"); autoload("hash-table-rehash-size", "HashTableFunctions"); autoload("hash-table-rehash-threshold", "HashTableFunctions"); autoload("hash-table-rehash-threshold", "HashTableFunctions"); autoload("hash-table-size", "HashTableFunctions"); autoload("hash-table-size", "HashTableFunctions"); autoload("hash-table-test", "HashTableFunctions"); autoload("hash-table-test", "HashTableFunctions"); autoload(PACKAGE_SYS, "%import", "PackageFunctions"); autoload("input-stream-p", "input_stream_p"); autoload("integer-decode-float", "FloatFunctions"); autoload("interactive-stream-p", "interactive_stream_p"); autoload("last", "last"); autoload("lisp-implementation-type", "lisp_implementation_type"); autoload("lisp-implementation-version", "lisp_implementation_version"); autoload("list-all-packages", "PackageFunctions"); autoload("listen", "listen"); autoload("log", "MathFunctions"); autoload("logand", "logand"); autoload("logandc1", "logandc1"); autoload("logandc2", "logandc2"); autoload("logbitp", "logbitp"); autoload("logcount", "logcount"); autoload("logeqv", "logeqv"); autoload("logior", "logior"); autoload("lognand", "lognand"); autoload("lognor", "lognor"); autoload("lognot", "lognot"); autoload("logorc1", "logorc1"); autoload("logorc2", "logorc2"); autoload("logtest", "logtest"); autoload("logxor", "logxor"); autoload("long-site-name", "SiteName"); autoload("machine-instance", "SiteName"); autoload("machine-type", "machine_type"); autoload("machine-version", "machine_version"); autoload("make-broadcast-stream", "BroadcastStream"); autoload("make-concatenated-stream", "ConcatenatedStream"); autoload("make-echo-stream", "EchoStream"); autoload("make-string-input-stream", "StringInputStream"); autoload("make-synonym-stream", "SynonymStream"); autoload("maphash", "HashTableFunctions"); autoload("mod", "mod"); autoload("open-stream-p", "open_stream_p"); autoload("output-stream-p", "output_stream_p"); autoload("package-name", "PackageFunctions"); autoload("package-nicknames", "PackageFunctions"); autoload("package-shadowing-symbols", "PackageFunctions"); autoload("package-use-list", "PackageFunctions"); autoload("package-used-by-list", "PackageFunctions"); autoload("packagep", "PackageFunctions"); autoload("peek-char", "peek_char"); autoload("print-not-readable-object", "PrintNotReadable"); autoload("probe-file", "probe_file"); autoload("rational", "FloatFunctions"); autoload("rem", "rem"); autoload("remhash", "HashTableFunctions"); autoload("remhash", "HashTableFunctions"); autoload("rename-package", "PackageFunctions"); autoload("room", "room"); autoload("scale-float", "FloatFunctions"); autoload("schar", "StringFunctions"); autoload("shadow", "PackageFunctions"); autoload("shadowing-import", "PackageFunctions"); autoload("short-site-name", "SiteName"); autoload("simple-condition-format-arguments", "SimpleCondition"); autoload("simple-condition-format-control", "SimpleCondition"); autoload("simple-string-p", "StringFunctions"); autoload("sin", "MathFunctions"); autoload("sinh", "MathFunctions"); autoload("software-type", "software_type"); autoload("software-version", "software_version"); autoload("sqrt", "MathFunctions"); autoload("stream-element-type", "stream_element_type"); autoload("stream-error-stream", "StreamError"); autoload("stream-external-format", "stream_external_format"); autoload(PACKAGE_SYS, "%set-stream-external-format", "Stream"); autoload("stringp", "StringFunctions"); autoload("sxhash", "HashTableFunctions"); autoload("sxhash", "HashTableFunctions"); autoload("synonym-stream-symbol", "SynonymStream"); autoload("tan", "MathFunctions"); autoload("tanh", "MathFunctions"); autoload("truename", "probe_file"); autoload("truncate", "truncate"); autoload("type-error-datum", "TypeError"); autoload("type-error-expected-type", "TypeError"); autoload("unbound-slot-instance", "unbound_slot_instance"); autoload("unexport", "PackageFunctions"); autoload("unuse-package", "PackageFunctions"); autoload(PACKAGE_EXT, "arglist", "arglist", true); autoload(PACKAGE_EXT, "assq", "assq", true); autoload(PACKAGE_EXT, "assql", "assql", true); autoload(PACKAGE_EXT, "file-directory-p", "probe_file", true); autoload(PACKAGE_EXT, "gc", "gc", true); autoload(PACKAGE_EXT, "get-floating-point-modes", "FloatFunctions", true); autoload(PACKAGE_EXT, "get-time-zone", "Time", true); autoload(PACKAGE_EXT, "make-slime-input-stream", "SlimeInputStream", true); autoload(PACKAGE_EXT, "make-slime-output-stream", "SlimeOutputStream", true); autoload(PACKAGE_EXT, "probe-directory", "probe_file", true); autoload(PACKAGE_EXT, "set-floating-point-modes", "FloatFunctions", true); autoload(PACKAGE_EXT, "simple-string-fill", "StringFunctions"); autoload(PACKAGE_EXT, "simple-string-search", "StringFunctions"); autoload(PACKAGE_EXT, "string-input-stream-current", "StringInputStream", true); autoload(PACKAGE_EXT, "string-find", "StringFunctions"); autoload(PACKAGE_EXT, "string-position", "StringFunctions"); autoload(PACKAGE_EXT, "make-weak-reference", "WeakReference", true); autoload(PACKAGE_EXT, "weak-reference-value", "WeakReference", true); autoload(PACKAGE_EXT, "finalize", "Primitives", true); autoload(PACKAGE_EXT, "cancel-finalization", "Primitives", true); autoload(PACKAGE_JAVA, "%jnew-proxy", "JProxy"); autoload(PACKAGE_JAVA, "%find-java-class", "JavaObject"); autoload(PACKAGE_JAVA, "%register-java-class", "JavaObject"); autoload(PACKAGE_JAVA, "%jmake-invocation-handler", "JProxy"); autoload(PACKAGE_JAVA, "%jmake-proxy", "JProxy"); autoload(PACKAGE_JAVA, "%jnew-runtime-class", "RuntimeClass"); autoload(PACKAGE_JAVA, "%jredefine-method", "RuntimeClass"); autoload(PACKAGE_JAVA, "%jregister-handler", "JHandler"); autoload(PACKAGE_JAVA, "%load-java-class-from-byte-array", "RuntimeClass"); autoload(PACKAGE_JAVA, "get-default-classloader", "JavaClassLoader"); autoload(PACKAGE_JAVA, "make-classloader", "JavaClassLoader"); autoload(PACKAGE_JAVA, "%add-to-classpath", "JavaClassLoader"); autoload(PACKAGE_JAVA, "dump-classpath", "JavaClassLoader"); autoload(PACKAGE_MOP, "eql-specializer-object", "EqualSpecializerObject", true); autoload(PACKAGE_MOP, "funcallable-instance-function", "FuncallableStandardObject", false); autoload(PACKAGE_MOP, "set-funcallable-instance-function", "FuncallableStandardObject", true); autoload(PACKAGE_PROF, "%start-profiler", "Profiler", true); autoload(PACKAGE_PROF, "stop-profiler", "Profiler", true); autoload(PACKAGE_SYS, "%%string=", "StringFunctions"); autoload(PACKAGE_SYS, "%adjust-array", "adjust_array"); autoload(PACKAGE_SYS, "%defpackage", "PackageFunctions"); autoload(PACKAGE_SYS, "%get-output-stream-bytes", "ByteArrayOutputStream"); //AS 20090325 autoload(PACKAGE_SYS, "%get-output-stream-array", "ByteArrayOutputStream"); autoload(PACKAGE_SYS, "%make-array", "make_array"); autoload(PACKAGE_SYS, "%make-byte-array-input-stream", "ByteArrayInputStream"); //AS 20100317 autoload(PACKAGE_SYS, "%make-byte-array-output-stream", "ByteArrayOutputStream"); //AS 20090325 autoload(PACKAGE_SYS, "%make-condition", "make_condition", true); autoload(PACKAGE_SYS, "%make-emf-cache", "EMFCache", true); autoload(PACKAGE_SYS, "%make-hash-table", "HashTableFunctions"); autoload(PACKAGE_SYS, "%make-hash-table", "HashTableFunctions"); autoload(PACKAGE_SYS, "%make-logical-pathname", "LogicalPathname", true); autoload(PACKAGE_SYS, "%make-server-socket", "make_server_socket"); autoload(PACKAGE_SYS, "%make-socket", "make_socket"); autoload(PACKAGE_SYS, "%make-string", "StringFunctions"); autoload(PACKAGE_SYS, "%make-string-output-stream", "StringOutputStream"); autoload(PACKAGE_SYS, "%nstring-capitalize", "StringFunctions"); autoload(PACKAGE_SYS, "%nstring-downcase", "StringFunctions"); autoload(PACKAGE_SYS, "%nstring-upcase", "StringFunctions"); autoload(PACKAGE_SYS, "%reinit-emf-cache", "EMFCache", true); autoload(PACKAGE_SYS, "%run-shell-command", "ShellCommand"); autoload(PACKAGE_SYS, "%server-socket-close", "server_socket_close"); autoload(PACKAGE_SYS, "%set-arglist", "arglist"); autoload(PACKAGE_CL, "find-class", "LispClass", true); autoload(PACKAGE_SYS, "%set-find-class", "LispClass", true); autoload(PACKAGE_SYS, "%set-class-direct-slots", "SlotClass", true); autoload(PACKAGE_SYS, "%set-function-info", "function_info"); autoload(PACKAGE_SYS, "%set-symbol-macro", "Primitives"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-and", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-andc1", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-andc2", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-eqv", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-ior", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-nand", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-nor", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-not", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-orc1", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-orc2", "SimpleBitVector"); autoload(PACKAGE_SYS, "%simple-bit-vector-bit-xor", "SimpleBitVector"); autoload(PACKAGE_SYS, "%socket-accept", "socket_accept"); autoload(PACKAGE_SYS, "%socket-close", "socket_close"); autoload(PACKAGE_SYS, "%socket-stream", "socket_stream"); autoload(PACKAGE_SYS, "%string-capitalize", "StringFunctions"); autoload(PACKAGE_SYS, "%string-downcase", "StringFunctions"); autoload(PACKAGE_SYS, "%string-equal", "StringFunctions"); autoload(PACKAGE_SYS, "%string-greaterp", "StringFunctions"); autoload(PACKAGE_SYS, "%string-lessp", "StringFunctions"); autoload(PACKAGE_SYS, "%string-not-equal", "StringFunctions"); autoload(PACKAGE_SYS, "%string-not-greaterp", "StringFunctions"); autoload(PACKAGE_SYS, "%string-not-lessp", "StringFunctions"); autoload(PACKAGE_SYS, "%string-upcase", "StringFunctions"); autoload(PACKAGE_SYS, "%string/=", "StringFunctions"); autoload(PACKAGE_SYS, "%string<", "StringFunctions"); autoload(PACKAGE_SYS, "%string<=", "StringFunctions"); autoload(PACKAGE_SYS, "%string=", "StringFunctions"); autoload(PACKAGE_SYS, "%string>", "StringFunctions"); autoload(PACKAGE_SYS, "%string>=", "StringFunctions"); autoload(PACKAGE_SYS, "%time", "Time"); autoload(PACKAGE_SYS, "cache-emf", "EMFCache", true); autoload(PACKAGE_SYS, "canonicalize-logical-host", "LogicalPathname", true); autoload(PACKAGE_SYS, "%class-direct-slots", "SlotClass"); autoload(PACKAGE_SYS, "%float-bits", "FloatFunctions"); autoload(PACKAGE_SYS, "coerce-to-double-float", "FloatFunctions"); autoload(PACKAGE_SYS, "coerce-to-single-float", "FloatFunctions"); autoload(PACKAGE_SYS, "create-new-file", "create_new_file"); autoload(PACKAGE_SYS, "default-time-zone", "Time"); autoload(PACKAGE_SYS, "disassemble-class-bytes", "disassemble_class_bytes", true); autoload(PACKAGE_SYS, "disable-zip-cache", "ZipCache", true); autoload(PACKAGE_SYS, "double-float-high-bits", "FloatFunctions", true); autoload(PACKAGE_SYS, "double-float-low-bits", "FloatFunctions", true); autoload(PACKAGE_SYS, "float-infinity-p", "FloatFunctions", true); autoload(PACKAGE_SYS, "float-nan-p", "FloatFunctions", true); autoload(PACKAGE_SYS, "float-string", "FloatFunctions", true); autoload(PACKAGE_SYS, "function-info", "function_info"); autoload(PACKAGE_SYS, "get-cached-emf", "EMFCache", true); autoload(PACKAGE_SYS, "get-function-info-value", "function_info"); autoload(PACKAGE_SYS, "hash-table-entries", "HashTableFunctions"); autoload(PACKAGE_SYS, "hash-table-entries", "HashTableFunctions"); autoload(PACKAGE_SYS, "layout-class", "Layout", true); autoload(PACKAGE_SYS, "layout-length", "Layout", true); autoload(PACKAGE_SYS, "layout-slot-index", "Layout", true); autoload(PACKAGE_SYS, "layout-slot-location", "Layout", true); autoload(PACKAGE_SYS, "make-case-frob-stream", "CaseFrobStream"); autoload(PACKAGE_SYS, "make-double-float", "FloatFunctions", true); autoload(PACKAGE_SYS, "make-file-stream", "FileStream"); autoload(PACKAGE_SYS, "make-fill-pointer-output-stream", "FillPointerOutputStream"); autoload(PACKAGE_SYS, "make-layout", "Layout", true); autoload(PACKAGE_SYS, "make-single-float", "FloatFunctions", true); autoload(PACKAGE_SYS, "%make-slot-definition", "SlotDefinition", true); autoload(PACKAGE_SYS, "make-structure-class", "StructureClass"); autoload(PACKAGE_SYS, "make-symbol-macro", "Primitives"); autoload(PACKAGE_SYS, "psxhash", "HashTableFunctions"); autoload(PACKAGE_SYS, "puthash", "HashTableFunctions"); autoload(PACKAGE_SYS, "puthash", "HashTableFunctions"); autoload(PACKAGE_SYS, "remove-zip-cache-entry", "ZipCache"); autoload(PACKAGE_SYS, "set-function-info-value", "function_info"); autoload(PACKAGE_SYS, "simple-list-remove-duplicates", "simple_list_remove_duplicates"); autoload(PACKAGE_SYS, "single-float-bits", "FloatFunctions", true); autoload(PACKAGE_SYS, "%std-allocate-instance", "StandardObject", true); autoload(PACKAGE_SYS, "swap-slots", "StandardObject", true); autoload(PACKAGE_SYS, "std-instance-layout", "StandardObject", true); autoload(PACKAGE_SYS, "%set-std-instance-layout", "StandardObject", true); autoload(PACKAGE_SYS, "std-instance-class", "StandardObject", true); autoload(PACKAGE_SYS, "standard-instance-access", "StandardObject", true); autoload(PACKAGE_SYS, "%set-standard-instance-access", "StandardObject", true); autoload(PACKAGE_SYS, "std-slot-boundp", "StandardObject", true); autoload(PACKAGE_SYS, "std-slot-value", "StandardObject", true); autoload(PACKAGE_SYS, "set-std-slot-value", "StandardObject", true); autoload(PACKAGE_SYS, "%allocate-funcallable-instance", "FuncallableStandardObject", true); autoload(PACKAGE_SYS, "unzip", "unzip", true); autoload(PACKAGE_SYS, "zip", "zip", true); autoload(Symbol.COPY_LIST, "copy_list"); autoload(PACKAGE_SYS, "make-fasl-class-loader", "FaslClassLoader", false); autoload(PACKAGE_SYS, "get-fasl-function", "FaslClassLoader", false); autoload(PACKAGE_SYS, "make-memory-class-loader", "MemoryClassLoader", false); autoload(PACKAGE_SYS, "put-memory-function", "MemoryClassLoader", false); autoload(PACKAGE_SYS, "get-memory-function", "MemoryClassLoader", false); autoload(Symbol.SET_CHAR, "StringFunctions"); autoload(Symbol.SET_SCHAR, "StringFunctions"); autoload(Symbol._SET_CLASS_SLOTS, "SlotClass"); autoload(Symbol._CLASS_SLOTS, "SlotClass"); autoload(Symbol.JAVA_EXCEPTION_CAUSE, "JavaException"); autoload(Symbol.JCLASS_NAME, "jclass_name"); autoload(Symbol.JCLASS_OF, "jclass_of"); autoload(Symbol.JMETHOD_RETURN_TYPE, "jmethod_return_type"); autoload(PACKAGE_JAVA, "%jget-property-value", "JavaBeans", false); autoload(PACKAGE_JAVA, "%jset-property-value", "JavaBeans", false); autoload(PACKAGE_EXT, "autoload-setf-expander", "AutoloadGeneralizedReference", true); autoload(PACKAGE_EXT, "autoload-setf-function", "AutoloadGeneralizedReference", true); autoload(PACKAGE_EXT, "autoload-ref-p", "AutoloadGeneralizedReference", true); } } abcl-src-1.9.0/src/org/armedbear/lisp/AutoloadGeneralizedReference.java0100644 0000000 0000000 00000017002 14202767264 024623 0ustar000000000 0000000 /* * AutoloadGeneralizedReference.java * * Copyright (C) 2014 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class AutoloadGeneralizedReference extends Autoload { Symbol indicator; private AutoloadGeneralizedReference(Symbol symbol, Symbol indicator, String filename) { super(symbol, filename, null); this.indicator = indicator; } @Override public void load() { Load.loadSystemFile(getFileName(), true); } static final Symbol SETF_EXPANDER = PACKAGE_SYS.intern("SETF-EXPANDER"); public static final Primitive AUTOLOAD_SETF_EXPANDER = new pf_autoload_setf_expander(); @DocString( name="autoload-setf-expander", args="symbol-or-symbols filename", doc="Setup the autoload for SYMBOL-OR-SYMBOLS on the setf-expander from FILENAME." ) private static final class pf_autoload_setf_expander extends Primitive { pf_autoload_setf_expander() { super("autoload-setf-expander", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject first, LispObject second) { final String filename = second.getStringValue(); return installAutoloadGeneralizedReference(first, SETF_EXPANDER, filename); } }; static final Symbol SETF_FUNCTION = PACKAGE_SYS.intern("SETF-FUNCTION"); public static final Primitive AUTOLOAD_SETF_FUNCTION = new pf_autoload_setf_function(); @DocString( name="autoload-setf-function", args="symbol-or-symbols filename", doc="Setup the autoload for SYMBOL-OR-SYMBOLS on the setf-function from FILENAME." ) private static final class pf_autoload_setf_function extends Primitive { pf_autoload_setf_function() { super("autoload-setf-function", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject first, LispObject second) { final String filename = second.getStringValue(); return installAutoloadGeneralizedReference(first, SETF_FUNCTION, filename); } }; public static final Primitive AUTOLOAD_REF_P = new pf_autoload_ref_p(); @DocString( name="autoload-ref-p", args="symbol", doc="Boolean predicate for whether SYMBOL has generalized reference functions which need to be resolved." ) private static final class pf_autoload_ref_p extends Primitive { pf_autoload_ref_p() { super("autoload-ref-p", PACKAGE_EXT, true, "symbol"); } @Override public LispObject execute(LispObject arg) { LispObject list = checkSymbol(arg).getPropertyList(); while (list != NIL) { if (list.car() instanceof AutoloadGeneralizedReference) { return T; } list = list.cdr(); } return NIL; } }; private static final LispObject installAutoloadGeneralizedReference(LispObject first, Symbol indicator, String filename) { if (first instanceof Symbol) { Symbol symbol = checkSymbol(first); install(symbol, indicator, filename); return T; } if (first instanceof Cons) { for (LispObject list = first; list != NIL; list = list.cdr()) { Symbol symbol = checkSymbol(list.car()); install(symbol, indicator, filename); } return T; } return error(new TypeError(first)); } private static LispObject install(Symbol symbol, Symbol indicator, String filename) { if (get(symbol, indicator) == NIL) { return Primitives.PUT.execute(symbol, indicator, new AutoloadGeneralizedReference(symbol, indicator, filename)); } else { return NIL; } } @Override public LispObject execute() { load(); return get(symbol, indicator, null).execute(); } @Override public LispObject execute(LispObject arg) { load(); return get(symbol, indicator, null).execute(arg); } @Override public LispObject execute(LispObject first, LispObject second) { load(); return get(symbol, indicator, null).execute(first, second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { load(); return get(symbol, indicator, null).execute(first, second, third); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { load(); return get(symbol, indicator, null).execute(first, second, third, fourth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { load(); return get(symbol, indicator, null).execute(first, second, third, fourth, fifth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { load(); return get(symbol, indicator, null).execute(first, second, third, fourth, fifth, sixth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { load(); return symbol.execute(first, second, third, fourth, fifth, sixth, seventh); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { load(); return get(symbol, indicator, null).execute(first, second, third, fourth, fifth, sixth, seventh, eighth); } @Override public LispObject execute(LispObject[] args) { load(); return get(symbol, indicator, null).execute(args); } } abcl-src-1.9.0/src/org/armedbear/lisp/AutoloadMacro.java0100644 0000000 0000000 00000007663 14202767264 021630 0ustar000000000 0000000 /* * AutoloadMacro.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class AutoloadMacro extends Autoload { private AutoloadMacro(Symbol symbol) { super(symbol); } private AutoloadMacro(Symbol symbol, String fileName) { super(symbol, fileName, null); } static void installAutoloadMacro(Symbol symbol, String fileName) { AutoloadMacro am = new AutoloadMacro(symbol, fileName); if (symbol.getSymbolFunction() instanceof SpecialOperator) put(symbol, Symbol.MACROEXPAND_MACRO, am); else symbol.setSymbolFunction(am); } @Override public void load() { Load.loadSystemFile(getFileName(), true); } @Override public String printObject() { StringBuilder sb = new StringBuilder(); sb.append(getSymbol().princToString()); sb.append(" \""); sb.append(getFileName()); return unreadableString(sb.toString()); } // ### autoload-macro private static final Primitive AUTOLOAD_MACRO = new Primitive("autoload-macro", PACKAGE_EXT, true) { @Override public LispObject execute(LispObject first) { if (first instanceof Symbol) { Symbol symbol = (Symbol) first; installAutoloadMacro(symbol, null); return T; } if (first instanceof Cons) { for (LispObject list = first; list != NIL; list = list.cdr()) { Symbol symbol = checkSymbol(list.car()); installAutoloadMacro(symbol, null); } return T; } return error(new TypeError(first)); } @Override public LispObject execute(LispObject first, LispObject second) { final String fileName = second.getStringValue(); if (first instanceof Symbol) { Symbol symbol = (Symbol) first; installAutoloadMacro(symbol, fileName); return T; } if (first instanceof Cons) { for (LispObject list = first; list != NIL; list = list.cdr()) { Symbol symbol = checkSymbol(list.car()); installAutoloadMacro(symbol, fileName); } return T; } return error(new TypeError(first)); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/BasicVector_ByteBuffer.java0100644 0000000 0000000 00000022650 14202767264 023410 0ustar000000000 0000000 /* * BasicVector_ByteBuffer.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; import java.nio.BufferOverflowException; // A basic vector is a specialized vector that is not displaced to another // array, has no fill pointer, and is not expressly adjustable. public final class BasicVector_ByteBuffer extends AbstractVector { private int capacity; private ByteBuffer elements; private boolean directAllocation; public BasicVector_ByteBuffer(int capacity) { this(capacity, false); } public BasicVector_ByteBuffer(int capacity, boolean directAllocation) { this.directAllocation = directAllocation; if (directAllocation) { elements = ByteBuffer.allocateDirect(capacity); } else { elements = ByteBuffer.allocate(capacity); } this.capacity = capacity; } public BasicVector_ByteBuffer(byte[] array, boolean directAllocation) { capacity = array.length; this.directAllocation = directAllocation; elements = ByteBuffer.wrap(array); // ??? Note somehow that we were constructed from a wrapped primitive array } public BasicVector_ByteBuffer(LispObject[] array, boolean directAllocation) { // FIXME: for now we assume that we're being handled an array of // primitive bytes this.directAllocation = directAllocation; capacity = array.length; if (directAllocation) { elements = ByteBuffer.allocateDirect(array.length); } else { elements = ByteBuffer.allocate(array.length); } for (int i = array.length; i-- > 0;) { // Faster please! elements.put(i, (byte)coerceToJavaByte(array[i])); } } public BasicVector_ByteBuffer(ByteBuffer buffer, boolean directAllocation) { elements = buffer; this.directAllocation = directAllocation; capacity = ((java.nio.Buffer)buffer).limit(); } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_8, new Cons(Fixnum.getInstance(capacity))); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_8; } @Override public boolean isSimpleVector() { return false; } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return capacity; } @Override public LispObject elt(int index) { try { return coerceFromJavaByte(elements.get(index)); } catch (IndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public int aref(int index) { try { return (((int)elements.get(index) & 0xff)); // XXX Hmmm } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); // Not reached. return 0; } } @Override public LispObject AREF(int index) { try { return coerceFromJavaByte(elements.get(index)); } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); return NIL; // Not reached. } } @Override public void aset(int index, int n) { try { elements.put(index, (byte) n); } catch (IndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public void aset(int index, LispObject value) { try { elements.put(index, coerceToJavaByte(value)); } catch (IndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public LispObject subseq(int start, int end) { // ??? Do we need to check that start, end are valid? BasicVector_ByteBuffer v = new BasicVector_ByteBuffer(end - start, directAllocation); ByteBuffer view = elements.asReadOnlyBuffer(); ((java.nio.Buffer)view).position(start); ((java.nio.Buffer)view).limit(end); try { v.elements.put(view); v.elements.position(0); return v; } catch (BufferOverflowException e) { return error(new TypeError("Could not form a subseq from " + start + " to " + end)); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 255) { type_error(obj, UNSIGNED_BYTE_8); // Not reached. return; } for (int i = length(); i-- > 0;) { elements.put(i, (byte) n); } } @Override public void shrink(int n) { // One cannot shrink a ByteBuffer physically, and the elements // field may refer to malloc()d memory that we shouldn't touch, so // use the java.nio.Buffer limit pointer. Not totally sure that // this strategy will work out… if (n < length()) { ((java.nio.Buffer)elements).limit(n); capacity = n; return; } if (n == length()) { return; } error(new LispError("Attempted to shrink an array to a size greater than its capacity")); } @Override public LispObject reverse() { BasicVector_ByteBuffer result = new BasicVector_ByteBuffer(length(), directAllocation); int i, j; for (i = 0, j = length() - 1; i < length(); i++, j--) { result.elements.put(i, elements.get(j)); } return result; } @Override public LispObject nreverse() { int i = 0; int j = capacity() - 1; while (i < j) { byte temp = elements.get(i); elements.put(i, elements.get(j)); elements.put(j, temp); ++i; --j; } return this; } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { ByteBuffer newElements; if (directAllocation) { newElements = ByteBuffer.allocateDirect(newCapacity); } else { newElements = ByteBuffer.allocate(newCapacity); } if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements.put(i, coerceToJavaByte(list.car())); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newElements.put(i, coerceToJavaByte(initialContents.elt(i))); } else type_error(initialContents, Symbol.SEQUENCE); return new BasicVector_ByteBuffer(newElements, directAllocation); } if (length() != newCapacity) { ByteBuffer newElements; if (directAllocation) { newElements = ByteBuffer.allocateDirect(newCapacity); } else { newElements = ByteBuffer.allocate(newCapacity); } if (elements.hasArray()) { newElements.put(elements.array(), 0, Math.min(length(), newCapacity)); } else { // FIXME: a more efficient version when we don't have a backing array int limit = Math.min(length(), newCapacity); for (int i = 0; i < limit; i++) { newElements.put(i, elements.get(i)); } } if (initialElement != null) { byte initValue = (byte)(initialElement.intValue() & 0xFF); for (int i = length(); i < newCapacity; i++) newElements.put(i, initValue); } return new BasicVector_ByteBuffer(newElements, directAllocation); } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexVector(newCapacity, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/BasicVector_CharBuffer.java0100644 0000000 0000000 00000021331 14202767264 023355 0ustar000000000 0000000 /* * BasicVector_CharBuffer.java * * Copyright (C) 2020 @easye * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; import java.nio.CharBuffer; /** A vector with specialized underlying storage for (unsigned-byte 16) */ public final class BasicVector_CharBuffer extends AbstractVector { private int capacity; private CharBuffer elements; private boolean directAllocation; public BasicVector_CharBuffer(int capacity) { this(capacity, false); } public BasicVector_CharBuffer(int capacity, boolean directAllocation) { this.directAllocation = directAllocation; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(capacity * 2); elements = b.asCharBuffer(); } else { elements = CharBuffer.allocate(capacity); } this.capacity = capacity; } public BasicVector_CharBuffer(LispObject[] array, boolean directAllocation) { capacity = array.length; this.directAllocation = directAllocation; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(capacity * 2); elements = b.asCharBuffer(); } else { elements = CharBuffer.allocate(capacity); } for (int i = array.length; i-- > 0;) { elements.put(i, (char)Fixnum.getValue(array[i])); // FIXME bulk copy } } public BasicVector_CharBuffer(ByteBuffer buffer, boolean directAllocation) { elements = buffer.asCharBuffer(); this.directAllocation = directAllocation; capacity = ((java.nio.Buffer)buffer).limit() / 2; } public BasicVector_CharBuffer(CharBuffer buffer, boolean directAllocation) { elements = buffer; this.directAllocation = directAllocation; capacity = ((java.nio.Buffer)buffer).limit(); } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_16, new Cons(Fixnum.getInstance(capacity))); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_16; } @Override public boolean isSimpleVector() { return false; } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return capacity; } @Override public LispObject elt(int index) { try { return Fixnum.getInstance(elements.get(index)); } catch (IndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } // Ignores fill pointer. @Override public int aref(int index) { try { return elements.get(index); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); // FIXME should implement method for length() contract // Not reached. return 0; } } // Ignores fill pointer. @Override public LispObject AREF(int index) { try { return Fixnum.getInstance(elements.get(index)); } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); // FIXME limit() --> capacity? return NIL; // Not reached. } } @Override public void aset(int index, int n) { try { elements.put(index, (char)n); } catch (IndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public void aset(int index, LispObject obj) { if (obj instanceof Fixnum) { try { elements.put(index, (char)((Fixnum)obj).value); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } else { type_error(obj, UNSIGNED_BYTE_16); } } @Override public LispObject subseq(int start, int end) { BasicVector_CharBuffer v = new BasicVector_CharBuffer(end - start); int i = start, j = 0; try { while (i < end) { v.elements.put(j++, elements.get(i++)); } return v; } catch (IndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 65535) { type_error(obj, UNSIGNED_BYTE_16); // Not reached. return; } char m = (char) n; for (int i = capacity; i-- > 0;) { elements.put(i, m); // FASTER!!! } } @Override public void shrink(int n) { // One cannot shrink the underlying ByteBuffer physically, and // the elements field may refer to malloc()d memory that we // shouldn't touch, so use the java.nio.Buffer limit pointer. // Not totally sure that this strategy will work out… if (n < length()) { ((java.nio.Buffer)elements).limit(n); capacity = n; return; } if (n == capacity) { return; } error(new LispError("End of native shrink routine: shouldn't be reachable.")); } @Override public LispObject reverse() { BasicVector_CharBuffer result = new BasicVector_CharBuffer(capacity); int i, j; for (i = 0, j = capacity - 1; i < capacity; i++, j--){ result.elements.put(i, elements.get(j)); } return result; } @Override public LispObject nreverse() { int i = 0; int j = capacity - 1; while (i < j) { char temp = elements.get(i); elements.put(i, elements.get(j)); elements.put(j, temp); ++i; --j; } return this; } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { LispObject[] newElements = new LispObject[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements[i] = list.car(); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newElements[i] = initialContents.elt(i); } else type_error(initialContents, Symbol.SEQUENCE); return new BasicVector_CharBuffer(newElements, directAllocation); } if (capacity != newCapacity) { // FIXME: more efficient LispObject[] newElements = new LispObject[newCapacity]; System.arraycopy(elements.array(), 0, newElements, 0, Math.min(capacity, newCapacity)); if (initialElement != null) { for (int i = capacity; i < newCapacity; i++) newElements[i] = initialElement; } return new BasicVector_CharBuffer(newElements, directAllocation); } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexVector(newCapacity, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/BasicVector_IntBuffer.java0100644 0000000 0000000 00000021730 14202767264 023235 0ustar000000000 0000000 /* * BasicVector_IntBuffer.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.IntBuffer; import java.nio.ByteBuffer; // A basic vector is a specialized vector that is not displaced to another // array, has no fill pointer, and is not expressly adjustable. public final class BasicVector_IntBuffer extends AbstractVector { private int capacity; private IntBuffer elements; private boolean directAllocation; public BasicVector_IntBuffer(int capacity) { this(capacity, false); } public BasicVector_IntBuffer(int capacity, boolean directAllocation) { this.directAllocation = directAllocation; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(capacity * 4); elements = b.asIntBuffer(); } else { elements = IntBuffer.allocate(capacity); } this.capacity = capacity; } public BasicVector_IntBuffer(LispObject[] array, boolean directAllocation) { capacity = array.length; this.directAllocation = directAllocation; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(capacity * 4); elements = b.asIntBuffer(); } else { elements = IntBuffer.allocate(capacity); } for (int i = array.length; i-- > 0;) { // FIXME: if LispObeject is a number that can't fit into an int elements.put(i, (int)(array[i].longValue() & 0xffffffffL)); } } public BasicVector_IntBuffer(ByteBuffer buffer, boolean directAllocation) { this.directAllocation = directAllocation; elements = buffer.asIntBuffer(); capacity = ((java.nio.Buffer)buffer).limit() / 4; } public BasicVector_IntBuffer(IntBuffer buffer) { this(buffer, false); } public BasicVector_IntBuffer(IntBuffer buffer, boolean directAllocation) { this.directAllocation = directAllocation; elements = buffer; capacity = ((java.nio.Buffer)buffer).limit(); } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_32, new Cons(Fixnum.getInstance(capacity))); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_32; } @Override public boolean isSimpleVector() { return false; } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return capacity; } @Override public LispObject elt(int index) { try { return number(((long)elements.get(index)) & 0xffffffffL); } catch (IndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public int aref(int index) { try { // FIXME: this shouldn't be used? return number(((long)elements.get(index)) & 0xffffffffL).intValue(); } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); return -1; // Not reached. } } @Override public long aref_long(int index) { try { return ((long)elements.get(index)) & 0xffffffffL; } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); return -1; // Not reached. } } @Override public LispObject AREF(int index) { try { return number(((long)elements.get(index)) & 0xffffffffL); } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); return NIL; // Not reached. } } @Override public void aset(int index, LispObject newValue) { try { if (newValue.isLessThan(Fixnum.ZERO) || newValue.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(newValue, UNSIGNED_BYTE_32); } elements.put(index, (int)(newValue.longValue() & 0xffffffffL)); } catch (IndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public LispObject subseq(int start, int end) { BasicVector_IntBuffer v = new BasicVector_IntBuffer(end - start); int i = start, j = 0; try { while (i < end) { v.elements.put(j++, elements.get(i++)); } return v; } catch (IndexOutOfBoundsException e) { // FIXME return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof LispInteger)) { type_error(obj, Symbol.INTEGER); // Not reached. return; } if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(obj, UNSIGNED_BYTE_32); } for (int i = capacity; i-- > 0;) { elements.put(i, (int)(obj.longValue() & 0xffffffffL)); } } @Override public void shrink(int n) { if (n < length()) { // One cannot shrink the underlying ByteBuffer physically, and // the elements field may refer to malloc()d memory that we // shouldn't touch, so use the java.nio.Buffer limit pointer. // Not totally sure that this strategy will work out… ((java.nio.Buffer)elements).limit(n); capacity = n; return; } if (n == capacity) { return; } error(new LispError()); } @Override public LispObject reverse() { BasicVector_IntBuffer result = new BasicVector_IntBuffer(capacity); int i, j; for (i = 0, j = capacity - 1; i < capacity; i++, j--) { result.elements.put(i, elements.get(j)); } return result; } @Override public LispObject nreverse() { int i = 0; int j = capacity - 1; while (i < j) { int temp = elements.get(i); elements.put(i, elements.get(j)); elements.put(j, temp); ++i; --j; } return this; } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { LispObject[] newElements = new LispObject[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements[i] = list.car(); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) { newElements[i] = initialContents.elt(i); } } else { type_error(initialContents, Symbol.SEQUENCE); } return new BasicVector_IntBuffer(newElements, directAllocation); } if (capacity != newCapacity) { LispObject[] newElements = new LispObject[newCapacity]; System.arraycopy(elements.array(), 0, newElements, 0, Math.min(capacity, newCapacity)); if (initialElement != null) { for (int i = capacity; i < newCapacity; i++) { newElements[i] = initialElement; } } return new BasicVector_IntBuffer(newElements, directAllocation); } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexVector(newCapacity, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/BasicVector_UnsignedByte16.java0100644 0000000 0000000 00000020227 14202767264 024120 0ustar000000000 0000000 /* * BasicVector_UnsignedByte16.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // A basic vector is a specialized vector that is not displaced to another // array, has no fill pointer, and is not expressly adjustable. public final class BasicVector_UnsignedByte16 extends AbstractVector { private int capacity; private int[] elements; public BasicVector_UnsignedByte16(int capacity) { elements = new int[capacity]; this.capacity = capacity; } private BasicVector_UnsignedByte16(LispObject[] array) { capacity = array.length; elements = new int[capacity]; for (int i = array.length; i-- > 0;) elements[i] = Fixnum.getValue(array[i]); } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_16, new Cons(Fixnum.getInstance(capacity))); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_16; } @Override public boolean isSimpleVector() { return false; } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return capacity; } @Override public LispObject elt(int index) { try { return Fixnum.getInstance(elements[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } // Ignores fill pointer. @Override public int aref(int index) { try { return elements[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); // Not reached. return 0; } } // Ignores fill pointer. @Override public LispObject AREF(int index) { try { return Fixnum.getInstance(elements[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); return NIL; // Not reached. } } @Override public void aset(int index, int n) { try { elements[index] = n; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public void aset(int index, LispObject obj) { if (obj instanceof Fixnum) { try { elements[index] = ((Fixnum)obj).value; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } else { type_error(obj, UNSIGNED_BYTE_16); } } @Override public LispObject subseq(int start, int end) { BasicVector_UnsignedByte16 v = new BasicVector_UnsignedByte16(end - start); int i = start, j = 0; try { while (i < end) v.elements[j++] = elements[i++]; return v; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 65535) { type_error(obj, UNSIGNED_BYTE_16); // Not reached. return; } for (int i = capacity; i-- > 0;) elements[i] = n; } @Override public void shrink(int n) { if (n < capacity) { int[] newArray = new int[n]; System.arraycopy(elements, 0, newArray, 0, n); elements = newArray; capacity = n; return; } if (n == capacity) return; error(new LispError()); } @Override public LispObject reverse() { BasicVector_UnsignedByte16 result = new BasicVector_UnsignedByte16(capacity); int i, j; for (i = 0, j = capacity - 1; i < capacity; i++, j--) result.elements[i] = elements[j]; return result; } @Override public LispObject nreverse() { int i = 0; int j = capacity - 1; while (i < j) { int temp = elements[i]; elements[i] = elements[j]; elements[j] = temp; ++i; --j; } return this; } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { LispObject[] newElements = new LispObject[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements[i] = list.car(); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newElements[i] = initialContents.elt(i); } else type_error(initialContents, Symbol.SEQUENCE); return new BasicVector_UnsignedByte16(newElements); } if (capacity != newCapacity) { LispObject[] newElements = new LispObject[newCapacity]; System.arraycopy(elements, 0, newElements, 0, Math.min(capacity, newCapacity)); if (initialElement != null) for (int i = capacity; i < newCapacity; i++) newElements[i] = initialElement; return new BasicVector_UnsignedByte16(newElements); } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexVector(newCapacity, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/BasicVector_UnsignedByte32.java0100644 0000000 0000000 00000016776 14202767264 024134 0ustar000000000 0000000 /* * BasicVector_UnsignedByte32.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // A basic vector is a specialized vector that is not displaced to another // array, has no fill pointer, and is not expressly adjustable. public final class BasicVector_UnsignedByte32 extends AbstractVector { private int capacity; private long[] elements; public BasicVector_UnsignedByte32(int capacity) { elements = new long[capacity]; this.capacity = capacity; } public BasicVector_UnsignedByte32(LispObject[] array) { capacity = array.length; elements = new long[capacity]; for (int i = array.length; i-- > 0;) elements[i] = array[i].longValue(); } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_32, new Cons(Fixnum.getInstance(capacity))); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_32; } @Override public boolean isSimpleVector() { return false; } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return capacity; } @Override public LispObject elt(int index) { try { return number(elements[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public int aref(int index) { try { return (int) elements[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); return -1; // Not reached. } } @Override public long aref_long(int index) { try { return elements[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); return -1; // Not reached. } } @Override public LispObject AREF(int index) { try { return number(elements[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); return NIL; // Not reached. } } @Override public void aset(int index, LispObject newValue) { try { elements[index] = newValue.longValue(); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public LispObject subseq(int start, int end) { BasicVector_UnsignedByte32 v = new BasicVector_UnsignedByte32(end - start); int i = start, j = 0; try { while (i < end) v.elements[j++] = elements[i++]; return v; } catch (ArrayIndexOutOfBoundsException e) { // FIXME return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof LispInteger)) { type_error(obj, Symbol.INTEGER); // Not reached. return; } if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(obj, UNSIGNED_BYTE_32); } long value = obj.longValue(); for (int i = capacity; i-- > 0;) elements[i] = value; } @Override public void shrink(int n) { if (n < capacity) { long[] newArray = new long[n]; System.arraycopy(elements, 0, newArray, 0, n); elements = newArray; capacity = n; return; } if (n == capacity) return; error(new LispError()); } @Override public LispObject reverse() { BasicVector_UnsignedByte32 result = new BasicVector_UnsignedByte32(capacity); int i, j; for (i = 0, j = capacity - 1; i < capacity; i++, j--) result.elements[i] = elements[j]; return result; } @Override public LispObject nreverse() { int i = 0; int j = capacity - 1; while (i < j) { long temp = elements[i]; elements[i] = elements[j]; elements[j] = temp; ++i; --j; } return this; } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { LispObject[] newElements = new LispObject[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements[i] = list.car(); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newElements[i] = initialContents.elt(i); } else type_error(initialContents, Symbol.SEQUENCE); return new BasicVector_UnsignedByte32(newElements); } if (capacity != newCapacity) { LispObject[] newElements = new LispObject[newCapacity]; System.arraycopy(elements, 0, newElements, 0, Math.min(capacity, newCapacity)); if (initialElement != null) for (int i = capacity; i < newCapacity; i++) newElements[i] = initialElement; return new BasicVector_UnsignedByte32(newElements); } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexVector(newCapacity, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/BasicVector_UnsignedByte8.java0100644 0000000 0000000 00000017261 14202767264 024045 0ustar000000000 0000000 /* * BasicVector_UnsignedByte8.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // A basic vector is a specialized vector that is not displaced to another // array, has no fill pointer, and is not expressly adjustable. public final class BasicVector_UnsignedByte8 extends AbstractVector { private int capacity; private byte[] elements; public BasicVector_UnsignedByte8(int capacity) { elements = new byte[capacity]; this.capacity = capacity; } public BasicVector_UnsignedByte8(byte[] array) { capacity = array.length; elements = new byte[capacity]; System.arraycopy(array, 0, elements, 0, capacity); } public BasicVector_UnsignedByte8(LispObject[] array) { capacity = array.length; elements = new byte[capacity]; for (int i = array.length; i-- > 0;) elements[i] = coerceToJavaByte(array[i]); } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_8, new Cons(Fixnum.getInstance(capacity))); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_8; } @Override public boolean isSimpleVector() { return false; } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return capacity; } @Override public LispObject elt(int index) { try { return coerceFromJavaByte(elements[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public int aref(int index) { try { return (((int)elements[index]) & 0xff); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); // Not reached. return 0; } } @Override public LispObject AREF(int index) { try { return coerceFromJavaByte(elements[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); return NIL; // Not reached. } } @Override public void aset(int index, int n) { try { elements[index] = (byte) n; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public void aset(int index, LispObject value) { try { elements[index] = coerceToJavaByte(value); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public LispObject subseq(int start, int end) { BasicVector_UnsignedByte8 v = new BasicVector_UnsignedByte8(end - start); int i = start, j = 0; try { while (i < end) v.elements[j++] = elements[i++]; return v; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 255) { type_error(obj, UNSIGNED_BYTE_8); // Not reached. return; } for (int i = capacity; i-- > 0;) elements[i] = (byte) n; } @Override public void shrink(int n) { if (n < capacity) { byte[] newArray = new byte[n]; System.arraycopy(elements, 0, newArray, 0, n); elements = newArray; capacity = n; return; } if (n == capacity) return; error(new LispError()); } @Override public LispObject reverse() { BasicVector_UnsignedByte8 result = new BasicVector_UnsignedByte8(capacity); int i, j; for (i = 0, j = capacity - 1; i < capacity; i++, j--) result.elements[i] = elements[j]; return result; } @Override public LispObject nreverse() { int i = 0; int j = capacity - 1; while (i < j) { byte temp = elements[i]; elements[i] = elements[j]; elements[j] = temp; ++i; --j; } return this; } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { LispObject[] newElements = new LispObject[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements[i] = list.car(); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newElements[i] = initialContents.elt(i); } else type_error(initialContents, Symbol.SEQUENCE); return new BasicVector_UnsignedByte8(newElements); } if (capacity != newCapacity) { byte[] newElements = new byte[newCapacity]; System.arraycopy(elements, 0, newElements, 0, Math.min(capacity, newCapacity)); if (initialElement != null) { byte initValue = (byte)(initialElement.intValue() & 0xFF); for (int i = capacity; i < newCapacity; i++) newElements[i] = initValue; } return new BasicVector_UnsignedByte8(newElements); } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexVector(newCapacity, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/Bignum.java0100644 0000000 0000000 00000052631 14202767264 020312 0ustar000000000 0000000 /* * Bignum.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; public final class Bignum extends LispInteger { public final BigInteger value; private static BigInteger MOST_NEGATIVE_FIXNUM = BigInteger.valueOf(Integer.MIN_VALUE); private static BigInteger MOST_POSITIVE_FIXNUM = BigInteger.valueOf(Integer.MAX_VALUE); public static LispInteger getInstance(long l) { if (Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE) return Fixnum.getInstance(l); else return new Bignum(l); } public static LispInteger getInstance(BigInteger n) { if (MOST_NEGATIVE_FIXNUM.compareTo(n) < 0 || MOST_POSITIVE_FIXNUM.compareTo(n) > 0) return new Bignum(n); else return Fixnum.getInstance(n.intValue()); } public static LispInteger getInstance(String s, int radix) { BigInteger value = new BigInteger(s, radix); return Bignum.getInstance(value); } private Bignum(long l) { value = BigInteger.valueOf(l); } private Bignum(BigInteger n) { value = n; } @Override public Object javaInstance() { return value; } @Override public Object javaInstance(Class c) { if (c == Byte.class || c == byte.class) return Byte.valueOf((byte)value.intValue()); if (c == Short.class || c == short.class) return Short.valueOf((short)value.intValue()); if (c == Integer.class || c == int.class) return Integer.valueOf(value.intValue()); if (c == Long.class || c == long.class) return Long.valueOf((long)value.longValue()); return javaInstance(); } @Override public LispObject typeOf() { if (value.signum() > 0) return list(Symbol.INTEGER, new Bignum((long)Integer.MAX_VALUE + 1)); return Symbol.BIGNUM; } @Override public LispObject classOf() { return BuiltInClass.BIGNUM; } @Override public LispObject typep(LispObject type) { if (type instanceof Symbol) { if (type == Symbol.BIGNUM) return T; if (type == Symbol.INTEGER) return T; if (type == Symbol.RATIONAL) return T; if (type == Symbol.REAL) return T; if (type == Symbol.NUMBER) return T; if (type == Symbol.SIGNED_BYTE) return T; if (type == Symbol.UNSIGNED_BYTE) return value.signum() >= 0 ? T : NIL; } else if (type instanceof LispClass) { if (type == BuiltInClass.BIGNUM) return T; if (type == BuiltInClass.INTEGER) return T; if (type == BuiltInClass.RATIONAL) return T; if (type == BuiltInClass.REAL) return T; if (type == BuiltInClass.NUMBER) return T; } else if (type instanceof Cons) { if (type.equal(UNSIGNED_BYTE_8)) return NIL; if (type.equal(UNSIGNED_BYTE_32)) { if (minusp()) return NIL; return isLessThanOrEqualTo(UNSIGNED_BYTE_32_MAX_VALUE) ? T : NIL; } } return super.typep(type); } @Override public boolean numberp() { return true; } @Override public boolean integerp() { return true; } @Override public boolean rationalp() { return true; } @Override public boolean realp() { return true; } @Override public boolean eql(LispObject obj) { if (this == obj) return true; if (obj instanceof Bignum) { if (value.equals(((Bignum)obj).value)) return true; } return false; } @Override public boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof Bignum) { if (value.equals(((Bignum)obj).value)) return true; } return false; } @Override public boolean equalp(LispObject obj) { if (obj != null && obj.numberp()) return isEqualTo(obj); return false; } @Override public LispObject ABS() { if (value.signum() >= 0) return this; return new Bignum(value.negate()); } @Override public LispObject NUMERATOR() { return this; } @Override public LispObject DENOMINATOR() { return Fixnum.ONE; } @Override public boolean evenp() { return !value.testBit(0); } @Override public boolean oddp() { return value.testBit(0); } @Override public boolean plusp() { return value.signum() > 0; } @Override public boolean minusp() { return value.signum() < 0; } @Override public boolean zerop() { return false; } @Override public int intValue() { return value.intValue(); } @Override public long longValue() { return value.longValue(); } @Override public float floatValue() { float f = value.floatValue(); if (Float.isInfinite(f)) error(new TypeError("The value " + princToString() + " is too large to be converted to a single float.")); return f; } @Override public double doubleValue() { double d = value.doubleValue(); if (Double.isInfinite(d)) error(new TypeError("The value " + princToString() + " is too large to be converted to a double float.")); return d; } public static BigInteger getValue(LispObject obj) { if (obj instanceof Bignum) { return ((Bignum)obj).value; } type_error(obj, Symbol.BIGNUM); // Not reached. return null; } @Override public final LispObject incr() { return number(value.add(BigInteger.ONE)); } @Override public final LispObject decr() { return number(value.subtract(BigInteger.ONE)); } @Override public LispObject add(int n) { return number(value.add(BigInteger.valueOf(n))); } @Override public LispObject add(LispObject obj) { if (obj instanceof Fixnum) return number(value.add(Fixnum.getBigInteger(obj))); if (obj instanceof Bignum) return number(value.add(((Bignum)obj).value)); if (obj instanceof Ratio) { BigInteger numerator = ((Ratio)obj).numerator(); BigInteger denominator = ((Ratio)obj).denominator(); return number(value.multiply(denominator).add(numerator), denominator); } if (obj instanceof SingleFloat) return new SingleFloat(floatValue() + ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(doubleValue() + ((DoubleFloat)obj).value); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart()); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject subtract(LispObject obj) { if (obj instanceof Fixnum) return number(value.subtract(Fixnum.getBigInteger(obj))); if (obj instanceof Bignum) return number(value.subtract(((Bignum)obj).value)); if (obj instanceof Ratio) { BigInteger numerator = ((Ratio)obj).numerator(); BigInteger denominator = ((Ratio)obj).denominator(); return number(value.multiply(denominator).subtract(numerator), denominator); } if (obj instanceof SingleFloat) return new SingleFloat(floatValue() - ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(doubleValue() - ((DoubleFloat)obj).value); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(subtract(c.getRealPart()), Fixnum.ZERO.subtract(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject multiplyBy(int n) { if (n == 0) return Fixnum.ZERO; if (n == 1) return this; return new Bignum(value.multiply(BigInteger.valueOf(n))); } @Override public LispObject multiplyBy(LispObject obj) { if (obj instanceof Fixnum) { int n = ((Fixnum)obj).value; if (n == 0) return Fixnum.ZERO; if (n == 1) return this; return new Bignum(value.multiply(BigInteger.valueOf(n))); } if (obj instanceof Bignum) return new Bignum(value.multiply(((Bignum)obj).value)); if (obj instanceof Ratio) { BigInteger n = ((Ratio)obj).numerator(); return number(n.multiply(value), ((Ratio)obj).denominator()); } if (obj instanceof SingleFloat) return new SingleFloat(floatValue() * ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(doubleValue() * ((DoubleFloat)obj).value); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(multiplyBy(c.getRealPart()), multiplyBy(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject divideBy(LispObject obj) { if (obj instanceof Fixnum) return number(value, Fixnum.getBigInteger(obj)); if (obj instanceof Bignum) return number(value, ((Bignum)obj).value); if (obj instanceof Ratio) { BigInteger d = ((Ratio)obj).denominator(); return number(d.multiply(value), ((Ratio)obj).numerator()); } if (obj instanceof SingleFloat) return new SingleFloat(floatValue() / ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(doubleValue() / ((DoubleFloat)obj).value); if (obj instanceof Complex) { Complex c = (Complex) obj; LispObject realPart = c.getRealPart(); LispObject imagPart = c.getImaginaryPart(); LispObject denominator = realPart.multiplyBy(realPart).add(imagPart.multiplyBy(imagPart)); return Complex.getInstance(multiplyBy(realPart).divideBy(denominator), Fixnum.ZERO.subtract(multiplyBy(imagPart).divideBy(denominator))); } return type_error(obj, Symbol.NUMBER); } @Override public boolean isEqualTo(LispObject obj) { if (obj instanceof Bignum) return value.equals(((Bignum)obj).value); if (obj instanceof SingleFloat) return isEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isEqualTo(((DoubleFloat)obj).rational()); if (obj.numberp()) return false; type_error(obj, Symbol.NUMBER); // Not reached. return false; } @Override public boolean isNotEqualTo(LispObject obj) { if (obj instanceof Bignum) return !value.equals(((Bignum)obj).value); if (obj instanceof SingleFloat) return isNotEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isNotEqualTo(((DoubleFloat)obj).rational()); if (obj.numberp()) return true; type_error(obj, Symbol.NUMBER); // Not reached. return false; } @Override public boolean isLessThan(LispObject obj) { if (obj instanceof Fixnum) return value.compareTo(Fixnum.getBigInteger(obj)) < 0; if (obj instanceof Bignum) return value.compareTo(((Bignum)obj).value) < 0; if (obj instanceof Ratio) { BigInteger n = value.multiply(((Ratio)obj).denominator()); return n.compareTo(((Ratio)obj).numerator()) < 0; } if (obj instanceof SingleFloat) return isLessThan(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isLessThan(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThan(LispObject obj) { if (obj instanceof Fixnum) return value.compareTo(Fixnum.getBigInteger(obj)) > 0; if (obj instanceof Bignum) return value.compareTo(((Bignum)obj).value) > 0; if (obj instanceof Ratio) { BigInteger n = value.multiply(((Ratio)obj).denominator()); return n.compareTo(((Ratio)obj).numerator()) > 0; } if (obj instanceof SingleFloat) return isGreaterThan(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isGreaterThan(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isLessThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value.compareTo(Fixnum.getBigInteger(obj)) <= 0; if (obj instanceof Bignum) return value.compareTo(((Bignum)obj).value) <= 0; if (obj instanceof Ratio) { BigInteger n = value.multiply(((Ratio)obj).denominator()); return n.compareTo(((Ratio)obj).numerator()) <= 0; } if (obj instanceof SingleFloat) return isLessThanOrEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isLessThanOrEqualTo(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value.compareTo(Fixnum.getBigInteger(obj)) >= 0; if (obj instanceof Bignum) return value.compareTo(((Bignum)obj).value) >= 0; if (obj instanceof Ratio) { BigInteger n = value.multiply(((Ratio)obj).denominator()); return n.compareTo(((Ratio)obj).numerator()) >= 0; } if (obj instanceof SingleFloat) return isGreaterThanOrEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isGreaterThanOrEqualTo(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public LispObject truncate(LispObject obj) { final LispThread thread = LispThread.currentThread(); LispObject value1, value2; try { if (obj instanceof Fixnum) { BigInteger divisor = ((Fixnum)obj).getBigInteger(); BigInteger[] results = value.divideAndRemainder(divisor); BigInteger quotient = results[0]; BigInteger remainder = results[1]; value1 = number(quotient); value2 = (remainder.signum() == 0) ? Fixnum.ZERO : number(remainder); } else if (obj instanceof Bignum) { BigInteger divisor = ((Bignum)obj).value; BigInteger[] results = value.divideAndRemainder(divisor); BigInteger quotient = results[0]; BigInteger remainder = results[1]; value1 = number(quotient); value2 = (remainder.signum() == 0) ? Fixnum.ZERO : number(remainder); } else if (obj instanceof Ratio) { Ratio divisor = (Ratio) obj; LispObject quotient = multiplyBy(divisor.DENOMINATOR()).truncate(divisor.NUMERATOR()); LispObject remainder = subtract(quotient.multiplyBy(divisor)); value1 = quotient; value2 = remainder; } else if (obj instanceof SingleFloat) { // "When rationals and floats are combined by a numerical // function, the rational is first converted to a float of the // same format." 12.1.4.1 return new SingleFloat(floatValue()).truncate(obj); } else if (obj instanceof DoubleFloat) { // "When rationals and floats are combined by a numerical // function, the rational is first converted to a float of the // same format." 12.1.4.1 return new DoubleFloat(doubleValue()).truncate(obj); } else return type_error(obj, Symbol.REAL); } catch (ArithmeticException e) { if (obj.zerop()) { LispObject operands = new Cons(this, new Cons(obj)); LispObject args = new Cons(Keyword.OPERATION, new Cons(Symbol.TRUNCATE, new Cons(Keyword.OPERANDS, new Cons(operands)))); return error(new DivisionByZero(args)); } else return error(new ArithmeticError(e.getMessage())); } return thread.setValues(value1, value2); } @Override public LispObject ash(LispObject obj) { BigInteger n = value; if (obj instanceof Fixnum) { int count = ((Fixnum)obj).value; if (count == 0) return this; // BigInteger.shiftLeft() succumbs to a stack overflow if count // is Integer.MIN_VALUE, so... if (count == Integer.MIN_VALUE) return n.signum() >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; return number(n.shiftLeft(count)); } if (obj instanceof Bignum) { BigInteger count = ((Bignum)obj).value; if (count.signum() > 0) return error(new LispError("Can't represent result of left shift.")); if (count.signum() < 0) return n.signum() >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; Debug.bug(); // Shouldn't happen. } return type_error(obj, Symbol.INTEGER); } @Override public LispObject LOGNOT() { return number(value.not()); } @Override public LispObject LOGAND(int n) { if (n >= 0) return Fixnum.getInstance(value.intValue() & n); else return number(value.and(BigInteger.valueOf(n))); } @Override public LispObject LOGAND(LispObject obj) { if (obj instanceof Fixnum) { int n = ((Fixnum)obj).value; if (n >= 0) return Fixnum.getInstance(value.intValue() & n); else return number(value.and(BigInteger.valueOf(n))); } else if (obj instanceof Bignum) { final BigInteger n = ((Bignum)obj).value; return number(value.and(n)); } else return type_error(obj, Symbol.INTEGER); } @Override public LispObject LOGIOR(int n) { return number(value.or(BigInteger.valueOf(n))); } @Override public LispObject LOGIOR(LispObject obj) { if (obj instanceof Fixnum) { final BigInteger n = ((Fixnum)obj).getBigInteger(); return number(value.or(n)); } else if (obj instanceof Bignum) { final BigInteger n = ((Bignum)obj).value; return number(value.or(n)); } else return type_error(obj, Symbol.INTEGER); } @Override public LispObject LOGXOR(int n) { return number(value.xor(BigInteger.valueOf(n))); } @Override public LispObject LOGXOR(LispObject obj) { final BigInteger n; if (obj instanceof Fixnum) n = ((Fixnum)obj).getBigInteger(); else if (obj instanceof Bignum) n = ((Bignum)obj).value; else return type_error(obj, Symbol.INTEGER); return number(value.xor(n)); } @Override public LispObject LDB(int size, int position) { BigInteger n = value.shiftRight(position); BigInteger mask = BigInteger.ONE.shiftLeft(size).subtract(BigInteger.ONE); return number(n.and(mask)); } @Override public int hashCode() { return value.hashCode(); } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); final int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue(thread)); String s = value.toString(base).toUpperCase(); if (Symbol.PRINT_RADIX.symbolValue(thread) != NIL) { StringBuffer sb = new StringBuffer(); switch (base) { case 2: sb.append("#b"); sb.append(s); break; case 8: sb.append("#o"); sb.append(s); break; case 10: sb.append(s); sb.append('.'); break; case 16: sb.append("#x"); sb.append(s); break; default: sb.append('#'); sb.append(String.valueOf(base)); sb.append('r'); sb.append(s); break; } s = sb.toString(); } return s; } } abcl-src-1.9.0/src/org/armedbear/lisp/Binding.java0100644 0000000 0000000 00000006370 14202767264 020442 0ustar000000000 0000000 /* * Binding.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.Serializable; /** Used by the environment to capture different kinds of bindings: * tags, blocks, functions and variables. * */ // Package accessibility. final class Binding implements Serializable { /** The symbol in case of a variable, block, symbol-macro or * non-SETF function binding, the tag (symbol or * integer) in case of a tag binding or the cons * in case of a SETF function binding */ final LispObject symbol; /** Used only for tags and blocks. Refers to the * defining environment. * */ Environment env = null; /** The value bound. * * In case of a block binding, it holds the block identifier to be used * with the Return to be thrown. * * In case of a tagbody, it holds the tail subforms of the tagbody, of * which the tag is the first subform. * * In case of a function binding, it holds the function object. * * In case of a variable binding, it holds the value associated with the * variable, unless specialp is true. * * In case of a symbol macro binding, holds the SymbolMacro instance * holding the macro's expansion. */ LispObject value; /** Only used for variable bindings. Indicates whether or not the value * should be retrieved from the dynamic environment or from this binding. */ boolean specialp; final Binding next; Binding(LispObject symbol, LispObject value, Binding next) { this.symbol = symbol; this.value = value; this.next = next; } Binding(LispObject symbol, Environment env, LispObject value, Binding next) { this(symbol, value, next); this.env = env; } } abcl-src-1.9.0/src/org/armedbear/lisp/BroadcastStream.java0100644 0000000 0000000 00000016347 14202767264 022153 0ustar000000000 0000000 /* * BroadcastStream.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class BroadcastStream extends Stream { final Stream[] streams; BroadcastStream(Stream[] streams) { super(Symbol.BROADCAST_STREAM); this.streams = streams; isOutputStream = true; if (streams.length == 0) { elementType = T; isBinaryStream = true; isCharacterStream = true; } else { elementType = streams[streams.length-1].getElementType(); if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) isCharacterStream = true; else isBinaryStream = true; } } public Stream[] getStreams() { return streams; } @Override public LispObject typeOf() { return Symbol.BROADCAST_STREAM; } @Override public LispObject classOf() { return BuiltInClass.BROADCAST_STREAM; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.BROADCAST_STREAM) return T; if (typeSpecifier == BuiltInClass.BROADCAST_STREAM) return T; return super.typep(typeSpecifier); } @Override public LispObject listen() { notSupported(); // Not reached. return NIL; } @Override public LispObject fileLength() { if (streams.length > 0) return streams[streams.length - 1].fileLength(); else return Fixnum.ZERO; } @Override public LispObject fileStringLength(LispObject arg) { if (streams.length > 0) return streams[streams.length - 1].fileStringLength(arg); else return Fixnum.ONE; } // Returns -1 at end of file. @Override protected int _readChar() { notSupported(); // Not reached. return -1; } @Override protected void _unreadChar(int n) { notSupported(); } @Override protected boolean _charReady() { notSupported(); // Not reached. return false; } @Override public void _writeChar(char c) { for (int i = 0; i < streams.length; i++) streams[i]._writeChar(c); } @Override public void _writeChars(char[] chars, int start, int end) { for (int i = 0; i < streams.length; i++) streams[i]._writeChars(chars, start, end); } @Override public void _writeString(String s) { for (int i = 0; i < streams.length; i++) streams[i]._writeString(s); } @Override public void _writeLine(String s) { for (int i = 0; i < streams.length; i++) streams[i]._writeLine(s); } // Reads an 8-bit byte. @Override public int _readByte() { notSupported(); // Not reached. return -1; } // Writes an 8-bit byte. @Override public void _writeByte(int n) { for (int i = 0; i < streams.length; i++) streams[i]._writeByte(n); } @Override public void _finishOutput() { for (int i = 0; i < streams.length; i++) streams[i]._finishOutput(); } @Override public void _clearInput() { notSupported(); } @Override protected long _getFilePosition() { if (streams.length == 0) return 0; else return streams[streams.length-1]._getFilePosition(); } @Override protected boolean _setFilePosition(LispObject arg) { return false; } @Override public void _close() { setOpen(false); } private void notSupported() { error(new TypeError("Operation is not supported for streams of type BROADCAST-STREAM.")); } @Override public String printObject() { return unreadableString("BROADCAST-STREAM"); } // ### make-broadcast-stream &rest streams => broadcast-stream private static final Primitive MAKE_BROADCAST_STREAM = new Primitive("make-broadcast-stream", "&rest streams") { @Override public LispObject execute() { return new BroadcastStream(new Stream[0]); } @Override public LispObject execute(LispObject[] args) { Stream[] streams = new Stream[args.length]; for (int i = 0; i < args.length; i++) { if (args[i] instanceof Stream) { if (((Stream)args[i]).isOutputStream()) { streams[i] = (Stream) args[i]; continue; } else return type_error(args[i], list(Symbol.SATISFIES, Symbol.OUTPUT_STREAM_P)); } else return type_error(args[i], Symbol.STREAM); } // All is well. return new BroadcastStream(streams); } }; // ### broadcast-stream-streams broadcast-stream => streams private static final Primitive BROADCAST_STREAM_STREAMS = new Primitive("broadcast-stream-streams", "broadcast-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof BroadcastStream) { BroadcastStream stream = (BroadcastStream) arg; Stream[] streams = stream.streams; LispObject result = NIL; for (int i = streams.length; i-- > 0;) result = new Cons(streams[i], result); return result; } return type_error(arg, Symbol.BROADCAST_STREAM); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/BuiltInClass.java0100644 0000000 0000000 00000041233 14202767264 021421 0ustar000000000 0000000 /* * BuiltInClass.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class BuiltInClass extends LispClass { private BuiltInClass(Symbol symbol) { super(symbol); } @Override public LispObject typeOf() { return Symbol.BUILT_IN_CLASS; } @Override public LispObject classOf() { return StandardClass.BUILT_IN_CLASS; } @Override public boolean isFinalized() { return true; } @Override public LispObject typep(LispObject type) { if (type == Symbol.BUILT_IN_CLASS) return T; if (type == StandardClass.BUILT_IN_CLASS) return T; return super.typep(type); } @Override public LispObject getDescription() { return new SimpleString(princToString()); } @Override public String printObject() { return unreadableString(getName().princToString()); } private static BuiltInClass addClass(Symbol symbol) { BuiltInClass c = new BuiltInClass(symbol); addClass(symbol, c); return c; } public static final BuiltInClass CLASS_T = addClass(T); public static final BuiltInClass ARRAY = addClass(Symbol.ARRAY); public static final BuiltInClass BIGNUM = addClass(Symbol.BIGNUM); public static final BuiltInClass BASE_STRING = addClass(Symbol.BASE_STRING); public static final BuiltInClass BIT_VECTOR = addClass(Symbol.BIT_VECTOR); public static final BuiltInClass CHARACTER = addClass(Symbol.CHARACTER); public static final BuiltInClass COMPLEX = addClass(Symbol.COMPLEX); public static final BuiltInClass CONS = addClass(Symbol.CONS); public static final BuiltInClass DOUBLE_FLOAT = addClass(Symbol.DOUBLE_FLOAT); public static final BuiltInClass ENVIRONMENT = addClass(Symbol.ENVIRONMENT); public static final BuiltInClass FIXNUM = addClass(Symbol.FIXNUM); public static final BuiltInClass FLOAT = addClass(Symbol.FLOAT); public static final BuiltInClass FUNCTION = addClass(Symbol.FUNCTION); public static final BuiltInClass HASH_TABLE = addClass(Symbol.HASH_TABLE); public static final BuiltInClass INTEGER = addClass(Symbol.INTEGER); public static final BuiltInClass JAVA_OBJECT = addClass(Symbol.JAVA_OBJECT); public static final BuiltInClass LIST = addClass(Symbol.LIST); public static final BuiltInClass LOGICAL_PATHNAME = addClass(Symbol.LOGICAL_PATHNAME); public static final BuiltInClass MAILBOX = addClass(Symbol.MAILBOX); public static final BuiltInClass MUTEX = addClass(Symbol.MUTEX); public static final BuiltInClass NIL_VECTOR = addClass(Symbol.NIL_VECTOR); public static final BuiltInClass NULL = addClass(Symbol.NULL); public static final BuiltInClass NUMBER = addClass(Symbol.NUMBER); public static final BuiltInClass PACKAGE = addClass(Symbol.PACKAGE); public static final BuiltInClass PATHNAME = addClass(Symbol.PATHNAME); public static final BuiltInClass JAR_PATHNAME = addClass(Symbol.JAR_PATHNAME); public static final BuiltInClass URL_PATHNAME = addClass(Symbol.URL_PATHNAME); public static final BuiltInClass RANDOM_STATE = addClass(Symbol.RANDOM_STATE); public static final BuiltInClass RATIO = addClass(Symbol.RATIO); public static final BuiltInClass RATIONAL = addClass(Symbol.RATIONAL); public static final BuiltInClass READTABLE = addClass(Symbol.READTABLE); public static final BuiltInClass REAL = addClass(Symbol.REAL); public static final BuiltInClass RESTART = addClass(Symbol.RESTART); public static final BuiltInClass SEQUENCE = addClass(Symbol.SEQUENCE); public static final BuiltInClass SIMPLE_ARRAY = addClass(Symbol.SIMPLE_ARRAY); public static final BuiltInClass SIMPLE_BASE_STRING = addClass(Symbol.SIMPLE_BASE_STRING); public static final BuiltInClass SIMPLE_BIT_VECTOR = addClass(Symbol.SIMPLE_BIT_VECTOR); public static final BuiltInClass SIMPLE_STRING = addClass(Symbol.SIMPLE_STRING); public static final BuiltInClass SIMPLE_VECTOR = addClass(Symbol.SIMPLE_VECTOR); public static final BuiltInClass SINGLE_FLOAT = addClass(Symbol.SINGLE_FLOAT); public static final BuiltInClass STRING = addClass(Symbol.STRING); public static final BuiltInClass SYMBOL = addClass(Symbol.SYMBOL); public static final BuiltInClass THREAD = addClass(Symbol.THREAD); public static final BuiltInClass VECTOR = addClass(Symbol.VECTOR); public static final BuiltInClass STACK_FRAME = addClass(Symbol.STACK_FRAME); public static final BuiltInClass LISP_STACK_FRAME = addClass(Symbol.LISP_STACK_FRAME); public static final BuiltInClass JAVA_STACK_FRAME = addClass(Symbol.JAVA_STACK_FRAME); public static final BuiltInClass WEAK_REFERENCE = addClass(Symbol.WEAK_REFERENCE); public static final StructureClass STRUCTURE_OBJECT = (StructureClass)addClass(Symbol.STRUCTURE_OBJECT, new StructureClass(Symbol.STRUCTURE_OBJECT, list(CLASS_T))); /* All the stream classes below are being defined as structure classes but won't be available as such until further action is taken: the 'defstruct' internal administration is missing. For STREAM and SYSTEM-STREAM, that bit is added in boot.lisp */ public static final LispClass STREAM = addClass(Symbol.STREAM, new StructureClass(Symbol.STREAM, list(STRUCTURE_OBJECT))); public static final LispClass SYSTEM_STREAM = addClass(Symbol.SYSTEM_STREAM, new StructureClass(Symbol.SYSTEM_STREAM, list(STREAM))); public static final LispClass TWO_WAY_STREAM = addClass(Symbol.TWO_WAY_STREAM, new StructureClass(Symbol.TWO_WAY_STREAM, list(SYSTEM_STREAM))); public static final LispClass BROADCAST_STREAM = addClass(Symbol.BROADCAST_STREAM, new StructureClass(Symbol.BROADCAST_STREAM, list(SYSTEM_STREAM))); public static final LispClass ECHO_STREAM = addClass(Symbol.ECHO_STREAM, new StructureClass(Symbol.ECHO_STREAM, list(SYSTEM_STREAM))); public static final LispClass CASE_FROB_STREAM = addClass(Symbol.CASE_FROB_STREAM, new StructureClass(Symbol.CASE_FROB_STREAM, list(SYSTEM_STREAM))); public static final LispClass STRING_STREAM = addClass(Symbol.STRING_STREAM, new StructureClass(Symbol.STRING_STREAM, list(SYSTEM_STREAM))); public static final LispClass STRING_INPUT_STREAM = addClass(Symbol.STRING_INPUT_STREAM, new StructureClass(Symbol.STRING_INPUT_STREAM, list(STRING_STREAM))); public static final LispClass STRING_OUTPUT_STREAM = addClass(Symbol.STRING_OUTPUT_STREAM, new StructureClass(Symbol.STRING_OUTPUT_STREAM, list(STRING_STREAM))); public static final LispClass SYNONYM_STREAM = addClass(Symbol.SYNONYM_STREAM, new StructureClass(Symbol.SYNONYM_STREAM, list(SYSTEM_STREAM))); public static final LispClass FILE_STREAM = addClass(Symbol.FILE_STREAM, new StructureClass(Symbol.FILE_STREAM, list(SYSTEM_STREAM))); public static final LispClass JAR_STREAM = addClass(Symbol.JAR_STREAM, new StructureClass(Symbol.JAR_STREAM, list(SYSTEM_STREAM))); public static final LispClass URL_STREAM = addClass(Symbol.URL_STREAM, new StructureClass(Symbol.URL_STREAM, list(SYSTEM_STREAM))); public static final LispClass CONCATENATED_STREAM = addClass(Symbol.CONCATENATED_STREAM, new StructureClass(Symbol.CONCATENATED_STREAM, list(SYSTEM_STREAM))); // Implementation defined streams public static final LispClass SOCKET_STREAM = addClass(Symbol.SOCKET_STREAM, new StructureClass(Symbol.SOCKET_STREAM, list(TWO_WAY_STREAM))); public static final LispClass SLIME_INPUT_STREAM = addClass(Symbol.SLIME_INPUT_STREAM, new StructureClass(Symbol.SLIME_INPUT_STREAM, list(STRING_STREAM))); public static final LispClass SLIME_OUTPUT_STREAM = addClass(Symbol.SLIME_OUTPUT_STREAM, new StructureClass(Symbol.SLIME_OUTPUT_STREAM, list(STRING_STREAM))); static { ARRAY.setDirectSuperclass(CLASS_T); ARRAY.setCPL(ARRAY, CLASS_T); BASE_STRING.setDirectSuperclass(STRING); BASE_STRING.setCPL(BASE_STRING, STRING, VECTOR, ARRAY, SEQUENCE, CLASS_T); BIGNUM.setDirectSuperclass(INTEGER); BIGNUM.setCPL(BIGNUM, INTEGER, RATIONAL, REAL, NUMBER, CLASS_T); BIT_VECTOR.setDirectSuperclass(VECTOR); BIT_VECTOR.setCPL(BIT_VECTOR, VECTOR, ARRAY, SEQUENCE, CLASS_T); BROADCAST_STREAM.setCPL(BROADCAST_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); CASE_FROB_STREAM.setCPL(CASE_FROB_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); CHARACTER.setDirectSuperclass(CLASS_T); CHARACTER.setCPL(CHARACTER, CLASS_T); CLASS_T.setCPL(CLASS_T); COMPLEX.setDirectSuperclass(NUMBER); COMPLEX.setCPL(COMPLEX, NUMBER, CLASS_T); CONCATENATED_STREAM.setCPL(CONCATENATED_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); CONS.setDirectSuperclass(LIST); CONS.setCPL(CONS, LIST, SEQUENCE, CLASS_T); DOUBLE_FLOAT.setDirectSuperclass(FLOAT); DOUBLE_FLOAT.setCPL(DOUBLE_FLOAT, FLOAT, REAL, NUMBER, CLASS_T); ECHO_STREAM.setCPL(ECHO_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); ENVIRONMENT.setDirectSuperclass(CLASS_T); ENVIRONMENT.setCPL(ENVIRONMENT, CLASS_T); FIXNUM.setDirectSuperclass(INTEGER); FIXNUM.setCPL(FIXNUM, INTEGER, RATIONAL, REAL, NUMBER, CLASS_T); FILE_STREAM.setCPL(FILE_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); JAR_STREAM.setCPL(JAR_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); URL_STREAM.setCPL(URL_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); FLOAT.setDirectSuperclass(REAL); FLOAT.setCPL(FLOAT, REAL, NUMBER, CLASS_T); FUNCTION.setDirectSuperclass(CLASS_T); FUNCTION.setCPL(FUNCTION, CLASS_T); HASH_TABLE.setDirectSuperclass(CLASS_T); HASH_TABLE.setCPL(HASH_TABLE, CLASS_T); INTEGER.setDirectSuperclass(RATIONAL); INTEGER.setCPL(INTEGER, RATIONAL, REAL, NUMBER, CLASS_T); JAVA_OBJECT.setDirectSuperclass(CLASS_T); JAVA_OBJECT.setCPL(JAVA_OBJECT, CLASS_T); LIST.setDirectSuperclass(SEQUENCE); LIST.setCPL(LIST, SEQUENCE, CLASS_T); LOGICAL_PATHNAME.setDirectSuperclass(PATHNAME); LOGICAL_PATHNAME.setCPL(LOGICAL_PATHNAME, PATHNAME, CLASS_T); MAILBOX.setDirectSuperclass(CLASS_T); MAILBOX.setCPL(MAILBOX, CLASS_T); MUTEX.setDirectSuperclass(CLASS_T); MUTEX.setCPL(MUTEX, CLASS_T); NIL_VECTOR.setDirectSuperclass(STRING); NIL_VECTOR.setCPL(NIL_VECTOR, STRING, VECTOR, ARRAY, SEQUENCE, CLASS_T); NULL.setDirectSuperclass(LIST); NULL.setCPL(NULL, SYMBOL, LIST, SEQUENCE, CLASS_T); NUMBER.setDirectSuperclass(CLASS_T); NUMBER.setCPL(NUMBER, CLASS_T); PACKAGE.setDirectSuperclass(CLASS_T); PACKAGE.setCPL(PACKAGE, CLASS_T); PATHNAME.setDirectSuperclass(CLASS_T); PATHNAME.setCPL(PATHNAME, CLASS_T); JAR_PATHNAME.setDirectSuperclass(PATHNAME); JAR_PATHNAME.setCPL(JAR_PATHNAME, PATHNAME, CLASS_T); URL_PATHNAME.setDirectSuperclass(PATHNAME); URL_PATHNAME.setCPL(URL_PATHNAME, PATHNAME, CLASS_T); RANDOM_STATE.setDirectSuperclass(CLASS_T); RANDOM_STATE.setCPL(RANDOM_STATE, CLASS_T); RATIO.setDirectSuperclass(RATIONAL); RATIO.setCPL(RATIO, RATIONAL, REAL, NUMBER, CLASS_T); RATIONAL.setDirectSuperclass(REAL); RATIONAL.setCPL(RATIONAL, REAL, NUMBER, CLASS_T); READTABLE.setDirectSuperclass(CLASS_T); READTABLE.setCPL(READTABLE, CLASS_T); REAL.setDirectSuperclass(NUMBER); REAL.setCPL(REAL, NUMBER, CLASS_T); RESTART.setDirectSuperclass(CLASS_T); RESTART.setCPL(RESTART, CLASS_T); SEQUENCE.setDirectSuperclass(CLASS_T); SEQUENCE.setCPL(SEQUENCE, CLASS_T); SIMPLE_ARRAY.setDirectSuperclass(ARRAY); SIMPLE_ARRAY.setCPL(SIMPLE_ARRAY, ARRAY, CLASS_T); SIMPLE_BASE_STRING.setDirectSuperclasses(list(BASE_STRING, SIMPLE_STRING)); SIMPLE_BASE_STRING.setCPL(SIMPLE_BASE_STRING, BASE_STRING, SIMPLE_STRING, STRING, VECTOR, SIMPLE_ARRAY, ARRAY, SEQUENCE, CLASS_T); SIMPLE_BIT_VECTOR.setDirectSuperclasses(list(BIT_VECTOR, SIMPLE_ARRAY)); SIMPLE_BIT_VECTOR.setCPL(SIMPLE_BIT_VECTOR, BIT_VECTOR, VECTOR, SIMPLE_ARRAY, ARRAY, SEQUENCE, CLASS_T); SIMPLE_STRING.setDirectSuperclasses(list(BASE_STRING, STRING, SIMPLE_ARRAY)); SIMPLE_STRING.setCPL(SIMPLE_STRING, BASE_STRING, STRING, VECTOR, SIMPLE_ARRAY, ARRAY, SEQUENCE, CLASS_T); SIMPLE_VECTOR.setDirectSuperclasses(list(VECTOR, SIMPLE_ARRAY)); SIMPLE_VECTOR.setCPL(SIMPLE_VECTOR, VECTOR, SIMPLE_ARRAY, ARRAY, SEQUENCE, CLASS_T); SINGLE_FLOAT.setDirectSuperclass(FLOAT); SINGLE_FLOAT.setCPL(SINGLE_FLOAT, FLOAT, REAL, NUMBER, CLASS_T); SLIME_INPUT_STREAM.setCPL(SLIME_INPUT_STREAM, STRING_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); SLIME_OUTPUT_STREAM.setCPL(SLIME_OUTPUT_STREAM, STRING_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); SOCKET_STREAM.setCPL(SOCKET_STREAM, TWO_WAY_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); STREAM.setCPL(STREAM, STRUCTURE_OBJECT, CLASS_T); STRING.setDirectSuperclass(VECTOR); STRING.setCPL(STRING, VECTOR, ARRAY, SEQUENCE, CLASS_T); STRING_INPUT_STREAM.setCPL(STRING_INPUT_STREAM, STRING_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); STRING_OUTPUT_STREAM.setCPL(STRING_OUTPUT_STREAM, STRING_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); STRING_STREAM.setCPL(STRING_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); STRUCTURE_OBJECT.setCPL(STRUCTURE_OBJECT, CLASS_T); SYMBOL.setDirectSuperclass(CLASS_T); SYMBOL.setCPL(SYMBOL, CLASS_T); SYNONYM_STREAM.setCPL(SYNONYM_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); SYSTEM_STREAM.setCPL(SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); THREAD.setDirectSuperclass(CLASS_T); THREAD.setCPL(THREAD, CLASS_T); TWO_WAY_STREAM.setCPL(TWO_WAY_STREAM, SYSTEM_STREAM, STREAM, STRUCTURE_OBJECT, CLASS_T); VECTOR.setDirectSuperclasses(list(ARRAY, SEQUENCE)); VECTOR.setCPL(VECTOR, ARRAY, SEQUENCE, CLASS_T); STACK_FRAME.setDirectSuperclasses(CLASS_T); STACK_FRAME.setCPL(STACK_FRAME, CLASS_T); LISP_STACK_FRAME.setDirectSuperclasses(STACK_FRAME); LISP_STACK_FRAME.setCPL(LISP_STACK_FRAME, STACK_FRAME, CLASS_T); JAVA_STACK_FRAME.setDirectSuperclasses(STACK_FRAME); JAVA_STACK_FRAME.setCPL(JAVA_STACK_FRAME, STACK_FRAME, CLASS_T); } static { StandardClass.initializeStandardClasses(); } } abcl-src-1.9.0/src/org/armedbear/lisp/ByteArrayInputStream.java0100644 0000000 0000000 00000006135 14202767264 023165 0ustar000000000 0000000 /* * ByteArrayInputStream.java * * Copyright (C) 2010 Alessio Stalla * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ByteArrayInputStream extends Stream { private final java.io.ByteArrayInputStream byteArrayInputStream; public ByteArrayInputStream(byte[] bytes) { this(bytes, UNSIGNED_BYTE_8); //Declared in Stream.java } ByteArrayInputStream(byte[] bytes, LispObject elementType) { super(Symbol.SYSTEM_STREAM); this.elementType = elementType; initAsBinaryInputStream(byteArrayInputStream = new java.io.ByteArrayInputStream(bytes)); } @Override public LispObject typeOf() { return Symbol.STREAM; //TODO } @Override public LispObject classOf() { return BuiltInClass.STREAM; //TODO } @Override public LispObject typep(LispObject type) { return super.typep(type); //TODO } // ### %make-byte-array-input-stream // %make-byte-array-input-stream bytes &optional element-type => byte-array-input-stream private static final Primitive MAKE_BYTE_ARRAY_INPUT_STREAM = new Primitive("%make-byte-array-input-stream", PACKAGE_SYS, false, "bytes &optional element-type") { @Override public LispObject execute(LispObject bytes) { return new ByteArrayInputStream((byte[]) bytes.javaInstance(byte[].class)); } @Override public LispObject execute(LispObject bytes, LispObject elementType) { return new ByteArrayInputStream((byte[]) bytes.javaInstance(byte[].class), elementType); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/ByteArrayOutputStream.java0100644 0000000 0000000 00000011742 14223403213 023346 0ustar000000000 0000000 /* * ByteArrayOutputStream.java * * Copyright (C) 2009 Alessio Stalla * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import org.armedbear.lisp.Java.Buffers.AllocationPolicy; import static org.armedbear.lisp.Lisp.*; public final class ByteArrayOutputStream extends Stream { private final java.io.ByteArrayOutputStream byteArrayOutputStream; public ByteArrayOutputStream() { this(UNSIGNED_BYTE_8); //Declared in Stream.java } ByteArrayOutputStream(LispObject elementType) { super(Symbol.SYSTEM_STREAM); this.elementType = elementType; initAsBinaryOutputStream(byteArrayOutputStream = new java.io.ByteArrayOutputStream(2048)); // based on statistics of ABCL's own .cls files // as per 20100111, 2048 is the 70th percentile, // meaning that only 30% of all .cls files is bigger // However, *every* .cls file is bigger than 32 bytes; // we want to prevent buffer resizing } @Override public LispObject typeOf() { return Symbol.STREAM; //TODO } @Override public LispObject classOf() { return BuiltInClass.STREAM; //TODO } @Override public LispObject typep(LispObject type) { return super.typep(type); //TODO } @Override protected long _getFilePosition() { if (elementType == NIL) return 0; return byteArrayOutputStream.size(); } public byte[] getByteArray() { if (elementType == NIL) { return new byte[0]; } else { return byteArrayOutputStream.toByteArray(); } } // ### %make-byte-array-output-stream // %make-byte-array-output-stream &optional element-type => byte-array-output-stream private static final Primitive MAKE_BYTE_ARRAY_OUTPUT_STREAM = new Primitive("%make-byte-array-output-stream", PACKAGE_SYS, false, "&optional element-type") { @Override public LispObject execute() { return new ByteArrayOutputStream(); } @Override public LispObject execute(LispObject arg) { return new ByteArrayOutputStream(arg); } }; // ### %get-output-stream-bytes // %get-output-stream-bytes byte-array-output-stream => java-byte-array private static final Primitive GET_OUTPUT_STREAM_STRING = new Primitive("%get-output-stream-bytes", PACKAGE_SYS, false, "byte-array-output-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof ByteArrayOutputStream) { return JavaObject.getInstance(((ByteArrayOutputStream)arg).getByteArray()); } return type_error(this, Symbol.STREAM); //TODO } }; private static final Primitive GET_OUTPUT_STREAM_ARRAY = new Primitive("%get-output-stream-array", PACKAGE_SYS, false, "byte-array-output-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof ByteArrayOutputStream) { byte[] array = ((ByteArrayOutputStream)arg).getByteArray(); if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { return new BasicVector_ByteBuffer(array, false); } else if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { return new BasicVector_UnsignedByte8(array); } } return type_error(this, Symbol.STREAM); // TODO } }; } abcl-src-1.9.0/src/org/armedbear/lisp/CapitalizeFirstStream.java0100644 0000000 0000000 00000004514 14202767264 023337 0ustar000000000 0000000 /* * CapitalizeFirstStream.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class CapitalizeFirstStream extends CaseFrobStream { boolean virgin = true; public CapitalizeFirstStream(Stream target) { super(target); } @Override public void _writeChar(char c) { if (virgin) { if (Character.isLetterOrDigit(c)) { c = LispCharacter.toUpperCase(c); virgin = false; } } else c = LispCharacter.toLowerCase(c); target._writeChar(c); } @Override public void _writeString(String s) { final int length = s.length(); for (int i = 0; i < length; i++) _writeChar(s.charAt(i)); } @Override public void _writeLine(String s) { _writeString(s); _writeChar('\n'); } } abcl-src-1.9.0/src/org/armedbear/lisp/CapitalizeStream.java0100644 0000000 0000000 00000005272 14202767264 022331 0ustar000000000 0000000 /* * CapitalizeStream.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class CapitalizeStream extends CaseFrobStream { private boolean inWord; public CapitalizeStream(Stream target) { super(target); } @Override public void _writeChar(char c) { if (inWord) { if (Character.isUpperCase(c)) { c = LispCharacter.toLowerCase(c); } else if (!Character.isLowerCase(c) && !Character.isDigit(c)) { inWord = false; } } else { // Not in a word. if (Character.isUpperCase(c)) { inWord = true; } else if (Character.isLowerCase(c)) { c = LispCharacter.toUpperCase(c); inWord = true; } else if (Character.isDigit(c)) { inWord = true; } } target._writeChar(c); } @Override public void _writeString(String s) { final int limit = s.length(); for (int i = 0; i < limit; i++) _writeChar(s.charAt(i)); } @Override public void _writeLine(String s) { target._writeString(s); target._writeChar('\n'); } } abcl-src-1.9.0/src/org/armedbear/lisp/CaseFrobStream.java0100644 0000000 0000000 00000013123 14202767264 021722 0ustar000000000 0000000 /* * CaseFrobStream.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class CaseFrobStream extends Stream { protected final Stream target; protected CaseFrobStream(Stream target) { super(Symbol.CASE_FROB_STREAM); Debug.assertTrue(target.isCharacterOutputStream()); this.target = target; } @Override public LispObject getElementType() { return target.getElementType(); } @Override public LispObject typeOf() { return Symbol.CASE_FROB_STREAM; } @Override public LispObject classOf() { return BuiltInClass.CASE_FROB_STREAM; } @Override public LispObject typep(LispObject type) { if (type == Symbol.CASE_FROB_STREAM) return T; if (type == BuiltInClass.CASE_FROB_STREAM) return T; return super.typep(type); } @Override public boolean isInputStream() { return false; } @Override public boolean isOutputStream() { return true; } @Override public boolean isCharacterInputStream() { return false; } @Override public boolean isBinaryInputStream() { return false; } @Override public boolean isCharacterOutputStream() { return true; } @Override public boolean isBinaryOutputStream() { return false; } @Override public int getCharPos() { return target.getCharPos(); } @Override public void setCharPos(int n) { target.setCharPos(n); } // Returns -1 at end of file. @Override protected int _readChar() { notSupported(); // Not reached. return -1; } @Override protected void _unreadChar(int n) { notSupported(); } @Override protected boolean _charReady() { notSupported(); // Not reached. return false; } @Override public void _writeChars(char[] chars, int start, int end) { _writeString(new String(chars, start, end)); } // Reads an 8-bit byte. @Override public int _readByte() { notSupported(); // Not reached. return -1; } // Writes an 8-bit byte. @Override public void _writeByte(int n) { notSupported(); } @Override public void _finishOutput() { target._finishOutput(); } @Override public void _clearInput() { notSupported(); } @Override public LispObject close(LispObject abort) { setOpen(false); return T; } @Override public LispObject listen() { notSupported(); // Not reached. return NIL; } @Override public LispObject terpri() { return target.terpri(); } @Override public LispObject freshLine() { return target.freshLine(); } @Override public String printObject() { return unreadableString("CASE-FROB-STREAM"); } private void notSupported() { error(new TypeError("Operation is not supported for streams of type CASE-FROB-STREAM.")); } // ### make-case-frob-stream target => case-frob-stream private static final Primitive MAKE_CASE_FROB_STREAM = new Primitive("make-case-frob-stream", PACKAGE_SYS, false, "target kind") { @Override public LispObject execute(LispObject first, LispObject second) { Stream target = checkCharacterOutputStream(first); if (second == Keyword.UPCASE) return new UpcaseStream(target); if (second == Keyword.DOWNCASE) return new DowncaseStream(target); if (second == Keyword.CAPITALIZE) return new CapitalizeStream(target); if (second == Keyword.CAPITALIZE_FIRST) return new CapitalizeFirstStream(target); return error(new TypeError( "Kind must be :UPCASE, :DOWNCASE, :CAPITALIZE or :CAPITALIZE-FIRST.")); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/CellError.java0100644 0000000 0000000 00000007315 14202767264 020761 0ustar000000000 0000000 /* * CellError.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class CellError extends LispError { protected CellError(LispClass cls) { super(cls); } public CellError(LispObject initArgs) { super(StandardClass.CELL_ERROR); initialize(initArgs); } @Override protected void initialize(LispObject initArgs) { super.initialize(initArgs); LispObject name = NIL; while (initArgs != NIL) { LispObject first = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.NAME) { name = initArgs.car(); break; } initArgs = initArgs.cdr(); } setCellName(name); } public final LispObject getCellName() { return getInstanceSlotValue(Symbol.NAME); } protected final void setCellName(LispObject name) { setInstanceSlotValue(Symbol.NAME, name); } @Override public LispObject typeOf() { return Symbol.CELL_ERROR; } @Override public LispObject classOf() { return StandardClass.CELL_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.CELL_ERROR) return T; if (type == StandardClass.CELL_ERROR) return T; return super.typep(type); } @Override public String getMessage() { if (Symbol.PRINT_ESCAPE.symbolValue() == NIL) return super.getMessage(); StringBuffer sb = new StringBuffer(typeOf().princToString()); sb.append(' '); sb.append(getCellName().princToString()); return unreadableString(sb.toString()); } // ### cell-error-name private static final Primitive CELL_ERROR_NAME = new Primitive("cell-error-name", "condition") { @Override public LispObject execute(LispObject arg) { if (arg.typep(Symbol.CELL_ERROR) == NIL) { return type_error(arg, Symbol.CELL_ERROR); } final StandardObject obj = (StandardObject) arg; return obj.getInstanceSlotValue(Symbol.NAME); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/CharHashMap.java0100644 0000000 0000000 00000005042 14223403213 021162 0ustar000000000 0000000 package org.armedbear.lisp; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; public class CharHashMap { final public T[] constants; final public T NULL; final static int CACHE_SIZE = 256; final HashMap backing; @SuppressWarnings("unchecked") public CharHashMap(Class componentType, T def) { NULL = def; constants = (T[]) Array.newInstance(componentType, CACHE_SIZE); Arrays.fill(constants, NULL); backing = new HashMap(); } @Override public Object clone() { CharHashMap n = new CharHashMap(constants.getClass().getComponentType(),NULL); System.arraycopy(constants,0, n.constants,0,CACHE_SIZE); n.backing.putAll(backing); return n; } public T get(char key) { if (key getCharIterator() { return new Iterator() { final Iterator carIt = backing.keySet().iterator(); int charNum = -1; public boolean hasNext() { if ( charNum c2 ? T : NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; char[] chars = new char[length]; for (int i = 0; i < length; i++) chars[i] = LispCharacter.toUpperCase(LispCharacter.getValue(array[i])); for (int i = 1; i < length; i++) { if (chars[i-1] <= chars[i]) return NIL; } return T; } }; // ### char-not-greaterp private static final Primitive CHAR_NOT_GREATERP = new Primitive("char-not-greaterp", "&rest characters") { @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispCharacter) return T; return type_error(arg, Symbol.CHARACTER); } @Override public LispObject execute(LispObject first, LispObject second) { char c1 = LispCharacter.toUpperCase(LispCharacter.getValue(first)); char c2 = LispCharacter.toUpperCase(LispCharacter.getValue(second)); return c1 <= c2 ? T : NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; char[] chars = new char[length]; for (int i = 0; i < length; i++) chars[i] = LispCharacter.toUpperCase(LispCharacter.getValue(array[i])); for (int i = 1; i < length; i++) { if (chars[i] < chars[i-1]) return NIL; } return T; } }; // ### char< private static final Primitive CHAR_LESS_THAN = new Primitive("char<", "&rest characters") { @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispCharacter) return T; return type_error(arg, Symbol.CHARACTER); } @Override public LispObject execute(LispObject first, LispObject second) { return LispCharacter.getValue(first) < LispCharacter.getValue(second) ? T : NIL; } @Override public LispObject execute(LispObject[] args) { final int length = args.length; char[] chars = new char[length]; for (int i = 0; i < length; i++) { chars[i] = LispCharacter.getValue(args[i]); } for (int i = 1; i < length; i++) { if (chars[i-1] >= chars[i]) return NIL; } return T; } }; // ### char<= private static final Primitive CHAR_LE = new Primitive("char<=", "&rest characters") { @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispCharacter) return T; return type_error(arg, Symbol.CHARACTER); } @Override public LispObject execute(LispObject first, LispObject second) { return LispCharacter.getValue(first) <= LispCharacter.getValue(second) ? T : NIL; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (LispCharacter.getValue(first) > LispCharacter.getValue(second)) return NIL; if (LispCharacter.getValue(second) > LispCharacter.getValue(third)) return NIL; return T; } @Override public LispObject execute(LispObject[] args) { final int length = args.length; char[] chars = new char[length]; for (int i = 0; i < length; i++) { chars[i] = LispCharacter.getValue(args[i]); } for (int i = 1; i < length; i++) { if (chars[i-1] > chars[i]) return NIL; } return T; } }; // ### char-lessp private static final Primitive CHAR_LESSP = new Primitive("char-lessp", "&rest characters") { @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispCharacter) return T; return type_error(arg, Symbol.CHARACTER); } @Override public LispObject execute(LispObject first, LispObject second) { char c1 = LispCharacter.toUpperCase(LispCharacter.getValue(first)); char c2 = LispCharacter.toUpperCase(LispCharacter.getValue(second)); return c1 < c2 ? T : NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; char[] chars = new char[length]; for (int i = 0; i < length; i++) chars[i] = LispCharacter.toUpperCase(LispCharacter.getValue(array[i])); for (int i = 1; i < length; i++) { if (chars[i-1] >= chars[i]) return NIL; } return T; } }; // ### char-not-lessp private static final Primitive CHAR_NOT_LESSP = new Primitive("char-not-lessp", "&rest characters") { @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispCharacter) return T; return type_error(arg, Symbol.CHARACTER); } @Override public LispObject execute(LispObject first, LispObject second) { char c1 = LispCharacter.toUpperCase(LispCharacter.getValue(first)); char c2 = LispCharacter.toUpperCase(LispCharacter.getValue(second)); return c1 >= c2 ? T : NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; char[] chars = new char[length]; for (int i = 0; i < length; i++) chars[i] = LispCharacter.toUpperCase(LispCharacter.getValue(array[i])); for (int i = 1; i < length; i++) { if (chars[i] > chars[i-1]) return NIL; } return T; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Closure.java0100644 0000000 0000000 00000017434 14202767264 020507 0ustar000000000 0000000 /* * Closure.java * * Copyright (C) 2002-2008 Peter Graves * Copyright (C) 2008 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class Closure extends Function { // Parameter types. public static final int REQUIRED = 0; public static final int OPTIONAL = 1; public static final int KEYWORD = 2; public static final int REST = 3; public static final int AUX = 4; private final LispObject body; private final LispObject executionBody; private final Environment environment; private final Symbol[] freeSpecials; private final ArgumentListProcessor arglist; /** Construct a closure object with a lambda-list described * by these parameters. * * * @param required Required parameters or an empty array for none * @param optional Optional parameters or an empty array for none * @param keyword Keyword parameters or an empty array for none * @param keys NIL if the lambda-list doesn't contain &key, T otherwise * @param rest the &rest parameter, or NIL if none * @param moreKeys NIL if &allow-other-keys not present, T otherwise */ public Closure(ArgumentListProcessor arglist) { // stuff we don't need: we're a compiled function body = null; executionBody = null; environment = null; this.arglist = arglist; freeSpecials = new Symbol[0]; } public Closure(LispObject lambdaExpression, Environment env) { this(null, lambdaExpression, env); } public Closure(final LispObject name, final LispObject lambdaExpression, final Environment env) { super(name, lambdaExpression.cadr()); final LispObject lambdaList = lambdaExpression.cadr(); setLambdaList(lambdaList); if (!(lambdaList == NIL || lambdaList instanceof Cons)) program_error("The lambda list " + lambdaList.princToString() + " is invalid."); this.body = lambdaExpression.cddr(); LispObject bodyAndDecls = parseBody(this.body, false); this.executionBody = bodyAndDecls.car(); LispObject specials = parseSpecials(bodyAndDecls.NTH(1)); this.environment = env; /* In the bootstrapping process, functions with MACRO LAMBDA LIST * lambda list types are being generated using the MACRO_FUNCTION instead * of the LAMBDA or NAMED_LAMBDA keys. * * Use that to perform argument list lambda list keyword checking. */ arglist = new ArgumentListProcessor(this, lambdaList, specials, (lambdaExpression.car() == Symbol.MACRO_FUNCTION) ? ArgumentListProcessor.LambdaListType.MACRO : ArgumentListProcessor.LambdaListType.ORDINARY); freeSpecials = arglist.freeSpecials(specials); } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.COMPILED_FUNCTION) return NIL; return super.typep(typeSpecifier); } public final LispObject getVariableList() { Symbol[] variables = arglist.getVariables(); LispObject result = NIL; for (int i = variables.length; i-- > 0;) result = new Cons(variables[i], result); return result; } // Returns body as a list. public final LispObject getBody() { return body; } public final Environment getEnvironment() { return environment; } @Override public LispObject execute() { return execute(new LispObject[0]); } @Override public LispObject execute(LispObject arg) { return execute(new LispObject[] {arg}); } @Override public LispObject execute(LispObject first, LispObject second) { return execute(new LispObject[] {first, second}); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return execute(new LispObject[] {first, second, third}); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return execute(new LispObject[] {first, second, third, fourth}); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { return execute(new LispObject[] {first, second, third, fourth, fifth}); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { return execute(new LispObject[] {first, second, third, fourth, fifth, sixth}); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { return execute(new LispObject[] {first, second, third, fourth, fifth, sixth, seventh}); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { return execute(new LispObject[] {first, second, third, fourth, fifth, sixth, seventh, eighth}); } @Override public LispObject execute(LispObject[] args) { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); Environment ext = new Environment(environment); args = arglist.match(args, environment, ext, thread); arglist.bindVars(args, ext, thread); for (Symbol special : freeSpecials) ext.declareSpecial(special); try { return progn(executionBody, ext, thread); } finally { thread.resetSpecialBindings(mark); } } protected final LispObject[] processArgs(LispObject[] args, LispThread thread) { return arglist.match(args, environment, environment, thread); } //Serialization @Override protected boolean shouldSerializeByName() { return false; //Closures have an environment that we must serialize, even if they're top-level function } } abcl-src-1.9.0/src/org/armedbear/lisp/ClosureBinding.java0100644 0000000 0000000 00000003703 14202767264 021774 0ustar000000000 0000000 /* * ClosureBinding.java * * Copyright (C) 2009 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.Serializable; /** This class serves merely to store a reference to an * object, used in the closure array. * * Objects of this type are used to model the fact that * closures close over bindings and not over values. * */ public class ClosureBinding implements Serializable { public LispObject value; public ClosureBinding(LispObject value) { this.value = value; } } abcl-src-1.9.0/src/org/armedbear/lisp/CompiledClosure.java0100644 0000000 0000000 00000015245 14223403213 022142 0ustar000000000 0000000 /* * CompiledClosure.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class CompiledClosure extends Closure implements Cloneable { public ClosureBinding[] ctx; public CompiledClosure(ArgumentListProcessor arglist) { super(arglist); } public CompiledClosure(LispObject lambdaList) { super(list(Symbol.LAMBDA, lambdaList), null); } final public CompiledClosure setContext(ClosureBinding[] context) { ctx = context; return this; } final public CompiledClosure dup() { CompiledClosure result = null; try { result = (CompiledClosure)super.clone(); } catch (CloneNotSupportedException e) { } return result; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.COMPILED_FUNCTION) return T; return super.typep(typeSpecifier); } private final LispObject notImplemented() { return error(new WrongNumberOfArgumentsException(this)); } // Zero args. public LispObject execute() { LispObject[] args = new LispObject[0]; return execute(args); } // One arg. public LispObject execute( LispObject first) { LispObject[] args = new LispObject[1]; args[0] = first; return execute(args); } // Two args. public LispObject execute( LispObject first, LispObject second) { LispObject[] args = new LispObject[2]; args[0] = first; args[1] = second; return execute(args); } // Three args. public LispObject execute( LispObject first, LispObject second, LispObject third) { LispObject[] args = new LispObject[3]; args[0] = first; args[1] = second; args[2] = third; return execute(args); } // Four args. public LispObject execute( LispObject first, LispObject second, LispObject third, LispObject fourth) { LispObject[] args = new LispObject[4]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; return execute(args); } // Five args. public LispObject execute( LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { LispObject[] args = new LispObject[5]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; args[4] = fifth; return execute(args); } // Six args. public LispObject execute( LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { LispObject[] args = new LispObject[6]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; args[4] = fifth; args[5] = sixth; return execute(args); } // Seven args. public LispObject execute( LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { LispObject[] args = new LispObject[7]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; args[4] = fifth; args[5] = sixth; args[6] = seventh; return execute(args); } // Eight args. public LispObject execute( LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { LispObject[] args = new LispObject[8]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; args[4] = fifth; args[5] = sixth; args[6] = seventh; args[7] = eighth; return execute(args); } // Arg array. public LispObject execute(LispObject[] args) { return notImplemented(); } // ### load-compiled-function private static final Primitive LOAD_COMPILED_FUNCTION = new Primitive("load-compiled-function", PACKAGE_SYS, true, "source") { @Override public LispObject execute(LispObject arg) { String namestring = null; if (arg instanceof Pathname) namestring = ((Pathname)arg).getNamestring(); else if (arg instanceof AbstractString) namestring = arg.getStringValue(); if(arg instanceof JavaObject) { try { return loadClassBytes((byte[]) arg.javaInstance(byte[].class)); } catch(Throwable t) { Debug.trace(t); return error(new LispError("Unable to load " + arg.princToString())); } } return error(new LispError("Unable to load " + arg.princToString())); } }; // ### varlist private static final Primitive VARLIST = new Primitive("varlist", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject arg) { if (arg instanceof Closure) return ((Closure)arg).getVariableList(); return type_error(arg, Symbol.COMPILED_FUNCTION); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/CompiledPrimitive.java0100644 0000000 0000000 00000005631 14202767264 022514 0ustar000000000 0000000 /* * CompiledPrimitive.java * * Copyright (C) 2002-2005 Peter Graves * $Id: CompiledPrimitive.java 12826 2010-07-25 19:09:13Z vvoutilainen $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public class CompiledPrimitive extends Primitive { public CompiledPrimitive(LispObject name) { super(name); } public CompiledPrimitive(String name) { super(name); } public CompiledPrimitive(Symbol symbol) { super(symbol); } public CompiledPrimitive(Symbol symbol, String arglist) { super(symbol, arglist); } public CompiledPrimitive(Symbol symbol, String arglist, String docstring) { super(symbol, arglist, docstring); } public CompiledPrimitive(String name, String arglist) { super(name, arglist); } public CompiledPrimitive(LispObject name, LispObject lambdaList) { super(name, lambdaList); } public CompiledPrimitive(String name, Package pkg) { super(name, pkg); } public CompiledPrimitive(String name, Package pkg, boolean exported) { super(name, pkg, exported); } public CompiledPrimitive(String name, Package pkg, boolean exported, String arglist) { super(name, pkg, exported, arglist); } public CompiledPrimitive(String name, Package pkg, boolean exported, String arglist, String docstring) { super(name, pkg, exported, arglist, docstring); } } abcl-src-1.9.0/src/org/armedbear/lisp/Complex.java0100644 0000000 0000000 00000021654 14202767264 020501 0ustar000000000 0000000 /* * Complex.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class Complex extends LispObject { public final LispObject realpart; public final LispObject imagpart; private Complex(LispObject realpart, LispObject imagpart) { this.realpart = realpart; this.imagpart = imagpart; } public static LispObject getInstance(LispObject realpart, LispObject imagpart) { if (!realpart.realp()) return type_error(realpart, Symbol.REAL); if (!imagpart.realp()) return type_error(imagpart, Symbol.REAL); if (realpart instanceof DoubleFloat) imagpart = DoubleFloat.coerceToFloat(imagpart); else if (imagpart instanceof DoubleFloat) realpart = DoubleFloat.coerceToFloat(realpart); else if (realpart instanceof SingleFloat) imagpart = SingleFloat.coerceToFloat(imagpart); else if (imagpart instanceof SingleFloat) realpart = SingleFloat.coerceToFloat(realpart); if (imagpart instanceof Fixnum) { if (((Fixnum)imagpart).value == 0) return realpart; } return new Complex(realpart, imagpart); } public LispObject getRealPart() { return realpart; } public LispObject getImaginaryPart() { return imagpart; } /** Coerces the complex parts into DoubleFloats * * @return a new complex with double-float real and imaginary parts */ public LispObject coerceToDoubleFloat() { return getInstance(DoubleFloat.coerceToFloat(realpart), DoubleFloat.coerceToFloat(imagpart)); } @Override public LispObject typeOf() { return Symbol.COMPLEX; } @Override public LispObject classOf() { return BuiltInClass.COMPLEX; } @Override public LispObject typep(LispObject type) { if (type == Symbol.COMPLEX) return T; if (type == Symbol.NUMBER) return T; if (type == BuiltInClass.COMPLEX) return T; if (type == BuiltInClass.NUMBER) return T; return super.typep(type); } @Override public boolean numberp() { return true; } @Override public boolean eql(LispObject obj) { if (this == obj) return true; if (obj instanceof Complex) { Complex c = (Complex) obj; return realpart.eql(c.realpart) && imagpart.eql(c.imagpart); } return false; } @Override public boolean equal(LispObject obj) { return eql(obj); } @Override public boolean equalp(LispObject obj) { if (obj != null && obj.numberp()) return isEqualTo(obj); return false; } @Override public final LispObject incr() { return new Complex(realpart.add(Fixnum.ONE), imagpart); } @Override public final LispObject decr() { return new Complex(realpart.subtract(Fixnum.ONE), imagpart); } @Override public LispObject add(LispObject obj) { if (obj instanceof Complex) { Complex c = (Complex) obj; return getInstance(realpart.add(c.realpart), imagpart.add(c.imagpart)); } return getInstance(realpart.add(obj), imagpart); } @Override public LispObject subtract(LispObject obj) { if (obj instanceof Complex) { Complex c = (Complex) obj; return getInstance(realpart.subtract(c.realpart), imagpart.subtract(c.imagpart)); } return getInstance(realpart.subtract(obj), imagpart); } @Override public LispObject multiplyBy(LispObject obj) { if (obj instanceof Complex) { LispObject a = realpart; LispObject b = imagpart; LispObject c = ((Complex)obj).getRealPart(); LispObject d = ((Complex)obj).getImaginaryPart(); // xy = (ac - bd) + i(ad + bc) // real part = ac - bd // imag part = ad + bc LispObject ac = a.multiplyBy(c); LispObject bd = b.multiplyBy(d); LispObject ad = a.multiplyBy(d); LispObject bc = b.multiplyBy(c); return Complex.getInstance(ac.subtract(bd), ad.add(bc)); } return Complex.getInstance(realpart.multiplyBy(obj), imagpart.multiplyBy(obj)); } @Override public LispObject divideBy(LispObject obj) { if (obj instanceof Complex) { LispObject a = realpart; LispObject b = imagpart; LispObject c = ((Complex)obj).getRealPart(); LispObject d = ((Complex)obj).getImaginaryPart(); LispObject ac = a.multiplyBy(c); LispObject bd = b.multiplyBy(d); LispObject bc = b.multiplyBy(c); LispObject ad = a.multiplyBy(d); LispObject denominator = c.multiplyBy(c).add(d.multiplyBy(d)); return Complex.getInstance(ac.add(bd).divideBy(denominator), bc.subtract(ad).divideBy(denominator)); } return Complex.getInstance(realpart.divideBy(obj), imagpart.divideBy(obj)); } @Override public boolean isEqualTo(LispObject obj) { if (obj instanceof Complex) { Complex c = (Complex) obj; return (realpart.isEqualTo(c.realpart) && imagpart.isEqualTo(c.imagpart)); } if (obj.numberp()) { // obj is a number, but not complex. if (imagpart instanceof SingleFloat) { if (((SingleFloat)imagpart).value == 0) { if (obj instanceof Fixnum) return ((Fixnum)obj).value == ((SingleFloat)realpart).value; if (obj instanceof SingleFloat) return ((SingleFloat)obj).value == ((SingleFloat)realpart).value; if (obj instanceof DoubleFloat) return ((DoubleFloat)obj).value == ((SingleFloat)realpart).value; } } if (imagpart instanceof DoubleFloat) { if (((DoubleFloat)imagpart).value == 0) { if (obj instanceof Fixnum) return ((Fixnum)obj).value == ((DoubleFloat)realpart).value; if (obj instanceof SingleFloat) return ((SingleFloat)obj).value == ((DoubleFloat)realpart).value; if (obj instanceof DoubleFloat) return ((DoubleFloat)obj).value == ((DoubleFloat)realpart).value; } } return false; } type_error(obj, Symbol.NUMBER); // Not reached. return false; } @Override public boolean isNotEqualTo(LispObject obj) { return !isEqualTo(obj); } @Override public LispObject ABS() { if (realpart.zerop()) return imagpart.ABS(); double real = DoubleFloat.coerceToFloat(realpart).value; double imag = DoubleFloat.coerceToFloat(imagpart).value; if (realpart instanceof DoubleFloat) return new DoubleFloat(Math.hypot(real, imag)); else return new SingleFloat((float)Math.hypot(real, imag)); } @Override public boolean zerop() { return realpart.zerop() && imagpart.zerop(); } @Override public LispObject COMPLEXP() { return T; } @Override public int sxhash() { return (mix(realpart.sxhash(), imagpart.sxhash()) & 0x7fffffff); } @Override public int psxhash() { return (mix(realpart.psxhash(), imagpart.psxhash()) & 0x7fffffff); } @Override public String printObject() { StringBuilder sb = new StringBuilder("#C("); sb.append(realpart.printObject()); sb.append(' '); sb.append(imagpart.printObject()); sb.append(')'); return sb.toString(); } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexArray.java0100644 0000000 0000000 00000021526 14202767264 021476 0ustar000000000 0000000 /* * ComplexArray.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ComplexArray extends AbstractArray { private final int[] dimv; private final LispObject elementType; private int totalSize; // For non-displaced arrays. private LispObject[] data; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexArray(int[] dimv, LispObject elementType) { this.dimv = dimv; this.elementType = elementType; totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; for (int i = totalSize; i-- > 0;) data[i] = Fixnum.ZERO; } public ComplexArray(int[] dimv, LispObject elementType, LispObject initialContents) { this.dimv = dimv; this.elementType = elementType; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; setInitialContents(0, dimv, initialContents, 0); } public ComplexArray(int[] dimv, AbstractArray array, int displacement) { this.dimv = dimv; this.elementType = array.getElementType(); this.array = array; this.displacement = displacement; totalSize = computeTotalSize(dimv); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data[index] = contents; } catch (ArrayIndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.ARRAY, elementType, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.ARRAY; } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return elementType; } @Override public int getTotalSize() { return totalSize; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject AREF(int index) { if (data != null) { try { return data[index]; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } else return array.AREF(index + displacement); } @Override public void aset(int index, LispObject newValue) { if (data != null) { try { data[index] = newValue; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } else array.aset(index + displacement, newValue); } @Override public void fill(LispObject obj) { if (data != null) { for (int i = data.length; i-- > 0;) data[i] = obj; } else { for (int i = totalSize; i-- > 0;) aset(i, obj); } } @Override public String printObject() { return printObject(dimv); } @Override public AbstractArray adjustArray(int[] dims, LispObject initialElement, LispObject initialContents) { if (isAdjustable()) { if (initialContents != null) setInitialContents(0, dims, initialContents, 0); else { //### FIXME Take the easy way out: we don't want to reorganize // all of the array code yet SimpleArray_T tempArray = new SimpleArray_T(dims, elementType); if (initialElement != null) tempArray.fill(initialElement); SimpleArray_T.copyArray(this, tempArray); this.data = tempArray.data; for (int i = 0; i < dims.length; i++) dimv[i] = dims[i]; } return this; } else { if (initialContents != null) return new ComplexArray(dims, elementType, initialContents); else { ComplexArray newArray = new ComplexArray(dims, elementType); if (initialElement != null) newArray.fill(initialElement); return newArray; } } } @Override public AbstractArray adjustArray(int[] dims, AbstractArray displacedTo, int displacement) { if (isAdjustable()) { for (int i = 0; i < dims.length; i++) dimv[i] = dims[i]; this.data = null; this.array = displacedTo; this.displacement = displacement; this.totalSize = computeTotalSize(dims); return this; } else { ComplexArray a = new ComplexArray(dims, displacedTo, displacement); return a; } } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexArray_ByteBuffer.java0100644 0000000 0000000 00000022604 14202767264 023611 0ustar000000000 0000000 /* * ComplexArray_ByteBuffer.java * * Copyright (C) 2020 easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; public final class ComplexArray_ByteBuffer extends AbstractArray { private final int[] dimv; private int totalSize; // For non-displaced arrays. private ByteBuffer data; private boolean directAllocation; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexArray_ByteBuffer(int[] dimv) { this(dimv, false); } public ComplexArray_ByteBuffer(int[] dimv, boolean directAllocation) { this.dimv = dimv; this.directAllocation = directAllocation; totalSize = computeTotalSize(dimv); if (directAllocation) { data = ByteBuffer.allocateDirect(totalSize); } else { data = ByteBuffer.allocate(totalSize); } } public ComplexArray_ByteBuffer(int[] dimv, LispObject initialContents) { this(dimv, initialContents, false); } public ComplexArray_ByteBuffer(int[] dimv, LispObject initialContents, boolean directAllocation) { this.dimv = dimv; final int rank = dimv.length; LispObject rest = initialContents; this.directAllocation = directAllocation; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); if (directAllocation) { data = ByteBuffer.allocateDirect(totalSize); } else { data = ByteBuffer.allocate(totalSize); } setInitialContents(0, dimv, initialContents, 0); } public ComplexArray_ByteBuffer(int[] dimv, AbstractArray array, int displacement) { this(dimv, array, displacement, false); } public ComplexArray_ByteBuffer(int[] dimv, AbstractArray array, int displacement, boolean directAllocation) { this.dimv = dimv; this.array = array; this.displacement = displacement; this.directAllocation = directAllocation; totalSize = computeTotalSize(dimv); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data.put(index, coerceToJavaByte(contents)); } catch (IndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.ARRAY, UNSIGNED_BYTE_8, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.ARRAY; } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_8; } @Override public int getTotalSize() { return totalSize; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject AREF(int index) { if (data != null) { try { return coerceFromJavaByte(data.get(index)); } catch (IndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } else return array.AREF(index + displacement); } @Override public void aset(int index, LispObject newValue) { if (data != null) { try { data.put(index, coerceToJavaByte(newValue)); } catch (IndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } else array.aset(index + displacement, newValue); } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 255) { type_error(obj, UNSIGNED_BYTE_8); // Not reached. return; } if (data != null) { for (int i = ((java.nio.Buffer)data).limit(); i-- > 0;) data.put(i, (byte) n); // FIXME Faster!! } else { for (int i = totalSize; i-- > 0;) aset(i, obj); } } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } return printObject(dimv); } int arrayTotalSize(int[] dims) { int result = 0; for (int dim : dims) { result += dim; } return result; } // FIXME move me to someplace more general public static void fill(ByteBuffer buffer, byte value) { for (int i = 0; i < ((java.nio.Buffer)buffer).limit(); i++) { buffer.put(i, value); } } @Override public AbstractArray adjustArray(int[] dims, LispObject initialElement, LispObject initialContents) { if (isAdjustable()) { if (initialContents != null) setInitialContents(0, dims, initialContents, 0); else { //### FIXME Take the easy way out: we don't want to reorganize // all of the array code yet // SimpleArray_ByteBuffer newBuffer = new SimpleArray_ByteBuffer(dims); ByteBuffer newBuffer; if (directAllocation) { newBuffer = ByteBuffer.allocateDirect(computeTotalSize(dims)); } else { newBuffer = ByteBuffer.allocate(computeTotalSize(dims)); } if (initialElement != null) { fill(newBuffer, coerceToJavaByte(initialElement)); } this.data = newBuffer; for (int i = 0; i < dims.length; i++) dimv[i] = dims[i]; } return this; } else { if (initialContents != null) return new ComplexArray_ByteBuffer(dims, initialContents); else { ComplexArray_ByteBuffer newArray = new ComplexArray_ByteBuffer(dims); if (initialElement != null) newArray.fill(initialElement); return newArray; } } } @Override public AbstractArray adjustArray(int[] dims, AbstractArray displacedTo, int displacement) { if (isAdjustable()) { for (int i = 0; i < dims.length; i++) dimv[i] = dims[i]; this.data = null; this.array = displacedTo; this.displacement = displacement; this.totalSize = computeTotalSize(dims); return this; } else { ComplexArray_ByteBuffer a = new ComplexArray_ByteBuffer(dims, displacedTo, displacement); return a; } } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexArray_IntBuffer.java0100644 0000000 0000000 00000022256 14202767264 023443 0ustar000000000 0000000 /* * ComplexArray_IntBuffer.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; import java.nio.IntBuffer; public final class ComplexArray_IntBuffer extends AbstractArray { private final int[] dimv; private int totalSize; // For non-displaced arrays. private IntBuffer data; private boolean directAllocation; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexArray_IntBuffer(int[] dimv) { this(dimv, false); } public ComplexArray_IntBuffer(int[] dimv, boolean directAllocation) { this.dimv = dimv; this.directAllocation = directAllocation; totalSize = computeTotalSize(dimv); if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(totalSize * 4); data = b.asIntBuffer(); } else { data = IntBuffer.allocate(totalSize); } } public ComplexArray_IntBuffer(int[] dimv, LispObject initialContents) { this(dimv, initialContents, false); } public ComplexArray_IntBuffer(int[] dimv, LispObject initialContents, boolean directAllocation) { this.dimv = dimv; this.directAllocation = directAllocation; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(totalSize * 4); data = b.asIntBuffer(); } else { data = IntBuffer.allocate(totalSize); } setInitialContents(0, dimv, initialContents, 0); } public ComplexArray_IntBuffer(int[] dimv, AbstractArray array, int displacement) { this(dimv, array, displacement, false); } public ComplexArray_IntBuffer(int[] dimv, AbstractArray array, int displacement, boolean directAllocation) { this.dimv = dimv; this.array = array; this.displacement = displacement; this.directAllocation = directAllocation; totalSize = computeTotalSize(dimv); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data.put(index,(int)(contents.longValue() & 0xffffffffL)); } catch (IndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) { newDims[i-1] = dims[i]; } if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.ARRAY, UNSIGNED_BYTE_32, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.ARRAY; } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) { result = new Cons(Fixnum.getInstance(dimv[i]), result); } return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_32; } @Override public int getTotalSize() { return totalSize; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject AREF(int index) { if (data != null) { try { return number(((long)data.get(index)) & 0xffffffffL); } catch (IndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } else return array.AREF(index + displacement); } @Override public void aset(int index, LispObject newValue) { if (data != null) { try { if (newValue.isLessThan(Fixnum.ZERO) || newValue.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(newValue, UNSIGNED_BYTE_32); } data.put(index, (int)(newValue.longValue() & 0xffffffffL)); } catch (IndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } else array.aset(index + displacement, newValue); } @Override public void fill(LispObject obj) { if (!(obj instanceof LispInteger)) { type_error(obj, Symbol.INTEGER); // Not reached. return; } if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(obj, UNSIGNED_BYTE_32); } if (data != null) { for (int i = ((java.nio.Buffer)data).limit(); i-- > 0;) { data.put(i, (int) (obj.longValue() & 0xffffffffL));; } } else { for (int i = totalSize; i-- > 0;) aset(i, obj); } } @Override public String printObject() { return printObject(dimv); } @Override public AbstractArray adjustArray(int[] dims, LispObject initialElement, LispObject initialContents) { if (isAdjustable()) { if (initialContents != null) { setInitialContents(0, dims, initialContents, 0); } else { //### FIXME Take the easy way out: we don't want to reorganize // all of the array code yet // ME 20200710: I don't understand why this is the "easy way" SimpleArray_IntBuffer tempArray = new SimpleArray_IntBuffer(dims); if (initialElement != null) { tempArray.fill(initialElement); } SimpleArray_IntBuffer.copyArray(this, tempArray); this.data = tempArray.data; for (int i = 0; i < dims.length; i++) { dimv[i] = dims[i]; } } return this; } else { if (initialContents != null) { return new ComplexArray_IntBuffer(dims, initialContents); } else { ComplexArray_IntBuffer newArray = new ComplexArray_IntBuffer(dims); if (initialElement != null) { newArray.fill(initialElement); } return newArray; } } } @Override public AbstractArray adjustArray(int[] dims, AbstractArray displacedTo, int displacement) { if (isAdjustable()) { for (int i = 0; i < dims.length; i++) { dimv[i] = dims[i]; } this.data = null; this.array = displacedTo; this.displacement = displacement; this.totalSize = computeTotalSize(dims); return this; } else { ComplexArray_IntBuffer a = new ComplexArray_IntBuffer(dims, displacedTo, displacement); return a; } } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexArray_UnsignedByte32.java0100644 0000000 0000000 00000022140 14202767264 024314 0ustar000000000 0000000 /* * ComplexArray_UnsignedByte32.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ComplexArray_UnsignedByte32 extends AbstractArray { private final int[] dimv; private int totalSize; // For non-displaced arrays. // FIXME We should really use an array of unboxed values! private LispObject[] data; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexArray_UnsignedByte32(int[] dimv) { this.dimv = dimv; totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; for (int i = totalSize; i-- > 0;) data[i] = NIL; } public ComplexArray_UnsignedByte32(int[] dimv, LispObject initialContents) { this.dimv = dimv; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; setInitialContents(0, dimv, initialContents, 0); } public ComplexArray_UnsignedByte32(int[] dimv, AbstractArray array, int displacement) { this.dimv = dimv; this.array = array; this.displacement = displacement; totalSize = computeTotalSize(dimv); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data[index] = contents; } catch (ArrayIndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.ARRAY, UNSIGNED_BYTE_32, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.ARRAY; } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_32; } @Override public int getTotalSize() { return totalSize; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject AREF(int index) { if (data != null) { try { return data[index]; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } else return array.AREF(index + displacement); } @Override public void aset(int index, LispObject newValue) { if (data != null) { try { data[index] = newValue; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } else array.aset(index + displacement, newValue); } @Override public void fill(LispObject obj) { if (!(obj instanceof LispInteger)) { type_error(obj, Symbol.INTEGER); // Not reached. return; } if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(obj, UNSIGNED_BYTE_32); } if (data != null) { for (int i = data.length; i-- > 0;) data[i] = obj; } else { for (int i = totalSize; i-- > 0;) aset(i, obj); } } @Override public String printObject() { return printObject(dimv); } @Override public AbstractArray adjustArray(int[] dims, LispObject initialElement, LispObject initialContents) { if (isAdjustable()) { if (initialContents != null) setInitialContents(0, dims, initialContents, 0); else { //### FIXME Take the easy way out: we don't want to reorganize // all of the array code yet SimpleArray_UnsignedByte32 tempArray = new SimpleArray_UnsignedByte32(dims); if (initialElement != null) tempArray.fill(initialElement); SimpleArray_UnsignedByte32.copyArray(this, tempArray); this.data = tempArray.data; for (int i = 0; i < dims.length; i++) dimv[i] = dims[i]; } return this; } else { if (initialContents != null) return new ComplexArray_UnsignedByte32(dims, initialContents); else { ComplexArray_UnsignedByte32 newArray = new ComplexArray_UnsignedByte32(dims); if (initialElement != null) newArray.fill(initialElement); return newArray; } } } @Override public AbstractArray adjustArray(int[] dims, AbstractArray displacedTo, int displacement) { if (isAdjustable()) { for (int i = 0; i < dims.length; i++) dimv[i] = dims[i]; this.data = null; this.array = displacedTo; this.displacement = displacement; this.totalSize = computeTotalSize(dims); return this; } else { ComplexArray_UnsignedByte32 a = new ComplexArray_UnsignedByte32(dims, displacedTo, displacement); return a; } } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexArray_UnsignedByte8.java0100644 0000000 0000000 00000022243 14202767264 024243 0ustar000000000 0000000 /* * ComplexArray_UnsignedByte8.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ComplexArray_UnsignedByte8 extends AbstractArray { private final int[] dimv; private int totalSize; // For non-displaced arrays. private byte[] data; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexArray_UnsignedByte8(int[] dimv) { this.dimv = dimv; totalSize = computeTotalSize(dimv); data = new byte[totalSize]; } public ComplexArray_UnsignedByte8(int[] dimv, LispObject initialContents) { this.dimv = dimv; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new byte[totalSize]; setInitialContents(0, dimv, initialContents, 0); } public ComplexArray_UnsignedByte8(int[] dimv, AbstractArray array, int displacement) { this.dimv = dimv; this.array = array; this.displacement = displacement; totalSize = computeTotalSize(dimv); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data[index] = coerceToJavaByte(contents); } catch (ArrayIndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.ARRAY, UNSIGNED_BYTE_8, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.ARRAY; } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_8; } @Override public int getTotalSize() { return totalSize; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject AREF(int index) { if (data != null) { try { return coerceFromJavaByte(data[index]); } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } else return array.AREF(index + displacement); } @Override public void aset(int index, LispObject newValue) { if (data != null) { try { data[index] = coerceToJavaByte(newValue); } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } else array.aset(index + displacement, newValue); } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 255) { type_error(obj, UNSIGNED_BYTE_8); // Not reached. return; } if (data != null) { for (int i = data.length; i-- > 0;) data[i] = (byte) n; } else { for (int i = totalSize; i-- > 0;) aset(i, obj); } } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } return printObject(dimv); } @Override public AbstractArray adjustArray(int[] dims, LispObject initialElement, LispObject initialContents) { if (isAdjustable()) { if (initialContents != null) setInitialContents(0, dims, initialContents, 0); else { //### FIXME Take the easy way out: we don't want to reorganize // all of the array code yet SimpleArray_UnsignedByte8 tempArray = new SimpleArray_UnsignedByte8(dims); if (initialElement != null) tempArray.fill(initialElement); SimpleArray_UnsignedByte8.copyArray(this, tempArray); this.data = tempArray.data; for (int i = 0; i < dims.length; i++) dimv[i] = dims[i]; } return this; } else { if (initialContents != null) return new ComplexArray_UnsignedByte8(dims, initialContents); else { ComplexArray_UnsignedByte8 newArray = new ComplexArray_UnsignedByte8(dims); if (initialElement != null) newArray.fill(initialElement); return newArray; } } } @Override public AbstractArray adjustArray(int[] dims, AbstractArray displacedTo, int displacement) { if (isAdjustable()) { for (int i = 0; i < dims.length; i++) dimv[i] = dims[i]; this.data = null; this.array = displacedTo; this.displacement = displacement; this.totalSize = computeTotalSize(dims); return this; } else { ComplexArray_UnsignedByte8 a = new ComplexArray_UnsignedByte8(dims, displacedTo, displacement); return a; } } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexBitVector.java0100644 0000000 0000000 00000027454 14202767264 022327 0ustar000000000 0000000 /* * ComplexBitVector.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ComplexBitVector extends AbstractBitVector { private int fillPointer = -1; // -1 indicates no fill pointer. private boolean isDisplaced; // For displaced bit vectors. private AbstractArray array; private int displacement; public ComplexBitVector(int capacity) { this.capacity = capacity; int size = capacity >>> 6; if ((capacity & LONG_MASK) != 0) ++size; bits = new long[size]; } public ComplexBitVector(int capacity, AbstractArray array, int displacement) { this.capacity = capacity; this.array = array; this.displacement = displacement; isDisplaced = true; } @Override public LispObject typeOf() { return list(Symbol.BIT_VECTOR, Fixnum.getInstance(capacity)); } @Override public boolean hasFillPointer() { return fillPointer >= 0; } @Override public int getFillPointer() { return fillPointer; } @Override public void setFillPointer(int n) { fillPointer = n; } @Override public void setFillPointer(LispObject obj) { if (obj == T) fillPointer = capacity(); else { int n = Fixnum.getValue(obj); if (n > capacity()) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") exceeds the capacity of the vector ("); sb.append(capacity()); sb.append(")."); error(new LispError(sb.toString())); } else if (n < 0) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") is negative."); error(new LispError(sb.toString())); } else fillPointer = n; } } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public int length() { return fillPointer >= 0 ? fillPointer : capacity; } @Override public LispObject elt(int index) { if (index >= length()) badIndex(index, length()); return AREF(index); } @Override public LispObject AREF(int index) { if (index < 0 || index >= capacity) badIndex(index, capacity); if (bits != null) { int offset = index >> 6; return (bits[offset] & (1L << index)) != 0 ? Fixnum.ONE : Fixnum.ZERO; } else { // Displaced bit vector. return array.AREF(index + displacement); } } @Override protected int getBit(int index) { if (bits != null) { int offset = index >> 6; return (bits[offset] & (1L << index)) != 0 ? 1 : 0; } else return Fixnum.getValue(array.AREF(index + displacement)); } @Override public void aset(int index, LispObject newValue) { if (index < 0 || index >= capacity) badIndex(index, capacity); if (newValue instanceof Fixnum) { switch (((Fixnum)newValue).value) { case 0: if (bits != null) { final int offset = index >> 6; bits[offset] &= ~(1L << index); } else clearBit(index); return; case 1: if (bits != null) { final int offset = index >> 6; bits[offset] |= 1L << index; } else setBit(index); return; } } // Fall through... type_error(newValue, Symbol.BIT); } @Override protected void setBit(int index) { if (bits != null) { int offset = index >> 6; bits[offset] |= 1L << index; } else array.aset(index + displacement, Fixnum.ONE); } @Override protected void clearBit(int index) { if (bits != null) { int offset = index >> 6; bits[offset] &= ~(1L << index); } else array.aset(index + displacement, Fixnum.ZERO); } @Override public void shrink(int n) { if (bits != null) { if (n < capacity) { int size = n >>> 6; if ((n & LONG_MASK) != 0) ++size; if (size < bits.length) { long[] newbits = new long[size]; System.arraycopy(bits, 0, newbits, 0, size); bits = newbits; } capacity = n; return; } if (n == capacity) return; } error(new LispError()); } @Override public boolean isSimpleVector() { return false; } // FIXME @Override public void vectorPushExtend(LispObject element) { final int fp = getFillPointer(); if (fp < 0) noFillPointer(); if (fp >= capacity()) { // Need to extend vector. ensureCapacity(capacity() * 2 + 1); } aset(fp, element); setFillPointer(fp + 1); } // FIXME @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element) { vectorPushExtend(element); return Fixnum.getInstance(getFillPointer() - 1); } // FIXME @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) { int ext = Fixnum.getValue(extension); final int fp = getFillPointer(); if (fp < 0) noFillPointer(); if (fp >= capacity()) { // Need to extend vector. ext = Math.max(ext, capacity() + 1); ensureCapacity(capacity() + ext); } aset(fp, element); setFillPointer(fp + 1); return Fixnum.getInstance(fp); } private final void ensureCapacity(int minCapacity) { if (bits != null) { if (capacity < minCapacity) { int size = minCapacity >>> 6; if ((minCapacity & LONG_MASK) != 0) ++size; long[] newBits = new long[size]; System.arraycopy(bits, 0, newBits, 0, bits.length); bits = newBits; capacity = minCapacity; } } else { Debug.assertTrue(array != null); if (capacity < minCapacity || array.getTotalSize() - displacement < minCapacity) { // Copy array. int size = minCapacity >>> 6; if ((minCapacity & LONG_MASK) != 0) ++size; bits = new long[size]; final int limit = Math.min(capacity, array.getTotalSize() - displacement); for (int i = 0; i < limit; i++) { int n = Fixnum.getValue(array.AREF(displacement + i)); if (n == 1) setBit(i); else clearBit(i); } capacity = minCapacity; array = null; displacement = 0; isDisplaced = false; } } } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (bits == null) { // Copy array. int size = capacity >>> 6; if ((capacity & LONG_MASK) != 0) ++size; bits = new long[size]; for (int i = 0; i < capacity; i++) { int n = Fixnum.getValue(array.AREF(displacement + i)); if (n == 1) setBit(i); else clearBit(i); } array = null; displacement = 0; isDisplaced = false; } if (capacity != newCapacity) { int size = newCapacity >>> 6; if ((newCapacity & LONG_MASK) != 0) ++size; if (initialContents != null) { bits = new long[size]; capacity = newCapacity; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { aset(i, list.car()); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) aset(i, initialContents.elt(i)); } else type_error(initialContents, Symbol.SEQUENCE); } else { long[] newBits = new long[size]; System.arraycopy(bits, 0, newBits, 0, Math.min(bits.length, newBits.length)); bits = newBits; if (newCapacity > capacity && initialElement != null) { int n = Fixnum.getValue(initialElement); if (n == 1) for (int i = capacity; i < newCapacity; i++) setBit(i); else for (int i = capacity; i < newCapacity; i++) clearBit(i); } } capacity = newCapacity; } return this; } @Override public AbstractVector adjustArray(int size, AbstractArray displacedTo, int displacement) { capacity = size; array = displacedTo; this.displacement = displacement; bits = null; isDisplaced = true; return this; } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexString.java0100644 0000000 0000000 00000037470 14202767264 021673 0ustar000000000 0000000 /* * ComplexString.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ComplexString extends AbstractString { private int capacity; private int fillPointer = -1; // -1 indicates no fill pointer. private boolean isDisplaced; // For non-displaced arrays. private char[] chars; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexString(int capacity) { this.capacity = capacity; chars = new char[capacity]; isDisplaced = false; } public ComplexString(int capacity, AbstractArray array, int displacement) { this.capacity = capacity; this.array = array; this.displacement = displacement; isDisplaced = true; } @Override public LispObject typeOf() { return list(Symbol.STRING, number(capacity())); } @Override public LispObject classOf() { return BuiltInClass.STRING; } @Override public boolean hasFillPointer() { return fillPointer >= 0; } @Override public int getFillPointer() { return fillPointer; } @Override public void setFillPointer(int n) { fillPointer = n; } @Override public void setFillPointer(LispObject obj) { if (obj == T) fillPointer = capacity(); else { int n = Fixnum.getValue(obj); if (n > capacity()) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") exceeds the capacity of the vector ("); sb.append(capacity()); sb.append(")."); error(new LispError(sb.toString())); } else if (n < 0) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") is negative."); error(new LispError(sb.toString())); } else fillPointer = n; } } @Override public boolean isDisplaced() { return isDisplaced; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public char[] chars() { if (chars != null) return chars; Debug.assertTrue(array != null); char[] copy = new char[capacity]; if (array instanceof AbstractString) System.arraycopy(array.chars(), displacement, copy, 0, capacity); else if (array.getElementType() == Symbol.CHARACTER) { for (int i = 0; i < capacity; i++) { LispObject obj = array.AREF(displacement + i); copy[i] = LispCharacter.getValue(obj); } } else type_error(array, Symbol.STRING); return copy; } @Override public char[] getStringChars() { if (fillPointer < 0) return chars(); char[] ret = new char[fillPointer]; System.arraycopy(chars(), 0, ret, 0, fillPointer); return ret; } @Override public boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof AbstractString) { AbstractString string = (AbstractString) obj; if (string.length() != length()) return false; for (int i = length(); i-- > 0;) if (string.charAt(i) != charAt(i)) return false; return true; } if (obj instanceof NilVector) return obj.equal(this); return false; } @Override public boolean equalp(LispObject obj) { if (this == obj) return true; if (obj instanceof AbstractString) { AbstractString string = (AbstractString) obj; if (string.length() != length()) return false; for (int i = length(); i-- > 0;) { if (string.charAt(i) != charAt(i)) { if (LispCharacter.toLowerCase(string.charAt(i)) != LispCharacter.toLowerCase(charAt(i))) return false; } } return true; } if (obj instanceof AbstractBitVector) return false; if (obj instanceof AbstractArray) return obj.equalp(this); return false; } @Override public LispObject subseq(int start, int end) { SimpleString s = new SimpleString(end - start); int i = start, j = 0; while (i < end) s.setCharAt(j++, charAt(i++)); return s; } @Override public void fill(LispObject obj) { fill(LispCharacter.getValue(obj)); } @Override public void fill(char c) { for (int i = length(); i-- > 0;) setCharAt(i, c); } @Override public void shrink(int n) { if (chars != null) { if (n < capacity) { char[] newArray = new char[n]; System.arraycopy(chars, 0, newArray, 0, n); chars = newArray; capacity = n; fillPointer = -1; return; } if (n == capacity) return; } Debug.assertTrue(chars == null); // Displaced array. Copy existing characters. chars = new char[n]; if (array instanceof AbstractString) { AbstractString string = (AbstractString) array; for (int i = 0; i < n; i++) { chars[i] = string.charAt(displacement + i); } } else { for (int i = 0; i < n; i++) { LispCharacter character = (LispCharacter) array.AREF(displacement + i); chars[i] = character.value; } } capacity = n; array = null; displacement = 0; isDisplaced = false; fillPointer = -1; } @Override public LispObject reverse() { int length = length(); SimpleString result = new SimpleString(length); int i, j; for (i = 0, j = length - 1; i < length; i++, j--) result.setCharAt(i, charAt(j)); return result; } @Override public LispObject nreverse() { int i = 0; int j = length() - 1; while (i < j) { char temp = charAt(i); setCharAt(i, charAt(j)); setCharAt(j, temp); ++i; --j; } return this; } @Override public String getStringValue() { if (fillPointer >= 0) return new String(chars(), 0, fillPointer); else return new String(chars()); } @Override public Object javaInstance() { return new String(getStringValue()); } @Override public Object javaInstance(Class c) { return javaInstance(); } @Override public final int capacity() { return capacity; } @Override public final int length() { return fillPointer >= 0 ? fillPointer : capacity; } @Override public char charAt(int index) { if (chars != null) { try { return chars[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return 0; // Not reached. } } else return LispCharacter.getValue(array.AREF(index + displacement)); } @Override public void setCharAt(int index, char c) { if (chars != null) { try { chars[index] = c; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } else array.aset(index + displacement, LispCharacter.getInstance(c)); } @Override public LispObject elt(int index) { final int limit = length(); if (index < 0 || index >= limit) badIndex(index, limit); return LispCharacter.getInstance(charAt(index)); } // Ignores fill pointer. @Override public LispObject CHAR(int index) { return LispCharacter.getInstance(charAt(index)); } // Ignores fill pointer. @Override public LispObject AREF(int index) { return LispCharacter.getInstance(charAt(index)); } @Override public void aset(int index, LispObject newValue) { setCharAt(index, LispCharacter.getValue(newValue)); } @Override public void vectorPushExtend(LispObject element) { if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ensureCapacity(capacity * 2 + 1); } if (chars != null) { chars[fillPointer] = LispCharacter.getValue(element); } else array.aset(fillPointer + displacement, element); ++fillPointer; } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element) { vectorPushExtend(element); return Fixnum.getInstance(fillPointer - 1); } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) { int ext = Fixnum.getValue(extension); if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ext = Math.max(ext, capacity + 1); ensureCapacity(capacity + ext); } if (chars != null) { chars[fillPointer] = LispCharacter.getValue(element); } else array.aset(fillPointer + displacement, element); return Fixnum.getInstance(fillPointer++); } public final void ensureCapacity(int minCapacity) { if (chars != null) { if (capacity < minCapacity) { char[] newArray = new char[minCapacity]; System.arraycopy(chars, 0, newArray, 0, capacity); chars = newArray; capacity = minCapacity; } } else { Debug.assertTrue(array != null); if (capacity < minCapacity || array.getTotalSize() - displacement < minCapacity) { // Copy array. chars = new char[minCapacity]; final int limit = Math.min(capacity, array.getTotalSize() - displacement); if (array instanceof AbstractString) { AbstractString string = (AbstractString) array; for (int i = 0; i < limit; i++) { chars[i] = string.charAt(displacement + i); } } else { for (int i = 0; i < limit; i++) { LispCharacter character = (LispCharacter) array.AREF(displacement + i); chars[i] = character.value; } } capacity = minCapacity; array = null; displacement = 0; isDisplaced = false; } } } @Override public int sxhash() { int hashCode = randomStringHashBase; final int limit = length(); for (int i = 0; i < limit; i++) { hashCode += charAt(i); hashCode += (hashCode << 10); hashCode ^= (hashCode >> 6); } hashCode += (hashCode << 3); hashCode ^= (hashCode >> 11); hashCode += (hashCode << 15); return (hashCode & 0x7fffffff); } // For EQUALP hash tables. @Override public int psxhash() { int hashCode = randomStringHashBase; final int limit = length(); for (int i = 0; i < limit; i++) { hashCode += Character.toUpperCase(charAt(i)); hashCode += (hashCode << 10); hashCode ^= (hashCode >> 6); } hashCode += (hashCode << 3); hashCode ^= (hashCode >> 11); hashCode += (hashCode << 15); return (hashCode & 0x7fffffff); } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE- // ARRAY. In this case none of the original contents of array // appears in the resulting array." char[] newChars = new char[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newChars[i] = LispCharacter.getValue(list.car()); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newChars[i] = LispCharacter.getValue(initialContents.elt(i)); } else type_error(initialContents, Symbol.SEQUENCE); chars = newChars; } else { if (chars == null) { // Displaced array. Copy existing characters. chars = new char[newCapacity]; final int limit = Math.min(capacity, newCapacity); if (array instanceof AbstractString) { AbstractString string = (AbstractString) array; for (int i = 0; i < limit; i++) { chars[i] = string.charAt(displacement + i); } } else { for (int i = 0; i < limit; i++) { LispCharacter character = (LispCharacter) array.AREF(displacement + i); chars[i] = character.value; } } } else if (capacity != newCapacity) { char[] newElements = new char[newCapacity]; System.arraycopy(chars, 0, newElements, 0, Math.min(capacity, newCapacity)); chars = newElements; } if (initialElement != null && capacity < newCapacity) { // Initialize new elements. final char c = LispCharacter.getValue(initialElement); for (int i = capacity; i < newCapacity; i++) chars[i] = c; } } capacity = newCapacity; array = null; displacement = 0; isDisplaced = false; return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { capacity = newCapacity; array = displacedTo; this.displacement = displacement; chars = null; isDisplaced = true; return this; } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexVector.java0100644 0000000 0000000 00000030721 14202767264 021657 0ustar000000000 0000000 /* * ComplexVector.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // A vector that is displaced to another array, has a fill pointer, and/or is // expressly adjustable. It can hold elements of any type. public final class ComplexVector extends AbstractVector { private int capacity; private int fillPointer = -1; // -1 indicates no fill pointer. private boolean isDisplaced; // For non-displaced arrays. private LispObject[] elements; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexVector(int capacity) { elements = new LispObject[capacity]; for (int i = capacity; i-- > 0;) elements[i] = Fixnum.ZERO; this.capacity = capacity; } public ComplexVector(int capacity, AbstractArray array, int displacement) { this.capacity = capacity; this.array = array; this.displacement = displacement; isDisplaced = true; } @Override public LispObject typeOf() { return list(Symbol.VECTOR, T, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public boolean hasFillPointer() { return fillPointer >= 0; } @Override public int getFillPointer() { return fillPointer; } @Override public void setFillPointer(int n) { fillPointer = n; } @Override public void setFillPointer(LispObject obj) { if (obj == T) fillPointer = capacity(); else { int n = Fixnum.getValue(obj); if (n > capacity()) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") exceeds the capacity of the vector ("); sb.append(capacity()); sb.append(")."); error(new LispError(sb.toString())); } else if (n < 0) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") is negative."); error(new LispError(sb.toString())); } else fillPointer = n; } } @Override public boolean isDisplaced() { return isDisplaced; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject getElementType() { return T; } @Override public boolean isSimpleVector() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return fillPointer >= 0 ? fillPointer : capacity; } @Override public LispObject elt(int index) { final int limit = length(); if (index < 0 || index >= limit) badIndex(index, limit); return AREF(index); } // Ignores fill pointer. @Override public LispObject AREF(int index) { if (elements != null) { try { return elements[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); return NIL; // Not reached. } } else { // Displaced array. if (index < 0 || index >= capacity) badIndex(index, capacity); return array.AREF(index + displacement); } } @Override public void aset(int index, LispObject newValue) { if (elements != null) { try { elements[index] = newValue; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); } } else { // Displaced array. if (index < 0 || index >= capacity) badIndex(index, capacity); else array.aset(index + displacement, newValue); } } @Override public LispObject subseq(int start, int end) { SimpleVector v = new SimpleVector(end - start); int i = start, j = 0; try { while (i < end) v.aset(j++, AREF(i++)); return v; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { for (int i = capacity; i-- > 0;) elements[i] = obj; } @Override public void shrink(int n) { if (elements != null) { if (n < elements.length) { LispObject[] newArray = new LispObject[n]; System.arraycopy(elements, 0, newArray, 0, n); elements = newArray; capacity = n; if (fillPointer != -1) { // update fill pointer if it is setted fillPointer = Math.min(fillPointer, capacity); } return; } if (n == elements.length) return; } error(new LispError()); } @Override public LispObject reverse() { int length = length(); SimpleVector result = new SimpleVector(length); int i, j; for (i = 0, j = length - 1; i < length; i++, j--) result.aset(i, AREF(j)); return result; } @Override public LispObject nreverse() { if (elements != null) { int i = 0; int j = length() - 1; while (i < j) { LispObject temp = elements[i]; elements[i] = elements[j]; elements[j] = temp; ++i; --j; } } else { // Displaced array. int length = length(); LispObject[] data = new LispObject[length]; int i, j; for (i = 0, j = length - 1; i < length; i++, j--) data[i] = AREF(j); elements = data; capacity = length; array = null; displacement = 0; isDisplaced = false; fillPointer = -1; } return this; } @Override public void vectorPushExtend(LispObject element) { if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ensureCapacity(capacity * 2 + 1); } aset(fillPointer++, element); } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element) { vectorPushExtend(element); return Fixnum.getInstance(fillPointer - 1); } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) { int ext = Fixnum.getValue(extension); if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ext = Math.max(ext, capacity + 1); ensureCapacity(capacity + ext); } aset(fillPointer, element); return Fixnum.getInstance(fillPointer++); } private final void ensureCapacity(int minCapacity) { if (elements != null) { if (capacity < minCapacity) { LispObject[] newArray = new LispObject[minCapacity]; System.arraycopy(elements, 0, newArray, 0, capacity); elements = newArray; capacity = minCapacity; } } else { // Displaced array. Debug.assertTrue(array != null); if (capacity < minCapacity || array.getTotalSize() - displacement < minCapacity) { // Copy array. elements = new LispObject[minCapacity]; final int limit = Math.min(capacity, array.getTotalSize() - displacement); for (int i = 0; i < limit; i++) elements[i] = array.AREF(displacement + i); capacity = minCapacity; array = null; displacement = 0; isDisplaced = false; } } } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE- // ARRAY. In this case none of the original contents of array // appears in the resulting array." LispObject[] newElements = new LispObject[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements[i] = list.car(); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newElements[i] = initialContents.elt(i); } else type_error(initialContents, Symbol.SEQUENCE); elements = newElements; } else { if (elements == null) { // Displaced array. Copy existing elements. elements = new LispObject[newCapacity]; final int limit = Math.min(capacity, newCapacity); for (int i = 0; i < limit; i++) elements[i] = array.AREF(displacement + i); } else if (capacity != newCapacity) { LispObject[] newElements = new LispObject[newCapacity]; System.arraycopy(elements, 0, newElements, 0, Math.min(capacity, newCapacity)); elements = newElements; } // Initialize new elements (if any). if (initialElement != null) for (int i = capacity; i < newCapacity; i++) elements[i] = initialElement; } capacity = newCapacity; array = null; displacement = 0; isDisplaced = false; return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { capacity = newCapacity; array = displacedTo; this.displacement = displacement; elements = null; isDisplaced = true; return this; } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexVector_ByteBuffer.java0100644 0000000 0000000 00000032217 14202767264 023776 0ustar000000000 0000000 /* * ComplexVector_ByteBuffer.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; // A specialized vector of element type (UNSIGNED-BYTE 8) that is displaced to // another array, has a fill pointer, and/or is expressly adjustable. public final class ComplexVector_ByteBuffer extends AbstractVector { private int capacity; private int fillPointer = -1; // -1 indicates no fill pointer. private boolean isDisplaced; // For non-displaced arrays. private ByteBuffer elements; private boolean directAllocation; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexVector_ByteBuffer(int capacity) { this(capacity, false); } public ComplexVector_ByteBuffer(int capacity, boolean directAllocation) { this.capacity = capacity; this.directAllocation = directAllocation; if (directAllocation) { elements = ByteBuffer.allocateDirect(capacity); } else { elements = ByteBuffer.allocate(capacity); } } public ComplexVector_ByteBuffer(int capacity, AbstractArray array, int displacement) { this(capacity, array, displacement, false); } public ComplexVector_ByteBuffer(int capacity, AbstractArray array, int displacement, boolean directAllocation) { this.capacity = capacity; this.array = array; this.displacement = displacement; this.directAllocation = directAllocation; isDisplaced = true; } @Override public LispObject typeOf() { return list(Symbol.VECTOR, UNSIGNED_BYTE_8, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public boolean hasFillPointer() { return fillPointer >= 0; } @Override public int getFillPointer() { return fillPointer; } @Override public void setFillPointer(int n) { fillPointer = n; } @Override public void setFillPointer(LispObject obj) { if (obj == T) fillPointer = capacity(); else { int n = Fixnum.getValue(obj); if (n > capacity()) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") exceeds the capacity of the vector ("); sb.append(capacity()); sb.append(")."); error(new LispError(sb.toString())); } else if (n < 0) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") is negative."); error(new LispError(sb.toString())); } else fillPointer = n; } } @Override public boolean isDisplaced() { return isDisplaced; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_8; } @Override public boolean isSimpleVector() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return fillPointer >= 0 ? fillPointer : capacity; } @Override public LispObject elt(int index) { final int limit = length(); if (index < 0 || index >= limit) badIndex(index, limit); return AREF(index); } // Ignores fill pointer. @Override public LispObject AREF(int index) { if (elements != null) { try { return coerceFromJavaByte(elements.get(index)); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); return NIL; // Not reached. } } else { // Displaced array. if (index < 0 || index >= capacity) { badIndex(index, capacity); } return array.AREF(index + displacement); } } @Override public void aset(int index, int n) { if (elements != null) { try { elements.put(index, (byte) n); } catch (IndexOutOfBoundsException e) { badIndex(index, capacity); } } else { // Displaced array. if (index < 0 || index >= capacity) { badIndex(index, capacity); } else { array.aset(index + displacement, n); } } } @Override public void aset(int index, LispObject newValue) { if (elements != null) { try { elements.put(index, coerceToJavaByte(newValue)); } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); } } else { array.aset(index + displacement, newValue); } } @Override public LispObject subseq(int start, int end) { SimpleVector v = new SimpleVector(end - start); int i = start, j = 0; try { while (i < end) v.aset(j++, AREF(i++)); return v; } catch (IndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 255) { type_error(obj, UNSIGNED_BYTE_8); // Not reached. return; } for (int i = capacity; i-- > 0;) elements.put(i, (byte) n); } @Override public void shrink(int n) { // One cannot shrink the underlying ByteBuffer physically, so // use the limit marker to denote the length if (n < length()) { ((java.nio.Buffer)elements).limit(n); this.capacity = n; return; } if (n == ((java.nio.Buffer)elements).limit()) { return; } error(new LispError()); } @Override public LispObject reverse() { int length = length(); BasicVector_ByteBuffer result = new BasicVector_ByteBuffer(length, directAllocation); int i, j; for (i = 0, j = length - 1; i < length; i++, j--) result.aset(i, AREF(j)); return result; } @Override public LispObject nreverse() { if (elements != null) { int i = 0; int j = length() - 1; while (i < j) { byte temp = elements.get(i); elements.put(i, elements.get(j)); elements.put(j, temp); ++i; --j; } } else { // Displaced array. int length = length(); ByteBuffer data = null; if (directAllocation) { data = ByteBuffer.allocateDirect(length); } else { data = ByteBuffer.allocate(length); } int i, j; for (i = 0, j = length - 1; i < length; i++, j--) { data.put(i, coerceToJavaByte(AREF(j))); } elements = data; capacity = length; array = null; displacement = 0; isDisplaced = false; fillPointer = -1; } return this; } @Override public void vectorPushExtend(LispObject element) { if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ensureCapacity(capacity * 2 + 1); } aset(fillPointer, element); ++fillPointer; } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element) { vectorPushExtend(element); return Fixnum.getInstance(fillPointer - 1); } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) { int ext = Fixnum.getValue(extension); if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ext = Math.max(ext, capacity + 1); ensureCapacity(capacity + ext); } aset(fillPointer, element); return Fixnum.getInstance(fillPointer++); } private final void ensureCapacity(int minCapacity) { if (elements != null) { if (capacity < minCapacity) { ByteBuffer newBuffer = null; if (directAllocation) { newBuffer = ByteBuffer.allocateDirect(minCapacity); } else { newBuffer = ByteBuffer.allocate(minCapacity); } elements.position(0); newBuffer.put(elements); newBuffer.position(0); elements = newBuffer; capacity = minCapacity; } } else { // Displaced array. Debug.assertTrue(array != null); if (capacity < minCapacity || array.getTotalSize() - displacement < minCapacity) { // Copy array. if (directAllocation) { elements = ByteBuffer.allocateDirect(minCapacity); } else { elements = ByteBuffer.allocate(minCapacity); } final int limit = Math.min(length(), array.getTotalSize() - displacement); for (int i = 0; i < limit; i++) { elements.put(i, coerceToJavaByte(array.AREF(displacement + i))); } capacity = minCapacity; array = null; displacement = 0; isDisplaced = false; } } } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE- // ARRAY. In this case none of the original contents of array // appears in the resulting array." ByteBuffer newElements = null; if (directAllocation) { newElements = ByteBuffer.allocateDirect(newCapacity); } else { newElements = ByteBuffer.allocate(newCapacity); } if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements.put(i, coerceToJavaByte(list.car())); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) { newElements.put(i, coerceToJavaByte(initialContents.elt(i))); } } else { type_error(initialContents, Symbol.SEQUENCE); } elements = newElements; } else { if (elements == null) { // Displaced array. Copy existing elements. if (directAllocation) { elements = ByteBuffer.allocateDirect(newCapacity); } else { elements = ByteBuffer.allocate(newCapacity); } final int limit = Math.min(capacity, newCapacity); for (int i = 0; i < limit; i++) { elements.put(i, coerceToJavaByte(array.AREF(displacement + i))); } } else if (capacity != newCapacity) { ByteBuffer newElements = null; if (directAllocation) { newElements = ByteBuffer.allocateDirect(newCapacity); } else { newElements = ByteBuffer.allocate(newCapacity); } newElements.put(elements.array(), 0, Math.min(capacity, newCapacity)); elements = newElements; } // Initialize new elements (if applicable). if (initialElement != null) { byte b = coerceToJavaByte(initialElement); for (int i = capacity; i < newCapacity; i++) { elements.put(i, b); } } } capacity = newCapacity; array = null; displacement = 0; isDisplaced = false; return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { capacity = newCapacity; array = displacedTo; this.displacement = displacement; elements = null; isDisplaced = true; return this; } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexVector_IntBuffer.java0100644 0000000 0000000 00000032601 14202767264 023622 0ustar000000000 0000000 /* * ComplexVector_IntBuffer.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; import java.nio.IntBuffer; // A specialized vector of element type (UNSIGNED-BYTE 32) that is displaced to // another array, has a fill pointer, and/or is expressly adjustable. public final class ComplexVector_IntBuffer extends AbstractVector { private int capacity; private int fillPointer = -1; // -1 indicates no fill pointer. private boolean isDisplaced; // For non-displaced arrays. private IntBuffer elements; private boolean directAllocation; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexVector_IntBuffer(int capacity) { this(capacity, false); } public ComplexVector_IntBuffer(int capacity, boolean directAllocation) { this.capacity = capacity; this.directAllocation = directAllocation; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(capacity * 4); elements = b.asIntBuffer(); } else { elements = IntBuffer.allocate(capacity); } } public ComplexVector_IntBuffer(int capacity, AbstractArray array, int displacement) { this(capacity, array, displacement, false); } public ComplexVector_IntBuffer(int capacity, AbstractArray array, int displacement, boolean directAllocation) { this.capacity = capacity; this.array = array; this.displacement = displacement; this.directAllocation = directAllocation; isDisplaced = true; } @Override public LispObject typeOf() { return list(Symbol.VECTOR, UNSIGNED_BYTE_32, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public boolean hasFillPointer() { return fillPointer >= 0; } @Override public int getFillPointer() { return fillPointer; } @Override public void setFillPointer(int n) { fillPointer = n; } @Override public void setFillPointer(LispObject obj) { if (obj == T) { fillPointer = capacity(); } else { int n = Fixnum.getValue(obj); if (n > capacity()) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") exceeds the capacity of the vector ("); sb.append(capacity()); sb.append(")."); error(new LispError(sb.toString())); } else if (n < 0) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") is negative."); error(new LispError(sb.toString())); } else { fillPointer = n; } } } @Override public boolean isDisplaced() { return isDisplaced; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_32; } @Override public boolean isSimpleVector() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return fillPointer >= 0 ? fillPointer : capacity; } @Override public LispObject elt(int index) { final int limit = length(); if (index < 0 || index >= limit) badIndex(index, limit); return AREF(index); } // Ignores fill pointer. @Override public LispObject AREF(int index) { if (elements != null) { try { return number(((long)elements.get(index)) & 0xffffffffL); } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); return NIL; // Not reached. } } else { // Displaced array. if (index < 0 || index >= capacity) { badIndex(index, capacity); } return array.AREF(index + displacement); } } @Override public void aset(int index, LispObject newValue) { if (newValue.isLessThan(Fixnum.ZERO) || newValue.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(newValue, UNSIGNED_BYTE_32); } if (elements != null) { try { elements.put(index, (int)(newValue.longValue() & 0xffffffffL)); } catch (IndexOutOfBoundsException e) { badIndex(index, ((java.nio.Buffer)elements).limit()); } } else { // Displaced array. if (index < 0 || index >= capacity) { badIndex(index, capacity); } else { array.aset(index + displacement, newValue); } } } @Override public LispObject subseq(int start, int end) { SimpleVector v = new SimpleVector(end - start); int i = start, j = 0; try { while (i < end) { v.aset(j++, AREF(i++)); } return v; } catch (IndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof LispInteger)) { type_error(obj, Symbol.INTEGER); // Not reached. return; } if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(obj, UNSIGNED_BYTE_32); } for (int i = capacity; i-- > 0;) { elements.put(i, coerceToJavaUnsignedInt(obj)); } } @Override public void shrink(int n) { // One cannot shrink the underlying ByteBuffer physically, so // use the limit marker to denote the length if (n < length()) { ((java.nio.Buffer)elements).limit(n); this.capacity = n; return; } if (n == ((java.nio.Buffer)elements).limit()) { return; } error(new LispError()); } @Override public LispObject reverse() { int length = length(); SimpleVector result = new SimpleVector(length); int i, j; for (i = 0, j = length - 1; i < length; i++, j--) { result.aset(i, AREF(j)); } return result; } @Override public LispObject nreverse() { if (elements != null) { int i = 0; int j = length() - 1; while (i < j) { int temp = elements.get(i); elements.put(i, elements.get(j)); elements.put(j, temp); ++i; --j; } } else { // Displaced array. int length = length(); IntBuffer data = null; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(length * 4); data = b.asIntBuffer(); } else { data = IntBuffer.allocate(length); } int i, j; for (i = 0, j = length - 1; i < length; i++, j--) { data.put(i, coerceToJavaUnsignedInt(AREF(j))); } elements = data; capacity = length; array = null; displacement = 0; isDisplaced = false; fillPointer = -1; } return this; } @Override public void vectorPushExtend(LispObject element) { if (fillPointer < 0) { noFillPointer(); } if (fillPointer >= capacity) { // Need to extend vector. ensureCapacity(capacity * 2 + 1); } aset(fillPointer, element); ++fillPointer; } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element) { vectorPushExtend(element); return Fixnum.getInstance(fillPointer - 1); } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) { int ext = Fixnum.getValue(extension); if (fillPointer < 0) { noFillPointer(); } if (fillPointer >= capacity) { // Need to extend vector. ext = Math.max(ext, capacity + 1); ensureCapacity(capacity + ext); } aset(fillPointer, element); return Fixnum.getInstance(fillPointer++); } private final void ensureCapacity(int minCapacity) { if (elements != null) { if (capacity < minCapacity) { IntBuffer newBuffer = null; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(minCapacity * 4); newBuffer = b.asIntBuffer(); } else { newBuffer = IntBuffer.allocate(minCapacity); } elements.position(0); newBuffer.put(elements); newBuffer.position(0); elements = newBuffer; capacity = minCapacity; } } else { // Displaced array. Debug.assertTrue(array != null); if (capacity < minCapacity || array.getTotalSize() - displacement < minCapacity) { // Copy array. if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(minCapacity * 4); elements = b.asIntBuffer(); } else { elements = IntBuffer.allocate(minCapacity); } final int limit = Math.min(capacity, array.getTotalSize() - displacement); for (int i = 0; i < limit; i++) { elements.put(i, coerceToJavaUnsignedInt(AREF(displacement + i))); } capacity = minCapacity; array = null; displacement = 0; isDisplaced = false; } } } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE- // ARRAY. In this case none of the original contents of array // appears in the resulting array." IntBuffer newElements = null; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(newCapacity * 4); newElements = b.asIntBuffer(); } else { newElements = IntBuffer.allocate(newCapacity); } if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements.put(i, coerceToJavaUnsignedInt(list.car())); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) { newElements.put(i, coerceToJavaUnsignedInt(initialContents.elt(i))); } } else { type_error(initialContents, Symbol.SEQUENCE); } elements = newElements; } else { if (elements == null) { // Displaced array. Copy existing elements. if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(newCapacity * 4); elements = b.asIntBuffer(); } else { elements = IntBuffer.allocate(newCapacity); } final int limit = Math.min(capacity, newCapacity); for (int i = 0; i < limit; i++) { elements.put(i,(int)(array.AREF(displacement + i).longValue() & 0xffffffffL)); } } else if (capacity != newCapacity) { IntBuffer newElements = null; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(newCapacity * 4); newElements = b.asIntBuffer(); } else { newElements = IntBuffer.allocate(newCapacity); } newElements.put(elements.array(), 0, Math.min(capacity, newCapacity)); newElements.position(0); elements = newElements; } // Initialize new elements (if aapplicable). if (initialElement != null) { for (int i = capacity; i < newCapacity; i++) { elements.put(i, coerceToJavaUnsignedInt(initialElement)); } } } capacity = newCapacity; array = null; displacement = 0; isDisplaced = false; return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { capacity = newCapacity; array = displacedTo; this.displacement = displacement; elements = null; isDisplaced = true; return this; } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexVector_UnsignedByte32.java0100644 0000000 0000000 00000031375 14202767264 024512 0ustar000000000 0000000 /* * ComplexVector_UnsignedByte32.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // A specialized vector of element type (UNSIGNED-BYTE 32) that is displaced to // another array, has a fill pointer, and/or is expressly adjustable. public final class ComplexVector_UnsignedByte32 extends AbstractVector { private int capacity; private int fillPointer = -1; // -1 indicates no fill pointer. private boolean isDisplaced; // For non-displaced arrays. private LispObject[] elements; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexVector_UnsignedByte32(int capacity) { elements = new LispObject[capacity]; for (int i = capacity; i-- > 0;) elements[i] = Fixnum.ZERO; this.capacity = capacity; } public ComplexVector_UnsignedByte32(int capacity, AbstractArray array, int displacement) { this.capacity = capacity; this.array = array; this.displacement = displacement; isDisplaced = true; } @Override public LispObject typeOf() { return list(Symbol.VECTOR, UNSIGNED_BYTE_32, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public boolean hasFillPointer() { return fillPointer >= 0; } @Override public int getFillPointer() { return fillPointer; } @Override public void setFillPointer(int n) { fillPointer = n; } @Override public void setFillPointer(LispObject obj) { if (obj == T) fillPointer = capacity(); else { int n = Fixnum.getValue(obj); if (n > capacity()) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") exceeds the capacity of the vector ("); sb.append(capacity()); sb.append(")."); error(new LispError(sb.toString())); } else if (n < 0) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") is negative."); error(new LispError(sb.toString())); } else fillPointer = n; } } @Override public boolean isDisplaced() { return isDisplaced; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_32; } @Override public boolean isSimpleVector() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return fillPointer >= 0 ? fillPointer : capacity; } @Override public LispObject elt(int index) { final int limit = length(); if (index < 0 || index >= limit) badIndex(index, limit); return AREF(index); } // Ignores fill pointer. @Override public LispObject AREF(int index) { if (elements != null) { try { return elements[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); return NIL; // Not reached. } } else { // Displaced array. if (index < 0 || index >= capacity) badIndex(index, capacity); return array.AREF(index + displacement); } } @Override public void aset(int index, LispObject newValue) { if (elements != null) { try { elements[index] = newValue; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); } } else { // Displaced array. if (index < 0 || index >= capacity) badIndex(index, capacity); else array.aset(index + displacement, newValue); } } @Override public LispObject subseq(int start, int end) { SimpleVector v = new SimpleVector(end - start); int i = start, j = 0; try { while (i < end) v.aset(j++, AREF(i++)); return v; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof LispInteger)) { type_error(obj, Symbol.INTEGER); // Not reached. return; } if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(obj, UNSIGNED_BYTE_32); } for (int i = capacity; i-- > 0;) elements[i] = obj; } @Override public void shrink(int n) { if (elements != null) { if (n < elements.length) { LispObject[] newArray = new LispObject[n]; System.arraycopy(elements, 0, newArray, 0, n); elements = newArray; capacity = n; return; } if (n == elements.length) return; } error(new LispError()); } @Override public LispObject reverse() { int length = length(); SimpleVector result = new SimpleVector(length); int i, j; for (i = 0, j = length - 1; i < length; i++, j--) result.aset(i, AREF(j)); return result; } @Override public LispObject nreverse() { if (elements != null) { int i = 0; int j = length() - 1; while (i < j) { LispObject temp = elements[i]; elements[i] = elements[j]; elements[j] = temp; ++i; --j; } } else { // Displaced array. int length = length(); LispObject[] data = new LispObject[length]; int i, j; for (i = 0, j = length - 1; i < length; i++, j--) data[i] = AREF(j); elements = data; capacity = length; array = null; displacement = 0; isDisplaced = false; fillPointer = -1; } return this; } @Override public void vectorPushExtend(LispObject element) { if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ensureCapacity(capacity * 2 + 1); } aset(fillPointer, element); ++fillPointer; } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element) { vectorPushExtend(element); return Fixnum.getInstance(fillPointer - 1); } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) { int ext = Fixnum.getValue(extension); if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ext = Math.max(ext, capacity + 1); ensureCapacity(capacity + ext); } aset(fillPointer, element); return Fixnum.getInstance(fillPointer++); } private final void ensureCapacity(int minCapacity) { if (elements != null) { if (capacity < minCapacity) { LispObject[] newArray = new LispObject[minCapacity]; System.arraycopy(elements, 0, newArray, 0, capacity); elements = newArray; capacity = minCapacity; } } else { // Displaced array. Debug.assertTrue(array != null); if (capacity < minCapacity || array.getTotalSize() - displacement < minCapacity) { // Copy array. elements = new LispObject[minCapacity]; final int limit = Math.min(capacity, array.getTotalSize() - displacement); for (int i = 0; i < limit; i++) elements[i] = array.AREF(displacement + i); capacity = minCapacity; array = null; displacement = 0; isDisplaced = false; } } } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE- // ARRAY. In this case none of the original contents of array // appears in the resulting array." LispObject[] newElements = new LispObject[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements[i] = list.car(); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newElements[i] = initialContents.elt(i); } else type_error(initialContents, Symbol.SEQUENCE); elements = newElements; } else { if (elements == null) { // Displaced array. Copy existing elements. elements = new LispObject[newCapacity]; final int limit = Math.min(capacity, newCapacity); for (int i = 0; i < limit; i++) elements[i] = array.AREF(displacement + i); } else if (capacity != newCapacity) { LispObject[] newElements = new LispObject[newCapacity]; System.arraycopy(elements, 0, newElements, 0, Math.min(capacity, newCapacity)); elements = newElements; } // Initialize new elements (if aapplicable). if (initialElement != null) { for (int i = capacity; i < newCapacity; i++) elements[i] = initialElement; } } capacity = newCapacity; array = null; displacement = 0; isDisplaced = false; return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { capacity = newCapacity; array = displacedTo; this.displacement = displacement; elements = null; isDisplaced = true; return this; } } abcl-src-1.9.0/src/org/armedbear/lisp/ComplexVector_UnsignedByte8.java0100644 0000000 0000000 00000032217 14202767264 024431 0ustar000000000 0000000 /* * ComplexVector_UnsignedByte8.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // A specialized vector of element type (UNSIGNED-BYTE 8) that is displaced to // another array, has a fill pointer, and/or is expressly adjustable. public final class ComplexVector_UnsignedByte8 extends AbstractVector { private int capacity; private int fillPointer = -1; // -1 indicates no fill pointer. private boolean isDisplaced; // For non-displaced arrays. private byte[] elements; // For displaced arrays. private AbstractArray array; private int displacement; public ComplexVector_UnsignedByte8(int capacity) { elements = new byte[capacity]; this.capacity = capacity; } public ComplexVector_UnsignedByte8(int capacity, AbstractArray array, int displacement) { this.capacity = capacity; this.array = array; this.displacement = displacement; isDisplaced = true; } @Override public LispObject typeOf() { return list(Symbol.VECTOR, UNSIGNED_BYTE_8, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.VECTOR; } @Override public boolean hasFillPointer() { return fillPointer >= 0; } @Override public int getFillPointer() { return fillPointer; } @Override public void setFillPointer(int n) { fillPointer = n; } @Override public void setFillPointer(LispObject obj) { if (obj == T) fillPointer = capacity(); else { int n = Fixnum.getValue(obj); if (n > capacity()) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") exceeds the capacity of the vector ("); sb.append(capacity()); sb.append(")."); error(new LispError(sb.toString())); } else if (n < 0) { StringBuffer sb = new StringBuffer("The new fill pointer ("); sb.append(n); sb.append(") is negative."); error(new LispError(sb.toString())); } else fillPointer = n; } } @Override public boolean isDisplaced() { return isDisplaced; } @Override public LispObject arrayDisplacement() { LispObject value1, value2; if (array != null) { value1 = array; value2 = Fixnum.getInstance(displacement); } else { value1 = NIL; value2 = Fixnum.ZERO; } return LispThread.currentThread().setValues(value1, value2); } @Override public LispObject getElementType() { return UNSIGNED_BYTE_8; } @Override public boolean isSimpleVector() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return fillPointer >= 0 ? fillPointer : capacity; } @Override public LispObject elt(int index) { final int limit = length(); if (index < 0 || index >= limit) badIndex(index, limit); return AREF(index); } // Ignores fill pointer. @Override public LispObject AREF(int index) { if (elements != null) { try { return coerceFromJavaByte(elements[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); return NIL; // Not reached. } } else { // Displaced array. if (index < 0 || index >= capacity) badIndex(index, capacity); return array.AREF(index + displacement); } } @Override public void aset(int index, int n) { if (elements != null) { try { elements[index] = (byte) n; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); } } else { // Displaced array. if (index < 0 || index >= capacity) badIndex(index, capacity); else array.aset(index + displacement, n); } } @Override public void aset(int index, LispObject newValue) { if (elements != null) { try { elements[index] = coerceToJavaByte(newValue); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, elements.length); } } else array.aset(index + displacement, newValue); } @Override public LispObject subseq(int start, int end) { SimpleVector v = new SimpleVector(end - start); int i = start, j = 0; try { while (i < end) v.aset(j++, AREF(i++)); return v; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 255) { type_error(obj, UNSIGNED_BYTE_8); // Not reached. return; } for (int i = capacity; i-- > 0;) elements[i] = (byte) n; } @Override public void shrink(int n) { if (elements != null) { if (n < elements.length) { byte[] newArray = new byte[n]; System.arraycopy(elements, 0, newArray, 0, n); elements = newArray; capacity = n; return; } if (n == elements.length) return; } error(new LispError()); } @Override public LispObject reverse() { int length = length(); BasicVector_UnsignedByte8 result = new BasicVector_UnsignedByte8(length); int i, j; for (i = 0, j = length - 1; i < length; i++, j--) result.aset(i, AREF(j)); return result; } @Override public LispObject nreverse() { if (elements != null) { int i = 0; int j = length() - 1; while (i < j) { byte temp = elements[i]; elements[i] = elements[j]; elements[j] = temp; ++i; --j; } } else { // Displaced array. int length = length(); byte[] data = new byte[length]; int i, j; for (i = 0, j = length - 1; i < length; i++, j--) data[i] = coerceToJavaByte(AREF(j)); elements = data; capacity = length; array = null; displacement = 0; isDisplaced = false; fillPointer = -1; } return this; } @Override public void vectorPushExtend(LispObject element) { if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ensureCapacity(capacity * 2 + 1); } aset(fillPointer, element); ++fillPointer; } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element) { vectorPushExtend(element); return Fixnum.getInstance(fillPointer - 1); } @Override public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) { int ext = Fixnum.getValue(extension); if (fillPointer < 0) noFillPointer(); if (fillPointer >= capacity) { // Need to extend vector. ext = Math.max(ext, capacity + 1); ensureCapacity(capacity + ext); } aset(fillPointer, element); return Fixnum.getInstance(fillPointer++); } private final void ensureCapacity(int minCapacity) { if (elements != null) { if (capacity < minCapacity) { byte[] newArray = new byte[minCapacity]; System.arraycopy(elements, 0, newArray, 0, capacity); elements = newArray; capacity = minCapacity; } } else { // Displaced array. Debug.assertTrue(array != null); if (capacity < minCapacity || array.getTotalSize() - displacement < minCapacity) { // Copy array. elements = new byte[minCapacity]; final int limit = Math.min(capacity, array.getTotalSize() - displacement); for (int i = 0; i < limit; i++) elements[i] = coerceToJavaByte(array.AREF(displacement + i)); capacity = minCapacity; array = null; displacement = 0; isDisplaced = false; } } } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE- // ARRAY. In this case none of the original contents of array // appears in the resulting array." byte[] newElements = new byte[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newElements[i] = coerceToJavaByte(list.car()); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newElements[i] = coerceToJavaByte(initialContents.elt(i)); } else type_error(initialContents, Symbol.SEQUENCE); elements = newElements; } else { if (elements == null) { // Displaced array. Copy existing elements. elements = new byte[newCapacity]; final int limit = Math.min(capacity, newCapacity); for (int i = 0; i < limit; i++) elements[i] = coerceToJavaByte(array.AREF(displacement + i)); } else if (capacity != newCapacity) { byte[] newElements = new byte[newCapacity]; System.arraycopy(elements, 0, newElements, 0, Math.min(capacity, newCapacity)); elements = newElements; } // Initialize new elements (if aapplicable). if (initialElement != null) { byte b = coerceToJavaByte(initialElement); for (int i = capacity; i < newCapacity; i++) elements[i] = b; } } capacity = newCapacity; array = null; displacement = 0; isDisplaced = false; return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { capacity = newCapacity; array = displacedTo; this.displacement = displacement; elements = null; isDisplaced = true; return this; } } abcl-src-1.9.0/src/org/armedbear/lisp/ConcatenatedStream.java0100644 0000000 0000000 00000017046 14223403213 022616 0ustar000000000 0000000 /* * ConcatenatedStream.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ConcatenatedStream extends Stream { LispObject streams; ConcatenatedStream(LispObject streams) { super(Symbol.CONCATENATED_STREAM); this.streams = streams; isInputStream = true; } @Override public boolean isCharacterInputStream() { if (streams == NIL) return true; return ((Stream)streams.car()).isCharacterInputStream(); } @Override public boolean isBinaryInputStream() { if (streams == NIL) return true; return ((Stream)streams.car()).isBinaryInputStream(); } @Override public boolean isCharacterOutputStream() { return false; } @Override public boolean isBinaryOutputStream() { return false; } @Override public LispObject typeOf() { return Symbol.CONCATENATED_STREAM; } @Override public LispObject classOf() { return BuiltInClass.CONCATENATED_STREAM; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.CONCATENATED_STREAM) return T; if (typeSpecifier == BuiltInClass.CONCATENATED_STREAM) return T; return super.typep(typeSpecifier); } @Override public LispObject getElementType() { if (streams == NIL) return NIL; return ((Stream)streams.car()).getElementType(); } @Override public LispObject readCharNoHang(boolean eofError, LispObject eofValue) { if (streams == NIL) { if (eofError) return error(new EndOfFile(this)); else return eofValue; } try { return _charReady() ? readChar(eofError, eofValue) : NIL; } catch (java.io.IOException e) { return error(new StreamError(this, e)); } } @Override public LispObject listen() { if (streams == NIL) return NIL; Stream stream = (Stream)streams.car(); if (stream.listen() == NIL) { streams = streams.cdr(); return listen(); } return T; } // Returns -1 at end of file. @Override protected int _readChar() throws java.io.IOException { int n; if (streams == NIL) return -1; Stream stream = (Stream) streams.car(); n = stream._readChar(); if (n >= 0) return n; streams = streams.cdr(); return _readChar(); } @Override protected void _unreadChar(int n) throws java.io.IOException { if (streams == NIL) error(new StreamError(this, "UNREAD-CHAR was invoked without a stream to unread into.")); Stream stream = (Stream)streams.car(); stream._unreadChar(n); } @Override protected boolean _charReady() throws java.io.IOException { if (streams == NIL) return false; Stream stream = (Stream) streams.car(); if (stream._charReady()) return true; LispObject remainingStreams = streams.cdr(); while (remainingStreams != NIL) { stream = (Stream) remainingStreams.car(); if (stream._charReady()) return true; remainingStreams = remainingStreams.cdr(); } return false; } @Override public void _writeChar(char c) { outputStreamError(); } @Override public void _writeChars(char[] chars, int start, int end) { outputStreamError(); } @Override public void _writeString(String s) { outputStreamError(); } @Override public void _writeLine(String s) { outputStreamError(); } // Reads an 8-bit byte. @Override public int _readByte() { if (streams == NIL) return -1; Stream stream = (Stream) streams.car(); int n = stream._readByte(); if (n >= 0) return n; streams = streams.cdr(); return _readByte(); } // Writes an 8-bit byte. @Override public void _writeByte(int n) { outputStreamError(); } @Override public void _finishOutput() { outputStreamError(); } @Override public void _clearInput() { // FIXME } private void outputStreamError() { error(new StreamError(this, String.valueOf(this) + " is not an output stream.")); } // ### make-concatenated-stream &rest streams => concatenated-stream private static final Primitive MAKE_CONCATENATED_STREAM = new Primitive("make-concatenated-stream", "&rest streams") { @Override public LispObject execute(LispObject[] args) { LispObject streams = NIL; for (int i = 0; i < args.length; i++) { if (args[i] instanceof Stream) { Stream stream = (Stream) args[i]; if (stream.isInputStream()) { // streams[i] = (Stream) args[i]; streams = new Cons(stream, streams); continue; } } error(new TypeError(String.valueOf(args[i]) + " is not an input stream.")); } return new ConcatenatedStream(streams.nreverse()); } }; // ### concatenated-stream-streams concatenated-stream => streams private static final Primitive CONCATENATED_STREAM_STREAMS = new Primitive("concatenated-stream-streams", "concatenated-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof ConcatenatedStream) return ((ConcatenatedStream)arg).streams; return type_error(arg, Symbol.CONCATENATED_STREAM); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Condition.java0100644 0000000 0000000 00000014226 14202767264 021015 0ustar000000000 0000000 /* * Condition.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class Condition extends StandardObject { protected String message; public Condition() { super(StandardClass.CONDITION); Debug.assertTrue(slots.length == 2); setFormatArguments(NIL); } protected Condition(LispClass cls) { super(cls); Debug.assertTrue(slots.length >= 2); setFormatArguments(NIL); } public Condition(LispClass cls, int length) { super(cls, length); } public Condition(LispObject initArgs) { super(StandardClass.CONDITION); Debug.assertTrue(slots.length == 2); initialize(initArgs); } protected void initialize(LispObject initArgs) { LispObject control = null; LispObject arguments = null; LispObject first, second; while (initArgs instanceof Cons) { first = initArgs.car(); initArgs = initArgs.cdr(); second = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.FORMAT_CONTROL) { if (control == null) control = second; } else if (first == Keyword.FORMAT_ARGUMENTS) { if (arguments == null) arguments = second; } } if (control != null) setFormatControl(control); if (arguments == null) arguments = NIL; setFormatArguments(arguments); } public Condition(String message) { super(StandardClass.CONDITION); Debug.assertTrue(slots.length == 2); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); } public final LispObject getFormatControl() { return getInstanceSlotValue(Symbol.FORMAT_CONTROL); } public final void setFormatControl(LispObject formatControl) { setInstanceSlotValue(Symbol.FORMAT_CONTROL, formatControl); } public final void setFormatControl(String s) { setFormatControl(new SimpleString(s)); } public final LispObject getFormatArguments() { return getInstanceSlotValue(Symbol.FORMAT_ARGUMENTS); } public final void setFormatArguments(LispObject formatArguments) { setInstanceSlotValue(Symbol.FORMAT_ARGUMENTS, formatArguments); } /** * Extending classes should override this method if they want to * customize how they will be printed. */ public String getMessage() { return null; } @Override public LispObject typeOf() { LispObject c = getLispClass(); if (c instanceof LispClass) return ((LispClass)c).getName(); else if (c != null) return Symbol.CLASS_NAME.execute(c); return Symbol.CONDITION; } @Override public LispObject classOf() { LispObject c = getLispClass(); if (c != null) return c; return StandardClass.CONDITION; } @Override public LispObject typep(LispObject type) { if (type == Symbol.CONDITION) return T; if (type == StandardClass.CONDITION) return T; return super.typep(type); } public String getConditionReport() { String s = getMessage(); if (s != null) return s; LispObject formatControl = getFormatControl(); if (formatControl != NIL) { return format(formatControl, getFormatArguments()); } return unreadableString(typeOf().princToString()); } @Override public final String printObject() { final LispThread thread = LispThread.currentThread(); if (Symbol.PRINT_ESCAPE.symbolValue(thread) == NIL) { String s = getMessage(); if (s != null) return s; LispObject formatControl = getFormatControl(); if (formatControl instanceof Function) { StringOutputStream stream = new StringOutputStream(); Symbol.APPLY.execute(formatControl, stream, getFormatArguments()); return stream.getString().getStringValue(); } if (formatControl instanceof AbstractString) { LispObject f = Symbol.FORMAT.getSymbolFunction(); if (f == null || f instanceof Autoload) return format(formatControl, getFormatArguments()); return Symbol.APPLY.execute(f, NIL, formatControl, getFormatArguments()).getStringValue(); } } final int maxLevel; LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread); if (printLevel instanceof Fixnum) maxLevel = ((Fixnum)printLevel).value; else maxLevel = Integer.MAX_VALUE; LispObject currentPrintLevel = _CURRENT_PRINT_LEVEL_.symbolValue(thread); int currentLevel = ((Fixnum)currentPrintLevel).value; if (currentLevel >= maxLevel) return "#"; return unreadableString(typeOf().princToString()); } } abcl-src-1.9.0/src/org/armedbear/lisp/Cons.java0100644 0000000 0000000 00000036266 14202767264 020001 0ustar000000000 0000000 /* * Cons.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class Cons extends LispObject implements java.io.Serializable { public LispObject car; public LispObject cdr; public Cons(LispObject car, LispObject cdr) { this.car = car; this.cdr = cdr; ++count; } public Cons(LispObject car) { this.car = car; this.cdr = NIL; ++count; } public Cons(String name, LispObject value) { this.car = new SimpleString(name); this.cdr = value != null ? value : NULL_VALUE; ++count; } public Cons(Cons original) { Cons rest = original; LispObject result = NIL; while (rest.car() != NIL) { result = result.push(rest.car()); if (rest.cdr() == NIL) { break; } rest = (Cons) rest.cdr(); } result = result.nreverse(); this.car = result.car(); this.cdr = result.cdr(); ++count; } @Override public LispObject typeOf() { return Symbol.CONS; } @Override public LispObject classOf() { return BuiltInClass.CONS; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier instanceof Symbol) { if (typeSpecifier == Symbol.LIST) return T; if (typeSpecifier == Symbol.CONS) return T; if (typeSpecifier == Symbol.SEQUENCE) return T; if (typeSpecifier == T) return T; } else if (typeSpecifier instanceof LispClass) { if (typeSpecifier == BuiltInClass.LIST) return T; if (typeSpecifier == BuiltInClass.CONS) return T; if (typeSpecifier == BuiltInClass.SEQUENCE) return T; if (typeSpecifier == BuiltInClass.CLASS_T) return T; } return NIL; } @Override public final boolean constantp() { if (car == Symbol.QUOTE) { if (cdr instanceof Cons) if (((Cons)cdr).cdr == NIL) return true; } return false; } @Override public boolean atom() { return false; } @Override public LispObject RPLACA(LispObject obj) { car = obj; return this; } @Override public LispObject RPLACD(LispObject obj) { cdr = obj; return this; } @Override public int hashCode() { return this.sxhash(); } @Override public final int sxhash() { return computeHash(this, 4); } private static final int computeHash(LispObject obj, int depth) { if (obj instanceof Cons) { if (depth > 0) { int n1 = computeHash(((Cons)obj).car, depth - 1); int n2 = computeHash(((Cons)obj).cdr, depth - 1); return n1 ^ n2; } else { // This number comes from SBCL, but since we're not really // using SBCL's SXHASH algorithm, it's probably not optimal. // But who knows? return 261835505; } } else return obj.sxhash(); } @Override public final int psxhash() { return computeEqualpHash(this, 4); } private static final int computeEqualpHash(LispObject obj, int depth) { if (obj instanceof Cons) { if (depth > 0) { int n1 = computeEqualpHash(((Cons)obj).car, depth - 1); int n2 = computeEqualpHash(((Cons)obj).cdr, depth - 1); return n1 ^ n2; } else return 261835505; // See above. } else return obj.psxhash(); } @Override public final boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof Cons) { if (car.equal(((Cons)obj).car) && cdr.equal(((Cons)obj).cdr)) return true; } return false; } @Override public final boolean equalp(LispObject obj) { if (this == obj) return true; if (obj instanceof Cons) { if (car.equalp(((Cons)obj).car) && cdr.equalp(((Cons)obj).cdr)) return true; } return false; } @Override public final int length() { int length = 1; LispObject obj = cdr; while (obj != NIL) { ++length; if (obj instanceof Cons) { obj = ((Cons)obj).cdr; } else type_error(obj, Symbol.LIST); } return length; } @Override public LispObject NTH(int index) { if (index < 0) type_error(Fixnum.getInstance(index), Symbol.UNSIGNED_BYTE); int i = 0; LispObject obj = this; while (true) { if (i == index) return obj.car(); obj = obj.cdr(); if (obj == NIL) return NIL; ++i; } } @Override public LispObject elt(int index) { if (index < 0) type_error(Fixnum.getInstance(index), Symbol.UNSIGNED_BYTE); int i = 0; Cons cons = this; while (true) { if (i == index) return cons.car; LispObject conscdr = cons.cdr; if (conscdr instanceof Cons) { cons = (Cons) conscdr; } else { if (conscdr == NIL) { // Index too large. type_error(Fixnum.getInstance(index), list(Symbol.INTEGER, Fixnum.ZERO, Fixnum.getInstance(length() - 1))); } else { // Dotted list. type_error(conscdr, Symbol.LIST); } // Not reached. return NIL; } ++i; } } @Override public LispObject reverse() { Cons cons = this; LispObject result = new Cons(cons.car); while (cons.cdr instanceof Cons) { cons = (Cons) cons.cdr; result = new Cons(cons.car, result); } if (cons.cdr != NIL) return type_error(cons.cdr, Symbol.LIST); return result; } @Override public final LispObject nreverse() { if (cdr instanceof Cons) { Cons cons = (Cons) cdr; if (cons.cdr instanceof Cons) { Cons cons1 = cons; LispObject list = NIL; do { Cons temp = (Cons) cons.cdr; cons.cdr = list; list = cons; cons = temp; } while (cons.cdr instanceof Cons); if (cons.cdr != NIL) return type_error(cons.cdr, Symbol.LIST); cdr = list; cons1.cdr = cons; } else if (cons.cdr != NIL) return type_error(cons.cdr, Symbol.LIST); LispObject temp = car; car = cons.car; cons.car = temp; } else if (cdr != NIL) return type_error(cdr, Symbol.LIST); return this; } @Override public final LispObject[] copyToArray() { final int length = length(); LispObject[] array = new LispObject[length]; LispObject rest = this; for (int i = 0; i < length; i++) { array[i] = rest.car(); rest = rest.cdr(); } return array; } @Override public LispObject execute() { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(); } return signalExecutionError(); } @Override public LispObject execute(LispObject arg) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(arg); } return signalExecutionError(); } @Override public LispObject execute(LispObject first, LispObject second) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(first, second); } return signalExecutionError(); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(first, second, third); } return signalExecutionError(); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(first, second, third, fourth); } return signalExecutionError(); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(first, second, third, fourth, fifth); } return signalExecutionError(); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(first, second, third, fourth, fifth, sixth); } return signalExecutionError(); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(first, second, third, fourth, fifth, sixth, seventh); } return signalExecutionError(); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(first, second, third, fourth, fifth, sixth, seventh, eighth); } return signalExecutionError(); } @Override public LispObject execute(LispObject[] args) { if (car == Symbol.LAMBDA) { Closure closure = new Closure(this, new Environment()); return closure.execute(args); } return signalExecutionError(); } private final LispObject signalExecutionError() { return type_error(this, list(Symbol.OR, Symbol.FUNCTION, Symbol.SYMBOL)); } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); final LispObject printLength = Symbol.PRINT_LENGTH.symbolValue(thread); final int maxLength; if (printLength instanceof Fixnum) maxLength = ((Fixnum)printLength).value; else maxLength = Integer.MAX_VALUE; final LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread); final int maxLevel; if (printLevel instanceof Fixnum) maxLevel = ((Fixnum)printLevel).value; else maxLevel = Integer.MAX_VALUE; StringBuilder sb = new StringBuilder(); if (car == Symbol.QUOTE) { if (cdr instanceof Cons) { // Not a dotted list. if (cdr.cdr() == NIL) { sb.append('\''); sb.append(cdr.car().printObject()); return sb.toString(); } } } if (car == Symbol.FUNCTION) { if (cdr instanceof Cons) { // Not a dotted list. if (cdr.cdr() == NIL) { sb.append("#'"); sb.append(cdr.car().printObject()); return sb.toString(); } } } LispObject currentPrintLevel = _CURRENT_PRINT_LEVEL_.symbolValue(thread); int currentLevel = Fixnum.getValue(currentPrintLevel); if (currentLevel < maxLevel) { final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(_CURRENT_PRINT_LEVEL_, currentPrintLevel.incr()); try { int count = 0; boolean truncated = false; sb.append('('); if (count < maxLength) { LispObject p = this; sb.append(p.car().printObject()); ++count; while ((p = p.cdr()) instanceof Cons) { sb.append(' '); if (count < maxLength) { sb.append(p.car().printObject()); ++count; } else { truncated = true; break; } } if (!truncated && p != NIL) { sb.append(" . "); sb.append(p.printObject()); } } else truncated = true; if (truncated) sb.append("..."); sb.append(')'); } finally { thread.resetSpecialBindings(mark); } } else sb.append('#'); return sb.toString(); } // Statistics for TIME. private static long count; /*package*/ static long getCount() { return count; } /*package*/ static void setCount(long n) { count = n; } } abcl-src-1.9.0/src/org/armedbear/lisp/ControlError.java0100644 0000000 0000000 00000004573 14202767264 021525 0ustar000000000 0000000 /* * ControlError.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ControlError extends LispError { public ControlError(LispObject initArgs) { super(StandardClass.CONTROL_ERROR); initialize(initArgs); } public ControlError(String message) { super(StandardClass.CONTROL_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); } @Override public LispObject typeOf() { return Symbol.CONTROL_ERROR; } @Override public LispObject classOf() { return StandardClass.CONTROL_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.CONTROL_ERROR) return T; if (type == StandardClass.CONTROL_ERROR) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/ControlTransfer.java0100644 0000000 0000000 00000005301 14202767264 022206 0ustar000000000 0000000 /* * ControlTransfer.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; /** This class is the parent class of all non-local transfer of * control events in ABCL. The classes inheriting from this class each * represent a transfer of control event as it is available in the * standard: GO (represented by Go), RETURN (by Return) and THROW (by Throw). * * Please note that you should only be using these classes in case * you've establisched a corresponding TAGBODY, BLOCK or CATCH-like * construct in your code. * * Otherwise, be aware that if you are mixing Lisp and Java code, * Lisp code being called into might throw one of the three exception types * and cause execution to be transferred to the nearest handler - presumably * outside your Java code. * */ abstract public class ControlTransfer extends RuntimeException { public ControlTransfer() { } /** * Overridden in order to make ControlTransfer construct * faster. This avoids gathering stack trace information. */ @Override public Throwable fillInStackTrace() { return this; } public ControlTransfer(String message) { super(message); } public abstract LispObject getCondition(); } abcl-src-1.9.0/src/org/armedbear/lisp/Debug.java0100644 0000000 0000000 00000006303 14223403213 020072 0ustar000000000 0000000 /* * Debug.java * * Copyright (C) 2002-2003 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.PrintWriter; import java.io.StringWriter; public final class Debug { public static final void assertTrue(boolean b) { if (!b) { String msg = "ABCL Debug.assertTrue() assertion failed!"; System.err.println(msg); Error e = new Error(msg); e.printStackTrace(System.err); StringBuffer buffer = new StringBuffer(); final String CR = "\n"; buffer.append(msg).append(CR); StackTraceElement[] stack = e.getStackTrace(); for (int i = 0; i < stack.length; i++) { buffer.append(stack[i].toString()).append(CR); } throw new Error(buffer.toString()); } } // Does not throw an exception. public static void bug() { trace(new Exception("BUG!")); } public static final void trace(String s) { System.err.println(s); } @SuppressWarnings("CallToThreadDumpStack") public static final void trace(Throwable t) { t.printStackTrace(); } public static final void trace(String message, Throwable t) { trace(message); trace(t); } public static final Symbol _DEBUG_WARN_ = exportSpecial("*DEBUG-WARN*", PACKAGE_SYS, NIL); public static void setDebugWarnings(boolean flag) { if (flag) { _DEBUG_WARN_.setSymbolValue(T); } else { _DEBUG_WARN_.setSymbolValue(NIL); } } public static final void warn(String s) { if (_DEBUG_WARN_.getSymbolValue() != null) { trace(s); } } } abcl-src-1.9.0/src/org/armedbear/lisp/DispatchMacroFunction.java0100644 0000000 0000000 00000005256 14202767264 023321 0ustar000000000 0000000 /* * DispatchMacroFunction.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class DispatchMacroFunction extends Function { public DispatchMacroFunction(String name) { super(name); } public DispatchMacroFunction(String name, String arglist) { super(name, arglist); } public DispatchMacroFunction(String name, Package pkg) { super(name, pkg); } public DispatchMacroFunction(String name, Package pkg, boolean exported) { super(name, pkg, exported); } public DispatchMacroFunction(String name, Package pkg, boolean exported, String arglist) { super(name, pkg, exported, arglist); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { Stream stream = inSynonymOf(first); char c = LispCharacter.getValue(second); int n; if (third == NIL) n = -1; else n = Fixnum.getValue(third); return execute(stream, c, n); } public abstract LispObject execute(Stream stream, char c, int n) ; } abcl-src-1.9.0/src/org/armedbear/lisp/DivisionByZero.java0100644 0000000 0000000 00000004576 14202767264 022015 0ustar000000000 0000000 /* * DivisionByZero.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class DivisionByZero extends ArithmeticError { public DivisionByZero() { super(StandardClass.DIVISION_BY_ZERO); setFormatControl("Arithmetic error DIVISION-BY-ZERO signalled."); } public DivisionByZero(LispObject initArgs) { super(StandardClass.DIVISION_BY_ZERO); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.DIVISION_BY_ZERO; } @Override public LispObject classOf() { return StandardClass.DIVISION_BY_ZERO; } @Override public LispObject typep(LispObject type) { if (type == Symbol.DIVISION_BY_ZERO) return T; if (type == StandardClass.DIVISION_BY_ZERO) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/Do.java0100644 0000000 0000000 00000016357 14206360343 017427 0ustar000000000 0000000 /* * Do.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class Do { // ### do private static final SpecialOperator DO = new sf_do(); private static final class sf_do extends SpecialOperator { sf_do() { super(Symbol.DO, "varlist endlist &body body"); } @Override public LispObject execute(LispObject args, Environment env) { return _do(args, env, false); } }; // ### do* private static final SpecialOperator DO_STAR = new sf_do_star(); private static final class sf_do_star extends SpecialOperator { sf_do_star() { super(Symbol.DO_STAR, "varlist endlist &body body"); } @Override public LispObject execute(LispObject args, Environment env) { return _do(args, env, true); } }; static final LispObject _do(LispObject args, Environment env, boolean sequential) { LispObject varlist = args.car(); LispObject second = args.cadr(); LispObject end_test_form = second.car(); LispObject result_forms = second.cdr(); LispObject body = args.cddr(); // Process variable specifications. final int numvars = varlist.length(); Symbol[] vars = new Symbol[numvars]; LispObject[] initforms = new LispObject[numvars]; LispObject[] stepforms = new LispObject[numvars]; for (int i = 0; i < numvars; i++) { final LispObject varspec = varlist.car(); if (varspec instanceof Cons) { vars[i] = checkSymbol(varspec.car()); initforms[i] = varspec.cadr(); // Is there a step form? if (varspec.cddr() != NIL) stepforms[i] = varspec.caddr(); } else { // Not a cons, must be a symbol. vars[i] = checkSymbol(varspec); initforms[i] = NIL; } varlist = varlist.cdr(); } final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); // Process declarations. final LispObject bodyAndDecls = parseBody(body, false); LispObject specials = parseSpecials(bodyAndDecls.NTH(1)); body = bodyAndDecls.car(); Environment ext = new Environment(env); for (int i = 0; i < numvars; i++) { Symbol var = vars[i]; LispObject value = eval(initforms[i], (sequential ? ext : env), thread); ext = new Environment(ext); if (specials != NIL && memq(var, specials)) thread.bindSpecial(var, value); else if (var.isSpecialVariable()) thread.bindSpecial(var, value); else ext.bind(var, value); } LispObject list = specials; while (list != NIL) { ext.declareSpecial(checkSymbol(list.car())); list = list.cdr(); } // Look for tags. LispObject localTags = preprocessTagBody(body, ext); LispObject blockId = new LispObject(); try { thread.envStack.push(ext); // Implicit block. ext.addBlock(NIL, blockId); while (true) { // Execute body. // Test for termination. if (eval(end_test_form, ext, thread) != NIL) break; processTagBody(body, localTags, ext); // Update variables. if (sequential) { for (int i = 0; i < numvars; i++) { LispObject step = stepforms[i]; if (step != null) { Symbol symbol = vars[i]; LispObject value = eval(step, ext, thread); if (symbol.isSpecialVariable() || ext.isDeclaredSpecial(symbol)) thread.rebindSpecial(symbol, value); else ext.rebind(symbol, value); } } } else { // Evaluate step forms. LispObject results[] = new LispObject[numvars]; for (int i = 0; i < numvars; i++) { LispObject step = stepforms[i]; if (step != null) { LispObject result = eval(step, ext, thread); results[i] = result; } } // Update variables. for (int i = 0; i < numvars; i++) { if (results[i] != null) { Symbol symbol = vars[i]; LispObject value = results[i]; if (symbol.isSpecialVariable() || ext.isDeclaredSpecial(symbol)) thread.rebindSpecial(symbol, value); else ext.rebind(symbol, value); } } } if (interrupted) handleInterrupt(); } LispObject result = progn(result_forms, ext, thread); return result; } catch (Return ret) { if (ret.getBlock() == blockId) { return ret.getResult(); } throw ret; } finally { while (thread.envStack.pop() != ext) {} thread.resetSpecialBindings(mark); ext.inactive = true; } } } abcl-src-1.9.0/src/org/armedbear/lisp/DocString.java0100644 0000000 0000000 00000004224 14202767264 020760 0ustar000000000 0000000 /* * DocString.java * * Copyright (C) 2010 Matt Seddon * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.lang.annotation.*; /** * An annotation type to expose documentation to ABCL. * Note: the TAGS ant target also pulls information from here. It * expects name to be the first item in the DocString declaration, * and not broken onto multiple lines. */ @Retention(RetentionPolicy.RUNTIME) public @interface DocString { /** The lisp name. */ public String name() default ""; /** The arguments. */ public String args() default ""; /** The return value(s) of a function */ public String returns() default ""; /** The documentation string. */ public String doc() default ""; } abcl-src-1.9.0/src/org/armedbear/lisp/DoubleFloat.java0100644 0000000 0000000 00000052563 14202767264 021275 0ustar000000000 0000000 /* * DoubleFloat.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; public final class DoubleFloat extends LispObject { public static final DoubleFloat ZERO = new DoubleFloat(0); public static final DoubleFloat MINUS_ZERO = new DoubleFloat(-0.0d); public static final DoubleFloat ONE = new DoubleFloat(1); public static final DoubleFloat MINUS_ONE = new DoubleFloat(-1); public static final DoubleFloat DOUBLE_FLOAT_POSITIVE_INFINITY = new DoubleFloat(Double.POSITIVE_INFINITY); public static final DoubleFloat DOUBLE_FLOAT_NEGATIVE_INFINITY = new DoubleFloat(Double.NEGATIVE_INFINITY); static { Symbol.DOUBLE_FLOAT_POSITIVE_INFINITY.initializeConstant(DOUBLE_FLOAT_POSITIVE_INFINITY); Symbol.DOUBLE_FLOAT_NEGATIVE_INFINITY.initializeConstant(DOUBLE_FLOAT_NEGATIVE_INFINITY); } public static DoubleFloat getInstance(double d) { if (d == 0) { long bits = Double.doubleToRawLongBits(d); if (bits < 0) return MINUS_ZERO; else return ZERO; } else if (d == 1) return ONE; else if (d == -1) return MINUS_ONE; else return new DoubleFloat(d); } public final double value; public DoubleFloat(double value) { this.value = value; } @Override public LispObject typeOf() { return Symbol.DOUBLE_FLOAT; } @Override public LispObject classOf() { return BuiltInClass.DOUBLE_FLOAT; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.FLOAT) return T; if (typeSpecifier == Symbol.REAL) return T; if (typeSpecifier == Symbol.NUMBER) return T; if (typeSpecifier == Symbol.DOUBLE_FLOAT) return T; if (typeSpecifier == Symbol.LONG_FLOAT) return T; if (typeSpecifier == BuiltInClass.FLOAT) return T; if (typeSpecifier == BuiltInClass.DOUBLE_FLOAT) return T; return super.typep(typeSpecifier); } @Override public boolean numberp() { return true; } @Override public boolean realp() { return true; } @Override public boolean eql(LispObject obj) { if (this == obj) return true; if (obj instanceof DoubleFloat) { if (value == 0) { // "If an implementation supports positive and negative zeros // as distinct values, then (EQL 0.0 -0.0) returns false." double d = ((DoubleFloat)obj).value; long bits = Double.doubleToRawLongBits(d); return bits == Double.doubleToRawLongBits(value); } if (value == ((DoubleFloat)obj).value) return true; } return false; } @Override public boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof DoubleFloat) { if (value == 0) { // same as EQL double d = ((DoubleFloat)obj).value; long bits = Double.doubleToRawLongBits(d); return bits == Double.doubleToRawLongBits(value); } if (value == ((DoubleFloat)obj).value) return true; } return false; } @Override public boolean equalp(int n) { // "If two numbers are the same under =." return value == n; } @Override public boolean equalp(LispObject obj) { if (obj != null && obj.numberp()) return isEqualTo(obj); return false; } @Override public LispObject ABS() { if (value > 0) return this; if (value == 0) // 0.0 or -0.0 return ZERO; return new DoubleFloat(- value); } @Override public boolean plusp() { return value > 0; } @Override public boolean minusp() { return value < 0; } @Override public boolean zerop() { return value == 0; } @Override public boolean floatp() { return true; } public static double getValue(LispObject obj) { if (obj instanceof DoubleFloat) return ((DoubleFloat)obj).value; type_error(obj, Symbol.FLOAT); // Not reached. return 0; } public final double getValue() { return value; } @Override public double doubleValue() { return value; } @Override public Object javaInstance() { return Double.valueOf(value); } @Override public Object javaInstance(Class c) { if (c == Float.class || c == float.class) return Float.valueOf((float)value); return javaInstance(); } @Override public final LispObject incr() { return new DoubleFloat(value + 1); } @Override public final LispObject decr() { return new DoubleFloat(value - 1); } @Override public LispObject negate() { if (value == 0) { long bits = Double.doubleToRawLongBits(value); return (bits < 0) ? ZERO : MINUS_ZERO; } return new DoubleFloat(-value); } @Override public LispObject add(LispObject obj) { if (obj instanceof Fixnum) return new DoubleFloat(value + ((Fixnum)obj).value); if (obj instanceof SingleFloat) return new DoubleFloat(value + ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value + ((DoubleFloat)obj).value); if (obj instanceof Bignum) return new DoubleFloat(value + ((Bignum)obj).doubleValue()); if (obj instanceof Ratio) return new DoubleFloat(value + ((Ratio)obj).doubleValue()); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart()); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject subtract(LispObject obj) { if (obj instanceof Fixnum) return new DoubleFloat(value - ((Fixnum)obj).value); if (obj instanceof SingleFloat) return new DoubleFloat(value - ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value - ((DoubleFloat)obj).value); if (obj instanceof Bignum) return new DoubleFloat(value - ((Bignum)obj).doubleValue()); if (obj instanceof Ratio) return new DoubleFloat(value - ((Ratio)obj).doubleValue()); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(subtract(c.getRealPart()), ZERO.subtract(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject multiplyBy(LispObject obj) { if (obj instanceof Fixnum) return new DoubleFloat(value * ((Fixnum)obj).value); if (obj instanceof SingleFloat) return new DoubleFloat(value * ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value * ((DoubleFloat)obj).value); if (obj instanceof Bignum) return new DoubleFloat(value * ((Bignum)obj).doubleValue()); if (obj instanceof Ratio) return new DoubleFloat(value * ((Ratio)obj).doubleValue()); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(multiplyBy(c.getRealPart()), multiplyBy(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject divideBy(LispObject obj) { if (obj instanceof Fixnum) return new DoubleFloat(value / ((Fixnum)obj).value); if (obj instanceof SingleFloat) return new DoubleFloat(value / ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value / ((DoubleFloat)obj).value); if (obj instanceof Bignum) return new DoubleFloat(value / ((Bignum)obj).doubleValue()); if (obj instanceof Ratio) return new DoubleFloat(value / ((Ratio)obj).doubleValue()); if (obj instanceof Complex) { Complex c = (Complex) obj; LispObject re = c.getRealPart(); LispObject im = c.getImaginaryPart(); LispObject denom = re.multiplyBy(re).add(im.multiplyBy(im)); LispObject resX = multiplyBy(re).divideBy(denom); LispObject resY = multiplyBy(Fixnum.MINUS_ONE).multiplyBy(im).divideBy(denom); return Complex.getInstance(resX, resY); } return type_error(obj, Symbol.NUMBER); } @Override public boolean isEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value == ((Fixnum)obj).value; if (obj instanceof SingleFloat) return value == ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value == ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isEqualTo(obj); if (obj instanceof Ratio) return rational().isEqualTo(obj); if (obj instanceof Complex) return obj.isEqualTo(this); type_error(obj, Symbol.NUMBER); // Not reached. return false; } @Override public boolean isNotEqualTo(LispObject obj) { return !isEqualTo(obj); } @Override public boolean isLessThan(LispObject obj) { if (obj instanceof Fixnum) return value < ((Fixnum)obj).value; if (obj instanceof SingleFloat) return value < ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value < ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isLessThan(obj); if (obj instanceof Ratio) return rational().isLessThan(obj); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThan(LispObject obj) { if (obj instanceof Fixnum) return value > ((Fixnum)obj).value; if (obj instanceof SingleFloat) return value > ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value > ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isGreaterThan(obj); if (obj instanceof Ratio) return rational().isGreaterThan(obj); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isLessThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value <= ((Fixnum)obj).value; if (obj instanceof SingleFloat) return value <= ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value <= ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isLessThanOrEqualTo(obj); if (obj instanceof Ratio) return rational().isLessThanOrEqualTo(obj); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value >= ((Fixnum)obj).value; if (obj instanceof SingleFloat) return value >= ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value >= ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isGreaterThanOrEqualTo(obj); if (obj instanceof Ratio) return rational().isGreaterThanOrEqualTo(obj); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public LispObject truncate(LispObject obj) { // "When rationals and floats are combined by a numerical function, // the rational is first converted to a float of the same format." // 12.1.4.1 if (obj instanceof Fixnum) { return truncate(new DoubleFloat(((Fixnum)obj).value)); } if (obj instanceof Bignum) { return truncate(new DoubleFloat(((Bignum)obj).doubleValue())); } if (obj instanceof Ratio) { return truncate(new DoubleFloat(((Ratio)obj).doubleValue())); } if (obj instanceof SingleFloat) { final LispThread thread = LispThread.currentThread(); double divisor = ((SingleFloat)obj).value; double quotient = value / divisor; if (value != 0) MathFunctions.OverUnderFlowCheck(quotient); if (quotient >= Integer.MIN_VALUE && quotient <= Integer.MAX_VALUE) { int q = (int) quotient; return thread.setValues(Fixnum.getInstance(q), new DoubleFloat(value - q * divisor)); } // We need to convert the quotient to a bignum. long bits = Double.doubleToRawLongBits((double)quotient); int s = ((bits >> 63) == 0) ? 1 : -1; int e = (int) ((bits >> 52) & 0x7ffL); long m; if (e == 0) m = (bits & 0xfffffffffffffL) << 1; else m = (bits & 0xfffffffffffffL) | 0x10000000000000L; LispObject significand = number(m); Fixnum exponent = Fixnum.getInstance(e - 1075); Fixnum sign = Fixnum.getInstance(s); LispObject result = significand; result = result.multiplyBy(MathFunctions.EXPT.execute(Fixnum.TWO, exponent)); result = result.multiplyBy(sign); // Calculate remainder. LispObject product = result.multiplyBy(obj); LispObject remainder = subtract(product); return thread.setValues(result, remainder); } if (obj instanceof DoubleFloat) { // Debug.trace("value = " + value); final LispThread thread = LispThread.currentThread(); double divisor = ((DoubleFloat)obj).value; // Debug.trace("divisor = " + divisor); double quotient = value / divisor; if (value != 0) MathFunctions.OverUnderFlowCheck(quotient); // Debug.trace("quotient = " + quotient); if (quotient >= Integer.MIN_VALUE && quotient <= Integer.MAX_VALUE) { int q = (int) quotient; return thread.setValues(Fixnum.getInstance(q), new DoubleFloat(value - q * divisor)); } // We need to convert the quotient to a bignum. long bits = Double.doubleToRawLongBits((double)quotient); int s = ((bits >> 63) == 0) ? 1 : -1; int e = (int) ((bits >> 52) & 0x7ffL); long m; if (e == 0) m = (bits & 0xfffffffffffffL) << 1; else m = (bits & 0xfffffffffffffL) | 0x10000000000000L; LispObject significand = number(m); // Debug.trace("significand = " + significand.printObject()); Fixnum exponent = Fixnum.getInstance(e - 1075); // Debug.trace("exponent = " + exponent.printObject()); Fixnum sign = Fixnum.getInstance(s); // Debug.trace("sign = " + sign.printObject()); LispObject result = significand; // Debug.trace("result = " + result.printObject()); result = result.multiplyBy(MathFunctions.EXPT.execute(Fixnum.TWO, exponent)); // Debug.trace("result = " + result.printObject()); result = result.truncate(Fixnum.ONE); LispObject remainder = coerceToFloat(thread._values[1]); result = result.multiplyBy(sign); // Debug.trace("result = " + result.printObject()); // // Calculate remainder. // LispObject product = result.multiplyBy(obj); // Debug.trace("product = " + product.printObject()); // LispObject remainder = subtract(product); return thread.setValues(result, remainder); } return type_error(obj, Symbol.REAL); } @Override public int hashCode() { long bits = Double.doubleToLongBits(value); return (int) (bits ^ (bits >>> 32)); } @Override public int psxhash() { if ((value % 1) == 0) return (((int)value) & 0x7fffffff); else return (hashCode() & 0x7fffffff); } @Override public String printObject() { if (value == Double.POSITIVE_INFINITY) { StringBuilder sb = new StringBuilder("#."); sb.append(Symbol.DOUBLE_FLOAT_POSITIVE_INFINITY.printObject()); return sb.toString(); } if (value == Double.NEGATIVE_INFINITY) { StringBuilder sb = new StringBuilder("#."); sb.append(Symbol.DOUBLE_FLOAT_NEGATIVE_INFINITY.printObject()); return sb.toString(); } LispThread thread = LispThread.currentThread(); boolean printReadably = Symbol.PRINT_READABLY.symbolValue(thread) != NIL; if (value != value) { if (printReadably) return "#.(CL:PROGN \"Comment: create a NaN.\" (CL:/ 0.0d0 0.0d0))"; else return unreadableString("DOUBLE-FLOAT NaN", false); } String s1 = String.valueOf(value); if (printReadably || !memq(Symbol.READ_DEFAULT_FLOAT_FORMAT.symbolValue(thread), list(Symbol.DOUBLE_FLOAT, Symbol.LONG_FLOAT))) { if (s1.indexOf('E') >= 0) return s1.replace('E', 'd'); else return s1.concat("d0"); } else return s1; } public LispObject rational() { final long bits = Double.doubleToRawLongBits(value); int sign = ((bits >> 63) == 0) ? 1 : -1; int storedExponent = (int) ((bits >> 52) & 0x7ffL); long mantissa; if (storedExponent == 0) mantissa = (bits & 0xfffffffffffffL) << 1; else mantissa = (bits & 0xfffffffffffffL) | 0x10000000000000L; if (mantissa == 0) return Fixnum.ZERO; if (sign < 0) mantissa = -mantissa; // Subtract bias. final int exponent = storedExponent - 1023; BigInteger numerator, denominator; if (exponent < 0) { numerator = BigInteger.valueOf(mantissa); denominator = BigInteger.valueOf(1).shiftLeft(52 - exponent); } else { numerator = BigInteger.valueOf(mantissa).shiftLeft(exponent); denominator = BigInteger.valueOf(0x10000000000000L); // (ash 1 52) } return number(numerator, denominator); } public static DoubleFloat coerceToFloat(LispObject obj) { if (obj instanceof DoubleFloat) return (DoubleFloat) obj; if (obj instanceof Fixnum) return new DoubleFloat(((Fixnum)obj).value); if (obj instanceof Bignum) return new DoubleFloat(((Bignum)obj).doubleValue()); if (obj instanceof SingleFloat) return new DoubleFloat(((SingleFloat)obj).value); if (obj instanceof Ratio) return new DoubleFloat(((Ratio)obj).doubleValue()); error(new TypeError("The value " + obj.princToString() + " cannot be converted to type DOUBLE-FLOAT.")); // Not reached. return null; } } abcl-src-1.9.0/src/org/armedbear/lisp/DowncaseStream.java0100644 0000000 0000000 00000004005 14202767264 022000 0ustar000000000 0000000 /* * DowncaseStream.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class DowncaseStream extends CaseFrobStream { public DowncaseStream(Stream target) { super(target); } @Override public void _writeChar(char c) { target._writeChar(LispCharacter.toLowerCase(c)); } @Override public void _writeString(String s) { target._writeString(s.toLowerCase()); } @Override public void _writeLine(String s) { target._writeLine(s.toLowerCase()); } } abcl-src-1.9.0/src/org/armedbear/lisp/EMFCache.java0100644 0000000 0000000 00000022033 14202767264 020415 0ustar000000000 0000000 /* * EMFCache.java * * Copyright (C) 2003-2006 Peter Graves, 2013 Rudolf Schlatte * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.concurrent.ConcurrentHashMap; public final class EMFCache extends LispObject { ConcurrentHashMap cache = new ConcurrentHashMap();; EqlSpecialization eqlSpecializations[] = new EqlSpecialization[0]; void clearCache() { cache = new ConcurrentHashMap(); } @Override public String printObject() { return unreadableString("EMF-CACHE"); } static final FuncallableStandardObject checkStandardGenericFunction(LispObject obj) { if (obj instanceof FuncallableStandardObject) return (FuncallableStandardObject) obj; return (FuncallableStandardObject) // Not reached. type_error(obj, Symbol.STANDARD_GENERIC_FUNCTION); } private static class EqlSpecialization extends LispObject { public LispObject eqlTo; public EqlSpecialization(LispObject eqlTo) { this.eqlTo = eqlTo; } } private static class CacheEntry { final LispObject[] array; CacheEntry(LispObject[] array) { this.array = array; } @Override public int hashCode() { int result = 0; for (int i = array.length; i-- > 0;) result ^= array[i].hashCode(); return result; } @Override public boolean equals(Object object) { if (!(object instanceof CacheEntry)) return false; final CacheEntry otherEntry = (CacheEntry) object; if (otherEntry.array.length != array.length) return false; final LispObject[] otherArray = otherEntry.array; for (int i = array.length; i-- > 0;) if (array[i] != otherArray[i]) return false; return true; } } private static final Primitive _MAKE_EMF_CACHE = new pf__make_emf_cache(); @DocString(name="%make-emf-cache") private static final class pf__make_emf_cache extends Primitive { pf__make_emf_cache() { super("%make-emf-cache", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return new EMFCache(); } }; private static final Primitive _REINIT_EMF_CACHE = new pf__reinit_emf_cache(); @DocString(name="%reinit-emf-cache", args="generic-function eql-specilizer-objects-list") private static final class pf__reinit_emf_cache extends Primitive { pf__reinit_emf_cache() { super("%reinit-emf-cache", PACKAGE_SYS, true, "generic-function eql-specializer-objects-list"); } @Override public LispObject execute(LispObject generic_function, LispObject eql_specializers) { final FuncallableStandardObject gf = checkStandardGenericFunction(generic_function); EMFCache cache = gf.cache; cache.clearCache(); cache.eqlSpecializations = new EqlSpecialization[eql_specializers.length()]; for (int i = 0; i < cache.eqlSpecializations.length; i++) { cache.eqlSpecializations[i] = new EqlSpecialization(eql_specializers.car()); eql_specializers = eql_specializers.cdr(); } return T; } }; private static final Primitive CACHE_EMF = new pf_cache_emf(); @DocString(name="cache-emf", args="generic-function args emf") private static final class pf_cache_emf extends Primitive { pf_cache_emf() { super("cache-emf", PACKAGE_SYS, true, "generic-function args emf"); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { final FuncallableStandardObject gf = checkStandardGenericFunction(first); EMFCache cache = gf.cache; LispObject args = second; int numberOfRequiredArgs = gf.getInstanceSlotValue(Symbol.REQUIRED_ARGS).length(); LispObject[] array = new LispObject[numberOfRequiredArgs]; for (int i = numberOfRequiredArgs; i-- > 0;) { array[i] = cache.getArgSpecialization(args.car()); args = args.cdr(); } CacheEntry specializations = new CacheEntry(array); ConcurrentHashMap ht = cache.cache; ht.put(specializations, third); return third; } }; private static final Primitive GET_CACHED_EMF = new pf_get_cached_emf(); @DocString(name="get-cached-emf", args="generic-function args") private static final class pf_get_cached_emf extends Primitive { pf_get_cached_emf() { super("get-cached-emf", PACKAGE_SYS, true, "generic-function args"); } @Override public LispObject execute(LispObject first, LispObject second) { final FuncallableStandardObject gf = checkStandardGenericFunction(first); EMFCache cache = gf.cache; LispObject args = second; int numberOfRequiredArgs = gf.getInstanceSlotValue(Symbol.REQUIRED_ARGS).length(); LispObject[] array = new LispObject[numberOfRequiredArgs]; for (int i = numberOfRequiredArgs; i-- > 0;) { array[i] = cache.getArgSpecialization(args.car()); args = args.cdr(); } CacheEntry specializations = new CacheEntry(array); ConcurrentHashMap ht = cache.cache; LispObject emf = (LispObject) ht.get(specializations); return emf != null ? emf : NIL; } }; /** * Returns an object representing generic function * argument arg in a CacheEntry * *

In the simplest case, when this generic function * does not have EQL specialized methods, and therefore * only argument types are relevant for choosing * applicable methods, the value returned is the * class of arg * *

If the function has EQL specialized methods: * - if arg is EQL to some of the EQL-specializers, * a special object representing equality to that specializer * is returned. * - otherwise class of the arg is returned. * *

Note that we do not consider argument position, when * calculating arg specialization. In rare cases (when one argument * is eql-specialized to a symbol specifying class of another * argument) this may result in redundant cache entries caching the * same method. But the method cached is anyway correct for the * arguments (because in case of cache miss, correct method is * calculated by other code, which does not rely on * getArgSpecialization; and because EQL is true only for objects of * the same type, which guaranties that if a type-specialized * methods was chached by eql-specialization, all the cache hits * into this records will be from args of the conforming type). * *

Consider: *


   * (defgeneric f (a b))
   *
   * (defmethod f (a (b (eql 'symbol)))
   *   "T (EQL 'SYMBOL)")
   *
   * (defmethod f ((a symbol) (b (eql 'symbol)))
   *   "SYMBOL (EQL 'SYMBOL)")
   *
   * (f 12 'symbol)
   * => "T (EQL 'SYMBOL)"
   *
   * (f 'twelve 'symbol)
   * => "SYMBOL (EQL 'SYMBOL)"
   *
   * (f 'symbol 'symbol)
   * => "SYMBOL (EQL 'SYMBOL)"
   *
   * 
* * After the two above calls cache will contain three keys: *
   * { class FIXNUM, EqlSpecialization('SYMBOL) }
   * { class SYMBOL, EqlSpecialization('SYMBOL) }
   * { EqlSpecialization('SYMBOL), EqlSpecialization('SYMBOL) }.
   * 
*/ LispObject getArgSpecialization(LispObject arg) { for (EqlSpecialization eqlSpecialization : eqlSpecializations) { if (eqlSpecialization.eqlTo.eql(arg)) return eqlSpecialization; } return arg.classOf(); } } abcl-src-1.9.0/src/org/armedbear/lisp/EchoStream.java0100644 0000000 0000000 00000015567 14202767264 021132 0ustar000000000 0000000 /* * EchoStream.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class EchoStream extends Stream { private final Stream in; private final Stream out; private int unreadChar = -1; public EchoStream(Stream in, Stream out) { super(Symbol.ECHO_STREAM); this.in = in; this.out = out; } public EchoStream(Stream in, Stream out, boolean interactive) { super(Symbol.ECHO_STREAM); this.in = in; this.out = out; setInteractive(interactive); } @Override public LispObject getElementType() { LispObject itype = in.getElementType(); LispObject otype = out.getElementType(); if (itype.equal(otype)) return itype; return Symbol.NULL; // FIXME } public Stream getInputStream() { return in; } public Stream getOutputStream() { return out; } @Override public LispObject typeOf() { return Symbol.ECHO_STREAM; } @Override public LispObject classOf() { return BuiltInClass.ECHO_STREAM; } @Override public LispObject typep(LispObject type) { if (type == Symbol.ECHO_STREAM) return T; if (type == BuiltInClass.ECHO_STREAM) return T; return super.typep(type); } @Override public boolean isInputStream() { return true; } @Override public boolean isOutputStream() { return true; } @Override public boolean isCharacterInputStream() { return in.isCharacterInputStream(); } @Override public boolean isBinaryInputStream() { return in.isBinaryInputStream(); } @Override public boolean isCharacterOutputStream() { return out.isCharacterOutputStream(); } @Override public boolean isBinaryOutputStream() { return out.isBinaryOutputStream(); } // Returns -1 at end of file. @Override protected int _readChar() throws java.io.IOException { int n = in._readChar(); if (n >= 0) { // Not at end of file. if (unreadChar < 0) out._writeChar((char)n); else unreadChar = -1; } return n; } @Override protected void _unreadChar(int n) throws java.io.IOException { in._unreadChar(n); unreadChar = n; } @Override protected boolean _charReady() throws java.io.IOException { return in._charReady(); } @Override public void _writeChar(char c) { out._writeChar(c); } @Override public void _writeChars(char[] chars, int start, int end) { out._writeChars(chars, start, end); } @Override public void _writeString(String s) { out._writeString(s); } @Override public void _writeLine(String s) { out._writeLine(s); } // Reads an 8-bit byte. @Override public int _readByte() { int n = in._readByte(); if (n >= 0) out._writeByte(n); return n; } // Writes an 8-bit byte. @Override public void _writeByte(int n) { out._writeByte(n); } @Override public void _finishOutput() { out._finishOutput(); } @Override public void _clearInput() { in._clearInput(); } @Override public LispObject close(LispObject abort) { // "The effect of CLOSE on a constructed stream is to close the // argument stream only. There is no effect on the constituents of // composite streams." setOpen(false); return T; } @Override public LispObject listen() { return in.listen(); } @Override public LispObject freshLine() { return out.freshLine(); } // ### make-echo-stream // input-stream output-stream => echo-stream private static final Primitive MAKE_ECHO_STREAM = new Primitive("make-echo-stream", "input-stream output-stream") { @Override public LispObject execute(LispObject first, LispObject second) { if (!(first instanceof Stream)) return type_error(first, Symbol.STREAM); if (!(second instanceof Stream)) return type_error(second, Symbol.STREAM); return new EchoStream((Stream) first, (Stream) second); } }; // ### echo-stream-input-stream // echo-stream => input-stream private static final Primitive ECHO_STREAM_INPUT_STREAM = new Primitive("echo-stream-input-stream", "echo-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof EchoStream) return ((EchoStream)arg).getInputStream(); return type_error(arg, Symbol.ECHO_STREAM); } }; // ### echo-stream-output-stream // echo-stream => output-stream private static final Primitive ECHO_STREAM_OUTPUT_STREAM = new Primitive("echo-stream-output-stream", "echo-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof EchoStream) return ((EchoStream)arg).getOutputStream(); return type_error(arg, Symbol.ECHO_STREAM); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/EndOfFile.java0100644 0000000 0000000 00000004446 14202767264 020665 0ustar000000000 0000000 /* * EndOfFile.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class EndOfFile extends StreamError { public EndOfFile(Stream stream) { super(StandardClass.END_OF_FILE); setStream(stream); } public EndOfFile(LispObject initArgs) { super(StandardClass.END_OF_FILE); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.END_OF_FILE; } @Override public LispObject classOf() { return StandardClass.END_OF_FILE; } @Override public LispObject typep(LispObject type) { if (type == Symbol.END_OF_FILE) return T; if (type == StandardClass.END_OF_FILE) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/Environment.java0100644 0000000 0000000 00000025326 14202767264 021376 0ustar000000000 0000000 /* * Environment.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.Serializable; import static org.armedbear.lisp.Lisp.*; public final class Environment extends LispObject implements Serializable { Binding vars; FunctionBinding lastFunctionBinding; private Binding blocks; private Binding tags; public boolean inactive; //default value: false == active public Environment() {} public Environment(Environment parent) { if (parent != null) { vars = parent.vars; lastFunctionBinding = parent.lastFunctionBinding; blocks = parent.blocks; tags = parent.tags; } } // Construct a new Environment extending parent with the specified symbol- // value binding. public Environment(Environment parent, Symbol symbol, LispObject value) { this(parent); vars = new Binding(symbol, value, vars); } @Override public LispObject typeOf() { return Symbol.ENVIRONMENT; } @Override public LispObject classOf() { return BuiltInClass.ENVIRONMENT; } @Override public LispObject typep(LispObject type) { if (type == Symbol.ENVIRONMENT) return T; if (type == BuiltInClass.ENVIRONMENT) return T; return super.typep(type); } public boolean isEmpty() { if (lastFunctionBinding != null) return false; if (vars != null) { for (Binding binding = vars; binding != null; binding = binding.next) if (!binding.specialp) return false; } return true; } public void bind(Symbol symbol, LispObject value) { vars = new Binding(symbol, value, vars); } public void rebind(Symbol symbol, LispObject value) { Binding binding = getBinding(symbol); binding.value = value; } public LispObject lookup(LispObject symbol, Binding binding) { while (binding != null) { if (binding.symbol == symbol) return binding.value; binding = binding.next; } return null; } public LispObject lookup(LispObject symbol) { return lookup(symbol, vars); } public Binding getBinding(LispObject symbol) { return getBinding(symbol, vars); } public Binding getBinding(LispObject symbol, Binding binding) { while (binding != null) { if (binding.symbol == symbol) return binding; binding = binding.next; } return null; } // Function bindings. public void addFunctionBinding(LispObject name, LispObject value) { lastFunctionBinding = new FunctionBinding(name, value, lastFunctionBinding); } public LispObject lookupFunction(LispObject name) { FunctionBinding binding = lastFunctionBinding; if (name instanceof Symbol) { while (binding != null) { if (binding.name == name) return binding.value; binding = binding.next; } // Not found in environment. return name.getSymbolFunction(); } if (name instanceof Cons) { while (binding != null) { if (binding.name.equal(name)) return binding.value; binding = binding.next; } } return null; } public void addBlock(LispObject symbol, LispObject block) { blocks = new Binding(symbol, this, block, blocks); } public LispObject lookupBlock(LispObject symbol) { Binding binding = blocks; while (binding != null) { if (binding.symbol == symbol) return binding.value; binding = binding.next; } return null; } public Binding getBlockBinding(LispObject block) { Binding binding = blocks; while (binding != null) { if (binding.symbol == block) return binding; binding = binding.next; } return null; } public void addTagBinding(LispObject tag, LispObject code) { tags = new Binding(tag, this, code, tags); } public Binding getTagBinding(LispObject tag) { Binding binding = tags; while (binding != null) { if (binding.symbol.eql(tag)) return binding; binding = binding.next; } return null; } // Returns body with declarations removed. public LispObject processDeclarations(LispObject body) { LispObject bodyAndDecls = parseBody(body, false); LispObject specials = parseSpecials(bodyAndDecls.NTH(1)); for (; specials != NIL; specials = specials.cdr()) declareSpecial(checkSymbol(specials.car())); return bodyAndDecls.car(); } public void declareSpecial(Symbol var) { vars = new Binding(var, null, vars); vars.specialp = true; } /** Return true if a symbol is declared special. * * If there is no binding in the current (lexical) environment, * the current dynamic environment (thread) is checked. */ public boolean isDeclaredSpecial(Symbol var) { Binding binding = getBinding(var); return (binding != null) ? binding.specialp : (LispThread.currentThread().getSpecialBinding(var) != null); } @Override public String printObject() { return unreadableString("ENVIRONMENT"); } // ### make-environment public static final Primitive MAKE_ENVIRONMENT = new Primitive("make-environment", PACKAGE_SYS, true, "&optional parent-environment") { @Override public LispObject execute() { return new Environment(); } @Override public LispObject execute(LispObject arg) { if (arg == NIL) return new Environment(); return new Environment(checkEnvironment(arg)); } }; // ### environment-add-macro-definition public static final Primitive ENVIRONMENT_ADD_MACRO_DEFINITION = new Primitive("environment-add-macro-definition", PACKAGE_SYS, true, "environment name expander") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { Environment env = checkEnvironment(first); LispObject name = second; LispObject expander = third; env.addFunctionBinding(name, expander); return env; } }; // ### environment-add-function-definition public static final Primitive ENVIRONMENT_ADD_FUNCTION_DEFINITION = new Primitive("environment-add-function-definition", PACKAGE_SYS, true, "environment name lambda-expression") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { checkEnvironment(first).addFunctionBinding(second, third); return first; } }; // ### environment-add-symbol-binding public static final Primitive ENVIRONMENT_ADD_SYMBOL_BINDING = new Primitive("environment-add-symbol-binding", PACKAGE_SYS, true, "environment symbol value") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { checkEnvironment(first).bind(checkSymbol(second), third); return first; } }; // ### empty-environment-p private static final Primitive EMPTY_ENVIRONMENT_P = new Primitive("empty-environment-p", PACKAGE_SYS, true, "environment") { @Override public LispObject execute(LispObject arg) { return checkEnvironment(arg).isEmpty() ? T : NIL; } }; // ### environment-variables private static final Primitive ENVIRONMENT_VARS = new Primitive("environment-variables", PACKAGE_SYS, true, "environment") { @Override public LispObject execute(LispObject arg) { Environment env = checkEnvironment(arg); LispObject result = NIL; for (Binding binding = env.vars; binding != null; binding = binding.next) if (!binding.specialp) result = result.push(new Cons(binding.symbol, binding.value)); return result.nreverse(); } }; // ### environment-all-variables private static final Primitive ENVIRONMENT_ALL_VARS = new Primitive("environment-all-variables", PACKAGE_SYS, true, "environment") { @Override public LispObject execute(LispObject arg) { Environment env = checkEnvironment(arg); LispObject result = NIL; for (Binding binding = env.vars; binding != null; binding = binding.next) if (binding.specialp) result = result.push(binding.symbol); else result = result.push(new Cons(binding.symbol, binding.value)); return result.nreverse(); } }; // ### environment-all-functions private static final Primitive ENVIRONMENT_ALL_FUNS = new Primitive("environment-all-functions", PACKAGE_SYS, true, "environment") { @Override public LispObject execute(LispObject arg) { Environment env = checkEnvironment(arg); LispObject result = NIL; for (FunctionBinding binding = env.lastFunctionBinding; binding != null; binding = binding.next) result = result.push(new Cons(binding.name, binding.value)); return result.nreverse(); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Extensions.java0100644 0000000 0000000 00000031665 14242624277 021234 0ustar000000000 0000000 /* * Extensions.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.IOException; import java.util.*; public final class Extensions { // ### *ed-functions* public static final Symbol _ED_FUNCTIONS_ = exportSpecial("*ED-FUNCTIONS*", PACKAGE_EXT, list(intern("DEFAULT-ED-FUNCTION", PACKAGE_SYS))); // ### truly-the value-type form => result* private static final SpecialOperator TRULY_THE = new truly_the(); private static class truly_the extends SpecialOperator { truly_the() { super("truly-the", PACKAGE_EXT, true, "type value"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() != 2) return error(new WrongNumberOfArgumentsException(this, 2)); return eval(args.cadr(), env, LispThread.currentThread()); } } // ### neq private static final Primitive NEQ = new neq(); private static class neq extends Primitive { neq() { super(Symbol.NEQ, "obj1 obj2"); } @Override public LispObject execute(LispObject first, LispObject second) { return first != second ? T : NIL; } } // ### memq item list => tail private static final Primitive MEMQ = new memq(); private static class memq extends Primitive { memq() { super(Symbol.MEMQ, "item list"); } @Override public LispObject execute(LispObject item, LispObject list) { while (list instanceof Cons) { if (item == ((Cons)list).car) return list; list = ((Cons)list).cdr; } if (list != NIL) type_error(list, Symbol.LIST); return NIL; } } // ### memql item list => tail private static final Primitive MEMQL = new memql(); private static class memql extends Primitive { memql() { super(Symbol.MEMQL, "item list"); } @Override public LispObject execute(LispObject item, LispObject list) { while (list instanceof Cons) { if (item.eql(((Cons)list).car)) return list; list = ((Cons)list).cdr; } if (list != NIL) type_error(list, Symbol.LIST); return NIL; } } // ### adjoin-eql item list => new-list private static final Primitive ADJOIN_EQL = new adjoin_eql(); private static class adjoin_eql extends Primitive { adjoin_eql() { super(Symbol.ADJOIN_EQL, "item list"); } @Override public LispObject execute(LispObject item, LispObject list) { return memql(item, list) ? list : new Cons(item, list); } } // ### special-variable-p private static final Primitive SPECIAL_VARIABLE_P = new special_variable_p(); private static class special_variable_p extends Primitive { special_variable_p() { super("special-variable-p", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { return arg.isSpecialVariable() ? T : NIL; } } // ### source symbol private static final Primitive SOURCE = new source(); private static class source extends Primitive { source() { super("source", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { return get(arg, Symbol._SOURCE, NIL); } } // ### source-file-position symbol private static final Primitive SOURCE_FILE_POSITION = new source_file_position(); private static class source_file_position extends Primitive { source_file_position() { super("source-file-position", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { LispObject obj = get(arg, Symbol._SOURCE, NIL); if (obj instanceof Cons) return obj.cdr(); return NIL; } } // XXX rename to something else as it doesn't always refer to a pathname. public static final Primitive SOURCE_PATHNAME = new pf_source_pathname(); @DocString( name="source-pathname", args="symbol", doc="Returns either the pathname corresponding to the file from which this symbol was compiled," + "or the keyword :TOP-LEVEL." ) private static class pf_source_pathname extends Primitive { pf_source_pathname() { super("source-pathname", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { LispObject obj = get(arg, Symbol._SOURCE, NIL); if (obj instanceof Cons) return obj.car(); return obj; } } // ### exit private static final Primitive EXIT = new exit(); private static class exit extends Primitive { exit() { super("exit", PACKAGE_EXT, true, "&key status"); } @Override public LispObject execute() { throw new ProcessingTerminated(); } @Override public LispObject execute(LispObject first, LispObject second) { int status = 0; if (first == Keyword.STATUS) { if (second instanceof Fixnum) status = ((Fixnum)second).value; } throw new ProcessingTerminated(status); } } // ### quit private static final Primitive QUIT = new quit(); private static class quit extends Primitive { quit() { super("quit", PACKAGE_EXT, true, "&key status"); } @Override public LispObject execute() { ((Stream)Symbol.STANDARD_OUTPUT.getSymbolValue())._finishOutput(); ((Stream)Symbol.ERROR_OUTPUT.getSymbolValue())._finishOutput(); throw new ProcessingTerminated(); } @Override public LispObject execute(LispObject first, LispObject second) { int status = 0; if (first == Keyword.STATUS) { if (second instanceof Fixnum) status = ((Fixnum)second).value; } throw new ProcessingTerminated(status); } } // ### dump-java-stack private static final Primitive DUMP_JAVA_STACK = new dump_java_stack(); private static class dump_java_stack extends Primitive { dump_java_stack() { super("dump-java-stack", PACKAGE_EXT, true); } @Override public LispObject execute() { Thread.dumpStack(); return LispThread.currentThread().nothing(); } } public static final Primitive MAKE_TEMP_FILE = new make_temp_file(); @DocString(name="make-temp-file", doc="Create and return the pathname of a previously non-existent file.", args="&key prefix suffix") private static class make_temp_file extends Primitive { make_temp_file() { super("make-temp-file", PACKAGE_EXT, true, "&key prefix suffix"); } @Override public LispObject execute(LispObject ... args) { String prefix = "abcl"; String suffix = null; if ( args.length % 2 != 0) { error(new WrongNumberOfArgumentsException("Expecting an even number of arguments including keywords.")); } for (int i = 0; i < args.length; i++ ) { if (args[i].SYMBOLP() != NIL) { if (args[i].equals(Keyword.PREFIX)) { String specifiedPrefix = args[i + 1].getStringValue(); if (specifiedPrefix != null) { if (specifiedPrefix.equals(NIL.getStringValue())) { error (new TypeError("Cannot create temporary file with NIL prefix.")); } prefix = specifiedPrefix; i += 1; } } else if (args[i].equals(Keyword.SUFFIX)) { String specifiedSuffix = args[i + 1].getStringValue(); if (specifiedSuffix != null) { if (specifiedSuffix.equals(NIL.getStringValue())) { suffix =null; } else { suffix = specifiedSuffix; } i += 1; } } } else { error(new TypeError("Expected matching keyword argument.", args[i], Keyword.PREFIX.classOf())); } } return createTempFile(prefix, suffix); } @Override public LispObject execute() { return createTempFile("abcl", null); } private LispObject createTempFile(String prefix, String suffix) { try { File file = File.createTempFile(prefix, suffix, null); if (file != null) return Pathname.create(file.getPath()); } catch (IllegalArgumentException e) { // "Failed to create temporary file due to argument problems." error(new JavaException(e)); } catch (SecurityException e) { //"Failed to create problem due to problems with JVM SecurityManager." error(new JavaException(e)); } catch (IOException e) { // "Failed to create temporary file." error(new JavaException(e)); } return NIL; } } public static final Primitive MAKE_TEMP_DIRECTORY = new make_temp_directory(); @DocString(name="make-temp-directory", doc="Create and return the pathname of a previously non-existent directory.") private static class make_temp_directory extends Primitive { make_temp_directory() { super("make-temp-directory", PACKAGE_EXT, true, ""); } @Override public LispObject execute() { try { File dir = File.createTempFile("abcl", null); dir.delete(); if (dir.mkdirs()) { return Pathname.create(dir + "/"); } } catch (Throwable t) { Debug.trace(t); } return NIL; } } // ### interrupt-lisp private static final Primitive INTERRUPT_LISP = new interrupt_lisp(); private static class interrupt_lisp extends Primitive { interrupt_lisp() { super("interrupt-lisp", PACKAGE_EXT, true, ""); } @Override public LispObject execute(LispObject[] args) { if (args.length < 1) return error(new WrongNumberOfArgumentsException(this, 1, -1)); final LispThread thread; if (args[0] instanceof LispThread) { thread = (LispThread) args[0]; } else { return type_error(args[0], Symbol.THREAD); } setInterrupted(thread,true); // engage the compiler-insert check Lisp.interrupted/Lisp.handleInterrupts mechanism return T; } } // ### getenv variable => string private static final Primitive GETENV = new getenv(); private static class getenv extends Primitive { getenv() { super("getenv", PACKAGE_EXT, true, "variable", "Return the value of the environment VARIABLE if it exists, otherwise return NIL."); } @Override public LispObject execute(LispObject arg) { AbstractString string; if (arg instanceof AbstractString) { string = (AbstractString) arg; } else return type_error(arg, Symbol.STRING); String result = System.getenv(string.getStringValue()); if (result != null) return new SimpleString(result); else return NIL; } } // ### getenv-all variable => string private static final Primitive GETENV_ALL = new getenv_all(); private static class getenv_all extends Primitive { getenv_all() { super("getenv-all", PACKAGE_EXT, true, "variable", "Returns all environment variables as an alist containing (name . value)"); } @Override public LispObject execute() { Cons result = new Cons(NIL); Map env = System.getenv(); for (Map.Entry entry : env.entrySet()) { Cons entryPair = new Cons(new SimpleString(entry.getKey()), new SimpleString(entry.getValue())); result = new Cons(entryPair, result); } return result; } } } abcl-src-1.9.0/src/org/armedbear/lisp/FaslClassLoader.java0100644 0000000 0000000 00000015364 14223403213 022055 0ustar000000000 0000000 /* * JavaClassLoader.java * * Copyright (C) 2010 Alessio Stalla * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.InputStream; import static org.armedbear.lisp.Lisp.*; public class FaslClassLoader extends JavaClassLoader { private final String baseName; private final JavaObject boxedThis = new JavaObject(this); public FaslClassLoader(String baseName) { this.baseName = baseName; } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { /* First we check if we should load the class ourselves, * allowing the default handlers to kick in if we don't... * * This strategy eliminates ClassNotFound exceptions inside * the inherited loadClass() eliminated ~80k exceptions during * Maxima compilation. Generally, creation of an exception object * is a pretty heavy operation, because it processes the call stack, * which - in ABCL - is pretty deep, most of the time. */ if (name.startsWith(baseName + "_")) { String internalName = name.replace(".", "/"); if (!internalName.contains("/")) internalName = "org/armedbear/lisp/" + internalName; Class c = this.findLoadedClass(internalName); if (c == null && checkPreCompiledClassLoader) { c = findPrecompiledClassOrNull(name); // Oh, we have to return here so we don't become the owning class loader? if (c != null) return c; } if (c == null) { c = findClass(name); } if (c != null) { if (resolve) { resolveClass(c); } return c; } } // Fall through to our super's default handling return super.loadClass(name, resolve); } @Override protected Class findClass(String name) throws ClassNotFoundException { try { if (checkPreCompiledClassLoader) { Class c = findPrecompiledClassOrNull(name); if (c != null) return c; } byte[] b = getFunctionClassBytes(name); return defineLispClass(name, b, 0, b.length); } catch(Throwable e) { //TODO handle this better, readFunctionBytes uses Debug.assert() but should return null e.printStackTrace(); if(e instanceof ControlTransfer) { throw (ControlTransfer) e; } throw new ClassNotFoundException("Function class not found: " + name, e); } } @Override public InputStream getResourceAsStream(String resourceName) { final LispThread thread = LispThread.currentThread(); Pathname name = (Pathname)Pathname.create(resourceName.substring("org/armedbear/lisp/".length())); LispObject truenameFasl = Symbol.LOAD_TRUENAME_FASL.symbolValue(thread); LispObject truename = Symbol.LOAD_TRUENAME.symbolValue(thread); if (truenameFasl instanceof Pathname) { return (Pathname.mergePathnames(name, (Pathname)truenameFasl, Keyword.NEWEST)) .getInputStream(); } else if (truename instanceof Pathname) { return (Pathname.mergePathnames(name, (Pathname) truename, Keyword.NEWEST)) .getInputStream(); } else if (!Symbol.PROBE_FILE.execute(name).equals(NIL)) { return name.getInputStream(); } return null; } public LispObject loadFunction(int fnNumber) { //Function name is fnIndex + 1 String name = baseName + "_" + (fnNumber + 1); try { Class clz = loadClass(name); Function f = (Function) clz.newInstance(); if (clz.getClassLoader() instanceof JavaClassLoader) { // Don't do this for system classes (though probably dont need this for other classes) f.setClassBytes(getFunctionClassBytes(name)); } return f; } catch(Throwable e) { if(e instanceof ControlTransfer) { throw (ControlTransfer) e; } Debug.trace(e); return error(new LispError("Compiled function can't be loaded: " + name + " from " + Symbol.LOAD_TRUENAME.symbolValue())); } } private static final Primitive MAKE_FASL_CLASS_LOADER = new pf_make_fasl_class_loader(); private static final class pf_make_fasl_class_loader extends Primitive { pf_make_fasl_class_loader() { super("make-fasl-class-loader", PACKAGE_SYS, false, "base-name"); } @Override public LispObject execute(LispObject baseName) { return new FaslClassLoader(baseName.getStringValue()).boxedThis; } }; private static final Primitive GET_FASL_FUNCTION = new pf_get_fasl_function(); private static final class pf_get_fasl_function extends Primitive { pf_get_fasl_function() { super("get-fasl-function", PACKAGE_SYS, false, "loader function-number"); } @Override public LispObject execute(LispObject loader, LispObject fnNumber) { FaslClassLoader l = (FaslClassLoader) loader.javaInstance(FaslClassLoader.class); return l.loadFunction(fnNumber.intValue()); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/FaslReader.java0100644 0000000 0000000 00000023171 14202767264 021076 0ustar000000000 0000000 /* * FaslReader.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class FaslReader { // ### fasl-read-string public static final ReaderMacroFunction FASL_READ_STRING = new ReaderMacroFunction("fasl-read-string", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char terminator) { return stream.readString(terminator, Stream.faslReadtable); } }; // ### fasl-read-list public static final ReaderMacroFunction FASL_READ_LIST = new ReaderMacroFunction("fasl-read-list", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char ignored) { return stream.readList(false, Stream.faslReadtable); } }; // ### fasl-read-quote public static final ReaderMacroFunction FASL_READ_QUOTE = new ReaderMacroFunction("fasl-read-quote", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char ignored) { return new Cons(Symbol.QUOTE, new Cons(stream.read(true, NIL, true, LispThread.currentThread(), Stream.faslReadtable))); } }; // ### fasl-read-dispatch-char public static final ReaderMacroFunction FASL_READ_DISPATCH_CHAR = new ReaderMacroFunction("fasl-read-dispatch-char", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char c) { return stream.readDispatchChar(c, Stream.faslReadtable); } }; // ### fasl-sharp-left-paren public static final DispatchMacroFunction FASL_SHARP_LEFT_PAREN = new DispatchMacroFunction("fasl-sharp-left-paren", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readSharpLeftParen(c, n, Stream.faslReadtable); } }; // ### fasl-sharp-star public static final DispatchMacroFunction FASL_SHARP_STAR = new DispatchMacroFunction("fasl-sharp-star", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char ignored, int n) { return stream.readSharpStar(ignored, n, Stream.faslReadtable); } }; // ### fasl-sharp-dot public static final DispatchMacroFunction FASL_SHARP_DOT = new DispatchMacroFunction("fasl-sharp-dot", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readSharpDot(c, n, Stream.faslReadtable); } }; // ### fasl-sharp-colon public static final DispatchMacroFunction FASL_SHARP_COLON = new DispatchMacroFunction("fasl-sharp-colon", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { LispThread thread = LispThread.currentThread(); return stream.readSymbol(FaslReadtable.getInstance()); } }; // ### fasl-sharp-a public static final DispatchMacroFunction FASL_SHARP_A = new DispatchMacroFunction("fasl-sharp-a", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readArray(n, Stream.faslReadtable); } }; // ### fasl-sharp-b public static final DispatchMacroFunction FASL_SHARP_B = new DispatchMacroFunction("fasl-sharp-b", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readRadix(2, Stream.faslReadtable); } }; // ### fasl-sharp-c public static final DispatchMacroFunction FASL_SHARP_C = new DispatchMacroFunction("fasl-sharp-c", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readComplex(Stream.faslReadtable); } }; // ### fasl-sharp-o public static final DispatchMacroFunction FASL_SHARP_O = new DispatchMacroFunction("fasl-sharp-o", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readRadix(8, Stream.faslReadtable); } }; // ### fasl-sharp-p public static final DispatchMacroFunction FASL_SHARP_P = new DispatchMacroFunction("fasl-sharp-p", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readPathname(Stream.faslReadtable); } }; // ### fasl-sharp-r public static final DispatchMacroFunction FASL_SHARP_R = new DispatchMacroFunction("fasl-sharp-r", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readRadix(n, Stream.faslReadtable); } }; // ### fasl-sharp-s public static final DispatchMacroFunction FASL_SHARP_S = new DispatchMacroFunction("fasl-sharp-s", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readStructure(Stream.faslReadtable); } }; // ### fasl-sharp-x public static final DispatchMacroFunction FASL_SHARP_X = new DispatchMacroFunction("fasl-sharp-x", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readRadix(16, Stream.faslReadtable); } }; // ### fasl-sharp-quote public static final DispatchMacroFunction FASL_SHARP_QUOTE = new DispatchMacroFunction("fasl-sharp-quote", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return new Cons(Symbol.FUNCTION, new Cons(stream.read(true, NIL, true, LispThread.currentThread(), Stream.faslReadtable))); } }; // ### fasl-sharp-backslash public static final DispatchMacroFunction FASL_SHARP_BACKSLASH = new DispatchMacroFunction("fasl-sharp-backslash", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readCharacterLiteral(FaslReadtable.getInstance(), LispThread.currentThread()); } }; // ### fasl-sharp-question-mark public static final DispatchMacroFunction FASL_SHARP_QUESTION_MARK = new DispatchMacroFunction("fasl-sharp-question-mark", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return Load.getUninternedSymbol(n); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/FaslReadtable.java0100644 0000000 0000000 00000012420 14223403213 021532 0ustar000000000 0000000 /* * FaslReadtable.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class FaslReadtable extends Readtable { public FaslReadtable() { super(); } @Override protected void initialize() { Byte[] syntax = this.syntax.constants; syntax[9] = SYNTAX_TYPE_WHITESPACE; // tab syntax[10] = SYNTAX_TYPE_WHITESPACE; // linefeed syntax[12] = SYNTAX_TYPE_WHITESPACE; // form feed syntax[13] = SYNTAX_TYPE_WHITESPACE; // return syntax[' '] = SYNTAX_TYPE_WHITESPACE; syntax['"'] = SYNTAX_TYPE_TERMINATING_MACRO; syntax['\''] = SYNTAX_TYPE_TERMINATING_MACRO; syntax['('] = SYNTAX_TYPE_TERMINATING_MACRO; syntax[')'] = SYNTAX_TYPE_TERMINATING_MACRO; syntax[','] = SYNTAX_TYPE_TERMINATING_MACRO; syntax[';'] = SYNTAX_TYPE_TERMINATING_MACRO; syntax['`'] = SYNTAX_TYPE_TERMINATING_MACRO; syntax['#'] = SYNTAX_TYPE_NON_TERMINATING_MACRO; syntax['\\'] = SYNTAX_TYPE_SINGLE_ESCAPE; syntax['|'] = SYNTAX_TYPE_MULTIPLE_ESCAPE; LispObject[] readerMacroFunctions = this.readerMacroFunctions.constants; readerMacroFunctions[';'] = LispReader.READ_COMMENT; readerMacroFunctions['"'] = FaslReader.FASL_READ_STRING; readerMacroFunctions['('] = FaslReader.FASL_READ_LIST; readerMacroFunctions[')'] = LispReader.READ_RIGHT_PAREN; readerMacroFunctions['\''] = FaslReader.FASL_READ_QUOTE; readerMacroFunctions['#'] = FaslReader.FASL_READ_DISPATCH_CHAR; // BACKQUOTE-MACRO and COMMA-MACRO are defined in backquote.lisp. readerMacroFunctions['`'] = Symbol.BACKQUOTE_MACRO; readerMacroFunctions[','] = Symbol.COMMA_MACRO; DispatchTable dt = new DispatchTable(); LispObject[] dtfunctions = dt.functions.constants; dtfunctions['('] = FaslReader.FASL_SHARP_LEFT_PAREN; dtfunctions['*'] = FaslReader.FASL_SHARP_STAR; dtfunctions['.'] = FaslReader.FASL_SHARP_DOT; dtfunctions[':'] = FaslReader.FASL_SHARP_COLON; dtfunctions['A'] = FaslReader.FASL_SHARP_A; dtfunctions['B'] = FaslReader.FASL_SHARP_B; dtfunctions['C'] = FaslReader.FASL_SHARP_C; dtfunctions['O'] = FaslReader.FASL_SHARP_O; dtfunctions['P'] = FaslReader.FASL_SHARP_P; dtfunctions['R'] = FaslReader.FASL_SHARP_R; dtfunctions['S'] = FaslReader.FASL_SHARP_S; dtfunctions['X'] = FaslReader.FASL_SHARP_X; dtfunctions['\''] = FaslReader.FASL_SHARP_QUOTE; dtfunctions['\\'] = FaslReader.FASL_SHARP_BACKSLASH; dtfunctions['|'] = LispReader.SHARP_VERTICAL_BAR; dtfunctions[')'] = LispReader.SHARP_ILLEGAL; dtfunctions['<'] = LispReader.SHARP_ILLEGAL; dtfunctions[' '] = LispReader.SHARP_ILLEGAL; dtfunctions[8] = LispReader.SHARP_ILLEGAL; // backspace dtfunctions[9] = LispReader.SHARP_ILLEGAL; // tab dtfunctions[10] = LispReader.SHARP_ILLEGAL; // newline, linefeed dtfunctions[12] = LispReader.SHARP_ILLEGAL; // page dtfunctions[13] = LispReader.SHARP_ILLEGAL; // return dtfunctions['?'] = FaslReader.FASL_SHARP_QUESTION_MARK; dispatchTables.constants['#'] = dt; readtableCase = Keyword.PRESERVE; // after all, all symbols will have been uppercased by the reader, // if applicable, when reading the source file; so, any lower-case // symbols are really meant to be lower case, even if printed without // pipe characters, which may happen if the READTABLE-CASE of the // current readtable is :PRESERVE when printing the symbols } private static final FaslReadtable instance = new FaslReadtable(); public static final FaslReadtable getInstance() { return instance; } } abcl-src-1.9.0/src/org/armedbear/lisp/FileError.java0100644 0000000 0000000 00000007647 14202767264 020771 0ustar000000000 0000000 /* * FileError.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class FileError extends LispError { // initArgs is either a normal initArgs list or a pathname. public FileError(LispObject initArgs) { super(StandardClass.FILE_ERROR); if (initArgs instanceof Cons) initialize(initArgs); else setPathname(initArgs); } @Override protected void initialize(LispObject initArgs) { super.initialize(initArgs); LispObject pathname = NIL; while (initArgs != NIL) { LispObject first = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.PATHNAME) { pathname = initArgs.car(); break; } initArgs = initArgs.cdr(); } setPathname(pathname); } public FileError(String message) { super(StandardClass.FILE_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); setPathname(NIL); } public FileError(String message, LispObject pathname) { super(StandardClass.FILE_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); setPathname(pathname); } public LispObject getPathname() { return getInstanceSlotValue(Symbol.PATHNAME); } private void setPathname(LispObject pathname) { setInstanceSlotValue(Symbol.PATHNAME, pathname); } @Override public LispObject typeOf() { return Symbol.FILE_ERROR; } @Override public LispObject classOf() { return StandardClass.FILE_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.FILE_ERROR) return T; if (type == StandardClass.FILE_ERROR) return T; return super.typep(type); } // ### file-error-pathname private static final Primitive FILE_ERROR_PATHNAME = new Primitive("file-error-pathname", "condition") { @Override public LispObject execute(LispObject arg) { if (arg.typep(Symbol.FILE_ERROR) == NIL) { return type_error(arg, Symbol.FILE_ERROR); } final StandardObject obj = (StandardObject) arg; return obj.getInstanceSlotValue(Symbol.PATHNAME); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/FileStream.java0100644 0000000 0000000 00000026172 14223403213 021105 0ustar000000000 0000000 /* * FileStream.java * * Copyright (C) 2004-2006 Peter Graves * Copyright (C) 2008 Hideo at Yokohama * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import org.armedbear.lisp.util.RandomAccessCharacterFile; public final class FileStream extends Stream { private final RandomAccessCharacterFile racf; private final Pathname pathname; private final int bytesPerUnit; public FileStream(Pathname pathname, LispObject elementType, LispObject direction, LispObject ifExists, LispObject format) throws IOException { /* externalFormat is a LispObject of which the first char is a * name of a character encoding (such as :UTF-8 or :ISO-8859-1), used * by ABCL as a string designator, unless the name is :CODE-PAGE. * A real string is (thus) also allowed. * * Then, a property list follows with 3 possible keys: * :ID (values: code page numbers supported by MS-DOS/IBM-DOS/MS-Windows * :EOL-STYLE (values: :CR / :LF / :CRLF [none means native]) * :LITTLE-ENDIAN (values: NIL / T) * * These definitions have been taken from FLEXI-STREAMS: * http://www.weitz.de/flexi-streams/#make-external-format */ super(Symbol.FILE_STREAM); final File file = pathname.getFile(); String mode = null; if (direction == Keyword.INPUT) { mode = "r"; isInputStream = true; } else if (direction == Keyword.OUTPUT) { mode = "rw"; isOutputStream = true; } else if (direction == Keyword.IO) { mode = "rw"; isInputStream = true; isOutputStream = true; } Debug.assertTrue(mode != null); RandomAccessFile raf = new RandomAccessFile(file, mode); // ifExists is ignored unless we have an output stream. if (isOutputStream) { final long length = file.isFile() ? file.length() : 0; if (length > 0) { if (ifExists == Keyword.OVERWRITE) raf.seek(0); else if (ifExists == Keyword.APPEND) raf.seek(raf.length()); else raf.setLength(0); } } setExternalFormat(format); // don't touch raf directly after passing it to racf. // the state will become inconsistent if you do that. racf = new RandomAccessCharacterFile(raf, encoding); this.pathname = pathname; this.elementType = elementType; if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) { isCharacterStream = true; bytesPerUnit = 1; if (isInputStream) { initAsCharacterInputStream(racf.getReader()); } if (isOutputStream) { initAsCharacterOutputStream(racf.getWriter()); } } else { isBinaryStream = true; int width = Fixnum.getValue(elementType.cadr()); bytesPerUnit = width / 8; if (isInputStream) { initAsBinaryInputStream(racf.getInputStream()); } if (isOutputStream) { initAsBinaryOutputStream(racf.getOutputStream()); } } } @Override public LispObject typeOf() { return Symbol.FILE_STREAM; } @Override public LispObject classOf() { return BuiltInClass.FILE_STREAM; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.FILE_STREAM) return T; if (typeSpecifier == BuiltInClass.FILE_STREAM) return T; return super.typep(typeSpecifier); } @Override public void setExternalFormat(LispObject format) { super.setExternalFormat(format); if (racf != null) // setExternalFormat also called before 'racf' is set up racf.setEncoding(encoding); } public Pathname getPathname() { return pathname; } @Override public LispObject fileLength() { final long length; if (isOpen()) { try { length = racf.length(); } catch (IOException e) { error(new StreamError(this, e)); // Not reached. return NIL; } } else { String namestring = pathname.getNamestring(); if (namestring == null) return error(new SimpleError("Pathname has no namestring: " + pathname.princToString())); File file = new File(namestring); length = file.length(); // in 8-bit bytes } if (isCharacterStream) return number(length); // "For a binary file, the length is measured in units of the // element type of the stream." return number(length / bytesPerUnit); } @Override protected boolean _charReady() { return true; } @Override public void _clearInput() { try { if (isInputStream) { racf.position(racf.length()); } else { streamNotInputStream(); } } catch (IOException e) { error(new StreamError(this, e)); } } @Override protected long _getFilePosition() { try { long pos = racf.position(); return pos / bytesPerUnit; } catch (IOException e) { error(new StreamError(this, e)); // Not reached. return -1; } } @Override protected boolean _setFilePosition(LispObject arg) { try { long pos = 0; if (arg == Keyword.START) pos = 0; else if (arg == Keyword.END) pos = racf.length(); else if (arg instanceof Fixnum) pos = ((Fixnum) arg).value * bytesPerUnit; else if (arg instanceof Bignum) pos = ((Bignum) arg).longValue() * bytesPerUnit; else type_error(arg, Symbol.INTEGER); racf.position(pos); } catch (IOException e) { error(new StreamError(this, e)); } return true; } @Override public void _close() { try { racf.close(); setOpen(false); } catch (IOException e) { error(new StreamError(this, e)); } } @Override public String printObject() { return unreadableString("FILE-STREAM"); } // ### make-file-stream pathname element-type direction if-exists external-format => stream private static final Primitive MAKE_FILE_STREAM = new Primitive("make-file-stream", PACKAGE_SYS, true, "pathname element-type direction if-exists external-format") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { final Pathname pathname; if (first instanceof Pathname) { pathname = (Pathname) first; } else { return type_error(first, Symbol.PATHNAME); } LispObject elementType = second; LispObject direction = third; LispObject ifExists = fourth; LispObject externalFormat = fifth; if (direction != Keyword.INPUT && direction != Keyword.OUTPUT && direction != Keyword.IO) error(new LispError("Direction must be :INPUT, :OUTPUT, or :IO.")); if (pathname.isJar()) { if (direction != Keyword.INPUT) { error(new FileError("Only direction :INPUT is supported for jar files.", pathname)); } try { return new JarStream(pathname, elementType, direction, ifExists, externalFormat); } catch (IOException e) { return error(new StreamError(null, e)); } } else if (pathname instanceof URLPathname && !(URLPathname.isFile(pathname))) { if (direction != Keyword.INPUT) { error(new FileError("Only direction :INPUT is supported for URLs.", pathname)); } try { return new URLStream(pathname, elementType, direction, ifExists, externalFormat); } catch (IOException e) { return error(new StreamError(null, e)); } } else { try { return new FileStream(pathname, elementType, direction, ifExists, externalFormat); } catch (FileNotFoundException e) { return NIL; } catch (IOException e) { return error(new StreamError(null, e)); } } } }; } abcl-src-1.9.0/src/org/armedbear/lisp/FillPointerOutputStream.java0100644 0000000 0000000 00000006647 14202767264 023723 0ustar000000000 0000000 /* * FillPointerOutputStream.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class FillPointerOutputStream extends Stream { ComplexString string; FillPointerOutputStream(ComplexString string) { super(Symbol.SYSTEM_STREAM); elementType = Symbol.CHARACTER; isOutputStream = true; isInputStream = false; isCharacterStream = true; isBinaryStream = false; this.string = string; setWriter(new Writer()); } // ### make-fill-pointer-output-stream string => string-stream private static final Primitive MAKE_FILL_POINTER_OUTPUT_STREAM = new Primitive("make-fill-pointer-output-stream", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject arg) { if (arg instanceof ComplexString) { ComplexString string = (ComplexString) arg; if (string.getFillPointer() >= 0) return new FillPointerOutputStream(string); } return type_error(arg, list(Symbol.AND, Symbol.STRING, list(Symbol.SATISFIES, Symbol.ARRAY_HAS_FILL_POINTER_P))); } }; class Writer extends java.io.Writer { @Override public void write(char cbuf[], int off, int len) { int fp = string.getFillPointer(); if (fp >= 0) { final int limit = Math.min(cbuf.length, off + len); string.ensureCapacity(fp + limit); for (int i = off; i < limit; i++) { string.setCharAt(fp, cbuf[i]); ++fp; } } string.setFillPointer(fp); } @Override public void flush() { } @Override public void close() { } } } abcl-src-1.9.0/src/org/armedbear/lisp/Fixnum.java0100644 0000000 0000000 00000063020 14202767264 020331 0ustar000000000 0000000 /* * Fixnum.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; public final class Fixnum extends LispInteger { public static final int MAX_POS_CACHE = 256;//just like before - however never set this to less than 256 public static final Fixnum[] constants = new Fixnum[MAX_POS_CACHE]; static { for (int i = 0; i < MAX_POS_CACHE; i++) constants[i] = new Fixnum(i); } public static final Fixnum ZERO = constants[0]; public static final Fixnum ONE = constants[1]; public static final Fixnum TWO = constants[2]; public static final Fixnum THREE = constants[3]; public static final Fixnum MINUS_ONE = Fixnum.getInstance(-1); public static Fixnum getInstance(int n) { return (n >= 0 && n < MAX_POS_CACHE) ? constants[n] : new Fixnum(n); } public final int value; // set to private to hunt down sneaky creators private Fixnum(int value) { this.value = value; } @Override public Object javaInstance() { return Integer.valueOf(value); } @Override public Object javaInstance(Class c) { if (c == Byte.class || c == byte.class) return Byte.valueOf((byte)value); if (c == Short.class || c == short.class) return Short.valueOf((short)value); if (c == Long.class || c == long.class) return Long.valueOf((long)value); return javaInstance(); } @Override public LispObject typeOf() { if (value == 0 || value == 1) return Symbol.BIT; if (value > 1) return list(Symbol.INTEGER, ZERO, Fixnum.getInstance(Integer.MAX_VALUE)); return Symbol.FIXNUM; } @Override public LispObject classOf() { return BuiltInClass.FIXNUM; } @Override public LispObject getDescription() { StringBuffer sb = new StringBuffer("The fixnum "); sb.append(value); return new SimpleString(sb); } @Override public LispObject typep(LispObject type) { if (type instanceof Symbol) { if (type == Symbol.FIXNUM) return T; if (type == Symbol.INTEGER) return T; if (type == Symbol.RATIONAL) return T; if (type == Symbol.REAL) return T; if (type == Symbol.NUMBER) return T; if (type == Symbol.SIGNED_BYTE) return T; if (type == Symbol.UNSIGNED_BYTE) return value >= 0 ? T : NIL; if (type == Symbol.BIT) return (value == 0 || value == 1) ? T : NIL; } else if (type instanceof LispClass) { if (type == BuiltInClass.FIXNUM) return T; if (type == BuiltInClass.INTEGER) return T; if (type == BuiltInClass.RATIONAL) return T; if (type == BuiltInClass.REAL) return T; if (type == BuiltInClass.NUMBER) return T; } else if (type instanceof Cons) { if (type.equal(UNSIGNED_BYTE_8)) return (value >= 0 && value <= 255) ? T : NIL; if (type.equal(UNSIGNED_BYTE_16)) return (value >= 0 && value <= 65535) ? T : NIL; if (type.equal(UNSIGNED_BYTE_32)) return value >= 0 ? T : NIL; } return super.typep(type); } @Override public boolean numberp() { return true; } @Override public boolean integerp() { return true; } @Override public boolean rationalp() { return true; } @Override public boolean realp() { return true; } @Override public boolean eql(int n) { return value == n; } @Override public boolean eql(LispObject obj) { if (this == obj) return true; if (obj instanceof Fixnum) { if (value == ((Fixnum)obj).value) return true; } return false; } @Override public boolean equal(int n) { return value == n; } @Override public boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof Fixnum) { if (value == ((Fixnum)obj).value) return true; } return false; } @Override public boolean equalp(int n) { return value == n; } @Override public boolean equalp(LispObject obj) { if (obj != null && obj.numberp()) return isEqualTo(obj); return false; } @Override public LispObject ABS() { if (value >= 0) return this; return LispInteger.getInstance(-(long)value); } @Override public LispObject NUMERATOR() { return this; } @Override public LispObject DENOMINATOR() { return ONE; } @Override public boolean evenp() { return (value & 0x01) == 0; } @Override public boolean oddp() { return (value & 0x01) != 0; } @Override public boolean plusp() { return value > 0; } @Override public boolean minusp() { return value < 0; } @Override public boolean zerop() { return value == 0; } public static int getValue(LispObject obj) { if (obj instanceof Fixnum) return ((Fixnum)obj).value; type_error(obj, Symbol.FIXNUM); // Not reached. return 0; } @Override public float floatValue() { return (float)value; } @Override public double doubleValue() { return (double)value; } public static int getInt(LispObject obj) { if (obj instanceof Fixnum) return ((Fixnum)obj).value; type_error(obj, Symbol.FIXNUM); // Not reached. return 0; } public static BigInteger getBigInteger(LispObject obj) { if (obj instanceof Fixnum) return BigInteger.valueOf(((Fixnum)obj).value); type_error(obj, Symbol.FIXNUM); // Not reached. return null; } @Override public int intValue() { return value; } @Override public long longValue() { return (long) value; } public final BigInteger getBigInteger() { return BigInteger.valueOf(value); } @Override public final LispObject incr() { return LispInteger.getInstance(1 + (long)value); } @Override public final LispObject decr() { return LispInteger.getInstance(-1 + (long)value); } @Override public LispObject negate() { return LispInteger.getInstance((-(long)value)); } @Override public LispObject add(int n) { return LispInteger.getInstance((long) value + n); } @Override public LispObject add(LispObject obj) { if (obj instanceof Fixnum) { long result = (long) value + ((Fixnum)obj).value; return LispInteger.getInstance(result); } if (obj instanceof Bignum) return number(getBigInteger().add(((Bignum)obj).value)); if (obj instanceof Ratio) { BigInteger numerator = ((Ratio)obj).numerator(); BigInteger denominator = ((Ratio)obj).denominator(); return number(getBigInteger().multiply(denominator).add(numerator), denominator); } if (obj instanceof SingleFloat) return new SingleFloat(value + ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value + ((DoubleFloat)obj).value); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart()); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject subtract(int n) { return LispInteger.getInstance((long)value - n); } @Override public LispObject subtract(LispObject obj) { if (obj instanceof Fixnum) return number((long) value - ((Fixnum)obj).value); if (obj instanceof Bignum) return number(getBigInteger().subtract(Bignum.getValue(obj))); if (obj instanceof Ratio) { BigInteger numerator = ((Ratio)obj).numerator(); BigInteger denominator = ((Ratio)obj).denominator(); return number( getBigInteger().multiply(denominator).subtract(numerator), denominator); } if (obj instanceof SingleFloat) return new SingleFloat(value - ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value - ((DoubleFloat)obj).value); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(subtract(c.getRealPart()), ZERO.subtract(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject multiplyBy(int n) { long result = (long) value * n; return LispInteger.getInstance(result); } @Override public LispObject multiplyBy(LispObject obj) { if (obj instanceof Fixnum) { long result = (long) value * ((Fixnum)obj).value; return LispInteger.getInstance(result); } if (obj instanceof Bignum) return number(getBigInteger().multiply(((Bignum)obj).value)); if (obj instanceof Ratio) { BigInteger numerator = ((Ratio)obj).numerator(); BigInteger denominator = ((Ratio)obj).denominator(); return number( getBigInteger().multiply(numerator), denominator); } if (obj instanceof SingleFloat) return new SingleFloat(value * ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value * ((DoubleFloat)obj).value); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(multiplyBy(c.getRealPart()), multiplyBy(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject divideBy(LispObject obj) { try { if (obj instanceof Fixnum) { final int divisor = ((Fixnum)obj).value; // (/ MOST-NEGATIVE-FIXNUM -1) is a bignum. if (value > Integer.MIN_VALUE) if (value % divisor == 0) return Fixnum.getInstance(value / divisor); return number(BigInteger.valueOf(value), BigInteger.valueOf(divisor)); } if (obj instanceof Bignum) return number(getBigInteger(), ((Bignum)obj).value); if (obj instanceof Ratio) { BigInteger numerator = ((Ratio)obj).numerator(); BigInteger denominator = ((Ratio)obj).denominator(); return number(getBigInteger().multiply(denominator), numerator); } if (obj instanceof SingleFloat) return new SingleFloat(value / ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value / ((DoubleFloat)obj).value); if (obj instanceof Complex) { Complex c = (Complex) obj; LispObject realPart = c.getRealPart(); LispObject imagPart = c.getImaginaryPart(); LispObject denominator = realPart.multiplyBy(realPart).add(imagPart.multiplyBy(imagPart)); return Complex.getInstance(multiplyBy(realPart).divideBy(denominator), Fixnum.ZERO.subtract(multiplyBy(imagPart).divideBy(denominator))); } return type_error(obj, Symbol.NUMBER); } catch (ArithmeticException e) { if (obj.zerop()) { LispObject operands = new Cons(this, new Cons(obj)); LispObject args = new Cons(Keyword.OPERATION, new Cons(Symbol.SLASH, new Cons(Keyword.OPERANDS, new Cons(operands)))); return error(new DivisionByZero(args)); } return error(new ArithmeticError(e.getMessage())); } } @Override public boolean isEqualTo(int n) { return value == n; } @Override public boolean isEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value == ((Fixnum)obj).value; if (obj instanceof SingleFloat) return isEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return value == ((DoubleFloat)obj).value; if (obj instanceof Complex) return obj.isEqualTo(this); if (obj.numberp()) return false; type_error(obj, Symbol.NUMBER); // Not reached. return false; } @Override public boolean isNotEqualTo(int n) { return value != n; } @Override public boolean isNotEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value != ((Fixnum)obj).value; // obj is not a fixnum. if (obj instanceof SingleFloat) return isNotEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return value != ((DoubleFloat)obj).value; if (obj instanceof Complex) return obj.isNotEqualTo(this); if (obj.numberp()) return true; type_error(obj, Symbol.NUMBER); // Not reached. return false; } @Override public boolean isLessThan(int n) { return value < n; } @Override public boolean isLessThan(LispObject obj) { if (obj instanceof Fixnum) return value < ((Fixnum)obj).value; if (obj instanceof Bignum) return getBigInteger().compareTo(Bignum.getValue(obj)) < 0; if (obj instanceof Ratio) { BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator()); return n.compareTo(((Ratio)obj).numerator()) < 0; } if (obj instanceof SingleFloat) return isLessThan(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isLessThan(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThan(int n) { return value > n; } @Override public boolean isGreaterThan(LispObject obj) { if (obj instanceof Fixnum) return value > ((Fixnum)obj).value; if (obj instanceof Bignum) return getBigInteger().compareTo(Bignum.getValue(obj)) > 0; if (obj instanceof Ratio) { BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator()); return n.compareTo(((Ratio)obj).numerator()) > 0; } if (obj instanceof SingleFloat) return isGreaterThan(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isGreaterThan(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isLessThanOrEqualTo(int n) { return value <= n; } @Override public boolean isLessThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value <= ((Fixnum)obj).value; if (obj instanceof Bignum) return getBigInteger().compareTo(Bignum.getValue(obj)) <= 0; if (obj instanceof Ratio) { BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator()); return n.compareTo(((Ratio)obj).numerator()) <= 0; } if (obj instanceof SingleFloat) return isLessThanOrEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isLessThanOrEqualTo(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThanOrEqualTo(int n) { return value >= n; } @Override public boolean isGreaterThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) return value >= ((Fixnum)obj).value; if (obj instanceof Bignum) return getBigInteger().compareTo(Bignum.getValue(obj)) >= 0; if (obj instanceof Ratio) { BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator()); return n.compareTo(((Ratio)obj).numerator()) >= 0; } if (obj instanceof SingleFloat) return isGreaterThanOrEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isGreaterThanOrEqualTo(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public LispObject truncate(LispObject obj) { final LispThread thread = LispThread.currentThread(); final LispObject value1, value2; try { if (obj instanceof Fixnum) { int divisor = ((Fixnum)obj).value; int quotient = value / divisor; int remainder = value % divisor; value1 = Fixnum.getInstance(quotient); value2 = remainder == 0 ? Fixnum.ZERO : Fixnum.getInstance(remainder); } else if (obj instanceof Bignum) { BigInteger val = getBigInteger(); BigInteger divisor = ((Bignum)obj).value; BigInteger[] results = val.divideAndRemainder(divisor); BigInteger quotient = results[0]; BigInteger remainder = results[1]; value1 = number(quotient); value2 = (remainder.signum() == 0) ? Fixnum.ZERO : number(remainder); } else if (obj instanceof Ratio) { Ratio divisor = (Ratio) obj; LispObject quotient = multiplyBy(divisor.DENOMINATOR()).truncate(divisor.NUMERATOR()); LispObject remainder = subtract(quotient.multiplyBy(divisor)); value1 = quotient; value2 = remainder; } else if (obj instanceof SingleFloat) { // "When rationals and floats are combined by a numerical function, // the rational is first converted to a float of the same format." // 12.1.4.1 return new SingleFloat(value).truncate(obj); } else if (obj instanceof DoubleFloat) { // "When rationals and floats are combined by a numerical function, // the rational is first converted to a float of the same format." // 12.1.4.1 return new DoubleFloat(value).truncate(obj); } else return type_error(obj, Symbol.REAL); } catch (ArithmeticException e) { if (obj.zerop()) { LispObject operands = new Cons(this, new Cons(obj)); LispObject args = new Cons(Keyword.OPERATION, new Cons(Symbol.TRUNCATE, new Cons(Keyword.OPERANDS, new Cons(operands)))); return error(new DivisionByZero(args)); } else return error(new ArithmeticError(e.getMessage())); } return thread.setValues(value1, value2); } @Override public LispObject MOD(LispObject divisor) { if (divisor instanceof Fixnum) return MOD(((Fixnum)divisor).value); return super.MOD(divisor); } @Override public LispObject MOD(int divisor) { final int r; try { r = value % divisor; } catch (ArithmeticException e) { return error(new ArithmeticError("Division by zero.")); } if (r == 0) return Fixnum.ZERO; if (divisor < 0) { if (value > 0) return Fixnum.getInstance(r + divisor); } else { if (value < 0) return Fixnum.getInstance(r + divisor); } return Fixnum.getInstance(r); } @Override public LispObject ash(int shift) { if (value == 0) return this; if (shift == 0) return this; long n = value; if (shift <= -32) { // Right shift. return n >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; } if (shift < 0) return Fixnum.getInstance((int)(n >> -shift)); if (shift <= 32) { n = n << shift; return LispInteger.getInstance(n); } // BigInteger.shiftLeft() succumbs to a stack overflow if shift // is Integer.MIN_VALUE, so... if (shift == Integer.MIN_VALUE) return n >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; return number(BigInteger.valueOf(value).shiftLeft(shift)); } @Override public LispObject ash(LispObject obj) { if (obj instanceof Fixnum) return ash(((Fixnum)obj).value); if (obj instanceof Bignum) { if (value == 0) return this; BigInteger n = BigInteger.valueOf(value); BigInteger shift = ((Bignum)obj).value; if (shift.signum() > 0) return error(new LispError("Can't represent result of left shift.")); if (shift.signum() < 0) return n.signum() >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; Debug.bug(); // Shouldn't happen. } return type_error(obj, Symbol.INTEGER); } @Override public LispObject LOGNOT() { return Fixnum.getInstance(~value); } @Override public LispObject LOGAND(int n) { return Fixnum.getInstance(value & n); } @Override public LispObject LOGAND(LispObject obj) { if (obj instanceof Fixnum) return Fixnum.getInstance(value & ((Fixnum)obj).value); if (obj instanceof Bignum) { if (value >= 0) { int n2 = (((Bignum)obj).value).intValue(); return Fixnum.getInstance(value & n2); } else { BigInteger n1 = getBigInteger(); BigInteger n2 = ((Bignum)obj).value; return number(n1.and(n2)); } } return type_error(obj, Symbol.INTEGER); } @Override public LispObject LOGIOR(int n) { return Fixnum.getInstance(value | n); } @Override public LispObject LOGIOR(LispObject obj) { if (obj instanceof Fixnum) return Fixnum.getInstance(value | ((Fixnum)obj).value); if (obj instanceof Bignum) { BigInteger n1 = getBigInteger(); BigInteger n2 = ((Bignum)obj).value; return number(n1.or(n2)); } return type_error(obj, Symbol.INTEGER); } @Override public LispObject LOGXOR(int n) { return Fixnum.getInstance(value ^ n); } @Override public LispObject LOGXOR(LispObject obj) { if (obj instanceof Fixnum) return Fixnum.getInstance(value ^ ((Fixnum)obj).value); if (obj instanceof Bignum) { BigInteger n1 = getBigInteger(); BigInteger n2 = ((Bignum)obj).value; return number(n1.xor(n2)); } return type_error(obj, Symbol.INTEGER); } @Override public LispObject LDB(int size, int position) { long n = (long) value >> position; long mask = (1L << size) - 1; return number(n & mask); } final static BigInteger BIGINTEGER_TWO = new BigInteger ("2"); /** Computes fixnum^bignum, returning a fixnum or a bignum. */ public LispObject pow(LispObject obj) { BigInteger y = Bignum.getValue(obj); if (y.compareTo (BigInteger.ZERO) < 0) return (Fixnum.getInstance(1)).divideBy(this.pow(Bignum.getInstance(y.negate()))); if (y.compareTo(BigInteger.ZERO) == 0) // No need to test base here; CLHS says 0^0 == 1. return Fixnum.getInstance(1); int x = this.value; if (x == 0) return Fixnum.getInstance(0); if (x == 1) return Fixnum.getInstance(1); BigInteger xy = BigInteger.ONE; BigInteger term = BigInteger.valueOf((long) x); while (! y.equals(BigInteger.ZERO)) { if (y.testBit(0)) xy = xy.multiply(term); term = term.multiply(term); y = y.shiftLeft(1); } return Bignum.getInstance(xy); } @Override public int hashCode() { return value; } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue(thread)); String s = Integer.toString(value, base).toUpperCase(); if (Symbol.PRINT_RADIX.symbolValue(thread) != NIL) { StringBuilder sb = new StringBuilder(); switch (base) { case 2: sb.append("#b"); sb.append(s); break; case 8: sb.append("#o"); sb.append(s); break; case 10: sb.append(s); sb.append('.'); break; case 16: sb.append("#x"); sb.append(s); break; default: sb.append('#'); sb.append(String.valueOf(base)); sb.append('r'); sb.append(s); break; } s = sb.toString(); } return s; } } abcl-src-1.9.0/src/org/armedbear/lisp/FloatFunctions.java0100644 0000000 0000000 00000041670 14202767264 022030 0ustar000000000 0000000 /* * FloatFunctions.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; public final class FloatFunctions { // ### set-floating-point-modes &key traps => private static final Primitive SET_FLOATING_POINT_MODES = new Primitive("set-floating-point-modes", PACKAGE_EXT, true, "&key traps") { @Override public LispObject execute(LispObject[] args) { if (args.length % 2 != 0) program_error("Odd number of keyword arguments."); for (int i = 0; i < args.length; i += 2) { LispObject key = checkSymbol(args[i]); LispObject value = args[i+1]; if (key == Keyword.TRAPS) { boolean trap_overflow = false; boolean trap_underflow = false; while (value != NIL) { LispObject car = value.car(); if (car == Keyword.OVERFLOW) trap_overflow = true; else if (car == Keyword.UNDERFLOW) trap_underflow = true; else error(new LispError("Unsupported floating point trap: " + car.princToString())); value = value.cdr(); } TRAP_OVERFLOW = trap_overflow; TRAP_UNDERFLOW = trap_underflow; } else error(new LispError("Unrecognized keyword: " + key.princToString())); } return LispThread.currentThread().nothing(); } }; // ### get-floating-point-modes => modes private static final Primitive GET_FLOATING_POINT_MODES = new Primitive("get-floating-point-modes", PACKAGE_EXT, true, "") { @Override public LispObject execute() { LispObject traps = NIL; if (TRAP_UNDERFLOW) traps = traps.push(Keyword.UNDERFLOW); if (TRAP_OVERFLOW) traps = traps.push(Keyword.OVERFLOW); return list(Keyword.TRAPS, traps); } }; // ### integer-decode-float float => significand, exponent, integer-sign private static final Primitive INTEGER_DECODE_FLOAT = new Primitive("integer-decode-float", "float") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) { if (arg.equals(SingleFloat.SINGLE_FLOAT_POSITIVE_INFINITY) || arg.equals(SingleFloat.SINGLE_FLOAT_NEGATIVE_INFINITY)) { return error(new LispError("Cannot decode infinity.")); } int bits = Float.floatToRawIntBits(((SingleFloat)arg).value); int s = ((bits >> 31) == 0) ? 1 : -1; int e = (int) ((bits >> 23) & 0xffL); int m; if (e == 0) m = (bits & 0x7fffff) << 1; else m = (bits & 0x7fffff) | 0x800000; LispObject significand = number(m); Fixnum exponent = Fixnum.getInstance(e - 150); Fixnum sign = Fixnum.getInstance(s); return LispThread.currentThread().setValues(significand, exponent, sign); } if (arg instanceof DoubleFloat) { if (arg.equals(DoubleFloat.DOUBLE_FLOAT_POSITIVE_INFINITY) || arg.equals(DoubleFloat.DOUBLE_FLOAT_NEGATIVE_INFINITY)) { return error(new LispError("Cannot decode infinity.")); } long bits = Double.doubleToRawLongBits((double)((DoubleFloat)arg).value); int s = ((bits >> 63) == 0) ? 1 : -1; int e = (int) ((bits >> 52) & 0x7ffL); long m; if (e == 0) m = (bits & 0xfffffffffffffL) << 1; else m = (bits & 0xfffffffffffffL) | 0x10000000000000L; LispObject significand = number(m); Fixnum exponent = Fixnum.getInstance(e - 1075); Fixnum sign = Fixnum.getInstance(s); return LispThread.currentThread().setValues(significand, exponent, sign); } return type_error(arg, Symbol.FLOAT); } }; // ### %float-bits float => integer private static final Primitive _FLOAT_BITS = new Primitive("%float-bits", PACKAGE_SYS, true, "integer") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) { int bits = Float.floatToIntBits(((SingleFloat)arg).value); BigInteger big = BigInteger.valueOf(bits >> 1); return Bignum.getInstance(big.shiftLeft(1).add(((bits & 1) == 1) ? BigInteger.ONE : BigInteger.ZERO)); } if (arg instanceof DoubleFloat) { long bits = Double.doubleToLongBits(((DoubleFloat)arg).value); BigInteger big = BigInteger.valueOf(bits >> 1); return Bignum.getInstance(big.shiftLeft(1).add(((bits & 1) == 1) ? BigInteger.ONE : BigInteger.ZERO)); } return type_error(arg, Symbol.FLOAT); } }; // ### rational private static final Primitive RATIONAL = new Primitive("rational", "number") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) return ((SingleFloat)arg).rational(); if (arg instanceof DoubleFloat) return ((DoubleFloat)arg).rational(); if (arg.rationalp()) return arg; return type_error(arg, Symbol.REAL); } }; // ### float-radix // float-radix float => float-radix private static final Primitive FLOAT_RADIX = new Primitive("float-radix", "float") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat || arg instanceof DoubleFloat) return Fixnum.TWO; return type_error(arg, Symbol.FLOAT); } }; static final Fixnum FIXNUM_24 = Fixnum.getInstance(24); static final Fixnum FIXNUM_53 = Fixnum.getInstance(53); // ### float-digits // float-digits float => float-digits private static final Primitive FLOAT_DIGITS = new Primitive("float-digits", "float") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) return FIXNUM_24; if (arg instanceof DoubleFloat) return FIXNUM_53; return type_error(arg, Symbol.FLOAT); } }; // ### scale-float float integer => scaled-float private static final Primitive SCALE_FLOAT = new Primitive("scale-float", "float integer") { @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof SingleFloat) { float f = ((SingleFloat)first).value; int n = Fixnum.getValue(second); return new SingleFloat(f * (float) Math.pow(2, n)); } if (first instanceof DoubleFloat) { double d = ((DoubleFloat)first).value; int n = Fixnum.getValue(second); return new DoubleFloat(d * Math.pow(2, n)); } return type_error(first, Symbol.FLOAT); } }; // ### coerce-to-single-float private static final Primitive COERCE_TO_SINGLE_FLOAT = new Primitive("coerce-to-single-float", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject arg) { return SingleFloat.coerceToFloat(arg); } }; // ### coerce-to-double-float private static final Primitive COERCE_TO_DOUBLE_FLOAT = new Primitive("coerce-to-double-float", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject arg) { return DoubleFloat.coerceToFloat(arg); } }; // ### float // float number &optional prototype => float private static final Primitive FLOAT = new Primitive("float", "number &optional prototype") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat || arg instanceof DoubleFloat) return arg; return SingleFloat.coerceToFloat(arg); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof SingleFloat) return SingleFloat.coerceToFloat(first); if (second instanceof DoubleFloat) return DoubleFloat.coerceToFloat(first); return type_error(second, Symbol.FLOAT); } }; // ### floatp // floatp object => generalized-boolean private static final Primitive FLOATP = new Primitive("floatp", "object") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) return T; if (arg instanceof DoubleFloat) return T; return NIL; } }; // ### single-float-bits private static final Primitive SINGLE_FLOAT_BITS = new Primitive("single-float-bits", PACKAGE_SYS, true, "float") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) { SingleFloat f = (SingleFloat) arg; return Fixnum.getInstance(Float.floatToIntBits(f.value)); } return type_error(arg, Symbol.FLOAT); } }; // ### double-float-high-bits private static final Primitive DOUBLE_FLOAT_HIGH_BITS = new Primitive("double-float-high-bits", PACKAGE_SYS, true, "float") { @Override public LispObject execute(LispObject arg) { if (arg instanceof DoubleFloat) { DoubleFloat f = (DoubleFloat) arg; return number(Double.doubleToLongBits(f.value) >>> 32); } return type_error(arg, Symbol.DOUBLE_FLOAT); } }; // ### double-float-low-bits private static final Primitive DOUBLE_FLOAT_LOW_BITS = new Primitive("double-float-low-bits", PACKAGE_SYS, true, "float") { @Override public LispObject execute(LispObject arg) { if (arg instanceof DoubleFloat) { DoubleFloat f = (DoubleFloat) arg; return number(Double.doubleToLongBits(f.value) & 0xffffffffL); } return type_error(arg, Symbol.DOUBLE_FLOAT); } }; // ### make-single-float bits => float private static final Primitive MAKE_SINGLE_FLOAT = new Primitive("make-single-float", PACKAGE_SYS, true, "bits") { @Override public LispObject execute(LispObject arg) { if (arg instanceof Fixnum) { int bits = ((Fixnum)arg).value; return new SingleFloat(Float.intBitsToFloat(bits)); } if (arg instanceof Bignum) { long bits = ((Bignum)arg).value.longValue(); return new SingleFloat(Float.intBitsToFloat((int)bits)); } return type_error(arg, Symbol.INTEGER); } }; // ### make-double-float bits => float private static final Primitive MAKE_DOUBLE_FLOAT = new Primitive("make-double-float", PACKAGE_SYS, true, "bits") { @Override public LispObject execute(LispObject arg) { if (arg instanceof Fixnum) { long bits = (long) ((Fixnum)arg).value; return new DoubleFloat(Double.longBitsToDouble(bits)); } if (arg instanceof Bignum) { long bits = ((Bignum)arg).value.longValue(); return new DoubleFloat(Double.longBitsToDouble(bits)); } return type_error(arg, Symbol.INTEGER); } }; // ### float-infinity-p private static final Primitive FLOAT_INFINITY_P = new Primitive("float-infinity-p", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) return Float.isInfinite(((SingleFloat)arg).value) ? T : NIL; if (arg instanceof DoubleFloat) return Double.isInfinite(((DoubleFloat)arg).value) ? T : NIL; return type_error(arg, Symbol.FLOAT); } }; // ### float-nan-p private static final Primitive FLOAT_NAN_P = new Primitive("float-nan-p", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) return Float.isNaN(((SingleFloat)arg).value) ? T : NIL; if (arg instanceof DoubleFloat) return Double.isNaN(((DoubleFloat)arg).value) ? T : NIL; return type_error(arg, Symbol.FLOAT); } }; // ### float-string private static final Primitive FLOAT_STRING = new Primitive("float-string", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject arg) { final String s1; if (arg instanceof SingleFloat) s1 = String.valueOf(((SingleFloat)arg).value); else if (arg instanceof DoubleFloat) s1 = String.valueOf(((DoubleFloat)arg).value); else return type_error(arg, Symbol.FLOAT); int i = s1.indexOf('E'); if (i < 0) return new SimpleString(s1); String s2 = s1.substring(0, i); int exponent = Integer.parseInt(s1.substring(i + 1)); if (exponent == 0) return new SimpleString(s2); int index = s2.indexOf('.'); if (index < 0) return new SimpleString(s2); StringBuffer sb = new StringBuffer(s2); if (index >= 0) sb.deleteCharAt(index); // Now we've got just the digits in the StringBuffer. if (exponent > 0) { int newIndex = index + exponent; if (newIndex < sb.length()) sb.insert(newIndex, '.'); else if (newIndex == sb.length()) sb.append('.'); else { // We need to add some zeros. while (newIndex > sb.length()) sb.append('0'); sb.append('.'); } } else { Debug.assertTrue(exponent < 0); int newIndex = index + exponent; while (newIndex < 0) { sb.insert(0, '0'); ++newIndex; } sb.insert(0, '.'); } return new SimpleString(sb.toString()); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/FloatingPointInexact.java0100644 0000000 0000000 00000004414 14202767264 023156 0ustar000000000 0000000 /* * FloatingPointInexact.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class FloatingPointInexact extends ArithmeticError { public FloatingPointInexact(LispObject initArgs) { super(StandardClass.FLOATING_POINT_INEXACT); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.FLOATING_POINT_INEXACT; } @Override public LispObject classOf() { return StandardClass.FLOATING_POINT_INEXACT; } @Override public LispObject typep(LispObject type) { if (type == Symbol.FLOATING_POINT_INEXACT) return T; if (type == StandardClass.FLOATING_POINT_INEXACT) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/FloatingPointInvalidOperation.java0100644 0000000 0000000 00000004532 14202767264 025033 0ustar000000000 0000000 /* * FloatingPointInvalidOperation.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class FloatingPointInvalidOperation extends ArithmeticError { public FloatingPointInvalidOperation(LispObject initArgs) { super(StandardClass.FLOATING_POINT_INVALID_OPERATION); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.FLOATING_POINT_INVALID_OPERATION; } @Override public LispObject classOf() { return StandardClass.FLOATING_POINT_INVALID_OPERATION; } @Override public LispObject typep(LispObject type) { if (type == Symbol.FLOATING_POINT_INVALID_OPERATION) return T; if (type == StandardClass.FLOATING_POINT_INVALID_OPERATION) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/FloatingPointOverflow.java0100644 0000000 0000000 00000004425 14202767264 023370 0ustar000000000 0000000 /* * FloatingPointOverflow.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class FloatingPointOverflow extends ArithmeticError { public FloatingPointOverflow(LispObject initArgs) { super(StandardClass.FLOATING_POINT_OVERFLOW); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.FLOATING_POINT_OVERFLOW; } @Override public LispObject classOf() { return StandardClass.FLOATING_POINT_OVERFLOW; } @Override public LispObject typep(LispObject type) { if (type == Symbol.FLOATING_POINT_OVERFLOW) return T; if (type == StandardClass.FLOATING_POINT_OVERFLOW) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/FloatingPointUnderflow.java0100644 0000000 0000000 00000004435 14202767264 023533 0ustar000000000 0000000 /* * FloatingPointUnderflow.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class FloatingPointUnderflow extends ArithmeticError { public FloatingPointUnderflow(LispObject initArgs) { super(StandardClass.FLOATING_POINT_UNDERFLOW); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.FLOATING_POINT_UNDERFLOW; } @Override public LispObject classOf() { return StandardClass.FLOATING_POINT_UNDERFLOW; } @Override public LispObject typep(LispObject type) { if (type == Symbol.FLOATING_POINT_UNDERFLOW) return T; if (type == StandardClass.FLOATING_POINT_UNDERFLOW) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/FuncallableStandardClass.java0100644 0000000 0000000 00000005270 14202767264 023745 0ustar000000000 0000000 /* * FuncallableStandardClass.java * * Copyright (C) 2003-2005 Peter Graves, 2012 Rudolf Schlatte * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class FuncallableStandardClass extends StandardClass { public FuncallableStandardClass() { super(StandardClass.layoutFuncallableStandardClass); } public FuncallableStandardClass(Symbol symbol, LispObject directSuperclasses) { super(StandardClass.layoutFuncallableStandardClass, symbol, directSuperclasses); } @Override public LispObject typeOf() { return Symbol.FUNCALLABLE_STANDARD_CLASS; } @Override public LispObject classOf() { return StandardClass.FUNCALLABLE_STANDARD_CLASS; } @Override public LispObject typep(LispObject type) { if (type == Symbol.FUNCALLABLE_STANDARD_CLASS) return T; if (type == StandardClass.FUNCALLABLE_STANDARD_CLASS) return T; return super.typep(type); } @Override public String printObject() { StringBuilder sb = new StringBuilder(Symbol.FUNCALLABLE_STANDARD_CLASS.printObject()); if (getName() != null) { sb.append(' '); sb.append(getName().printObject()); } return unreadableString(sb.toString()); } } abcl-src-1.9.0/src/org/armedbear/lisp/FuncallableStandardObject.java0100644 0000000 0000000 00000017667 14202767264 024123 0ustar000000000 0000000 /* * FuncallableStandardObject.java * * Copyright (C) 2003-2006 Peter Graves, 2012 Rudolf Schlatte * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ // TODO: swap-slots is currently handled by StandardObject, so doesn't // exchange the functions. package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class FuncallableStandardObject extends StandardObject { LispObject function; // KLUDGE: this is only needed for generic functions, but doesn't hurt // to have it here. EMFCache cache = new EMFCache(); protected FuncallableStandardObject() { super(); } protected FuncallableStandardObject(Layout layout) { this(layout, layout.getLength()); } protected FuncallableStandardObject(Layout layout, int length) { super(layout, length); } protected FuncallableStandardObject(LispClass cls, int length) { super(cls, length); } protected FuncallableStandardObject(LispClass cls) { super(cls); } @Override public LispObject typep(LispObject type) { if (type == Symbol.COMPILED_FUNCTION) { if (function != null) return function.typep(type); else return NIL; } if (type == Symbol.FUNCALLABLE_STANDARD_OBJECT) return T; if (type == StandardClass.FUNCALLABLE_STANDARD_OBJECT) return T; return super.typep(type); } @Override public LispObject execute() { return function.execute(); } @Override public LispObject execute(LispObject arg) { return function.execute(arg); } @Override public LispObject execute(LispObject first, LispObject second) { return function.execute(first, second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return function.execute(first, second, third); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return function.execute(first, second, third, fourth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { return function.execute(first, second, third, fourth, fifth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { return function.execute(first, second, third, fourth, fifth, sixth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { return function.execute(first, second, third, fourth, fifth, sixth, seventh); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { return function.execute(first, second, third, fourth, fifth, sixth, seventh, eighth); } @Override public LispObject execute(LispObject[] args) { return function.execute(args); } private static final Primitive _ALLOCATE_FUNCALLABLE_INSTANCE = new pf__allocate_funcallable_instance(); @DocString(name="%allocate-funcallable-instance", args="class", returns="instance") private static final class pf__allocate_funcallable_instance extends Primitive { pf__allocate_funcallable_instance() { super("%allocate-funcallable-instance", PACKAGE_SYS, true, "class"); } @Override public LispObject execute(LispObject arg) { if (arg.typep(StandardClass.FUNCALLABLE_STANDARD_CLASS) != NIL) { LispObject l = Symbol.CLASS_LAYOUT.execute(arg); if (! (l instanceof Layout)) { return program_error("Invalid standard class layout for: " + arg.princToString() + "."); } return new FuncallableStandardObject((Layout)l); } return type_error(arg, Symbol.FUNCALLABLE_STANDARD_CLASS); } }; // AMOP p. 230 private static final Primitive SET_FUNCALLABLE_INSTANCE_FUNCTION = new pf_set_funcallable_instance_function(); @DocString(name="set-funcallable-instance-function", args="funcallable-instance function", returns="unspecified") private static final class pf_set_funcallable_instance_function extends Primitive { pf_set_funcallable_instance_function() { super("set-funcallable-instance-function", PACKAGE_MOP, true, "funcallable-instance function"); } @Override public LispObject execute(LispObject first, LispObject second) { checkFuncallableStandardObject(first).function = second; return second; } }; private static final Primitive FUNCALLABLE_INSTANCE_FUNCTION = new pf_funcallable_instance_function(); @DocString(name="funcallable-instance-function", args="funcallable-instance", returns="function") private static final class pf_funcallable_instance_function extends Primitive { pf_funcallable_instance_function() { super("funcallable-instance-function", PACKAGE_MOP, false, "funcallable-instance"); } @Override public LispObject execute(LispObject arg) { return checkFuncallableStandardObject(arg).function; } }; // Profiling. private int callCount; private int hotCount; @Override public final int getCallCount() { return callCount; } @Override public void setCallCount(int n) { callCount = n; } @Override public final void incrementCallCount() { ++callCount; } @Override public final int getHotCount() { return hotCount; } @Override public void setHotCount(int n) { hotCount = n; } @Override public final void incrementHotCount() { ++hotCount; } public static final FuncallableStandardObject checkFuncallableStandardObject(LispObject obj) { if (obj instanceof FuncallableStandardObject) return (FuncallableStandardObject) obj; return (FuncallableStandardObject) // Not reached. type_error(obj, Symbol.FUNCALLABLE_STANDARD_OBJECT); } } abcl-src-1.9.0/src/org/armedbear/lisp/Function.java0100644 0000000 0000000 00000034641 14223403213 020637 0ustar000000000 0000000 /* * Function.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import static org.armedbear.lisp.Lisp.*; public abstract class Function extends Operator implements Serializable { private LispObject propertyList = NIL; private int callCount; private int hotCount; /** * The value of *load-truename* which was current when this function * was loaded, used for fetching the class bytes in case of disassembly. */ public final LispObject loadedFrom; protected Function() { LispObject loadTruename = Symbol.LOAD_TRUENAME.symbolValueNoThrow(); LispObject loadTruenameFasl = Symbol.LOAD_TRUENAME_FASL.symbolValueNoThrow(); loadedFrom = loadTruenameFasl != null ? loadTruenameFasl : (loadTruename != null ? loadTruename : NIL); } public Function(String name) { this(name, (String)null); } public Function(String name, String arglist) { this(); if(arglist != null) setLambdaList(new SimpleString(arglist)); if (name != null) { Symbol symbol = Symbol.addFunction(name.toUpperCase(), this); if (cold) symbol.setBuiltInFunction(true); setLambdaName(symbol); } } public Function(Symbol symbol) { this(symbol, null, null); } public Function(Symbol symbol, String arglist) { this(symbol, arglist, null); } public Function(Symbol symbol, String arglist, String docstring) { this(); symbol.setSymbolFunction(this); if (cold) symbol.setBuiltInFunction(true); setLambdaName(symbol); if(arglist != null) setLambdaList(new SimpleString(arglist)); if (docstring != null) symbol.setDocumentation(Symbol.FUNCTION, new SimpleString(docstring)); } public Function(String name, Package pkg) { this(name, pkg, false); } public Function(String name, Package pkg, boolean exported) { this(name, pkg, exported, null, null); } public Function(String name, Package pkg, boolean exported, String arglist) { this(name, pkg, exported, arglist, null); } public Function(String name, Package pkg, boolean exported, String arglist, String docstring) { this(); if (arglist instanceof String) setLambdaList(new SimpleString(arglist)); if (name != null) { Symbol symbol; if (exported) symbol = pkg.internAndExport(name.toUpperCase()); else symbol = pkg.intern(name.toUpperCase()); symbol.setSymbolFunction(this); if (cold) symbol.setBuiltInFunction(true); setLambdaName(symbol); if (docstring != null) symbol.setDocumentation(Symbol.FUNCTION, new SimpleString(docstring)); } } public Function(LispObject name) { this(); setLambdaName(name); } public Function(LispObject name, LispObject lambdaList) { this(); setLambdaName(name); setLambdaList(lambdaList); } @Override public LispObject typeOf() { return Symbol.FUNCTION; } @Override public LispObject classOf() { return BuiltInClass.FUNCTION; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.FUNCTION) return T; if (typeSpecifier == Symbol.COMPILED_FUNCTION) return T; if (typeSpecifier == BuiltInClass.FUNCTION) return T; return super.typep(typeSpecifier); } @Override public final LispObject getPropertyList() { if (propertyList == null) propertyList = NIL; return propertyList; } @Override public final void setPropertyList(LispObject obj) { if (obj == null) throw new NullPointerException(); propertyList = obj; } public final void setClassBytes(byte[] bytes) { propertyList = putf(propertyList, Symbol.CLASS_BYTES, new JavaObject(bytes)); } public final LispObject getClassBytes() { LispObject o = getf(propertyList, Symbol.CLASS_BYTES, NIL); if(o != NIL) { return o; } else { ClassLoader c = getClass().getClassLoader(); if(c instanceof JavaClassLoader) { final LispThread thread = LispThread.currentThread(); SpecialBindingsMark mark = thread.markSpecialBindings(); try { thread.bindSpecial(Symbol.LOAD_TRUENAME, loadedFrom); return new JavaObject(((JavaClassLoader) c).getFunctionClassBytes(this)); } catch(Throwable t) { //This is because unfortunately getFunctionClassBytes uses //Debug.assertTrue(false) to signal errors if(t instanceof ControlTransfer) { throw (ControlTransfer) t; } else { return NIL; } } finally { thread.resetSpecialBindings(mark); } } else { return NIL; } } } public static final Primitive FUNCTION_CLASS_BYTES = new pf_function_class_bytes(); public static final class pf_function_class_bytes extends Primitive { public pf_function_class_bytes() { super("function-class-bytes", PACKAGE_SYS, false, "function"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Function) { return ((Function) arg).getClassBytes(); } return type_error(arg, Symbol.FUNCTION); } } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 0)); } @Override public LispObject execute(LispObject arg) { return error(new WrongNumberOfArgumentsException(this, 1)); } @Override public LispObject execute(LispObject first, LispObject second) { return error(new WrongNumberOfArgumentsException(this, 2)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return error(new WrongNumberOfArgumentsException(this, 3)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return error(new WrongNumberOfArgumentsException(this, 4)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { return error(new WrongNumberOfArgumentsException(this, 5)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { return error(new WrongNumberOfArgumentsException(this, 6)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { return error(new WrongNumberOfArgumentsException(this, 7)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { return error(new WrongNumberOfArgumentsException(this, 8)); } @Override public LispObject execute(LispObject[] args) { return error(new WrongNumberOfArgumentsException(this)); } @Override public String printObject() { LispObject name = getLambdaName(); if (name != null && name != NIL) { return unreadableString(name.princToString()); } // No name. LispObject lambdaList = getLambdaList(); if (lambdaList != null) { StringBuilder sb = new StringBuilder("FUNCTION "); sb.append("(LAMBDA "); if (lambdaList == NIL) { sb.append("()"); } else { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_LENGTH, Fixnum.THREE); try { sb.append(lambdaList.printObject()); } finally { thread.resetSpecialBindings(mark); } } sb.append(")"); return unreadableString(sb.toString()); } return unreadableString("FUNCTION"); } // Used by the JVM compiler. public final void argCountError() { error(new WrongNumberOfArgumentsException(this)); } // Profiling. @Override public final int getCallCount() { return callCount; } @Override public void setCallCount(int n) { callCount = n; } @Override public final void incrementCallCount() { ++callCount; } @Override public final int getHotCount() { return hotCount; } @Override public void setHotCount(int n) { hotCount = n; } @Override public final void incrementHotCount() { ++hotCount; } //Serialization public static class SerializedNamedFunction implements Serializable { private final Symbol name; public SerializedNamedFunction(Symbol name) { this.name = name; } public Object readResolve() { return name.getSymbolFunctionOrDie(); } } public static class ObjectInputStreamWithClassLoader extends ObjectInputStream { private final ClassLoader classLoader; public ObjectInputStreamWithClassLoader(InputStream in, ClassLoader classLoader) throws IOException { super(in); this.classLoader = classLoader; } @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { return Class.forName(desc.getName(), false, classLoader); } } public static class SerializedLocalFunction implements Serializable { final LispObject className; final LispObject classBytes; final byte[] serializedFunction; public SerializedLocalFunction(Function function) { this.className = new SimpleString(function.getClass().getName()); this.classBytes = function.getClassBytes(); serializingClosure.set(true); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); new ObjectOutputStream(baos).writeObject(function); serializedFunction = baos.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); } finally { serializingClosure.remove(); } } public Object readResolve() throws InvalidObjectException { MemoryClassLoader loader = new MemoryClassLoader(); MemoryClassLoader.PUT_MEMORY_FUNCTION.execute(JavaObject.getInstance(loader), className, classBytes); try { ByteArrayInputStream in = new ByteArrayInputStream(serializedFunction); return new ObjectInputStreamWithClassLoader(in, loader).readObject(); } catch (Exception e) { InvalidObjectException ex = new InvalidObjectException("Could not read the serialized function back"); ex.initCause(e); throw ex; } } } private static final ThreadLocal serializingClosure = new ThreadLocal(); public Object writeReplace() throws ObjectStreamException { if(shouldSerializeByName()) { return new SerializedNamedFunction((Symbol) getLambdaName()); } else if(getClassBytes() == NIL || serializingClosure.get() != null) { return this; } else { return new SerializedLocalFunction(this); } } protected boolean shouldSerializeByName() { LispObject lambdaName = getLambdaName(); return lambdaName instanceof Symbol && lambdaName.getSymbolFunction() == this; } } abcl-src-1.9.0/src/org/armedbear/lisp/FunctionBinding.java0100644 0000000 0000000 00000003702 14202767264 022144 0ustar000000000 0000000 /* * FunctionBinding.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.Serializable; // Package accessibility. final class FunctionBinding implements Serializable { LispObject name; LispObject value; final FunctionBinding next; FunctionBinding() { next = null; } FunctionBinding(LispObject name, LispObject value, FunctionBinding next) { this.name = name; this.value = value; this.next = next; } } abcl-src-1.9.0/src/org/armedbear/lisp/Go.java0100644 0000000 0000000 00000004225 14202767264 017432 0ustar000000000 0000000 /* * Go.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class Go extends ControlTransfer { public final LispObject tagbody; public final LispObject tag; public Go(LispObject tagbody, LispObject tag) { this.tagbody = tagbody; this.tag = tag; } public LispObject getTagBody() { return tagbody; } public LispObject getTag() { return tag; } @Override public LispObject getCondition() { StringBuffer sb = new StringBuffer("No tag named "); sb.append(tag.princToString()); sb.append(" is currently visible"); return new ControlError(sb.toString()); } } abcl-src-1.9.0/src/org/armedbear/lisp/HashTable.java0100644 0000000 0000000 00000033320 14202767264 020716 0ustar000000000 0000000 /* * HashTable.java * * Copyright (C) 2002-2007 Peter Graves * Copyright (C) 2010 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.util.concurrent.locks.ReentrantLock; import static org.armedbear.lisp.Lisp.*; public class HashTable extends LispObject implements org.armedbear.lisp.protocol.Hashtable { protected static final float loadFactor = 0.75f; protected final LispObject rehashSize; protected final LispObject rehashThreshold; // The rounded product of the capacity and the load factor. When the number // of elements exceeds the threshold, the implementation calls rehash(). protected int threshold; // Array containing the actual key-value mappings. @SuppressWarnings("VolatileArrayField") protected volatile HashEntry[] buckets; // The number of key-value pairs. protected volatile int count; final Comparator comparator; final private ReentrantLock lock = new ReentrantLock(); protected HashTable(Comparator c, int size, LispObject rehashSize, LispObject rehashThreshold) { this.rehashSize = rehashSize; this.rehashThreshold = rehashThreshold; buckets = new HashEntry[size]; threshold = (int) (size * loadFactor); comparator = c; } protected static int calculateInitialCapacity(int size) { int capacity = 1; while (capacity < size) { capacity <<= 1; } return capacity; } public static HashTable newEqHashTable(int size, LispObject rehashSize, LispObject rehashThreshold) { return new HashTable(new Comparator(), size, rehashSize, rehashThreshold); } public static HashTable newEqlHashTable(int size, LispObject rehashSize, LispObject rehashThreshold) { return new HashTable(new EqlComparator(), size, rehashSize, rehashThreshold); } public static HashTable newEqualHashTable(int size, LispObject rehashSize, LispObject rehashThreshold) { return new HashTable(new EqualComparator(), size, rehashSize, rehashThreshold); } public static LispObject newEqualpHashTable(int size, LispObject rehashSize, LispObject rehashThreshold) { return new HashTable(new EqualpComparator(), size, rehashSize, rehashThreshold); } public final LispObject getRehashSize() { return rehashSize; } public final LispObject getRehashThreshold() { return rehashThreshold; } public int getSize() { return buckets.length; } public int getCount() { return count; } @Override public LispObject typeOf() { return Symbol.HASH_TABLE; } @Override public LispObject classOf() { return BuiltInClass.HASH_TABLE; } @Override public LispObject typep(LispObject type) { if (type == Symbol.HASH_TABLE) { return T; } if (type == BuiltInClass.HASH_TABLE) { return T; } return super.typep(type); } @Override public boolean equalp(LispObject obj) { if (this == obj) { return true; } if (obj instanceof HashTable) { HashTable ht = (HashTable) obj; if (count != ht.count) { return false; } if (getTest() != ht.getTest()) { return false; } LispObject entries = ENTRIES(); while (entries != NIL) { LispObject entry = entries.car(); LispObject key = entry.car(); LispObject value = entry.cdr(); if (!value.equalp(ht.get(key))) { return false; } entries = entries.cdr(); } return true; } return false; } @Override public LispObject getParts() { // No need to take out a read lock, for the same reason as MAPHASH HashEntry[] b = buckets; LispObject parts = NIL; for (int i = 0; i < b.length; i++) { HashEntry e = b[i]; while (e != null) { parts = parts.push(new Cons("KEY [bucket " + i + "]", e.key)); parts = parts.push(new Cons("VALUE", e.value)); e = e.next; } } return parts.nreverse(); } public void clear() { lock.lock(); try { buckets = new HashEntry[buckets.length]; count = 0; } finally { lock.unlock(); } } // gethash key hash-table &optional default => value, present-p public LispObject gethash(LispObject key) { LispObject value = get(key); final LispObject presentp; if (value == null) { value = presentp = NIL; } else { presentp = T; } return LispThread.currentThread().setValues(value, presentp); } // gethash key hash-table &optional default => value, present-p public LispObject gethash(LispObject key, LispObject defaultValue) { LispObject value = get(key); final LispObject presentp; if (value == null) { value = defaultValue; presentp = NIL; } else { presentp = T; } return LispThread.currentThread().setValues(value, presentp); } public LispObject gethash1(LispObject key) { final LispObject value = get(key); return value != null ? value : NIL; } public LispObject puthash(LispObject key, LispObject newValue) { put(key, newValue); return newValue; } // remhash key hash-table => generalized-boolean public LispObject remhash(LispObject key) { // A value in a Lisp hash table can never be null, so... return remove(key) != null ? T : NIL; } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue(LispThread.currentThread()) != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); return null; // Not reached. } StringBuilder sb = new StringBuilder(getTest().princToString()); sb.append(' '); sb.append(Symbol.HASH_TABLE.princToString()); sb.append(' '); sb.append(count); if (count == 1) { sb.append(" entry"); } else { sb.append(" entries"); } sb.append(", "); sb.append(buckets.length); sb.append(" buckets"); return unreadableString(sb.toString()); } public Symbol getTest() { return comparator.getTest(); } protected HashEntry getEntry(LispObject key) { HashEntry[] b = buckets; int hash = comparator.hash(key); HashEntry e = b[hash & (b.length - 1)]; while (e != null) { if (hash == e.hash && (key == e.key || comparator.keysEqual(key, e.key))) { return e; } e = e.next; } return null; } public LispObject get(LispObject key) { HashEntry e = getEntry(key); LispObject v = (e == null) ? null : e.value; if (e == null || v != null) { return v; } lock.lock(); try { return e.value; } finally { lock.unlock(); } } public void put(LispObject key, LispObject value) { lock.lock(); try { HashEntry e = getEntry(key); if (e != null) { e.value = value; } else { // Not found. We need to add a new entry. if (++count > threshold) { rehash(); } int hash = comparator.hash(key); int index = hash & (buckets.length - 1); buckets[index] = new HashEntry(key, hash, value, buckets[index]); } } finally { lock.unlock(); } } public LispObject remove(LispObject key) { lock.lock(); try { int index = comparator.hash(key) & (buckets.length - 1); HashEntry e = buckets[index]; HashEntry last = null; while (e != null) { if (comparator.keysEqual(key, e.key)) { if (last == null) { buckets[index] = e.next; } else { last.next = e.next; } --count; return e.value; } last = e; e = e.next; } return null; } finally { lock.unlock(); } } protected void rehash() { lock.lock(); try { final int newCapacity = buckets.length * 2; threshold = (int) (newCapacity * loadFactor); int mask = newCapacity - 1; HashEntry[] newBuckets = new HashEntry[newCapacity]; for (int i = buckets.length; i-- > 0;) { HashEntry e = buckets[i]; while (e != null) { final int index = comparator.hash(e.key) & mask; newBuckets[index] = new HashEntry(e.key, e.hash, e.value, newBuckets[index]); e = e.next; } } buckets = newBuckets; } finally { lock.unlock(); } } public LispObject ENTRIES() { return getEntries(); } // Returns a list of (key . value) pairs. public LispObject getEntries() { // No need to take out a read lock, for the same reason as MAPHASH HashEntry[] b = buckets; LispObject list = NIL; for (int i = b.length; i-- > 0;) { HashEntry e = b[i]; while (e != null) { list = new Cons(new Cons(e.key, e.value), list); e = e.next; } } return list; } public LispObject MAPHASH(LispObject function) { // Don't take out a read lock: it can't be upgraded to a write // lock, which would block the scenario where put() is called to // set the value of the current entry HashEntry[] b = buckets; for (int i = b.length; i-- > 0;) { HashEntry e = b[i]; while (e != null) { function.execute(e.key, e.value); e = e.next; } } return NIL; } protected static class Comparator { Symbol getTest() { return Symbol.EQ; } boolean keysEqual(LispObject key1, LispObject key2) { return key1 == key2; } int hash(LispObject key) { return key.sxhash(); } } protected static class EqlComparator extends Comparator { @Override Symbol getTest() { return Symbol.EQL; } @Override boolean keysEqual(LispObject key1, LispObject key2) { return key1.eql(key2); } } protected static class EqualComparator extends Comparator { @Override Symbol getTest() { return Symbol.EQUAL; } @Override boolean keysEqual(LispObject key1, LispObject key2) { return key1.equal(key2); } } protected static class EqualpComparator extends Comparator { @Override Symbol getTest() { return Symbol.EQUALP; } @Override boolean keysEqual(LispObject key1, LispObject key2) { return key1.equalp(key2); } @Override int hash(LispObject key) { return key.psxhash(); } } protected static class HashEntry { LispObject key; int hash; volatile LispObject value; HashEntry next; HashEntry(LispObject key, int hash, LispObject value, HashEntry next) { this.key = key; this.hash = hash; this.value = value; this.next = next; } } // For EQUALP hash tables. @Override public int psxhash() { long result = 2062775257; // Chosen at random. result = mix(result, count); result = mix(result, getTest().sxhash()); return (int) (result & 0x7fffffff); } } abcl-src-1.9.0/src/org/armedbear/lisp/HashTableFunctions.java0100644 0000000 0000000 00000036521 14223403213 022575 0ustar000000000 0000000 /* * HashTableFunctions.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class HashTableFunctions { static final LispObject FUNCTION_EQ = Symbol.EQ.getSymbolFunction(); static final LispObject FUNCTION_EQL = Symbol.EQL.getSymbolFunction(); static final LispObject FUNCTION_EQUAL = Symbol.EQUAL.getSymbolFunction(); static final LispObject FUNCTION_EQUALP = Symbol.EQUALP.getSymbolFunction(); private static final Primitive _MAKE_HASH_TABLE = new pf__make_hash_table(); @DocString(name="%make-hash-table") private static final class pf__make_hash_table extends Primitive { pf__make_hash_table() { super("%make-hash-table", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject test, LispObject size, LispObject rehashSize, LispObject rehashThreshold) { final int n = Fixnum.getValue(size); if (test == FUNCTION_EQL || test == NIL) return HashTable.newEqlHashTable(n, rehashSize, rehashThreshold); if (test == FUNCTION_EQ) return HashTable.newEqHashTable(n, rehashSize, rehashThreshold); if (test == FUNCTION_EQUAL) return HashTable.newEqualHashTable(n, rehashSize, rehashThreshold); if (test == FUNCTION_EQUALP) return HashTable.newEqualpHashTable(n, rehashSize, rehashThreshold); return error(new LispError("Unsupported test for MAKE-HASH-TABLE: " + test.princToString())); } }; private static final Primitive _MAKE_WEAK_HASH_TABLE = new pf__make_weak_hash_table(); @DocString(name="%make-weak-hash-table") private static final class pf__make_weak_hash_table extends Primitive { pf__make_weak_hash_table() { super("%make-weak-hash-table", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject test, LispObject size, LispObject rehashSize, LispObject rehashThreshold, LispObject weakness) { final int n = Fixnum.getValue(size); if (test == FUNCTION_EQL || test == NIL) return WeakHashTable.newEqlHashTable(n, rehashSize, rehashThreshold, weakness); if (test == FUNCTION_EQ) return WeakHashTable.newEqHashTable(n, rehashSize, rehashThreshold, weakness); if (test == FUNCTION_EQUAL) return WeakHashTable.newEqualHashTable(n, rehashSize, rehashThreshold, weakness); if (test == FUNCTION_EQUALP) return WeakHashTable.newEqualpHashTable(n, rehashSize, rehashThreshold, weakness); return error(new LispError("Unsupported test for MAKE-HASH-TABLE: " + test.princToString())); } }; private static final Primitive GETHASH = new pf_gethash(); @DocString(name="gethash", args="key hash-table &optional default", returns="value, present-p", doc="Returns the value associated with KEY in HASH-TABLE.") private static final class pf_gethash extends Primitive { pf_gethash() { super(Symbol.GETHASH, "key hash-table &optional default"); } @Override public LispObject execute(LispObject key, LispObject ht) { if (ht instanceof WeakHashTable) { return ((WeakHashTable)ht).gethash(key); } return checkHashTable(ht).gethash(key); } @Override public LispObject execute(LispObject key, LispObject ht, LispObject defaultValue) { if (ht instanceof WeakHashTable) { return ((WeakHashTable)ht).gethash(key, defaultValue); } return checkHashTable(ht).gethash(key, defaultValue); } }; private static final Primitive GETHASH1 = new pf_gethash1(); @DocString(name="gethash1", args="key hash-table", returns="value") private static final class pf_gethash1 extends Primitive { pf_gethash1() { super(Symbol.GETHASH1, "key hash-table"); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof WeakHashTable) { final WeakHashTable ht = (WeakHashTable) second; synchronized (ht) { final LispObject value = ht.get(first); return value != null ? value : NIL; } } else { final HashTable ht = checkHashTable(second); synchronized (ht) { final LispObject value = ht.get(first); return value != null ? value : NIL; } } } }; private static final Primitive PUTHASH = new pf_puthash(); @DocString(name="puthash", args="key hash-table new-value &optional default", returns="value") private static final class pf_puthash extends Primitive { pf_puthash() { super(Symbol.PUTHASH, "key hash-table new-value &optional default"); } @Override public LispObject execute(LispObject key, LispObject ht, LispObject value) { if (ht instanceof WeakHashTable) { return ((WeakHashTable)ht).puthash(key, value); } return checkHashTable(ht).puthash(key, value); } @Override public LispObject execute(LispObject key, LispObject ht, LispObject ignored, LispObject value) { if (ht instanceof WeakHashTable) { return ((WeakHashTable)ht).puthash(key, value); } return checkHashTable(ht).puthash(key, value); } }; private static final Primitive REMHASH = new pf_remhash(); @DocString(name="remhash", args="key hash-table", returns="generalized-boolean", doc="Removes the value for KEY in HASH-TABLE, if any.") private static final class pf_remhash extends Primitive { pf_remhash() { super(Symbol.REMHASH, "key hash-table"); } @Override public LispObject execute(LispObject key, LispObject ht) { if (ht instanceof WeakHashTable) { return ((WeakHashTable)ht).remhash(key); } return checkHashTable(ht).remhash(key); } }; private static final Primitive CLRHASH = new pf_clrhash(); @DocString(name="clrhash", args="hash-table", returns="hash-table") private static final class pf_clrhash extends Primitive { pf_clrhash() { super(Symbol.CLRHASH, "hash-table"); } @Override public LispObject execute(LispObject ht) { if (ht instanceof WeakHashTable) { ((WeakHashTable)ht).clear(); return ht; } checkHashTable(ht).clear(); return ht; } }; private static final Primitive HASH_TABLE_COUNT = new pf_hash_table_count(); @DocString(name="hash-table-count", args="hash-table", doc="Returns the number of entries in HASH-TABLE.") private static final class pf_hash_table_count extends Primitive { pf_hash_table_count() { super(Symbol.HASH_TABLE_COUNT, "hash-table"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof WeakHashTable) { return Fixnum.getInstance(((WeakHashTable)arg).getCount()); } return Fixnum.getInstance(checkHashTable(arg).getCount()); } }; private static final Primitive SXHASH = new pf_sxhash(); @DocString(name="sxhash", args="object => hash-code") private static final class pf_sxhash extends Primitive { pf_sxhash() { super(Symbol.SXHASH, "object"); } @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(arg.sxhash()); } }; // For EQUALP hash tables. @DocString(name="psxhash", args="object") private static final Primitive PSXHASH = new pf_psxhash(); private static final class pf_psxhash extends Primitive { pf_psxhash() { super("psxhash", PACKAGE_SYS, true, "object"); } @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(arg.psxhash()); } }; private static final Primitive HASH_TABLE_P = new pf_hash_table_p(); @DocString(name="hash-table-p", args="object", doc="Whether OBJECT is an instance of a hash-table.") private static final class pf_hash_table_p extends Primitive { pf_hash_table_p(){ super(Symbol.HASH_TABLE_P,"object"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof WeakHashTable) return T; return arg instanceof HashTable ? T : NIL; } }; private static final Primitive HASH_TABLE_ENTRIES = new pf_hash_table_entries(); @DocString(name="hah-table-entries", args="hash-table", doc="Returns a list of all key/values pairs in HASH-TABLE.") private static final class pf_hash_table_entries extends Primitive { pf_hash_table_entries() { super("hash-table-entries", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject arg) { if (arg instanceof WeakHashTable) { return ((WeakHashTable)arg).ENTRIES(); } return checkHashTable(arg).ENTRIES(); } }; private static final Primitive HASH_TABLE_TEST = new pf_hash_table_test(); @DocString(name="hash-table-test", args="hash-table", doc="Return the test used for the keys of HASH-TABLE.") private static final class pf_hash_table_test extends Primitive { pf_hash_table_test() { super(Symbol.HASH_TABLE_TEST, "hash-table"); } public LispObject execute(LispObject arg) { if (arg instanceof WeakHashTable) { return ((WeakHashTable)arg).getTest(); } return checkHashTable(arg).getTest(); } }; private static final Primitive HASH_TABLE_SIZE = new pf_hash_table_size(); @DocString(name="hash-table-size", args="hash-table", doc="Returns the number of storage buckets in HASH-TABLE.") private static final class pf_hash_table_size extends Primitive { pf_hash_table_size() { super(Symbol.HASH_TABLE_SIZE, "hash-table"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof WeakHashTable) { return Fixnum.getInstance(((WeakHashTable)arg).getSize()); } return Fixnum.getInstance(checkHashTable(arg).getSize()); } }; private static final Primitive HASH_TABLE_REHASH_SIZE = new pf_hash_table_rehash_size(); @DocString(name="hash-table-rehash-size", args="hash-table") private static final class pf_hash_table_rehash_size extends Primitive { pf_hash_table_rehash_size() { super(Symbol.HASH_TABLE_REHASH_SIZE, "hash-table"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof WeakHashTable) { return ((WeakHashTable)arg).getRehashSize(); } return checkHashTable(arg).getRehashSize(); } }; private static final Primitive HASH_TABLE_REHASH_THRESHOLD = new pf_hash_table_rehash_threshold(); @DocString(name="hash-table-rehash-threshold", args="hash-table") private static final class pf_hash_table_rehash_threshold extends Primitive { pf_hash_table_rehash_threshold() { super(Symbol.HASH_TABLE_REHASH_THRESHOLD, "hash-table"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof WeakHashTable) { return ((WeakHashTable)arg).getRehashThreshold(); } return checkHashTable(arg).getRehashThreshold(); } }; private static final Primitive MAPHASH = new pf_maphash(); @DocString(name="maphash", args="function hash-table", doc="Iterates over all entries in the hash-table. For each entry," + " the function is called with two arguments--the key and the" + " value of that entry.") private static final class pf_maphash extends Primitive { pf_maphash() { super(Symbol.MAPHASH, "function hash-table"); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof WeakHashTable) { return ((WeakHashTable)second).MAPHASH(first); } return checkHashTable(second).MAPHASH(first); } }; private static final Primitive HASH_TABLE_WEAKNESS = new pf_hash_table_weakness(); @DocString(name="hash-table-weakness", args="hash-table", doc="Return weakness property of HASH-TABLE, or NIL if it has none.") private static final class pf_hash_table_weakness extends Primitive { pf_hash_table_weakness() { super(Symbol.HASH_TABLE_WEAKNESS, "hash-table"); } @Override public LispObject execute(LispObject first) { if (first instanceof HashTable) { return NIL; } else if (first instanceof WeakHashTable) { return ((WeakHashTable)first).getWeakness(); } return type_error(first, Symbol.HASH_TABLE); } }; protected static HashTable checkHashTable(LispObject ht) { if (ht instanceof HashTable) return (HashTable)ht; type_error(ht, Symbol.HASH_TABLE); return null; } } abcl-src-1.9.0/src/org/armedbear/lisp/IllegalMonitorState.java0100644 0000000 0000000 00000005014 14202767264 023004 0ustar000000000 0000000 /* * IllegalMonitorState.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class IllegalMonitorState extends ProgramError { public IllegalMonitorState() { // This is really just an ordinary PROGRAM-ERROR, broken out into its // own Java class as a convenience for the implementation. super(StandardClass.PROGRAM_ERROR); setFormatControl(getMessage().replaceAll("~","~~")); setFormatArguments(NIL); } public IllegalMonitorState(String message) { // This is really just an ordinary PROGRAM-ERROR, broken out into its // own Java class as a convenience for the implementation. super(StandardClass.PROGRAM_ERROR); if (message != null) { this.message = message; } setFormatControl(getMessage().replaceAll("~","~~")); setFormatArguments(NIL); } String message = "Illegal monitor state."; @Override public String getMessage() { return message; } } abcl-src-1.9.0/src/org/armedbear/lisp/IntegrityError.java0100644 0000000 0000000 00000003437 14202767264 022061 0ustar000000000 0000000 /* * IntegrityError.java * * Copyright (C) 2011 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; /** This error is invoked in situations where the code can't continue * because some precondition isn't met, although it's not an assertion * error per se. */ public class IntegrityError extends Error { public IntegrityError() { } } abcl-src-1.9.0/src/org/armedbear/lisp/Interpreter.java0100644 0000000 0000000 00000062270 14202767264 021374 0ustar000000000 0000000 /* * Interpreter.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; public final class Interpreter { // There can only be one interpreter. public static Interpreter interpreter; private final boolean jlisp; private final InputStream inputStream; private final OutputStream outputStream; private static boolean noinit = false; private static boolean nosystem = false; private static boolean noinform = false; private static boolean help = false; private static boolean doubledash = false; public static synchronized Interpreter getInstance() { return interpreter; } // Interface. public static synchronized Interpreter createInstance() { if (interpreter != null) return null; interpreter = new Interpreter(); _NOINFORM_.setSymbolValue(T); initializeLisp(); return interpreter; } public static synchronized Interpreter createDefaultInstance(String[] args) { if (interpreter != null) return null; interpreter = new Interpreter(); if (args != null) preprocessCommandLineArguments(args); if (!noinform) { Stream out = getStandardOutput(); out._writeString(banner()); out._finishOutput(); } if (help) { Stream out = getStandardOutput(); out._writeString(help()); out._finishOutput(); exit(0); // FIXME } if (noinform) _NOINFORM_.setSymbolValue(T); else { double uptime = (System.currentTimeMillis() - Main.startTimeMillis) / 1000.0; getStandardOutput()._writeString("Low-level initialization completed in " + uptime + " seconds.\n"); } initializeLisp(); initializeTopLevel(); if (!nosystem) initializeSystem(); if (!noinit) processInitializationFile(); doubledash = false; if (args != null) postprocessCommandLineArguments(args); return interpreter; } public static synchronized Interpreter createJLispInstance( InputStream in, OutputStream out, String initialDirectory, String version) { if (interpreter != null) return null; interpreter = new Interpreter(in, out, initialDirectory); Stream stdout = getStandardOutput(); stdout._writeLine(version); stdout._writeString(banner()); stdout._finishOutput(); initializeJLisp(); initializeTopLevel(); initializeSystem(); processInitializationFile(); return interpreter; } public static boolean initialized() { return initialized; } private Interpreter() { jlisp = false; inputStream = null; outputStream = null; } private Interpreter(InputStream inputStream, OutputStream outputStream, String initialDirectory) { jlisp = true; this.inputStream = inputStream; this.outputStream = outputStream; resetIO(new Stream(Symbol.SYSTEM_STREAM, inputStream, Symbol.CHARACTER), new Stream(Symbol.SYSTEM_STREAM, outputStream, Symbol.CHARACTER)); if (!initialDirectory.endsWith(File.separator)) initialDirectory = initialDirectory.concat(File.separator); Symbol.DEFAULT_PATHNAME_DEFAULTS.setSymbolValue(Pathname.create(initialDirectory)); } // Interface. public LispObject eval(String s) { return Lisp.eval(new StringInputStream(s).read(true, NIL, false, LispThread.currentThread(), Stream.currentReadtable)); } public static synchronized void initializeLisp() { if (!initialized) { Load.loadSystemFile("boot.lisp", false, false, false); initialized = true; } } public static synchronized void initializeJLisp() { if (!initialized) { Symbol.FEATURES.setSymbolValue(new Cons(Keyword.J, Symbol.FEATURES.getSymbolValue())); Load.loadSystemFile("boot.lisp", false, false, false); try { Class.forName("org.armedbear.j.LispAPI"); } catch (ClassNotFoundException e) { } // FIXME: what to do? Load.loadSystemFile("j.lisp", false); // not being autoloaded initialized = true; } } private static boolean topLevelInitialized; private static synchronized void initializeTopLevel() { if (!topLevelInitialized) { // Resolve top-level-loop autoload. Symbol TOP_LEVEL_LOOP = intern("TOP-LEVEL-LOOP", PACKAGE_TPL); LispObject tplFun = TOP_LEVEL_LOOP.getSymbolFunction(); if (tplFun instanceof Autoload) { Autoload autoload = (Autoload) tplFun; autoload.load(); } topLevelInitialized = true; } } private static synchronized void processInitializationFile() { try { String userHome = System.getProperty("user.home"); File file = new File(userHome, ".abclrc"); if (file.isFile()) { final double startLoad = System.currentTimeMillis(); Load.load(file.getCanonicalPath()); if (!noinform) { final double loadtime = (System.currentTimeMillis() - startLoad) / 1000.0; getStandardOutput() ._writeString("Loading " + file + " completed in " + loadtime + " seconds.\n"); } return; } } catch (IOException e) { e.printStackTrace(); } } private static synchronized void initializeSystem() { Load.loadSystemFile("system", false); // not being autoloaded } // Check for --noinit; verify that arguments are supplied for --load and // --eval options. Copy all unrecognized arguments into // ext:*command-line-argument-list* private static void preprocessCommandLineArguments(String[] args) { LispObject arglist = NIL; if (args != null) { for (int i = 0; i < args.length; ++i) { String arg = args[i]; if (doubledash) { arglist = new Cons(args[i], arglist); } else if (arg.equals("--")) { doubledash = true; } else if (arg.equals("--noinit")) { noinit = true; } else if (arg.equals("--nosystem")) { nosystem = true; } else if (arg.equals("--noinform")) { noinform = true; } else if (arg.equals("--help")) { help = true; } else if (arg.equals("--batch")) { _BATCH_MODE_.setSymbolValue(T); } else if (arg.equals("--eval")) { if (i + 1 < args.length) { ++i; } else { System.err.println("No argument supplied to --eval"); exit(1); // FIXME } } else if (arg.equals("--load") || arg.equals("--load-system-file")) { if (i + 1 < args.length) { ++i; } else { System.err.println("No argument supplied to --load"); exit(1); // FIXME } } else { arglist = new Cons(args[i], arglist); } } } arglist.nreverse(); _COMMAND_LINE_ARGUMENT_LIST_.setSymbolValue(arglist); } // Do the --load and --eval actions. private static void postprocessCommandLineArguments(String[] args) { if (args != null) { for (int i = 0; i < args.length; ++i) { String arg = args[i]; if (doubledash) { continue; } else if (arg.equals("--")) { doubledash = true; } else if (arg.equals("--eval")) { if (i + 1 < args.length) { try { evaluate(args[i + 1]); } catch (UnhandledCondition c) { final String separator = System.getProperty("line.separator"); StringBuilder sb = new StringBuilder(); sb.append(separator); sb.append("Caught "); sb.append(c.getCondition().typeOf().printObject()); sb.append(" while processing --eval option \"" + args[i + 1] + "\":"); sb.append(separator); sb.append(" "); final LispThread thread = LispThread.currentThread(); thread.bindSpecial(Symbol.PRINT_ESCAPE, NIL); sb.append(c.getCondition().princToString()); sb.append(separator); System.err.print(sb.toString()); exit(2); // FIXME } ++i; } else { // Shouldn't happen. System.err.println("No argument supplied to --eval"); exit(1); // FIXME } } else if (arg.equals("--load") || arg.equals("--load-system-file")) { if (i + 1 < args.length) { if (arg.equals("--load")) Load.load(Pathname.mergePathnames((Pathname)Pathname.create(args[i + 1]), checkPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.getSymbolValue())), false, false, true); else Load.loadSystemFile(args[i + 1], false); // not being autoloaded ++i; } else { // Shouldn't happen. System.err.println("No argument supplied to --load"); exit(1); // FIXME } } } } if (_BATCH_MODE_.getSymbolValue() == T) { exit(0); // FIXME } } @SuppressWarnings("CallToThreadDumpStack") public void run() { final LispThread thread = LispThread.currentThread(); try { Symbol TOP_LEVEL_LOOP = intern("TOP-LEVEL-LOOP", PACKAGE_TPL); LispObject tplFun = TOP_LEVEL_LOOP.getSymbolFunction(); if (tplFun instanceof Function) { thread.execute(tplFun); return; } } catch (ProcessingTerminated e) { throw e; } catch (IntegrityError e) { return; } catch (Throwable t) { t.printStackTrace(); return; } // We only arrive here if something went wrong and we weren't able // to load top-level.lisp and run the normal top-level loop. Stream out = getStandardOutput(); while (true) { try { thread.resetStack(); thread.clearSpecialBindings(); out._writeString("* "); out._finishOutput(); LispObject object = getStandardInput().read(false, EOF, false, thread, Stream.currentReadtable); if (object == EOF) break; out.setCharPos(0); Symbol.MINUS.setSymbolValue(object); LispObject result = Lisp.eval(object, new Environment(), thread); Debug.assertTrue(result != null); Symbol.STAR_STAR_STAR.setSymbolValue(Symbol.STAR_STAR.getSymbolValue()); Symbol.STAR_STAR.setSymbolValue(Symbol.STAR.getSymbolValue()); Symbol.STAR.setSymbolValue(result); Symbol.PLUS_PLUS_PLUS.setSymbolValue(Symbol.PLUS_PLUS.getSymbolValue()); Symbol.PLUS_PLUS.setSymbolValue(Symbol.PLUS.getSymbolValue()); Symbol.PLUS.setSymbolValue(Symbol.MINUS.getSymbolValue()); out = getStandardOutput(); out.freshLine(); LispObject[] values = thread.getValues(); Symbol.SLASH_SLASH_SLASH.setSymbolValue(Symbol.SLASH_SLASH.getSymbolValue()); Symbol.SLASH_SLASH.setSymbolValue(Symbol.SLASH.getSymbolValue()); if (values != null) { LispObject slash = NIL; for (int i = values.length; i-- > 0;) slash = new Cons(values[i], slash); Symbol.SLASH.setSymbolValue(slash); for (int i = 0; i < values.length; i++) out._writeLine(values[i].printObject()); } else { Symbol.SLASH.setSymbolValue(new Cons(result)); out._writeLine(result.printObject()); } out._finishOutput(); } catch (StackOverflowError e) { getStandardInput().clearInput(); out._writeLine("Stack overflow"); } catch (ControlTransfer c) { // We're on the toplevel, if this occurs, // we're toast... reportError(c, thread); } catch (ProcessingTerminated e) { throw e; } catch (IntegrityError e) { return; } catch (Throwable t) { getStandardInput().clearInput(); out.printStackTrace(t); thread.printBacktrace(); } } } private static void reportError(ControlTransfer c, LispThread thread) { getStandardInput().clearInput(); Stream out = getStandardOutput(); out.freshLine(); Condition condition = (Condition) c.getCondition(); out._writeLine("Error: unhandled condition: " + condition.princToString()); if (thread != null) thread.printBacktrace(); } private static void reportError(UnhandledCondition c, LispThread thread) { getStandardInput().clearInput(); Stream out = getStandardOutput(); out.freshLine(); Condition condition = (Condition) c.getCondition(); out._writeLine("Error: unhandled condition: " + condition.princToString()); if (thread != null) thread.printBacktrace(); } public void kill(int status) { if (jlisp) { try { inputStream.close(); } catch (IOException e) { Debug.trace(e); } try { outputStream.close(); } catch (IOException e) { Debug.trace(e); } } else { ((Stream)Symbol.STANDARD_OUTPUT.getSymbolValue())._finishOutput(); ((Stream)Symbol.ERROR_OUTPUT.getSymbolValue())._finishOutput(); System.exit(status); } } public synchronized void dispose() { Debug.trace("Interpreter.dispose"); Debug.assertTrue(interpreter == this); interpreter = null; } @Override protected void finalize() throws Throwable { System.err.println("Interpreter.finalize"); } public static final class UnhandledCondition extends Error { LispObject condition; UnhandledCondition(LispObject condition) { this.condition = condition; } public LispObject getCondition() { return condition; } @Override public String getMessage() { String conditionText; LispThread thread = LispThread.currentThread(); SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, NIL); try { conditionText = getCondition().princToString(); } catch (Throwable t) { conditionText = ""; } finally { thread.resetSpecialBindings(mark); } return "Unhandled lisp condition: " + conditionText; } }; private static final Primitive _DEBUGGER_HOOK_FUNCTION = new Primitive("%debugger-hook-function", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject first, LispObject second) { final LispObject condition = first; if (interpreter == null) { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, NIL); try { final LispObject truename = Symbol.LOAD_TRUENAME.symbolValue(thread); if (truename != NIL) { final LispObject stream = _LOAD_STREAM_.symbolValue(thread); if (stream instanceof Stream) { final int lineNumber = ((Stream)stream).getLineNumber() + 1; final int offset = ((Stream)stream).getOffset(); Debug.trace("Error loading " + truename.princToString() + " at line " + lineNumber + " (offset " + offset + ")"); } } Debug.trace("Encountered unhandled condition of type " + condition.typeOf().princToString() + ':'); Debug.trace(" " + condition.princToString()); } catch (Throwable t) {} // catch any exception to throw below finally { thread.resetSpecialBindings(mark); } } UnhandledCondition uc = new UnhandledCondition(condition); if (condition.typep(Symbol.JAVA_EXCEPTION) != NIL) uc.initCause((Throwable)JavaException .JAVA_EXCEPTION_CAUSE.execute(condition).javaInstance()); throw uc; } }; public static final LispObject readFromString(String s) { return new StringInputStream(s).read(true, NIL, false, LispThread.currentThread(), Stream.currentReadtable); } // For j. /** Runs its input string through the lisp reader and evaluates the result. * * @param s A string with a valid Common Lisp expression * @return The result of the evaluation * @exception UnhandledCondition in case the an error occurs which * should be passed to the Lisp debugger */ public static LispObject evaluate(String s) { if (!initialized) initializeJLisp(); StringInputStream stream = new StringInputStream(s); final LispThread thread = LispThread.currentThread(); LispObject obj = null; final SpecialBindingsMark mark0 = thread.markSpecialBindings(); thread.bindSpecial(Symbol.DEBUGGER_HOOK, _DEBUGGER_HOOK_FUNCTION); try { // catch possible errors from use of SHARPSIGN_DOT macros in --eval stanzas obj = stream.read(false, EOF, false, thread, Stream.currentReadtable); } finally { thread.resetSpecialBindings(mark0); } if (obj == EOF) return error(new EndOfFile(stream)); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.DEBUGGER_HOOK, _DEBUGGER_HOOK_FUNCTION); try { return Lisp.eval(obj, new Environment(), thread); } finally { thread.resetSpecialBindings(mark); } } private static final String build; static { String s = null; InputStream in = Interpreter.class.getResourceAsStream("build"); if (in != null) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); s = reader.readLine(); reader.close(); } catch (IOException e) {} } build = s; } private static String banner() { final String sep = System.getProperty("line.separator"); StringBuilder sb = new StringBuilder("Armed Bear Common Lisp "); sb.append(Version.getVersion()); if (build != null) { sb.append(" (built "); sb.append(build); sb.append(')'); } sb.append(sep); sb.append("Java "); sb.append(System.getProperty("java.version")); sb.append(' '); sb.append(System.getProperty("java.vendor")); sb.append(sep); String vm = System.getProperty("java.vm.name"); if (vm != null) { sb.append(vm); sb.append(sep); } return sb.toString(); } private static String help() { final String sep = System.getProperty("line.separator"); StringBuilder sb = new StringBuilder("Parameters:"); sb.append(sep); sb.append("--help").append(sep) .append(" Displays this message."); sb.append(sep); sb.append("--noinform").append(sep) .append(" Suppresses the printing of startup information and banner."); sb.append(sep); sb.append("--noinit").append(sep) .append(" Suppresses the loading of the '~/.abclrc' startup file."); sb.append(sep); sb.append("--nosystem").append(sep) .append(" Suppresses loading the 'system.lisp' customization file. "); sb.append(sep); sb.append("--eval
").append(sep) .append(" Evaluates the before initializing REPL."); sb.append(sep); sb.append("--load ").append(sep) .append(" Loads the file before initializing REPL."); sb.append(sep); sb.append("--load-system-file ").append(sep) .append(" Loads the system file before initializing REPL."); sb.append(sep); sb.append("--batch").append(sep) .append(" The process evaluates forms specified by arguments and possibly by those").append(sep) .append(" by those in the intialization file '~/.abcl', and then exits."); sb.append(sep); sb.append(sep); sb.append("The occurance of '--' copies the remaining arguments, unprocessed, into").append(sep) .append("the variable EXTENSIONS:*COMMAND-LINE-ARGUMENT-LIST*."); sb.append(sep); return sb.toString(); } } abcl-src-1.9.0/src/org/armedbear/lisp/JHandler.java0100644 0000000 0000000 00000013113 14202767264 020550 0ustar000000000 0000000 /* * JHandler.java * * Copyright (C) 2003-2005 Andras Simon, Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; public final class JHandler { static final Map> table = new WeakHashMap>(); public static void callLisp (String s, Object o) { callLisp(s, o, ""); } public static void callLisp (String s, Object o, String s1) { callLisp(s, o, s1, new int[] {}); } public static void callLisp (String s, Object o, String s1, int ai[]) { callLisp(s, o, new String[] { s1 }, ai); } public static void callLisp (String s, Object o, String as[]) { callLisp(s, o, as, new int[] {}); } public static void callLisp (String s, Object o, String as[], int ai[]) { if (table.containsKey(o)) { Map entryTable = table.get(o); if (entryTable.containsKey(s)) { final Entry entry = entryTable.get(s); final Function f = entry.getHandler(); final LispObject data = entry.getData(); final Fixnum count = entry.getCount(); final Fixnum[] lispAi = new Fixnum[ai.length]; for (int i = 0; i < ai.length; i++) { lispAi[i] = Fixnum.getInstance(ai[i]); } final LispObject lispAiVector = new SimpleVector(lispAi); final SimpleString[] lispAs = new SimpleString[as.length]; for (int i = 0; i < as.length; i++) { lispAs[i] = new SimpleString(as[i]); } final LispObject lispAsVector = new SimpleVector(lispAs); LispObject[] args = new LispObject[] //FIXME: count -> seq_num { data, new JavaObject(o), lispAiVector, lispAsVector, internKeyword(s), count }; f.execute(args); } } } // jregister-handler1 object event handler data count private static final Primitive _JREGISTER_HANDLER = new Primitive("%jregister-handler", PACKAGE_JAVA) { @Override public LispObject execute(LispObject[] args) { if (args.length != 5) return error(new WrongNumberOfArgumentsException(this, 5)); Map entryTable = null; Object object = args[0].javaInstance(); String event = ((Symbol)args[1]).getName(); if (!table.containsKey(object)) { entryTable = new HashMap(); table.put(object,entryTable); } else { entryTable = (Map)table.get(object); } Entry entry = new Entry((Function) args[2], args[3], event, entryTable); if (args[4] != NIL) entry.addCount(((Fixnum)args[4]).value); entryTable.put(event,entry); return T; } }; private static class Entry { Function handler; LispObject data; int count = -1; Map entryTable; String event; public Entry (Function handler, LispObject data, String event, Map entryTable) { this.entryTable = entryTable; this.event = event; this.handler = handler; this.data = data; } public Function getHandler () { return handler; } public void addData (LispObject data) { this.data = data; } public LispObject getData () { return data; } public void addCount (int count) { this.count = count; } public Fixnum getCount () { if (count == 0) entryTable.remove(event); return (Fixnum.getInstance (count--)); } } } abcl-src-1.9.0/src/org/armedbear/lisp/JProxy.java0100644 0000000 0000000 00000023255 14223403213 020304 0ustar000000000 0000000 /* * JProxy.java * * Copyright (C) 2002-2005 Peter Graves, Andras Simon * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; public final class JProxy { static final Map table = new WeakHashMap(); // ### %jnew-proxy interface &rest method-names-and-defs private static final Primitive _JNEW_PROXY = new Primitive("%jnew-proxy", PACKAGE_JAVA, false, "interface &rest method-names-and-defs") { @Override public LispObject execute(LispObject[] args) { int length = args.length; if (length < 3 || length % 2 != 1) return error(new WrongNumberOfArgumentsException(this)); Map lispDefinedMethods = new HashMap(); for (int i = 1; i < length; i += 2) lispDefinedMethods.put(args[i].getStringValue(), (Function) args[i + 1]); Class iface = (Class) args[0].javaInstance(); Object proxy = Proxy.newProxyInstance(iface.getClassLoader(), new Class[] { iface }, new LispHandler(table)); table.put(proxy, new Entry(iface, lispDefinedMethods)); return new JavaObject(proxy); } }; private static class LispHandler implements InvocationHandler { Map table; LispHandler (Map table) { this.table = table; } public Object invoke(Object proxy, Method method, Object[] args) { String methodName = method.getName(); if (methodName.equals("hashCode")) return Integer.valueOf(System.identityHashCode(proxy)); if (methodName.equals("equals")) return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); if (methodName.equals("toString")) return proxy.getClass().getName() + '@' + Integer.toHexString(proxy.hashCode()); if (table.containsKey(proxy)) { Entry entry = (Entry) table.get(proxy); Function f = entry.getLispMethod(methodName); if (f != null) { LispObject lispArgs = NIL; if (args != null) { for (int i = args.length - 1 ; 0 <= i ; i--) lispArgs = lispArgs.push(new JavaObject(args[i])); } LispObject result = evalCall(f, lispArgs, new Environment(), LispThread.currentThread()); return (method.getReturnType() == void.class ? null : result.javaInstance()); } } return null; } } private static class Entry { Class iface; Map lispDefinedMethods; public Entry (Class iface, Map lispDefinedMethods) { this.iface = iface; this.lispDefinedMethods = lispDefinedMethods; } public Function getLispMethod(String methodName) { if (lispDefinedMethods.containsKey(methodName)) return (Function)lispDefinedMethods.get(methodName); return null; } } //NEW IMPLEMENTATION by Alessio Stalla /** * A weak map associating each proxy instance with a "Lisp-this" object. */ static final Map proxyMap = new WeakHashMap(); public static class LispInvocationHandler implements InvocationHandler { private Function function; private static Method hashCodeMethod; private static Method equalsMethod; private static Method toStringMethod; static { try { hashCodeMethod = Object.class.getMethod("hashCode", new Class[] {}); equalsMethod = Object.class.getMethod("equals", new Class[] { Object.class }); toStringMethod = Object.class.getMethod("toString", new Class[] {}); } catch (Exception e) { throw new Error("Something got horribly wrong - can't get a method from Object.class", e); } } public LispInvocationHandler(Function function) { this.function = function; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(hashCodeMethod.equals(method)) { return System.identityHashCode(proxy); } if(equalsMethod.equals(method)) { return proxy == args[0]; } if(toStringMethod.equals(method)) { return proxy.getClass().getName() + '@' + Integer.toHexString(proxy.hashCode()); } if(args == null) { args = new Object[0]; } LispObject lispArgs = NIL; synchronized(proxyMap) { lispArgs = lispArgs.push(toLispObject(proxyMap.get(proxy))); } lispArgs = lispArgs.push(new SimpleString(method.getName())); for(int i = 0; i < args.length; i++) { lispArgs = lispArgs.push(toLispObject(args[i])); } Object retVal = LispThread.currentThread().execute (Symbol.APPLY, function, lispArgs.reverse()).javaInstance(); //(function.execute(lispArgs)).javaInstance(); /* DOES NOT WORK due to autoboxing! if(retVal != null && !method.getReturnType().isAssignableFrom(retVal.getClass())) { return error(new TypeError(new JavaObject(retVal), new JavaObject(method.getReturnType()))); }*/ return retVal; } } private static final Primitive _JMAKE_INVOCATION_HANDLER = new Primitive("%jmake-invocation-handler", PACKAGE_JAVA, false, "function") { public LispObject execute(LispObject[] args) { int length = args.length; if (length != 1) { return error(new WrongNumberOfArgumentsException(this, 1)); } if(!(args[0] instanceof Function)) { return type_error(args[0], Symbol.FUNCTION); } return new JavaObject(new LispInvocationHandler((Function) args[0])); } }; private static final Primitive _JMAKE_PROXY = new Primitive("%jmake-proxy", PACKAGE_JAVA, false, "interfaces invocation-handler") { public LispObject execute(final LispObject[] args) { int length = args.length; if (length != 3) { return error(new WrongNumberOfArgumentsException(this, 3)); } if(!(args[0] instanceof Cons)) { return type_error(args[0], Symbol.CONS); } Class[] ifaces = new Class[args[0].length()]; LispObject ifList = args[0]; for(int i = 0; i < ifaces.length; i++) { ifaces[i] = (Class) ifList.car().javaInstance(Class.class); ifList = ifList.cdr(); } InvocationHandler invocationHandler = (InvocationHandler) ((JavaObject) args[1]).javaInstance(InvocationHandler.class); Object proxy = Proxy.newProxyInstance( JavaClassLoader.getCurrentClassLoader(), ifaces, invocationHandler); synchronized(proxyMap) { proxyMap.put(proxy, args[2]); } return new JavaObject(proxy); } }; static LispObject toLispObject(Object obj) { return (obj instanceof LispObject) ? (LispObject) obj : new JavaObject(obj); } } abcl-src-1.9.0/src/org/armedbear/lisp/JarPathname.java0100644 0000000 0000000 00000047116 14223403213 021245 0ustar000000000 0000000 /* * JarPathname.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.InputStream; import java.io.IOException; import java.io.File; import java.net.URL; import java.net.URI; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class JarPathname extends URLPathname { static final public String JAR_URI_SUFFIX = "!/"; static final public String JAR_URI_PREFIX = "jar:"; protected JarPathname() {} public static JarPathname create() { return new JarPathname(); } public static JarPathname create(JarPathname p) { JarPathname result = new JarPathname(); result.copyFrom(p); return result; } public static JarPathname createFromPathname(Pathname p) { JarPathname result = new JarPathname(); URLPathname rootDevice = new URLPathname(); if (p instanceof URLPathname) { rootDevice.copyFrom(p); } else if (p instanceof Pathname) { rootDevice = URLPathname.create(p); } else { simple_error("Argument is already a JAR-PATHNAME: ~a", p); } result.setDevice(new Cons(rootDevice, NIL)); return result; } /** Transform a reference to a nested Jar to an entry */ public static JarPathname archiveAsEntry(JarPathname p) { JarPathname result = new JarPathname(); result = (JarPathname)result.copyFrom(p); LispObject jars = result.getJars(); jars = jars.nreverse(); Pathname entry = (Pathname)jars.car(); jars = jars.cdr().nreverse(); result .setDevice(jars) .setDirectory(entry.getDirectory()) .setName(entry.getName()) .setType(entry.getType()); return result; } /** Transform an entry in a jar to a reference as a jar */ public static JarPathname createFromEntry(JarPathname p) { JarPathname result = new JarPathname(); result .copyFrom(p) .setDirectory(NIL) .setName(NIL) .setType(NIL) .setVersion(Keyword.NEWEST); Pathname entryPath = p.getEntryPath(); LispObject device = result.getDevice(); device = device.reverse().push(entryPath).reverse(); result.setDevice(device); return result; } @DocString(name="as-jar-pathname-archive", args="pathname", returns="jar-pathname", doc="Returns PATHNAME as a reference to a JAR-PATHNAME archive" + "\n" + "If PATHNAME names an ordinary file, the resulting JAR-PATHNAME addresses the" + "file as an archive. If PATHNAME names an entry in an archive, the resulting" + "JAR-PATHNAME addresses that entry as a zip archive within that archive.") private static final Primitive AS_JAR_PATHNAME_ARCHIVE = new pf_as_jar_pathname_archive(); private static class pf_as_jar_pathname_archive extends Primitive { pf_as_jar_pathname_archive() { super("as-jar-pathname-archive", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof AbstractString) { arg = coerceToPathname(arg); } if (arg instanceof JarPathname) { return createFromEntry((JarPathname)arg); } if (arg instanceof Pathname) { return createFromPathname((Pathname)arg); } type_error(arg, list(Symbol.OR, Symbol.PATHNAME, Symbol.URL_PATHNAME, Symbol.JAR_PATHNAME)); return (LispObject)UNREACHED; } }; static public JarPathname createFromFile(String s) { JarPathname result = JarPathname.create(JAR_URI_PREFIX + "file:" + s + JAR_URI_SUFFIX); result.setVersion(Keyword.NEWEST); return result; } static public JarPathname createEntryFromFile(String jar, String entry) { JarPathname result = JarPathname.create(JAR_URI_PREFIX + "file:" + jar + JAR_URI_SUFFIX + entry); result.setVersion(Keyword.NEWEST); return result; } static public JarPathname createEntryFromJar(JarPathname jar, String entry) { if (jar.isArchiveEntry()) { simple_error("Failed to create the entry ~a in ~a", entry, jar); return (JarPathname)UNREACHED; } JarPathname result = new JarPathname(); result.copyFrom(jar); String path = new String(entry); if (!path.startsWith("/")) { path = "/" + path; } Pathname p = Pathname.create(path); result .setDirectory(p.getDirectory()) .setName(p.getName()) .setType(p.getType()) .setVersion(Keyword.NEWEST); return result; } /** * Enumerate the components of a jar namestring */ static List enumerate(String s) { ArrayList result = new ArrayList(); int i = s.lastIndexOf(JAR_URI_PREFIX); if (i == -1) { parse_error("Failed to find any occurence of '" + JAR_URI_PREFIX + "' prefixes:" + s); return null; // not reached } i += JAR_URI_PREFIX.length(); // advance index to end of "jar:jar:jar:..." if ((i % JAR_URI_PREFIX.length()) != 0) { parse_error("Failed to parse 'jar:' prefixes:" + s); return null; } int prefixCount = i / JAR_URI_PREFIX.length(); String withoutPrefixes = s.substring(i); String parts[] = withoutPrefixes.split(JAR_URI_SUFFIX); // Do we have as many prefixes as suffixes? String notEndingInSuffix = withoutPrefixes + "nonce"; String suffixParts[] = notEndingInSuffix.split(JAR_URI_SUFFIX); int suffixCount = suffixParts.length - 1; if (suffixCount != prefixCount) { parse_error("Mismatched 'jar:' prefix and '/!' suffixes in jar: " + s); return null; } if (parts.length == 1) { if (!s.endsWith(JAR_URI_SUFFIX)) { error(new SimpleError("No trailing jar uri suffix: " + s)); return null; } if (!isValidURL(parts[0])) { error(new SimpleError("Not a valid URI: " + parts[0])); return null; } result.add(parts[0]); return result; } // The root, non-JarPathname location of this reference // For files, possibly either a relative or absolute directory result.add(parts[0]); // The references to the pathnames of archives located within the // root jar. // These will be relative directory paths suffixed with JAR_URI_SUFFIX for (int j = 1; j < prefixCount; j++) { String ns = parts[j] + JAR_URI_SUFFIX; result.add(ns); } // possibly return the path inside the last jar as an absolute path if (parts.length == (prefixCount + 1)) { result.add("/" + parts[parts.length - 1]); } return result; } static public JarPathname create(String s) { if (!s.startsWith(JAR_URI_PREFIX)) { parse_error("Cannot create a PATHNAME-JAR from namestring: " + s); return (JarPathname)UNREACHED; } List contents = JarPathname.enumerate(s); if (contents == null) { parse_error("Couldn't parse PATHNAME-JAR from namestring: " + s); return (JarPathname)UNREACHED; } JarPathname result = new JarPathname(); // Normalize the root jar to be a URL URLPathname rootPathname; String rootNamestring = contents.get(0); if (!isValidURL(rootNamestring)) { Pathname root = Pathname.create(rootNamestring); rootPathname = URLPathname.createFromFile(root); } else { rootPathname = URLPathname.create(rootNamestring); } LispObject jars = NIL; jars = jars.push(rootPathname); if (contents.size() == 1) { result.setDevice(jars); return result; } for (int i = 1; i < contents.size(); i++) { String ns = contents.get(i); if (ns.endsWith(JAR_URI_SUFFIX)) { String nsWithoutSuffix = ns.substring(0, ns.length() - JAR_URI_SUFFIX.length()); Pathname pathname = (Pathname)Pathname.create(nsWithoutSuffix); Pathname jar = new Pathname(); jar.copyFrom(pathname); jars = jars.push(jar); } else { Pathname p = (Pathname)Pathname.create(contents.get(i)); result.copyFrom(p); } } jars = jars.nreverse(); result.setDevice(jars); result.validateComponents(); return result; } public LispObject validateComponents() { if (!(getDevice() instanceof Cons)) { return type_error("Invalid DEVICE for JAR-PATHNAME", getDevice(), Symbol.CONS); } LispObject jars = getDevice(); LispObject rootJar = getRootJar(); if (!(rootJar instanceof URLPathname)) { return type_error("The first element in the DEVICE component of a JAR-PATHNAME is not of expected type", rootJar, Symbol.URL_PATHNAME); } jars = jars.cdr(); while (!jars.car().equals(NIL)) { LispObject jar = jars.car(); if (!((jar instanceof Pathname) || (jar instanceof URLPathname))) { return type_error("The value in DEVICE component of a JAR-PATHNAME is not of expected type", jar, list(Symbol.OR, Symbol.PATHNAME, Symbol.URL_PATHNAME)); } jars = jars.cdr(); } return T; } public String getNamestring() { StringBuffer sb = new StringBuffer(); LispObject jars = getJars(); if (jars.equals(NIL) || jars.equals(Keyword.UNSPECIFIC)) { // type_error("JAR-PATHNAME has bad DEVICE", // jars, // list(Symbol.NOT, // list(Symbol.OR, // list(Symbol.EQL, NIL), // list(Symbol.EQL, Keyword.UNSPECIFIC)))); return null; } for (int i = 0; i < jars.length() - 1; i++) { sb.append(JAR_URI_PREFIX); } LispObject root = getRootJar(); if (root instanceof URLPathname) { String ns = ((URLPathname)root).getNamestringAsURL(); sb.append(JAR_URI_PREFIX) .append(ns) .append(JAR_URI_SUFFIX); } else if (root instanceof Pathname) { // For transitional compatibility? String ns = ((Pathname)root).getNamestring(); sb.append(JAR_URI_PREFIX) .append("file:") .append(ns) .append(JAR_URI_SUFFIX); } else { simple_error("Unable to generate namestring for jar with root pathname ~a", root); } LispObject innerJars = jars.cdr(); while (innerJars.car() != NIL) { Pathname jar = (Pathname)innerJars.car(); Pathname p = new Pathname(); p.copyFrom(jar) .setDevice(NIL); String ns = p.getNamestring(); sb.append(ns) .append(JAR_URI_SUFFIX); innerJars = innerJars.cdr(); } if (getDirectory() != NIL || getName() != NIL || getType() != NIL) { Pathname withoutDevice = new Pathname(); withoutDevice .copyFrom(this) .setDevice(NIL); String withoutDeviceNamestring = withoutDevice.getNamestring(); // need to URI encode? if (withoutDeviceNamestring.startsWith("/")) { sb.append(withoutDeviceNamestring.substring(1)); } else { sb.append(withoutDeviceNamestring); } } return sb.toString(); } LispObject getRootJar() { LispObject jars = getJars(); if (!(jars instanceof Cons)) { type_error("JAR-PATHNAME device is not a cons", jars, Symbol.CONS); return (LispObject)UNREACHED; } return jars.car(); } String getRootJarAsURLString() { return JarPathname.JAR_URI_PREFIX + ((URLPathname)getRootJar()).getNamestring() + JarPathname.JAR_URI_SUFFIX; } LispObject getJars() { return getDevice(); } public static LispObject truename(Pathname pathname, boolean errorIfDoesNotExist) { if (!(pathname instanceof JarPathname)) { return URLPathname.truename(pathname, errorIfDoesNotExist); } JarPathname p = new JarPathname(); p.copyFrom(pathname); // Run truename resolution on the path of local jar archives if (p.isLocalFile()) { Pathname rootJar; if (URLPathname.hasExplicitFile((Pathname)p.getRootJar())) { rootJar = new URLPathname(); } else { rootJar = new Pathname(); } rootJar.copyFrom((Pathname)p.getRootJar()); // Ensure that we don't return a JarPathname if the current // default is one when we resolve its TRUENAME. Under Windows, // the device will get filled in with the DOS drive letter if // applicable. if (rootJar.getDevice().equals(NIL) && !Utilities.isPlatformWindows) { rootJar.setDevice(Keyword.UNSPECIFIC); } LispObject rootJarTruename = Pathname.truename(rootJar, errorIfDoesNotExist); if (rootJarTruename.equals(NIL)) { return Pathname.doTruenameExit(rootJar, errorIfDoesNotExist); } LispObject otherJars = p.getJars().cdr(); URLPathname newRootJar; if (rootJarTruename instanceof Pathname) { newRootJar = URLPathname.createFromFile((Pathname)rootJarTruename); } else { newRootJar = (URLPathname) rootJarTruename; } p.setDevice(new Cons(newRootJar, otherJars)); } if (!p.isArchiveEntry()) { ZipCache.Archive archive = ZipCache.getArchive(p); if (archive == null) { return Pathname.doTruenameExit(pathname, errorIfDoesNotExist); } return p; } ZipEntry entry = ZipCache.getZipEntry(p); if (entry == null) { return Pathname.doTruenameExit(pathname, errorIfDoesNotExist); } return p; } public boolean isLocalFile() { Pathname p = (Pathname) getRootJar(); if (p != null) { return p.isLocalFile(); } return false; } public boolean isArchiveEntry() { return !(getDirectory().equals(NIL) && getName().equals(NIL) && getType().equals(NIL)); } public JarPathname getArchive() { if (!isArchiveEntry()) { return (JarPathname)simple_error("Pathname already represents an archive."); } JarPathname archive = new JarPathname(); archive.copyFrom(this); archive .setDirectory(NIL) .setName(NIL) .setType(NIL); return archive; } public LispObject classOf() { return BuiltInClass.JAR_PATHNAME; } @Override public LispObject typeOf() { return Symbol.JAR_PATHNAME; } public InputStream getInputStream() { // XXX We only return the bytes of an entry in a JAR if (!isArchiveEntry()) { simple_error("Can only get input stream for an entry in a JAR-PATHNAME.", this); } InputStream result = ZipCache.getEntryAsInputStream(this); if (result == null) { error(new FileError("Failed to get InputStream", this)); } return result; } /** List the contents of a directory within a JAR archive */ static public LispObject listDirectory(JarPathname pathname) { String directory = pathname.asEntryPath(); // We should only be listing directories if (pathname.getDirectory() == NIL) { return simple_error("Not a directory in a jar ~a", pathname); } if (directory.length() == 0) { directory = "/*"; } else { if (directory.endsWith("/")) { directory = "/" + directory + "*"; } else { directory = "/" + directory + "/*"; } } Pathname wildcard = (Pathname)Pathname.create(directory); LispObject result = NIL; Iterator> iterator = ZipCache.getEntriesIterator(pathname); while (iterator.hasNext()) { Map.Entry e = iterator.next(); JarPathname entry = e.getKey(); if (!Symbol.PATHNAME_MATCH_P.execute(entry, wildcard).equals(NIL)) { result = result.push(entry); } } return result.nreverse(); } @DocString(name="match-wild-jar-pathname", args="wild-jar-pathname", returns="pathnames", doc="Returns the pathnames matching WILD-JAR-PATHNAME which must be both wild and a JAR-PATHNAME") static final Primitive MATCH_WILD_JAR_PATHNAME = new pf_match_wild_jar_pathname(); private static class pf_match_wild_jar_pathname extends Primitive { pf_match_wild_jar_pathname() { super(Symbol.MATCH_WILD_JAR_PATHNAME, "wild-jar-pathname"); } @Override public LispObject execute(LispObject arg) { Pathname pathname = coerceToPathname(arg); if (pathname instanceof LogicalPathname) { pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); } if (!pathname.isJar()) { return new FileError("Not a jar pathname.", pathname); } if (!pathname.isWild()) { return new FileError("Not a wild pathname.", pathname); } JarPathname jarPathname = new JarPathname(); jarPathname .copyFrom(pathname) .setDirectory(NIL) .setName(NIL) .setType(NIL); JarPathname wildcard = (JarPathname)Symbol.TRUENAME.execute(jarPathname); Iterator> iterator = ZipCache.getEntriesIterator(wildcard); wildcard .setDirectory(pathname.getDirectory()) .setName(pathname.getName()) .setType(pathname.getType()); LispObject result = NIL; while (iterator.hasNext()) { Map.Entry e = iterator.next(); JarPathname entry = e.getKey(); LispObject matches = Symbol.PATHNAME_MATCH_P.execute(entry, wildcard); if (!matches.equals(NIL)) { result = new Cons(entry, result); } } return result; } } public long getLastModified() { if (!isArchiveEntry()) { ZipCache.Archive archive = ZipCache.getArchive(this); if (archive != null) { return archive.lastModified; } } else { ZipEntry entry = ZipCache.getZipEntry(this); if (entry != null) { return entry.getTime(); } } return 0; } static JarPathname joinEntry(JarPathname root, Pathname entry) { JarPathname result = new JarPathname(); result .copyFrom(root) .setDirectory(entry.getDirectory()) .setName(entry.getName()) .setType(entry.getType()); // ??? VERSION return result; } } abcl-src-1.9.0/src/org/armedbear/lisp/JarStream.java0100644 0000000 0000000 00000011000 14202767264 020742 0ustar000000000 0000000 /* * JarStream.java * * Copyright (C) 2010 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.BufferedReader; /** * Stream interface for an entry in a jar pathname. * * This only supports reading from the stream. */ public final class JarStream extends Stream { private final Pathname pathname; private final InputStream input; private final Reader reader; private final int bytesPerUnit; public JarStream(Pathname pathname, LispObject elementType, LispObject direction, LispObject ifExists, LispObject format) throws IOException { super(Symbol.JAR_STREAM); Debug.assertTrue(direction == Keyword.INPUT); Debug.assertTrue(pathname.getName() != NIL); isInputStream = true; super.setExternalFormat(format); this.pathname = pathname; this.elementType = elementType; this.input = pathname.getInputStream(); if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) { isCharacterStream = true; bytesPerUnit = 1; InputStreamReader isr = new InputStreamReader(input); this.reader = (Reader) new BufferedReader(isr); initAsCharacterInputStream(this.reader); } else { isBinaryStream = true; int width = Fixnum.getValue(elementType.cadr()); bytesPerUnit = width / 8; this.reader = null; initAsBinaryInputStream(this.input); } } @Override public LispObject typeOf() { return Symbol.JAR_STREAM; } @Override public LispObject classOf() { return BuiltInClass.JAR_STREAM; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.JAR_STREAM) return T; if (typeSpecifier == BuiltInClass.JAR_STREAM) return T; return super.typep(typeSpecifier); } @Override public void setExternalFormat(LispObject format) { super.setExternalFormat(format); } public Pathname getPathname() { return pathname; } @Override public void _close() { try { if (input != null) { input.close(); } if (reader != null) { reader.close(); } setOpen(false); } catch (IOException e) { error(new StreamError(this, e)); } } @Override public String printObject() { StringBuffer sb = new StringBuffer(); sb.append(Symbol.JAR_STREAM.princToString()); String namestring = pathname.getNamestring(); if (namestring != null) { sb.append(" "); sb.append(namestring); } return unreadableString(sb.toString()); } } abcl-src-1.9.0/src/org/armedbear/lisp/Java.java0100644 0000000 0000000 00000162472 14223403213 017737 0ustar000000000 0000000 /* * Java.java * * Copyright (C) 2002-2006 Peter Graves, Andras Simon * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.text.MessageFormat; import java.math.BigInteger; import java.util.*; public final class Java { static final Map registeredExceptions = new HashMap(); private static final LispClass java_exception = LispClass.findClass(Symbol.JAVA_EXCEPTION); static boolean isJavaException(LispClass lc) { return lc.subclassp(java_exception); } private static final Primitive ENSURE_JAVA_OBJECT = new pf_ensure_java_object(); @DocString(name="ensure-java-object", args="obj", doc="Ensures OBJ is wrapped in a JAVA-OBJECT, wrapping it if necessary.") private static final class pf_ensure_java_object extends Primitive { pf_ensure_java_object() { super("ensure-java-object", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject obj) { return obj instanceof JavaObject ? obj : new JavaObject(obj); } }; private static final Primitive REGISTER_JAVA_EXCEPTION = new pf_register_java_exception(); @DocString(name="register-java-exception", // => T args="exception-name condition-symbol", doc="Registers the Java Throwable named by the symbol EXCEPTION-NAME as the condition " + "designated by CONDITION-SYMBOL. Returns T if successful, NIL if not.") private static final class pf_register_java_exception extends Primitive { pf_register_java_exception() { super("register-java-exception", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject className, LispObject symbol) { LispClass lispClass = (LispClass) LispClass.findClass(symbol, true); // FIXME Signal a continuable error if the exception is already registered. if (isJavaException(lispClass)) { registeredExceptions.put(classForName(className.getStringValue()), (Symbol)symbol); return T; } return NIL; } }; private static final Primitive UNREGISTER_JAVA_EXCEPTION = new pf_unregister_java_exception(); @DocString(name="unregister-java-exception", args="exception-name", doc="Unregisters the Java Throwable EXCEPTION-NAME previously registered" + " by REGISTER-JAVA-EXCEPTION.") private static final class pf_unregister_java_exception extends Primitive { pf_unregister_java_exception() { super("unregister-java-exception", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject className) { // FIXME Verify that EXCEPTION-NAME designates a subclass of Throwable. return registeredExceptions.remove(classForName(className.getStringValue())) == null ? NIL : T; } }; static Symbol getCondition(Class cl) { Class o = classForName("java.lang.Object"); for (Class c = cl ; c != o ; c = c.getSuperclass()) { Object object = registeredExceptions.get(c); if (object instanceof Symbol) { LispClass lispClass = (LispClass) LispClass.findClass((Symbol) object, true); if(isJavaException(lispClass)) { return (Symbol) object; } } } return null; } private static final Primitive JCLASS = new pf_jclass(); @DocString(name="jclass", args="name-or-class-ref &optional class-loader", doc="Returns a reference to the Java class designated by" + " NAME-OR-CLASS-REF. If the CLASS-LOADER parameter is passed, the" + " class is resolved with respect to the given ClassLoader.") private static final class pf_jclass extends Primitive { pf_jclass() { super(Symbol.JCLASS); } @Override public LispObject execute(LispObject arg) { return JavaObject.getInstance(javaClass(arg, JavaClassLoader.getCurrentClassLoader())); } @Override public LispObject execute(LispObject className, LispObject classLoader) { ClassLoader loader = (ClassLoader) classLoader.javaInstance(ClassLoader.class); return JavaObject.getInstance(javaClass(className, loader)); } }; static final LispObject jfield(Primitive fun, LispObject[] args, boolean translate) { if (args.length < 2 || args.length > 4) error(new WrongNumberOfArgumentsException(fun, 2, 4)); String fieldName = null; Class c; Field f; Class fieldType; Object instance = null; try { if (args[1] instanceof AbstractString) { // Cases 1-5. fieldName = args[1].getStringValue(); c = javaClass(args[0]); } else { // Cases 6 and 7. fieldName = args[0].getStringValue(); instance = JavaObject.getObject(args[1]); c = instance.getClass(); } f = c.getField(fieldName); fieldType = f.getType(); switch (args.length) { case 2: // Cases 1 and 6. break; case 3: // Cases 2,3, and 7. if (instance == null) { // Cases 2 and 3. if (args[2] instanceof JavaObject) { // Case 2. instance = JavaObject.getObject(args[2]); break; } else { // Case 3. f.set(null,args[2].javaInstance(fieldType)); return args[2]; } } else { // Case 7. f.set(instance,args[2].javaInstance(fieldType)); return args[2]; } case 4: // Cases 4 and 5. if (args[2] != NIL) { // Case 4. instance = JavaObject.getObject(args[2]); } f.set(instance,args[3].javaInstance(fieldType)); return args[3]; } return JavaObject.getInstance(f.get(instance), translate, f.getType()); } catch (NoSuchFieldException e) { error(new LispError("no such field")); } catch (SecurityException e) { error(new LispError("inaccessible field")); } catch (IllegalAccessException e) { error(new LispError("illegal access")); } catch (IllegalArgumentException e) { error(new LispError("illegal argument")); } // Not reached return NIL; } private static final Primitive JFIELD = new pf_jfield(); @DocString(name="jfield", args="class-ref-or-field field-or-instance &optional instance value", doc="Retrieves or modifies a field in a Java class or instance.\n\n"+ "Supported argument patterns:\n\n"+ " Case 1: class-ref field-name:\n"+ " Retrieves the value of a static field.\n\n"+ " Case 2: class-ref field-name instance-ref:\n"+ " Retrieves the value of a class field of the instance.\n\n"+ " Case 3: class-ref field-name primitive-value:\n"+ " Stores a primitive-value in a static field.\n\n"+ " Case 4: class-ref field-name instance-ref value:\n"+ " Stores value in a class field of the instance.\n\n"+ " Case 5: class-ref field-name nil value:\n"+ " Stores value in a static field (when value may be\n"+ " confused with an instance-ref).\n\n"+ " Case 6: field-name instance:\n"+ " Retrieves the value of a field of the instance. The\n"+ " class is derived from the instance.\n\n"+ " Case 7: field-name instance value:\n"+ " Stores value in a field of the instance. The class is\n"+ " derived from the instance.\n\n" ) private static final class pf_jfield extends Primitive { pf_jfield() { super("jfield", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { return jfield(this, args, true); } }; private static final Primitive JFIELD_RAW = new pf_jfield_raw(); @DocString(name="jfield", args="class-ref-or-field field-or-instance &optional instance value", doc="Retrieves or modifies a field in a Java class or instance. Does not\n"+ "attempt to coerce its value or the result into a Lisp object.\n\n"+ "Supported argument patterns:\n\n"+ " Case 1: class-ref field-name:\n"+ " Retrieves the value of a static field.\n\n"+ " Case 2: class-ref field-name instance-ref:\n"+ " Retrieves the value of a class field of the instance.\n\n"+ " Case 3: class-ref field-name primitive-value:\n"+ " Stores a primitive-value in a static field.\n\n"+ " Case 4: class-ref field-name instance-ref value:\n"+ " Stores value in a class field of the instance.\n\n"+ " Case 5: class-ref field-name nil value:\n"+ " Stores value in a static field (when value may be\n"+ " confused with an instance-ref).\n\n"+ " Case 6: field-name instance:\n"+ " Retrieves the value of a field of the instance. The\n"+ " class is derived from the instance.\n\n"+ " Case 7: field-name instance value:\n"+ " Stores value in a field of the instance. The class is\n"+ " derived from the instance.\n\n" ) private static final class pf_jfield_raw extends Primitive { pf_jfield_raw() { super("jfield-raw", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { return jfield(this, args, false); } }; private static final Primitive JCONSTRUCTOR = new pf_jconstructor(); @DocString(name="jconstructor", args="class-ref &rest parameter-class-refs", doc="Returns a reference to the Java constructor of CLASS-REF with the" + " given PARAMETER-CLASS-REFS.") private static final class pf_jconstructor extends Primitive { pf_jconstructor() { super("jconstructor", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { if (args.length < 1) error(new WrongNumberOfArgumentsException(this, 1, -1)); try { final Class c = javaClass(args[0]); int argCount = 0; if (args.length == 2 && args[1] instanceof Fixnum) { argCount = Fixnum.getValue(args[1]); } else { Class[] parameterTypes = new Class[args.length-1]; for (int i = 1; i < args.length; i++) { parameterTypes[i-1] = javaClass(args[i]); } return JavaObject.getInstance(c.getConstructor(parameterTypes)); } // Parameter types not explicitly specified. Constructor[] constructors = c.getConstructors(); for (int i = 0; i < constructors.length; i++) { Constructor constructor = constructors[i]; if (constructor.getParameterTypes().length == argCount) return JavaObject.getInstance(constructor); } throw new NoSuchMethodException(); } catch (NoSuchMethodException e) { error(new LispError("no such constructor")); } catch (ControlTransfer e) { throw e; } catch (Throwable t) { // ControlTransfer addressed above error(new LispError(getMessage(t))); } // Not reached. return NIL; } }; private static final Primitive JMETHOD = new pf_jmethod(); @DocString(name="jmethod", args="class-ref method-name &rest parameter-class-refs", doc="Returns a reference to the Java method METHOD-NAME of CLASS-REF with the" + " given PARAMETER-CLASS-REFS.") private static final class pf_jmethod extends Primitive { pf_jmethod() { super("jmethod", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { if (args.length < 2) error(new WrongNumberOfArgumentsException(this, 2, -1)); final Class c = javaClass(args[0]); String methodName = args[1].getStringValue(); try { int argCount = 0; if (args.length == 3 && args[2] instanceof Fixnum) { argCount = ((Fixnum)args[2]).value; } else { Class[] parameterTypes = new Class[args.length-2]; for (int i = 2; i < args.length; i++) parameterTypes[i-2] = javaClass(args[i]); return JavaObject.getInstance(c.getMethod(methodName, parameterTypes)); } // Parameter types were not explicitly specified. Method[] methods = c.getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals(methodName) && method.getParameterTypes().length == argCount) return JavaObject.getInstance(method); } throw new NoSuchMethodException(); } catch (NoSuchMethodException e) { StringBuilder sb = new StringBuilder("No such method: "); sb.append(c.getName()); sb.append('.'); sb.append(methodName); sb.append('('); for (int i = 2; i < args.length; i++) { sb.append(args[i].princToString()); if (i < args.length - 1) sb.append(','); } sb.append(')'); error(new LispError(sb.toString())); } catch (ControlTransfer e) { throw e; } catch (Throwable t) { // ControlTransfer addressed above error(new LispError(getMessage(t))); } // Not reached. return NIL; } }; static final LispObject jstatic(Primitive fun, LispObject[] args, boolean translate) { if (args.length < 2) { error(new WrongNumberOfArgumentsException(fun, 2, -1)); } try { Method m = null; Class c = null; LispObject methodRef = args[0]; List staticMethods = new ArrayList(); String methodName = null; if (methodRef instanceof JavaObject) { Object obj = ((JavaObject)methodRef).getObject(); if (obj instanceof Method) { staticMethods.add((Method) obj); methodName = ((Method)obj).getName(); } else { error(new LispError(methodRef + "is not a valid reference to a Method")); } } else if (methodRef instanceof AbstractString) { c = javaClass(args[1]); if (c != null) { methodName = methodRef.getStringValue(); Method[] methods = c.getMethods(); int argCount = args.length - 2; for(Method m1 : methods) { if(Modifier.isStatic(m1.getModifiers())) { staticMethods.add(m1); } } } } else { type_error(methodRef, Symbol.STRING); } if (staticMethods.size() > 0) { m = findMethod(staticMethods.toArray(new Method[staticMethods.size()]), methodName, args, 2); } if (m == null) { StringBuilder sb = new StringBuilder("No such static method: "); String className = ""; if (c != null) { className = c.getName(); } sb.append(className); sb.append('.'); sb.append(methodName); sb.append('('); for (int i = 2; i < args.length; i++) { LispObject argClass = Symbol.JCLASS_OF.execute(args[i]); sb.append(argClass.princToString()); if (i < args.length - 1) sb.append(','); } sb.append(')'); error(new LispError(sb.toString())); } Object[] methodArgs = new Object[args.length-2]; Class[] argTypes = m.getParameterTypes(); for (int i = 2; i < args.length; i++) { LispObject arg = args[i]; if (arg.equals(NIL)) { methodArgs[i-2] = false; } else if (arg.equals(T)) { methodArgs[i-2] = true; } else { methodArgs[i-2] = arg.javaInstance(argTypes[i-2]); } } m.setAccessible(true); Object result = null; if (!m.isVarArgs()) { result = m.invoke(null, methodArgs); } else if (argTypes.length == 1) { result = m.invoke(null, (Object)methodArgs); } else { Object[] objectArgs = new Object[methodArgs.length]; for (int i = 0; i < methodArgs.length; i++) { objectArgs[i] = methodArgs[i]; } result = m.invoke(null, objectArgs); } return JavaObject.getInstance(result, translate, m.getReturnType()); } catch (ControlTransfer c) { throw c; } catch (Throwable t) { // ControlTransfer handled above if (t instanceof InvocationTargetException) t = t.getCause(); Symbol condition = getCondition(t.getClass()); if (condition == null) error(new JavaException(t)); else Symbol.SIGNAL.execute( condition, Keyword.CAUSE, JavaObject.getInstance(t), Keyword.FORMAT_CONTROL, new SimpleString(getMessage(t))); } // Not reached. return NIL; } private static final Primitive JSTATIC = new pf_jstatic(); @DocString(name="jstatic", args="method class &rest args", doc="Invokes the static method METHOD on class CLASS with ARGS.") private static final class pf_jstatic extends Primitive { pf_jstatic() { super("jstatic", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { return jstatic(this, args, true); } }; private static final Primitive JSTATIC_RAW = new pf_jstatic_raw(); @DocString(name="jstatic-raw", args="method class &rest args", doc="Invokes the static method METHOD on class CLASS with ARGS. Does not "+ "attempt to coerce the arguments or result into a Lisp object.") private static final class pf_jstatic_raw extends Primitive { pf_jstatic_raw() { super("jstatic-raw", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { return jstatic(this, args, false); } }; private static final Primitive JNEW = new pf_jnew(); @DocString(name="jnew", args="constructor &rest args", doc="Invokes the Java constructor CONSTRUCTOR with the arguments ARGS.") private static final class pf_jnew extends Primitive { pf_jnew() { super("jnew", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { if (args.length < 1) error(new WrongNumberOfArgumentsException(this, 1, -1)); LispObject classRef = args[0]; try { Constructor constructor; if(classRef instanceof AbstractString) { constructor = findConstructor(javaClass(classRef), args); } else { Object object = JavaObject.getObject(classRef); if(object instanceof Constructor) { constructor = (Constructor) object; } else if(object instanceof Class) { constructor = findConstructor((Class) object, args); } else { return error(new LispError(classRef.princToString() + " is neither a Constructor nor a Class")); } } Class[] argTypes = constructor.getParameterTypes(); Object[] initargs = new Object[args.length-1]; for (int i = 1; i < args.length; i++) { LispObject arg = args[i]; if (arg.equals(NIL)) { initargs[i-1] = false ; } else if (arg.equals(T)) { initargs[i-1] = true; } else { initargs[i-1] = arg.javaInstance(argTypes[i-1]); } } return JavaObject.getInstance(constructor.newInstance(initargs)); } catch (ControlTransfer c) { throw c; } catch (Throwable t) { // ControlTransfer handled above if (t instanceof InvocationTargetException) t = t.getCause(); Symbol condition = getCondition(t.getClass()); if (condition == null) error(new JavaException(t)); else Symbol.SIGNAL.execute( condition, Keyword.CAUSE, JavaObject.getInstance(t), Keyword.FORMAT_CONTROL, new SimpleString(getMessage(t))); } // Not reached. return NIL; } }; private static final Primitive JNEW_ARRAY = new pf_jnew_array(); @DocString(name="jnew-array", args="element-type &rest dimensions", doc="Creates a new Java array of type ELEMENT-TYPE, with the given" + " DIMENSIONS.") private static final class pf_jnew_array extends Primitive { pf_jnew_array() { super("jnew-array", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { if (args.length < 2) error(new WrongNumberOfArgumentsException(this, 2, -1)); try { Class c = javaClass(args[0]); int[] dimensions = new int[args.length - 1]; for (int i = 1; i < args.length; i++) dimensions[i-1] = ((Integer)args[i].javaInstance()).intValue(); return JavaObject.getInstance(Array.newInstance(c, dimensions)); } catch (Throwable t) { // no code -> no ControlTransfer error(new JavaException(t)); } // Not reached. return NIL; } }; static final LispObject jarray_ref(Primitive fun, LispObject[] args, boolean translate) { if (args.length < 2) error(new WrongNumberOfArgumentsException(fun, 2, -1)); try { Object a = args[0].javaInstance(); for (int i = 1; i no ControlTransfer Symbol condition = getCondition(t.getClass()); if (condition == null) error(new JavaException(t)); else Symbol.SIGNAL.execute( condition, Keyword.CAUSE, JavaObject.getInstance(t), Keyword.FORMAT_CONTROL, new SimpleString(getMessage(t))); } // Not reached. return NIL; } private static final Primitive JARRAY_REF = new pf_jarray_ref(); @DocString(name="jarray-ref", args="java-array &rest indices", doc="Dereferences the Java array JAVA-ARRAY using the given INDICES, " + "coercing the result into a Lisp object, if possible.") private static final class pf_jarray_ref extends Primitive { pf_jarray_ref() { super("jarray-ref", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { return jarray_ref(this, args, true); } }; private static final Primitive JARRAY_REF_RAW = new pf_jarray_ref_raw(); @DocString(name="jarray-ref-raw", args="java-array &rest indices", doc="Dereference the Java array JAVA-ARRAY using the given INDICES. " + "Does not attempt to coerce the result into a Lisp object.") private static final class pf_jarray_ref_raw extends Primitive { pf_jarray_ref_raw() { super("jarray-ref-raw", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { return jarray_ref(this, args, false); } }; private static final Primitive JARRAY_SET = new pf_jarray_set(); @DocString(name="jarray-set", args="java-array new-value &rest indices", doc="Stores NEW-VALUE at the given INDICES in JAVA-ARRAY.") private static final class pf_jarray_set extends Primitive { pf_jarray_set() { super("jarray-set", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { if (args.length < 3) error(new WrongNumberOfArgumentsException(this, 3, -1)); try { Object a = args[0].javaInstance(); LispObject v = args[1]; for (int i = 2; i no ControlTransfer Symbol condition = getCondition(t.getClass()); if (condition == null) error(new JavaException(t)); else Symbol.SIGNAL.execute( condition, Keyword.CAUSE, JavaObject.getInstance(t), Keyword.FORMAT_CONTROL, new SimpleString(getMessage(t))); } // Not reached. return NIL; } }; /** Calls makeLispObject() to convert the result to an appropriate Lisp type. */ private static final Primitive JCALL = new pf_jcall(); @DocString(name="jcall", args="method-ref instance &rest args", doc="Invokes the Java method METHOD-REF on INSTANCE with arguments ARGS," + " coercing the result into a Lisp object, if possible.") private static final class pf_jcall extends Primitive { pf_jcall() { super(Symbol.JCALL); } @Override public LispObject execute(LispObject[] args) { return jcall(this, args, true); } }; /** * Does no type conversion. The result of the call is simply wrapped in a * JavaObject. */ private static final Primitive JCALL_RAW = new pf_jcall_raw(); @DocString(name="jcall-raw", args="method-ref instance &rest args", doc="Invokes the Java method METHOD-REF on INSTANCE with arguments ARGS." + " Does not attempt to coerce the result into a Lisp object.") private static final class pf_jcall_raw extends Primitive { pf_jcall_raw() { super(Symbol.JCALL_RAW); } @Override public LispObject execute(LispObject[] args) { return jcall(this, args, false); } }; private static final Primitive JRESOLVE_METHOD = new pf_jresolve_method(); @DocString(name="jresolve-method", args="method-name instance &rest args", doc="Finds the most specific Java method METHOD-NAME on INSTANCE " + "applicable to arguments ARGS. Returns NIL if no suitable method is " + "found. The algorithm used for resolution is the same used by JCALL " + "when it is called with a string as the first parameter (METHOD-REF).") private static final class pf_jresolve_method extends Primitive { pf_jresolve_method() { super(Symbol.JRESOLVE_METHOD); } @Override public LispObject execute(LispObject[] args) { if (args.length < 2) { error(new WrongNumberOfArgumentsException(this, 2, -1)); } final LispObject methodArg = args[0]; final LispObject instanceArg = args[1]; final Object instance; Class intendedClass = null; if (instanceArg instanceof AbstractString) { instance = instanceArg.getStringValue(); } else if (instanceArg instanceof JavaObject) { JavaObject jobj = ((JavaObject)instanceArg); instance = jobj.getObject(); intendedClass = jobj.getIntendedClass(); } else { instance = instanceArg.javaInstance(); } if(instance == null) { return program_error("JRESOLVE-METHOD: instance must not be null."); } String methodName = methodArg.getStringValue(); Object[] methodArgs = translateMethodArguments(args, 2); Method method = findMethod(instance, intendedClass, methodName, methodArgs); if (method != null) { return JavaObject.getInstance(method); } else if (instanceArg instanceof JavaObject) { // Sometimes JavaObject.intendedClass has the default // value java.lang.Object, so we try again to resolve // the method using a dynamically requested value for // java.lang.Class. intendedClass = ((JavaObject)instanceArg).getObject().getClass(); method = findMethod(instance, intendedClass, methodName, methodArgs); } else { return NIL; } if (method != null) { return JavaObject.getInstance(method); } else { return NIL; } } }; static LispObject jcall(Primitive fun, LispObject[] args, boolean translate) { if (args.length < 2) error(new WrongNumberOfArgumentsException(fun, 2, -1)); try { final LispObject methodArg = args[0]; final LispObject instanceArg = args[1]; final Object instance; Method method; Object[] methodArgs; Class intendedClass = null; if (instanceArg instanceof AbstractString) { instance = instanceArg.getStringValue(); } else if (instanceArg instanceof JavaObject) { JavaObject jobj = ((JavaObject)instanceArg); instance = jobj.getObject(); intendedClass = jobj.getIntendedClass(); } else { instance = instanceArg.javaInstance(); } if(instance == null) { throw new NullPointerException(); //Handled below } if (methodArg instanceof AbstractString) { String methodName = methodArg.getStringValue(); methodArgs = translateMethodArguments(args, 2); method = findMethod(instance, intendedClass, methodName, methodArgs); if (method == null) { if (intendedClass == null) { String msg = MessageFormat.format("No instance method named {0} found for type {1}", methodName, instance.getClass().getName()); throw new NoSuchMethodException(msg); } String classes = intendedClass.getName(); Class actualClass = instance.getClass(); if(actualClass != intendedClass) { classes += " or " + actualClass.getName(); } throw new NoSuchMethodException("No applicable method named " + methodName + " found in " + classes); } } else method = (Method) JavaObject.getObject(methodArg); Class[] argTypes = (Class[])method.getParameterTypes(); if(argTypes.length != args.length - 2) { return error(new WrongNumberOfArgumentsException("Wrong number of arguments for " + method + ": expected " + argTypes.length + ", got " + (args.length - 2))); } methodArgs = new Object[argTypes.length]; for (int i = 2; i < args.length; i++) { LispObject arg = args[i]; if (arg.equals(NIL)) { methodArgs[i-2] = false; } else if (arg.equals(T)) { methodArgs[i-2] = true; } else { methodArgs[i-2] = arg.javaInstance(argTypes[i-2]); } } if (!method.isAccessible()) { // Possible for static member classes: see #229 if (Modifier.isPublic(method.getModifiers())) { method.setAccessible(true); } } return JavaObject.getInstance(method.invoke(instance, methodArgs), translate, method.getReturnType()); } catch (ControlTransfer t) { throw t; } catch (Throwable t) { // ControlTransfer handled above if (t instanceof InvocationTargetException) t = t.getCause(); Symbol condition = getCondition(t.getClass()); if (condition == null) error(new JavaException(t)); else Symbol.SIGNAL.execute( condition, Keyword.CAUSE, JavaObject.getInstance(t), Keyword.FORMAT_CONTROL, new SimpleString(getMessage(t))); } // Not reached. return null; } private static Object[] translateMethodArguments(LispObject[] args) { return translateMethodArguments(args, 0); } private static Object[] translateMethodArguments(LispObject[] args, int offs) { int argCount = args.length - offs; Object[] javaArgs = new Object[argCount]; for (int i = 0; i < argCount; ++i) { Object x = args[i + offs]; if (x.equals(NIL)) { javaArgs[i] = false; } else if (x.equals(T)) { javaArgs[i] = true; } else { javaArgs[i] = ((LispObject) x).javaInstance(); } } return javaArgs; } private static Method findMethod(Method[] methods, String methodName, Object[] javaArgs) { int argCount = javaArgs.length; Method result = null; for (int i = methods.length; i-- > 0;) { Method method = methods[i]; if (!method.getName().equals(methodName)) { continue; } if (method.getParameterTypes().length != argCount) { continue; } Class[] methodTypes = (Class[]) method.getParameterTypes(); if (!isApplicableMethod(methodTypes, javaArgs)) { continue; } if (result == null || isMoreSpecialized(methodTypes, result.getParameterTypes())) { result = method; } } return result; } private static Method findMethod(Object instance, Class intendedClass, String methodName, Object[] methodArgs) { if(intendedClass == null) { intendedClass = instance.getClass(); } Method method = findMethod(intendedClass, methodName, methodArgs); Class actualClass = null; if(method == null) { actualClass = instance.getClass(); if(intendedClass != actualClass) { method = findMethod(actualClass, methodName, methodArgs); if (method != null) { if (isMethodCallableOnInstance(actualClass, method)) { return method; } } } } return method; } private static boolean isMethodCallableOnInstance(Class instance, Method method) { if (Modifier.isPublic(method.getModifiers())) { return true; } if (instance.isMemberClass()) { return isMethodCallableOnInstance(instance.getEnclosingClass(), method); } return false; } private static Method findMethod(Class c, String methodName, Object[] javaArgs) { Method[] methods = c.getMethods(); return findMethod(methods, methodName, javaArgs); } private static Method findMethod(Class c, String methodName, LispObject[] args, int offset) { Object[] javaArgs = translateMethodArguments(args, offset); return findMethod(c, methodName, javaArgs); } private static Method findMethod(Method[] methods, String methodName, LispObject[] args, int offset) { Object[] javaArgs = translateMethodArguments(args, offset); return findMethod(methods, methodName, javaArgs); } static Constructor findConstructor(Class c, LispObject[] args) throws NoSuchMethodException { int argCount = args.length - 1; Object[] javaArgs = translateMethodArguments(args, 1); Constructor[] ctors = c.getConstructors(); Constructor result = null; for (int i = ctors.length; i-- > 0;) { Constructor ctor = ctors[i]; if (ctor.getParameterTypes().length != argCount) { continue; } Class[] methodTypes = (Class[]) ctor.getParameterTypes(); if (!isApplicableMethod(methodTypes, javaArgs)) { continue; } if (result == null || isMoreSpecialized(methodTypes, result.getParameterTypes())) { result = ctor; } } if (result == null) { StringBuilder sb = new StringBuilder(c.getSimpleName()); sb.append('('); boolean first = true; for(Object o : javaArgs) { if(first) { first = false; } else { sb.append(", "); } if(o != null) { sb.append(o.getClass().getName()); } else { sb.append(""); } } sb.append(')'); throw new NoSuchMethodException(sb.toString()); } return result; } private static boolean isAssignable(Class from, Class to) { from = maybeBoxClass(from); to = maybeBoxClass(to); if (to.isAssignableFrom(from)) { return true; } if (Byte.class.equals(from)) { return Short.class.equals(to) || Integer.class.equals(to) || Long.class.equals(to) || Float.class.equals(to) || Double.class.equals(to); } else if (Short.class.equals(from) || Character.class.equals(from)) { return Integer.class.equals(to) || Long.class.equals(to) || Float.class.equals(to) || Double.class.equals(to); } else if (Integer.class.equals(from)) { return Long.class.equals(to) || Float.class.equals(to) || Double.class.equals(to); } else if (Long.class.equals(from)) { return Float.class.equals(to) || Double.class.equals(to); } else if (Float.class.equals(from)) { return Double.class.equals(to); } else if (from.isArray() && to.isArray()) { // for now just indicate that anything is assignable to an // java.lang.Object[], as this is the most common case if (to.getComponentType().equals(java.lang.Object.class)) { return true; } } return false; } private static boolean isApplicableMethod(Class[] methodTypes, Object[] args) { for (int i = 0; i < methodTypes.length; ++i) { Class methodType = methodTypes[i]; Object arg = args[i]; if (arg == null) { return !methodType.isPrimitive(); } else if (!isAssignableWithValue(arg.getClass(), methodType, arg)) { return false; } } return true; } private static boolean isAssignableWithValue(Class from, Class to, Object value) { if (isAssignable(from, to)) { return true; } if (!(value instanceof Number)) { return false; } from = maybeBoxClass(from); to = maybeBoxClass(to); if (Integer.class.equals(from)) { int v = ((java.lang.Number)value).intValue(); if (Short.class.equals(to) && Short.MAX_VALUE >= v && v >= Short.MIN_VALUE) { return true; } if (Byte.class.equals(to) && 255 >= v && v >= 0) { return true; } // Java 8 introduces BigInteger.longValueExact() which will make the following much easier } else if (BigInteger.class.equals(from)) { // ??? should only need to check for possible conversion to longs BigInteger v = (java.math.BigInteger) value; final BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE); final BigInteger minLong = BigInteger.valueOf(Long.MIN_VALUE); if (Long.class.equals(to) && ((v.compareTo(maxLong) == -1) || (v.compareTo(maxLong) == 0)) && ((v.compareTo(minLong) == 1) || (v.compareTo(minLong) == 0))) { return true; } } return false; } private static boolean isMoreSpecialized(Class[] xtypes, Class[] ytypes) { for (int i = 0; i < xtypes.length; ++i) { Class xtype = maybeBoxClass(xtypes[i]); Class ytype = maybeBoxClass(ytypes[i]); if (xtype.equals(ytype)) { continue; } if (isAssignable(xtype, ytype)) { return true; } } return false; } public static Class maybeBoxClass(Class clazz) { if(clazz.isPrimitive()) { return getBoxedClass(clazz); } else { return clazz; } } private static Class getBoxedClass(Class clazz) { if (clazz.equals(int.class)) { return Integer.class; } else if (clazz.equals(boolean.class)) { return Boolean.class; } else if (clazz.equals(byte.class)) { return Byte.class; } else if (clazz.equals(char.class)) { return Character.class; } else if (clazz.equals(long.class)) { return Long.class; } else if (clazz.equals(float.class)) { return Float.class; } else if (clazz.equals(double.class)) { return Double.class; } else if (clazz.equals(short.class)) { return Short.class; } else { // if (methodType.equals(void.class)) return Void.class; } } // DEPRECATED Remove MAKE-IMMEDIATE-OBJECT in abcl-0.29 private static final Primitive MAKE_IMMEDIATE_OBJECT = new pf_make_immediate_object(); @DocString(name="make-immediate-object", args="object &optional type", doc="Attempts to coerce a given Lisp object into a java-object of the\n" + "given type. If type is not provided, works as jobject-lisp-value.\n" + "Currently, type may be :BOOLEAN, treating the object as a truth value,\n" + "or :REF, which returns Java null if NIL is provided.\n" + "\n" + "Deprecated. Please use JAVA:+NULL+, JAVA:+TRUE+, and JAVA:+FALSE+ for\n" + "constructing wrapped primitive types, JAVA:JOBJECT-LISP-VALUE for converting a\n" + "JAVA:JAVA-OBJECT to a Lisp value, or JAVA:JNULL-REF-P to distinguish a wrapped\n" + "null JAVA-OBJECT from NIL.") private static final class pf_make_immediate_object extends Primitive { pf_make_immediate_object() { super("make-immediate-object", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject[] args) { Symbol.WARN.getSymbolFunction() .execute(new SimpleString("JAVA:MAKE-IMMEDIATE-OBJECT is deprecated.")); if (args.length < 1) error(new WrongNumberOfArgumentsException(this, 1, -1)); LispObject object = args[0]; if (args.length > 1) { LispObject type = args[1]; if (type == Keyword.BOOLEAN) { if (object == NIL) return JavaObject.getInstance(Boolean.FALSE); else return JavaObject.getInstance(Boolean.TRUE); } if (type == Keyword.REF) { if (object == NIL) return JavaObject.getInstance(null); else error(new LispError("MAKE-IMMEDIATE-OBJECT: not implemented")); } // other special cases come here } return JavaObject.getInstance(object.javaInstance()); } }; private static final Primitive JNULL_REF_P = new pf_jnull_ref_p(); @DocString(name="jnull-ref-p", args="object", doc="Returns a non-NIL value when the JAVA-OBJECT `object` is `null`,\n" + "or signals a TYPE-ERROR condition if the object isn't of\n" + "the right type.") private static final class pf_jnull_ref_p extends Primitive { pf_jnull_ref_p() { super("jnull-ref-p", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject ref) { if (ref instanceof JavaObject) { JavaObject jref = (JavaObject)ref; return (jref.javaInstance() == null) ? T : NIL; } else return Lisp.type_error(ref, Symbol.JAVA_OBJECT); } }; private static final Primitive JAVA_OBJECT_P = new pf_java_object_p(); @DocString(name="java-object-p", args="object", doc="Returns T if OBJECT is a JAVA-OBJECT.") private static final class pf_java_object_p extends Primitive { pf_java_object_p() { super("java-object-p", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject arg) { return (arg instanceof JavaObject) ? T : NIL; } }; private static final Primitive JOBJECT_LISP_VALUE = new pf_jobject_lisp_value(); @DocString(name="jobject-lisp-value", args="java-object", doc="Attempts to coerce JAVA-OBJECT into a Lisp object.") private static final class pf_jobject_lisp_value extends Primitive { pf_jobject_lisp_value() { super("jobject-lisp-value", PACKAGE_JAVA, true, "java-object"); } @Override public LispObject execute(LispObject arg) { return JavaObject.getInstance(arg.javaInstance(), true); } }; private static final Primitive JCOERCE = new pf_jcoerce(); @DocString(name="jcoerce", args="object intended-class", doc="Attempts to coerce OBJECT into a JavaObject of class INTENDED-CLASS." + " Raises a TYPE-ERROR if no conversion is possible.") private static final class pf_jcoerce extends Primitive { pf_jcoerce() { super("jcoerce", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject javaObject, LispObject intendedClass) { Object o = javaObject.javaInstance(); Class c = javaClass(intendedClass); try { return JavaObject.getInstance(o, c); } catch(ClassCastException e) { return type_error(javaObject, new SimpleString(c.getName())); } } }; private static final Primitive JRUN_EXCEPTION_PROTECTED = new pf_jrun_exception_protected(); @DocString(name="jrun-exception-protected", args="closure", doc="Invokes the function CLOSURE and returns the result. "+ "Signals an error if stack or heap exhaustion occurs.") private static final class pf_jrun_exception_protected extends Primitive { pf_jrun_exception_protected() { super("jrun-exception-protected", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject closure) { Function fun = checkFunction(closure); try { return LispThread.currentThread().execute(closure); } catch (OutOfMemoryError oom) { return error(new StorageCondition("Out of memory " + oom.getMessage())); } catch (StackOverflowError oos) { oos.printStackTrace(); return error(new StorageCondition("Stack overflow.")); } } }; private static Class classForName(String className) { return classForName(className, JavaClassLoader.getPersistentInstance()); } private static Class classForName(String className, ClassLoader classLoader) { try { if (!className.endsWith("[]")) { return Class.forName(className, true, classLoader); } else { // if (className.startsWith("byte")) { return Class.forName("[B"); } else if (className.startsWith("char")) { return Class.forName("[C"); } else if (className.startsWith("double")) { return Class.forName("[D"); } else if (className.startsWith("float")) { return Class.forName("[F"); } else if (className.startsWith("int")) { return Class.forName("[I"); } else if (className.startsWith("long")) { return Class.forName("[J"); } else if (className.startsWith("short")) { return Class.forName("[S"); } else if (className.startsWith("boolean")) { return Class.forName("[Z"); } else { final String arrayTypeName = "[L" + className.substring(0, className.length() - 2) + ";"; return Class.forName(arrayTypeName); } } } catch (ClassNotFoundException e) { error(new LispError("Class not found: " + className)); // Not reached. return null; } } private static Class javaClass(LispObject obj) { return javaClass(obj, JavaClassLoader.getCurrentClassLoader()); } // Supports Java primitive types too. static Class javaClass(LispObject obj, ClassLoader classLoader) { if (obj instanceof AbstractString || obj instanceof Symbol) { String s = javaString(obj); if (s.equals("boolean")) return Boolean.TYPE; if (s.equals("byte")) return Byte.TYPE; if (s.equals("char")) return Character.TYPE; if (s.equals("short")) return Short.TYPE; if (s.equals("int")) return Integer.TYPE; if (s.equals("long")) return Long.TYPE; if (s.equals("float")) return Float.TYPE; if (s.equals("double")) return Double.TYPE; // Not a primitive Java type. Class c; c = classForName(s, classLoader); if (c == null) error(new LispError(s + " does not designate a Java class.")); return c; } // It's not a string, so it must be a JavaObject. final JavaObject javaObject; if (obj instanceof JavaObject) { javaObject = (JavaObject) obj; } else { type_error(obj, list(Symbol.OR, Symbol.STRING, Symbol.JAVA_OBJECT)); // Not reached. return null; } final Object javaObjectgetObject = javaObject.getObject(); if (javaObjectgetObject instanceof Class) { return (Class) javaObjectgetObject; } error(new LispError(obj.princToString() + " does not designate a Java class.")); return null; } static final String getMessage(Throwable t) { String message = t.getMessage(); if (message == null || message.length() == 0) message = t.getClass().getName(); return message; } // FIXME: better handled as a Lisp symbol? With a Java enum, the // compiler probably has a better chance to optimize. public static class Buffers { public enum AllocationPolicy { PRIMITIVE_ARRAY, NIO; }; public static AllocationPolicy active = AllocationPolicy.NIO; } } abcl-src-1.9.0/src/org/armedbear/lisp/JavaBeans.java0100644 0000000 0000000 00000012464 14223403213 020703 0ustar000000000 0000000 /* * Java.java * * Copyright (C) 2002-2006 Peter Graves, Andras Simon * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; public final class JavaBeans { private static final Primitive JGET_PROPERTY_VALUE = new pf__jget_property_value(); @DocString(name="%jget-propety-value", args="java-object property-name", doc="Gets a JavaBeans property on JAVA-OBJECT.\n" + "SYSTEM-INTERNAL: Use jproperty-value instead.") private static final class pf__jget_property_value extends Primitive { pf__jget_property_value() { super("%jget-property-value", PACKAGE_JAVA, false, "java-object property-name"); } @Override public LispObject execute(LispObject javaObject, LispObject propertyName) { try { Object obj = javaObject.javaInstance(); PropertyDescriptor pd = getPropertyDescriptor(obj, propertyName); Object value = pd.getReadMethod().invoke(obj); if(value instanceof LispObject) { return (LispObject) value; } else if(value != null) { return JavaObject.getInstance(value, true); } else { return NIL; } } catch (Exception e) { return error(new JavaException(e)); } } }; private static final Primitive JSET_PROPERTY_VALUE = new pf__jset_property_value(); @DocString(name="%jset-propety-value", args="java-object property-name value", doc="Sets a JavaBean property on JAVA-OBJECT.\n" + "SYSTEM-INTERNAL: Use (setf jproperty-value) instead.") private static final class pf__jset_property_value extends Primitive { pf__jset_property_value() { super("%jset-property-value", PACKAGE_JAVA, false, "java-object property-name value"); } @Override public LispObject execute(LispObject javaObject, LispObject propertyName, LispObject value) { Object obj = null; try { obj = javaObject.javaInstance(); PropertyDescriptor pd = getPropertyDescriptor(obj, propertyName); Object jValue; //TODO maybe we should do this in javaInstance(Class) if(value instanceof JavaObject) { jValue = value.javaInstance(); } else { if(Boolean.TYPE.equals(pd.getPropertyType()) || Boolean.class.equals(pd.getPropertyType())) { jValue = value != NIL; } else { jValue = value != NIL ? value.javaInstance() : null; } } pd.getWriteMethod().invoke(obj, jValue); return value; } catch (Exception e) { return error(new JavaException(e)); } } }; static PropertyDescriptor getPropertyDescriptor(Object obj, LispObject propertyName) throws IntrospectionException { String prop = ((AbstractString) propertyName).getStringValue(); BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); for(PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { if(pd.getName().equals(prop)) { return pd; } } error(new LispError("Property " + prop + " not found in " + obj)); return null; // not reached } } abcl-src-1.9.0/src/org/armedbear/lisp/JavaClassLoader.java0100644 0000000 0000000 00000031021 14202767264 022055 0ustar000000000 0000000 /* * JavaClassLoader.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; public class JavaClassLoader extends URLClassLoader { private static JavaClassLoader persistentInstance; public static boolean checkPreCompiledClassLoader = true; public Class loadClass(String name) throws ClassNotFoundException { if (checkPreCompiledClassLoader) { Class c = findPrecompiledClassOrNull(name); if (c != null) { return c; } } return loadClass(name, false); } /** * Returns a class loaded by the system or bootstrap class loader; * or return null if not found. * * On AOT systems like GCJ and IKVM this means a class implemented in ASM or CLR * * like findLoadedClass it does not throw an exception if a class is not found */ public Class findPrecompiledClassOrNull(String name) { ClassLoader ourCL = JavaClassLoader.class.getClassLoader(); while (ourCL != null) { try { return Class.forName(name, true, ourCL); } catch (ClassNotFoundException cnf) { } ourCL = ourCL.getParent(); } try { return findSystemClass(name); } catch (ClassNotFoundException e) { return null; } } public byte[] getFunctionClassBytes(String name) { Pathname pathname = (Pathname)Pathname.create(name.substring("org/armedbear/lisp/".length()) + "." + Lisp._COMPILE_FILE_CLASS_EXTENSION_.symbolValue().getStringValue()); return readFunctionBytes(pathname); } public byte[] getFunctionClassBytes(Class functionClass) { String className = functionClass.getName(); try { String ext = Lisp._COMPILE_FILE_CLASS_EXTENSION_.symbolValue().getStringValue(); InputStream is = getResourceAsStream(className.replace('.', '/') + "." + ext); if (is != null) { byte[] imgDataBa = new byte[(int) is.available()]; DataInputStream dataIs = new DataInputStream(is); dataIs.readFully(imgDataBa); return imgDataBa; } } catch (IOException e) { } return getFunctionClassBytes(className); } final public byte[] getFunctionClassBytes(Function f) { byte[] b = getFunctionClassBytes(f.getClass()); f.setClassBytes(b); return b; } private static Set packages = Collections.synchronizedSet(new HashSet()); public JavaClassLoader() { this(JavaClassLoader.class.getClassLoader()); } public JavaClassLoader(ClassLoader parent) { super(new URL[] {}, parent); } public JavaClassLoader(JavaClassLoader parent) { super(new URL[] {}, (ClassLoader)parent); } public JavaClassLoader(URL[] classpath, ClassLoader parent) { super(classpath, parent); } public static JavaClassLoader getPersistentInstance() { return getPersistentInstance(null); } public static JavaClassLoader getPersistentInstance(String packageName) { if (persistentInstance == null) persistentInstance = new JavaClassLoader(); definePackage(packageName); return persistentInstance; } private static void definePackage(String packageName) { if (packageName != null && !packages.contains(packageName)) { persistentInstance.definePackage(packageName,"","1.0","","","1.0","",null); packages.add(packageName); } } public Class loadClassFromByteArray(byte[] classbytes) { return loadClassFromByteArray(null, classbytes); } public Class loadClassFromByteArray(String className, byte[] classbytes) { try { long length = classbytes.length; if (length < Integer.MAX_VALUE) { Class c = defineLispClass(className, classbytes, 0, (int) length); if (c != null) { resolveClass(c); return c; } } } catch (LinkageError e) { throw e; } catch (Throwable t) { Debug.trace(t); } return null; } protected final Class defineLispClass(String name, byte[] b, int off, int len) throws ClassFormatError { ///if (checkPreCompiledClassLoader) Debug.trace("DEFINE JAVA CLASS " + name + " " + len); return defineClass(name, b, off, len); } public Class loadClassFromByteArray(String className, byte[] bytes, int offset, int length) { try { Class c = defineLispClass(className, bytes, offset, length); if (c != null) { resolveClass(c); return c; } } catch (VerifyError e) { error(new LispError("Class verification failed: " + e.getMessage())); } catch (Throwable t) { Debug.trace(t); } return null; } @Override public void addURL(URL url) { super.addURL(url); } public static final Symbol CLASSLOADER = PACKAGE_JAVA.intern("*CLASSLOADER*"); private static final Primitive GET_DEFAULT_CLASSLOADER = new pf_get_default_classloader(); private static final class pf_get_default_classloader extends Primitive { private final LispObject defaultClassLoader = new JavaObject(new JavaClassLoader()); pf_get_default_classloader() { super("get-default-classloader", PACKAGE_JAVA, true, ""); } @Override public LispObject execute() { return defaultClassLoader; } }; // ### make-classloader &optional parent => java-class-loader private static final Primitive MAKE_CLASSLOADER = new pf_make_classloader(); private static final class pf_make_classloader extends Primitive { pf_make_classloader() { super("make-classloader", PACKAGE_JAVA, true, "&optional parent"); } @Override public LispObject execute() { return new JavaObject(new JavaClassLoader(getCurrentClassLoader())); } @Override public LispObject execute(LispObject parent) { return new JavaObject(new JavaClassLoader((ClassLoader) parent.javaInstance(ClassLoader.class))); } }; // ### dump-classpath &optional classloader => list-of-pathname-lists private static final Primitive DUMP_CLASSPATH = new pf_dump_classpath(); private static final class pf_dump_classpath extends Primitive { pf_dump_classpath() { super("dump-classpath", PACKAGE_JAVA, true, "&optional classloader"); } @Override public LispObject execute() { return execute(new JavaObject(getCurrentClassLoader())); } @Override public LispObject execute(LispObject classloader) { LispObject list = NIL; Object o = classloader.javaInstance(); while(o instanceof ClassLoader) { ClassLoader cl = (ClassLoader) o; list = list.push(dumpClassPath(cl)); o = cl.getParent(); } return list.nreverse(); } }; private static final Primitive GET_CURRENT_CLASSLOADER = new pf_get_current_classloader(); @DocString(name="get-current-classloader") private static final class pf_get_current_classloader extends Primitive { pf_get_current_classloader() { super("get-current-classloader", PACKAGE_JAVA, true); } @Override public LispObject execute() { return new JavaObject(getCurrentClassLoader()); } }; // ### %add-to-classpath jar-or-jars &optional (classloader (get-current-classloader)) private static final Primitive ADD_TO_CLASSPATH = new pf_add_to_classpath(); private static final class pf_add_to_classpath extends Primitive { pf_add_to_classpath() { super("%add-to-classpath", PACKAGE_JAVA, false, "jar-or-jars &optional (classloader (get-current-classloader))"); } @Override public LispObject execute(LispObject jarOrJars) { return execute(jarOrJars, new JavaObject(getCurrentClassLoader())); } @Override public LispObject execute(LispObject jarOrJars, LispObject classloader) { Object o = classloader.javaInstance(); if(o instanceof JavaClassLoader) { JavaClassLoader jcl = (JavaClassLoader) o; if(jarOrJars instanceof Cons) { while(jarOrJars != NIL) { addURL(jcl, jarOrJars.car()); jarOrJars = jarOrJars.cdr(); } } else { addURL(jcl, jarOrJars); } return T; } else { return error(new TypeError(o + " must be an instance of " + JavaClassLoader.class.getName())); } } }; protected static void addURL(JavaClassLoader jcl, LispObject jar) { URLPathname urlPathname = null; if (jar instanceof URLPathname) { urlPathname = (URLPathname)jar; } else if (jar instanceof Pathname) { urlPathname = URLPathname.createFromFile((Pathname)jar); } else if (jar instanceof AbstractString) { String namestring = jar.getStringValue(); if (!Pathname.isValidURL(namestring)) { Pathname p = Pathname.create(namestring); if (p != null) { urlPathname = URLPathname.create(p); } } else { urlPathname = URLPathname.create(namestring); } } if (urlPathname == null) { error(new TypeError(jar + " must be a pathname designator")); } jcl.addURL(urlPathname.toURL()); } public static LispObject dumpClassPath(ClassLoader o) { if(o instanceof URLClassLoader) { LispObject list = NIL; for(URL u : ((URLClassLoader) o).getURLs()) { list = list.push(URLPathname.create(u)); } return new Cons(new JavaObject(o), list.nreverse()); } else { return new JavaObject(o); } } public static ClassLoader getCurrentClassLoader() { LispObject classLoader = CLASSLOADER.symbolValueNoThrow(); if(classLoader != null) { return (ClassLoader) classLoader.javaInstance(ClassLoader.class); } else { return Lisp.class.getClassLoader(); } } } abcl-src-1.9.0/src/org/armedbear/lisp/JavaException.java0100644 0000000 0000000 00000006676 14202767264 021641 0ustar000000000 0000000 /* * JavaException.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.PrintWriter; import java.io.StringWriter; public class JavaException extends LispError { private final Throwable throwable; public JavaException(Throwable throwable) { super(StandardClass.JAVA_EXCEPTION); Debug.assertTrue(slots.length == 3); Debug.assertTrue(throwable != null); this.throwable = throwable; setInstanceSlotValue(Symbol.CAUSE, new JavaObject(throwable)); setFormatControl("Java exception: ~A."); setFormatArguments(new Cons(new JavaObject(throwable))); } @Override public LispObject typeOf() { return Symbol.JAVA_EXCEPTION; } @Override public LispObject classOf() { return StandardClass.JAVA_EXCEPTION; } @Override public LispObject typep(LispObject type) { if (type == Symbol.JAVA_EXCEPTION) return T; if (type == StandardClass.JAVA_EXCEPTION) return T; return super.typep(type); } @Override public String getMessage() { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); throwable.printStackTrace(pw); String s = sw.toString(); final String separator = System.getProperty("line.separator"); if (s.endsWith(separator)) s = s.substring(0, s.length() - separator.length()); return s; } // ### java-exception-cause java-exception => cause protected static final Primitive JAVA_EXCEPTION_CAUSE = new Primitive(Symbol.JAVA_EXCEPTION_CAUSE, "java-exception", "Returns the cause of JAVA-EXCEPTION. (The cause is the Java Throwable\n" + " object that caused JAVA-EXCEPTION to be signalled.)") { @Override public LispObject execute(LispObject arg) { return Symbol.STD_SLOT_VALUE.execute(arg, Symbol.CAUSE); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/JavaObject.java0100644 0000000 0000000 00000063236 14223403213 021064 0ustar000000000 0000000 /* * JavaObject.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.math.BigInteger; import java.util.*; public final class JavaObject extends LispObject implements Serializable { final Object obj; private final Class intendedClass; public JavaObject(Object obj) { this.obj = obj; this.intendedClass = obj != null ? Java.maybeBoxClass(obj.getClass()) : null; } public static final Symbol JAVA_CLASS_JCLASS = PACKAGE_JAVA.intern("JAVA-CLASS-JCLASS"); public static final Symbol JAVA_CLASS = PACKAGE_JAVA.intern("JAVA-CLASS"); public static final Symbol ENSURE_JAVA_CLASS = PACKAGE_JAVA.intern("ENSURE-JAVA-CLASS"); /** * Constructs a Java Object with the given intended class, used to access * the object reflectively. If the class represents a primitive type, * the corresponding wrapper type is used instead. * @throws ClassCastException if the object is not an instance of the * intended class. */ public JavaObject(Object obj, Class intendedClass) { if(obj != null && intendedClass == null) { intendedClass = obj.getClass(); } if(intendedClass != null) { intendedClass = Java.maybeBoxClass(intendedClass); if(!intendedClass.isInstance(obj)) { if (intendedClass.equals(java.lang.Byte.class) && obj instanceof java.lang.Number) { // Maps any number to two's complement 8bit byte representation // ??? Is this a reasonable thing? this.obj = ((java.lang.Number)obj).byteValue(); this.intendedClass = intendedClass; return; } throw new ClassCastException(obj + " can not be cast to " + intendedClass); } } this.obj = obj; this.intendedClass = intendedClass; } @Override public LispObject typeOf() { return Symbol.JAVA_OBJECT; } @Override public LispObject classOf() { if(obj == null) { return BuiltInClass.JAVA_OBJECT; } else { return ENSURE_JAVA_CLASS.execute(new JavaObject(obj.getClass())); } } @Override public LispObject typep(LispObject type) { if (type == Symbol.JAVA_OBJECT) return T; if (type == BuiltInClass.JAVA_OBJECT) return T; LispObject cls = NIL; if(type instanceof Symbol) { cls = LispClass.findClass(type, false); } if(cls == NIL) { cls = type; } if(cls.typep(LispClass.findClass(JAVA_CLASS, false)) != NIL) { if(obj != null) { Class c = (Class) JAVA_CLASS_JCLASS.execute(cls).javaInstance(); return c.isAssignableFrom(obj.getClass()) ? T : NIL; } else { return T; } } else if(cls == BuiltInClass.SEQUENCE) { //This information is replicated here from java.lisp; it is a very //specific case, not worth implementing CPL traversal in typep if(java.util.List.class.isInstance(obj) || java.util.Set.class.isInstance(obj)) { return T; } } return super.typep(type); } @Override public LispObject STRING() { return new SimpleString(obj != null? obj.toString(): "null"); } public final Object getObject() { return obj; } /** Encapsulates obj, if required. * If obj is a {@link LispObject}, it's returned as-is. * * @param obj Any java object * @return obj or a new JavaObject encapsulating obj */ public final static LispObject getInstance(Object obj) { if (obj == null) return new JavaObject(null); if (obj instanceof LispObject) return (LispObject)obj; return new JavaObject(obj); } /** Encapsulates obj, if required. * If obj is a {@link LispObject}, it's returned as-is. * If not, a java object with the specified intended class is returned. * * @param obj Any java object * @param intendedClass the class that shall be used to access obj * @return obj or a new JavaObject encapsulating obj */ public final static LispObject getInstance(Object obj, Class intendedClass) { if (obj == null) return new JavaObject(null); if (obj instanceof LispObject) return (LispObject)obj; return new JavaObject(obj, intendedClass); } /** Encapsulates obj, if required. * If obj is a {@link LispObject}, it's returned as-is. * If obj is of a type which can be mapped to a lisp type, * an object of the mapped type is returned, if translated is true. * * @param obj * @param translated * @return a LispObject representing or encapsulating obj */ public final static LispObject getInstance(Object obj, boolean translated) { return getInstance(obj, translated, obj != null ? obj.getClass() : null); } /** Encapsulates obj, if required. * If obj is a {@link LispObject}, it's returned as-is. * If obj is of a type which can be mapped to a lisp type, * an object of the mapped type is returned, if translated is true. * * @param obj * @param translated * @param intendedClass the class that shall be used to reflectively * access obj; it is an error for obj not to be * an instance of this class. This parameter is ignored * if translated == true and the object can be * converted to a Lisp object. * @return a LispObject representing or encapsulating obj */ public final static LispObject getInstance(Object obj, boolean translated, Class intendedClass) { if (! translated) return getInstance(obj, intendedClass); if (obj == null) return NIL; if (obj instanceof LispObject) return (LispObject)obj; if (obj instanceof String) return new SimpleString((String)obj); if (obj instanceof Number) { // Number types ordered according to decreasing // estimated chances of occurrance if (obj instanceof Integer) return Fixnum.getInstance(((Integer)obj).intValue()); if (obj instanceof Float) return new SingleFloat((Float)obj); if (obj instanceof Double) return new DoubleFloat((Double)obj); if (obj instanceof Long) return LispInteger.getInstance(((Long)obj).longValue()); if (obj instanceof BigInteger) return Bignum.getInstance((BigInteger)obj); if (obj instanceof Short) return Fixnum.getInstance(((Short)obj).shortValue()); if (obj instanceof Byte) return Fixnum.getInstance(((Byte)obj).byteValue()); // We don't handle BigDecimal: it doesn't map to a Lisp type } if (obj instanceof Boolean) return ((Boolean)obj).booleanValue() ? T : NIL; if (obj instanceof Character) return LispCharacter.getInstance((Character)obj); if (obj instanceof Object[]) { Object[] array = (Object[]) obj; SimpleVector v = new SimpleVector(array.length); for (int i = array.length; i-- > 0;) v.aset(i, JavaObject.getInstance(array[i], translated)); return v; } // TODO // We might want to handle: // - streams // - others? return new JavaObject(obj, intendedClass); } @Override public Object javaInstance() { return obj; } @Override public Object javaInstance(Class c) { if(obj == null) { if(c.isPrimitive()) { throw new NullPointerException("Cannot assign null to " + c); } return obj; } else { c = Java.maybeBoxClass(c); if (c.isAssignableFrom(intendedClass) || c.isInstance(obj)) { // XXX In the case that c.isInstance(obj) should we then // "fix" the intendedClass field with the (presumably) // narrower type of 'obj'? // ME 20100323: I decided not to because a) we don't // know the "proper" class to narrow to (i.e. maybe // there's something "narrower" and b) I'm not sure how // primitive types relate to their boxed // representations. return obj; } else if (c.isArray() && obj.getClass().isArray()) { // ??? only supports conversions to java.lang.Object[] // && c.getComponentType().equals(obj.getClass().getComponentType())) { return obj; } else { return error(new TypeError(intendedClass.getName() + " is not assignable to " + c.getName())); } } } /** Returns the encapsulated Java object for * interoperability with wait, notify, synchronized, etc. * * @return The encapsulated object */ @Override public Object lockableInstance() { return obj; } public Class getIntendedClass() { return intendedClass; } public static final Object getObject(LispObject o) { if (o instanceof JavaObject) return ((JavaObject)o).obj; return // Not reached. type_error(o, Symbol.JAVA_OBJECT); } @Override public final boolean equal(LispObject other) { if (this == other) return true; if (other instanceof JavaObject) return (obj == ((JavaObject)other).obj); return false; } @Override public final boolean equalp(LispObject other) { return equal(other); } @Override public int sxhash() { return obj == null ? 0 : (obj.hashCode() & 0x7ffffff); } public static LispObject JAVA_OBJECT_TO_STRING_LENGTH = LispInteger.getInstance(32); public static final Symbol _JAVA_OBJECT_TO_STRING_LENGTH = exportSpecial("*JAVA-OBJECT-TO-STRING-LENGTH*", PACKAGE_JAVA, JAVA_OBJECT_TO_STRING_LENGTH); static { String doc = "Length to truncate toString() PRINT-OBJECT output for an otherwise " + "unspecialized JAVA-OBJECT. Can be set to NIL to indicate no limit."; _JAVA_OBJECT_TO_STRING_LENGTH .setDocumentation(Symbol.VARIABLE, new SimpleString(doc)); } @Override public String printObject() { if (obj instanceof ControlTransfer) return obj.toString(); final String s; if (obj != null) { Class c = obj.getClass(); StringBuilder sb = new StringBuilder(c.isArray() ? "jarray" : c.getName()); sb.append(' '); try { String ts = obj.toString(); int length = -1; LispObject stringLength = _JAVA_OBJECT_TO_STRING_LENGTH.symbolValueNoThrow(); if (stringLength instanceof Fixnum) { length = Fixnum.getValue(stringLength); } if (length < 0) { sb.append(ts); } else if (ts.length() > length) { // use '....' to not confuse user with PPRINT conventions sb.append(ts.substring(0, length)).append("...."); } else { sb.append(ts); } s = sb.toString(); } catch (Exception e) { return serror(new JavaException(e)); } } else { s = "null"; } return unreadableString(s); } @Override public LispObject getDescription() { return new SimpleString(describeJavaObject(this)); } @Override public LispObject getParts() { if(obj != null) { LispObject parts = NIL; parts = parts.push(new Cons("Java class", new JavaObject(obj.getClass()))); if (intendedClass != null) { parts = parts.push(new Cons("intendedClass", new SimpleString(intendedClass.getCanonicalName()))); } if (obj.getClass().isArray()) { int length = Array.getLength(obj); for (int i = 0; i < length; i++) { parts = parts .push(new Cons(new SimpleString(String.valueOf(i)), JavaObject.getInstance(Array.get(obj, i)))); } } else { parts = Symbol.NCONC.execute(parts, getInspectedFields()); } if (obj instanceof java.lang.Class) { Class o = (java.lang.Class)obj; try { Class[] classes = o.getClasses(); LispObject classesList = NIL; for (int i = 0; i < classes.length; i++) { classesList = classesList.push(JavaObject.getInstance(classes[i])); } if (!classesList.equals(NIL)) { parts = parts .push(new Cons("Member classes", classesList.nreverse())); } } catch (SecurityException e) { Debug.trace(e); } Class[] interfaces = o.getInterfaces(); LispObject interfacesList = NIL; for (int i = 0; i < interfaces.length; i++) { interfacesList = interfacesList.push(JavaObject.getInstance(interfaces[i])); } if (!interfacesList.equals(NIL)) { parts = parts .push(new Cons("Interfaces", interfacesList.nreverse())); } LispObject superclassList = NIL; Class superclass = o.getSuperclass(); while (superclass != null) { superclassList = superclassList.push(JavaObject.getInstance(superclass)); superclass = superclass.getSuperclass(); } if (!superclassList.equals(NIL)) { parts = parts .push(new Cons("Superclasses", superclassList.nreverse())); } } return parts.nreverse(); } else { return NIL; } } private LispObject getInspectedFields() { final LispObject[] acc = new LispObject[] { NIL }; doClassHierarchy(obj.getClass(), new Function() { @Override public LispObject execute(LispObject arg) { //No possibility of type error - we're mapping this function //over a list of classes Class c = (Class) arg.javaInstance(); for(Field f : c.getDeclaredFields()) { LispObject value = NIL; try { if(!f.isAccessible()) { f.setAccessible(true); } value = JavaObject.getInstance(f.get(obj)); } catch(Exception e) {} acc[0] = acc[0].push(new Cons(f.getName(), value)); } return acc[0]; } }); return acc[0].nreverse(); } /** * Executes a function repeatedly over the minimal subtree of the * Java class hierarchy which contains every class in . */ private static void doClassHierarchy(Collection> classes, LispObject callback, Set> visited) { Collection> newClasses = new LinkedList>(); for(Class clss : classes) { if(clss == null) { continue; } if(!visited.contains(clss)) { callback.execute(JavaObject.getInstance(clss, true)); visited.add(clss); } if(!visited.contains(clss.getSuperclass())) { newClasses.add(clss.getSuperclass()); } for(Class iface : clss.getInterfaces()) { if (!visited.contains(iface)) { newClasses.add(iface); } } } if(!newClasses.isEmpty()) { doClassHierarchy(newClasses, callback, visited); } } /** * Executes a function recursively over and its superclasses and * interfaces. */ public static void doClassHierarchy(Class clss, LispObject callback) { if (clss != null) { Set> visited = new HashSet>(); Collection> classes = new ArrayList>(1); classes.add(clss); doClassHierarchy(classes, callback, visited); } } public static LispObject mapcarClassHierarchy(Class clss, final LispObject fn) { final LispObject[] acc = new LispObject[] { NIL }; doClassHierarchy(clss, new Function() { @Override public LispObject execute(LispObject arg) { acc[0] = acc[0].push(fn.execute(arg)); return acc[0]; } }); return acc[0].nreverse(); } public static String describeJavaObject(final JavaObject javaObject) { final Object obj = javaObject.getObject(); final StringBuilder sb = new StringBuilder(javaObject.princToString()); sb.append(" is an object of type "); sb.append(Symbol.JAVA_OBJECT.princToString()); sb.append("."); sb.append(System.getProperty("line.separator")); sb.append("The wrapped Java object is "); if (obj == null) { sb.append("null."); } else { sb.append("an "); final Class c = obj.getClass(); String className = c.getName(); if (c.isArray()) { sb.append("array of "); if (className.startsWith("[L") && className.endsWith(";")) { className = className.substring(1, className.length() - 1); sb.append(className); sb.append(" objects"); } else if (className.startsWith("[") && className.length() > 1) { char descriptor = className.charAt(1); final String type; switch (descriptor) { case 'B': type = "bytes"; break; case 'C': type = "chars"; break; case 'D': type = "doubles"; break; case 'F': type = "floats"; break; case 'I': type = "ints"; break; case 'J': type = "longs"; break; case 'S': type = "shorts"; break; case 'Z': type = "booleans"; break; default: type = "unknown type"; } sb.append(type); } sb.append(" with "); final int length = java.lang.reflect.Array.getLength(obj); sb.append(length); sb.append(" element"); if (length != 1) sb.append('s'); sb.append('.'); } else { sb.append("instance of "); sb.append(className); sb.append(':'); sb.append(System.getProperty("line.separator")); sb.append(" \""); sb.append(obj.toString()); sb.append('"'); } } return sb.toString(); } private static final Primitive DESCRIBE_JAVA_OBJECT = new pf_describe_java_object(); @DocString(name="describe-java-object", args="object stream", doc="Print a human friendly description of Java OBJECT to STREAM.") private static final class pf_describe_java_object extends Primitive { pf_describe_java_object() { super("describe-java-object", PACKAGE_JAVA, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (!(first instanceof JavaObject)) return type_error(first, Symbol.JAVA_OBJECT); final Stream stream = checkStream(second); final JavaObject javaObject = (JavaObject) first; stream._writeString(describeJavaObject(javaObject)); return LispThread.currentThread().nothing(); } }; //JAVA-CLASS support //There is no point for this Map to be weak since values keep a reference to the corresponding //key (the Java class). This should not be a problem since Java classes are limited in number - //if they grew indefinitely, the JVM itself would crash. private static final Map, LispObject> javaClassMap = new HashMap, LispObject>(); public static LispObject registerJavaClass(Class javaClass, LispObject classMetaObject) { synchronized (javaClassMap) { javaClassMap.put(javaClass, classMetaObject); return classMetaObject; } } public static LispObject findJavaClass(Class javaClass) { synchronized (javaClassMap) { LispObject c = javaClassMap.get(javaClass); if (c != null) { return c; } else { return NIL; } } } private static final Primitive _FIND_JAVA_CLASS = new Primitive("%find-java-class", PACKAGE_JAVA, false, "class-name-or-class") { public LispObject execute(LispObject arg) { try { if(arg instanceof AbstractString) { return findJavaClass(Class.forName((String) arg.getStringValue())); } else { return findJavaClass((Class) arg.javaInstance()); } } catch (ClassNotFoundException e) { return error(new LispError("Cannot find Java class " + arg.getStringValue())); } } }; private static final Primitive _REGISTER_JAVA_CLASS = new Primitive("%register-java-class", PACKAGE_JAVA, false, "jclass class-metaobject") { public LispObject execute(LispObject jclass, LispObject classMetaObject) { return registerJavaClass((Class) jclass.javaInstance(), classMetaObject); } }; // ### +null+ public final static Symbol NULL = Lisp.exportConstant("+NULL+", PACKAGE_JAVA, new JavaObject(null)); static { String doc = "The JVM null object reference."; NULL.setDocumentation(Symbol.VARIABLE, new SimpleString(doc)); } // ### +true+ public final static Symbol TRUE = Lisp.exportConstant("+TRUE+", PACKAGE_JAVA, new JavaObject(true)); static { String doc = "The JVM primitive value for boolean true."; TRUE.setDocumentation(Symbol.VARIABLE, new SimpleString(doc)); } // ### +false+ public final static Symbol FALSE = Lisp.exportConstant("+FALSE+", PACKAGE_JAVA, new JavaObject(false)); static { String doc = "The JVM primitive value for boolean false."; FALSE.setDocumentation(Symbol.VARIABLE, new SimpleString(doc)); } } abcl-src-1.9.0/src/org/armedbear/lisp/JavaStackFrame.java0100644 0000000 0000000 00000010655 14223403213 021673 0ustar000000000 0000000 /* * JavaStackFrame.java * * Copyright (C) 2009 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import org.armedbear.lisp.protocol.Inspectable; public class JavaStackFrame extends StackFrame implements Inspectable { public final StackTraceElement javaFrame; public JavaStackFrame(StackTraceElement javaFrame) { this.javaFrame = javaFrame; } @Override public LispObject typeOf() { return Symbol.JAVA_STACK_FRAME; } @Override public LispObject classOf() { return BuiltInClass.JAVA_STACK_FRAME; } @Override public String printObject() { final String JAVA_STACK_FRAME = "JAVA-STACK-FRAME"; return unreadableString(JAVA_STACK_FRAME + " " + toLispString().toString()); } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.JAVA_STACK_FRAME) return T; if (typeSpecifier == BuiltInClass.JAVA_STACK_FRAME) return T; return super.typep(typeSpecifier); } static final Symbol CLASS = internKeyword("CLASS"); static final Symbol METHOD = internKeyword("METHOD"); static final Symbol FILE = internKeyword("FILE"); static final Symbol LINE = internKeyword("LINE"); static final Symbol NATIVE_METHOD = internKeyword("NATIVE-METHOD"); public LispObject toLispList() { LispObject result = Lisp.NIL; String fileName; if ( javaFrame == null) return result; result = result.push(CLASS); result = result.push(new SimpleString(javaFrame.getClassName())); result = result.push(METHOD); result = result.push(new SimpleString(javaFrame.getMethodName())); result = result.push(FILE); fileName=javaFrame.getFileName(); if (fileName == null) { result.push(new SimpleString("(Unkown source)")) ; } else { result = result.push(new SimpleString(fileName)) ; } result = result.push(LINE); result = result.push(Fixnum.getInstance(javaFrame.getLineNumber())); if (javaFrame.isNativeMethod()) { result = result.push(NATIVE_METHOD); result = result.push(Symbol.T); } return result.nreverse(); } @Override public SimpleString toLispString() { return new SimpleString(javaFrame.toString()); } @Override public LispObject getParts() { LispObject result = NIL; result = result.push(new Cons("CLASS", new SimpleString(javaFrame.getClassName()))); result = result.push(new Cons("METHOD", new SimpleString(javaFrame.getMethodName()))); result = result.push(new Cons("FILE", new SimpleString(javaFrame.getFileName()))); result = result.push(new Cons("LINE", Fixnum.getInstance(javaFrame.getLineNumber()))); result = result.push(new Cons("NATIVE-METHOD", LispObject.getInstance(javaFrame.isNativeMethod()))); return result.nreverse(); } } abcl-src-1.9.0/src/org/armedbear/lisp/Keyword.java0100644 0000000 0000000 00000021056 14212332540 020474 0ustar000000000 0000000 /* * Keyword.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class Keyword { public static final Symbol ABCL = internKeyword("ABCL"), ABORT = internKeyword("ABORT"), ABSOLUTE = internKeyword("ABSOLUTE"), ADJUSTABLE = internKeyword("ADJUSTABLE"), ALLOW_OTHER_KEYS = internKeyword("ALLOW-OTHER-KEYS"), ANSI_CL = internKeyword("ANSI-CL"), APPEND = internKeyword("APPEND"), ARMEDBEAR = internKeyword("ARMEDBEAR"), BACK = internKeyword("BACK"), BOOLEAN = internKeyword("BOOLEAN"), CAPITALIZE = internKeyword("CAPITALIZE"), CAPITALIZE_FIRST = internKeyword("CAPITALIZE-FIRST"), CASE = internKeyword("CASE"), CATCH = internKeyword("CATCH"), CAUSE = internKeyword("CAUSE"), CHAR = internKeyword("CHAR"), COMMON = internKeyword("COMMON"), COMMON_LISP = internKeyword("COMMON-LISP"), COMPILE_TOPLEVEL = internKeyword("COMPILE-TOPLEVEL"), COUNT_ONLY = internKeyword("COUNT-ONLY"), CREATE = internKeyword("CREATE"), DARWIN = internKeyword("DARWIN"), DATUM = internKeyword("DATUM"), DECLARED = internKeyword("DECLARED"), DEFAULT = internKeyword("DEFAULT"), DEFAULTS = internKeyword("DEFAULTS"), DEVICE = internKeyword("DEVICE"), DIRECTION = internKeyword("DIRECTION"), DIRECTORY = internKeyword("DIRECTORY"), DIRECT_SUPERCLASSES = internKeyword("DIRECT-SUPERCLASSES"), DOWNCASE = internKeyword("DOWNCASE"), ELEMENT_TYPE = internKeyword("ELEMENT-TYPE"), END = internKeyword("END"), ERROR = internKeyword("ERROR"), EXECUTE = internKeyword("EXECUTE"), EXPECTED_TYPE = internKeyword("EXPECTED-TYPE"), EXTERNAL = internKeyword("EXTERNAL"), EXTERNAL_FORMAT = internKeyword("EXTERNAL-FORMAT"), FILL_POINTER = internKeyword("FILL-POINTER"), FORMAT_ARGUMENTS = internKeyword("FORMAT-ARGUMENTS"), FORMAT_CONTROL = internKeyword("FORMAT-CONTROL"), FROM_END = internKeyword("FROM-END"), FREEBSD = internKeyword("FREEBSD"), HOST = internKeyword("HOST"), IF_DOES_NOT_EXIST = internKeyword("IF-DOES-NOT-EXIST"), IF_EXISTS = internKeyword("IF-EXISTS"), INHERITED = internKeyword("INHERITED"), INITIAL_CONTENTS = internKeyword("INITIAL-CONTENTS"), INITIAL_ELEMENT = internKeyword("INITIAL-ELEMENT"), INPUT = internKeyword("INPUT"), INSTANCE = internKeyword("INSTANCE"), INT = internKeyword("INT"), INTERNAL = internKeyword("INTERNAL"), INVERT = internKeyword("INVERT"), IO = internKeyword("IO"), J = internKeyword("J"), // BEGIN deprecated: use "JAVA-" instead JAVA_1_4 = internKeyword("JAVA-1.4"), JAVA_1_5 = internKeyword("JAVA-1.5"), JAVA_1_6 = internKeyword("JAVA-1.6"), JAVA_1_7 = internKeyword("JAVA-1.7"), JAVA_1_8 = internKeyword("JAVA-1.8"), JAVA_1_9 = internKeyword("JAVA-1.9"), // END deprecated KEY = internKeyword("KEY"), KEY_AND_VALUE = internKeyword("KEY-AND-VALUE"), KEY_OR_VALUE = internKeyword("KEY-OR-VALUE"), LINUX = internKeyword("LINUX"), LOAD_TOPLEVEL = internKeyword("LOAD-TOPLEVEL"), LOCAL = internKeyword("LOCAL"), LONG = internKeyword("LONG"), MOP = internKeyword("MOP"), NAME = internKeyword("NAME"), NETBSD = internKeyword("NETBSD"), NEW_VERSION = internKeyword("NEW"), NEWEST = internKeyword("NEWEST"), NICKNAMES = internKeyword("NICKNAMES"), NONE = internKeyword("NONE"), NO_ERROR = internKeyword("NO-ERROR"), OBJECT = internKeyword("OBJECT"), OPENBSD = internKeyword("OPENBSD"), OPERANDS = internKeyword("OPERANDS"), OPERATION = internKeyword("OPERATION"), OUTPUT = internKeyword("OUTPUT"), OVERFLOW = internKeyword("OVERFLOW"), OVERWRITE = internKeyword("OVERWRITE"), PACKAGE = internKeyword("PACKAGE"), PATHNAME = internKeyword("PATHNAME"), PROBE = internKeyword("PROBE"), PREFIX = internKeyword("PREFIX"), // EXT:MAKE-TEMP-FILE PUBLIC = internKeyword("PUBLIC"), PRESERVE = internKeyword("PRESERVE"), REF = internKeyword("REF"), RELATIVE = internKeyword("RELATIVE"), RENAME = internKeyword("RENAME"), RENAME_AND_DELETE = internKeyword("RENAME-AND-DELETE"), SIZE = internKeyword("SIZE"), SOLARIS = internKeyword("SOLARIS"), START = internKeyword("START"), STATUS = internKeyword("STATUS"), STREAM = internKeyword("STREAM"), SUNOS = internKeyword("SUNOS"), SUFFIX = internKeyword("SUFFIX"), // EXT:MAKE-TEMP-FILE SUPERSEDE = internKeyword("SUPERSEDE"), TEST = internKeyword("TEST"), TEST_NOT = internKeyword("TEST-NOT"), TIME = internKeyword("TIME"), TOP_LEVEL = internKeyword("TOP-LEVEL"), TRAPS = internKeyword("TRAPS"), TYPE = internKeyword("TYPE"), UNDERFLOW = internKeyword("UNDERFLOW"), UNIX = internKeyword("UNIX"), UNSPECIFIC = internKeyword("UNSPECIFIC"), UP = internKeyword("UP"), UPCASE = internKeyword("UPCASE"), USE = internKeyword("USE"), VALUE = internKeyword("VALUE"), VERSION = internKeyword("VERSION"), WILD = internKeyword("WILD"), WILD_ERROR_P = internKeyword("WILD-ERROR-P"), WILD_INFERIORS = internKeyword("WILD-INFERIORS"), WINDOWS = internKeyword("WINDOWS"), X86 = internKeyword("X86"), X86_64 = internKeyword("X86-64"), CDR6 = internKeyword("CDR6"); } abcl-src-1.9.0/src/org/armedbear/lisp/LICENSE0100644 0000000 0000000 00000002177 14202767264 017233 0ustar000000000 0000000 The software in this package is distributed under the GNU General Public License (with a special exception described below). A copy of GNU General Public License (GPL) is included in this distribution, in the file COPYING. Linking this software statically or dynamically with other modules is making a combined work based on this software. Thus, the terms and conditions of the GNU General Public License cover the whole combination. As a special exception, the copyright holders of this software give you permission to link this software with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this software. If you modify this software, you may extend this exception to your version of the software, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. abcl-src-1.9.0/src/org/armedbear/lisp/Layout.java0100644 0000000 0000000 00000020755 14202767264 020350 0ustar000000000 0000000 /* * Layout.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.util.concurrent.ConcurrentHashMap; import static org.armedbear.lisp.Lisp.*; public class Layout extends LispObject { private final LispObject lispClass; public final ConcurrentHashMap slotTable; final LispObject[] slotNames; final LispObject sharedSlots; private boolean invalid; public Layout(LispObject lispClass, LispObject instanceSlots, LispObject sharedSlots) { this.lispClass = lispClass; Debug.assertTrue(instanceSlots.listp()); int length = instanceSlots.length(); slotNames = new LispObject[length]; int i = 0; while (instanceSlots != NIL) { slotNames[i++] = instanceSlots.car(); instanceSlots = instanceSlots.cdr(); } Debug.assertTrue(i == length); this.sharedSlots = sharedSlots; slotTable = initializeSlotTable(slotNames); } public Layout(LispObject lispClass, LispObject[] instanceSlotNames, LispObject sharedSlots) { this.lispClass = lispClass; this.slotNames = instanceSlotNames; this.sharedSlots = sharedSlots; slotTable = initializeSlotTable(slotNames); } // Copy constructor. Layout(Layout oldLayout) { lispClass = oldLayout.getLispClass(); slotNames = oldLayout.slotNames; sharedSlots = oldLayout.sharedSlots; slotTable = initializeSlotTable(slotNames); } private ConcurrentHashMap initializeSlotTable(LispObject[] slotNames) { ConcurrentHashMap ht = new ConcurrentHashMap(slotNames.length); for (int i = slotNames.length; i-- > 0;) ht.put(slotNames[i], Fixnum.getInstance(i)); return ht; } @Override public LispObject getParts() { LispObject result = NIL; result = result.push(new Cons("class", getLispClass())); for (int i = 0; i < slotNames.length; i++) { result = result.push(new Cons("slot " + i, slotNames[i])); } result = result.push(new Cons("shared slots", sharedSlots)); return result.nreverse(); } public LispObject getLispClass() { return lispClass; } public boolean isInvalid() { return invalid; } public void invalidate() { invalid = true; } public LispObject[] getSlotNames() { return slotNames; } public int getLength() { return slotNames.length; } public LispObject getSharedSlots() { return sharedSlots; } @Override public String printObject() { return unreadableString("LAYOUT"); } // Generates a list of slot definitions for the slot names in this layout. protected LispObject generateSlotDefinitions() { LispObject list = NIL; for (int i = slotNames.length; i-- > 0;) list = list.push(new SlotDefinition(slotNames[i], NIL)); return list; } // ### make-layout private static final Primitive MAKE_LAYOUT = new Primitive("make-layout", PACKAGE_SYS, true, "class instance-slots class-slots") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return new Layout(first, checkList(second), checkList(third)); } }; // ### layout-class private static final Primitive LAYOUT_CLASS = new Primitive("layout-class", PACKAGE_SYS, true, "layout") { @Override public LispObject execute(LispObject arg) { return checkLayout(arg).getLispClass(); } }; // ### layout-length private static final Primitive LAYOUT_LENGTH = new Primitive("layout-length", PACKAGE_SYS, true, "layout") { @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(checkLayout(arg).slotNames.length); } }; public int getSlotIndex(LispObject slotName) { LispObject index = slotTable.get(slotName); if (index != null) return ((Fixnum)index).value; return -1; } public LispObject getSharedSlotLocation(LispObject slotName) { LispObject rest = sharedSlots; while (rest != NIL) { LispObject location = rest.car(); if (location.car() == slotName) return location; rest = rest.cdr(); } return null; } // ### layout-slot-index layout slot-name => index private static final Primitive LAYOUT_SLOT_INDEX = new Primitive("layout-slot-index", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject first, LispObject second) { final LispObject slotNames[] = checkLayout(first).slotNames; for (int i = slotNames.length; i-- > 0;) { if (slotNames[i] == second) return Fixnum.getInstance(i); } return NIL; } }; // ### layout-slot-location layout slot-name => location private static final Primitive LAYOUT_SLOT_LOCATION = new Primitive("layout-slot-location", PACKAGE_SYS, true, "layout slot-name") { @Override public LispObject execute(LispObject first, LispObject second) { final Layout layOutFirst = checkLayout(first); final LispObject slotNames[] = layOutFirst.slotNames; final int limit = slotNames.length; for (int i = 0; i < limit; i++) { if (slotNames[i] == second) return Fixnum.getInstance(i); } // Reaching here, it's not an instance slot. LispObject rest = layOutFirst.sharedSlots; while (rest != NIL) { LispObject location = rest.car(); if (location.car() == second) return location; rest = rest.cdr(); } return NIL; } }; // ### %make-instances-obsolete class => class private static final Primitive _MAKE_INSTANCES_OBSOLETE = new Primitive("%make-instances-obsolete", PACKAGE_SYS, true, "class") { @Override public LispObject execute(LispObject arg) { final LispObject lispClass = arg; LispObject oldLayout; // Non-finalized classes might not have a valid layout, but they do // not have instances either so we can abort. if (lispClass instanceof LispClass) { if (!((LispClass)lispClass).isFinalized()) return arg; oldLayout = ((LispClass)lispClass).getClassLayout(); } else if (lispClass instanceof StandardObject) { if (((StandardObject)arg) .getInstanceSlotValue(StandardClass.symFinalizedP) == NIL) return arg; oldLayout = Symbol.CLASS_LAYOUT.execute(lispClass); } else { return type_error(arg, Symbol.CLASS); } Layout newLayout = new Layout((Layout)oldLayout); if (lispClass instanceof LispClass) ((LispClass)lispClass).setClassLayout(newLayout); else Symbol.CLASS_LAYOUT.getSymbolSetfFunction() .execute(newLayout, lispClass); ((Layout)oldLayout).invalidate(); return arg; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Lisp.java0100644 0000000 0000000 00000300714 14242624277 017776 0ustar000000000 0000000 /* * Lisp.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Method; import java.math.BigInteger; import java.net.URL; import java.nio.charset.Charset; import java.util.Hashtable; import java.util.concurrent.ConcurrentHashMap; public final class Lisp { public static final boolean debug = true; public static boolean cold = true; public static boolean initialized; // Packages. public static final Package PACKAGE_CL = Packages.createPackage("COMMON-LISP", 2048); // EH 10-10-2010: Actual number = 1014 public static final Package PACKAGE_CL_USER = Packages.createPackage("COMMON-LISP-USER", 1024); public static final Package PACKAGE_KEYWORD = Packages.createPackage("KEYWORD", 1024); public static final Package PACKAGE_SYS = Packages.createPackage("SYSTEM", 2048); // EH 10-10-2010: Actual number = 1216 public static final Package PACKAGE_MOP = Packages.createPackage("MOP", 512); // EH 10-10-2010: Actual number = 277 public static final Package PACKAGE_TPL = Packages.createPackage("TOP-LEVEL", 128); // EH 10-10-2010: Actual number = 6 public static final Package PACKAGE_EXT = Packages.createPackage("EXTENSIONS", 256); // EH 10-10-2010: Actual number = 131 public static final Package PACKAGE_JVM = Packages.createPackage("JVM", 2048); // EH 10-10-2010: Actual number = 1518 public static final Package PACKAGE_LOOP = Packages.createPackage("LOOP", 512); // EH 10-10-2010: Actual number = 305 public static final Package PACKAGE_PROF = Packages.createPackage("PROFILER"); public static final Package PACKAGE_JAVA = Packages.createPackage("JAVA"); public static final Package PACKAGE_LISP = Packages.createPackage("LISP"); public static final Package PACKAGE_THREADS = Packages.createPackage("THREADS"); public static final Package PACKAGE_FORMAT = Packages.createPackage("FORMAT"); public static final Package PACKAGE_XP = Packages.createPackage("XP"); public static final Package PACKAGE_PRECOMPILER = Packages.createPackage("PRECOMPILER"); public static final Package PACKAGE_SEQUENCE = Packages.createPackage("SEQUENCE", 128); // EH 10-10-2010: Actual number 62 @DocString(name="nil") public static final Symbol NIL = Nil.NIL; // We need NIL before we can call usePackage(). static { PACKAGE_CL.addNickname("CL"); PACKAGE_CL_USER.addNickname("CL-USER"); PACKAGE_CL_USER.usePackage(PACKAGE_CL); PACKAGE_CL_USER.usePackage(PACKAGE_EXT); PACKAGE_CL_USER.usePackage(PACKAGE_JAVA); PACKAGE_SYS.addNickname("SYS"); PACKAGE_SYS.usePackage(PACKAGE_CL); PACKAGE_SYS.usePackage(PACKAGE_EXT); PACKAGE_MOP.usePackage(PACKAGE_CL); PACKAGE_MOP.usePackage(PACKAGE_EXT); PACKAGE_MOP.usePackage(PACKAGE_SYS); PACKAGE_TPL.addNickname("TPL"); PACKAGE_TPL.usePackage(PACKAGE_CL); PACKAGE_TPL.usePackage(PACKAGE_EXT); PACKAGE_EXT.addNickname("EXT"); PACKAGE_EXT.usePackage(PACKAGE_CL); PACKAGE_EXT.usePackage(PACKAGE_THREADS); PACKAGE_JVM.usePackage(PACKAGE_CL); PACKAGE_JVM.usePackage(PACKAGE_EXT); PACKAGE_JVM.usePackage(PACKAGE_SYS); PACKAGE_LOOP.usePackage(PACKAGE_CL); PACKAGE_PROF.addNickname("PROF"); PACKAGE_PROF.usePackage(PACKAGE_CL); PACKAGE_PROF.usePackage(PACKAGE_EXT); PACKAGE_JAVA.usePackage(PACKAGE_CL); PACKAGE_JAVA.usePackage(PACKAGE_EXT); PACKAGE_LISP.usePackage(PACKAGE_CL); PACKAGE_LISP.usePackage(PACKAGE_EXT); PACKAGE_LISP.usePackage(PACKAGE_SYS); PACKAGE_THREADS.usePackage(PACKAGE_CL); PACKAGE_THREADS.usePackage(PACKAGE_EXT); PACKAGE_THREADS.usePackage(PACKAGE_SYS); PACKAGE_FORMAT.usePackage(PACKAGE_CL); PACKAGE_FORMAT.usePackage(PACKAGE_EXT); PACKAGE_XP.usePackage(PACKAGE_CL); PACKAGE_PRECOMPILER.addNickname("PRE"); PACKAGE_PRECOMPILER.usePackage(PACKAGE_CL); PACKAGE_PRECOMPILER.usePackage(PACKAGE_EXT); PACKAGE_PRECOMPILER.usePackage(PACKAGE_SYS); PACKAGE_SEQUENCE.usePackage(PACKAGE_CL); } // End-of-file marker. public static final LispObject EOF = new LispObject(); // String hash randomization base // Sets a base offset hashing value per JVM session, as an antidote to // http://www.nruns.com/_downloads/advisory28122011.pdf // (Denial of Service through hash table multi-collisions) public static final int randomStringHashBase = (int)(new java.util.Date().getTime()); public static boolean profiling; public static boolean sampling; public static volatile boolean sampleNow; // args must not be null! public static final LispObject funcall(LispObject fun, LispObject[] args, LispThread thread) { thread._values = null; // 26-07-2009: For some reason we cannot "just" call the array version; // it causes an error (Wrong number of arguments for LOOP-FOR-IN) // which is probably a sign of an issue in our design? switch (args.length) { case 0: return thread.execute(fun); case 1: return thread.execute(fun, args[0]); case 2: return thread.execute(fun, args[0], args[1]); case 3: return thread.execute(fun, args[0], args[1], args[2]); case 4: return thread.execute(fun, args[0], args[1], args[2], args[3]); case 5: return thread.execute(fun, args[0], args[1], args[2], args[3], args[4]); case 6: return thread.execute(fun, args[0], args[1], args[2], args[3], args[4], args[5]); case 7: return thread.execute(fun, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); case 8: return thread.execute(fun, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); default: return thread.execute(fun, args); } } public static final LispObject macroexpand(LispObject form, final Environment env, final LispThread thread) { LispObject expanded = NIL; while (true) { form = macroexpand_1(form, env, thread); LispObject[] values = thread._values; if (values[1] == NIL) { values[1] = expanded; return form; } expanded = T; } } public static final LispObject macroexpand_1(final LispObject form, final Environment env, final LispThread thread) { if (form instanceof Cons) { LispObject car = ((Cons)form).car; if (car instanceof Symbol) { LispObject obj = env.lookupFunction(car); if (obj instanceof AutoloadMacro) { // Don't autoload function objects here: // we want that to happen upon the first use. // in case of macro functions, this *is* the first use. Autoload autoload = (Autoload) obj; autoload.load(); obj = car.getSymbolFunction(); } if (obj instanceof SpecialOperator) { obj = get(car, Symbol.MACROEXPAND_MACRO, null); if (obj instanceof Autoload) { Autoload autoload = (Autoload) obj; autoload.load(); obj = get(car, Symbol.MACROEXPAND_MACRO, null); } } if (obj instanceof MacroObject) { LispObject expander = ((MacroObject)obj).expander; if (profiling) if (!sampling) expander.incrementCallCount(); LispObject hook = coerceToFunction(Symbol.MACROEXPAND_HOOK.symbolValue(thread)); return thread.setValues(hook.execute(expander, form, env), T); } } } else if (form instanceof Symbol) { Symbol symbol = (Symbol) form; LispObject obj = env.lookup(symbol); if (obj == null) { obj = symbol.getSymbolMacro(); } if (obj instanceof SymbolMacro) { return thread.setValues(((SymbolMacro)obj).getExpansion(), T); } } // Not a macro. return thread.setValues(form, NIL); } @DocString(name="interactive-eval") private static final Primitive INTERACTIVE_EVAL = new Primitive("interactive-eval", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject object) { final LispThread thread = LispThread.currentThread(); thread.setSpecialVariable(Symbol.MINUS, object); LispObject result; try { result = thread.execute(Symbol.EVAL.getSymbolFunction(), object); } catch (OutOfMemoryError e) { return error(new StorageCondition("Out of memory " + e.getMessage())); } catch (StackOverflowError e) { thread.setSpecialVariable(_SAVED_BACKTRACE_, thread.backtrace(0)); return error(new StorageCondition("Stack overflow.")); } catch (ControlTransfer c) { throw c; } catch (ProcessingTerminated c) { throw c; } catch (IntegrityError c) { throw c; } catch (Throwable t) // ControlTransfer handled above { Debug.trace(t); thread.setSpecialVariable(_SAVED_BACKTRACE_, thread.backtrace(0)); return error(new LispError("Caught " + t + ".")); } Debug.assertTrue(result != null); thread.setSpecialVariable(Symbol.STAR_STAR_STAR, thread.safeSymbolValue(Symbol.STAR_STAR)); thread.setSpecialVariable(Symbol.STAR_STAR, thread.safeSymbolValue(Symbol.STAR)); thread.setSpecialVariable(Symbol.STAR, result); thread.setSpecialVariable(Symbol.PLUS_PLUS_PLUS, thread.safeSymbolValue(Symbol.PLUS_PLUS)); thread.setSpecialVariable(Symbol.PLUS_PLUS, thread.safeSymbolValue(Symbol.PLUS)); thread.setSpecialVariable(Symbol.PLUS, thread.safeSymbolValue(Symbol.MINUS)); LispObject[] values = thread._values; thread.setSpecialVariable(Symbol.SLASH_SLASH_SLASH, thread.safeSymbolValue(Symbol.SLASH_SLASH)); thread.setSpecialVariable(Symbol.SLASH_SLASH, thread.safeSymbolValue(Symbol.SLASH)); if (values != null) { LispObject slash = NIL; for (int i = values.length; i-- > 0;) slash = new Cons(values[i], slash); thread.setSpecialVariable(Symbol.SLASH, slash); } else thread.setSpecialVariable(Symbol.SLASH, new Cons(result)); return result; } }; private static final void pushJavaStackFrames() { final LispThread thread = LispThread.currentThread(); final StackTraceElement[] frames = thread.getJavaStackTrace(); // frames[0] java.lang.Thread.getStackTrace // frames[1] org.armedbear.lisp.LispThread.getJavaStackTrace // frames[2] org.armedbear.lisp.Lisp.pushJavaStackFrames if (frames.length > 5 && frames[3].getClassName().equals("org.armedbear.lisp.Lisp") && frames[3].getMethodName().equals("error") && frames[4].getClassName().startsWith("org.armedbear.lisp.Lisp") && frames[4].getMethodName().equals("eval")) { // Error condition arising from within Lisp.eval(), so no // Java stack frames should be visible to the consumer of the stack abstraction return; } // Search for last Primitive in the StackTrace; that was the // last entry point from Lisp. int last = frames.length - 1; for (int i = 0; i<= last; i++) { if (frames[i].getClassName().startsWith("org.armedbear.lisp.Primitive")) last = i; } // Do not include the first three frames which, as noted above, constitute // the invocation of this method. while (last > 2) { thread.pushStackFrame(new JavaStackFrame(frames[last])); last--; } } public static final LispObject error(LispObject condition) { pushJavaStackFrames(); return Symbol.ERROR.execute(condition); } public static final LispObject stackError() { pushJavaStackFrames(); return Symbol.ERROR.execute(new StorageCondition("Stack overflow.")); } public static final LispObject memoryError(OutOfMemoryError exception) { pushJavaStackFrames(); return Symbol.ERROR.execute(new StorageCondition("Out of memory: " + exception.getMessage())); } public static final int ierror(LispObject condition) { error(condition); return 0; // Not reached } public static final String serror(LispObject condition) { error(condition); return ""; // Not reached } public static final LispObject error(LispObject condition, LispObject message) { pushJavaStackFrames(); return Symbol.ERROR.execute(condition, Keyword.FORMAT_CONTROL, message); } public static final int ierror(LispObject condition, LispObject message) { error(condition, message); return 0; // Not reached } public static final String serror(LispObject condition, LispObject message) { error(condition, message); return ""; // Not reached } public static final LispObject parse_error(String message) { return error(new ParseError(message)); } public static final LispObject simple_error(String formatControl, Object... args) { LispObject lispArgs = NIL; for (int i = 0; i < args.length; i++) { if (args[i] instanceof LispObject) { lispArgs = lispArgs.push((LispObject)args[i]); } else if (args[i] instanceof String) { lispArgs = lispArgs.push(new SimpleString((String)args[i])); } else { lispArgs = lispArgs.push(new JavaObject(args[i])); } } lispArgs = lispArgs.nreverse(); LispObject format = new SimpleString(formatControl); SimpleError s = new SimpleError(format, lispArgs); return error(s); } public static final LispObject type_error(LispObject datum, LispObject expectedType) { return error(new TypeError(datum, expectedType)); } public static final LispObject type_error(String message, LispObject datum, LispObject expectedType) { return error(new TypeError(message, datum, expectedType)); } public static final LispObject program_error(String message) { return error(new ProgramError(message)); } public static final LispObject program_error(LispObject initArgs) { return error(new ProgramError(initArgs)); } public static volatile boolean interrupted; public static volatile LispThread threadToInterrupt; public static synchronized final void setInterrupted(LispThread thread, boolean b) { if (b) { threadToInterrupt = thread; } else { threadToInterrupt = null; } interrupted = b; } public static synchronized final void handleInterrupt() { LispThread currentThread = LispThread.currentThread(); LispThread checkThread = threadToInterrupt; setInterrupted(null, false); if ((currentThread == threadToInterrupt) || (threadToInterrupt == null)) { // Symbol.BREAK.getSymbolFunction().execute(); currentThread.processThreadInterrupts(); } setInterrupted(null, false); } // Used by the compiler. public static final LispObject loadTimeValue(LispObject obj) { final LispThread thread = LispThread.currentThread(); if (Symbol.LOAD_TRUENAME.symbolValue(thread) != NIL) return eval(obj, new Environment(), thread); else return NIL; } public static final LispObject eval(LispObject obj) { return eval(obj, new Environment(), LispThread.currentThread()); } public static final LispObject eval(final LispObject obj, final Environment env, final LispThread thread) { thread._values = null; if (interrupted) handleInterrupt(); if (thread.isDestroyed()) throw new ThreadDestroyed(); if (obj instanceof Symbol) { Symbol symbol = (Symbol)obj; LispObject result; if (symbol.isSpecialVariable()) { if (symbol.constantp()) return symbol.getSymbolValue(); else result = thread.lookupSpecial(symbol); } else if (env.isDeclaredSpecial(symbol)) result = thread.lookupSpecial(symbol); else result = env.lookup(symbol); if (result == null) { result = symbol.getSymbolMacro(); if (result == null) { result = symbol.getSymbolValue(); } if(result == null) { return error(new UnboundVariable(obj)); } } if (result instanceof SymbolMacro) return eval(((SymbolMacro)result).getExpansion(), env, thread); return result; } else if (obj instanceof Cons) { LispObject first = ((Cons)obj).car; if (first instanceof Symbol) { LispObject fun = env.lookupFunction(first); if (fun instanceof SpecialOperator) { if (profiling) if (!sampling) fun.incrementCallCount(); // Don't eval args! return fun.execute(((Cons)obj).cdr, env); } if (fun instanceof MacroObject) { try { thread.envStack.push(new Environment(null,NIL,fun)); return eval(macroexpand(obj, env, thread), env, thread);} finally { thread.envStack.pop(); } } if (fun instanceof Autoload) { Autoload autoload = (Autoload) fun; autoload.load(); return eval(obj, env, thread); } return evalCall(fun != null ? fun : first, ((Cons)obj).cdr, env, thread); } else { if (first instanceof Cons && first.car() == Symbol.LAMBDA) { Closure closure = new Closure(first, env); return evalCall(closure, ((Cons)obj).cdr, env, thread); } else return program_error("Illegal function object: " + first.princToString() + "."); } } else return obj; } public static final int CALL_REGISTERS_MAX = 8; // Also used in JProxy.java. public static final LispObject evalCall(LispObject function, LispObject args, Environment env, LispThread thread) { if (args == NIL) { return thread.execute(function); } LispObject first = eval(args.car(), env, thread); args = ((Cons)args).cdr; if (args == NIL) { thread._values = null; return thread.execute(function, first); } LispObject second = eval(args.car(), env, thread); args = ((Cons)args).cdr; if (args == NIL) { thread._values = null; return thread.execute(function, first, second); } LispObject third = eval(args.car(), env, thread); args = ((Cons)args).cdr; if (args == NIL) { thread._values = null; return thread.execute(function, first, second, third); } LispObject fourth = eval(args.car(), env, thread); args = ((Cons)args).cdr; if (args == NIL) { thread._values = null; return thread.execute(function, first, second, third, fourth); } LispObject fifth = eval(args.car(), env, thread); args = ((Cons)args).cdr; if (args == NIL) { thread._values = null; return thread.execute(function, first, second, third, fourth, fifth); } LispObject sixth = eval(args.car(), env, thread); args = ((Cons)args).cdr; if (args == NIL) { thread._values = null; return thread.execute(function, first, second, third, fourth, fifth, sixth); } LispObject seventh = eval(args.car(), env, thread); args = ((Cons)args).cdr; if (args == NIL) { thread._values = null; return thread.execute(function, first, second, third, fourth, fifth, sixth, seventh); } LispObject eighth = eval(args.car(), env, thread); args = ((Cons)args).cdr; if (args == NIL) { thread._values = null; return thread.execute(function, first, second, third, fourth, fifth, sixth, seventh, eighth); } // More than CALL_REGISTERS_MAX arguments. final int length = args.length() + CALL_REGISTERS_MAX; LispObject[] array = new LispObject[length]; array[0] = first; array[1] = second; array[2] = third; array[3] = fourth; array[4] = fifth; array[5] = sixth; array[6] = seventh; array[7] = eighth; for (int i = CALL_REGISTERS_MAX; i < length; i++) { array[i] = eval(args.car(), env, thread); args = args.cdr(); } thread._values = null; return thread.execute(function, array); } public static final LispObject parseBody(LispObject body, boolean documentationAllowed) { LispObject decls = NIL; LispObject doc = NIL; while (body != NIL) { LispObject form = body.car(); if (documentationAllowed && form instanceof AbstractString && body.cdr() != NIL) { doc = body.car(); documentationAllowed = false; } else if (form instanceof Cons && form.car() == Symbol.DECLARE) decls = new Cons(form, decls); else break; body = body.cdr(); } return list(body, decls.nreverse(), doc); } public static final LispObject parseSpecials(LispObject forms) { LispObject specials = NIL; while (forms != NIL) { LispObject decls = forms.car(); Debug.assertTrue(decls instanceof Cons); Debug.assertTrue(decls.car() == Symbol.DECLARE); decls = decls.cdr(); while (decls != NIL) { LispObject decl = decls.car(); if (decl instanceof Cons && decl.car() == Symbol.SPECIAL) { decl = decl.cdr(); while (decl != NIL) { specials = new Cons(checkSymbol(decl.car()), specials); decl = decl.cdr(); } } decls = decls.cdr(); } forms = forms.cdr(); } return specials; } public static final LispObject progn(LispObject body, Environment env, LispThread thread) { LispObject result = NIL; while (body != NIL) { result = eval(body.car(), env, thread); body = ((Cons)body).cdr; } return result; } public static final LispObject preprocessTagBody(LispObject body, Environment env) { LispObject localTags = NIL; // Tags that are local to this TAGBODY. while (body != NIL) { LispObject current = body.car(); body = ((Cons)body).cdr; if (current instanceof Cons) continue; // It's a tag. env.addTagBinding(current, body); localTags = new Cons(current, localTags); } return localTags; } /** Throws a Go exception to cause a non-local transfer * of control event, after checking that the extent of * the catching tagbody hasn't ended yet. * * This version is used by the compiler. */ public static final LispObject nonLocalGo(LispObject tagbody, LispObject tag) { if (tagbody == null) return error(new ControlError("Unmatched tag " + tag.princToString() + " for GO outside lexical extent.")); throw new Go(tagbody, tag); } /** Throws a Go exception to cause a non-local transfer * of control event, after checking that the extent of * the catching tagbody hasn't ended yet. * * This version is used by the interpreter. */ static final LispObject nonLocalGo(Binding binding, LispObject tag) { if (binding.env.inactive) return error(new ControlError("Unmatched tag " + binding.symbol.princToString() + " for GO outside of lexical extent.")); throw new Go(binding.env, binding.symbol); } /** Throws a Return exception to cause a non-local transfer * of control event, after checking that the extent of * the catching block hasn't ended yet. * * This version is used by the compiler. */ public static final LispObject nonLocalReturn(LispObject blockId, LispObject blockName, LispObject result) { if (blockId == null) return error(new ControlError("Unmatched block " + blockName.princToString() + " for " + "RETURN-FROM outside lexical extent.")); throw new Return(blockId, result); } /** Throws a Return exception to cause a non-local transfer * of control event, after checking that the extent of * the catching block hasn't ended yet. * * This version is used by the interpreter. */ static final LispObject nonLocalReturn(Binding binding, Symbol block, LispObject result) { if (binding == null) { return error(new LispError("No block named " + block.getName() + " is currently visible.")); } if (binding.env.inactive) return error(new ControlError("Unmatched block " + binding.symbol.princToString() + " for RETURN-FROM outside of" + " lexical extent.")); throw new Return(binding.symbol, binding.value, result); } public static final LispObject processTagBody(LispObject body, LispObject localTags, Environment env) { LispObject remaining = body; LispThread thread = LispThread.currentThread(); while (remaining != NIL) { LispObject current = remaining.car(); if (current instanceof Cons) { try { // Handle GO inline if possible. if (((Cons)current).car == Symbol.GO) { if (interrupted) handleInterrupt(); LispObject tag = current.cadr(); Binding binding = env.getTagBinding(tag); if (binding == null) return error(new ControlError("No tag named " + tag.princToString() + " is currently visible.")); else if (memql(tag, localTags)) { if (binding.value != null) { remaining = binding.value; continue; } } throw new Go(binding.env, tag); } eval(current, env, thread); } catch (Go go) { LispObject tag; if (go.getTagBody() == env && memql(tag = go.getTag(), localTags)) { Binding binding = env.getTagBinding(tag); if (binding != null && binding.value != null) { remaining = binding.value; continue; } } throw go; } } remaining = ((Cons)remaining).cdr; } thread._values = null; return NIL; } // Environment wrappers. static final boolean isSpecial(Symbol sym, LispObject ownSpecials) { if (ownSpecials != null) { if (sym.isSpecialVariable()) return true; for (; ownSpecials != NIL; ownSpecials = ownSpecials.cdr()) { if (sym == ownSpecials.car()) return true; } } return false; } public static final void bindArg(LispObject ownSpecials, Symbol sym, LispObject value, Environment env, LispThread thread) { if (isSpecial(sym, ownSpecials)) { env.declareSpecial(sym); thread.bindSpecial(sym, value); } else env.bind(sym, value); } public static void bindArg(boolean special, Symbol sym, LispObject value, Environment env, LispThread thread) { if (special) { env.declareSpecial(sym); thread.bindSpecial(sym, value); } else env.bind(sym, value); } public static LispObject list(LispObject[] obj) { LispObject theList = NIL; if (obj.length > 0) for (int i = obj.length - 1; i >= 0; i--) theList = new Cons(obj[i], theList); return theList; } public static final Cons list(LispObject obj1, LispObject... remaining) { Cons theList = null; if (remaining.length > 0) { theList = new Cons(remaining[remaining.length-1]); for (int i = remaining.length - 2; i >= 0; i--) theList = new Cons(remaining[i], theList); } return (theList == null) ? new Cons(obj1) : new Cons(obj1, theList); } @Deprecated public static final Cons list1(LispObject obj1) { return new Cons(obj1); } @Deprecated public static final Cons list2(LispObject obj1, LispObject obj2) { return new Cons(obj1, new Cons(obj2)); } @Deprecated public static final Cons list3(LispObject obj1, LispObject obj2, LispObject obj3) { return new Cons(obj1, new Cons(obj2, new Cons(obj3))); } @Deprecated public static final Cons list4(LispObject obj1, LispObject obj2, LispObject obj3, LispObject obj4) { return new Cons(obj1, new Cons(obj2, new Cons(obj3, new Cons(obj4)))); } @Deprecated public static final Cons list5(LispObject obj1, LispObject obj2, LispObject obj3, LispObject obj4, LispObject obj5) { return new Cons(obj1, new Cons(obj2, new Cons(obj3, new Cons(obj4, new Cons(obj5))))); } @Deprecated public static final Cons list6(LispObject obj1, LispObject obj2, LispObject obj3, LispObject obj4, LispObject obj5, LispObject obj6) { return new Cons(obj1, new Cons(obj2, new Cons(obj3, new Cons(obj4, new Cons(obj5, new Cons(obj6)))))); } @Deprecated public static final Cons list7(LispObject obj1, LispObject obj2, LispObject obj3, LispObject obj4, LispObject obj5, LispObject obj6, LispObject obj7) { return new Cons(obj1, new Cons(obj2, new Cons(obj3, new Cons(obj4, new Cons(obj5, new Cons(obj6, new Cons(obj7))))))); } @Deprecated public static final Cons list8(LispObject obj1, LispObject obj2, LispObject obj3, LispObject obj4, LispObject obj5, LispObject obj6, LispObject obj7, LispObject obj8) { return new Cons(obj1, new Cons(obj2, new Cons(obj3, new Cons(obj4, new Cons(obj5, new Cons(obj6, new Cons(obj7, new Cons(obj8)))))))); } @Deprecated public static final Cons list9(LispObject obj1, LispObject obj2, LispObject obj3, LispObject obj4, LispObject obj5, LispObject obj6, LispObject obj7, LispObject obj8, LispObject obj9) { return new Cons(obj1, new Cons(obj2, new Cons(obj3, new Cons(obj4, new Cons(obj5, new Cons(obj6, new Cons(obj7, new Cons(obj8, new Cons(obj9))))))))); } // Used by the compiler. public static final LispObject multipleValueList(LispObject result) { LispThread thread = LispThread.currentThread(); LispObject[] values = thread._values; if (values == null) return new Cons(result); thread._values = null; LispObject list = NIL; for (int i = values.length; i-- > 0;) list = new Cons(values[i], list); return list; } // Used by the compiler for MULTIPLE-VALUE-CALLs with a single values form. public static final LispObject multipleValueCall1(LispObject result, LispObject function, LispThread thread) { LispObject[] values = thread._values; thread._values = null; if (values == null) return thread.execute(coerceToFunction(function), result); else return funcall(coerceToFunction(function), values, thread); } public static final void progvBindVars(LispObject symbols, LispObject values, LispThread thread) { for (LispObject list = symbols; list != NIL; list = list.cdr()) { Symbol symbol = checkSymbol(list.car()); LispObject value; if (values != NIL) { value = values.car(); values = values.cdr(); } else { // "If too few values are supplied, the remaining symbols are // bound and then made to have no value." value = null; } thread.bindSpecial(symbol, value); } } public static final LispInteger checkInteger(LispObject obj) { if (obj instanceof LispInteger) return (LispInteger) obj; return (LispInteger) // Not reached. type_error(obj, Symbol.INTEGER); } public static final Symbol checkSymbol(LispObject obj) { if (obj instanceof Symbol) return (Symbol) obj; return (Symbol)// Not reached. type_error(obj, Symbol.SYMBOL); } public static final LispObject checkList(LispObject obj) { if (obj.listp()) return obj; return type_error(obj, Symbol.LIST); } public static final AbstractArray checkArray(LispObject obj) { if (obj instanceof AbstractArray) return (AbstractArray) obj; return (AbstractArray)// Not reached. type_error(obj, Symbol.ARRAY); } public static final AbstractVector checkVector(LispObject obj) { if (obj instanceof AbstractVector) return (AbstractVector) obj; return (AbstractVector)// Not reached. type_error(obj, Symbol.VECTOR); } public static final DoubleFloat checkDoubleFloat(LispObject obj) { if (obj instanceof DoubleFloat) return (DoubleFloat) obj; return (DoubleFloat)// Not reached. type_error(obj, Symbol.DOUBLE_FLOAT); } public static final SingleFloat checkSingleFloat(LispObject obj) { if (obj instanceof SingleFloat) return (SingleFloat) obj; return (SingleFloat)// Not reached. type_error(obj, Symbol.SINGLE_FLOAT); } public static final StackFrame checkStackFrame(LispObject obj) { if (obj instanceof StackFrame) return (StackFrame) obj; return (StackFrame)// Not reached. type_error(obj, Symbol.STACK_FRAME); } static { // ### *gensym-counter* Symbol.GENSYM_COUNTER.initializeSpecial(Fixnum.ZERO); } public static final Symbol gensym(LispThread thread) { return gensym("G", thread); } public static final Symbol gensym(String prefix, LispThread thread) { StringBuilder sb = new StringBuilder(prefix); final Symbol gensymCounter = Symbol.GENSYM_COUNTER; SpecialBinding binding = thread.getSpecialBinding(gensymCounter); final LispObject oldValue; if (binding != null) { oldValue = binding.value; if ((oldValue instanceof Fixnum || oldValue instanceof Bignum) && Fixnum.ZERO.isLessThanOrEqualTo(oldValue)) { binding.value = oldValue.incr(); } else { binding.value = Fixnum.ZERO; error(new TypeError("The value of *GENSYM-COUNTER* was not a nonnegative integer. Old value: " + oldValue.princToString() + " New value: 0")); } } else { // we're manipulating a global resource // make sure we operate thread-safely synchronized (gensymCounter) { oldValue = gensymCounter.getSymbolValue(); if ((oldValue instanceof Fixnum || oldValue instanceof Bignum) && Fixnum.ZERO.isLessThanOrEqualTo(oldValue)) { gensymCounter.setSymbolValue(oldValue.incr()); } else { gensymCounter.setSymbolValue(Fixnum.ZERO); error(new TypeError("The value of *GENSYM-COUNTER* was not a nonnegative integer. Old value: " + oldValue.princToString() + " New value: 0")); } } } // Decimal representation. if (oldValue instanceof Fixnum) sb.append(((Fixnum)oldValue).value); else if (oldValue instanceof Bignum) sb.append(((Bignum)oldValue).value.toString()); return new Symbol(new SimpleString(sb)); } public static final String javaString(LispObject arg) { if (arg instanceof AbstractString) return arg.getStringValue(); if (arg instanceof Symbol) return ((Symbol)arg).getName(); if (arg instanceof LispCharacter) return String.valueOf(new char[] {((LispCharacter)arg).value}); type_error(arg, list(Symbol.OR, Symbol.STRING, Symbol.SYMBOL, Symbol.CHARACTER)); // Not reached. return null; } public static final LispObject number(long n) { if (n >= Integer.MIN_VALUE && n <= Integer.MAX_VALUE) return Fixnum.getInstance((int)n); else return Bignum.getInstance(n); } private static final BigInteger INT_MIN = BigInteger.valueOf(Integer.MIN_VALUE); private static final BigInteger INT_MAX = BigInteger.valueOf(Integer.MAX_VALUE); public static final LispObject number(BigInteger numerator, BigInteger denominator) { if (denominator.signum() == 0) { LispObject operands = new Cons(Bignum.getInstance(numerator), new Cons(Bignum.getInstance(denominator))); LispObject args = new Cons(Keyword.OPERATION, new Cons(Symbol.SLASH, new Cons(Keyword.OPERANDS, new Cons(operands)))); error(new DivisionByZero(args)); } if (denominator.signum() < 0) { numerator = numerator.negate(); denominator = denominator.negate(); } BigInteger gcd = numerator.gcd(denominator); if (!gcd.equals(BigInteger.ONE)) { numerator = numerator.divide(gcd); denominator = denominator.divide(gcd); } if (denominator.equals(BigInteger.ONE)) return number(numerator); else return new Ratio(numerator, denominator); } public static final LispObject number(BigInteger n) { if (n.compareTo(INT_MIN) >= 0 && n.compareTo(INT_MAX) <= 0) return Fixnum.getInstance(n.intValue()); else return Bignum.getInstance(n); } public static final int mod(int number, int divisor) { final int r; try { r = number % divisor; } catch (ArithmeticException e) { error(new ArithmeticError("Division by zero.")); // Not reached. return 0; } if (r == 0) return r; if (divisor < 0) { if (number > 0) return r + divisor; } else { if (number < 0) return r + divisor; } return r; } // Adapted from SBCL. public static final int mix(long x, long y) { long xy = x * 3 + y; return (int) (536870911L & (441516657L ^ xy ^ (xy >> 5))); } // Used by the compiler. public static LispObject readObjectFromString(String s) { return readObjectFromReader(new StringReader(s)); } final static Charset UTF8CHARSET = Charset.forName("UTF-8"); public static LispObject readObjectFromStream(InputStream s) { return readObjectFromReader(new InputStreamReader(s)); } public static LispObject readObjectFromReader(Reader r) { LispThread thread = LispThread.currentThread(); SpecialBindingsMark mark = thread.markSpecialBindings(); try { thread.bindSpecial(Symbol.READ_BASE, LispInteger.getInstance(10)); thread.bindSpecial(Symbol.READ_EVAL, Symbol.T); thread.bindSpecial(Symbol.READ_SUPPRESS, Nil.NIL); // No need to bind read default float format: all floats are written // with their correct exponent markers due to the fact that DUMP-FORM // binds read-default-float-format to NIL // No need to bind the default read table, because the default fasl // read table is used below return new Stream(Symbol.SYSTEM_STREAM, r).read(true, NIL, false, LispThread.currentThread(), Stream.faslReadtable); } finally { thread.resetSpecialBindings(mark); } } @Deprecated public static final LispObject loadCompiledFunction(final String namestring) { Pathname name = (Pathname)Pathname.create(namestring); byte[] bytes = readFunctionBytes(name); if (bytes != null) return loadClassBytes(bytes); return null; } public static byte[] readFunctionBytes(final Pathname name) { final LispThread thread = LispThread.currentThread(); Pathname load = null; LispObject truenameFasl = Symbol.LOAD_TRUENAME_FASL.symbolValue(thread); LispObject truename = Symbol.LOAD_TRUENAME.symbolValue(thread); if (truenameFasl instanceof Pathname) { load = Pathname.mergePathnames(name, (Pathname)truenameFasl, Keyword.NEWEST); } else if (truename instanceof Pathname) { load = Pathname.mergePathnames(name, (Pathname)truename, Keyword.NEWEST); } else { if (!Symbol.PROBE_FILE.execute(name).equals(NIL)) { load = name; } else { load = null; } } InputStream input = null; if (load != null) { input = load.getInputStream(); } else { // Make a last-ditch attempt to load from the boot classpath XXX OSGi hack URL url = null; try { url = Lisp.class.getResource(name.getNamestring()); input = url.openStream(); } catch (IOException e) { System.err.println("Failed to read class bytes from boot class " + url); error(new LispError("Failed to read class bytes from boot class " + url)); } } byte[] bytes = new byte[4096]; try { if (input == null) { Debug.trace("Pathname: " + name); Debug.trace("load: " + load); Debug.trace("LOAD_TRUENAME_FASL: " + truenameFasl); Debug.trace("LOAD_TRUENAME: " + truename); Debug.assertTrue(input != null); } int n = 0; java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); try { while (n >= 0) { n = input.read(bytes, 0, 4096); if (n >= 0) { baos.write(bytes, 0, n); } } } catch (IOException e) { Debug.trace("Failed to read bytes from " + "'" + name.getNamestring() + "'"); return null; } bytes = baos.toByteArray(); } finally { try { input.close(); } catch (IOException e) { Debug.trace("Failed to close InputStream: " + e); } } return bytes; } public static final Function makeCompiledFunctionFromClass(Class c) { try { if (c != null) { Function obj = (Function)c.newInstance(); return obj; } else { return null; } } catch (InstantiationException e) {} // ### FIXME catch (IllegalAccessException e) {} // ### FIXME return null; } public static final LispObject loadCompiledFunction(InputStream in, int size) { byte[] bytes = readFunctionBytes(in, size); if (bytes != null) return loadClassBytes(bytes); else return error(new FileError("Can't read file off stream.")); } private static final byte[] readFunctionBytes(InputStream in, int size) { try { byte[] bytes = new byte[size]; int bytesRemaining = size; int bytesRead = 0; while (bytesRemaining > 0) { int n = in.read(bytes, bytesRead, bytesRemaining); if (n < 0) break; bytesRead += n; bytesRemaining -= n; } in.close(); if (bytesRemaining > 0) Debug.trace("bytesRemaining = " + bytesRemaining); return bytes; } catch (IOException t) { Debug.trace(t); // FIXME: call error()? } return null; } public static final Function loadClassBytes(byte[] bytes) { return loadClassBytes(bytes, new JavaClassLoader()); } public static final Function loadClassBytes(byte[] bytes, JavaClassLoader cl) { Class c = cl.loadClassFromByteArray(null, bytes, 0, bytes.length); Function obj = makeCompiledFunctionFromClass(c); if (obj != null) { obj.setClassBytes(bytes); } return obj; } public static final LispObject makeCompiledClosure(LispObject template, ClosureBinding[] context) { return ((CompiledClosure)template).dup().setContext(context); } public static final String safeWriteToString(LispObject obj) { try { return obj.printObject(); } catch (NullPointerException e) { Debug.trace(e); return "null"; } } public static final boolean isValidSetfFunctionName(LispObject obj) { if (obj instanceof Cons) { Cons cons = (Cons) obj; if (cons.car == Symbol.SETF && cons.cdr instanceof Cons) { Cons cdr = (Cons) cons.cdr; return (cdr.car instanceof Symbol && cdr.cdr == NIL); } } return false; } public static final boolean isValidMacroFunctionName(LispObject obj) { if (obj instanceof Cons) { Cons cons = (Cons) obj; if (cons.car == Symbol.MACRO_FUNCTION && cons.cdr instanceof Cons) { Cons cdr = (Cons) cons.cdr; return (cdr.car instanceof Symbol && cdr.cdr == NIL); } } return false; } public static final LispObject FUNCTION_NAME = list(Symbol.OR, Symbol.SYMBOL, list(Symbol.CONS, list(Symbol.EQL, Symbol.SETF), list(Symbol.CONS, Symbol.SYMBOL, Symbol.NULL))); public static final LispObject UNSIGNED_BYTE_8 = list(Symbol.UNSIGNED_BYTE, Fixnum.constants[8]); public static final LispObject UNSIGNED_BYTE_16 = list(Symbol.UNSIGNED_BYTE, Fixnum.constants[16]); public static final LispObject UNSIGNED_BYTE_32 = list(Symbol.UNSIGNED_BYTE, Fixnum.constants[32]); public static final LispObject UNSIGNED_BYTE_32_MAX_VALUE = Bignum.getInstance(4294967295L); public static final LispObject getUpgradedArrayElementType(LispObject type) { if (type instanceof Symbol) { if (type == Symbol.CHARACTER || type == Symbol.BASE_CHAR || type == Symbol.STANDARD_CHAR) return Symbol.CHARACTER; if (type == Symbol.BIT) return Symbol.BIT; if (type == NIL) return NIL; } if (type == BuiltInClass.CHARACTER) return Symbol.CHARACTER; if (type instanceof Cons) { if (type.equal(UNSIGNED_BYTE_8)) return type; if (type.equal(UNSIGNED_BYTE_16)) return type; if (type.equal(UNSIGNED_BYTE_32)) return type; LispObject car = type.car(); if (car == Symbol.INTEGER) { LispObject lower = type.cadr(); LispObject upper = type.cdr().cadr(); // Convert to inclusive bounds. if (lower instanceof Cons) lower = lower.car().incr(); if (upper instanceof Cons) upper = upper.car().decr(); if (lower.integerp() && upper.integerp()) { if (lower instanceof Fixnum && upper instanceof Fixnum) { int l = ((Fixnum)lower).value; if (l >= 0) { int u = ((Fixnum)upper).value; if (u <= 1) return Symbol.BIT; if (u <= 255) return UNSIGNED_BYTE_8; if (u <= 65535) return UNSIGNED_BYTE_16; return UNSIGNED_BYTE_32; } } if (lower.isGreaterThanOrEqualTo(Fixnum.ZERO)) { if (lower.isLessThanOrEqualTo(UNSIGNED_BYTE_32_MAX_VALUE)) { if (upper.isLessThanOrEqualTo(UNSIGNED_BYTE_32_MAX_VALUE)) return UNSIGNED_BYTE_32; } } } } else if (car == Symbol.EQL) { LispObject obj = type.cadr(); if (obj instanceof Fixnum) { int val = ((Fixnum)obj).value; if (val >= 0) { if (val <= 1) return Symbol.BIT; if (val <= 255) return UNSIGNED_BYTE_8; if (val <= 65535) return UNSIGNED_BYTE_16; return UNSIGNED_BYTE_32; } } else if (obj instanceof Bignum) { if (obj.isGreaterThanOrEqualTo(Fixnum.ZERO)) { if (obj.isLessThanOrEqualTo(UNSIGNED_BYTE_32_MAX_VALUE)) return UNSIGNED_BYTE_32; } } } else if (car == Symbol.MEMBER) { LispObject rest = type.cdr(); while (rest != NIL) { LispObject obj = rest.car(); if (obj instanceof LispCharacter) rest = rest.cdr(); else return T; } return Symbol.CHARACTER; } } return T; } // TODO rename to coerceToJavaChar public static final char coerceToJavaChar(LispObject obj) { return (char)Fixnum.getValue(obj); } public static final byte coerceToJavaByte(LispObject obj) { return (byte)Fixnum.getValue(obj); } public static final int coerceToJavaUnsignedInt(LispObject obj) { return (int) (obj.longValue() & 0xffffffffL); } public static final LispObject coerceFromJavaByte(byte b) { return Fixnum.constants[((int)b) & 0xff]; } public static final LispCharacter checkCharacter(LispObject obj) { if (obj instanceof LispCharacter) return (LispCharacter) obj; return (LispCharacter) // Not reached. type_error(obj, Symbol.CHARACTER); } public static final Package checkPackage(LispObject obj) { if (obj instanceof Package) return (Package) obj; return (Package) // Not reached. type_error(obj, Symbol.PACKAGE); } public static Pathname checkPathname(LispObject obj) { if (obj instanceof Pathname) return (Pathname) obj; return (Pathname) // Not reached. type_error(obj, Symbol.PATHNAME); } public static final Function checkFunction(LispObject obj) { if (obj instanceof Function) return (Function) obj; return (Function) // Not reached. type_error(obj, Symbol.FUNCTION); } public static final Stream checkStream(LispObject obj) { if (obj instanceof Stream) return (Stream) obj; return (Stream) // Not reached. type_error(obj, Symbol.STREAM); } public static final Stream checkCharacterInputStream(LispObject obj) { final Stream stream = checkStream(obj); if (stream.isCharacterInputStream()) return stream; return (Stream) // Not reached. error(new TypeError("The value " + obj.princToString() + " is not a character input stream.")); } public static final Stream checkCharacterOutputStream(LispObject obj) { final Stream stream = checkStream(obj); if (stream.isCharacterOutputStream()) return stream; return (Stream) // Not reached. error(new TypeError("The value " + obj.princToString() + " is not a character output stream.")); } public static final Stream checkBinaryInputStream(LispObject obj) { final Stream stream = checkStream(obj); if (stream.isBinaryInputStream()) return stream; return (Stream) // Not reached. error(new TypeError("The value " + obj.princToString() + " is not a binary input stream.")); } public static final Stream outSynonymOf(LispObject obj) { if (obj instanceof Stream) return (Stream) obj; if (obj == T) return checkCharacterOutputStream(Symbol.TERMINAL_IO.symbolValue()); if (obj == NIL) return checkCharacterOutputStream(Symbol.STANDARD_OUTPUT.symbolValue()); return (Stream) // Not reached. type_error(obj, Symbol.STREAM); } public static final Stream inSynonymOf(LispObject obj) { if (obj instanceof Stream) return (Stream) obj; if (obj == T) return checkCharacterInputStream(Symbol.TERMINAL_IO.symbolValue()); if (obj == NIL) return checkCharacterInputStream(Symbol.STANDARD_INPUT.symbolValue()); return (Stream) // Not reached. type_error(obj, Symbol.STREAM); } public static final void writeByte(int n, LispObject obj) { if (n < 0 || n > 255) type_error(Fixnum.getInstance(n), UNSIGNED_BYTE_8); checkStream(obj)._writeByte(n); } public static final Readtable checkReadtable(LispObject obj) { if (obj instanceof Readtable) return (Readtable) obj; return (Readtable)// Not reached. type_error(obj, Symbol.READTABLE); } public final static AbstractString checkString(LispObject obj) { if (obj instanceof AbstractString) return (AbstractString) obj; return (AbstractString)// Not reached. type_error(obj, Symbol.STRING); } public final static Layout checkLayout(LispObject obj) { if (obj instanceof Layout) return (Layout) obj; return (Layout)// Not reached. type_error(obj, Symbol.LAYOUT); } public static final Readtable designator_readtable(LispObject obj) { if (obj == NIL) obj = STANDARD_READTABLE.symbolValue(); if (obj == null) throw new NullPointerException(); return checkReadtable(obj); } public static final Environment checkEnvironment(LispObject obj) { if (obj instanceof Environment) return (Environment) obj; return (Environment)// Not reached. type_error(obj, Symbol.ENVIRONMENT); } public static final void checkBounds(int start, int end, int length) { if (start < 0 || end < 0 || start > end || end > length) { StringBuilder sb = new StringBuilder("The bounding indices "); sb.append(start); sb.append(" and "); sb.append(end); sb.append(" are bad for a sequence of length "); sb.append(length); sb.append('.'); error(new TypeError(sb.toString())); } } public static final LispObject coerceToFunction(LispObject obj) { if (obj instanceof Function) return obj; if (obj instanceof FuncallableStandardObject) return obj; if (obj instanceof Symbol) { LispObject fun = obj.getSymbolFunction(); if (fun instanceof Function) return (Function) fun; if (fun instanceof FuncallableStandardObject) return fun; } else if (obj instanceof Cons && obj.car() == Symbol.LAMBDA) return new Closure(obj, new Environment()); if (obj instanceof Cons && obj.car() == Symbol.NAMED_LAMBDA) { LispObject name = obj.cadr(); if (name instanceof Symbol || isValidSetfFunctionName(name)) { return new Closure(name, new Cons(Symbol.LAMBDA, obj.cddr()), new Environment()); } return type_error(name, FUNCTION_NAME); } error(new UndefinedFunction(obj)); // Not reached. return null; } // Returns package or throws exception. public static final Package coerceToPackage(LispObject obj) { if (obj instanceof Package) return (Package) obj; String name = javaString(obj); Package pkg = getCurrentPackage().findPackage(name); if (pkg != null) return pkg; error(new PackageError(obj.princToString() + " is not the name of a package.", obj)); // Not reached. return null; } public static Pathname coerceToPathname(LispObject arg) { if (arg instanceof Pathname) return (Pathname) arg; if (arg instanceof AbstractString) return (Pathname)Pathname.create(((AbstractString)arg).toString()); if (arg instanceof FileStream) return ((FileStream)arg).getPathname(); if (arg instanceof JarStream) return ((JarStream)arg).getPathname(); if (arg instanceof URLStream) return ((URLStream)arg).getPathname(); type_error(arg, list(Symbol.OR, Symbol.STRING, Symbol.PATHNAME, Symbol.JAR_PATHNAME, Symbol.URL_PATHNAME, Symbol.FILE_STREAM, Symbol.JAR_STREAM, Symbol.URL_STREAM)); // Not reached. return null; } public static LispObject assq(LispObject item, LispObject alist) { while (alist instanceof Cons) { LispObject entry = ((Cons)alist).car; if (entry instanceof Cons) { if (((Cons)entry).car == item) return entry; } else if (entry != NIL) return type_error(entry, Symbol.LIST); alist = ((Cons)alist).cdr; } if (alist != NIL) return type_error(alist, Symbol.LIST); return NIL; } public static final boolean memq(LispObject item, LispObject list) { while (list instanceof Cons) { if (item == ((Cons)list).car) return true; list = ((Cons)list).cdr; } if (list != NIL) type_error(list, Symbol.LIST); return false; } public static final boolean memql(LispObject item, LispObject list) { while (list instanceof Cons) { if (item.eql(((Cons)list).car)) return true; list = ((Cons)list).cdr; } if (list != NIL) type_error(list, Symbol.LIST); return false; } // Property lists. public static final LispObject getf(LispObject plist, LispObject indicator, LispObject defaultValue) { LispObject list = plist; while (list != NIL) { if (list.car() == indicator) return list.cadr(); if (list.cdr() instanceof Cons) list = list.cddr(); else return error(new TypeError("Malformed property list: " + plist.princToString())); } return defaultValue; } public static final LispObject get(LispObject symbol, LispObject indicator) { LispObject list = checkSymbol(symbol).getPropertyList(); while (list != NIL) { if (list.car() == indicator) return list.cadr(); list = list.cddr(); } return NIL; } public static final LispObject get(LispObject symbol, LispObject indicator, LispObject defaultValue) { LispObject list = checkSymbol(symbol).getPropertyList(); while (list != NIL) { if (list.car() == indicator) return list.cadr(); list = list.cddr(); } return defaultValue; } public static final LispObject put(Symbol symbol, LispObject indicator, LispObject value) { LispObject list = symbol.getPropertyList(); while (list != NIL) { if (list.car() == indicator) { // Found it! LispObject rest = list.cdr(); rest.setCar(value); return value; } list = list.cddr(); } // Not found. symbol.setPropertyList(new Cons(indicator, new Cons(value, symbol.getPropertyList()))); return value; } public static final LispObject putf(LispObject plist, LispObject indicator, LispObject value) { LispObject list = plist; while (list != NIL) { if (list.car() == indicator) { // Found it! LispObject rest = list.cdr(); rest.setCar(value); return plist; } list = list.cddr(); } // Not found. return new Cons(indicator, new Cons(value, plist)); } public static final LispObject remprop(Symbol symbol, LispObject indicator) { LispObject list = checkList(symbol.getPropertyList()); LispObject prev = null; while (list != NIL) { if (!(list.cdr() instanceof Cons)) error(new ProgramError("The symbol " + symbol.princToString() + " has an odd number of items in its property list.")); if (list.car() == indicator) { // Found it! if (prev != null) prev.setCdr(list.cddr()); else symbol.setPropertyList(list.cddr()); return T; } prev = list.cdr(); list = list.cddr(); } // Not found. return NIL; } public static final String format(LispObject formatControl, LispObject formatArguments) { final LispThread thread = LispThread.currentThread(); String control = formatControl.getStringValue(); LispObject[] args = formatArguments.copyToArray(); StringBuffer sb = new StringBuffer(); if (control != null) { final int limit = control.length(); int j = 0; final int NEUTRAL = 0; final int TILDE = 1; int state = NEUTRAL; for (int i = 0; i < limit; i++) { char c = control.charAt(i); if (state == NEUTRAL) { if (c == '~') state = TILDE; else sb.append(c); } else if (state == TILDE) { if (c == 'A' || c == 'a') { if (j < args.length) { LispObject obj = args[j++]; final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, NIL); thread.bindSpecial(Symbol.PRINT_READABLY, NIL); try { sb.append(obj.printObject()); } finally { thread.resetSpecialBindings(mark); } } } else if (c == 'S' || c == 's') { if (j < args.length) { LispObject obj = args[j++]; final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, T); try { sb.append(obj.printObject()); } finally { thread.resetSpecialBindings(mark); } } } else if (c == 'D' || c == 'd') { if (j < args.length) { LispObject obj = args[j++]; final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, NIL); thread.bindSpecial(Symbol.PRINT_RADIX, NIL); thread.bindSpecial(Symbol.PRINT_BASE, Fixnum.constants[10]); try { sb.append(obj.printObject()); } finally { thread.resetSpecialBindings(mark); } } } else if (c == 'X' || c == 'x') { if (j < args.length) { LispObject obj = args[j++]; final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, NIL); thread.bindSpecial(Symbol.PRINT_RADIX, NIL); thread.bindSpecial(Symbol.PRINT_BASE, Fixnum.constants[16]); try { sb.append(obj.printObject()); } finally { thread.resetSpecialBindings(mark); } } } else if (c == '%') { sb.append('\n'); } state = NEUTRAL; } else { // There are no other valid states. Debug.assertTrue(false); } } } return sb.toString(); } public static final Symbol intern(String name, Package pkg) { return pkg.intern(name); } // Used by the compiler. public static final Symbol internInPackage(String name, String packageName) { Package pkg = getCurrentPackage().findPackage(packageName); if (pkg == null) error(new LispError(packageName + " is not the name of a package.")); return pkg.intern(name); } public static final Symbol internKeyword(String s) { return PACKAGE_KEYWORD.intern(s); } // The compiler's object table. static final ConcurrentHashMap objectTable = new ConcurrentHashMap(); public static LispObject recall(String key) { return objectTable.remove(key); } public static LispObject recall(SimpleString key) { return objectTable.remove(key.getStringValue()); } // ### remember public static final Primitive REMEMBER = new Primitive("remember", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject key, LispObject value) { objectTable.put(key.getStringValue(), value); return NIL; } }; public static final Symbol internSpecial(String name, Package pkg, LispObject value) { Symbol symbol = pkg.intern(name); symbol.setSpecial(true); symbol.setSymbolValue(value); return symbol; } public static final Symbol internConstant(String name, Package pkg, LispObject value) { Symbol symbol = pkg.intern(name); symbol.initializeConstant(value); return symbol; } public static final Symbol exportSpecial(String name, Package pkg, LispObject value) { Symbol symbol = pkg.intern(name); pkg.export(symbol); // FIXME Inefficient! symbol.setSpecial(true); symbol.setSymbolValue(value); return symbol; } public static final Symbol exportConstant(String name, Package pkg, LispObject value) { Symbol symbol = pkg.intern(name); pkg.export(symbol); // FIXME Inefficient! symbol.initializeConstant(value); return symbol; } static { String userDir = System.getProperty("user.dir"); if (userDir != null && userDir.length() > 0) { if (userDir.charAt(userDir.length() - 1) != File.separatorChar) userDir = userDir.concat(File.separator); } // This string will be converted to a pathname when Pathname.java is loaded. Symbol.DEFAULT_PATHNAME_DEFAULTS.initializeSpecial(new SimpleString(userDir)); } static { Symbol._PACKAGE_.initializeSpecial(PACKAGE_CL_USER); } public static final Package getCurrentPackage() { return (Package) Symbol._PACKAGE_.symbolValueNoThrow(); } public static final void resetIO(Stream in, Stream out) { stdin = in; stdout = out; Symbol.STANDARD_INPUT.setSymbolValue(stdin); Symbol.STANDARD_OUTPUT.setSymbolValue(stdout); Symbol.ERROR_OUTPUT.setSymbolValue(stdout); Symbol.TRACE_OUTPUT.setSymbolValue(stdout); Symbol.TERMINAL_IO.setSymbolValue(new TwoWayStream(stdin, stdout, true)); Symbol.QUERY_IO.setSymbolValue(new TwoWayStream(stdin, stdout, true)); Symbol.DEBUG_IO.setSymbolValue(new TwoWayStream(stdin, stdout, true)); } // Used in org/armedbear/j/JLisp.java. public static final void resetIO() { resetIO(new Stream(Symbol.SYSTEM_STREAM, System.in, Symbol.CHARACTER, true), new Stream(Symbol.SYSTEM_STREAM, System.out, Symbol.CHARACTER, true)); } public static final TwoWayStream getTerminalIO() { return (TwoWayStream) Symbol.TERMINAL_IO.symbolValueNoThrow(); } public static final Stream getStandardInput() { return (Stream) Symbol.STANDARD_INPUT.symbolValueNoThrow(); } public static final Stream getStandardOutput() { return checkCharacterOutputStream(Symbol.STANDARD_OUTPUT.symbolValue()); } static { Symbol.CURRENT_READTABLE.initializeSpecial(new Readtable()); } // ### +standard-readtable+ // internal symbol public static final Symbol STANDARD_READTABLE = internConstant("+STANDARD-READTABLE+", PACKAGE_SYS, new Readtable()); public static final Readtable currentReadtable() { return (Readtable) Symbol.CURRENT_READTABLE.symbolValue(); } static { Symbol.READ_SUPPRESS.initializeSpecial(NIL); Symbol.DEBUGGER_HOOK.initializeSpecial(NIL); } static { Symbol.MOST_POSITIVE_FIXNUM.initializeConstant(Fixnum.getInstance(Integer.MAX_VALUE)); Symbol.MOST_NEGATIVE_FIXNUM.initializeConstant(Fixnum.getInstance(Integer.MIN_VALUE)); Symbol.MOST_POSITIVE_JAVA_LONG.initializeConstant(Bignum.getInstance(Long.MAX_VALUE)); Symbol.MOST_NEGATIVE_JAVA_LONG.initializeConstant(Bignum.getInstance(Long.MIN_VALUE)); } public static void exit(int status) { Interpreter interpreter = Interpreter.getInstance(); if (interpreter != null) interpreter.kill(status); } // ### t public static final Symbol T = Symbol.T; static { T.initializeConstant(T); } static { Symbol.READ_EVAL.initializeSpecial(T); } // // ### *features* // static { final String osName = System.getProperty("os.name"); final String javaVersion = System.getProperty("java.version"); final String osArch = System.getProperty("os.arch"); // Common features LispObject featureList = list(Keyword.ARMEDBEAR, Keyword.ABCL, Keyword.COMMON_LISP, Keyword.ANSI_CL, Keyword.CDR6, Keyword.MOP, internKeyword("PACKAGE-LOCAL-NICKNAMES")); // add the contents of version as a keyword symbol regardless of runtime value featureList = featureList.push(internKeyword("JVM-" + javaVersion)); { String platformVersion = null; if (javaVersion.startsWith("1.")) { // pre int i = javaVersion.indexOf(".", 2); platformVersion = javaVersion.substring(2, i); } else { int i = javaVersion.indexOf("."); if (i >= 0) { platformVersion = javaVersion.substring(0, i); } else { platformVersion = javaVersion; } } // We wish to declare an integer Java version, but specialized // builds can suffix further information upon the java.version // property. try { Integer.parseInt(javaVersion); } catch (NumberFormatException e) { for (int i = 0; i < javaVersion.length(); i++) { char c = javaVersion.charAt(i); // Unicode? if (!Character.isDigit(c)) { // Push the non-conforming keyword for completeness featureList.push(internKeyword("JAVA-" + javaVersion)); platformVersion = javaVersion.substring(0, i); break; } } } featureList = featureList.push(internKeyword("JAVA-" + platformVersion)); } { // Deprecated java version if (javaVersion.startsWith("1.5")) { featureList = new Cons(Keyword.JAVA_1_5, featureList); } else if (javaVersion.startsWith("1.6")) { featureList = new Cons(Keyword.JAVA_1_6, featureList); } else if (javaVersion.startsWith("1.7")) { featureList = new Cons(Keyword.JAVA_1_7, featureList); } else if (javaVersion.startsWith("1.8")) { featureList = new Cons(Keyword.JAVA_1_8, featureList); } } // OS type if (osName.startsWith("Linux")) featureList = Primitives.APPEND.execute(list(Keyword.UNIX, Keyword.LINUX), featureList); else if (osName.startsWith("SunOS")) featureList = Primitives.APPEND.execute(list(Keyword.UNIX, Keyword.SUNOS, Keyword.SOLARIS), featureList); else if (osName.startsWith("Mac OS X") || osName.startsWith("Darwin")) featureList = Primitives.APPEND.execute(list(Keyword.UNIX, Keyword.DARWIN), featureList); else if (osName.startsWith("FreeBSD")) featureList = Primitives.APPEND.execute(list(Keyword.UNIX, Keyword.FREEBSD), featureList); else if (osName.startsWith("OpenBSD")) featureList = Primitives.APPEND.execute(list(Keyword.UNIX, Keyword.OPENBSD), featureList); else if (osName.startsWith("NetBSD")) featureList = Primitives.APPEND.execute(list(Keyword.UNIX, Keyword.NETBSD), featureList); else if (osName.startsWith("Windows")) featureList = new Cons(Keyword.WINDOWS, featureList); // Processor architecture if (osArch != null) { if (osArch.equals("amd64") || osArch.equals("x86_64")) { featureList = featureList.push(Keyword.X86_64); } else if (osArch.equals("x86") || osArch.equals("i386")) { featureList = featureList.push(Keyword.X86); } else { // just push the value of 'os.arch' as a keyword featureList = featureList.push(internKeyword(osArch.toUpperCase())); } } // Available Threading models if (LispThread.virtualThreadingAvailable()) { featureList = featureList.push(internKeyword("VIRTUAL-THREADS")); } Symbol.FEATURES.initializeSpecial(featureList); } static { Symbol.MODULES.initializeSpecial(NIL); } static { Symbol.LOAD_VERBOSE.initializeSpecial(NIL); Symbol.LOAD_PRINT.initializeSpecial(NIL); Symbol.LOAD_PATHNAME.initializeSpecial(NIL); Symbol.LOAD_TRUENAME.initializeSpecial(NIL); Symbol.LOAD_TRUENAME_FASL.initializeSpecial(NIL); Symbol.COMPILE_VERBOSE.initializeSpecial(T); Symbol.COMPILE_PRINT.initializeSpecial(T); Symbol._COMPILE_FILE_PATHNAME_.initializeSpecial(NIL); Symbol.COMPILE_FILE_TRUENAME.initializeSpecial(NIL); } // ### *double-colon-package-separators* // internal symbol public static final Symbol DOUBLE_COLON_PACKAGE_SEPARATORS = internSpecial("*DOUBLE-COLON-PACKAGE-SEPARATORS*", PACKAGE_SYS, NIL); // ### *load-depth* // internal symbol public static final Symbol _LOAD_DEPTH_ = internSpecial("*LOAD-DEPTH*", PACKAGE_SYS, Fixnum.ZERO); // ### *load-stream* // internal symbol public static final Symbol _LOAD_STREAM_ = internSpecial("*LOAD-STREAM*", PACKAGE_SYS, NIL); // ### *fasl-loader* public static final Symbol _FASL_LOADER_ = exportSpecial("*FASL-LOADER*", PACKAGE_SYS, NIL); // ### *source* // internal symbol public static final Symbol _SOURCE_ = exportSpecial("*SOURCE*", PACKAGE_SYS, NIL); // ### *source-position* // internal symbol public static final Symbol _SOURCE_POSITION_ = exportSpecial("*SOURCE-POSITION*", PACKAGE_SYS, NIL); // ### *autoload-verbose* // internal symbol public static final Symbol _AUTOLOAD_VERBOSE_ = exportSpecial("*AUTOLOAD-VERBOSE*", PACKAGE_EXT, NIL); // ### *preloading-cache* public static final Symbol AUTOLOADING_CACHE = internSpecial("*AUTOLOADING-CACHE*", PACKAGE_SYS, NIL); // ### *compile-file-type* public static final Symbol _COMPILE_FILE_TYPE_ = exportSpecial("*COMPILE-FILE-TYPE*", PACKAGE_SYS, new SimpleString("abcl")); // ### *compile-file-class-extension* public static final Symbol _COMPILE_FILE_CLASS_EXTENSION_ = exportSpecial("*COMPILE-FILE-CLASS-EXTENSION*", PACKAGE_SYS, new SimpleString("cls")); // ### *compile-file-zip* public static final Symbol _COMPILE_FILE_ZIP_ = exportSpecial("*COMPILE-FILE-ZIP*", PACKAGE_SYS, T); static { Symbol.MACROEXPAND_HOOK.initializeSpecial(Symbol.FUNCALL); } public static final int ARRAY_DIMENSION_MAX = Integer.MAX_VALUE; static { // ### array-dimension-limit Symbol.ARRAY_DIMENSION_LIMIT.initializeConstant(Fixnum.getInstance(ARRAY_DIMENSION_MAX)); } // ### char-code-limit // "The upper exclusive bound on the value returned by the function CHAR-CODE." public static final int CHAR_MAX = Character.MAX_VALUE; static { Symbol.CHAR_CODE_LIMIT.initializeConstant(Fixnum.getInstance(CHAR_MAX + 1)); } static { Symbol.READ_BASE.initializeSpecial(Fixnum.constants[10]); } static { Symbol.READ_DEFAULT_FLOAT_FORMAT.initializeSpecial(Symbol.SINGLE_FLOAT); } // Printer control variables. static { Symbol.PRINT_ARRAY.initializeSpecial(T); Symbol.PRINT_BASE.initializeSpecial(Fixnum.constants[10]); Symbol.PRINT_CASE.initializeSpecial(Keyword.UPCASE); Symbol.PRINT_CIRCLE.initializeSpecial(NIL); Symbol.PRINT_ESCAPE.initializeSpecial(T); Symbol.PRINT_GENSYM.initializeSpecial(T); Symbol.PRINT_LENGTH.initializeSpecial(NIL); Symbol.PRINT_LEVEL.initializeSpecial(NIL); Symbol.PRINT_LINES.initializeSpecial(NIL); Symbol.PRINT_MISER_WIDTH.initializeSpecial(NIL); Symbol.PRINT_PPRINT_DISPATCH.initializeSpecial(NIL); Symbol.PRINT_PRETTY.initializeSpecial(NIL); Symbol.PRINT_RADIX.initializeSpecial(NIL); Symbol.PRINT_READABLY.initializeSpecial(NIL); Symbol.PRINT_RIGHT_MARGIN.initializeSpecial(NIL); } public static final Symbol _PRINT_STRUCTURE_ = exportSpecial("*PRINT-STRUCTURE*", PACKAGE_EXT, T); // ### *current-print-length* public static final Symbol _CURRENT_PRINT_LENGTH_ = exportSpecial("*CURRENT-PRINT-LENGTH*", PACKAGE_SYS, Fixnum.ZERO); // ### *current-print-level* public static final Symbol _CURRENT_PRINT_LEVEL_ = exportSpecial("*CURRENT-PRINT-LEVEL*", PACKAGE_SYS, Fixnum.ZERO); public static final Symbol _PRINT_FASL_ = internSpecial("*PRINT-FASL*", PACKAGE_SYS, NIL); static { Symbol._RANDOM_STATE_.initializeSpecial(new RandomState()); } static { Symbol.STAR.initializeSpecial(NIL); Symbol.STAR_STAR.initializeSpecial(NIL); Symbol.STAR_STAR_STAR.initializeSpecial(NIL); Symbol.MINUS.initializeSpecial(NIL); Symbol.PLUS.initializeSpecial(NIL); Symbol.PLUS_PLUS.initializeSpecial(NIL); Symbol.PLUS_PLUS_PLUS.initializeSpecial(NIL); Symbol.SLASH.initializeSpecial(NIL); Symbol.SLASH_SLASH.initializeSpecial(NIL); Symbol.SLASH_SLASH_SLASH.initializeSpecial(NIL); } // Floating point constants. static { Symbol.PI.initializeConstant(new DoubleFloat(Math.PI)); Symbol.SHORT_FLOAT_EPSILON.initializeConstant(new SingleFloat((float)5.960465E-8)); Symbol.SINGLE_FLOAT_EPSILON.initializeConstant(new SingleFloat((float)5.960465E-8)); Symbol.DOUBLE_FLOAT_EPSILON.initializeConstant(new DoubleFloat((double)1.1102230246251568E-16)); Symbol.LONG_FLOAT_EPSILON.initializeConstant(new DoubleFloat((double)1.1102230246251568E-16)); Symbol.SHORT_FLOAT_NEGATIVE_EPSILON.initializeConstant(new SingleFloat(2.9802326e-8f)); Symbol.SINGLE_FLOAT_NEGATIVE_EPSILON.initializeConstant(new SingleFloat(2.9802326e-8f)); Symbol.DOUBLE_FLOAT_NEGATIVE_EPSILON.initializeConstant(new DoubleFloat((double)5.551115123125784E-17)); Symbol.LONG_FLOAT_NEGATIVE_EPSILON.initializeConstant(new DoubleFloat((double)5.551115123125784E-17)); Symbol.MOST_POSITIVE_SHORT_FLOAT.initializeConstant(new SingleFloat(Float.MAX_VALUE)); Symbol.MOST_POSITIVE_SINGLE_FLOAT.initializeConstant(new SingleFloat(Float.MAX_VALUE)); Symbol.MOST_POSITIVE_DOUBLE_FLOAT.initializeConstant(new DoubleFloat(Double.MAX_VALUE)); Symbol.MOST_POSITIVE_LONG_FLOAT.initializeConstant(new DoubleFloat(Double.MAX_VALUE)); Symbol.LEAST_POSITIVE_SHORT_FLOAT.initializeConstant(new SingleFloat(Float.MIN_VALUE)); Symbol.LEAST_POSITIVE_SINGLE_FLOAT.initializeConstant(new SingleFloat(Float.MIN_VALUE)); Symbol.LEAST_POSITIVE_DOUBLE_FLOAT.initializeConstant(new DoubleFloat(Double.MIN_VALUE)); Symbol.LEAST_POSITIVE_LONG_FLOAT.initializeConstant(new DoubleFloat(Double.MIN_VALUE)); Symbol.LEAST_POSITIVE_NORMALIZED_SHORT_FLOAT.initializeConstant(new SingleFloat(1.17549435e-38f)); Symbol.LEAST_POSITIVE_NORMALIZED_SINGLE_FLOAT.initializeConstant(new SingleFloat(1.17549435e-38f)); Symbol.LEAST_POSITIVE_NORMALIZED_DOUBLE_FLOAT.initializeConstant(new DoubleFloat(2.2250738585072014e-308d)); Symbol.LEAST_POSITIVE_NORMALIZED_LONG_FLOAT.initializeConstant(new DoubleFloat(2.2250738585072014e-308d)); Symbol.MOST_NEGATIVE_SHORT_FLOAT.initializeConstant(new SingleFloat(- Float.MAX_VALUE)); Symbol.MOST_NEGATIVE_SINGLE_FLOAT.initializeConstant(new SingleFloat(- Float.MAX_VALUE)); Symbol.MOST_NEGATIVE_DOUBLE_FLOAT.initializeConstant(new DoubleFloat(- Double.MAX_VALUE)); Symbol.MOST_NEGATIVE_LONG_FLOAT.initializeConstant(new DoubleFloat(- Double.MAX_VALUE)); Symbol.LEAST_NEGATIVE_SHORT_FLOAT.initializeConstant(new SingleFloat(- Float.MIN_VALUE)); Symbol.LEAST_NEGATIVE_SINGLE_FLOAT.initializeConstant(new SingleFloat(- Float.MIN_VALUE)); Symbol.LEAST_NEGATIVE_DOUBLE_FLOAT.initializeConstant(new DoubleFloat(- Double.MIN_VALUE)); Symbol.LEAST_NEGATIVE_LONG_FLOAT.initializeConstant(new DoubleFloat(- Double.MIN_VALUE)); Symbol.LEAST_NEGATIVE_NORMALIZED_SHORT_FLOAT.initializeConstant(new SingleFloat(-1.17549435e-38f)); Symbol.LEAST_NEGATIVE_NORMALIZED_SINGLE_FLOAT.initializeConstant(new SingleFloat(-1.17549435e-38f)); Symbol.LEAST_NEGATIVE_NORMALIZED_DOUBLE_FLOAT.initializeConstant(new DoubleFloat(-2.2250738585072014e-308d)); Symbol.LEAST_NEGATIVE_NORMALIZED_LONG_FLOAT.initializeConstant(new DoubleFloat(-2.2250738585072014e-308d)); } static { Symbol.BOOLE_CLR.initializeConstant(Fixnum.ZERO); Symbol.BOOLE_SET.initializeConstant(Fixnum.ONE); Symbol.BOOLE_1.initializeConstant(Fixnum.TWO); Symbol.BOOLE_2.initializeConstant(Fixnum.constants[3]); Symbol.BOOLE_C1.initializeConstant(Fixnum.constants[4]); Symbol.BOOLE_C2.initializeConstant(Fixnum.constants[5]); Symbol.BOOLE_AND.initializeConstant(Fixnum.constants[6]); Symbol.BOOLE_IOR.initializeConstant(Fixnum.constants[7]); Symbol.BOOLE_XOR.initializeConstant(Fixnum.constants[8]); Symbol.BOOLE_EQV.initializeConstant(Fixnum.constants[9]); Symbol.BOOLE_NAND.initializeConstant(Fixnum.constants[10]); Symbol.BOOLE_NOR.initializeConstant(Fixnum.constants[11]); Symbol.BOOLE_ANDC1.initializeConstant(Fixnum.constants[12]); Symbol.BOOLE_ANDC2.initializeConstant(Fixnum.constants[13]); Symbol.BOOLE_ORC1.initializeConstant(Fixnum.constants[14]); Symbol.BOOLE_ORC2.initializeConstant(Fixnum.constants[15]); } static { // ### call-arguments-limit Symbol.CALL_ARGUMENTS_LIMIT.initializeConstant(Fixnum.getInstance(2147483647)); } static { // ### lambda-parameters-limit Symbol.LAMBDA_PARAMETERS_LIMIT.initializeConstant(Fixnum.getInstance(1024)); // A conservative value, as actual limit is unknown, dependent on // width of constants. Arguments limited by the name length of // the arguments whose printed representation cannot execeed 65535 // bytes. } static { // ### multiple-values-limit Symbol.MULTIPLE_VALUES_LIMIT.initializeConstant(Fixnum.constants[32]); } static { // ### internal-time-units-per-second Symbol.INTERNAL_TIME_UNITS_PER_SECOND.initializeConstant(Fixnum.getInstance(1000)); } static { Symbol.LAMBDA_LIST_KEYWORDS .initializeConstant(list(Symbol.AND_OPTIONAL, Symbol.AND_REST, Symbol.AND_KEY, Symbol.AND_AUX, Symbol.AND_BODY, Symbol.AND_WHOLE, Symbol.AND_ALLOW_OTHER_KEYS, Symbol.AND_ENVIRONMENT)); } // ### call-registers-limit public static final Symbol CALL_REGISTERS_LIMIT = exportConstant("CALL-REGISTERS-LIMIT", PACKAGE_SYS, Fixnum.constants[CALL_REGISTERS_MAX]); // ### *warn-on-redefinition* public static final Symbol _WARN_ON_REDEFINITION_ = exportSpecial("*WARN-ON-REDEFINITION*", PACKAGE_EXT, T); // ### *saved-backtrace* public static final Symbol _SAVED_BACKTRACE_ = exportSpecial("*SAVED-BACKTRACE*", PACKAGE_EXT, NIL); // ### *command-line-argument-list* public static final Symbol _COMMAND_LINE_ARGUMENT_LIST_ = exportSpecial("*COMMAND-LINE-ARGUMENT-LIST*", PACKAGE_EXT, NIL); // ### *batch-mode* public static final Symbol _BATCH_MODE_ = exportSpecial("*BATCH-MODE*", PACKAGE_EXT, NIL); // ### *noinform* public static final Symbol _NOINFORM_ = exportSpecial("*NOINFORM*", PACKAGE_SYS, NIL); // ### *disassembler* public static final Symbol _DISASSEMBLER_ = exportSpecial("*DISASSEMBLER*", PACKAGE_EXT, new SimpleString("javap -c -verbose")); // or "jad -dis -p" // ### *speed* compiler policy public static final Symbol _SPEED_ = exportSpecial("*SPEED*", PACKAGE_SYS, Fixnum.ONE); // ### *space* compiler policy public static final Symbol _SPACE_ = exportSpecial("*SPACE*", PACKAGE_SYS, Fixnum.ONE); // ### *safety* compiler policy public static final Symbol _SAFETY_ = exportSpecial("*SAFETY*", PACKAGE_SYS, Fixnum.ONE); // ### *debug* compiler policy public static final Symbol _DEBUG_ = exportSpecial("*DEBUG*", PACKAGE_SYS, Fixnum.ONE); // ### *explain* compiler policy public static final Symbol _EXPLAIN_ = exportSpecial("*EXPLAIN*", PACKAGE_SYS, NIL); // ### *enable-inline-expansion* public static final Symbol _ENABLE_INLINE_EXPANSION_ = exportSpecial("*ENABLE-INLINE-EXPANSION*", PACKAGE_EXT, T); // ### *require-stack-frame* public static final Symbol _REQUIRE_STACK_FRAME_ = exportSpecial("*REQUIRE-STACK-FRAME*", PACKAGE_EXT, NIL); static { Symbol.SUPPRESS_COMPILER_WARNINGS.initializeSpecial(NIL); } public static final Symbol _COMPILE_FILE_ENVIRONMENT_ = exportSpecial("*COMPILE-FILE-ENVIRONMENT*", PACKAGE_SYS, NIL); public static final LispObject UNBOUND_VALUE = new unboundValue(); static class unboundValue extends LispObject { @Override public String printObject() { return unreadableString("UNBOUND", false); } } public static final LispObject NULL_VALUE = new nullValue(); static class nullValue extends LispObject { @Override public String printObject() { return unreadableString("null", false); } } public static final Symbol _SLOT_UNBOUND_ = exportConstant("+SLOT-UNBOUND+", PACKAGE_SYS, UNBOUND_VALUE); public static final Symbol _CL_PACKAGE_ = exportConstant("+CL-PACKAGE+", PACKAGE_SYS, PACKAGE_CL); public static final Symbol _KEYWORD_PACKAGE_ = exportConstant("+KEYWORD-PACKAGE+", PACKAGE_SYS, PACKAGE_KEYWORD); // ### *backquote-count* public static final Symbol _BACKQUOTE_COUNT_ = internSpecial("*BACKQUOTE-COUNT*", PACKAGE_SYS, Fixnum.ZERO); // ### *bq-vector-flag* public static final Symbol _BQ_VECTOR_FLAG_ = internSpecial("*BQ-VECTOR-FLAG*", PACKAGE_SYS, list(new Symbol("bqv"))); // ### *traced-names* public static final Symbol _TRACED_NAMES_ = exportSpecial("*TRACED-NAMES*", PACKAGE_SYS, NIL); // Floating point traps. protected static boolean TRAP_OVERFLOW = true; protected static boolean TRAP_UNDERFLOW = true; // Extentions static { Symbol._INSPECTOR_HOOK_.initializeSpecial(NIL); } private static final void loadClass(String className) { try { Class.forName(className); } catch (ClassNotFoundException e) { Debug.trace(e); } } static { loadClass("org.armedbear.lisp.Primitives"); loadClass("org.armedbear.lisp.SpecialOperators"); loadClass("org.armedbear.lisp.Extensions"); loadClass("org.armedbear.lisp.CompiledClosure"); loadClass("org.armedbear.lisp.Autoload"); loadClass("org.armedbear.lisp.AutoloadMacro"); loadClass("org.armedbear.lisp.AutoloadGeneralizedReference"); loadClass("org.armedbear.lisp.cxr"); loadClass("org.armedbear.lisp.Do"); loadClass("org.armedbear.lisp.dolist"); loadClass("org.armedbear.lisp.dotimes"); loadClass("org.armedbear.lisp.Pathname"); loadClass("org.armedbear.lisp.LispClass"); loadClass("org.armedbear.lisp.BuiltInClass"); loadClass("org.armedbear.lisp.StructureObject"); loadClass("org.armedbear.lisp.ash"); loadClass("org.armedbear.lisp.Java"); loadClass("org.armedbear.lisp.PackageFunctions"); cold = false; } private static Stream stdin = new Stream(Symbol.SYSTEM_STREAM, System.in, Symbol.CHARACTER, true); private static Stream stdout = new Stream(Symbol.SYSTEM_STREAM,System.out, Symbol.CHARACTER, true); static { Symbol.STANDARD_INPUT.initializeSpecial(stdin); Symbol.STANDARD_OUTPUT.initializeSpecial(stdout); Symbol.ERROR_OUTPUT.initializeSpecial(stdout); Symbol.TRACE_OUTPUT.initializeSpecial(stdout); Symbol.TERMINAL_IO.initializeSpecial(new TwoWayStream(stdin, stdout, true)); Symbol.QUERY_IO.initializeSpecial(new TwoWayStream(stdin, stdout, true)); Symbol.DEBUG_IO.initializeSpecial(new TwoWayStream(stdin, stdout, true)); } private static final SpecialOperator WITH_INLINE_CODE = new with_inline_code(); private static class with_inline_code extends SpecialOperator { with_inline_code() { super("with-inline-code", PACKAGE_JVM, true, "(&optional target repr) &body body"); } @Override public LispObject execute(LispObject args, Environment env) { return error(new SimpleError("This is a placeholder. It should only be called in compiled code, and tranformed by the compiler using special form handlers.")); } } // A synonym for the null reference which indicates to the reader of // the code that we have performed a non-local exit via the // condition system before this reference is reached. public static java.lang.Object UNREACHED = null; } abcl-src-1.9.0/src/org/armedbear/lisp/LispCharacter.java0100644 0000000 0000000 00000044634 14223403213 021601 0ustar000000000 0000000 /* * LispCharacter.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.HashMap; import java.util.Map; public final class LispCharacter extends LispObject { public static final LispCharacter[] constants; public static final CharHashMap lispChars; static { lispChars = new CharHashMap(LispCharacter.class,null){ public LispCharacter get(char c) { LispCharacter lc = super.get(c); if (lc==null) { lc = new LispCharacter(c); put(c, lc); } return lc; } }; constants = lispChars.constants; for (int i = constants.length; i-- > 0;) constants[i] = new LispCharacter((char)i); } public final char value; private String name; public static LispCharacter getInstance(char c) { return lispChars.get(c); } // This needs to be public for the compiler. private LispCharacter(char c) { this.value = c; } @Override public LispObject typeOf() { if (isStandardChar()) return Symbol.STANDARD_CHAR; return Symbol.CHARACTER; } @Override public LispObject classOf() { return BuiltInClass.CHARACTER; } @Override public LispObject getDescription() { StringBuilder sb = new StringBuilder("character #\\"); sb.append(value); sb.append(" char-code #x"); sb.append(Integer.toHexString(value)); return new SimpleString(sb); } @Override public LispObject typep(LispObject type) { if (type == Symbol.CHARACTER) return T; if (type == BuiltInClass.CHARACTER) return T; if (type == Symbol.BASE_CHAR) return T; if (type == Symbol.STANDARD_CHAR) return isStandardChar() ? T : NIL; return super.typep(type); } @Override public boolean characterp() { return true; } @Override public LispObject STRING() { return new SimpleString(value); } boolean isStandardChar() { if (value >= ' ' && value < 127) return true; if (value == '\n') return true; return false; } @Override public boolean eql(char c) { return value == c; } @Override public boolean eql(LispObject obj) { if (this == obj) return true; if (obj instanceof LispCharacter) { if (value == ((LispCharacter)obj).value) return true; } return false; } @Override public boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof LispCharacter) { if (value == ((LispCharacter)obj).value) return true; } return false; } @Override public boolean equalp(LispObject obj) { if (this == obj) return true; if (obj instanceof LispCharacter) { if (value == ((LispCharacter)obj).value) return true; return LispCharacter.toLowerCase(value) == LispCharacter.toLowerCase(((LispCharacter)obj).value); } return false; } public static char getValue(LispObject obj) { if (obj instanceof LispCharacter) return ((LispCharacter)obj).value; type_error(obj, Symbol.CHARACTER); // Not reached. return 0; } public final char getValue() { return value; } @Override public Object javaInstance() { return Character.valueOf(value); } @Override public Object javaInstance(Class c) { return javaInstance(); } @Override public int sxhash() { return value; } @Override public int psxhash() { return Character.toUpperCase(value); } /** See LispObject.getStringValue() */ @Override public String getStringValue() { return String.valueOf(value); } @Override public final String printObject() { final LispThread thread = LispThread.currentThread(); boolean printReadably = (Symbol.PRINT_READABLY.symbolValue(thread) != NIL); // "Specifically, if *PRINT-READABLY* is true, printing proceeds as if // *PRINT-ESCAPE*, *PRINT-ARRAY*, and *PRINT-GENSYM* were also true, // and as if *PRINT-LENGTH*, *PRINT-LEVEL*, and *PRINT-LINES* were // false." boolean printEscape = printReadably || (Symbol.PRINT_ESCAPE.symbolValue(thread) != NIL); StringBuilder sb = new StringBuilder(); if (printEscape) { sb.append("#\\"); switch (value) { case 0: sb.append("Null"); break; case 7: sb.append("Bell"); break; case '\b': sb.append("Backspace"); break; case '\t': sb.append("Tab"); break; case '\n': sb.append("Newline"); break; case '\f': sb.append("Page"); break; case '\r': sb.append("Return"); break; case 27: sb.append("Escape"); break; case 127: sb.append("Rubout"); break; case 160: sb.append("No-break_space"); break; default: if (name!=null) sb.append(name); else sb.append(value); break; } } else { sb.append(value); } return sb.toString(); } // ### character private static final Primitive CHARACTER = new Primitive(Symbol.CHARACTER, "character") { @Override public LispObject execute(LispObject arg) { if (arg instanceof LispCharacter) return arg; if (arg instanceof AbstractString) { if (arg.length() == 1) return ((AbstractString)arg).AREF(0); } else if (arg instanceof Symbol) { String name = ((Symbol)arg).getName(); if (name.length() == 1) return LispCharacter.getInstance(name.charAt(0)); } return type_error(arg, Symbol.CHARACTER_DESIGNATOR); } }; // ### whitespacep private static final Primitive WHITESPACEP = new Primitive("whitespacep", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject arg) { return Character.isWhitespace(LispCharacter.getValue(arg)) ? T : NIL; } }; // ### char-code private static final Primitive CHAR_CODE = new Primitive(Symbol.CHAR_CODE, "character") { @Override public LispObject execute(LispObject arg) { int n = LispCharacter.getValue(arg); return Fixnum.getInstance(n); } }; // ### char-int private static final Primitive CHAR_INT = new Primitive(Symbol.CHAR_INT, "character") { @Override public LispObject execute(LispObject arg) { int n = LispCharacter.getValue(arg); return Fixnum.getInstance(n); } }; // ### code-char private static final Primitive CODE_CHAR = new Primitive(Symbol.CODE_CHAR, "code") { @Override public LispObject execute(LispObject arg) { int n = Fixnum.getValue(arg); if (Character.isValidCodePoint(n)) return LispCharacter.getInstance((char)n); return NIL; } }; // ### characterp private static final Primitive CHARACTERP = new Primitive(Symbol.CHARACTERP, "object") { @Override public LispObject execute(LispObject arg) { return arg instanceof LispCharacter ? T : NIL; } }; // ### both-case-p private static final Primitive BOTH_CASE_P = new Primitive(Symbol.BOTH_CASE_P, "character") { @Override public LispObject execute(LispObject arg) { char c = getValue(arg); if (Character.isLowerCase(c) || Character.isUpperCase(c)) return T; return NIL; } }; // ### lower-case-p private static final Primitive LOWER_CASE_P = new Primitive(Symbol.LOWER_CASE_P, "character") { @Override public LispObject execute(LispObject arg) { return Character.isLowerCase(getValue(arg)) ? T : NIL; } }; // ### upper-case-p private static final Primitive UPPER_CASE_P = new Primitive(Symbol.UPPER_CASE_P, "character") { @Override public LispObject execute(LispObject arg) { return Character.isUpperCase(getValue(arg)) ? T : NIL; } }; // ### char-downcase private static final Primitive CHAR_DOWNCASE = new Primitive(Symbol.CHAR_DOWNCASE, "character") { @Override public LispObject execute(LispObject arg) { final char c = LispCharacter.getValue(arg); if (c < 128) return constants[LOWER_CASE_CHARS[c]]; return LispCharacter.getInstance(toLowerCase(c)); } }; // ### char-upcase private static final Primitive CHAR_UPCASE = new Primitive(Symbol.CHAR_UPCASE, "character") { @Override public LispObject execute(LispObject arg) { final char c; c = LispCharacter.getValue(arg); if (c < 128) return constants[UPPER_CASE_CHARS[c]]; return LispCharacter.getInstance(toUpperCase(c)); } }; // ### digit-char private static final Primitive DIGIT_CHAR = new Primitive(Symbol.DIGIT_CHAR, "weight &optional radix") { @Override public LispObject execute(LispObject arg) { if (arg instanceof Bignum) return NIL; int weight = Fixnum.getValue(arg); if (weight < 10) return constants['0'+weight]; return NIL; } @Override public LispObject execute(LispObject first, LispObject second) { int radix; if (second instanceof Fixnum) radix = ((Fixnum)second).value; else radix = -1; if (radix < 2 || radix > 36) return type_error(second, list(Symbol.INTEGER, Fixnum.TWO, Fixnum.constants[36])); if (first instanceof Bignum) return NIL; int weight = Fixnum.getValue(first); if (weight >= radix) return NIL; if (weight < 10) return constants['0' + weight]; return constants['A' + weight - 10]; } }; // ### digit-char-p char &optional radix => weight private static final Primitive DIGIT_CHAR_P = new Primitive(Symbol.DIGIT_CHAR_P, "char &optional radix") { @Override public LispObject execute(LispObject arg) { final int n = Character.digit(LispCharacter.getValue(arg), 10); return n < 0 ? NIL : Fixnum.getInstance(n); } @Override public LispObject execute(LispObject first, LispObject second) { char c; c = LispCharacter.getValue(first); if (second instanceof Fixnum) { int radix = ((Fixnum)second).value; if (radix >= 2 && radix <= 36) { int n = Character.digit(c, radix); return n < 0 ? NIL : Fixnum.constants[n]; } } return type_error(second, list(Symbol.INTEGER, Fixnum.TWO, Fixnum.constants[36])); } }; // ### standard-char-p private static final Primitive STANDARD_CHAR_P = new Primitive(Symbol.STANDARD_CHAR_P, "character") { @Override public LispObject execute(LispObject arg) { return checkCharacter(arg).isStandardChar() ? T : NIL; } }; // ### graphic-char-p private static final Primitive GRAPHIC_CHAR_P = new Primitive(Symbol.GRAPHIC_CHAR_P, "char") { @Override public LispObject execute(LispObject arg) { char c = LispCharacter.getValue(arg); if (c >= ' ' && c < 127) return T; return Character.isISOControl(c) ? NIL : T; } }; // ### alpha-char-p private static final Primitive ALPHA_CHAR_P = new Primitive(Symbol.ALPHA_CHAR_P, "character") { @Override public LispObject execute(LispObject arg) { return Character.isLetter(LispCharacter.getValue(arg)) ? T : NIL; } }; // ### alphanumericp private static final Primitive ALPHANUMERICP = new Primitive(Symbol.ALPHANUMERICP, "character") { @Override public LispObject execute(LispObject arg) { return Character.isLetterOrDigit(LispCharacter.getValue(arg)) ? T : NIL; } }; public static final int nameToChar(String s) { String lower = s.toLowerCase(); LispCharacter lc = namedToChar.get(lower); if (lc!=null) return lc.value; if (lower.length() == 5 && lower.startsWith("u")) { try { final int i = Integer.parseInt(lower.substring(1, 5), 16); return i; } catch (NumberFormatException e) {}; } if (lower.equals("nul")) return 0; if (lower.equals("bel")) return 7; if (lower.equals("bs")) return '\b'; if (lower.equals("ht")) return '\t'; if (lower.equals("linefeed") || lower.equals("lf")) return '\n'; if (lower.equals("ff")) return '\f'; if (lower.equals("cr")) return '\r'; if (lower.equals("esc")) return 27; if (lower.equals("space") || lower.equals("sp")) return ' '; if (lower.equals("rubout") || lower.equals("del") || lower.equals("delete")) return 127; if (lower.equals("no-break_space")) return 160; if (lower.startsWith("u")) { int length = lower.length(); if (length > 1 && length < 5) { try { final int i = Integer.parseInt(lower.substring(1), 16); return i; } catch (NumberFormatException e) {}; // fall through } } // Unknown. return -1; } // ### name-char private static final Primitive NAME_CHAR = new Primitive(Symbol.NAME_CHAR, "name") { @Override public LispObject execute(LispObject arg) { String s = arg.STRING().getStringValue(); int n = nameToChar(s); return n >= 0 ? LispCharacter.getInstance((char)n) : NIL; } }; public static final String charToName(char c) { switch (c) { case 0: return "Null"; case 7: return "Bell"; case '\b': return "Backspace"; case '\t': return "Tab"; case '\n': return "Newline"; case '\f': return "Page"; case '\r': return "Return"; case 27: return "Escape"; case ' ': return "Space"; case 127: return "Rubout"; case 160: return "No-break_space"; } if (c<0 || c>255) return null; return lispChars.get(c).name; } // ### char-name private static final Primitive CHAR_NAME = new Primitive(Symbol.CHAR_NAME, "character") { @Override public LispObject execute(LispObject arg) { String name = charToName(LispCharacter.getValue(arg)); return name != null ? new SimpleString(name) : NIL; } }; public static final char toUpperCase(char c) { if (c < 128) return UPPER_CASE_CHARS[c]; return Character.toUpperCase(c); } static int maxNamedChar = 0; static Map namedToChar = new HashMap(); static void setCharNames(int i, String[] string) { int settingChar = i; int index = 0; int stringLen = string.length; while(stringLen-->0) { setCharName(settingChar,string[index]); index++; settingChar++; } if (maxNamedChar 0;) UPPER_CASE_CHARS[i] = Character.toUpperCase((char)i); } public static final char toLowerCase(char c) { if (c < 128) return LOWER_CASE_CHARS[c]; return Character.toLowerCase(c); } static final char[] LOWER_CASE_CHARS = new char[128]; static { for (int i = LOWER_CASE_CHARS.length; i-- > 0;) LOWER_CASE_CHARS[i] = Character.toLowerCase((char)i); } } abcl-src-1.9.0/src/org/armedbear/lisp/LispClass.java0100644 0000000 0000000 00000021515 14202767264 020763 0ustar000000000 0000000 /* * LispClass.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.util.concurrent.ConcurrentHashMap; import static org.armedbear.lisp.Lisp.*; public abstract class LispClass extends StandardObject { private static final ConcurrentHashMap map = new ConcurrentHashMap(); public static T addClass(Symbol symbol, T c) { map.put(symbol, c); return c; } public static LispObject addClass(Symbol symbol, LispObject c) { map.put(symbol, c); return c; } public static void removeClass(Symbol symbol) { map.remove(symbol); } public static LispClass findClass(Symbol symbol) { return (LispClass)map.get(symbol); } public static LispObject findClass(LispObject name, boolean errorp) { final Symbol symbol = checkSymbol(name); final LispObject c; c = map.get(symbol); if (c != null) return c; if (errorp) { StringBuilder sb = new StringBuilder("There is no class named "); sb.append(name.princToString()); sb.append('.'); return error(new LispError(sb.toString())); } return NIL; } private final int sxhash; private LispObject name; private LispObject propertyList; private Layout classLayout; private LispObject directSuperclasses = NIL; private LispObject directSubclasses = NIL; private LispObject classPrecedenceList = NIL; private LispObject directMethods = NIL; private LispObject documentation = NIL; private boolean finalized; protected LispClass(Layout layout) { super(layout, layout == null ? 0 : layout.getLength()); sxhash = hashCode() & 0x7fffffff; } protected LispClass(Symbol symbol) { this(null, symbol); } protected LispClass(Layout layout, Symbol symbol) { super(layout, layout == null ? 0 : layout.getLength()); setName(symbol); sxhash = hashCode() & 0x7fffffff; } protected LispClass(Layout layout, Symbol symbol, LispObject directSuperclasses) { super(layout, layout == null ? 0 : layout.getLength()); sxhash = hashCode() & 0x7fffffff; setName(symbol); setDirectSuperclasses(directSuperclasses); } @Override public LispObject getParts() { LispObject result = NIL; result = result.push(new Cons("NAME", name != null ? name : NIL)); result = result.push(new Cons("LAYOUT", getClassLayout() != null ? getClassLayout() : NIL)); result = result.push(new Cons("DIRECT-SUPERCLASSES", getDirectSuperclasses())); result = result.push(new Cons("DIRECT-SUBCLASSES", getDirectSubclasses())); result = result.push(new Cons("CLASS-PRECEDENCE-LIST", getCPL())); result = result.push(new Cons("DIRECT-METHODS", getDirectMethods())); result = result.push(new Cons("DOCUMENTATION", getDocumentation())); return result.nreverse(); } @Override public final int sxhash() { return sxhash; } public LispObject getName() { return name; } public void setName(LispObject name) { this.name = name; } @Override public final LispObject getPropertyList() { if (propertyList == null) propertyList = NIL; return propertyList; } @Override public final void setPropertyList(LispObject obj) { if (obj == null) throw new NullPointerException(); propertyList = obj; } public Layout getClassLayout() { return classLayout; } public void setClassLayout(LispObject layout) { classLayout = layout == NIL ? null : (Layout)layout; } public final int getLayoutLength() { if (layout == null) return 0; return layout.getLength(); } public LispObject getDirectSuperclasses() { return directSuperclasses; } public void setDirectSuperclasses(LispObject directSuperclasses) { this.directSuperclasses = directSuperclasses; } public boolean isFinalized() { return finalized; } public void setFinalized(boolean b) { finalized = b; } // When there's only one direct superclass... public final void setDirectSuperclass(LispObject superclass) { setDirectSuperclasses(new Cons(superclass)); } public LispObject getDirectSubclasses() { return directSubclasses; } public void setDirectSubclasses(LispObject directSubclasses) { this.directSubclasses = directSubclasses; } public LispObject getCPL() { return classPrecedenceList; } public void setCPL(LispObject... cpl) { LispObject obj1 = cpl[0]; if (obj1 instanceof Cons && cpl.length == 1) classPrecedenceList = obj1; else { Debug.assertTrue(obj1 == this); LispObject l = NIL; for (int i = cpl.length; i-- > 0;) l = new Cons(cpl[i], l); classPrecedenceList = l; } } public LispObject getDirectMethods() { return directMethods; } public void setDirectMethods(LispObject methods) { directMethods = methods; } public LispObject getDocumentation() { return documentation; } public void setDocumentation(LispObject doc) { documentation = doc; } @Override public LispObject typeOf() { return Symbol.CLASS; } @Override public LispObject classOf() { return StandardClass.CLASS; } @Override public LispObject typep(LispObject type) { if (type == Symbol.CLASS) return T; if (type == StandardClass.CLASS) return T; return super.typep(type); } public boolean subclassp(LispObject obj) { return subclassp(this, obj); } public static boolean subclassp(LispObject cls, LispObject obj) { LispObject cpl; if (cls instanceof LispClass) cpl = ((LispClass)cls).getCPL(); else cpl = Symbol.CLASS_PRECEDENCE_LIST.execute(cls); while (cpl != NIL) { if (cpl.car() == obj) return true; cpl = ((Cons)cpl).cdr; } return false; } // ### find-class symbol &optional errorp environment => class private static final Primitive FIND_CLASS = new Primitive(Symbol.FIND_CLASS, "symbol &optional errorp environment") { @Override public LispObject execute(LispObject arg) { return findClass(arg, true); } @Override public LispObject execute(LispObject first, LispObject second) { return findClass(first, second != NIL); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { // FIXME Use environment! return findClass(first, second != NIL); } }; // ### %set-find-class private static final Primitive _SET_FIND_CLASS = new Primitive("%set-find-class", PACKAGE_SYS, true) { @Override public LispObject execute(LispObject first, LispObject second) { final Symbol name = checkSymbol(first); if (second == NIL) { removeClass(name); return second; } addClass(name, second); return second; } }; // ### subclassp private static final Primitive SUBCLASSP = new Primitive(Symbol.SUBCLASSP, "class") { @Override public LispObject execute(LispObject first, LispObject second) { return LispClass.subclassp(first, second) ? T : NIL; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/LispError.java0100644 0000000 0000000 00000004422 14202767264 021005 0ustar000000000 0000000 /* * LispError.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class LispError extends SeriousCondition { public LispError() { } protected LispError(LispClass cls) { super(cls); } public LispError(LispObject initArgs) { super(StandardClass.ERROR); initialize(initArgs); } public LispError(String message) { super(StandardClass.ERROR); setFormatControl(message); } @Override public LispObject typeOf() { return Symbol.ERROR; } @Override public LispObject classOf() { return StandardClass.ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.ERROR) return T; if (type == StandardClass.ERROR) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/LispInteger.java0100644 0000000 0000000 00000003762 14202767264 021317 0ustar000000000 0000000 /* * LispInteger.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; /** This class merely serves as the super class for * Fixnum and Bignum */ public class LispInteger extends LispObject implements java.io.Serializable { public static LispInteger getInstance(long l) { if (Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE) return Fixnum.getInstance((int)l); else return Bignum.getInstance(l); } public static LispInteger getInstance(int i) { return Fixnum.getInstance(i); } } abcl-src-1.9.0/src/org/armedbear/lisp/LispObject.java0100644 0000000 0000000 00000065456 14223403213 021120 0ustar000000000 0000000 /* * LispObject.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.WeakHashMap; public class LispObject //extends Lisp { /** Function to allow objects to return the value * "they stand for". Used by AutoloadedFunctionProxy to return * the function it is proxying. */ public LispObject resolve() { return this; } public LispObject typeOf() { return T; } static public LispObject getInstance(boolean b) { return b ? T : NIL; } public LispObject classOf() { return BuiltInClass.CLASS_T; } public LispObject getDescription() { StringBuilder sb = new StringBuilder("An object of type "); sb.append(typeOf().princToString()); sb.append(" at #x"); sb.append(Integer.toHexString(System.identityHashCode(this)).toUpperCase()); return new SimpleString(sb); } /** * Implementing the getParts() protocol will allow INSPECT to * return information about the substructure of a descendent of * LispObject. * * The protocol is to return a List of Cons pairs, where the car of * each pair contains a decriptive string, and the cdr returns a * subobject for inspection. */ public LispObject getParts() { return NIL; } public boolean getBooleanValue() { return true; } public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == T) return T; if (typeSpecifier == BuiltInClass.CLASS_T) return T; if (typeSpecifier == Symbol.ATOM) return T; return NIL; } public boolean constantp() { return true; } public final LispObject CONSTANTP() { return constantp() ? T : NIL; } public final LispObject ATOM() { return atom() ? T : NIL; } public boolean atom() { return true; } public Object javaInstance() { return this; } public Object javaInstance(Class c) { if (c.isAssignableFrom(getClass())) { return this; } if (c == Boolean.class || c == boolean.class) return Boolean.TRUE; return error(new LispError("The value " + princToString() + " is not of class " + c.getName())); } /** This method returns 'this' by default, but allows * objects to return different values to increase Java * interoperability * * @return An object to be used with synchronized, wait, notify, etc */ public Object lockableInstance() { return this; } public final LispObject car() { if (this instanceof Cons) { return ((Cons)this).car; } else if (this instanceof Nil) { return NIL; } return type_error(this, Symbol.LIST); } public final void setCar(LispObject obj) { if (this instanceof Cons) { ((Cons)this).car = obj; return; } type_error(this, Symbol.CONS); } public LispObject RPLACA(LispObject obj) { return type_error(this, Symbol.CONS); } public final LispObject cdr() { if (this instanceof Cons) { return ((Cons)this).cdr; } else if (this instanceof Nil) { return NIL; } return type_error(this, Symbol.LIST); } public final void setCdr(LispObject obj) { if (this instanceof Cons) { ((Cons)this).cdr = obj; return; } type_error(this, Symbol.CONS); } public LispObject RPLACD(LispObject obj) { return type_error(this, Symbol.CONS); } public final LispObject cadr() { LispObject tail = cdr(); if (!(tail instanceof Nil)) { return tail.car(); } else return NIL; } public final LispObject cddr() { LispObject tail = cdr(); if (!(tail instanceof Nil)) { return tail.cdr(); } else return NIL; } public final LispObject caddr() { LispObject tail = cddr(); if (!(tail instanceof Nil)) { return tail.car(); } else return NIL; } public final LispObject nthcdr(int n) { if (n < 0) return type_error(Fixnum.getInstance(n), list(Symbol.INTEGER, Fixnum.ZERO)); if (this instanceof Cons) { LispObject result = this; for (int i = n; i-- > 0;) { result = result.cdr(); if (result == NIL) break; } return result; } else if (this instanceof Nil) { return NIL; } return type_error(this, Symbol.LIST); } public final LispObject push(LispObject obj) { if (this instanceof Cons) { return new Cons(obj, this); } else if (this instanceof Nil) { return new Cons(obj); } return type_error(this, Symbol.LIST); } final public LispObject EQ(LispObject obj) { return this == obj ? T : NIL; } public boolean eql(char c) { return false; } public boolean eql(int n) { return false; } public boolean eql(LispObject obj) { return this == obj; } public final LispObject EQL(LispObject obj) { return eql(obj) ? T : NIL; } public final LispObject EQUAL(LispObject obj) { return equal(obj) ? T : NIL; } public boolean equal(int n) { return false; } public boolean equal(LispObject obj) { return this == obj; } public boolean equalp(int n) { return false; } public boolean equalp(LispObject obj) { return this == obj; } public LispObject ABS() { return type_error(this, Symbol.NUMBER); } public LispObject NUMERATOR() { return type_error(this, Symbol.RATIONAL); } public LispObject DENOMINATOR() { return type_error(this, Symbol.RATIONAL); } public final LispObject EVENP() { return evenp() ? T : NIL; } public boolean evenp() { type_error(this, Symbol.INTEGER); // Not reached. return false; } public final LispObject ODDP() { return oddp() ? T : NIL; } public boolean oddp() { type_error(this, Symbol.INTEGER); // Not reached. return false; } public final LispObject PLUSP() { return plusp() ? T : NIL; } public boolean plusp() { type_error(this, Symbol.REAL); // Not reached. return false; } public final LispObject MINUSP() { return minusp() ? T : NIL; } public boolean minusp() { type_error(this, Symbol.REAL); // Not reached. return false; } public final LispObject NUMBERP() { return numberp() ? T : NIL; } public boolean numberp() { return false; } public final LispObject ZEROP() { return zerop() ? T : NIL; } public boolean zerop() { type_error(this, Symbol.NUMBER); // Not reached. return false; } public LispObject COMPLEXP() { return NIL; } public final LispObject FLOATP() { return floatp() ? T : NIL; } public boolean floatp() { return false; } public final LispObject INTEGERP() { return integerp() ? T : NIL; } public boolean integerp() { return false; } public final LispObject RATIONALP() { return rationalp() ? T : NIL; } public boolean rationalp() { return false; } public final LispObject REALP() { return realp() ? T : NIL; } public boolean realp() { return false; } public final LispObject STRINGP() { return stringp() ? T : NIL; } public boolean stringp() { return false; } public LispObject SIMPLE_STRING_P() { return NIL; } public final LispObject VECTORP() { return vectorp() ? T : NIL; } public boolean vectorp() { return false; } public final LispObject CHARACTERP() { return characterp() ? T : NIL; } public boolean characterp() { return false; } public int length() { type_error(this, Symbol.SEQUENCE); // Not reached. return 0; } public final LispObject LENGTH() { return Fixnum.getInstance(length()); } public LispObject CHAR(int index) { return type_error(this, Symbol.STRING); } public LispObject SCHAR(int index) { return type_error(this, Symbol.SIMPLE_STRING); } public LispObject NTH(int index) { return type_error(this, Symbol.LIST); } public final LispObject NTH(LispObject arg) { return NTH(Fixnum.getValue(arg)); } public LispObject elt(int index) { return type_error(this, Symbol.SEQUENCE); } public LispObject reverse() { return type_error(this, Symbol.SEQUENCE); } public LispObject nreverse() { return type_error(this, Symbol.SEQUENCE); } public long aref_long(int index) { return AREF(index).longValue(); } public int aref(int index) { return AREF(index).intValue(); } public LispObject AREF(int index) { return type_error(this, Symbol.ARRAY); } public final LispObject AREF(LispObject index) { return AREF(Fixnum.getValue(index)); } public void aset(int index, int n) { aset(index, Fixnum.getInstance(n)); } public void aset(int index, LispObject newValue) { type_error(this, Symbol.ARRAY); } public final void aset(LispObject index, LispObject newValue) { aset(Fixnum.getValue(index), newValue); } public LispObject SVREF(int index) { return type_error(this, Symbol.SIMPLE_VECTOR); } public void svset(int index, LispObject newValue) { type_error(this, Symbol.SIMPLE_VECTOR); } public void vectorPushExtend(LispObject element) { noFillPointer(); } public LispObject VECTOR_PUSH_EXTEND(LispObject element) { return noFillPointer(); } public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension) { return noFillPointer(); } public final LispObject noFillPointer() { return type_error(this, list(Symbol.AND, Symbol.VECTOR, list(Symbol.SATISFIES, Symbol.ARRAY_HAS_FILL_POINTER_P))); } public LispObject[] copyToArray() { type_error(this, Symbol.LIST); // Not reached. return null; } public final LispObject SYMBOLP() { return (this instanceof Symbol) ? T : NIL; } public final boolean listp() { return (this instanceof Cons) || (this instanceof Nil); } public final LispObject LISTP() { return listp() ? T : NIL; } public final boolean endp() { if (this instanceof Cons) return false; else if (this instanceof Nil) return true; type_error(this, Symbol.LIST); // Not reached. return false; } public final LispObject ENDP() { return endp() ? T : NIL; } public LispObject NOT() { return NIL; } public boolean isSpecialOperator() { type_error(this, Symbol.SYMBOL); // Not reached. return false; } public boolean isSpecialVariable() { return false; } private static final WeakHashMap documentationHashTable = new WeakHashMap(); public LispObject getDocumentation(LispObject docType) { LispObject alist; synchronized (documentationHashTable) { alist = documentationHashTable.get(this); } if (alist != null) { LispObject entry = assq(docType, alist); if (entry instanceof Cons) return ((Cons)entry).cdr; } if(docType == Symbol.FUNCTION && this instanceof Symbol) { LispObject fn = ((Symbol)this).getSymbolFunction(); if(fn instanceof Function) { DocString ds = fn.getClass().getAnnotation(DocString.class); if(ds != null) { String arglist = ds.args(); String docstring = ds.doc(); if(arglist.length() != 0) ((Function)fn).setLambdaList(new SimpleString(arglist)); if(docstring.length() != 0) { SimpleString doc = new SimpleString(docstring); ((Symbol)this).setDocumentation(Symbol.FUNCTION, doc); return doc; } else if (fn.typep(Symbol.STANDARD_GENERIC_FUNCTION) != NIL) { return Symbol.SLOT_VALUE.execute(fn, Symbol._DOCUMENTATION); } } } } return NIL; } public void setDocumentation(LispObject docType, LispObject documentation) { synchronized (documentationHashTable) { LispObject alist = documentationHashTable.get(this); if (alist == null) alist = NIL; LispObject entry = assq(docType, alist); if (entry instanceof Cons) { ((Cons)entry).cdr = documentation; } else { alist = alist.push(new Cons(docType, documentation)); documentationHashTable.put(this, alist); } } } public LispObject getPropertyList() { return null; } public void setPropertyList(LispObject obj) { } public LispObject getSymbolValue() { return type_error(this, Symbol.SYMBOL); } public LispObject getSymbolFunction() { return type_error(this, Symbol.SYMBOL); } public LispObject getSymbolFunctionOrDie() { return type_error(this, Symbol.SYMBOL); } public LispObject getSymbolSetfFunction() { return type_error(this, Symbol.SYMBOL); } public LispObject getSymbolSetfFunctionOrDie() { return type_error(this, Symbol.SYMBOL); } /** PRINC-TO-STRING function to be used with Java objects * * @return A string in human-readable format, as per PRINC definition */ public String princToString() { LispThread thread = LispThread.currentThread(); SpecialBindingsMark mark = thread.markSpecialBindings(); try { thread.bindSpecial(Symbol.PRINT_READABLY, NIL); thread.bindSpecial(Symbol.PRINT_ESCAPE, NIL); return printObject(); } finally { thread.resetSpecialBindings(mark); } } public String printObject() { return unreadableString(toString(), false); } /** Calls unreadableString(String s, boolean identity) with a default * identity value of 'true'. * * This function is a helper for printObject() * * @param s String representation of this object. * @return String enclosed in the non-readable #< ... > markers */ public final String unreadableString(String s) { return unreadableString(s, true); } /** Creates a non-readably (as per CLHS terminology) representation * of the 'this' object, using string 's'. * * If the current value of the variable *PRINT-READABLY* is T, a * Lisp error is thrown and no value is returned. * * This function is a helper for printObject() * * @param s * @param identity when 'true', includes Java's identityHash for the object * in the output. * @return a non reabable string (i.e. one enclosed in the #< > markers) */ public final String unreadableString(String s, boolean identity) { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); return null; // not reached } StringBuilder sb = new StringBuilder("#<"); sb.append(s); if (identity) { sb.append(" {"); sb.append(Integer.toHexString(System.identityHashCode(this)).toUpperCase()); sb.append("}"); } sb.append(">"); return sb.toString(); } // Special operator public LispObject execute(LispObject args, Environment env) { return error(new LispError()); } public LispObject execute() { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject arg) { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject first, LispObject second) { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject first, LispObject second, LispObject third) { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { return type_error(this, Symbol.FUNCTION); } public LispObject execute(LispObject[] args) { return type_error(this, Symbol.FUNCTION); } // Used by COMPILE-MULTIPLE-VALUE-CALL. public LispObject dispatch(LispObject[] args) { switch (args.length) { case 0: return execute(); case 1: return execute(args[0]); case 2: return execute(args[0], args[1]); case 3: return execute(args[0], args[1], args[2]); case 4: return execute(args[0], args[1], args[2], args[3]); case 5: return execute(args[0], args[1], args[2], args[3], args[4]); case 6: return execute(args[0], args[1], args[2], args[3], args[4], args[5]); case 7: return execute(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); case 8: return execute(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); default: return execute(args); } } public int intValue() { type_error(this, Symbol.INTEGER); // Not reached. return 0; } public long longValue() { type_error(this, Symbol.INTEGER); // Not reached. return 0; } public float floatValue() { type_error(this, Symbol.SINGLE_FLOAT); // Not reached return 0; } public double doubleValue() { type_error(this, Symbol.DOUBLE_FLOAT); // Not reached return 0; } public LispObject incr() { return type_error(this, Symbol.NUMBER); } public LispObject decr() { return type_error(this, Symbol.NUMBER); } public LispObject negate() { return Fixnum.ZERO.subtract(this); } public LispObject add(int n) { return add(Fixnum.getInstance(n)); } public LispObject add(LispObject obj) { return type_error(this, Symbol.NUMBER); } public LispObject subtract(int n) { return subtract(Fixnum.getInstance(n)); } public LispObject subtract(LispObject obj) { return type_error(this, Symbol.NUMBER); } public LispObject multiplyBy(int n) { return multiplyBy(Fixnum.getInstance(n)); } public LispObject multiplyBy(LispObject obj) { return type_error(this, Symbol.NUMBER); } public LispObject divideBy(LispObject obj) { return type_error(this, Symbol.NUMBER); } public boolean isEqualTo(int n) { return isEqualTo(Fixnum.getInstance(n)); } public boolean isEqualTo(LispObject obj) { type_error(this, Symbol.NUMBER); // Not reached. return false; } public final LispObject IS_E(LispObject obj) { return isEqualTo(obj) ? T : NIL; } public boolean isNotEqualTo(int n) { return isNotEqualTo(Fixnum.getInstance(n)); } public boolean isNotEqualTo(LispObject obj) { type_error(this, Symbol.NUMBER); // Not reached. return false; } public final LispObject IS_NE(LispObject obj) { return isNotEqualTo(obj) ? T : NIL; } public boolean isLessThan(int n) { return isLessThan(Fixnum.getInstance(n)); } public boolean isLessThan(LispObject obj) { type_error(this, Symbol.REAL); // Not reached. return false; } public final LispObject IS_LT(LispObject obj) { return isLessThan(obj) ? T : NIL; } public boolean isGreaterThan(int n) { return isGreaterThan(Fixnum.getInstance(n)); } public boolean isGreaterThan(LispObject obj) { type_error(this, Symbol.REAL); // Not reached. return false; } public final LispObject IS_GT(LispObject obj) { return isGreaterThan(obj) ? T : NIL; } public boolean isLessThanOrEqualTo(int n) { return isLessThanOrEqualTo(Fixnum.getInstance(n)); } public boolean isLessThanOrEqualTo(LispObject obj) { type_error(this, Symbol.REAL); // Not reached. return false; } public final LispObject IS_LE(LispObject obj) { return isLessThanOrEqualTo(obj) ? T : NIL; } public boolean isGreaterThanOrEqualTo(int n) { return isGreaterThanOrEqualTo(Fixnum.getInstance(n)); } public boolean isGreaterThanOrEqualTo(LispObject obj) { type_error(this, Symbol.REAL); // Not reached. return false; } public final LispObject IS_GE(LispObject obj) { return isGreaterThanOrEqualTo(obj) ? T : NIL; } public LispObject truncate(LispObject obj) { return type_error(this, Symbol.REAL); } public LispObject MOD(LispObject divisor) { truncate(divisor); final LispThread thread = LispThread.currentThread(); LispObject remainder = thread._values[1]; thread.clearValues(); if (!remainder.zerop()) { if (divisor.minusp()) { if (plusp()) return remainder.add(divisor); } else { if (minusp()) return remainder.add(divisor); } } return remainder; } public LispObject MOD(int divisor) { return MOD(Fixnum.getInstance(divisor)); } public LispObject ash(int shift) { return ash(Fixnum.getInstance(shift)); } public LispObject ash(LispObject obj) { return type_error(this, Symbol.INTEGER); } public LispObject LOGNOT() { return type_error(this, Symbol.INTEGER); } public LispObject LOGAND(int n) { return LOGAND(Fixnum.getInstance(n)); } public LispObject LOGAND(LispObject obj) { return type_error(this, Symbol.INTEGER); } public LispObject LOGIOR(int n) { return LOGIOR(Fixnum.getInstance(n)); } public LispObject LOGIOR(LispObject obj) { return type_error(this, Symbol.INTEGER); } public LispObject LOGXOR(int n) { return LOGXOR(Fixnum.getInstance(n)); } public LispObject LOGXOR(LispObject obj) { return type_error(this, Symbol.INTEGER); } public LispObject LDB(int size, int position) { return type_error(this, Symbol.INTEGER); } public int sxhash() { return hashCode() & 0x7fffffff; } // For EQUALP hash tables. public int psxhash() { return sxhash(); } public int psxhash(int depth) { return psxhash(); } public LispObject STRING() { return error(new TypeError(princToString() + " cannot be coerced to a string.")); } public char[] chars() { type_error(this, Symbol.STRING); // Not reached. return null; } public char[] getStringChars() { type_error(this, Symbol.STRING); // Not reached. return null; } /** Returns a string representing the value * of a 'string designator', if the instance is one. * * Throws an error if the instance isn't a string designator. */ public String getStringValue() { type_error(this, Symbol.STRING); // Not reached. return null; } public LispObject getSlotValue_0() { return type_error(this, Symbol.STRUCTURE_OBJECT); } public LispObject getSlotValue_1() { return type_error(this, Symbol.STRUCTURE_OBJECT); } public LispObject getSlotValue_2() { return type_error(this, Symbol.STRUCTURE_OBJECT); } public LispObject getSlotValue_3() { return type_error(this, Symbol.STRUCTURE_OBJECT); } public LispObject getSlotValue(int index) { return type_error(this, Symbol.STRUCTURE_OBJECT); } public int getFixnumSlotValue(int index) { type_error(this, Symbol.STRUCTURE_OBJECT); // Not reached. return 0; } public boolean getSlotValueAsBoolean(int index) { type_error(this, Symbol.STRUCTURE_OBJECT); // Not reached. return false; } public void setSlotValue_0(LispObject value) { type_error(this, Symbol.STRUCTURE_OBJECT); } public void setSlotValue_1(LispObject value) { type_error(this, Symbol.STRUCTURE_OBJECT); } public void setSlotValue_2(LispObject value) { type_error(this, Symbol.STRUCTURE_OBJECT); } public void setSlotValue_3(LispObject value) { type_error(this, Symbol.STRUCTURE_OBJECT); } public void setSlotValue(int index, LispObject value) { type_error(this, Symbol.STRUCTURE_OBJECT); } public LispObject SLOT_VALUE(LispObject slotName) { return type_error(this, Symbol.STANDARD_OBJECT); } public void setSlotValue(LispObject slotName, LispObject newValue) { type_error(this, Symbol.STANDARD_OBJECT); } // Profiling. public int getCallCount() { return 0; } public void setCallCount(int n) { } public void incrementCallCount() { } public int getHotCount() { return 0; } public void setHotCount(int n) { } public void incrementHotCount() { } } abcl-src-1.9.0/src/org/armedbear/lisp/LispReader.java0100644 0000000 0000000 00000026316 14202767264 021124 0ustar000000000 0000000 /* * LispReader.java * * Copyright (C) 2004-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class LispReader { // ### read-comment public static final ReaderMacroFunction READ_COMMENT = new ReaderMacroFunction("read-comment", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char ignored) { try { while (true) { int n = stream._readChar(); if (n < 0) return LispThread.currentThread().setValues(); if (n == '\n') return LispThread.currentThread().setValues(); } } catch (java.io.IOException e) { return LispThread.currentThread().setValues(); } } }; // ### read-string public static final ReaderMacroFunction READ_STRING = new ReaderMacroFunction("read-string", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char terminator) { return stream.readString(terminator, Stream.currentReadtable); } }; // ### read-list public static final ReaderMacroFunction READ_LIST = new ReaderMacroFunction("read-list", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char ignored) { return stream.readList(false, Stream.currentReadtable); } }; // ### read-right-paren public static final ReaderMacroFunction READ_RIGHT_PAREN = new ReaderMacroFunction("read-right-paren", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char ignored) { return error(new ReaderError("Unmatched right parenthesis.", stream)); } }; // ### read-quote public static final ReaderMacroFunction READ_QUOTE = new ReaderMacroFunction("read-quote", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char ignored) { return new Cons(Symbol.QUOTE, new Cons(stream.read(true, NIL, true, LispThread.currentThread(), Stream.currentReadtable))); } }; // ### read-dispatch-char public static final ReaderMacroFunction READ_DISPATCH_CHAR = new ReaderMacroFunction("read-dispatch-char", PACKAGE_SYS, false, "stream character") { @Override public LispObject execute(Stream stream, char c) { return stream.readDispatchChar(c, Stream.currentReadtable); } }; // ### sharp-left-paren public static final DispatchMacroFunction SHARP_LEFT_PAREN = new DispatchMacroFunction("sharp-left-paren", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readSharpLeftParen(c, n, Stream.currentReadtable); } }; // ### sharp-star public static final DispatchMacroFunction SHARP_STAR = new DispatchMacroFunction("sharp-star", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char ignored, int n) { return stream.readSharpStar(ignored, n, Stream.currentReadtable); } }; // ### sharp-dot public static final DispatchMacroFunction SHARP_DOT = new DispatchMacroFunction("sharp-dot", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readSharpDot(c, n, Stream.currentReadtable); } }; // ### sharp-colon public static final DispatchMacroFunction SHARP_COLON = new DispatchMacroFunction("sharp-colon", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readSymbol(); } }; // ### sharp-a public static final DispatchMacroFunction SHARP_A = new DispatchMacroFunction("sharp-a", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readArray(n, Stream.currentReadtable); } }; // ### sharp-b public static final DispatchMacroFunction SHARP_B = new DispatchMacroFunction("sharp-b", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readRadix(2, Stream.currentReadtable); } }; // ### sharp-c public static final DispatchMacroFunction SHARP_C = new DispatchMacroFunction("sharp-c", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readComplex(Stream.currentReadtable); } }; // ### sharp-o public static final DispatchMacroFunction SHARP_O = new DispatchMacroFunction("sharp-o", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readRadix(8, Stream.currentReadtable); } }; // ### sharp-p public static final DispatchMacroFunction SHARP_P = new DispatchMacroFunction("sharp-p", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readPathname(Stream.currentReadtable); } }; // ### sharp-r public static final DispatchMacroFunction SHARP_R = new DispatchMacroFunction("sharp-r", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readRadix(n, Stream.currentReadtable); } }; // ### sharp-s public static final DispatchMacroFunction SHARP_S = new DispatchMacroFunction("sharp-s", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readStructure(Stream.currentReadtable); } }; // ### sharp-x public static final DispatchMacroFunction SHARP_X = new DispatchMacroFunction("sharp-x", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return stream.readRadix(16, Stream.currentReadtable); } }; // ### sharp-quote public static final DispatchMacroFunction SHARP_QUOTE = new DispatchMacroFunction("sharp-quote", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { return new Cons(Symbol.FUNCTION, new Cons(stream.read(true, NIL, true, LispThread.currentThread(), Stream.currentReadtable))); } }; // ### sharp-backslash public static final DispatchMacroFunction SHARP_BACKSLASH = new DispatchMacroFunction("sharp-backslash", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { final LispThread thread = LispThread.currentThread(); final Readtable rt = (Readtable) Symbol.CURRENT_READTABLE.symbolValue(thread); return stream.readCharacterLiteral(rt, thread); } }; // ### sharp-vertical-bar public static final DispatchMacroFunction SHARP_VERTICAL_BAR = new DispatchMacroFunction("sharp-vertical-bar", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { stream.skipBalancedComment(); return LispThread.currentThread().setValues(); } }; // ### sharp-illegal public static final DispatchMacroFunction SHARP_ILLEGAL = new DispatchMacroFunction("sharp-illegal", PACKAGE_SYS, false, "stream sub-char numarg") { @Override public LispObject execute(Stream stream, char c, int n) { StringBuilder sb = new StringBuilder("Illegal # macro character: #\\"); String s = LispCharacter.charToName(c); if (s != null) sb.append(s); else sb.append(c); return error(new ReaderError(sb.toString(), stream)); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/LispStackFrame.java0100644 0000000 0000000 00000011620 14223403213 021712 0ustar000000000 0000000 /* * LispStackFrame.java * * Copyright (C) 2009 Mark Evenson * $Id: LispStackFrame.java 14572 2013-08-10 08:24:46Z mevenson $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class LispStackFrame extends StackFrame { public final LispObject operator; private final LispObject[] args; public LispThread thread; private final static class UnavailableArgument extends LispObject { public UnavailableArgument () { } @Override public String printObject() { return unreadableString("unavailable arg", false); } } private final static LispObject UNAVAILABLE_ARG = new UnavailableArgument(); public LispStackFrame(Object[] stack, int framePos, int numArgs) { operator = (LispObject) stack[framePos]; args = new LispObject[numArgs]; for (int i = 0; i < numArgs; i++) { args[i] = (LispObject) stack[framePos + 1 + i]; } } @Override public LispObject typeOf() { return Symbol.LISP_STACK_FRAME; } @Override public LispObject classOf() { return BuiltInClass.LISP_STACK_FRAME; } @Override public String printObject() { String result = ""; final String LISP_STACK_FRAME = "LISP-STACK-FRAME"; try { result = unreadableString(LISP_STACK_FRAME + " " + toLispList().printObject()); } catch (Throwable t) { // error while printing stack Debug.trace("Serious printing error: "); Debug.trace(t); result = unreadableString(LISP_STACK_FRAME); } return result; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.LISP_STACK_FRAME) return T; if (typeSpecifier == BuiltInClass.LISP_STACK_FRAME) return T; return super.typep(typeSpecifier); } public LispObject toLispList() { LispObject result = argsToLispList(); if (operator instanceof Operator) { LispObject lambdaName = ((Operator)operator).getLambdaName(); if (lambdaName != null && lambdaName != Lisp.NIL) return result.push(lambdaName); } return result.push(operator); } private LispObject argsToLispList() { LispObject result = Lisp.NIL; for (int i = 0; i < args.length; i++) // `args' come here from LispThread.execute. I don't know // how it comes that some callers pass NULL ptrs around but // we better do not create conses with their CAR being NULL; // it'll horribly break printing such a cons; and probably // other bad things may happen, too. --TCR, 2009-09-17. if (args[i] == null) result = result.push(UNAVAILABLE_ARG); else result = result.push(args[i]); return result.nreverse(); } public SimpleString toLispString() { String result; try { result = this.toLispList().printObject(); } catch (Throwable t) { // error while printing stack Debug.trace("Serious printing error: "); Debug.trace(t); result = unreadableString("LISP-STACK-FRAME"); } return new SimpleString(result); } public int getNumArgs() { return args.length; } public LispObject getOperator() { return operator; } @Override public LispObject getParts() { LispObject result = NIL; result = result.push(new Cons("OPERATOR", getOperator())); LispObject args = argsToLispList(); if (args != NIL) { result = result.push(new Cons("ARGS", args)); } return result.nreverse(); } } abcl-src-1.9.0/src/org/armedbear/lisp/LispThread.java0100644 0000000 0000000 00000161275 14242624277 021135 0ustar000000000 0000000 /* * LispThread.java * * Copyright (C) 2003-2007 Peter Graves * $Id: LispThread.java 14465 2013-04-24 12:50:37Z rschlatte $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import static org.armedbear.lisp.Lisp.*; import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.Stack; import java.text.MessageFormat; public final class LispThread extends LispObject { // use a concurrent hashmap: we may want to add threads // while at the same time iterating the hash final static ConcurrentHashMap map = new ConcurrentHashMap(); LispObject threadValue = NIL; private static ThreadLocal threads = new ThreadLocal(){ @Override public LispThread initialValue() { Thread thisThread = Thread.currentThread(); LispThread thread = LispThread.map.get(thisThread); if (thread == null) { thread = new LispThread(thisThread); LispThread.map.put(thisThread,thread); } return thread; } }; public static final LispThread currentThread() { return threads.get(); } final Thread javaThread; private boolean destroyed; final LispObject name; public LispObject[] _values; private boolean threadInterrupted; private LispObject pending = NIL; private Symbol wrapper = PACKAGE_THREADS.intern("THREAD-FUNCTION-WRAPPER"); /** Stack holding bindings for evaluated functions */ public StackenvStack = new Stack(); LispThread(Thread javaThread) { this.javaThread = javaThread; name = new SimpleString(javaThread.getName()); } public static boolean virtualThreadingAvailable() { try { Class clazz = Class.forName("java.lang.Thread"); Class[] parameters = { java.lang.Runnable.class }; Method method = clazz.getDeclaredMethod("startVirtualThread", parameters); return true; } catch (ClassNotFoundException e1) { Debug.trace("Failed to get java.lang.Thread by name"); } catch (NoSuchMethodException e2) { // This is the case in non-Loom JVMs } catch (SecurityException e3) { Debug.trace("SecurityException caught introspecting threading interface: " + e3.toString()); } return false; } public static Symbol NATIVE_THREADS = internKeyword("NATIVE"); public static Symbol VIRTUAL_THREADS = internKeyword("VIRTUAL"); static { if (virtualThreadingAvailable()) { Symbol._THREADING_MODEL.initializeSpecial(VIRTUAL_THREADS); } else { Symbol._THREADING_MODEL.initializeSpecial(NATIVE_THREADS); } } static Method threadBuilder = null; static Method builderName = null; static Method builderDaemon = null; static Method builderVirtual = null; static Method builderTask = null; static Method builderBuild = null; static { try { Class clazz = Class.forName("java.lang.Thread"); threadBuilder = clazz.getDeclaredMethod("builder"); clazz = Class.forName("java.lang.Thread$Builder"); builderDaemon = clazz.getDeclaredMethod("daemon", boolean.class); builderName = clazz.getDeclaredMethod("name", String.class); builderVirtual = clazz.getDeclaredMethod("virtual"); builderTask = clazz.getDeclaredMethod("task", java.lang.Runnable.class); builderBuild = clazz.getDeclaredMethod("build"); } catch (Exception e) { if (virtualThreadingAvailable()) { Debug.trace("Failed to introspect virtual threading methods: " + e); } } } LispThread(final Function fun, LispObject name) { Runnable r = new Runnable() { public void run() { try { threadValue = funcall(wrapper, new LispObject[] { fun }, LispThread.this); } catch (ThreadDestroyed ignored) { // Might happen. } catch (ProcessingTerminated e) { System.exit(e.getStatus()); } catch (Throwable t) { // any error: process thread interrupts if (isInterrupted()) { processThreadInterrupts(); } String msg = MessageFormat.format("Ignoring uncaught exception {0}.", t.toString()); Debug.warn(msg); } finally { // make sure the thread is *always* removed from the hash again map.remove(Thread.currentThread()); } } }; this.name = name; Thread thread = null; if (Symbol._THREADING_MODEL.getSymbolValue().equals(NATIVE_THREADS)) { thread = new Thread(r); if (name != NIL) { thread.setName(name.getStringValue()); } thread.setDaemon(true); } else { synchronized (threadBuilder) { // Thread.Builder isn't thread safe Object o = null; try { o = threadBuilder.invoke(null); if (name != NIL) { o = builderName.invoke(o, name.getStringValue()); } o = builderDaemon.invoke(o, true); o = builderVirtual.invoke(o); o = builderTask.invoke(o, r); thread = (java.lang.Thread)builderBuild.invoke(o); } catch (IllegalAccessException e1) { Debug.trace("Use of reflection to start virtual thread failed: " + e1.toString()); } catch (InvocationTargetException e2) { Debug.trace("Failed to invoke method to start virtual thread: " + e2.toString()); } } } if (thread == null) { Debug.trace("Failed to create java.lang.Thread"); javaThread = null; } else { javaThread = thread; map.put(javaThread, this); javaThread.start(); } } public StackTraceElement[] getJavaStackTrace() { return javaThread.getStackTrace(); } @Override public LispObject typeOf() { return Symbol.THREAD; } @Override public LispObject classOf() { return BuiltInClass.THREAD; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.THREAD) return T; if (typeSpecifier == BuiltInClass.THREAD) return T; return super.typep(typeSpecifier); } public final synchronized boolean isDestroyed() { return destroyed; } final synchronized boolean isInterrupted() { return threadInterrupted; } final synchronized void setDestroyed(boolean b) { destroyed = b; } final synchronized void interrupt(LispObject function, LispObject args) { pending = new Cons(args, pending); pending = new Cons(function, pending); threadInterrupted = true; javaThread.interrupt(); } final synchronized void processThreadInterrupts() { while (pending != NIL) { LispObject function = pending.car(); LispObject args = pending.cadr(); pending = pending.cddr(); Primitives.APPLY.execute(function, args); } threadInterrupted = false; } public final LispObject[] getValues() { return _values; } public final LispObject[] getValues(LispObject result, int count) { if (_values == null) { LispObject[] values = new LispObject[count]; if (count > 0) values[0] = result; for (int i = 1; i < count; i++) values[i] = NIL; return values; } // If the caller doesn't want any extra values, just return the ones // we've got. if (count <= _values.length) return _values; // The caller wants more values than we have. Pad with NILs. LispObject[] values = new LispObject[count]; for (int i = _values.length; i-- > 0;) values[i] = _values[i]; for (int i = _values.length; i < count; i++) values[i] = NIL; return values; } /** Used by the JVM compiler for MULTIPLE-VALUE-CALL. */ public final LispObject[] accumulateValues(LispObject result, LispObject[] oldValues) { if (oldValues == null) { if (_values != null) return _values; LispObject[] values = new LispObject[1]; values[0] = result; return values; } if (_values != null) { if (_values.length == 0) return oldValues; final int totalLength = oldValues.length + _values.length; LispObject[] values = new LispObject[totalLength]; System.arraycopy(oldValues, 0, values, 0, oldValues.length); System.arraycopy(_values, 0, values, oldValues.length, _values.length); return values; } // _values is null. final int totalLength = oldValues.length + 1; LispObject[] values = new LispObject[totalLength]; System.arraycopy(oldValues, 0, values, 0, oldValues.length); values[totalLength - 1] = result; return values; } public final LispObject setValues() { _values = new LispObject[0]; return NIL; } public final LispObject setValues(LispObject value1) { _values = null; return value1; } public final LispObject setValues(LispObject value1, LispObject value2) { _values = new LispObject[2]; _values[0] = value1; _values[1] = value2; return value1; } public final LispObject setValues(LispObject value1, LispObject value2, LispObject value3) { _values = new LispObject[3]; _values[0] = value1; _values[1] = value2; _values[2] = value3; return value1; } public final LispObject setValues(LispObject value1, LispObject value2, LispObject value3, LispObject value4) { _values = new LispObject[4]; _values[0] = value1; _values[1] = value2; _values[2] = value3; _values[3] = value4; return value1; } public final LispObject setValues(LispObject[] values) { switch (values.length) { case 0: _values = values; return NIL; case 1: _values = null; return values[0]; default: _values = values; return values[0]; } } public final void clearValues() { _values = null; } public final LispObject nothing() { _values = new LispObject[0]; return NIL; } /** * Force a single value, for situations where multiple values should be * ignored. */ public final LispObject value(LispObject obj) { _values = null; return obj; } final static int UNASSIGNED_SPECIAL_INDEX = 0; /** Indicates the last special slot which has been assigned. * Symbols which don't have a special slot assigned use a slot * index of 0 for efficiency reasons: it eliminates the need to * check for index validity before accessing the specials array. * */ final static AtomicInteger lastSpecial = new AtomicInteger(UNASSIGNED_SPECIAL_INDEX); /** A list of indices which can be (re)used for symbols to * be assigned a special slot index. */ final static ConcurrentLinkedQueue freeSpecialIndices = new ConcurrentLinkedQueue(); final static int specialsInitialSize = Integer.valueOf(System.getProperty("abcl.specials.initialSize","4096")); /** This array stores the current special binding for every symbol * which has been globally or locally declared special. * * If the array element has a null value, this means there currently * is no active binding. If the array element contains a valid * SpecialBinding object, but the value field of it is null, that * indicates an "UNBOUND VARIABLE" situation. */ SpecialBinding[] specials = new SpecialBinding[specialsInitialSize + 1]; final static ConcurrentHashMap> specialNames = new ConcurrentHashMap>(); /** The number of slots to grow the specials table in * case of insufficient storage. */ final static int specialsDelta = Integer.valueOf(System.getProperty("abcl.specials.grow.delta","1024")); /** This variable points to the head of a linked list of saved * special bindings. Its main purpose is to allow a mark/reset * interface to special binding and unbinding. */ private SpecialBindingsMark savedSpecials = null; /** Marks the state of the special bindings, * for later rewinding by resetSpecialBindings(). */ public final SpecialBindingsMark markSpecialBindings() { return savedSpecials; } /** Restores the state of the special bindings to what * was captured in the marker 'mark' by a call to markSpecialBindings(). */ public final void resetSpecialBindings(SpecialBindingsMark mark) { SpecialBindingsMark c = savedSpecials; while (mark != c) { specials[c.idx] = c.binding; c = c.next; } savedSpecials = c; } /** Clears out all active special bindings including any marks * previously set. Invoking resetSpecialBindings() with marks * set before this call results in undefined behaviour. */ // Package level access: only for Interpreter.run() final void clearSpecialBindings() { resetSpecialBindings(null); } /** Assigns a specials array index number to the symbol, * if it doesn't already have one. */ private void assignSpecialIndex(Symbol sym) { if (sym.specialIndex != 0) return; synchronized (sym) { // Don't use an atomic access: we'll be swapping values only once. if (sym.specialIndex == 0) { Integer next = freeSpecialIndices.poll(); if (next == null && specials.length < lastSpecial.get() && null == System.getProperty("abcl.specials.grow.slowly")) { // free slots are exhausted; in the middle and at the end. System.gc(); next = freeSpecialIndices.poll(); } if (next == null) sym.specialIndex = lastSpecial.incrementAndGet(); else sym.specialIndex = next.intValue(); } } } /** Frees up an index previously assigned to a symbol for re-assignment * to another symbol. Returns without effect if the symbol has the * default UNASSIGNED_SPECIAL_INDEX special index. */ protected static void releaseSpecialIndex(Symbol sym) { int index = sym.specialIndex; if (index != UNASSIGNED_SPECIAL_INDEX) { // clear out the values in the Iterator it = map.values().iterator(); while (it.hasNext()) { LispThread thread = it.next(); // clear out the values in the saved specials list SpecialBindingsMark savedSpecial = thread.savedSpecials; while (savedSpecial != null) { if (savedSpecial.idx == index) { savedSpecial.idx = 0; savedSpecial.binding = null; } savedSpecial = savedSpecial.next; } thread.specials[index] = null; } freeSpecialIndices.add(Integer.valueOf(index)); } } private void growSpecials() { SpecialBinding[] newSpecials = new SpecialBinding[specials.length + specialsDelta]; System.arraycopy(specials, 0, newSpecials, 0, specials.length); specials = newSpecials; } private SpecialBinding ensureSpecialBinding(int idx) { SpecialBinding binding; boolean assigned; do { try { binding = specials[idx]; assigned = true; } catch (ArrayIndexOutOfBoundsException e) { assigned = false; binding = null; // suppresses 'unassigned' error growSpecials(); } } while (! assigned); return binding; } public final SpecialBinding bindSpecial(Symbol name, LispObject value) { int idx; assignSpecialIndex(name); SpecialBinding binding = ensureSpecialBinding(idx = name.specialIndex); savedSpecials = new SpecialBindingsMark(idx, binding, savedSpecials); return specials[idx] = new SpecialBinding(idx, value); } public final SpecialBinding bindSpecialToCurrentValue(Symbol name) { int idx; assignSpecialIndex(name); SpecialBinding binding = ensureSpecialBinding(idx = name.specialIndex); savedSpecials = new SpecialBindingsMark(idx, binding, savedSpecials); return specials[idx] = new SpecialBinding(idx, (binding == null) ? name.getSymbolValue() : binding.value); } /** Looks up the value of a special binding in the context of the * given thread. * * In order to find the value of a special variable (in general), * use {@link Symbol#symbolValue}. * * @param name The name of the special variable, normally a symbol * @return The inner most binding of the special, or null if unbound * * @see Symbol#symbolValue */ public final LispObject lookupSpecial(Symbol name) { SpecialBinding binding = ensureSpecialBinding(name.specialIndex); return (binding == null) ? null : binding.value; } public final SpecialBinding getSpecialBinding(Symbol name) { return ensureSpecialBinding(name.specialIndex); } public final LispObject setSpecialVariable(Symbol name, LispObject value) { SpecialBinding binding = ensureSpecialBinding(name.specialIndex); if (binding != null) return binding.value = value; name.setSymbolValue(value); return value; } public final LispObject pushSpecial(Symbol name, LispObject thing) { SpecialBinding binding = ensureSpecialBinding(name.specialIndex); if (binding != null) return binding.value = new Cons(thing, binding.value); LispObject value = name.getSymbolValue(); if (value != null) { LispObject newValue = new Cons(thing, value); name.setSymbolValue(newValue); return newValue; } else return error(new UnboundVariable(name)); } // Returns symbol value or NIL if unbound. public final LispObject safeSymbolValue(Symbol name) { SpecialBinding binding = ensureSpecialBinding(name.specialIndex); if (binding != null) return binding.value; LispObject value = name.getSymbolValue(); return value != null ? value : NIL; } public final void rebindSpecial(Symbol name, LispObject value) { SpecialBinding binding = getSpecialBinding(name); binding.value = value; } private LispObject catchTags = NIL; public void pushCatchTag(LispObject tag) { catchTags = new Cons(tag, catchTags); } public void popCatchTag() { if (catchTags != NIL) catchTags = catchTags.cdr(); else Debug.assertTrue(false); } public void throwToTag(LispObject tag, LispObject result) { LispObject rest = catchTags; while (rest != NIL) { if (rest.car() == tag) throw new Throw(tag, result, this); rest = rest.cdr(); } error(new ControlError("Attempt to throw to the nonexistent tag " + tag.princToString() + ".")); } private static class StackMarker { final int numArgs; StackMarker(int numArgs) { this.numArgs = numArgs; } int getNumArgs() { return numArgs; } } // markers for args private final static StackMarker STACK_MARKER_0 = new StackMarker(0); private final static StackMarker STACK_MARKER_1 = new StackMarker(1); private final static StackMarker STACK_MARKER_2 = new StackMarker(2); private final static StackMarker STACK_MARKER_3 = new StackMarker(3); private final static StackMarker STACK_MARKER_4 = new StackMarker(4); private final static StackMarker STACK_MARKER_5 = new StackMarker(5); private final static StackMarker STACK_MARKER_6 = new StackMarker(6); private final static StackMarker STACK_MARKER_7 = new StackMarker(7); private final static StackMarker STACK_MARKER_8 = new StackMarker(8); private final int STACK_FRAME_EXTRA = 2; // a LispStackFrame with n arguments occupies n + STACK_FRAME_EXTRA elements // in {@code stack} array. // stack[framePos] == operation // stack[framePos + 1 + i] == arg[i] // stack[framePos + 1 + n] == initially SrackMarker(n) // LispStackFrame object may be lazily allocated later. // In this case it is stored in stack framePos + 1 + n] // // Java stack frame occupies 1 element // stack[framePos] == JavaStackFrame // // Stack consists of a list of StackSegments. // Top StackSegment is cached in variables stack and stackPtr. private StackSegment topStackSegment = new StackSegment(INITIAL_SEGMENT_SIZE, null); private Object[] stack = topStackSegment.stack; private int stackPtr = 0; private StackSegment spareStackSegment; private static class StackSegment implements org.armedbear.lisp.protocol.Inspectable { final Object[] stack; final StackSegment next; int stackPtr; StackSegment(int size, StackSegment next) { stack = new Object[size]; this.next = next; } public LispObject getParts() { Cons result = new Cons(NIL); return result .push(new Symbol("INITIAL-SEGMENT-SIZE")) .push(LispInteger.getInstance(LispThread.INITIAL_SEGMENT_SIZE)) .push(new Symbol("SEGMENT-SIZE")) .push(LispInteger.getInstance(LispThread.SEGMENT_SIZE)).nreverse(); } } private void ensureStackCapacity(int itemsToPush) { if (stackPtr + (itemsToPush - 1) >= stack.length) grow(itemsToPush); } private static final int INITIAL_SEGMENT_SIZE = 1 << 10; private static final int SEGMENT_SIZE = (1 << 19) - 4; // 4 MiB page on x86_64 private void grow(int numEntries) { topStackSegment.stackPtr = stackPtr; if (spareStackSegment != null) { // Use spare segement if available if (stackPtr > 0 && spareStackSegment.stack.length >= numEntries) { topStackSegment = spareStackSegment; stack = topStackSegment.stack; spareStackSegment = null; stackPtr = 0; return; } spareStackSegment = null; } int newSize = stackPtr + numEntries; if (topStackSegment.stack.length < SEGMENT_SIZE || stackPtr == 0) { // grow initial segment from initial size to standard size int newLength = Math.max(newSize, Math.min(SEGMENT_SIZE, stack.length * 2)); StackSegment newSegment = new StackSegment(newLength, topStackSegment.next); System.arraycopy(stack, 0, newSegment.stack, 0, stackPtr); topStackSegment = newSegment; stack = topStackSegment.stack; return; } // Allocate new segment topStackSegment = new StackSegment(Math.max(SEGMENT_SIZE, numEntries), topStackSegment); stack = topStackSegment.stack; stackPtr = 0; } private StackFrame getStackTop() { topStackSegment.stackPtr = stackPtr; if (stackPtr == 0) { assert topStackSegment.next == null; return null; } StackFrame prev = null; for (StackSegment segment = topStackSegment; segment != null; segment = segment.next) { Object[] stk = segment.stack; int framePos = segment.stackPtr; while (framePos > 0) { Object stackObj = stk[framePos - 1]; if (stackObj instanceof StackFrame) { if (prev != null) { prev.setNext((StackFrame) stackObj); } return (StackFrame) stack[stackPtr - 1]; } StackMarker marker = (StackMarker) stackObj; int numArgs = marker.getNumArgs(); LispStackFrame frame = new LispStackFrame(stk, framePos - numArgs - STACK_FRAME_EXTRA, numArgs); frame.thread = this; stk[framePos - 1] = frame; if (prev != null) { prev.setNext(frame); } prev = frame; framePos -= numArgs + STACK_FRAME_EXTRA; } } return (StackFrame) stack[stackPtr - 1]; } public final void pushStackFrame(JavaStackFrame frame) { frame.setNext(getStackTop()); ensureStackCapacity(1); stack[stackPtr] = frame; stackPtr += 1; } private void popStackFrame(int numArgs) { // Pop off intervening JavaFrames until we get back to a LispFrame Object stackObj = stack[stackPtr - 1]; if (stackObj instanceof StackMarker) { assert numArgs == ((StackMarker) stackObj).getNumArgs(); } else { while (stackObj instanceof JavaStackFrame) { stack[--stackPtr] = null; stackObj = stack[stackPtr - 1]; } if (stackObj instanceof StackMarker) { assert numArgs == ((StackMarker) stackObj).getNumArgs(); } else { assert numArgs == ((LispStackFrame) stackObj).getNumArgs(); } } stackPtr -= numArgs + STACK_FRAME_EXTRA; for (int i = 0; i < numArgs + STACK_FRAME_EXTRA; i++) { stack[stackPtr + i] = null; } if (stackPtr == 0) { popStackSegment(); } } private void popStackSegment() { topStackSegment.stackPtr = 0; if (topStackSegment.next != null) { spareStackSegment = topStackSegment; topStackSegment = topStackSegment.next; stack = topStackSegment.stack; } stackPtr = topStackSegment.stackPtr; } public final Environment setEnv(Environment env) { StackFrame stackTop = getStackTop(); return (stackTop != null) ? stackTop.setEnv(env) : null; } public void resetStack() { topStackSegment = new StackSegment(INITIAL_SEGMENT_SIZE, null); stack = topStackSegment.stack; spareStackSegment = null; stackPtr = 0; } @Override public LispObject execute(LispObject function) { ensureStackCapacity(STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = STACK_MARKER_0; stackPtr += STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(); } finally { envStack.pop() ; popStackFrame(0); } } @Override public LispObject execute(LispObject function, LispObject arg) { ensureStackCapacity(1 + STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = arg; stack[stackPtr + 2] = STACK_MARKER_1; stackPtr += 1 + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(arg); } finally { envStack.pop() ; popStackFrame(1); } } @Override public LispObject execute(LispObject function, LispObject first, LispObject second) { ensureStackCapacity(2 + STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = first; stack[stackPtr + 2] = second; stack[stackPtr + 3] = STACK_MARKER_2; stackPtr += 2 + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(first, second); } finally { envStack.pop() ; popStackFrame(2); } } @Override public LispObject execute(LispObject function, LispObject first, LispObject second, LispObject third) { ensureStackCapacity(3 + STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = first; stack[stackPtr + 2] = second; stack[stackPtr + 3] = third; stack[stackPtr + 4] = STACK_MARKER_3; stackPtr += 3 + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(first, second, third); } finally { envStack.pop() ; popStackFrame(3); } } @Override public LispObject execute(LispObject function, LispObject first, LispObject second, LispObject third, LispObject fourth) { ensureStackCapacity(4 + STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = first; stack[stackPtr + 2] = second; stack[stackPtr + 3] = third; stack[stackPtr + 4] = fourth; stack[stackPtr + 5] = STACK_MARKER_4; stackPtr += 4 + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(first, second, third, fourth); } finally { envStack.pop() ; popStackFrame(4); } } @Override public LispObject execute(LispObject function, LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { ensureStackCapacity(5 + STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = first; stack[stackPtr + 2] = second; stack[stackPtr + 3] = third; stack[stackPtr + 4] = fourth; stack[stackPtr + 5] = fifth; stack[stackPtr + 6] = STACK_MARKER_5; stackPtr += 5 + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(first, second, third, fourth, fifth); } finally { envStack.pop() ; popStackFrame(5); } } @Override public LispObject execute(LispObject function, LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { ensureStackCapacity(6 + STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = first; stack[stackPtr + 2] = second; stack[stackPtr + 3] = third; stack[stackPtr + 4] = fourth; stack[stackPtr + 5] = fifth; stack[stackPtr + 6] = sixth; stack[stackPtr + 7] = STACK_MARKER_6; stackPtr += 6 + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(first, second, third, fourth, fifth, sixth); } finally { envStack.pop() ; popStackFrame(6); } } @Override public LispObject execute(LispObject function, LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { ensureStackCapacity(7 + STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = first; stack[stackPtr + 2] = second; stack[stackPtr + 3] = third; stack[stackPtr + 4] = fourth; stack[stackPtr + 5] = fifth; stack[stackPtr + 6] = sixth; stack[stackPtr + 7] = seventh; stack[stackPtr + 8] = STACK_MARKER_7; stackPtr += 7 + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(first, second, third, fourth, fifth, sixth, seventh); } finally { envStack.pop(); popStackFrame(7); } } public LispObject execute(LispObject function, LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { ensureStackCapacity(8 + STACK_FRAME_EXTRA); stack[stackPtr] = function; stack[stackPtr + 1] = first; stack[stackPtr + 2] = second; stack[stackPtr + 3] = third; stack[stackPtr + 4] = fourth; stack[stackPtr + 5] = fifth; stack[stackPtr + 6] = sixth; stack[stackPtr + 7] = seventh; stack[stackPtr + 8] = eighth; stack[stackPtr + 9] = STACK_MARKER_8; stackPtr += 8 + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(first, second, third, fourth, fifth, sixth, seventh, eighth); } finally { envStack.pop() ; popStackFrame(8); } } public LispObject execute(LispObject function, LispObject[] args) { ensureStackCapacity(args.length + STACK_FRAME_EXTRA); stack[stackPtr] = function; System.arraycopy(args, 0, stack, stackPtr + 1, args.length); stack[stackPtr + args.length + 1] = new StackMarker(args.length); stackPtr += args.length + STACK_FRAME_EXTRA; try { envStack.push(new Environment(null,NIL,function)); return function.execute(args); } finally { envStack.pop() ; popStackFrame(args.length); } } public void printBacktrace() { printBacktrace(0); } public void printBacktrace(int limit) { StackFrame stackTop = getStackTop(); if (stackTop != null) { int count = 0; Stream out = checkCharacterOutputStream(Symbol.TRACE_OUTPUT.symbolValue()); out._writeLine("Evaluation stack:"); out._finishOutput(); StackFrame s = stackTop; while (s != null) { out._writeString(" "); out._writeString(String.valueOf(count)); out._writeString(": "); pprint(s.toLispList(), out.getCharPos(), out); out.terpri(); out._finishOutput(); if (limit > 0 && ++count == limit) break; s = s.next; } } } public LispObject backtrace(int limit) { StackFrame stackTop = getStackTop(); LispObject result = NIL; if (stackTop != null) { int count = 0; StackFrame s = stackTop; while (s != null) { result = result.push(s); if (limit > 0 && ++count == limit) break; s = s.getNext(); } } return result.nreverse(); } public void incrementCallCounts() { topStackSegment.stackPtr = stackPtr; int depth = 0; for (StackSegment segment = topStackSegment; segment != null; segment = segment.next) { Object[] stk = segment.stack; int framePos = segment.stackPtr; while (framePos > 0) { depth++; Object stackObj = stk[framePos - 1]; int numArgs; if (stackObj instanceof StackMarker) { numArgs = ((StackMarker) stackObj).getNumArgs(); } else if (stackObj instanceof LispStackFrame) { numArgs = ((LispStackFrame) stackObj).getNumArgs(); } else { assert stackObj instanceof JavaStackFrame; framePos--; continue; } // lisp stack frame framePos -= numArgs + STACK_FRAME_EXTRA; LispObject operator = (LispObject) stack[framePos]; if (operator != null) { if (depth <= 8) { operator.incrementHotCount(); } operator.incrementCallCount(); } } } } private static void pprint(LispObject obj, int indentBy, Stream stream) { if (stream.getCharPos() == 0) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < indentBy; i++) sb.append(' '); stream._writeString(sb.toString()); } String raw = obj.printObject(); if (stream.getCharPos() + raw.length() < 80) { // It fits. stream._writeString(raw); return; } // Object doesn't fit. if (obj instanceof Cons) { boolean newlineBefore = false; LispObject[] array = obj.copyToArray(); if (array.length > 0) { LispObject first = array[0]; if (first == Symbol.LET) { newlineBefore = true; } } int charPos = stream.getCharPos(); if (newlineBefore && charPos != indentBy) { stream.terpri(); charPos = stream.getCharPos(); } if (charPos < indentBy) { StringBuffer sb = new StringBuffer(); for (int i = charPos; i < indentBy; i++) sb.append(' '); stream._writeString(sb.toString()); } stream.print('('); for (int i = 0; i < array.length; i++) { pprint(array[i], indentBy + 2, stream); if (i < array.length - 1) stream.print(' '); } stream.print(')'); } else { stream.terpri(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < indentBy; i++) sb.append(' '); stream._writeString(sb.toString()); stream._writeString(raw); return; } } @Override public String printObject() { StringBuffer sb = new StringBuffer("THREAD"); if (name != NIL) { sb.append(" \""); sb.append(name.getStringValue()); sb.append("\""); } return unreadableString(sb.toString()); } @DocString(name="make-thread", args="function &key name", doc="Create a thread of execution running FUNCTION possibly named NAME") private static final Primitive MAKE_THREAD = new Primitive("make-thread", PACKAGE_THREADS, true, "function &key name") { @Override public LispObject execute(LispObject[] args) { final int length = args.length; if (length == 0) error(new WrongNumberOfArgumentsException(this, 1, -1)); LispObject name = NIL; if (length > 1) { if ((length - 1) % 2 != 0) program_error("Odd number of keyword arguments."); if (length > 3) error(new WrongNumberOfArgumentsException(this, -1, 2)); // don't count the keyword itself as an argument if (args[1] == Keyword.NAME) name = args[2].STRING(); else program_error("Unrecognized keyword argument " + args[1].princToString() + "."); } return new LispThread(checkFunction(args[0]), name); } }; @DocString(name="threadp", args="object", doc="Boolean predicate returning non-nil if OBJECT is a lisp thread") private static final Primitive THREADP = new Primitive("threadp", PACKAGE_THREADS, true) { @Override public LispObject execute(LispObject arg) { return arg instanceof LispThread ? T : NIL; } }; @DocString(name="thread-alive-p", args="thread", doc="Returns T if THREAD is alive.") private static final Primitive THREAD_ALIVE_P = new Primitive("thread-alive-p", PACKAGE_THREADS, true, "thread", "Boolean predicate whether THREAD is alive.") { @Override public LispObject execute(LispObject arg) { final LispThread lispThread; if (arg instanceof LispThread) { lispThread = (LispThread) arg; } else { return type_error(arg, Symbol.THREAD); } return lispThread.javaThread.isAlive() ? T : NIL; } }; @DocString(name="thread-name", args="thread", doc="Return the name of THREAD, if it has one.") private static final Primitive THREAD_NAME = new Primitive("thread-name", PACKAGE_THREADS, true) { @Override public LispObject execute(LispObject arg) { if (arg instanceof LispThread) { return ((LispThread)arg).name; } return type_error(arg, Symbol.THREAD); } }; private static final Primitive THREAD_JOIN = new Primitive("thread-join", PACKAGE_THREADS, true, "thread", "Waits for THREAD to die before resuming execution\n" + "Returns the result of the joined thread as its primary value.\n" + "Returns T if the joined thread finishes normally or NIL if it was interrupted.") { @Override public LispObject execute(LispObject arg) { // join the thread, and returns its value. The second return // value is T if the thread finishes normally, NIL if its // interrupted. if (arg instanceof LispThread) { final LispThread joinedThread = (LispThread) arg; final LispThread waitingThread = currentThread(); try { joinedThread.javaThread.join(); return waitingThread.setValues(joinedThread.threadValue, T); } catch (InterruptedException e) { waitingThread.processThreadInterrupts(); return waitingThread.setValues(joinedThread.threadValue, NIL); } } else { return type_error(arg, Symbol.THREAD); } } }; final static DoubleFloat THOUSAND = new DoubleFloat(1000); static final long sleepMillisPart(LispObject seconds) { double d = checkDoubleFloat(seconds.multiplyBy(THOUSAND)).getValue(); if (d < 0) { type_error(seconds, list(Symbol.REAL, Fixnum.ZERO)); } return (d < Long.MAX_VALUE ? (long) d : Long.MAX_VALUE); } static final int sleepNanosPart(LispObject seconds) { double d // d contains millis = checkDoubleFloat(seconds.multiplyBy(THOUSAND)).getValue(); double n = d * 1000000; // sleep interval in nanoseconds d = 1.0e6 * ((long)d); // sleep interval to millisecond precision n = n - d; return (n < Integer.MAX_VALUE ? (int) n : Integer.MAX_VALUE); } @DocString(name="sleep", args="seconds", doc="Causes the invoking thread to sleep for an interveral expressed in SECONDS.\n" + "SECONDS may be specified as a fraction of a second, with intervals\n" + "less than or equal to a nanosecond resulting in a yield of execution\n" + "to other waiting threads rather than an actual sleep.\n" + "A zero value of SECONDS *may* result in the JVM sleeping indefinitely,\n" + "depending on the implementation.") private static final Primitive SLEEP = new Primitive("sleep", PACKAGE_CL, true) { @Override public LispObject execute(LispObject arg) { long millis = sleepMillisPart(arg); int nanos = sleepNanosPart(arg); boolean zeroArgP = arg.ZEROP() != NIL; try { if (millis == 0 && nanos == 0) { if (zeroArgP) { Thread.sleep(0, 0); } else { Thread.sleep(0, 1); } } else { Thread.sleep(millis, nanos); } } catch (InterruptedException e) { currentThread().processThreadInterrupts(); } return NIL; } }; @DocString(name="mapcar-threads", args= "function", doc="Applies FUNCTION to all existing threads.") private static final Primitive MAPCAR_THREADS = new Primitive("mapcar-threads", PACKAGE_THREADS, true) { @Override public LispObject execute(LispObject arg) { Function fun = checkFunction(arg); final LispThread thread = LispThread.currentThread(); LispObject result = NIL; Iterator it = map.values().iterator(); while (it.hasNext()) { LispObject[] args = new LispObject[1]; args[0] = (LispThread) it.next(); result = new Cons(funcall(fun, args, thread), result); } return result; } }; @DocString(name="destroy-thread", args="thread", doc="Mark THREAD as destroyed") private static final Primitive DESTROY_THREAD = new Primitive("destroy-thread", PACKAGE_THREADS, true) { @Override public LispObject execute(LispObject arg) { final LispThread thread; if (arg instanceof LispThread) { thread = (LispThread) arg; } else { return type_error(arg, Symbol.THREAD); } thread.setDestroyed(true); return T; } }; // => T @DocString(name="interrupt-thread", args="thread function &rest args", doc="Interrupts thread and forces it to apply function to args. When the\n"+ "function returns, the thread's original computation continues. If\n"+ "multiple interrupts are queued for a thread, they are all run, but the\n"+ "order is not guaranteed.") private static final Primitive INTERRUPT_THREAD = new Primitive("interrupt-thread", PACKAGE_THREADS, true, "thread function &rest args", "Interrupts THREAD and forces it to apply FUNCTION to ARGS.\nWhen the function returns, the thread's original computation continues. If multiple interrupts are queued for a thread, they are all run, but the order is not guaranteed.") { @Override public LispObject execute(LispObject[] args) { if (args.length < 2) return error(new WrongNumberOfArgumentsException(this, 2, -1)); final LispThread thread; if (args[0] instanceof LispThread) { thread = (LispThread) args[0]; } else { return type_error(args[0], Symbol.THREAD); } LispObject fun = args[1]; LispObject funArgs = NIL; for (int i = args.length; i-- > 2;) funArgs = new Cons(args[i], funArgs); thread.interrupt(fun, funArgs); setInterrupted(thread,true); return T; } }; public static final Primitive CURRENT_THREAD = new pf_current_thread(); @DocString(name="current-thread", doc="Returns a reference to invoking thread.") private static final class pf_current_thread extends Primitive { pf_current_thread() { super("current-thread", PACKAGE_THREADS, true); } @Override public LispObject execute() { return currentThread(); } }; public static final Primitive BACKTRACE = new pf_backtrace(); @DocString(name="backtrace", doc="Returns a Java backtrace of the invoking thread.") private static final class pf_backtrace extends Primitive { pf_backtrace() { super("backtrace", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject[] args) { if (args.length > 1) return error(new WrongNumberOfArgumentsException(this, -1, 1)); int limit = args.length > 0 ? Fixnum.getValue(args[0]) : 0; return currentThread().backtrace(limit); } }; public static final Primitive FRAME_TO_STRING = new pf_frame_to_string(); @DocString(name="frame-to-string", args="frame", doc="Convert stack FRAME to a (potentially) readable string.") private static final class pf_frame_to_string extends Primitive { pf_frame_to_string() { super("frame-to-string", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject[] args) { if (args.length != 1) return error(new WrongNumberOfArgumentsException(this, 1)); return checkStackFrame(args[0]).toLispString(); } }; public static final Primitive FRAME_TO_LIST = new pf_frame_to_list(); @DocString(name="frame-to-list", args="frame") private static final class pf_frame_to_list extends Primitive { pf_frame_to_list() { super("frame-to-list", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject[] args) { if (args.length != 1) return error(new WrongNumberOfArgumentsException(this, 1)); return checkStackFrame(args[0]).toLispList(); } }; public static final SpecialOperator SYNCHRONIZED_ON = new so_synchronized_on(); @DocString(name="synchronized-on", args="form &body body") private static final class so_synchronized_on extends SpecialOperator { so_synchronized_on() { super("synchronized-on", PACKAGE_THREADS, true, "form &body body"); } @Override public LispObject execute(LispObject args, Environment env) { if (args == NIL) return error(new WrongNumberOfArgumentsException(this, 1)); LispThread thread = LispThread.currentThread(); synchronized (eval(args.car(), env, thread).lockableInstance()) { return progn(args.cdr(), env, thread); } } }; public static final Primitive OBJECT_WAIT = new pf_object_wait(); @DocString( name="object-wait", args="object &optional timeout", doc="Causes the current thread to block until object-notify or object-notify-all is called on OBJECT.\n" + "Optionally unblock execution after TIMEOUT seconds. A TIMEOUT of zero\n" + "means to wait indefinitely.\n" + "A non-zero TIMEOUT of less than a nanosecond is interpolated as a nanosecond wait." + "\n" + "See the documentation of java.lang.Object.wait() for further\n" + "information.\n" ) private static final class pf_object_wait extends Primitive { pf_object_wait() { super("object-wait", PACKAGE_THREADS, true); } @Override public LispObject execute(LispObject object) { try { object.lockableInstance().wait(); } catch (InterruptedException e) { currentThread().processThreadInterrupts(); } catch (IllegalMonitorStateException e) { return error(new IllegalMonitorState(e.getMessage())); } return NIL; } @Override public LispObject execute(LispObject object, LispObject timeout) { long millis = sleepMillisPart(timeout); int nanos = sleepNanosPart(timeout); boolean zeroArgP = timeout.ZEROP() != NIL; try { if (millis == 0 && nanos == 0) { if (zeroArgP) { object.lockableInstance().wait(0, 0); } else { object.lockableInstance().wait(0, 1); } } else { object.lockableInstance().wait(millis, nanos); } } catch (InterruptedException e) { currentThread().processThreadInterrupts(); } catch (IllegalMonitorStateException e) { return error(new IllegalMonitorState(e.getMessage())); } return NIL; } }; public static final Primitive OBJECT_NOTIFY = new pf_object_notify(); @DocString(name="object-notify", args="object", doc="Wakes up a single thread that is waiting on OBJECT's monitor." + "\nIf any threads are waiting on this object, one of them is chosen to be" + " awakened. The choice is arbitrary and occurs at the discretion of the" + " implementation. A thread waits on an object's monitor by calling one" + " of the wait methods.") private static final class pf_object_notify extends Primitive { pf_object_notify() { super("object-notify", PACKAGE_THREADS, true, "object"); } @Override public LispObject execute(LispObject object) { try { object.lockableInstance().notify(); } catch (IllegalMonitorStateException e) { return error(new IllegalMonitorState(e.getMessage())); } return NIL; } }; public static final Primitive OBJECT_NOTIFY_ALL = new pf_object_notify_all(); @DocString(name="object-notify-all", args="object", doc="Wakes up all threads that are waiting on this OBJECT's monitor." + "\nA thread waits on an object's monitor by calling one of the wait methods.") private static final class pf_object_notify_all extends Primitive { pf_object_notify_all() { super("object-notify-all", PACKAGE_THREADS, true); } @Override public LispObject execute(LispObject object) { try { object.lockableInstance().notifyAll(); } catch (IllegalMonitorStateException e) { return error(new IllegalMonitorState(e.getMessage())); } return NIL; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Load.java0100644 0000000 0000000 00000102751 14223403213 017727 0ustar000000000 0000000 /* * Load.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.text.MessageFormat; /* This file holds ABCL's (FASL and non-FASL) loading behaviours. * * The loading process works like this: * The loader associates the input filename with a special variable * and starts evaluating the forms in the file. * * If one of the forms is (INIT-FASL :VERSION ), from that * point the file is taken to be a FASL. * The FASL loader takes over and retrieves the file being loaded * from the special variable and continues loading from there. * */ public final class Load { public static final LispObject load(String filename) { final LispThread thread = LispThread.currentThread(); return load((Pathname)Pathname.create(filename), Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL, Symbol.LOAD_PRINT.symbolValue(thread) != NIL, true); } /** @return Pathname of loadable file based on NAME, or null if * none can be determined. */ private static final Pathname findLoadableFile(Pathname name) { LispObject truename = Symbol.PROBE_FILE.execute(name); if (truename instanceof Pathname) { Pathname t = (Pathname)truename; if (t.getName() != NIL && t.getName() != null) { return t; } } final String COMPILE_FILE_TYPE = Lisp._COMPILE_FILE_TYPE_.symbolValue().getStringValue(); if (name.getType() == NIL && (name.getName() != NIL || name.getName() != null)) { Pathname lispPathname = Pathname.create(name); lispPathname.setType(new SimpleString("lisp")); LispObject lisp = Symbol.PROBE_FILE.execute(lispPathname); Pathname abclPathname = Pathname.create(name); abclPathname.setType(new SimpleString(COMPILE_FILE_TYPE)); LispObject abcl = Symbol.PROBE_FILE.execute(abclPathname); if (lisp instanceof Pathname && abcl instanceof Pathname) { lispPathname = (Pathname)lisp; abclPathname = (Pathname)abcl; long lispLastModified = lispPathname.getLastModified(); long abclLastModified = abclPathname.getLastModified(); if (abclLastModified > lispLastModified) { return abclPathname; // fasl file is newer } else { return lispPathname; } } else if (abcl instanceof Pathname) { return (Pathname) abcl; } else if (lisp instanceof Pathname) { return (Pathname) lisp; } } if (name.isJar()) { if (name.getType().equals(NIL)) { name.setType(COMPILE_FILE_INIT_FASL_TYPE); Pathname result = findLoadableFile(name); if (result != null) { return result; } name.setType(new SimpleString(COMPILE_FILE_TYPE)); result = findLoadableFile(name); if (result != null) { return result; } } } return null; } public static final LispObject load(Pathname pathname, boolean verbose, boolean print, boolean ifDoesNotExist) { return load(pathname, verbose, print, ifDoesNotExist, false, Keyword.DEFAULT); } public static final LispObject load(InputStream in) { return load(in, new SimpleString("UTF-8")); } public static final LispObject load(InputStream in, LispObject format) { Stream stream = new Stream(Symbol.SYSTEM_STREAM, in, Symbol.CHARACTER, format); final LispThread thread = LispThread.currentThread(); return loadFileFromStream(null, null, stream, Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL, Symbol.LOAD_PRINT.symbolValue(thread) != NIL, false); } public static final LispObject load(final Pathname pathname, boolean verbose, boolean print, boolean ifDoesNotExist, boolean returnLastResult, LispObject externalFormat) { Pathname mergedPathname = null; if (!pathname.isAbsolute() && !pathname.isJar()) { Pathname pathnameDefaults = coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()); mergedPathname = Pathname.mergePathnames(pathname, pathnameDefaults); } Pathname loadableFile = findLoadableFile(mergedPathname != null ? mergedPathname : pathname); Pathname truename = (loadableFile != null ? (Pathname)Symbol.PROBE_FILE.execute(loadableFile) : null); if (truename == null || truename.equals(NIL)) { if (ifDoesNotExist) { return error(new FileError("File not found: " + pathname.princToString(), pathname)); } else { Debug.warn("Failed to load " + pathname.getNamestring()); return NIL; } } if (ZipCache.checkZipFile(truename)) { if (truename instanceof JarPathname) { truename = JarPathname.createFromEntry((JarPathname)truename); } else { truename = JarPathname.createFromPathname(truename); } Pathname loader = Pathname.create("__loader__._"); // FIXME use constants mergedPathname = (Pathname)Symbol.MERGE_PATHNAMES.execute(loader, truename); LispObject initTruename = Symbol.PROBE_FILE.execute(mergedPathname); if (initTruename.equals(NIL)) { // Maybe the enclosing JAR has been renamed? Pathname p = Pathname.create(mergedPathname); p.setName(Keyword.WILD); LispObject result = Symbol.MATCH_WILD_JAR_PATHNAME.execute(p); if (result instanceof Cons && ((Cons)result).length() == 1 && ((Cons)result).car() instanceof Pathname) { initTruename = (Pathname)result.car(); } else { String errorMessage = "Loadable FASL not found for " + pathname.printObject() + " in " + mergedPathname.printObject(); if (ifDoesNotExist) { return error(new FileError(errorMessage, mergedPathname)); } else { Debug.trace(errorMessage); return NIL; } } } truename = (Pathname)initTruename; } InputStream in = truename.getInputStream(); Debug.assertTrue(in != null); try { return loadFileFromStream(pathname, truename, new Stream(Symbol.SYSTEM_STREAM, in, Symbol.CHARACTER, externalFormat), verbose, print, false, returnLastResult); } finally { if (in != null) { try { in.close(); } catch (IOException e) { return error(new LispError(e.getMessage())); } } } } public static LispObject loadSystemFile(String filename, boolean auto) { LispThread thread = LispThread.currentThread(); if (auto) { final SpecialBindingsMark mark = thread.markSpecialBindings(); // Due to autoloading, we're not sure about the loader state. // Make sure that all reader relevant variables have known state. thread.bindSpecial(Symbol.CURRENT_READTABLE, STANDARD_READTABLE.symbolValue(thread)); thread.bindSpecial(Symbol.READ_BASE, Fixnum.constants[10]); thread.bindSpecial(Symbol.READ_SUPPRESS, NIL); thread.bindSpecial(Symbol.READ_EVAL, T); thread.bindSpecial(Symbol.READ_DEFAULT_FLOAT_FORMAT, Symbol.SINGLE_FLOAT); thread.bindSpecial(Symbol._PACKAGE_, PACKAGE_CL_USER); try { return loadSystemFile(filename, _AUTOLOAD_VERBOSE_.symbolValue(thread) != NIL, Symbol.LOAD_PRINT.symbolValue(thread) != NIL, auto); } finally { thread.resetSpecialBindings(mark); } } else { return loadSystemFile(filename, Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL, Symbol.LOAD_PRINT.symbolValue(thread) != NIL, auto); } } private static final Symbol FASL_LOADER = PACKAGE_SYS.intern("*FASL-LOADER*"); /** A file with this type in a packed FASL denotes the initial loader */ static final LispObject COMPILE_FILE_INIT_FASL_TYPE = new SimpleString("_"); private static final Pathname coercePathnameOrNull(LispObject p) { if (p == null) { return null; } Pathname result = null; try { result = (Pathname)p; } catch (Throwable t) { // XXX narrow me! return null; } return result; } public static final LispObject loadSystemFile(final String filename, boolean verbose, boolean print, boolean auto) { InputStream in = null; Pathname pathname = null; Pathname truename = null; pathname = (Pathname)Pathname.create(filename); LispObject bootPath = Site.getLispHome(); Pathname mergedPathname; if (bootPath instanceof Pathname) { mergedPathname = (Pathname)Symbol.MERGE_PATHNAMES.execute(pathname, bootPath); // So a PROBE-FILE won't attempt to merge when // *DEFAULT-PATHNAME-DEFAULTS* is a JAR if (mergedPathname.getDevice().equals(NIL) && !Utilities.isPlatformWindows) { mergedPathname.setDevice(Keyword.UNSPECIFIC); } } else { mergedPathname = pathname; } URL url = null; Pathname loadableFile = findLoadableFile(mergedPathname); if (loadableFile == null) { truename = null; } else { truename = (Pathname)Symbol.PROBE_FILE.execute(loadableFile); } final String COMPILE_FILE_TYPE = Lisp._COMPILE_FILE_TYPE_.symbolValue().getStringValue(); if (truename == null || truename.equals(NIL) || bootPath.equals(NIL)) { // Make an attempt to use the boot classpath String path = pathname.asEntryPath(); url = Lisp.class.getResource(path); if (url == null || url.toString().endsWith("/")) { url = Lisp.class.getResource(path.replace('-', '_') + "." + COMPILE_FILE_TYPE); if (url == null) { url = Lisp.class.getResource(path + ".lisp"); } } if (url == null) { return error(new LispError("Failed to find loadable system file " + "'" + path + "'" + " in boot classpath.")); } if (!bootPath.equals(NIL)) { Pathname urlPathname = (Pathname)URLPathname.create(url); loadableFile = findLoadableFile(urlPathname); truename = (Pathname)Symbol.PROBE_FILE.execute(loadableFile); if (truename.equals(NIL)) { return error(new LispError("Failed to find loadable system file in boot classpath " + "'" + url + "'")); } } else { truename = null; // We can't represent the FASL in a Pathname (q.v. OSGi) } } // Look for a init FASL inside a packed FASL if (truename != null && truename.getType().princToString().equals(COMPILE_FILE_TYPE) && ZipCache.checkZipFile(truename)) { Pathname init = (Pathname)Pathname.create(truename.getNamestring()); init.setType(COMPILE_FILE_INIT_FASL_TYPE); init.setName(new SimpleString("__loader__")); LispObject t = Symbol.PROBE_FILE.execute(init); if (t instanceof Pathname) { truename = (Pathname)t; } else { return error (new LispError("Failed to find loadable init FASL in " + "'" + init.getNamestring() + "'")); } } if (truename != null) { in = truename.getInputStream(); } else { try { Debug.assertTrue(url != null); in = url.openStream(); } catch (IOException e) { error(new FileError("Failed to load system file: " + "'" + filename + "'" + " from URL: " + "'" + url + "'")); } } if (in != null) { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(_WARN_ON_REDEFINITION_, NIL); thread.bindSpecial(FASL_LOADER, NIL); try { Stream stream = new Stream(Symbol.SYSTEM_STREAM, in, Symbol.CHARACTER); return loadFileFromStream(pathname, truename, stream, verbose, print, auto); } finally { thread.resetSpecialBindings(mark); try { in.close(); } catch (IOException e) { return error(new LispError(e.getMessage())); } } } return error(new FileError("Failed to load system file: " + "'" + filename + "'" + " resolved as " + "'" + mergedPathname + "'" , truename)); } // ### *fasl-version* // internal symbol static final Symbol _FASL_VERSION_ = exportConstant("*FASL-VERSION*", PACKAGE_SYS, Fixnum.getInstance(43)); // ### *fasl-external-format* // internal symbol private static final Symbol _FASL_EXTERNAL_FORMAT_ = internConstant("*FASL-EXTERNAL-FORMAT*", PACKAGE_SYS, new SimpleString("UTF-8")); // ### *fasl-uninterned-symbols* // internal symbol /** * This variable gets bound to NIL upon loading a FASL, but * gets set to a vector of symbols as one of the first actions * by the FASL itself. * */ public static final Symbol _FASL_UNINTERNED_SYMBOLS_ = internSpecial("*FASL-UNINTERNED-SYMBOLS*", PACKAGE_SYS, NIL); // Function to access the uninterned symbols "array" public final static LispObject getUninternedSymbol(int n) { LispThread thread = LispThread.currentThread(); LispObject uninternedSymbols = Load._FASL_UNINTERNED_SYMBOLS_.symbolValue(thread); if (! (uninternedSymbols instanceof Cons)) // it must be a vector return uninternedSymbols.AREF(n); // During normal loading, we won't get to this bit, however, // with eval-when processing, we may need to fall back to // *FASL-UNINTERNED-SYMBOLS* being an alist structure LispObject label = LispInteger.getInstance(n); while (uninternedSymbols != NIL) { LispObject item = uninternedSymbols.car(); if (label.eql(item.cdr())) return item.car(); uninternedSymbols = uninternedSymbols.cdr(); } return error(new LispError("No entry for uninterned symbol.")); } // ### init-fasl &key version private static final Primitive INIT_FASL = new init_fasl(); private static class init_fasl extends Primitive { init_fasl() { super("init-fasl", PACKAGE_SYS, true, "&key version"); } @Override public LispObject execute(LispObject first, LispObject second) { final LispThread thread = LispThread.currentThread(); if (first == Keyword.VERSION) { if (second.eql(_FASL_VERSION_.getSymbolValue())) { // OK thread.bindSpecial(_FASL_UNINTERNED_SYMBOLS_, NIL); thread.bindSpecial(_SOURCE_, NIL); return faslLoadStream(thread); } } return error(new SimpleError("FASL version mismatch; found '" + second.princToString() + "' but expected '" + _FASL_VERSION_.getSymbolValue().princToString() + "' in " + Symbol.LOAD_PATHNAME.symbolValue(thread).princToString() + " (try recompiling the file)")); } } private static final LispObject loadFileFromStream(Pathname pathname, Pathname truename, Stream in, boolean verbose, boolean print, boolean auto) { return loadFileFromStream(pathname == null ? NIL : pathname, truename == null ? NIL : truename, in, verbose, print, auto, false); } private static Symbol[] savedSpecials = new Symbol[] { // CLHS Specified Symbol.CURRENT_READTABLE, Symbol._PACKAGE_, // Compiler policy _SPEED_, _SPACE_, _SAFETY_, _DEBUG_, _EXPLAIN_ }; // A nil TRUENAME signals a load from stream which has no possible path private static final LispObject loadFileFromStream(LispObject pathname, LispObject truename, Stream in, boolean verbose, boolean print, boolean auto, boolean returnLastResult) { long start = System.currentTimeMillis(); final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); for (Symbol special : savedSpecials) thread.bindSpecialToCurrentValue(special); thread.bindSpecial(_BACKQUOTE_COUNT_, Fixnum.getInstance(0)); int loadDepth = Fixnum.getValue(_LOAD_DEPTH_.symbolValue(thread)); thread.bindSpecial(_LOAD_DEPTH_, Fixnum.getInstance(++loadDepth)); final String prefix = getLoadVerbosePrefix(loadDepth); try { thread.bindSpecial(Symbol.LOAD_PATHNAME, pathname); // The motivation behind the following piece of complexity // is the need to preserve the semantics of // *LOAD-TRUENAME* as always containing the truename of // the current "Lisp file". Since an ABCL packed FASL // actually has a Lisp file (aka "the init FASL") and one // or more Java classes from the compiler, we endeavor to // make *LOAD-TRUENAME* refer to the "overall" truename so // that a (LOAD *LOAD-TRUENAME*) would be equivalent to // reloading the complete current "Lisp file". If this // value diverges from the "true" truename, we set the // symbol SYS::*LOAD-TRUENAME-FASL* to that divergent // value. Currently the only code that uses this value is // Lisp.readFunctionBytes(). Pathname truePathname = null; if (!truename.equals(NIL)) { if (truename instanceof Pathname) { if (truename instanceof JarPathname) { truePathname = new JarPathname(); } else if (truename instanceof URLPathname) { truePathname = new URLPathname(); } else { truePathname = new Pathname(); } truePathname.copyFrom((Pathname)truename); } else if (truename instanceof AbstractString) { truePathname = (Pathname)Pathname.create(truename.getStringValue()); } else { Debug.assertTrue(false); } if (truePathname.getType().equal(Lisp._COMPILE_FILE_TYPE_.symbolValue(thread)) || truePathname.getType().equal(COMPILE_FILE_INIT_FASL_TYPE)) { Pathname truenameFasl = Pathname.create(truePathname); thread.bindSpecial(Symbol.LOAD_TRUENAME_FASL, truenameFasl); } if (truePathname.getType().equal(COMPILE_FILE_INIT_FASL_TYPE) && truePathname.isJar()) { // We set *LOAD-TRUENAME* to the argument that a // user would pass to LOAD. LispObject possibleTruePathname = probe_file.PROBE_FILE.execute(pathname); if (!possibleTruePathname.equals(NIL)) { truePathname = (Pathname) possibleTruePathname; } /* if (truePathname.getDevice().cdr() != NIL ) { Pathname enclosingJar = (Pathname)truePathname.getDevice().cdr().car(); truePathname.setDevice(new Cons(truePathname.getDevice().car(), NIL)); truePathname.setHost(NIL); truePathname.setDirectory(enclosingJar.getDirectory()); if (truePathname.getDirectory().car().equals(Keyword.RELATIVE)) { truePathname.getDirectory().setCar(Keyword.ABSOLUTE); } truePathname.setName(enclosingJar.getName()); truePathname.setType(enclosingJar.getType()); } else { // XXX There is something fishy in the asymmetry // between the "jar:jar:http:" and "jar:jar:file:" // cases but this currently passes the tests. if (!(truePathname.device.car() instanceof AbstractString)) { // assert truePathname.getDevice().car() instanceof Pathname; // Pathname p = Pathname.create((Pathname)truePathname.getDevice().car()); truePathname = (Pathname) probe_file.PROBE_FILE.execute(pathname); } } */ thread.bindSpecial(Symbol.LOAD_TRUENAME, truePathname); } else { thread.bindSpecial(Symbol.LOAD_TRUENAME, truename); } } else { thread.bindSpecial(Symbol.LOAD_TRUENAME, truename); } thread.bindSpecial(_SOURCE_, pathname != null ? pathname : NIL); if (verbose) { Stream out = getStandardOutput(); out.freshLine(); out._writeString(prefix); out._writeString(auto ? " Autoloading " : " Loading "); out._writeString(!truename.equals(NIL) ? truePathname.princToString() : "stream"); out._writeLine(" ..."); out._finishOutput(); LispObject result = loadStream(in, print, thread, returnLastResult); long elapsed = System.currentTimeMillis() - start; out.freshLine(); out._writeString(prefix); out._writeString(auto ? " Autoloaded " : " Loaded "); out._writeString(!truename.equals(NIL) ? truePathname.princToString() : "stream"); out._writeString(" ("); out._writeString(String.valueOf(((float)elapsed)/1000)); out._writeLine(" seconds)"); out._finishOutput(); return result; } else return loadStream(in, print, thread, returnLastResult); } finally { thread.resetSpecialBindings(mark); } } public static String getLoadVerbosePrefix(int loadDepth) { StringBuilder sb = new StringBuilder(";"); for (int i = loadDepth - 1; i-- > 0;) sb.append(' '); return sb.toString(); } private static final LispObject loadStream(Stream in, boolean print, LispThread thread, boolean returnLastResult) { final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(_LOAD_STREAM_, in); SpecialBinding sourcePositionBinding = thread.bindSpecial(_SOURCE_POSITION_, Fixnum.ZERO); try { final Environment env = new Environment(); LispObject result = NIL; while (true) { sourcePositionBinding.value = Fixnum.getInstance(in.getOffset()); LispObject obj = in.read(false, EOF, false, thread, Stream.currentReadtable); if (obj == EOF) break; result = eval(obj, env, thread); if (print) { Stream out = checkCharacterOutputStream(Symbol.STANDARD_OUTPUT.symbolValue(thread)); out._writeLine(result.printObject()); out._finishOutput(); } } if(returnLastResult) { return result; } else { return T; } } finally { thread.resetSpecialBindings(mark); } } static final LispObject faslLoadStream(LispThread thread) { Stream in = (Stream) _LOAD_STREAM_.symbolValue(thread); final Environment env = new Environment(); final SpecialBindingsMark mark = thread.markSpecialBindings(); LispObject result = NIL; try { // Same bindings are established in Lisp.readObjectFromString() thread.bindSpecial(Symbol.READ_BASE, LispInteger.getInstance(10)); thread.bindSpecial(Symbol.READ_EVAL, Symbol.T); thread.bindSpecial(Symbol.READ_SUPPRESS, Nil.NIL); in.setExternalFormat(_FASL_EXTERNAL_FORMAT_.symbolValue(thread)); while (true) { LispObject obj = in.read(false, EOF, false, // should be 'true' once we // have a FASL wide object table thread, Stream.faslReadtable); if (obj == EOF) break; result = eval(obj, env, thread); } } finally { thread.resetSpecialBindings(mark); } return result; //There's no point in using here the returnLastResult flag like in //loadStream(): this function is only called from init-fasl, which is //only called from load, which already has its own policy for choosing //whether to return T or the last value. } // ### %load filespec verbose print if-does-not-exist external-format=> generalized-boolean private static final Primitive _LOAD = new _load(); private static class _load extends Primitive { _load() { super("%load", PACKAGE_SYS, false, "filespec verbose print if-does-not-exist external-format"); } @Override public LispObject execute(LispObject filespec, LispObject verbose, LispObject print, LispObject ifDoesNotExist, LispObject externalFormat) { return load(filespec, verbose, print, ifDoesNotExist, NIL, externalFormat); } } // ### %load-returning-last-result filespec verbose print if-does-not-exist external-format => object private static final Primitive _LOAD_RETURNING_LAST_RESULT = new _load_returning_last_result(); private static class _load_returning_last_result extends Primitive { _load_returning_last_result() { super("%load-returning-last-result", PACKAGE_SYS, false, "filespec verbose print if-does-not-exist external-format"); } @Override public LispObject execute(LispObject filespec, LispObject verbose, LispObject print, LispObject ifDoesNotExist, LispObject externalFormat) { return load(filespec, verbose, print, ifDoesNotExist, T, externalFormat); } } static final LispObject load(LispObject filespec, LispObject verbose, LispObject print, LispObject ifDoesNotExist, LispObject returnLastResult, LispObject externalFormat) { if (filespec instanceof Stream) { if (((Stream)filespec).isOpen()) { // !?! in this case the external-format specifier is ignored: warn user? LispObject pathname; if (filespec instanceof FileStream) pathname = ((FileStream)filespec).getPathname(); else pathname = NIL; LispObject truename; if (pathname instanceof Pathname) truename = pathname; else truename = NIL; return loadFileFromStream(pathname, truename, (Stream) filespec, verbose != NIL, print != NIL, false, returnLastResult != NIL); } // If stream is closed, fall through... } Pathname pathname = coerceToPathname(filespec); if (pathname instanceof LogicalPathname) pathname = LogicalPathname.translateLogicalPathname((LogicalPathname)pathname); return load(pathname, verbose != NIL, print != NIL, ifDoesNotExist != NIL, returnLastResult != NIL, externalFormat); } // ### load-system-file private static final Primitive LOAD_SYSTEM_FILE = new load_system_file(); private static class load_system_file extends Primitive { load_system_file () { super("load-system-file", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { final LispThread thread = LispThread.currentThread(); return loadSystemFile(arg.getStringValue(), Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL || System.getProperty("abcl.autoload.verbose") != null, Symbol.LOAD_PRINT.symbolValue(thread) != NIL, false); } } } abcl-src-1.9.0/src/org/armedbear/lisp/LogicalPathname.java0100644 0000000 0000000 00000033070 14202767264 022115 0ustar000000000 0000000 /* * LogicalPathname.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.HashMap; import java.util.StringTokenizer; import java.text.MessageFormat; public final class LogicalPathname extends Pathname { public static final String LOGICAL_PATHNAME_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-;*."; private static final HashMap map = new HashMap(); // A logical host is represented as the string that names it. // (defvar *logical-pathname-translations* (make-hash-table :test 'equal)) public static HashTable TRANSLATIONS = HashTable.newEqualHashTable(LOGICAL_PATHNAME_CHARS.length(), NIL, NIL); private static final Symbol _TRANSLATIONS_ = exportSpecial("*LOGICAL-PATHNAME-TRANSLATIONS*", PACKAGE_SYS, TRANSLATIONS); static public boolean isValidLogicalPathname(String namestring) { if (!isValidURL(namestring)) { String host = getHostString(namestring); if (host != null && LogicalPathname.TRANSLATIONS.get(new SimpleString(host)) != null) { return true; } } return false; } protected LogicalPathname() { } // Used in Pathname._makePathname to indicate type for namestring public static LogicalPathname create() { return new LogicalPathname(); } public static LogicalPathname create(LogicalPathname p) { Pathname pathname = new Pathname(); pathname.copyFrom(p); LogicalPathname result = new LogicalPathname(); Pathname.ncoerce(pathname, result); return result; } public static LogicalPathname create(String namestring) { // parse host out then call create(host, rest); LogicalPathname result = null; if (LogicalPathname.isValidLogicalPathname(namestring)) { String h = LogicalPathname.getHostString(namestring); result = LogicalPathname.create(h, namestring.substring(namestring.indexOf(':') + 1)); return result; } error(new FileError("Failed to find a valid logical Pathname host in '" + namestring + "'", NIL)); // ??? return NIL as we don't have a // PATHNAME. Maybe signal a different // condition? return (LogicalPathname)UNREACHED; } public static LogicalPathname create(String host, String rest) { // This may be "too late" in the creation chain to be meaningful? SimpleString h = new SimpleString(host); if (LogicalPathname.TRANSLATIONS.get(h) == null) { // Logical pathnames are only valid when it's host exists String message = MessageFormat.format("'{0}' is not a defined logical host", host); error(new SimpleError(message)); } LogicalPathname result = new LogicalPathname(); final int limit = rest.length(); for (int i = 0; i < limit; i++) { char c = rest.charAt (i); if (LOGICAL_PATHNAME_CHARS.indexOf(c) < 0) { error(new ParseError("The character #\\" + c + " is not valid in a logical pathname.")); } } result.setHost(h); // "The device component of a logical pathname is always :UNSPECIFIC; // no other component of a logical pathname can be :UNSPECIFIC." result.setDevice(Keyword.UNSPECIFIC); int semi = rest.lastIndexOf(';'); if (semi >= 0) { // Directory. String d = rest.substring(0, semi + 1); result.setDirectory(parseDirectory(d)); rest = rest.substring(semi + 1); } else { // "If a relative-directory-marker precedes the directories, the // directory component parsed is as relative; otherwise, the // directory component is parsed as absolute." result.setDirectory(new Cons(Keyword.ABSOLUTE)); } int dot = rest.indexOf('.'); if (dot >= 0) { String n = rest.substring(0, dot); if (n.equals("*")) { result.setName(Keyword.WILD); } else { result.setName(new SimpleString(n.toUpperCase())); } rest = rest.substring(dot + 1); dot = rest.indexOf('.'); if (dot >= 0) { String t = rest.substring(0, dot); if (t.equals("*")) { result.setType(Keyword.WILD); } else { result.setType(new SimpleString(t.toUpperCase())); } // What's left is the version. String v = rest.substring(dot + 1); if (v.equals("*")) { result.setVersion(Keyword.WILD); } else if (v.equals("NEWEST") || v.equals("newest")) { result.setVersion(Keyword.NEWEST); } else { result.setVersion(PACKAGE_CL.intern("PARSE-INTEGER").execute(new SimpleString(v))); } } else { String t = rest; if (t.equals("*")) { result.setType(Keyword.WILD); } else { result.setType(new SimpleString(t.toUpperCase())); } } } else { String n = rest; if (n.equals("*")) { result.setName(Keyword.WILD); } else if (n.length() > 0) { result.setName(new SimpleString(n.toUpperCase())); } } return result; } public static final SimpleString canonicalizeStringComponent(AbstractString s) { final int limit = s.length(); for (int i = 0; i < limit; i++) { char c = s.charAt(i); if (LOGICAL_PATHNAME_CHARS.indexOf(c) < 0) { error(new ParseError("Invalid character #\\" + c + " in logical pathname component \"" + s + '"')); // Not reached. return null; } } return new SimpleString(s.getStringValue().toUpperCase()); } public static Pathname translateLogicalPathname(LogicalPathname pathname) { return (Pathname) Symbol.TRANSLATE_LOGICAL_PATHNAME.execute(pathname); } private static final LispObject parseDirectory(String s) { LispObject result; if (s.charAt(0) == ';') { result = new Cons(Keyword.RELATIVE); s = s.substring(1); } else result = new Cons(Keyword.ABSOLUTE); StringTokenizer st = new StringTokenizer(s, ";"); while (st.hasMoreTokens()) { String token = st.nextToken(); LispObject obj; if (token.equals("*")) obj = Keyword.WILD; else if (token.equals("**")) obj = Keyword.WILD_INFERIORS; else if (token.equals("..")) { if (result.car() instanceof AbstractString) { result = result.cdr(); continue; } obj= Keyword.UP; } else obj = new SimpleString(token.toUpperCase()); result = new Cons(obj, result); } return result.nreverse(); } @Override public LispObject typeOf() { return Symbol.LOGICAL_PATHNAME; } @Override public LispObject classOf() { return BuiltInClass.LOGICAL_PATHNAME; } @Override public LispObject typep(LispObject type) { if (type == Symbol.LOGICAL_PATHNAME) return T; if (type == BuiltInClass.LOGICAL_PATHNAME) return T; return super.typep(type); } @Override protected String getDirectoryNamestring() { StringBuilder sb = new StringBuilder(); // "If a pathname is converted to a namestring, the symbols NIL and // :UNSPECIFIC cause the field to be treated as if it were empty. That // is, both NIL and :UNSPECIFIC cause the component not to appear in // the namestring." 19.2.2.2.3.1 if (getDirectory() != NIL) { LispObject temp = getDirectory(); LispObject part = temp.car(); if (part == Keyword.ABSOLUTE) { } else if (part == Keyword.RELATIVE) sb.append(';'); else error(new FileError("Unsupported directory component " + part.princToString() + ".", this)); temp = temp.cdr(); while (temp != NIL) { part = temp.car(); if (part instanceof AbstractString) sb.append(part.getStringValue()); else if (part == Keyword.WILD) sb.append('*'); else if (part == Keyword.WILD_INFERIORS) sb.append("**"); else if (part == Keyword.UP) sb.append(".."); else error(new FileError("Unsupported directory component " + part.princToString() + ".", this)); sb.append(';'); temp = temp.cdr(); } } return sb.toString(); } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); boolean printReadably = (Symbol.PRINT_READABLY.symbolValue(thread) != NIL); boolean printEscape = (Symbol.PRINT_ESCAPE.symbolValue(thread) != NIL); StringBuilder sb = new StringBuilder(); if (printReadably || printEscape) sb.append("#P\""); sb.append(getHost().getStringValue()); sb.append(':'); if (getDirectory() != NIL) sb.append(getDirectoryNamestring()); if (getName() != NIL) { if (getName() == Keyword.WILD) sb.append('*'); else sb.append(getName().getStringValue()); } if (getType() != NIL) { sb.append('.'); if (getType() == Keyword.WILD) sb.append('*'); else sb.append(getType().getStringValue()); } if (getVersion().integerp()) { sb.append('.'); int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue(thread)); if (getVersion() instanceof Fixnum) sb.append(Integer.toString(((Fixnum)getVersion()).value, base).toUpperCase()); else if (getVersion() instanceof Bignum) sb.append(((Bignum)getVersion()).value.toString(base).toUpperCase()); } else if (getVersion() == Keyword.WILD) { sb.append(".*"); } else if (getVersion() == Keyword.NEWEST) { sb.append(".NEWEST"); } if (printReadably || printEscape) sb.append('"'); return sb.toString(); } // ### canonicalize-logical-host host => canonical-host private static final Primitive CANONICALIZE_LOGICAL_HOST = new canonicalize_logical_host(); private static class canonicalize_logical_host extends Primitive { canonicalize_logical_host() { super("canonicalize-logical-host", PACKAGE_SYS, true, "host"); } @Override public LispObject execute(LispObject arg) { AbstractString s = checkString(arg); if (s.length() == 0) { // "The null string, "", is not a valid value for any // component of a logical pathname." 19.3.2.2 return error(new LispError("Invalid logical host name: \"" + s.getStringValue() + '"')); } return canonicalizeStringComponent(s); } } // ### %make-logical-pathname namestring => logical-pathname private static final Primitive _MAKE_LOGICAL_PATHNAME = new _make_logical_pathname(); private static class _make_logical_pathname extends Primitive { _make_logical_pathname() { super("%make-logical-pathname", PACKAGE_SYS, true, "namestring"); } @Override public LispObject execute(LispObject arg) { // Check for a logical pathname host. String s = arg.getStringValue(); String h = getHostString(s); if (h != null) { if (h.length() == 0) { // "The null string, "", is not a valid value for any // component of a logical pathname." 19.3.2.2 return error(new LispError("Invalid logical host name: \"" + h + '"')); } if (LogicalPathname.TRANSLATIONS.get(new SimpleString(h)) != null) { // A defined logical pathname host. return LogicalPathname.create(h, s.substring(s.indexOf(':') + 1)); } } return error(new TypeError("Logical namestring does not specify a host: \"" + s + '"')); } } // "one or more uppercase letters, digits, and hyphens" protected static String getHostString(String s) { int colon = s.indexOf(':'); if (colon >= 0) { return s.substring(0, colon).toUpperCase(); } else { return null; } } public long getLastModified() { Pathname p = translateLogicalPathname(this); return p.getLastModified(); } } abcl-src-1.9.0/src/org/armedbear/lisp/MacroObject.java0100644 0000000 0000000 00000010061 14202767264 021250 0ustar000000000 0000000 /* * MacroObject.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class MacroObject extends Function { protected final LispObject name; public final LispObject expander; public MacroObject(LispObject name, LispObject expander) { this.name = name; this.expander = expander; if (name instanceof Symbol && name != NIL && expander instanceof Function) ((Function)expander).setLambdaName(list(Symbol.MACRO_FUNCTION, name)); } @Override public LispObject execute() { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject arg) { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject first, LispObject second) { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { return error(new UndefinedFunction(name)); } @Override public LispObject execute(LispObject[] args) { return error(new UndefinedFunction(name)); } @Override public String printObject() { return unreadableString("MACRO-OBJECT"); } } abcl-src-1.9.0/src/org/armedbear/lisp/Main.java0100644 0000000 0000000 00000004375 14202767264 017757 0ustar000000000 0000000 /* * Main.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class Main { public static final long startTimeMillis = System.currentTimeMillis(); public static void main(final String[] args) { // Run the interpreter in a secondary thread so we can control the stack // size. Runnable r = new Runnable() { public void run() { try { Interpreter interpreter = Interpreter.createDefaultInstance(args); if (interpreter != null) interpreter.run(); } catch (ProcessingTerminated e) { System.exit(e.getStatus()); } } }; new Thread(null, r, "interpreter", 4194304L).start(); } } abcl-src-1.9.0/src/org/armedbear/lisp/MathFunctions.java0100644 0000000 0000000 00000072001 14202767264 021644 0ustar000000000 0000000 /* * MathFunctions.java * * Copyright (C) 2004-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class MathFunctions { // Implementation of section 12.1.5.3, which says: // "If the result of any computation would be a complex number whose // real part is of type rational and whose imaginary part is zero, // the result is converted to the rational which is the real part." private static final LispObject complexToRealFixup(LispObject result, LispObject arg) { if (result instanceof Complex && ! (arg instanceof Complex)) { Complex c = (Complex)result; LispObject im = c.getImaginaryPart(); if (im.zerop()) return c.getRealPart(); } return result; } // ### sin private static final Primitive SIN = new Primitive("sin", "radians") { @Override public LispObject execute(LispObject arg) { return sin(arg); } }; static LispObject sin(LispObject arg) { if (arg instanceof DoubleFloat) return new DoubleFloat(Math.sin(((DoubleFloat)arg).value)); if (arg.realp()) return new SingleFloat((float)Math.sin(SingleFloat.coerceToFloat(arg).value)); if (arg instanceof Complex) { LispObject n = arg.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.ONE)); LispObject result = exp(n); result = result.subtract(exp(n.multiplyBy(Fixnum.MINUS_ONE))); return result.divideBy(Fixnum.TWO.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.ONE))); } return type_error(arg, Symbol.NUMBER); } // ### cos private static final Primitive COS = new Primitive("cos", "radians") { @Override public LispObject execute(LispObject arg) { return cos(arg); } }; static LispObject cos(LispObject arg) { if (arg instanceof DoubleFloat) return new DoubleFloat(Math.cos(((DoubleFloat)arg).value)); if (arg.realp()) return new SingleFloat((float)Math.cos(SingleFloat.coerceToFloat(arg).value)); if (arg instanceof Complex) { LispObject n = arg.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.ONE)); LispObject result = exp(n); result = result.add(exp(n.multiplyBy(Fixnum.MINUS_ONE))); return result.divideBy(Fixnum.TWO); } return type_error(arg, Symbol.NUMBER); } // ### tan private static final Primitive TAN = new Primitive("tan", "radians") { @Override public LispObject execute(LispObject arg) { if (arg instanceof DoubleFloat) return new DoubleFloat(Math.tan(((DoubleFloat)arg).value)); if (arg.realp()) return new SingleFloat((float)Math.tan(SingleFloat.coerceToFloat(arg).value)); return sin(arg).divideBy(cos(arg)); } }; // ### asin private static final Primitive ASIN = new Primitive("asin", "number") { @Override public LispObject execute(LispObject arg) { return asin(arg); } }; static LispObject asin(LispObject arg) { if (arg instanceof SingleFloat) { float f = ((SingleFloat)arg).value; if (Math.abs(f) <= 1) return new SingleFloat((float)Math.asin(f)); } if (arg instanceof DoubleFloat) { double d = ((DoubleFloat)arg).value; if (Math.abs(d) <= 1) return new DoubleFloat(Math.asin(d)); } LispObject result = arg.multiplyBy(arg); result = Fixnum.ONE.subtract(result); result = sqrt(result); LispObject n = Complex.getInstance(Fixnum.ZERO, Fixnum.ONE); n = n.multiplyBy(arg); result = n.add(result); result = log(result); result = result.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.MINUS_ONE)); return complexToRealFixup(result, arg); } // ### acos private static final Primitive ACOS = new Primitive("acos", "number") { @Override public LispObject execute(LispObject arg) { return acos(arg); } }; static LispObject acos(LispObject arg) { if (arg instanceof DoubleFloat) { double d = ((DoubleFloat)arg).value; if (Math.abs(d) <= 1) return new DoubleFloat(Math.acos(d)); } if (arg instanceof SingleFloat) { float f = ((SingleFloat)arg).value; if (Math.abs(f) <= 1) return new SingleFloat((float)Math.acos(f)); } LispObject result = new DoubleFloat(Math.PI/2); if (!(arg instanceof DoubleFloat)) { if (arg instanceof Complex && ((Complex)arg).getRealPart() instanceof DoubleFloat) { // do nothing; we want to keep the double float value } else result = new SingleFloat((float)((DoubleFloat)result).value); } result = result.subtract(asin(arg)); return complexToRealFixup(result, arg); } // ### atan private static final Primitive ATAN = new Primitive("atan", "number1 &optional number2") { @Override public LispObject execute(LispObject arg) { if (arg.numberp()) return atan(arg); return type_error(arg, Symbol.NUMBER); } // "If both number1 and number2 are supplied for atan, the result is // the arc tangent of number1/number2." // y = +0 x = +0 +0 // y = -0 x = +0 -0 // y = +0 x = -0 + // y = -0 x = -0 - @Override public LispObject execute(LispObject y, LispObject x) { if (!y.realp()) return type_error(y, Symbol.REAL); if (!x.realp()) return type_error(x, Symbol.REAL); double d1, d2; d1 = DoubleFloat.coerceToFloat(y).value; d2 = DoubleFloat.coerceToFloat(x).value; double result = Math.atan2(d1, d2); if (y instanceof DoubleFloat || x instanceof DoubleFloat) return new DoubleFloat(result); else return new SingleFloat((float)result); } }; static LispObject atan(LispObject arg) { if (arg instanceof Complex) { LispObject im = ((Complex)arg).imagpart; if (im.zerop()) return Complex.getInstance(atan(((Complex)arg).realpart), im); LispObject result = arg.multiplyBy(arg); result = result.add(Fixnum.ONE); result = Fixnum.ONE.divideBy(result); result = sqrt(result); LispObject n = Complex.getInstance(Fixnum.ZERO, Fixnum.ONE); n = n.multiplyBy(arg); n = n.add(Fixnum.ONE); result = n.multiplyBy(result); result = log(result); result = result.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.MINUS_ONE)); return result; } if (arg instanceof DoubleFloat) return new DoubleFloat(Math.atan(((DoubleFloat)arg).value)); return new SingleFloat((float)Math.atan(SingleFloat.coerceToFloat(arg).value)); } // ### sinh private static final Primitive SINH = new Primitive("sinh", "number") { @Override public LispObject execute(LispObject arg) { return sinh(arg); } }; static LispObject sinh(LispObject arg) { if (arg instanceof Complex) { LispObject im = ((Complex)arg).getImaginaryPart(); if (im.zerop()) return Complex.getInstance(sinh(((Complex)arg).getRealPart()), im); } if (arg instanceof SingleFloat) { double d = Math.sinh(((SingleFloat)arg).value); return new SingleFloat((float)d); } else if (arg instanceof DoubleFloat) { double d = Math.sinh(((DoubleFloat)arg).value); return new DoubleFloat(d); } LispObject result = exp(arg); result = result.subtract(exp(arg.multiplyBy(Fixnum.MINUS_ONE))); result = result.divideBy(Fixnum.TWO); return complexToRealFixup(result, arg); } // ### cosh private static final Primitive COSH = new Primitive("cosh", "number") { @Override public LispObject execute(LispObject arg) { return cosh(arg); } }; static LispObject cosh(LispObject arg) { if (arg instanceof Complex) { LispObject im = ((Complex)arg).getImaginaryPart(); if (im.zerop()) return Complex.getInstance(cosh(((Complex)arg).getRealPart()), im); } if (arg instanceof SingleFloat) { double d = Math.cosh(((SingleFloat)arg).value); return new SingleFloat((float)d); } else if (arg instanceof DoubleFloat) { double d = Math.cosh(((DoubleFloat)arg).value); return new DoubleFloat(d); } LispObject result = exp(arg); result = result.add(exp(arg.multiplyBy(Fixnum.MINUS_ONE))); result = result.divideBy(Fixnum.TWO); return complexToRealFixup(result, arg); } // ### tanh private static final Primitive TANH = new Primitive("tanh", "number") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) { double d = Math.tanh(((SingleFloat)arg).value); return new SingleFloat((float)d); } else if (arg instanceof DoubleFloat) { double d = Math.tanh(((DoubleFloat)arg).value); return new DoubleFloat(d); } return sinh(arg).divideBy(cosh(arg)); } }; // ### asinh private static final Primitive ASINH = new Primitive("asinh", "number") { @Override public LispObject execute(LispObject arg) { return asinh(arg); } }; static LispObject asinh(LispObject arg) { if (arg instanceof Complex) { LispObject im = ((Complex)arg).getImaginaryPart(); if (im.zerop()) return Complex.getInstance(asinh(((Complex)arg).getRealPart()), im); } LispObject result = arg.multiplyBy(arg); result = Fixnum.ONE.add(result); result = sqrt(result); result = result.add(arg); result = log(result); return complexToRealFixup(result, arg); } // ### acosh private static final Primitive ACOSH = new Primitive("acosh", "number") { @Override public LispObject execute(LispObject arg) { return acosh(arg); } }; static LispObject acosh(LispObject arg) { if (arg instanceof Complex) { LispObject im = ((Complex)arg).getImaginaryPart(); if (im.zerop()) return Complex.getInstance(acosh(((Complex)arg).getRealPart()), im); } LispObject n1 = arg.add(Fixnum.ONE); n1 = n1.divideBy(Fixnum.TWO); n1 = sqrt(n1); LispObject n2 = arg.subtract(Fixnum.ONE); n2 = n2.divideBy(Fixnum.TWO); n2 = sqrt(n2); LispObject result = n1.add(n2); result = log(result); result = result.multiplyBy(Fixnum.TWO); return complexToRealFixup(result, arg); } // ### atanh private static final Primitive ATANH = new Primitive("atanh", "number") { @Override public LispObject execute(LispObject arg) { return atanh(arg); } }; static LispObject atanh(LispObject arg) { if (arg instanceof Complex) { LispObject im = ((Complex)arg).getImaginaryPart(); if (im.zerop()) return Complex.getInstance(atanh(((Complex)arg).getRealPart()), im); } LispObject n1 = log(Fixnum.ONE.add(arg)); LispObject n2 = log(Fixnum.ONE.subtract(arg)); LispObject result = n1.subtract(n2); result = result.divideBy(Fixnum.TWO); return complexToRealFixup(result, arg); } // ### cis private static final Primitive CIS = new Primitive("cis", "radians") { @Override public LispObject execute(LispObject arg) { return cis(arg); } }; static LispObject cis(LispObject arg) { if (arg.realp()) return Complex.getInstance(cos(arg), sin(arg)); return type_error(arg, Symbol.REAL); } // ### exp private static final Primitive EXP = new Primitive("exp", "number") { @Override public LispObject execute(LispObject arg) { return exp(arg); } }; static LispObject exp(LispObject arg) { if (arg.realp()) { if (arg instanceof DoubleFloat) { double d = Math.pow(Math.E, ((DoubleFloat)arg).value); return OverUnderFlowCheck(new DoubleFloat(d)); } else { float f = (float) Math.pow(Math.E, SingleFloat.coerceToFloat(arg).value); return OverUnderFlowCheck(new SingleFloat(f)); } } if (arg instanceof Complex) { Complex c = (Complex) arg; return exp(c.getRealPart()).multiplyBy(cis(c.getImaginaryPart())); } return type_error(arg, Symbol.NUMBER); } // ### sqrt private static final Primitive SQRT = new Primitive("sqrt", "number") { @Override public LispObject execute(LispObject arg) { return sqrt(arg); } }; static final LispObject sqrt(LispObject obj) { if (obj instanceof DoubleFloat) { if (obj.minusp()) return Complex.getInstance(new DoubleFloat(0), sqrt(obj.negate())); return new DoubleFloat(Math.sqrt(DoubleFloat.coerceToFloat(obj).value)); } if (obj.realp()) { if (obj.minusp()) return Complex.getInstance(new SingleFloat(0), sqrt(obj.negate())); return new SingleFloat((float)Math.sqrt(SingleFloat.coerceToFloat(obj).value)); } if (obj instanceof Complex) { LispObject imagpart = ((Complex)obj).imagpart; if (imagpart.zerop()) { LispObject realpart = ((Complex)obj).realpart; if (realpart.minusp()) return Complex.getInstance(imagpart, sqrt(realpart.negate())); else return Complex.getInstance(sqrt(realpart), imagpart); } return exp(log(obj).divideBy(Fixnum.TWO)); } return type_error(obj, Symbol.NUMBER); } // ### log private static final Primitive LOG = new Primitive("log", "number &optional base") { @Override public LispObject execute(LispObject arg) { return log(arg); } @Override public LispObject execute(LispObject number, LispObject base) { if (number.realp() && !number.minusp() && base.isEqualTo(Fixnum.getInstance(10))) { double d = Math.log10(DoubleFloat.coerceToFloat(number).value); if (number instanceof DoubleFloat || base instanceof DoubleFloat) return new DoubleFloat(d); else return new SingleFloat((float)d); } return log(number).divideBy(log(base)); } }; static final LispObject log(LispObject obj) { if (obj.realp() && !obj.minusp()) { // Result is real. if (obj instanceof Fixnum) return new SingleFloat((float)Math.log(((Fixnum)obj).value)); if (obj instanceof Bignum) return new SingleFloat((float)Math.log(((Bignum)obj).doubleValue())); if (obj instanceof Ratio) return new SingleFloat((float)Math.log(((Ratio)obj).doubleValue())); if (obj instanceof SingleFloat) return new SingleFloat((float)Math.log(((SingleFloat)obj).value)); if (obj instanceof DoubleFloat) return new DoubleFloat(Math.log(((DoubleFloat)obj).value)); } else { // Result is complex. if (obj.realp() && obj.minusp()) { if (obj instanceof DoubleFloat) { DoubleFloat re = DoubleFloat.coerceToFloat(obj); DoubleFloat abs = new DoubleFloat(Math.abs(re.value)); DoubleFloat phase = new DoubleFloat(Math.PI); return Complex.getInstance(new DoubleFloat(Math.log(abs.getValue())), phase); } else { SingleFloat re = SingleFloat.coerceToFloat(obj); SingleFloat abs = new SingleFloat(Math.abs(re.value)); SingleFloat phase = new SingleFloat((float)Math.PI); return Complex.getInstance(new SingleFloat((float)Math.log(abs.value)), phase); } } else if (obj instanceof Complex) { if (((Complex)obj).getRealPart() instanceof DoubleFloat) { DoubleFloat re = DoubleFloat.coerceToFloat(((Complex)obj).getRealPart()); DoubleFloat im = DoubleFloat.coerceToFloat(((Complex)obj).getImaginaryPart()); DoubleFloat phase = new DoubleFloat(Math.atan2(im.getValue(), re.getValue())); // atan(y/x) DoubleFloat abs = DoubleFloat.coerceToFloat(obj.ABS()); return Complex.getInstance(new DoubleFloat(Math.log(abs.getValue())), phase); } else { SingleFloat re = SingleFloat.coerceToFloat(((Complex)obj).getRealPart()); SingleFloat im = SingleFloat.coerceToFloat(((Complex)obj).getImaginaryPart()); SingleFloat phase = new SingleFloat((float)Math.atan2(im.value, re.value)); // atan(y/x) SingleFloat abs = SingleFloat.coerceToFloat(obj.ABS()); return Complex.getInstance(new SingleFloat((float)Math.log(abs.value)), phase); } } } type_error(obj, Symbol.NUMBER); return NIL; } // ### expt base-number power-number => result public static final Primitive EXPT = new Primitive("expt", "base-number power-number") { @Override public LispObject execute(LispObject base, LispObject power) { if (power.zerop()) { if (power instanceof Fixnum) { if (base instanceof SingleFloat) return SingleFloat.ONE; if (base instanceof DoubleFloat) return DoubleFloat.ONE; if (base instanceof Complex) { if (((Complex)base).realpart instanceof SingleFloat) return Complex.getInstance(SingleFloat.ONE, SingleFloat.ZERO); if (((Complex)base).realpart instanceof DoubleFloat) return Complex.getInstance(DoubleFloat.ONE, DoubleFloat.ZERO); } return Fixnum.ONE; } if (power instanceof DoubleFloat) return DoubleFloat.ONE; if (base instanceof DoubleFloat) return DoubleFloat.ONE; return SingleFloat.ONE; } if (base.zerop()) return base; if (base.isEqualTo(1)) return base; if ((power instanceof Fixnum || power instanceof Bignum) && (base.rationalp() || (base instanceof Complex && ((Complex)base).realpart.rationalp()))) { // exact math version return intexp(base, power); } // for anything not a rational or complex rational, use // float approximation. boolean wantDoubleFloat = false; if (base instanceof DoubleFloat) wantDoubleFloat = true; else if (power instanceof DoubleFloat) wantDoubleFloat = true; else if (base instanceof Complex && (((Complex)base).getRealPart() instanceof DoubleFloat || ((Complex)base).getImaginaryPart() instanceof DoubleFloat)) wantDoubleFloat = true; else if (power instanceof Complex && (((Complex)power).getRealPart() instanceof DoubleFloat || ((Complex)power).getImaginaryPart() instanceof DoubleFloat)) wantDoubleFloat = true; if (wantDoubleFloat) { if (power instanceof Complex) power = ((Complex)power).coerceToDoubleFloat(); else power = DoubleFloat.coerceToFloat(power); if (base instanceof Complex) base = ((Complex)base).coerceToDoubleFloat(); else base = DoubleFloat.coerceToFloat(base); } if (base instanceof Complex || power instanceof Complex) return exp(power.multiplyBy(log(base))); final double x; // base final double y; // power if (base instanceof Fixnum) x = ((Fixnum)base).value; else if (base instanceof Bignum) x = ((Bignum)base).doubleValue(); else if (base instanceof Ratio) x = ((Ratio)base).doubleValue(); else if (base instanceof SingleFloat) x = ((SingleFloat)base).value; else if (base instanceof DoubleFloat) x = ((DoubleFloat)base).value; else return error(new LispError("EXPT: unsupported case: base is of type " + base.typeOf().princToString())); if (power instanceof Fixnum) y = ((Fixnum)power).value; else if (power instanceof Bignum) y = ((Bignum)power).doubleValue(); else if (power instanceof Ratio) y = ((Ratio)power).doubleValue(); else if (power instanceof SingleFloat) y = ((SingleFloat)power).value; else if (power instanceof DoubleFloat) y = ((DoubleFloat)power).value; else return error(new LispError("EXPT: unsupported case: power is of type " + power.typeOf().princToString())); double r = Math.pow(x, y); if (Double.isNaN(r)) { if (x < 0) { r = Math.pow(-x, y); double realPart = r * Math.cos(y * Math.PI); double imagPart = r * Math.sin(y * Math.PI); if (base instanceof DoubleFloat || power instanceof DoubleFloat) return Complex .getInstance(OverUnderFlowCheck(new DoubleFloat(realPart)), OverUnderFlowCheck(new DoubleFloat(imagPart))); else return Complex .getInstance(OverUnderFlowCheck(new SingleFloat((float)realPart)), OverUnderFlowCheck(new SingleFloat((float)imagPart))); } } if (base instanceof DoubleFloat || power instanceof DoubleFloat) return OverUnderFlowCheck(new DoubleFloat(r)); else return OverUnderFlowCheck(new SingleFloat((float)r)); } }; /** Checks number for over- or underflow values. * * @param number * @return number or signals an appropriate error */ final static LispObject OverUnderFlowCheck(LispObject number) { if (number instanceof Complex) { OverUnderFlowCheck(((Complex)number).realpart); OverUnderFlowCheck(((Complex)number).imagpart); return number; } if (TRAP_OVERFLOW) { if (number instanceof SingleFloat) if (Float.isInfinite(((SingleFloat)number).value)) return error(new FloatingPointOverflow(NIL)); if (number instanceof DoubleFloat) if (Double.isInfinite(((DoubleFloat)number).value)) return error(new FloatingPointOverflow(NIL)); } if (TRAP_UNDERFLOW) { if (number.zerop()) return error(new FloatingPointUnderflow(NIL)); } return number; } /** Checks number for over- or underflow values. * * @param number * @return number or signals an appropriate error */ final static float OverUnderFlowCheck(float number) { if (TRAP_OVERFLOW) { if (Float.isInfinite(number)) error(new FloatingPointOverflow(NIL)); } if (TRAP_UNDERFLOW) { if (number == 0) error(new FloatingPointUnderflow(NIL)); } return number; } /** Checks number for over- or underflow values. * * @param number * @return number or signals an appropriate error */ public final static double OverUnderFlowCheck(double number) { if (TRAP_OVERFLOW) { if (Double.isInfinite(number)) error(new FloatingPointOverflow(NIL)); } if (TRAP_UNDERFLOW) { if (number == 0) error(new FloatingPointUnderflow(NIL)); } return number; } // Adapted from SBCL. /** Return the exponent of base taken to the integer exponent power * * @param base A value of any type * @param power An integer (fixnum or bignum) value */ static final LispObject intexp(LispObject base, LispObject power) { if (power.isEqualTo(0)) return Fixnum.ONE; if (base.isEqualTo(1)) return base; if (base.isEqualTo(0)) return base; if (power.minusp()) { power = Fixnum.ZERO.subtract(power); return Fixnum.ONE.divideBy(intexp(base, power)); } if (base.eql(Fixnum.TWO)) return Fixnum.ONE.ash(power); LispObject nextn = power.ash(Fixnum.MINUS_ONE); LispObject total; if (power.oddp()) total = base; else total = Fixnum.ONE; while (true) { if (nextn.zerop()) return total; base = base.multiplyBy(base); if (nextn.oddp()) total = base.multiplyBy(total); nextn = nextn.ash(Fixnum.MINUS_ONE); } } } abcl-src-1.9.0/src/org/armedbear/lisp/MemoryClassLoader.java0100644 0000000 0000000 00000015076 14202767264 022460 0ustar000000000 0000000 /* * MemoryClassLoader.java * * Copyright (C) 2011 Erik Huelsmann * Copyright (C) 2010 Alessio Stalla * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.*; public class MemoryClassLoader extends JavaClassLoader { private final HashMap hashtable = new HashMap(); private final JavaObject boxedThis = new JavaObject(this); private final String internalNamePrefix; public MemoryClassLoader() { this("org/armedbear/lisp/"); } public MemoryClassLoader(String internalNamePrefix) { this.internalNamePrefix = internalNamePrefix; } public MemoryClassLoader(JavaClassLoader parent) { super(parent); this.internalNamePrefix = ""; } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { /* First we check if we should load the class ourselves, * allowing the default handlers to kick in if we don't... * * This strategy eliminates ClassNotFound exceptions inside * the inherited loadClass() eliminated ~80k exceptions during * Maxima compilation. Generally, creation of an exception object * is a pretty heavy operation, because it processes the call stack, * which - in ABCL - is pretty deep, most of the time. */ if (hashtable.containsKey(name)) { String internalName = internalNamePrefix + name; Class c = this.findLoadedClass(internalName); if (c == null) { c = findClass(name); } if (c != null) { if (resolve) { resolveClass(c); } return c; } } if (checkPreCompiledClassLoader) { Class c = findPrecompiledClassOrNull(name); if (c != null) { return c; } } // Fall through to our super's default handling return super.loadClass(name, resolve); } @Override protected Class findClass(String name) throws ClassNotFoundException { try { if (checkPreCompiledClassLoader) { Class c = findPrecompiledClassOrNull(name); if (c != null) return c; } byte[] b = getFunctionClassBytes(name); return defineLispClass(name, b, 0, b.length); } catch(Throwable e) { //TODO handle this better, readFunctionBytes uses Debug.assert() but should return null e.printStackTrace(); if(e instanceof ControlTransfer) { throw (ControlTransfer) e; } throw new ClassNotFoundException("Function class not found: " + name, e); } } public byte[] getFunctionClassBytes(String name) { if (hashtable.containsKey(name)) { return (byte[])hashtable.get(name).javaInstance(); } return super.getFunctionClassBytes(name); } public LispObject loadFunction(String name) { try { Class clz = loadClass(name); Function f = (Function) clz.newInstance(); getFunctionClassBytes(f); //as a side effect it sets them return f; } catch(Throwable e) { if(e instanceof ControlTransfer) { throw (ControlTransfer) e; } Debug.trace(e); return error(new LispError("Compiled function can't be loaded: " + name + " from memory")); } } private static final Primitive MAKE_MEMORY_CLASS_LOADER = new pf_make_memory_class_loader(); private static final class pf_make_memory_class_loader extends Primitive { pf_make_memory_class_loader() { super("make-memory-class-loader", PACKAGE_SYS, false); } @Override public LispObject execute() { return new MemoryClassLoader().boxedThis; } }; public static final Primitive PUT_MEMORY_FUNCTION = new pf_put_memory_function(); private static final class pf_put_memory_function extends Primitive { pf_put_memory_function() { super("put-memory-function", PACKAGE_SYS, false, "loader class-name class-bytes"); } @Override public LispObject execute(LispObject loader, LispObject className, LispObject classBytes) { MemoryClassLoader l = (MemoryClassLoader) loader.javaInstance(MemoryClassLoader.class); return (LispObject)l.hashtable.put(className.getStringValue(), (JavaObject)classBytes); } }; private static final Primitive GET_MEMORY_FUNCTION = new pf_get_memory_function(); private static final class pf_get_memory_function extends Primitive { pf_get_memory_function() { super("get-memory-function", PACKAGE_SYS, false, "loader class-name"); } @Override public LispObject execute(LispObject loader, LispObject name) { MemoryClassLoader l = (MemoryClassLoader) loader.javaInstance(MemoryClassLoader.class); return l.loadFunction(name.getStringValue()); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Nil.java0100644 0000000 0000000 00000010436 14202767264 017610 0ustar000000000 0000000 /* * Nil.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class Nil extends Symbol { final public static Symbol NIL = new Nil(PACKAGE_CL); public Nil(Package pkg) { super("NIL", pkg); pkg.addSymbol(this); initializeConstant(this); } @Override public Object javaInstance() { return null; } @Override public Object javaInstance(Class c) { if (c == Boolean.class || c == boolean.class) return Boolean.FALSE; return javaInstance(); } @Override public LispObject typeOf() { return Symbol.NULL; } @Override public LispObject classOf() { return BuiltInClass.NULL; } @Override public LispObject getDescription() { return new SimpleString("The symbol NIL"); } @Override public boolean getBooleanValue() { return false; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.NULL) return T; if (typeSpecifier == Symbol.LIST) return T; if (typeSpecifier == Symbol.SEQUENCE) return T; if (typeSpecifier == Symbol.SYMBOL) return T; if (typeSpecifier == Symbol.BOOLEAN) return T; if (typeSpecifier == BuiltInClass.NULL) return T; if (typeSpecifier == BuiltInClass.LIST) return T; if (typeSpecifier == BuiltInClass.SEQUENCE) return T; if (typeSpecifier == BuiltInClass.SYMBOL) return T; return super.typep(typeSpecifier); } @Override public boolean constantp() { return true; } @Override public final LispObject getSymbolValue() { return this; } @Override public int length() { return 0; } @Override public LispObject NTH(int index) { if (index < 0) error(new TypeError(String.valueOf(index) + " is not of type UNSIGNED-BYTE.")); return NIL; } @Override public LispObject elt(int index) { return error(new TypeError("ELT: invalid index " + index + " for " + this + ".")); } @Override public LispObject reverse() { return this; } @Override public LispObject nreverse() { return this; } @Override public LispObject[] copyToArray() { return new LispObject[0]; } @Override public LispObject NOT() { return T; } @Override public final LispObject getSymbolFunction() { return null; } public Object readResolve() throws java.io.ObjectStreamException { return NIL; } } abcl-src-1.9.0/src/org/armedbear/lisp/NilVector.java0100644 0000000 0000000 00000013732 14202767264 020775 0ustar000000000 0000000 /* * NilVector.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class NilVector extends AbstractString { private int capacity; public NilVector(int capacity) { this.capacity = capacity; } @Override public char[] chars() { if (capacity != 0) accessError(); return new char[0]; } @Override public char[] getStringChars() { if (capacity != 0) accessError(); return new char[0]; } @Override public String getStringValue() { if (capacity != 0) accessError(); return ""; } @Override public LispObject typeOf() { return list(Symbol.NIL_VECTOR, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.NIL_VECTOR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.NIL_VECTOR) return T; if (type == Symbol.SIMPLE_STRING) return T; if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.NIL_VECTOR) return T; if (type == BuiltInClass.SIMPLE_STRING) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public LispObject SIMPLE_STRING_P() { return T; } @Override public boolean equal(LispObject obj) { if (obj instanceof NilVector) { if (capacity != ((NilVector)obj).capacity) return false; if (capacity != 0) { accessError(); // Not reached. return false; } return true; } if (obj instanceof AbstractString) { if (capacity != obj.length()) return false; if (capacity != 0) { accessError(); // Not reached. return false; } return true; } return false; } public String getValue() { if (capacity == 0) return ""; accessError(); // Not reached. return null; } @Override public int length() { return capacity; } @Override public int capacity() { return capacity; } @Override public LispObject getElementType() { return NIL; } @Override public LispObject CHAR(int index) { return accessError(); } @Override public LispObject SCHAR(int index) { return accessError(); } @Override public LispObject AREF(int index) { return accessError(); } @Override public void aset(int index, LispObject newValue) { storeError(newValue); } @Override public char charAt(int index) { accessError(); // Not reached. return 0; } @Override public void setCharAt(int index, char c) { storeError(LispCharacter.getInstance(c)); } @Override public LispObject subseq(int start, int end) { if (capacity == 0 && start == 0 && end == 0) return this; return accessError(); } @Override public void fill(LispObject obj) { storeError(obj); } @Override public void fill(char c) { storeError(LispCharacter.getInstance(c)); } @Override public void shrink(int n) { } @Override public LispObject reverse() { return accessError(); } public LispObject accessError() { return error(new TypeError("Attempt to access an array of element type NIL.")); } private void storeError(LispObject obj) { error(new TypeError(String.valueOf(obj) + " is not of type NIL.")); } @Override public int sxhash() { return 0; } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { accessError(); // Not reached. return null; } @Override public AbstractVector adjustArray(int size, AbstractArray displacedTo, int displacement) { accessError(); // Not reached. return null; } } abcl-src-1.9.0/src/org/armedbear/lisp/Operator.java0100644 0000000 0000000 00000004765 14202767264 020671 0ustar000000000 0000000 /* * Operator.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class Operator extends LispObject { protected LispObject lambdaName; private LispObject lambdaList; public final LispObject getLambdaName() { return lambdaName; } public final void setLambdaName(LispObject obj) { lambdaName = obj; } public final LispObject getLambdaList() { if(lambdaList == null) { DocString ds = getClass().getAnnotation(DocString.class); if(ds != null) lambdaList = new SimpleString(ds.args()); } return lambdaList; } public final void setLambdaList(LispObject obj) { lambdaList = obj; } @Override public LispObject getParts() { LispObject result = NIL; result = result.push(new Cons("lambda-name", lambdaName)); result = result.push(new Cons("lambda-list", lambdaList)); return result.nreverse(); } } abcl-src-1.9.0/src/org/armedbear/lisp/Package.java0100644 0000000 0000000 00000075743 14223403213 020415 0ustar000000000 0000000 /* * Package.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentHashMap; public final class Package extends LispObject implements java.io.Serializable { private String name; private transient SimpleString lispName; private transient LispObject propertyList; /** Symbols internal to the package. */ private transient final ConcurrentHashMap internalSymbols = new ConcurrentHashMap(16); /** Symbols exported from the package. * * Those symbols in this collection are not contained in the internalSymbols */ private transient final ConcurrentHashMap externalSymbols = new ConcurrentHashMap(16); private transient HashMap shadowingSymbols; private transient ArrayList nicknames; private transient LispObject useList = null; private transient ArrayList usedByList = null; private transient ConcurrentHashMap localNicknames; // Anonymous package. public Package() { } public Package(String name) { this.name = name; lispName = new SimpleString(name); } public Package(String name, int size) { this.name = name; lispName = new SimpleString(name); } @Override public LispObject typeOf() { return Symbol.PACKAGE; } @Override public LispObject classOf() { return BuiltInClass.PACKAGE; } @Override public LispObject getDescription() { if (name != null) { StringBuilder sb = new StringBuilder("The "); sb.append(name); sb.append(" package"); return new SimpleString(sb); } return new SimpleString("PACKAGE"); } @Override public LispObject typep(LispObject type) { if (type == Symbol.PACKAGE) return T; if (type == BuiltInClass.PACKAGE) return T; return super.typep(type); } public final String getName() { return name; } public final LispObject NAME() { return lispName != null ? lispName : NIL; } @Override public final LispObject getPropertyList() { if (propertyList == null) propertyList = NIL; return propertyList; } @Override public final void setPropertyList(LispObject obj) { if (obj == null) throw new NullPointerException(); propertyList = obj; } public final List getNicknames() { return nicknames; } private void makeSymbolsUninterned(ConcurrentHashMap symbolMap) { Symbol sym; for (Iterator it = symbolMap.values().iterator(); it.hasNext();) { sym = it.next(); if (sym.getPackage() == this) { sym.setPackage(NIL); } } symbolMap.clear(); } public final synchronized boolean delete() { if (name != null) { if(useList instanceof Cons) { LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); unusePackage(pkg); usedPackages = usedPackages.cdr(); } } if (usedByList != null) { while (!usedByList.isEmpty()) { usedByList.get(0).unusePackage(this); } } LispObject packages = Packages.getPackagesNicknamingPackage(this); while (packages != NIL) { Package p = (Package)((Cons)packages).car(); packages = ((Cons)packages).cdr(); p.removeLocalPackageNicknamesForPackage(this); } Packages.deletePackage(this); makeSymbolsUninterned(internalSymbols); makeSymbolsUninterned(externalSymbols); // also clears externalSymbols name = null; lispName = null; nicknames = null; return true; } return false; } public final synchronized void rename(String newName, LispObject newNicks) { ArrayList arrayList = null; while (newNicks != NIL) { if (arrayList == null) arrayList = new ArrayList(); arrayList.add(javaString(newNicks.car())); newNicks = newNicks.cdr(); } // Remove old name and nicknames from Packages map. Packages.deletePackage(this); // Now change the names... name = newName; lispName = new SimpleString(newName); nicknames = arrayList; // And add the package back. Packages.addPackage(this); } public Symbol findInternalSymbol(SimpleString name) { return internalSymbols.get(name.toString()); } public Symbol findInternalSymbol(String name) { return internalSymbols.get(name); } public Symbol findExternalSymbol(SimpleString name) { return externalSymbols.get(name.toString()); } public Symbol findExternalSymbol(String name) { return externalSymbols.get(name); } public Symbol findExternalSymbol(SimpleString name, int hash) { return externalSymbols.get(name.toString()); } // Returns null if symbol is not accessible in this package. public Symbol findAccessibleSymbol(String name) { return findAccessibleSymbol(new SimpleString(name)); } // Returns null if symbol is not accessible in this package. public Symbol findAccessibleSymbol(SimpleString name) { // Look in external and internal symbols of this package. Symbol symbol = externalSymbols.get(name.toString()); if (symbol != null) return symbol; symbol = internalSymbols.get(name.toString()); if (symbol != null) return symbol; // Look in external symbols of used packages. if (useList instanceof Cons) { LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); symbol = pkg.findExternalSymbol(name); if (symbol != null) return symbol; usedPackages = usedPackages.cdr(); } } // Not found. return null; } public LispObject findSymbol(String name) { final SimpleString s = new SimpleString(name); final LispThread thread = LispThread.currentThread(); // Look in external and internal symbols of this package. Symbol symbol = externalSymbols.get(name); if (symbol != null) return thread.setValues(symbol, Keyword.EXTERNAL); symbol = internalSymbols.get(name); if (symbol != null) return thread.setValues(symbol, Keyword.INTERNAL); // Look in external symbols of used packages. if (useList instanceof Cons) { LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); symbol = pkg.findExternalSymbol(s); if (symbol != null) return thread.setValues(symbol, Keyword.INHERITED); usedPackages = usedPackages.cdr(); } } // Not found. return thread.setValues(NIL, NIL); } // Helper function to add NIL to PACKAGE_CL. public void addSymbol(Symbol symbol) { Debug.assertTrue(symbol.getPackage() == this); Debug.assertTrue(symbol.getName().equals("NIL")); externalSymbols.put(symbol.name.toString(), symbol); } private Symbol addSymbol(String name) { Symbol symbol = new Symbol(name, this); if (this == PACKAGE_KEYWORD) { symbol.initializeConstant(symbol); externalSymbols.put(name.toString(), symbol); } else internalSymbols.put(name.toString(), symbol); return symbol; } private Symbol addSymbol(SimpleString name) { return addSymbol(name.toString()); } public Symbol addInternalSymbol(String symbolName) { final Symbol symbol = new Symbol(symbolName, this); internalSymbols.put(symbolName, symbol); return symbol; } public Symbol addExternalSymbol(String symbolName) { final Symbol symbol = new Symbol(symbolName, this); externalSymbols.put(symbolName, symbol); return symbol; } public synchronized Symbol intern(SimpleString symbolName) { return intern(symbolName.toString()); } public synchronized Symbol intern(String symbolName) { // Look in external and internal symbols of this package. Symbol symbol = externalSymbols.get(symbolName); if (symbol != null) return symbol; symbol = internalSymbols.get(symbolName); if (symbol != null) return symbol; // Look in external symbols of used packages. if (useList instanceof Cons) { LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); symbol = pkg.externalSymbols.get(symbolName); if (symbol != null) return symbol; usedPackages = usedPackages.cdr(); } } // Not found. return addSymbol(symbolName); } public synchronized Symbol intern(final SimpleString s, final LispThread thread) { // Look in external and internal symbols of this package. Symbol symbol = externalSymbols.get(s.toString()); if (symbol != null) return (Symbol) thread.setValues(symbol, Keyword.EXTERNAL); symbol = internalSymbols.get(s.toString()); if (symbol != null) return (Symbol) thread.setValues(symbol, Keyword.INTERNAL); // Look in external symbols of used packages. if (useList instanceof Cons) { LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); symbol = pkg.findExternalSymbol(s); if (symbol != null) return (Symbol) thread.setValues(symbol, Keyword.INHERITED); usedPackages = usedPackages.cdr(); } } // Not found. return (Symbol) thread.setValues(addSymbol(s), NIL); } public synchronized Symbol internAndExport(String symbolName) { final SimpleString s = new SimpleString(symbolName); // Look in external and internal symbols of this package. Symbol symbol = externalSymbols.get(s.toString()); if (symbol != null) return symbol; symbol = internalSymbols.get(s.toString()); if (symbol != null) { export(symbol); return symbol; } if (useList instanceof Cons) { // Look in external symbols of used packages. LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); symbol = pkg.findExternalSymbol(s); if (symbol != null) { export(symbol); return symbol; } usedPackages = usedPackages.cdr(); } } // Not found. symbol = new Symbol(s, this); if (this == PACKAGE_KEYWORD) symbol.initializeConstant(symbol); externalSymbols.put(s.toString(), symbol); return symbol; } public synchronized LispObject unintern(final Symbol symbol) { final String symbolName = symbol.getName(); final boolean shadow; if (shadowingSymbols != null && shadowingSymbols.get(symbolName) == symbol) shadow = true; else shadow = false; if (shadow) { // Check for conflicts that might be exposed in used package list // if we remove the shadowing symbol. Symbol sym = null; if (useList instanceof Cons) { LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); Symbol s = pkg.findExternalSymbol(symbol.name); if (s != null) { if (sym == null) sym = s; else if (sym != s) { StringBuilder sb = new StringBuilder("Uninterning the symbol "); sb.append(symbol.getQualifiedName()); sb.append(" causes a name conflict between "); sb.append(sym.getQualifiedName()); sb.append(" and "); sb.append(s.getQualifiedName()); return error(new PackageError(sb.toString(), this)); } } usedPackages = usedPackages.cdr(); } } } // Reaching here, it's OK to remove the symbol. boolean found = false; if (externalSymbols.get(symbol.name.toString()) == symbol) { externalSymbols.remove(symbol.name.toString()); found = true; } if (internalSymbols.get(symbol.name.toString()) == symbol) { internalSymbols.remove(symbol.name.toString()); found = true; } if (! found) return NIL; if (shadow) { Debug.assertTrue(shadowingSymbols != null); shadowingSymbols.remove(symbolName); } if (symbol.getPackage() == this) symbol.setPackage(NIL); return T; } public synchronized void importSymbol(Symbol symbol) { if (symbol.getPackage() == this) return; // Nothing to do. Symbol sym = findAccessibleSymbol(symbol.name); if (sym != null && sym != symbol) { StringBuilder sb = new StringBuilder("The symbol "); sb.append(sym.getQualifiedName()); sb.append(" is already accessible in package "); sb.append(name); sb.append('.'); error(new PackageError(sb.toString(), this)); } internalSymbols.put(symbol.name.toString(), symbol); if (symbol.getPackage() == NIL) symbol.setPackage(this); } public synchronized void export(final Symbol symbol) { final String symbolName = symbol.getName(); boolean added = false; if (symbol.getPackage() != this) { Symbol sym = findAccessibleSymbol(symbol.name); if (sym != symbol) { StringBuilder sb = new StringBuilder("The symbol "); sb.append(symbol.getQualifiedName()); sb.append(" is not accessible in package "); sb.append(name); sb.append('.'); error(new PackageError(sb.toString(), this)); return; } internalSymbols.put(symbol.name.toString(), symbol); added = true; } if (added || internalSymbols.get(symbol.name.toString()) == symbol) { if (usedByList != null) { for (Iterator it = usedByList.iterator(); it.hasNext();) { Package pkg = (Package) it.next(); Symbol sym = pkg.findAccessibleSymbol(symbol.name); if (sym != null && sym != symbol) { if (pkg.shadowingSymbols != null && pkg.shadowingSymbols.get(symbolName) == sym) { // OK. } else { StringBuilder sb = new StringBuilder("The symbol "); sb.append(sym.getQualifiedName()); sb.append(" is already accessible in package "); sb.append(pkg.getName()); sb.append('.'); error(new PackageError(sb.toString(), pkg)); return; } } } } // No conflicts. internalSymbols.remove(symbol.name.toString()); externalSymbols.put(symbol.name.toString(), symbol); return; } if (externalSymbols.get(symbol.name.toString()) == symbol) // Symbol is already exported; there's nothing to do. return; StringBuilder sb = new StringBuilder("The symbol "); sb.append(symbol.getQualifiedName()); sb.append(" is not accessible in package "); sb.append(name); sb.append('.'); error(new PackageError(sb.toString(), this)); } public synchronized void unexport(final Symbol symbol) { if (externalSymbols.get(symbol.name.toString()) == symbol) { externalSymbols.remove(symbol.name.toString()); internalSymbols.put(symbol.name.toString(), symbol); } else if (findAccessibleSymbol(symbol.name.toString()) != symbol) { StringBuilder sb = new StringBuilder("The symbol "); sb.append(symbol.getQualifiedName()); sb.append(" is not accessible in package "); sb.append(name); error(new PackageError(sb.toString(), this)); } } public synchronized void shadow(final String symbolName) { if (shadowingSymbols == null) shadowingSymbols = new HashMap(); final SimpleString s = new SimpleString(symbolName); Symbol symbol = externalSymbols.get(s.toString()); if (symbol != null) { shadowingSymbols.put(symbolName, symbol); return; } symbol = internalSymbols.get(s.toString()); if (symbol != null) { shadowingSymbols.put(symbolName, symbol); return; } if (shadowingSymbols.get(symbolName) != null) return; symbol = new Symbol(s, this); internalSymbols.put(s.toString(), symbol); shadowingSymbols.put(symbolName, symbol); } public synchronized void shadowingImport(Symbol symbol) { final String symbolName = symbol.getName(); Symbol sym = externalSymbols.get(symbolName); if (sym == null) sym = internalSymbols.get(symbol.name.toString()); // if a different symbol with the same name is accessible, // [..] which implies that it must be uninterned if it was present if (sym != null && sym != symbol) { if (shadowingSymbols != null) shadowingSymbols.remove(symbolName); unintern(sym); } if (sym == null || sym != symbol) { // there was no symbol, or we just unintered it another one // intern the new one internalSymbols.put(symbol.name.toString(), symbol); } if (shadowingSymbols == null) shadowingSymbols = new HashMap(); shadowingSymbols.put(symbolName, symbol); } // "USE-PACKAGE causes PACKAGE to inherit all the external symbols of // PACKAGES-TO-USE. The inherited symbols become accessible as internal // symbols of PACKAGE." public void usePackage(Package pkg) { if (useList == null) useList = NIL; if (!memq(pkg, useList)) { // "USE-PACKAGE checks for name conflicts between the newly // imported symbols and those already accessible in package." Collection symbols = pkg.getExternalSymbols(); for (Iterator i = symbols.iterator(); i.hasNext();) { Symbol symbol = i.next(); Symbol existing = findAccessibleSymbol(symbol.name); if (existing != null && existing != symbol) { if (shadowingSymbols == null || shadowingSymbols.get(symbol.getName()) == null) { error(new PackageError("A symbol named " + symbol.getName() + " is already accessible in package " + name + ".", this)); return; } } } useList = useList.push(pkg); // Add this package to the used-by list of pkg. if (pkg.usedByList != null) Debug.assertTrue(!pkg.usedByList.contains(this)); if (pkg.usedByList == null) pkg.usedByList = new ArrayList(); pkg.usedByList.add(this); } } public void unusePackage(Package pkg) { if (useList instanceof Cons) { if (memq(pkg, useList)) { // FIXME Modify the original list instead of copying it! LispObject newList = NIL; while (useList != NIL) { if (useList.car() != pkg) newList = newList.push(useList.car()); useList = useList.cdr(); } useList = newList.nreverse(); Debug.assertTrue(!memq(pkg, useList)); Debug.assertTrue(pkg.usedByList != null); Debug.assertTrue(pkg.usedByList.contains(this)); pkg.usedByList.remove(this); } } } public final void addNickname(String s) { // This call will signal an error if there's a naming conflict. Packages.addNickname(this, s); if (nicknames != null) { if (nicknames.contains(s)) return; // Nothing to do. } else nicknames = new ArrayList(); nicknames.add(s); } public String getNickname() { if (nicknames != null && nicknames.size() > 0) return (String) nicknames.get(0); return null; } public LispObject packageNicknames() { LispObject list = NIL; if (nicknames != null) { for (int i = nicknames.size(); i-- > 0;) { String nickname = (String) nicknames.get(i); list = new Cons(new SimpleString(nickname), list); } } return list; } public LispObject getUseList() { if (useList == null) useList = NIL; return useList; } public boolean uses(LispObject pkg) { return (useList instanceof Cons) && memq(pkg, useList); } public LispObject getUsedByList() { LispObject list = NIL; if (usedByList != null) { for (Iterator it = usedByList.iterator(); it.hasNext();) { Package pkg = (Package) it.next(); list = new Cons(pkg, list); } } return list; } public LispObject getLocalPackageNicknames() { LispObject list = NIL; if (localNicknames != null) { for (Map.Entry entry : localNicknames.entrySet()) { list = new Cons(new Cons(entry.getKey(), entry.getValue()), list); } } return list; } public LispObject addLocalPackageNickname(String name, Package pack) { if (localNicknames == null) { localNicknames = new ConcurrentHashMap(); } if (localNicknames.containsKey(name)) { if (localNicknames.get(name) != pack) { return error(new LispError(name + " is already a nickname for " + pack.getName())); } else { // nothing to do return this; } } else { localNicknames.put(name, pack); return this; } } public LispObject removeLocalPackageNickname(String name) { if (localNicknames == null || !localNicknames.containsKey(name)) { return NIL; } else { // return generalized boolean: package that was nicknamed to `name' return localNicknames.remove(name); } } public void removeLocalPackageNicknamesForPackage(Package p) { if (localNicknames == null || !localNicknames.containsValue(p)) { return; } else { for (Map.Entry entry : localNicknames.entrySet()) { if (entry.getValue() == p) { localNicknames.remove(entry.getKey()); } } } } public Collection getLocallyNicknamedPackages() { // for implementing package-locally-nicknamed-by-list if (localNicknames == null) return new ArrayList(); else return localNicknames.values(); } // Find package named `name', taking local nicknames into account public Package findPackage(String name) { if (localNicknames != null) { Package pkg = localNicknames.get(name); if (pkg != null) return pkg; } return Packages.findPackageGlobally(name); } public LispObject getShadowingSymbols() { LispObject list = NIL; if (shadowingSymbols != null) { for (Iterator it = shadowingSymbols.values().iterator(); it.hasNext();) { Symbol symbol = (Symbol) it.next(); list = new Cons(symbol, list); } } return list; } public synchronized Collection getExternalSymbols() { return externalSymbols.values(); } public synchronized List getAccessibleSymbols() { ArrayList list = new ArrayList(); list.addAll(internalSymbols.values()); list.addAll(externalSymbols.values()); if (useList instanceof Cons) { LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); list.addAll(pkg.externalSymbols.values()); usedPackages = usedPackages.cdr(); } } return list; } public synchronized LispObject PACKAGE_INTERNAL_SYMBOLS() { LispObject list = NIL; Collection symbols = internalSymbols.values(); for (Iterator i = symbols.iterator(); i.hasNext();) list = new Cons(i.next(), list); return list; } public synchronized LispObject PACKAGE_EXTERNAL_SYMBOLS() { LispObject list = NIL; Collection symbols = externalSymbols.values(); for (Iterator i = symbols.iterator(); i.hasNext();) list = new Cons(i.next(), list); return list; } public synchronized LispObject PACKAGE_INHERITED_SYMBOLS() { LispObject list = NIL; if (useList instanceof Cons) { LispObject usedPackages = useList; while (usedPackages != NIL) { Package pkg = (Package) usedPackages.car(); Collection externals = pkg.getExternalSymbols(); for (Iterator i = externals.iterator(); i.hasNext();) { Symbol symbol = i.next(); if (shadowingSymbols != null && shadowingSymbols.get(symbol.getName()) != null) continue; if (externalSymbols.get(symbol.name.toString()) == symbol) continue; list = new Cons(symbol, list); } usedPackages = usedPackages.cdr(); } } return list; } public synchronized LispObject getSymbols() { LispObject list = NIL; Collection internals = internalSymbols.values(); for (Iterator i = internals.iterator(); i.hasNext();) list = new Cons(i.next(), list); Collection externals = externalSymbols.values(); for (Iterator i = externals.iterator(); i.hasNext();) list = new Cons(i.next(), list); return list; } public synchronized Symbol[] symbols() { Collection internals = internalSymbols.values(); Collection externals = externalSymbols.values(); Symbol[] array = new Symbol[internals.size() + externals.size()]; int i = 0; for (Iterator it = internals.iterator(); it.hasNext();) { Symbol symbol = (Symbol) it.next(); array[i++] = symbol; } for (Iterator it = externals.iterator(); it.hasNext();) { Symbol symbol = (Symbol) it.next(); array[i++] = symbol; } return array; } @Override public String printObject() { if (_PRINT_FASL_.symbolValue() != NIL && name != null) { StringBuilder sb = new StringBuilder("#.(CL:FIND-PACKAGE \""); sb.append(name); sb.append("\")"); return sb.toString(); } else { if (name != null) { return unreadableString("PACKAGE " + name, false); } else return unreadableString("PACKAGE"); } } public Object readResolve() throws java.io.ObjectStreamException { Package pkg = findPackage(name); if(pkg != null) { return pkg; } else { return error(new PackageError(name + " is not the name of a package.", new SimpleString(name))); } } } abcl-src-1.9.0/src/org/armedbear/lisp/PackageError.java0100644 0000000 0000000 00000011216 14202767264 021430 0ustar000000000 0000000 /* * PackageError.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class PackageError extends LispError { public PackageError(LispObject initArgs) { super(StandardClass.PACKAGE_ERROR); initialize(initArgs); } @Override protected void initialize(LispObject initArgs) { super.initialize(initArgs); if (initArgs.listp() && initArgs.car().stringp()) { setFormatControl(initArgs.car().getStringValue()); // When printing an error string, presumably, if the string contains // a symbol, we'll want to complain about its full name, not the accessible // name, because it may omit an (important) package name part. // Two problems: (1) symbols can be contained in sublists // (2) symbols may not be printed, but used otherwise. // ### FIXME: why special-case that here: binding *PRINT-ESCAPE* to T // will do exactly this, if the reader requests it. for (LispObject arg = initArgs.cdr(); arg != NIL; arg = arg.cdr()) { if (arg.car() instanceof Symbol) arg.setCar(new SimpleString(((Symbol)arg.car()).getQualifiedName())); } setFormatArguments(initArgs.cdr()); setPackage(NIL); return; } LispObject pkg = NIL; LispObject first, second; while (initArgs != NIL) { first = initArgs.car(); initArgs = initArgs.cdr(); second = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.PACKAGE) pkg = second; } setPackage(pkg); } public PackageError(String message) { super(StandardClass.PACKAGE_ERROR); setFormatControl(message); setPackage(NIL); } public PackageError(String message, LispObject pkg) { super(StandardClass.PACKAGE_ERROR); setFormatControl(message); setPackage(pkg); } @Override public LispObject typeOf() { return Symbol.PACKAGE_ERROR; } @Override public LispObject classOf() { return StandardClass.PACKAGE_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.PACKAGE_ERROR) return T; if (type == StandardClass.PACKAGE_ERROR) return T; return super.typep(type); } public LispObject getPackage() { return getInstanceSlotValue(Symbol.PACKAGE); } public void setPackage(LispObject pkg) { setInstanceSlotValue(Symbol.PACKAGE, pkg); } // ### package-error-package private static final Primitive PACKAGE_ERROR_PACKAGE = new Primitive("package-error-package", "condition") { @Override public LispObject execute(LispObject arg) { if (arg.typep(Symbol.PACKAGE_ERROR) == NIL) { return type_error(arg, Symbol.PACKAGE_ERROR); } final StandardObject obj = (StandardObject) arg; return obj.getInstanceSlotValue(Symbol.PACKAGE); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/PackageFunctions.java0100644 0000000 0000000 00000041374 14202767264 022317 0ustar000000000 0000000 /* * PackageFunctions.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class PackageFunctions { // ### packagep // packagep object => generalized-boolean private static final Primitive PACKAGEP = new Primitive("packagep", "object") { @Override public LispObject execute(LispObject arg) { return arg instanceof Package ? T : NIL; } }; // ### package-name // package-name package => nicknames private static final Primitive PACKAGE_NAME = new Primitive("package-name", "package") { @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).NAME(); } }; // ### package-nicknames // package-nicknames package => nicknames private static final Primitive PACKAGE_NICKNAMES = new Primitive("package-nicknames", "package") { @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).packageNicknames(); } }; // ### package-use-list // package-use-list package => use-list private static final Primitive PACKAGE_USE_LIST = new Primitive("package-use-list", "package") { @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).getUseList(); } }; // ### package-used-by-list // package-used-by-list package => used-by-list private static final Primitive PACKAGE_USED_BY_LIST = new Primitive("package-used-by-list", "package") { @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).getUsedByList(); } }; // ### %import // %import symbols &optional package => t private static final Primitive _IMPORT = new Primitive("%import", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject[] args) { if (args.length == 0 || args.length > 2) return error(new WrongNumberOfArgumentsException(this, 1, 2)); LispObject symbols = args[0]; Package pkg = args.length == 2 ? coerceToPackage(args[1]) : getCurrentPackage(); if (symbols.listp()) { while (symbols != NIL) { pkg.importSymbol(checkSymbol(symbols.car())); symbols = symbols.cdr(); } } else pkg.importSymbol(checkSymbol(symbols)); return T; } }; // ### unexport // unexport symbols &optional package => t private static final Primitive UNEXPORT = new Primitive("unexport", "symbols &optional package") { @Override public LispObject execute(LispObject[] args) { if (args.length == 0 || args.length > 2) return error(new WrongNumberOfArgumentsException(this, 1, 2)); LispObject symbols = args[0]; Package pkg = args.length == 2 ? coerceToPackage(args[1]) : getCurrentPackage(); if (symbols.listp()) { while (symbols != NIL) { pkg.unexport(checkSymbol(symbols.car())); symbols = symbols.cdr(); } } else pkg.unexport(checkSymbol(symbols)); return T; } }; // ### shadow // shadow symbol-names &optional package => t private static final Primitive SHADOW = new Primitive("shadow", "symbol-names &optional package") { @Override public LispObject execute(LispObject[] args) { if (args.length == 0 || args.length > 2) return error(new WrongNumberOfArgumentsException(this, 1, 2)); LispObject symbols = args[0]; Package pkg = args.length == 2 ? coerceToPackage(args[1]) : getCurrentPackage(); if (symbols.listp()) { while (symbols != NIL) { pkg.shadow(javaString(symbols.car())); symbols = symbols.cdr(); } } else pkg.shadow(javaString(symbols)); return T; } }; // ### shadowing-import // shadowing-import symbols &optional package => t private static final Primitive SHADOWING_IMPORT = new Primitive("shadowing-import", "symbols &optional package") { @Override public LispObject execute(LispObject[] args) { if (args.length == 0 || args.length > 2) return error(new WrongNumberOfArgumentsException(this, 1, 2)); LispObject symbols = args[0]; Package pkg = args.length == 2 ? coerceToPackage(args[1]) : getCurrentPackage(); if (symbols.listp()) { while (symbols != NIL) { pkg.shadowingImport(checkSymbol(symbols.car())); symbols = symbols.cdr(); } } else pkg.shadowingImport(checkSymbol(symbols)); return T; } }; // ### package-shadowing-symbols // package-shadowing-symbols package => used-by-list private static final Primitive PACKAGE_SHADOWING_SYMBOLS = new Primitive("package-shadowing-symbols", "package") { @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).getShadowingSymbols(); } }; // ### %delete-package private static final Primitive _DELETE_PACKAGE = new Primitive("%delete-package", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).delete() ? T : NIL; } }; // ### unuse-package // unuse-package packages-to-unuse &optional package => t private static final Primitive USE_PACKAGE = new Primitive("unuse-package", "packages-to-unuse &optional package") { @Override public LispObject execute(LispObject[] args) { if (args.length < 1 || args.length > 2) return error(new WrongNumberOfArgumentsException(this, 1, 2)); Package pkg; if (args.length == 2) pkg = coerceToPackage(args[1]); else pkg = getCurrentPackage(); if (args[0] instanceof Cons) { LispObject list = args[0]; while (list != NIL) { pkg.unusePackage(coerceToPackage(list.car())); list = list.cdr(); } } else pkg.unusePackage(coerceToPackage(args[0])); return T; } }; // ### rename-package // rename-package package new-name &optional new-nicknames => package-object private static final Primitive RENAME_PACKAGE = new Primitive("rename-package", "package new-name &optional new-nicknames") { @Override public LispObject execute(LispObject[] args) { if (args.length < 2 || args.length > 3) return error(new WrongNumberOfArgumentsException(this, 2, 3)); Package pkg = coerceToPackage(args[0]); String newName = javaString(args[1]); LispObject nicknames = args.length == 3 ? checkList(args[2]) : NIL; pkg.rename(newName, nicknames); return pkg; } }; private static final Primitive LIST_ALL_PACKAGES = new Primitive("list-all-packages", "") { @Override public LispObject execute() { return Packages.listAllPackages(); } }; // ### package-local-nicknames // package-local-nicknames package => nickname-alist private static final Primitive PACKAGE_LOCAL_NICKNAMES = new Primitive("package-local-nicknames", PACKAGE_EXT, true, "package") { @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).getLocalPackageNicknames(); } }; // ### add-package-local-nickname // add-package-local-nickname local-nickname package &optional package-designator => package private static final Primitive ADD_PACKAGE_LOCAL_NICKNAME = new Primitive("%add-package-local-nickname", PACKAGE_SYS, false, "local-nickname package &optional package-designator") { @Override public LispObject execute(LispObject nick, LispObject pack, LispObject target) { return coerceToPackage(target).addLocalPackageNickname(nick.getStringValue(), coerceToPackage(pack)); } @Override public LispObject execute(LispObject nick, LispObject pack) { return this.execute(nick, pack, getCurrentPackage()); } }; // ### remove-package-local-nickname // remove-package-local-nickname old-nickname &optional package-designator => boolean private static final Primitive REMOVE_PACKAGE_LOCAL_NICKNAME = new Primitive("remove-package-local-nickname", PACKAGE_EXT, true, "old-nickname &optional package-designator") { @Override public LispObject execute(LispObject nick, LispObject target) { return coerceToPackage(target).removeLocalPackageNickname(nick.getStringValue()); } @Override public LispObject execute(LispObject nick) { return this.execute(nick, getCurrentPackage()); } }; // ### package-locally-nicknamed-by-list // package-locally-nicknamed-by-list package => package-list private static final Primitive PACKAGE_LOCALLY_NICKNAMED_BY_LIST = new Primitive("package-locally-nicknamed-by-list", PACKAGE_EXT, true, "package") { @Override public LispObject execute(LispObject pack) { return Packages.getPackagesNicknamingPackage(coerceToPackage(pack)); } }; // ### %defpackage name nicknames size shadows shadowing-imports use // imports interns exports doc-string => package private static final Primitive _DEFPACKAGE = new Primitive("%defpackage", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject[] args) { if (args.length != 11) return error(new WrongNumberOfArgumentsException(this, 11)); final String packageName = args[0].getStringValue(); Package currentpkg = getCurrentPackage(); LispObject nicknames = checkList(args[1]); // FIXME size is ignored // LispObject size = args[2]; LispObject shadows = checkList(args[3]); LispObject shadowingImports = checkList(args[4]); LispObject use = checkList(args[5]); LispObject imports = checkList(args[6]); LispObject interns = checkList(args[7]); LispObject exports = checkList(args[8]); LispObject localNicknames = checkList(args[9]); // FIXME docString is ignored // LispObject docString = args[10]; Package pkg = currentpkg.findPackage(packageName); if (pkg != null) return pkg; if (nicknames != NIL) { LispObject list = nicknames; while (list != NIL) { LispObject lispNick = list.car(); String nick = javaString(lispNick); if (currentpkg.findPackage(nick) != null) { return error(new PackageError("A package named " + nick + " already exists.", lispNick)); } list = list.cdr(); } } pkg = Packages.createPackage(packageName); while (nicknames != NIL) { LispObject string = nicknames.car().STRING(); pkg.addNickname(string.getStringValue()); nicknames = nicknames.cdr(); } while (shadows != NIL) { String symbolName = shadows.car().getStringValue(); pkg.shadow(symbolName); shadows = shadows.cdr(); } while (shadowingImports != NIL) { LispObject si = shadowingImports.car(); Package otherPkg = coerceToPackage(si.car()); LispObject symbolNames = si.cdr(); while (symbolNames != NIL) { String symbolName = symbolNames.car().getStringValue(); Symbol sym = otherPkg.findAccessibleSymbol(symbolName); if (sym != null) pkg.shadowingImport(sym); else return error(new LispError(symbolName + " not found in package " + otherPkg.getName() + ".")); symbolNames = symbolNames.cdr(); } shadowingImports = shadowingImports.cdr(); } while (use != NIL) { LispObject obj = use.car(); if (obj instanceof Package) pkg.usePackage((Package)obj); else { LispObject string = obj.STRING(); Package p = currentpkg.findPackage(string.getStringValue()); if (p == null) return error(new LispError(obj.princToString() + " is not the name of a package.")); pkg.usePackage(p); } use = use.cdr(); } while (imports != NIL) { LispObject si = imports.car(); Package otherPkg = coerceToPackage(si.car()); LispObject symbolNames = si.cdr(); while (symbolNames != NIL) { String symbolName = symbolNames.car().getStringValue(); Symbol sym = otherPkg.findAccessibleSymbol(symbolName); if (sym != null) pkg.importSymbol(sym); else return error(new LispError(symbolName + " not found in package " + otherPkg.getName() + ".")); symbolNames = symbolNames.cdr(); } imports = imports.cdr(); } while (interns != NIL) { String symbolName = interns.car().getStringValue(); pkg.intern(symbolName); interns = interns.cdr(); } while (exports != NIL) { String symbolName = exports.car().getStringValue(); pkg.export(pkg.intern(symbolName)); exports = exports.cdr(); } while (localNicknames != NIL) { LispObject nickDecl = localNicknames.car(); String name = nickDecl.car().getStringValue(); Package pack = coerceToPackage(nickDecl.cadr()); pkg.addLocalPackageNickname(name, pack); localNicknames = localNicknames.cdr(); } return pkg; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Packages.java0100644 0000000 0000000 00000012742 14202767264 020606 0ustar000000000 0000000 /* * Packages.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; public final class Packages { private static final ArrayList packages = new ArrayList(); private static final HashMap map = new HashMap(); public static final synchronized Package createPackage(String name) { return createPackage(name, 0); } public static final synchronized Package createPackage(String name, int size) { Package pkg = (Package) map.get(name); if (pkg == null) { pkg = size != 0 ? new Package(name, size) : new Package(name); packages.add(pkg); map.put(name, pkg); } else Debug.trace("package " + name + " already exists"); return pkg; } public static final synchronized void addPackage(Package pkg) { final String name = pkg.getName(); if (map.get(name) != null) { error(new LispError("A package named " + name + " already exists.")); return; } packages.add(pkg); map.put(name, pkg); List nicknames = pkg.getNicknames(); if (nicknames != null) { for (Iterator it = nicknames.iterator(); it.hasNext();) { String nickname = (String) it.next(); addNickname(pkg, nickname); } } } /** Returns the current package of the current LispThread. Intended to be used from Java code manipulating an Interpreter instance. */ public static final synchronized Package findPackage(String name) { return getCurrentPackage().findPackage(name); } // Finds package named `name'. Returns null if package doesn't exist. // Called by Package.findPackage after checking package-local package // nicknames. static final synchronized Package findPackageGlobally(String name) { return (Package) map.get(name); } public static final synchronized Package makePackage(String name) { if (map.get(name) != null) { error(new LispError("A package named " + name + " already exists.")); // Not reached. return null; } Package pkg = new Package(name); packages.add(pkg); map.put(name, pkg); return pkg; } public static final synchronized void addNickname(Package pkg, String nickname) { Object obj = map.get(nickname); if (obj != null && obj != pkg) { error(new PackageError("A package named " + nickname + " already exists.", new SimpleString(nickname))); return; } map.put(nickname, pkg); } // Removes name and nicknames from map, removes pkg from packages. public static final synchronized boolean deletePackage(Package pkg) { String name = pkg.getName(); if (name != null) { map.remove(name); List nicknames = pkg.getNicknames(); if (nicknames != null) { for (Iterator it = nicknames.iterator(); it.hasNext();) { String nickname = (String) it.next(); map.remove(nickname); } } packages.remove(pkg); return true; } return false; } public static final synchronized LispObject listAllPackages() { LispObject result = NIL; for (Package pkg : packages) { result = new Cons(pkg, result); } return result; } public static final synchronized Package[] getAllPackages() { Package[] array = new Package[packages.size()]; packages.toArray(array); return array; } public static final synchronized LispObject getPackagesNicknamingPackage(Package thePackage) { LispObject result = NIL; for (Package pkg : packages) { for (Package nicknamedPackage : pkg.getLocallyNicknamedPackages()) { if (thePackage.equals(nicknamedPackage)) { result = new Cons(pkg, result); } } } return result; } } abcl-src-1.9.0/src/org/armedbear/lisp/ParseError.java0100644 0000000 0000000 00000004547 14202767264 021160 0ustar000000000 0000000 /* * ParseError.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ParseError extends LispError { public ParseError(String message) { super(StandardClass.PARSE_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); } public ParseError(LispObject initArgs) { super(StandardClass.PARSE_ERROR); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.PARSE_ERROR; } @Override public LispObject classOf() { return StandardClass.PARSE_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.PARSE_ERROR) return T; if (type == StandardClass.PARSE_ERROR) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/Pathname.java0100644 0000000 0000000 00000242540 14242624277 020626 0ustar000000000 0000000 /* * Pathname.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.*; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.text.MessageFormat; import java.util.Enumeration; import java.util.StringTokenizer; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; public class Pathname extends LispObject implements Serializable { protected static Pathname create() { return new Pathname(); } public static Pathname create(Pathname p) { if (p instanceof JarPathname) { return JarPathname.create((JarPathname)p); } else if (p instanceof URLPathname) { return URLPathname.create((URLPathname)p); } else if (p instanceof LogicalPathname) { return LogicalPathname.create((LogicalPathname)p); } else { return new Pathname((Pathname)p); } } public static Pathname create(String s) { // TODO distinguish between logical hosts and schemes for URLs // which we can meaningfully parse. if (s.startsWith(JarPathname.JAR_URI_PREFIX)) { return JarPathname.create(s); } if (isValidURL(s)) { return URLPathname.create(s); } else { if (LogicalPathname.isValidLogicalPathname(s)) { return LogicalPathname.create(s); } } Pathname result = Pathname.init(s); return result; } public static Pathname create(String s, String host) { return LogicalPathname.create(s, host); } protected LispObject host = NIL; public LispObject getHost() { return host; } public Pathname setHost(LispObject host) { this.host = host; return this; } protected LispObject device = NIL; public final LispObject getDevice() { return device; } public Pathname setDevice(LispObject device) { this.device = device; return this; } protected LispObject directory = NIL; public LispObject getDirectory() { return directory; } public Pathname setDirectory(LispObject directory) { this.directory = directory; return this; } protected LispObject name = NIL; public LispObject getName() { return name; } public Pathname setName(LispObject name) { this.name = name; return this; } /** A string, NIL, :WILD or :UNSPECIFIC. */ protected LispObject type = NIL; public LispObject getType() { return type; } public Pathname setType(LispObject type) { this.type = type; return this; } /** A positive integer, or NIL, :WILD, :UNSPECIFIC, or :NEWEST. */ protected LispObject version = NIL; public LispObject getVersion() { return version; } public Pathname setVersion(LispObject version) { this.version = version; return this; } /** * The path component separator used by internally generated * path namestrings. */ public final static char directoryDelimiter = '/'; // If we don't declare the no-arg constructor protected, then // inheriting classes cannot invoke their constructors !?! protected Pathname() {} private Pathname(Pathname p) { /** Copy constructor which shares no structure with the original. */ copyFrom(p); } /** * Coerces type between descendents of Pathname types by copying structure */ static public LispObject ncoerce(Pathname orig, Pathname dest) { return dest.copyFrom(orig); } /** * Create a deep copy of all the information referenced by p */ Pathname copyFrom(Pathname p) { if (p.host != NIL) { LispObject pHost = p.getHost(); if (pHost instanceof SimpleString) { setHost(new SimpleString(pHost.getStringValue())); } else if (pHost instanceof Symbol) { setHost(pHost); } else if (pHost instanceof Cons) { LispObject newHost = NIL; LispObject components = pHost.reverse(); while (!components.car().equals(NIL)) { LispObject copy = components.car(); // TODO actually make a copy? newHost = newHost.push(copy); components = components.cdr(); } setHost(newHost); } else { simple_error("Failed to copy host in pathname ~a", p); } } if (p.device != NIL) { if (p.device instanceof SimpleString) { device = new SimpleString(((SimpleString)p.getDevice()).getStringValue()); } else if (p.getDevice() instanceof Cons) { LispObject jars = p.getDevice(); setDevice(NIL); URLPathname root = null; Pathname rootPathname = (Pathname) jars.car(); if (rootPathname instanceof URLPathname) { root = URLPathname.create((URLPathname)rootPathname); } else { root = URLPathname.create((Pathname)rootPathname); } device = device.push(root); jars = jars.cdr(); while (jars.car() != NIL) { Pathname jar = (Pathname) Pathname.create(((Pathname)jars.car()).getNamestring()); device = device.push(jar); jars = jars.cdr(); } device.nreverse(); } else if (p.device instanceof Symbol) { // When is this the case? device = p.device; } else { simple_error("Failed to copy device in pathname ~a", p); } } if (p.directory != NIL) { if (p.directory instanceof Cons) { directory = NIL; for (LispObject list = p.directory; list != NIL; list = list.cdr()) { LispObject o = list.car(); if (o instanceof Symbol) { directory = directory.push(o); } else if (o instanceof SimpleString) { directory = directory.push(new SimpleString(((SimpleString)o).getStringValue())); } else { Debug.assertTrue(false); } } directory.nreverse(); } else { simple_error("Failed to copy directory in pathname ~a", p); } } if (p.name != NIL) { if (p.name instanceof SimpleString) { name = new SimpleString(((SimpleString)p.getName()).getStringValue()); } else if (p.name instanceof Symbol) { name = p.name; } else { simple_error("Failed to copy name in pathname ~a", p); } } if (p.type != NIL) { if (p.type instanceof SimpleString) { type = new SimpleString(((SimpleString)p.getType()).getStringValue()); } else if (p.type instanceof Symbol) { type = p.type; } else { simple_error("Failed to copy type in pathname ~a", p); } } if (p.version != NIL) { if (p.version instanceof Symbol) { version = p.version; } else if (p.version instanceof LispInteger) { version = p.version; } else { simple_error("Failed to copy version in pathname ~a", p); } } return this; } public static boolean isSupportedProtocol(String protocol) { // There is no programmatic way to know what protocols will // sucessfully construct a URL, so we check for well known ones... if ("jar".equals(protocol) || "file".equals(protocol)) // || "http".equals(protocol)) XXX remove this as an optimization { return true; } // ... and try the entire constructor with some hopefully // reasonable parameters for everything else. try { new URL(protocol, "example.org", "foo"); return true; } catch (MalformedURLException e) { return false; } } private static final Pathname init(String s) { Pathname result = new Pathname(); if (s == null) { return (Pathname)parse_error("Refusing to create a PATHNAME for the null reference."); } if (s.equals(".") || s.equals("./") || (Utilities.isPlatformWindows && s.equals(".\\"))) { result.setDirectory(new Cons(Keyword.RELATIVE)); return result; } if (s.startsWith("./")) { s = s.substring(2); } if (s.equals("..") || s.equals("../")) { result.setDirectory(list(Keyword.RELATIVE, Keyword.UP)); return result; } // UNC Windows shares if (Utilities.isPlatformWindows) { if (s.startsWith("\\\\") || s.startsWith("//")) { // UNC path support int shareIndex; int dirIndex; // match \\\\[directories-and-files] if (s.startsWith("\\\\")) { shareIndex = s.indexOf('\\', 2); dirIndex = s.indexOf('\\', shareIndex + 1); // match ////[directories-and-files] } else { shareIndex = s.indexOf('/', 2); dirIndex = s.indexOf('/', shareIndex + 1); } if (shareIndex == -1 || dirIndex == -1) { return (Pathname)parse_error("Unsupported UNC path format: \"" + s + '"'); } result .setHost(new SimpleString(s.substring(2, shareIndex))) .setDevice(new SimpleString(s.substring(shareIndex + 1, dirIndex))); Pathname p = (Pathname)Pathname.create(s.substring(dirIndex)); result .setDirectory(p.getDirectory()) .setName(p.getName()) .setType(p.getType()) .setVersion(p.getVersion()); return result; } } // A JAR file if (s.startsWith(JarPathname.JAR_URI_PREFIX) && s.endsWith(JarPathname.JAR_URI_SUFFIX)) { return (JarPathname)JarPathname.create(s); } // An entry in a JAR file final int separatorIndex = s.lastIndexOf(JarPathname.JAR_URI_SUFFIX); if (separatorIndex > 0 && s.startsWith(JarPathname.JAR_URI_PREFIX)) { return (JarPathname)JarPathname.create(s); } // A URL (anything with a scheme that is not a logical // pathname, and not a JAR file or an entry in a JAR file) if (isValidURL(s)) { return (URLPathname)URLPathname.create(s); } // Normalize path separators to forward slashes if (Utilities.isPlatformWindows) { if (s.contains("\\")) { s = s.replace("\\", "/"); } } // Expand user home directories if (Utilities.isPlatformUnix) { if (s.equals("~")) { s = System.getProperty("user.home").concat("/"); } else if (s.startsWith("~/")) { s = System.getProperty("user.home").concat(s.substring(1)); } } // possible MSDOS device if (Utilities.isPlatformWindows) { if (s.length() >= 2 && s.charAt(1) == ':') { result.setDevice(new SimpleString(s.charAt(0))); s = s.substring(2); } } String d = null; // Find last file separator char. for (int i = s.length(); i-- > 0;) { if (s.charAt(i) == '/') { d = s.substring(0, i + 1); s = s.substring(i + 1); break; } } if (d != null) { if (s.equals("..")) { d = d.concat(s); s = ""; } result.setDirectory(parseDirectory(d)); } int index = s.lastIndexOf('.'); String name = null; String type = null; if (index > 0) { name = s.substring(0, index); type = s.substring(index + 1); } else if (s.length() > 0) { name = s; } if (name != null) { if (name.equals("*")) { result.setName(Keyword.WILD); } else { result.setName(new SimpleString(name)); } } if (type != null) { if (type.equals("*")) { result.setType(Keyword.WILD); } else { result.setType(new SimpleString(type)); } } return result; } private static final LispObject parseDirectory(String d) { if (d.equals("/") || (Utilities.isPlatformWindows && d.equals("\\"))) { return new Cons(Keyword.ABSOLUTE); } LispObject result; if (d.startsWith("/") || (Utilities.isPlatformWindows && d.startsWith("\\"))) { result = new Cons(Keyword.ABSOLUTE); } else { result = new Cons(Keyword.RELATIVE); } StringTokenizer st = new StringTokenizer(d, "/\\"); while (st.hasMoreTokens()) { String token = st.nextToken(); LispObject obj; if (token.equals("*")) { obj = Keyword.WILD; } else if (token.equals("**")) { obj = Keyword.WILD_INFERIORS; } else if (token.equals("..")) { if (result.car() instanceof AbstractString) { result = result.cdr(); continue; } obj = Keyword.UP; } else { obj = new SimpleString(token); } result = new Cons(obj, result); } return result.nreverse(); } @Override public LispObject getParts() { LispObject parts = list(new Cons("HOST", getHost()), new Cons("DEVICE", getDevice()), new Cons("DIRECTORY", getDirectory()), new Cons("NAME", getName()), new Cons("TYPE", getType()), new Cons("VERSION", getVersion())); return parts; } @Override public LispObject typeOf() { if (isJar()) { return Symbol.JAR_PATHNAME; } if (isURL()) { return Symbol.URL_PATHNAME; } return Symbol.PATHNAME; } @Override public LispObject classOf() { if (isJar()) { return BuiltInClass.JAR_PATHNAME; } if (isURL()) { return BuiltInClass.URL_PATHNAME; } return BuiltInClass.PATHNAME; } @Override public LispObject typep(LispObject type) { if (type == Symbol.PATHNAME) { return T; } if (type == Symbol.JAR_PATHNAME && isJar()) { return T; } if (type == Symbol.URL_PATHNAME && isURL()) { return T; } if (type == BuiltInClass.PATHNAME) { return T; } if (type == BuiltInClass.JAR_PATHNAME && isJar()) { return T; } if (type == BuiltInClass.URL_PATHNAME && isURL()) { return T; } return super.typep(type); } public String getNamestring() { if (getDirectory() instanceof AbstractString) { Debug.assertTrue(false); } StringBuilder sb = new StringBuilder(); // "If a pathname is converted to a namestring, the symbols NIL and // :UNSPECIFIC cause the field to be treated as if it were empty. That // is, both NIL and :UNSPECIFIC cause the component not to appear in // the namestring." 19.2.2.2.3.1 if (getHost() != NIL) { Debug.assertTrue(getHost() instanceof AbstractString || isURL()); if (isURL()) { LispObject scheme = Symbol.GETF.execute(getHost(), URLPathname.SCHEME, NIL); LispObject authority = Symbol.GETF.execute(getHost(), URLPathname.AUTHORITY, NIL); Debug.assertTrue(scheme != NIL); sb.append(scheme.getStringValue()); sb.append(":"); if (authority != NIL) { sb.append("//"); sb.append(authority.getStringValue()); } } else if (this instanceof LogicalPathname) { sb.append(getHost().getStringValue()); sb.append(':'); } else { // A UNC path sb.append("//").append(getHost().getStringValue()).append("/"); } } if (getDevice().equals(NIL) || getDevice().equals(Keyword.UNSPECIFIC)) { // nothing emitted for device } else if (getDevice() instanceof AbstractString) { sb.append(getDevice().getStringValue()); if (this instanceof LogicalPathname || getHost() == NIL) { sb.append(':'); // non-UNC paths } } else { simple_error("Transitional error in pathname: should be a JAR-PATHNAME", this); } String directoryNamestring = getDirectoryNamestring(); sb.append(directoryNamestring); if (getName() instanceof AbstractString) { String n = getName().getStringValue(); if (n.indexOf('/') >= 0) { return null; } sb.append(n); } else if (getName() == Keyword.WILD) { sb.append('*'); } if (getType() != NIL && getType() != Keyword.UNSPECIFIC) { sb.append('.'); if (getType() instanceof AbstractString) { String t = getType().getStringValue(); // Allow Windows shortcuts to include TYPE if (!(t.endsWith(".lnk") && Utilities.isPlatformWindows)) { if (t.indexOf('.') >= 0) { return null; } } sb.append(t); } else if (getType() == Keyword.WILD) { sb.append('*'); } else { Debug.assertTrue(false); } } if (this instanceof LogicalPathname) { if (getVersion().integerp()) { sb.append('.'); int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue()); if (getVersion() instanceof Fixnum) { sb.append(Integer.toString(((Fixnum) getVersion()).value, base).toUpperCase()); } else if (getVersion() instanceof Bignum) { sb.append(((Bignum) getVersion()).value.toString(base).toUpperCase()); } } else if (getVersion() == Keyword.WILD) { sb.append(".*"); } else if (getVersion() == Keyword.NEWEST) { sb.append(".NEWEST"); } } return sb.toString(); } protected String getDirectoryNamestring() { validateDirectory(true); StringBuilder sb = new StringBuilder(); // "If a pathname is converted to a namestring, the symbols NIL and // :UNSPECIFIC cause the field to be treated as if it were empty. That // is, both NIL and :UNSPECIFIC cause the component not to appear in // the namestring." 19.2.2.2.3.1 if (getDirectory() != NIL && getDirectory() != Keyword.UNSPECIFIC) { LispObject temp = getDirectory(); LispObject part = temp.car(); temp = temp.cdr(); if (part == Keyword.ABSOLUTE) { sb.append(directoryDelimiter); } else if (part == Keyword.RELATIVE) { if (temp == NIL) { // #p"./" sb.append('.'); sb.append(directoryDelimiter); } // else: Nothing to do. } else { error(new FileError("Unsupported directory component " + part.printObject() + ".", this)); } while (temp != NIL) { part = temp.car(); if (part instanceof AbstractString) { sb.append(part.getStringValue()); } else if (part == Keyword.WILD) { sb.append('*'); } else if (part == Keyword.WILD_INFERIORS) { sb.append("**"); } else if (part == Keyword.UP) { sb.append(".."); } sb.append(directoryDelimiter); temp = temp.cdr(); } } return sb.toString(); } @Override public boolean equal(LispObject obj) { if (this == obj) { return true; } if (obj instanceof Pathname) { Pathname p = (Pathname) obj; if (Utilities.isPlatformWindows) { if (!host.equalp(p.host)) { return false; } if (!device.equalp(p.device)) { return false; } if (!directory.equalp(p.directory)) { return false; } if (!name.equalp(p.name)) { return false; } if (!type.equalp(p.type)) { return false; } // Ignore version component. //if (!version.equalp(p.version)) // return false; } else { // Unix. if (!host.equal(p.host)) { return false; } if (!device.equal(p.device)) { return false; } if (!directory.equal(p.directory)) { return false; } if (!name.equal(p.name)) { return false; } if (!type.equal(p.type)) { return false; } // Ignore version component. //if (!version.equal(p.version)) // return false; } return true; } return false; } @Override public boolean equalp(LispObject obj) { return equal(obj); } public boolean equals(Object o) { if (!(this.getClass().isAssignableFrom(o.getClass()))) { return super.equals(o); } return equal((Pathname)o); } public int hashCode() { return sxhash(); } @Override public int sxhash() { return ((getHost().sxhash() ^ getDevice().sxhash() ^ getDirectory().sxhash() ^ getName().sxhash() ^ getType().sxhash()) & 0x7fffffff); } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); final boolean printReadably = (Symbol.PRINT_READABLY.symbolValue(thread) != NIL); final boolean printEscape = (Symbol.PRINT_ESCAPE.symbolValue(thread) != NIL); boolean useNamestring; String s = null; s = getNamestring(); if (s != null) { useNamestring = true; if (printReadably) { // We have a namestring. Check for pathname components that // can't be read from the namestring. if ((getHost() != NIL && !isURL()) || getVersion() != NIL) { useNamestring = false; } else if (getName() instanceof AbstractString) { String n = getName().getStringValue(); if (n.equals(".") || n.equals("..")) { useNamestring = false; // ??? File.separatorChar is platform dependent. Does this help on Windows? } else if (n.indexOf(File.separatorChar) >= 0) { useNamestring = false; } } } } else { useNamestring = false; } StringBuilder sb = new StringBuilder(); if (useNamestring) { if (printReadably || printEscape) { sb.append("#P\""); } final int limit = s.length(); for (int i = 0; i < limit; i++) { char c = s.charAt(i); if (printReadably || printEscape) { if (c == '\"' || c == '\\') { sb.append('\\'); } } sb.append(c); } if (printReadably || printEscape) { sb.append('"'); } return sb.toString(); } sb.append("PATHNAME (with no namestring) "); if (getHost() != NIL) { sb.append(":HOST ") .append(getHost().printObject()) .append(" "); } if (getDevice() != NIL) { sb.append(":DEVICE ") .append(getDevice().printObject()) .append(" "); } if (getDirectory() != NIL) { sb.append(":DIRECTORY ") .append(getDirectory().printObject()) .append(" "); } if (getName() != NIL) { sb.append(":NAME ") .append(getName().printObject()) .append(" "); } if (getType() != NIL) { sb.append(":TYPE ") .append(getType().printObject()) .append(" "); } if (getVersion() != NIL) { sb.append(":VERSION ") .append(getVersion().printObject()) .append(" "); } if (sb.charAt(sb.length() - 1) == ' ') { sb.setLength(sb.length() - 1); } return unreadableString(sb.toString()); } public static Pathname parseNamestring(String s) { return (Pathname)Pathname.create(s); } public static boolean isValidURL(String s) { // On Windows, the scheme "[A-Z]:.*" is ambiguous; reject as urls // This special case reduced exceptions while compiling Maxima by 90%+ if (Utilities.isPlatformWindows && s.length() >= 2 && s.charAt(1) == ':') { char c = s.charAt(0); if (('A' <= s.charAt(0) && s.charAt(0) <= 'Z') || ('a' <= s.charAt(0) && s.charAt(0) <= 'z')) return false; } if (s.indexOf(':') == -1) // no schema separator; can't be valid return false; try { URL url = new URL(s); } catch (MalformedURLException e) { return false; } return true; } public static LispObject parseNamestring(AbstractString namestring) { // Check for a logical pathname host. String s = namestring.getStringValue(); if (!isValidURL(s)) { String h = LogicalPathname.getHostString(s); if (h != null && LogicalPathname.TRANSLATIONS.get(new SimpleString(h)) != null) { // A defined logical pathname host. return LogicalPathname.create(h, s.substring(s.indexOf(':') + 1)); } } return Pathname.create(s); } public static LogicalPathname parseNamestring(AbstractString namestring, AbstractString host) { String s = namestring.getStringValue(); // Look for a logical pathname host in the namestring. String h = LogicalPathname.getHostString(s); if (h != null) { if (!h.equals(host.getStringValue())) { error(new LispError("Host in " + s + " does not match requested host " + host.getStringValue())); // Not reached. return null; } // Remove host prefix from namestring. s = s.substring(s.indexOf(':') + 1); } if (LogicalPathname.TRANSLATIONS.get(host) != null) { // A defined logical pathname host. return LogicalPathname.create(host.getStringValue(), s); } error(new LispError(host.princToString() + " is not defined as a logical pathname host.")); // Not reached. return null; } static final void checkCaseArgument(LispObject arg) { if (arg != Keyword.COMMON && arg != Keyword.LOCAL) { type_error(arg, list(Symbol.MEMBER, Keyword.COMMON, Keyword.LOCAL)); } } private static final Primitive _PATHNAME_HOST = new pf_pathname_host(); @DocString(name="%pathname-host") private static class pf_pathname_host extends Primitive { pf_pathname_host() { super("%pathname-host", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { checkCaseArgument(second); // FIXME Why is this ignored? return coerceToPathname(first).getHost(); } } private static final Primitive _PATHNAME_DEVICE = new pf_pathname_device(); @DocString(name="%pathname-device") private static class pf_pathname_device extends Primitive { pf_pathname_device() { super("%pathname-device", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { checkCaseArgument(second); // FIXME Why is this ignored? return coerceToPathname(first).getDevice(); } } private static final Primitive _PATHNAME_DIRECTORY = new pf_pathname_directory(); @DocString(name="%pathname-directory") private static class pf_pathname_directory extends Primitive { pf_pathname_directory() { super("%pathname-directory", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { checkCaseArgument(second); // FIXME Why is this ignored? return coerceToPathname(first).getDirectory(); } } private static final Primitive _PATHNAME_NAME = new pf_pathname_name(); @DocString(name="%pathname-name") private static class pf_pathname_name extends Primitive { pf_pathname_name() { super ("%pathname-name", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { checkCaseArgument(second); // FIXME Why is this ignored? return coerceToPathname(first).getName(); } } private static final Primitive _PATHNAME_TYPE = new pf_pathname_type(); @DocString(name="%pathname-type") private static class pf_pathname_type extends Primitive { pf_pathname_type() { super("%pathname-type", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { checkCaseArgument(second); // FIXME Why is this ignored? return coerceToPathname(first).getType(); } } private static final Primitive PATHNAME_VERSION = new pf_pathname_version(); @DocString(name="pathname-version", args="pathname", returns="version", doc="Return the version component of PATHNAME.") private static class pf_pathname_version extends Primitive { pf_pathname_version() { super("pathname-version", "pathname"); } @Override public LispObject execute(LispObject arg) { return coerceToPathname(arg).getVersion(); } } private static final Primitive NAMESTRING = new pf_namestring(); @DocString(name="namestring", args="pathname", returns="namestring", doc="Returns the NAMESTRING of PATHNAME if it has one.\n" + "\n" + "If PATHNAME is of type url-pathname or jar-pathname the NAMESTRING is encoded\n" + "according to the uri percent escape rules.\n" + "\n" + "Signals an error if PATHNAME lacks a printable NAMESTRING representation.\n") private static class pf_namestring extends Primitive { pf_namestring() { super("namestring", "pathname"); } @Override public LispObject execute(LispObject arg) { Pathname pathname = coerceToPathname(arg); String namestring = pathname.getNamestring(); if (namestring == null) { error(new SimpleError("Pathname has no namestring: " + pathname.princToString())); } return new SimpleString(namestring); } } private static final Primitive DIRECTORY_NAMESTRING = new pf_directory_namestring(); // TODO clarify uri encoding rules in implementation, then document @DocString(name="directory-namestring", args="pathname", returns="namestring", doc="Returns the NAMESTRING of directory porition of PATHNAME if it has one.") private static class pf_directory_namestring extends Primitive { pf_directory_namestring() { super("directory-namestring", "pathname"); } @Override public LispObject execute(LispObject arg) { return new SimpleString(coerceToPathname(arg).getDirectoryNamestring()); } } private static final Primitive PATHNAME = new pf_pathname(); @DocString(name="pathname", args="pathspec", returns="pathname", doc="Returns the PATHNAME denoted by PATHSPEC.") private static class pf_pathname extends Primitive { pf_pathname() { super("pathname", "pathspec"); } @Override public LispObject execute(LispObject arg) { return coerceToPathname(arg); } } private static final Primitive _PARSE_NAMESTRING = new pf_parse_namestring(); @DocString(name="%parse-namestring", args="namestring host default-pathname", returns="pathname, position") private static class pf_parse_namestring extends Primitive { pf_parse_namestring() { super("%parse-namestring", PACKAGE_SYS, false, "namestring host default-pathname"); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { final LispThread thread = LispThread.currentThread(); final AbstractString namestring = checkString(first); // The HOST parameter must be a string or NIL. if (second == NIL) { // "If HOST is NIL, DEFAULT-PATHNAME is a logical pathname, and // THING is a syntactically valid logical pathname namestring // without an explicit host, then it is parsed as a logical // pathname namestring on the host that is the host component // of DEFAULT-PATHNAME." third = coerceToPathname(third); if (third instanceof LogicalPathname) { second = ((LogicalPathname) third).getHost(); } else { return thread.setValues(parseNamestring(namestring), namestring.LENGTH()); } } Debug.assertTrue(second != NIL); final AbstractString host = checkString(second); return thread.setValues(parseNamestring(namestring, host), namestring.LENGTH()); } } private static final Primitive MAKE_PATHNAME = new pf_make_pathname(); @DocString(name="make-pathname", args="&key host device directory name type version defaults case", returns="pathname", doc="Constructs and returns a pathname from the supplied keyword arguments.") private static class pf_make_pathname extends Primitive { pf_make_pathname() { super("make-pathname", "&key host device directory name type version defaults case"); } @Override public LispObject execute(LispObject[] args) { LispObject result = _makePathname(args); return result; } } // Used by the #p reader. public static final Pathname makePathname(LispObject args) { return (Pathname) _makePathname(args.copyToArray()); } public static final Pathname makePathname(File file) { String namestring = null; try { namestring = file.getCanonicalPath(); } catch (IOException e) { Debug.trace("Failed to make a Pathname from " + "." + file + "'"); return null; } return (Pathname)Pathname.create(namestring); } static final LispObject _makePathname(LispObject[] args) { if (args.length % 2 != 0) { program_error("Odd number of keyword arguments."); } LispObject host = NIL; LispObject device = NIL; LispObject directory = NIL; LispObject name = NIL; LispObject type = NIL; LispObject version = NIL; Pathname defaults = null; boolean hostSupplied = false; boolean deviceSupplied = false; boolean nameSupplied = false; boolean typeSupplied = false; boolean directorySupplied = false; boolean versionSupplied = false; for (int i = 0; i < args.length; i += 2) { LispObject key = args[i]; LispObject value = args[i + 1]; if (key == Keyword.HOST) { host = value; hostSupplied = true; } else if (key == Keyword.DEVICE) { device = value; deviceSupplied = true; if (!(value instanceof AbstractString || value.equals(Keyword.UNSPECIFIC) || value.equals(NIL) || value instanceof Cons)) { return type_error("DEVICE is not a string, :UNSPECIFIC, NIL, or a list.", value, list(Symbol.OR, Symbol.STRING, Keyword.UNSPECIFIC, NIL, Symbol.CONS)); } } else if (key == Keyword.DIRECTORY) { directorySupplied = true; if (value instanceof AbstractString) { directory = list(Keyword.ABSOLUTE, value); } else if (value == Keyword.WILD) { directory = list(Keyword.ABSOLUTE, Keyword.WILD); } else { // a valid pathname directory is a string, a list of // strings, nil, :wild, :unspecific // // ??? would be nice to (deftype pathname-arg () // '(or (member :wild :unspecific) string (and cons // ,(mapcar ... Is this possible? if ((value instanceof Cons // XXX check that the elements of a list are themselves valid || value == Keyword.UNSPECIFIC || value.equals(NIL))) { directory = value; } else { return type_error("DIRECTORY argument not a string, list of strings, nil, :WILD, or :UNSPECIFIC.", value, list(Symbol.OR, NIL, Symbol.STRING, Symbol.CONS, Keyword.WILD, Keyword.UNSPECIFIC)); } } } else if (key == Keyword.NAME) { name = value; nameSupplied = true; } else if (key == Keyword.TYPE) { type = value; typeSupplied = true; } else if (key == Keyword.VERSION) { version = value; versionSupplied = true; } else if (key == Keyword.DEFAULTS) { defaults = coerceToPathname(value); } else if (key == Keyword.CASE) { // Ignored. } } if (defaults != null) { if (!hostSupplied) { host = defaults.getHost(); } if (!directorySupplied) { directory = defaults.getDirectory(); } if (!deviceSupplied) { device = defaults.getDevice(); } if (!nameSupplied) { name = defaults.getName(); } if (!typeSupplied) { type = defaults.getType(); } if (!versionSupplied) { version = defaults.getVersion(); } } Pathname p; // Pathname is always created in following // resolution for values of HOST LispObject logicalHost = NIL; if (host != NIL) { if (host instanceof AbstractString) { logicalHost = LogicalPathname.canonicalizeStringComponent((AbstractString) host); } if (LogicalPathname.TRANSLATIONS.get(logicalHost) == null) { // Not a defined logical pathname host -- A UNC path //warning(new LispError(host.printObject() + " is not defined as a logical pathname host.")); p = Pathname.create(); p.setHost(host); } else { p = LogicalPathname.create(); p.setHost(logicalHost); } if (!Utilities.isPlatformWindows) { p.setDevice(Keyword.UNSPECIFIC); } } else { p = Pathname.create(); } if (device != NIL) { if (p instanceof LogicalPathname) { // "The device component of a logical pathname is always :UNSPECIFIC." if (device != Keyword.UNSPECIFIC) { return type_error("The device component of a logical pathname must be :UNSPECIFIC.", p.getDevice(), Keyword.UNSPECIFIC); } } else { if (device instanceof Cons) { LispObject normalizedDevice = NIL; if (device.car() instanceof SimpleString) { String rootNamestring = device.car().getStringValue(); URLPathname root = new URLPathname(); if (!isValidURL(rootNamestring)) { Pathname rootPathname = Pathname.create(rootNamestring); root = URLPathname.createFromFile(rootPathname); } else { root = URLPathname.create(rootNamestring); } normalizedDevice = normalizedDevice.push(root); } else { normalizedDevice = normalizedDevice.push(device.car()); } LispObject o = device.cdr(); while (!o.car().equals(NIL)) { Pathname next = coerceToPathname(o.car()); normalizedDevice = normalizedDevice.push(next); o = o.cdr(); } normalizedDevice = normalizedDevice.nreverse(); p.setDevice(normalizedDevice); } else { p.setDevice(device); } } } if (directory != NIL) { if (p instanceof LogicalPathname) { if (directory.listp()) { LispObject d = NIL; while (directory != NIL) { LispObject component = directory.car(); if (component instanceof AbstractString) { d = d.push(LogicalPathname.canonicalizeStringComponent((AbstractString) component)); } else { d = d.push(component); } directory = directory.cdr(); } p.setDirectory(d.nreverse()); } else if (directory == Keyword.WILD || directory == Keyword.WILD_INFERIORS) { p.setDirectory(directory); } else { error(new LispError("Invalid directory component for logical pathname: " + directory.princToString())); } } else { p.setDirectory(directory); } } if (name != NIL) { if (p instanceof LogicalPathname && name instanceof AbstractString) { p.setName(LogicalPathname.canonicalizeStringComponent((AbstractString) name)); } else if (name instanceof AbstractString) { p.setName(validateStringComponent((AbstractString) name)); } else { p.setName(name); } } if (type != NIL) { if (p instanceof LogicalPathname && type instanceof AbstractString) { p.setType(LogicalPathname.canonicalizeStringComponent((AbstractString) type)); } else { p.setType(type); } } p.setVersion(version); p.validateDirectory(true); // Possibly downcast type to JarPathname if (p.getDevice() instanceof Cons) { JarPathname result = new JarPathname(); result.copyFrom(p); Pathname root = (Pathname)result.getDevice().car(); URLPathname rootDevice = null; if (root instanceof URLPathname) { rootDevice = URLPathname.create((URLPathname)root); } else { rootDevice = URLPathname.create(root); } result.setDevice(new Cons(rootDevice, result.getDevice().cdr())); if (result.getDirectory().equals(NIL) && (!result.getName().equals(NIL) || !result.getType().equals(NIL))) { result.setDirectory(NIL.push(Keyword.ABSOLUTE)); } // sanity check that the pathname has been constructed correctly result.validateComponents(); return result; } // Possibly downcast to URLPathname if (p.isURL()) { URLPathname result = new URLPathname(); result.copyFrom(p); return result; } return p; } private static final AbstractString validateStringComponent(AbstractString s) { final int limit = s.length(); for (int i = 0; i < limit; i++) { char c = s.charAt(i); // XXX '\\' should be illegal in all Pathnames at this point? if (c == '/' || c == '\\' && Utilities.isPlatformWindows) { error(new LispError("Invalid character #\\" + c + " in pathname component \"" + s + '"')); // Not reached. return null; } } return s; } private final boolean validateDirectory(boolean signalError) { LispObject temp = getDirectory(); if (temp == Keyword.UNSPECIFIC) { return true; } while (temp != NIL) { LispObject first = temp.car(); temp = temp.cdr(); if (first == Keyword.ABSOLUTE || first == Keyword.WILD_INFERIORS) { LispObject second = temp.car(); if (second == Keyword.UP || second == Keyword.BACK) { if (signalError) { StringBuilder sb = new StringBuilder(); sb.append(first.printObject()); sb.append(" may not be followed immediately by "); sb.append(second.printObject()); sb.append('.'); error(new FileError(sb.toString(), this)); } return false; } } else if (first != Keyword.RELATIVE && first != Keyword.WILD && first != Keyword.UP && first != Keyword.BACK && !(first instanceof AbstractString)) { if (signalError) { error(new FileError("Unsupported directory component " + first.princToString() + ".", this)); } return false; } } return true; } private static final Primitive PATHNAMEP = new pf_pathnamep(); @DocString(name="pathnamep", args="object", returns="generalized-boolean", doc="Returns true if OBJECT is of type pathname; otherwise, returns false.") private static class pf_pathnamep extends Primitive { pf_pathnamep() { super("pathnamep", "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof Pathname ? T : NIL; } } private static final Primitive LOGICAL_PATHNAME_P = new pf_logical_pathname_p(); @DocString(name="logical-pathname-p", args="object", returns="generalized-boolean", doc="Returns true if OBJECT is of type logical-pathname; otherwise, returns false.") private static class pf_logical_pathname_p extends Primitive { pf_logical_pathname_p() { super("logical-pathname-p", PACKAGE_SYS, true, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof LogicalPathname ? T : NIL; } } private static final Primitive USER_HOMEDIR_PATHNAME = new pf_user_homedir_pathname(); @DocString(name="user-homedir-pathname", args="&optional host", returns="pathname", doc="Determines the pathname that corresponds to the user's home directory.\n" + "The value returned is obtained from the JVM system propoerty 'user.home'.\n" + "If HOST is specified, returns NIL.") private static class pf_user_homedir_pathname extends Primitive { pf_user_homedir_pathname() { super("user-homedir-pathname", "&optional host"); } @Override public LispObject execute(LispObject[] args) { switch (args.length) { case 0: { String s = System.getProperty("user.home"); if (!s.endsWith(File.separator)) { s = s.concat(File.separator); } return Pathname.create(s); } case 1: return NIL; default: return error(new WrongNumberOfArgumentsException(this, 0, 1)); } } } private static final Primitive LIST_DIRECTORY = new pf_list_directory(); @DocString(name="list-directory", args="directory &optional (resolve-symlinks nil)", returns="pathnames", doc="Lists the contents of DIRECTORY, optionally resolving symbolic links.") private static class pf_list_directory extends Primitive { pf_list_directory() { super("list-directory", PACKAGE_SYS, true, "directory &optional (resolve-symlinks t)"); } @Override public LispObject execute(LispObject arg) { return execute(arg, T); } @Override public LispObject execute(LispObject arg, LispObject resolveSymlinks) { Pathname pathname = coerceToPathname(arg); if (pathname instanceof LogicalPathname) { pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); } LispObject result = NIL; if (pathname.isJar()) { return JarPathname.listDirectory((JarPathname)pathname); } File f = pathname.getFile(); if (f.isDirectory()) { try { File[] files = f.listFiles(); if (files == null) { return error(new FileError("Unable to list directory " + pathname.princToString() + ".", pathname)); } for (int i = files.length; i-- > 0;) { File file = files[i]; String path; if (resolveSymlinks == NIL) { path = file.getAbsolutePath(); } else { path = file.getCanonicalPath(); } if (file.isDirectory() && !path.endsWith("/")) { path += "/"; } Pathname p; p = (Pathname)Pathname.create(path); result = new Cons(p, result); } } catch (IOException e) { return error(new FileError("Unable to list directory " + pathname.princToString() + ".", pathname)); } catch (SecurityException e) { return error(new FileError("Unable to list directory: " + e, pathname)); } } return result; } }; public boolean isAbsolute() { if (!directory.equals(NIL) || !(directory == null)) { if (getDirectory() instanceof Cons) { if (((Cons)getDirectory()).car().equals(Keyword.ABSOLUTE)) { return true; } } } return false; } // FIXME This should be named JAR-PATHNAME-P @DocString(name="pathname-jar-p", args="pathname", returns="generalized-boolean", doc="Predicate functionfor whether PATHNAME references a jar.") private static final Primitive PATHNAME_JAR_P = new pf_pathname_jar_p(); private static class pf_pathname_jar_p extends Primitive { pf_pathname_jar_p() { super("pathname-jar-p", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Pathname) { Pathname p = coerceToPathname(arg); return p.isJar() ? T : NIL; } else { return NIL; } } } public boolean isJar() { return (getDevice() instanceof Cons); } /// FIXME should be named URL-PATHNAME-P @DocString(name="pathname-url-p", args="pathname", returns="generalized-boolean", doc="Predicate function for whether PATHNAME references a jaurl.") private static final Primitive PATHNAME_URL_P = new pf_pathname_url_p(); private static class pf_pathname_url_p extends Primitive { pf_pathname_url_p() { super("pathname-url-p", PACKAGE_EXT, true, "pathname", "Predicate for whether PATHNAME references a URL."); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Pathname) { Pathname p = coerceToPathname(arg); return p.isURL() ? T : NIL; } else { return NIL; } } } public boolean isURL() { return (getHost() instanceof Cons); } public boolean isWild() { if (getHost() == Keyword.WILD || getHost() == Keyword.WILD_INFERIORS) { return true; } if (getDevice() == Keyword.WILD || getDevice() == Keyword.WILD_INFERIORS) { return true; } if (getDirectory() instanceof Cons) { if (memq(Keyword.WILD, getDirectory())) { return true; } if (memq(Keyword.WILD_INFERIORS, getDirectory())) { return true; } Cons d = (Cons) getDirectory(); while (true) { if (d.car() instanceof AbstractString) { String s = d.car().printObject(); if (s.contains("*")) { return true; } } if (d.cdr() == NIL || ! (d.cdr() instanceof Cons)) { break; } d = (Cons)d.cdr(); } } if (getName() == Keyword.WILD || getName() == Keyword.WILD_INFERIORS) { return true; } if (getName() instanceof AbstractString) { if (getName().printObject().contains("*")) { return true; } } if (getType() == Keyword.WILD || getType() == Keyword.WILD_INFERIORS) { return true; } if (getType() instanceof AbstractString) { if (getType().printObject().contains("*")) { return true; } } if (getVersion() == Keyword.WILD || getVersion() == Keyword.WILD_INFERIORS) { return true; } return false; } private static final Primitive _WILD_PATHNAME_P = new pf_wild_pathname_p(); @DocString(name="%wild-pathname-p", args="pathname keyword", returns="generalized-boolean", doc="Predicate for determing whether PATHNAME contains wild components.\n" + "KEYWORD, if non-nil, should be one of :directory, :host, :device,\n" + ":name, :type, or :version indicating that only the specified component\n" + "should be checked for wildness.") static final class pf_wild_pathname_p extends Primitive { pf_wild_pathname_p() { super("%wild-pathname-p", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { Pathname pathname = coerceToPathname(first); if (second == NIL) { return pathname.isWild() ? T : NIL; } if (second == Keyword.DIRECTORY) { if (pathname.getDirectory() instanceof Cons) { if (memq(Keyword.WILD, pathname.getDirectory())) { return T; } if (memq(Keyword.WILD_INFERIORS, pathname.getDirectory())) { return T; } } return NIL; } LispObject value; if (second == Keyword.HOST) { value = pathname.getHost(); } else if (second == Keyword.DEVICE) { value = pathname.getDevice(); } else if (second == Keyword.NAME) { value = pathname.getName(); } else if (second == Keyword.TYPE) { value = pathname.getType(); } else if (second == Keyword.VERSION) { value = pathname.getVersion(); } else { return program_error("Unrecognized keyword " + second.princToString() + "."); } if (value == Keyword.WILD || value == Keyword.WILD_INFERIORS) { return T; } else { return NIL; } } } static final Primitive MERGE_PATHNAMES = new pf_merge_pathnames(); @DocString(name="merge-pathnames", args="pathname &optional default-pathname default-version", returns="pathname", doc="Constructs a pathname from PATHNAME by filling in any unsupplied components\n" + "with the corresponding values from DEFAULT-PATHNAME and DEFAULT-VERSION.") static final class pf_merge_pathnames extends Primitive { pf_merge_pathnames() { super(Symbol.MERGE_PATHNAMES, "pathname &optional default-pathname default-version"); } @Override public LispObject execute(LispObject arg) { Pathname pathname = coerceToPathname(arg); Pathname defaultPathname = coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()); LispObject defaultVersion = Keyword.NEWEST; return mergePathnames(pathname, defaultPathname, defaultVersion); } @Override public LispObject execute(LispObject first, LispObject second) { Pathname pathname = coerceToPathname(first); Pathname defaultPathname = coerceToPathname(second); LispObject defaultVersion = Keyword.NEWEST; return mergePathnames(pathname, defaultPathname, defaultVersion); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { Pathname pathname = coerceToPathname(first); Pathname defaultPathname = coerceToPathname(second); LispObject defaultVersion = third; return mergePathnames(pathname, defaultPathname, defaultVersion); } } public static final Pathname mergePathnames(Pathname pathname, Pathname defaultPathname) { return mergePathnames(pathname, defaultPathname, Keyword.NEWEST); } public static final Pathname mergePathnames(final Pathname pathname, final Pathname defaultPathname, final LispObject defaultVersion) { Pathname result; Pathname p = Pathname.create(pathname); Pathname d; if (pathname instanceof LogicalPathname) { result = LogicalPathname.create(); d = Pathname.create(defaultPathname); } else { if (pathname instanceof JarPathname // If the defaults contain a JAR-PATHNAME, and the pathname // to be be merged is not a JAR-PATHNAME, does not have a // specified DEVICE or a specified HOST and has a NIL or // relative directory then the result will be a JAR-PATHNAME. || (defaultPathname instanceof JarPathname && !(pathname instanceof JarPathname) && pathname.getHost().equals(NIL) && pathname.getDevice().equals(NIL) && (pathname.getDirectory().equals(NIL) || pathname.getDirectory().car().equals(Keyword.RELATIVE)))) { result = JarPathname.create(); } else if (pathname instanceof URLPathname) { result = URLPathname.create(); } else { result = Pathname.create(); } if (defaultPathname instanceof LogicalPathname) { d = LogicalPathname.translateLogicalPathname((LogicalPathname) defaultPathname); } else { if (defaultPathname instanceof JarPathname) { d = JarPathname.create((JarPathname)defaultPathname); } else if (defaultPathname instanceof URLPathname) { d = URLPathname.create(defaultPathname); } else { d = Pathname.create(defaultPathname); } } } if (pathname.getHost().equals(NIL)) { result.setHost(d.getHost()); } else { result.setHost(p.getHost()); } if (!pathname.getDevice().equals(NIL)) { if (!Utilities.isPlatformWindows) { result.setDevice(p.getDevice()); } else { if (d instanceof JarPathname && p instanceof JarPathname) { result.setDevice(d.getDevice()); } else { result.setDevice(p.getDevice()); } } } else { // If the defaults contain a JAR-PATHNAME, and the pathname // to be be merged is not a JAR-PATHNAME, does not have a // specified DEVICE, a specified HOST, and doesn't contain a // relative DIRECTORY, then on non-MSDOG, set its device to // :UNSPECIFIC. if ((d instanceof JarPathname) && !(result instanceof JarPathname)) { if (!Utilities.isPlatformWindows) { result.setDevice(Keyword.UNSPECIFIC); } else { result.setDevice(d.getDevice()); } } else { if (p.isLocalFile()) { result.setDevice(d.getDevice()); } else { result.setDevice(p.getDevice()); } } } if (pathname.isJar()) { result.setDirectory(p.getDirectory()); } else { result.setDirectory(mergeDirectories(p.getDirectory(), d.getDirectory())); // Directories are always absolute in a JarPathname if (result instanceof JarPathname) { LispObject directories = result.getDirectory(); if ((!directories.car().equals(NIL)) && directories.car().equals(Keyword.RELATIVE)) { directories = directories.cdr().push(Keyword.ABSOLUTE); result.setDirectory(directories); } } } if (pathname.getName() != NIL) { result.setName(p.getName()); } else { result.setName(d.getName()); } if (pathname.getType() != NIL) { result.setType(p.getType()); } else { result.setType(d.getType()); } // JAR-PATHNAME directories are always absolute if ((result instanceof JarPathname) && (!result.getName().equals(NIL) || !result.getType().equals(NIL)) && result.getDirectory().equals(NIL)) { result.setDirectory(NIL.push(Keyword.ABSOLUTE)); } // CLtLv2 MERGE-PATHNAMES // "[T]he missing components in the given pathname are filled // in from the defaults pathname, except that if no version is // specified the default version is used." // "The merging rules for the version are more complicated and // depend on whether the pathname specifies a name. If the // pathname doesn't specify a name, then the version, if not // provided, will come from the defaults, just like the other // components. However, if the pathname does specify a name, // then the version is not affected by the defaults. The // reason is that the version ``belongs to'' some other file // name and is unlikely to have anything to do with the new // one. Finally, if this process leaves the // version missing, the default version is used." if (p.getVersion() != NIL) { result.setVersion(p.getVersion()); } else if (p.getName() == NIL) { if (defaultPathname.getVersion() == NIL) { result.setVersion(defaultVersion); } else { result.setVersion(defaultPathname.getVersion()); } } else if (defaultVersion == NIL) { result.setVersion(p.getVersion()); } if (result.getVersion() == NIL) { result.setVersion(defaultVersion); } if (pathname instanceof LogicalPathname) { // When we're returning a logical result.setDevice(Keyword.UNSPECIFIC); if (result.getDirectory().listp()) { LispObject original = result.getDirectory(); LispObject canonical = NIL; while (original != NIL) { LispObject component = original.car(); if (component instanceof AbstractString) { component = LogicalPathname.canonicalizeStringComponent((AbstractString) component); } canonical = canonical.push(component); original = original.cdr(); } result.setDirectory(canonical.nreverse()); } if (result.getName() instanceof AbstractString) { result.setName(LogicalPathname.canonicalizeStringComponent((AbstractString) result.getName())); } if (result.getType() instanceof AbstractString) { result.setType(LogicalPathname.canonicalizeStringComponent((AbstractString) result.getType())); } } // Downcast to URLPathname if resolving a URLPathname if (result instanceof Pathname && URLPathname.hasExplicitFile(result)) { URLPathname downcastResult = new URLPathname(); downcastResult.copyFrom(result); result = downcastResult; } return result; } private static final LispObject mergeDirectories(LispObject dir, LispObject defaultDir) { if (dir == NIL) { return defaultDir; } if (dir.car() == Keyword.RELATIVE && defaultDir != NIL) { LispObject result = NIL; while (defaultDir != NIL) { result = new Cons(defaultDir.car(), result); defaultDir = defaultDir.cdr(); } dir = dir.cdr(); // Skip :RELATIVE. while (dir != NIL) { result = new Cons(dir.car(), result); dir = dir.cdr(); } LispObject[] array = result.copyToArray(); for (int i = 0; i < array.length - 1; i++) { if (array[i] == Keyword.BACK) { if (array[i + 1] instanceof AbstractString || array[i + 1] == Keyword.WILD) { array[i] = null; array[i + 1] = null; } } } result = NIL; for (int i = 0; i < array.length; i++) { if (array[i] != null) { result = new Cons(array[i], result); } } return result; } return dir; } public static LispObject truename(Pathname pathname) { return truename(pathname, false); } public static LispObject truename(LispObject arg) { return truename(arg, false); } public static LispObject truename(LispObject arg, boolean errorIfDoesNotExist) { final Pathname pathname = coerceToPathname(arg); return truename(pathname, errorIfDoesNotExist); } /** @return The canonical TRUENAME as a Pathname if the pathname * exists, otherwise returns NIL or possibly a subtype of * LispError if there are logical problems with the input. */ public static LispObject truename(Pathname pathname, boolean errorIfDoesNotExist) { if (pathname == null || pathname.equals(NIL)) { return doTruenameExit(pathname, errorIfDoesNotExist); } if (pathname instanceof LogicalPathname) { pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); } if (pathname.isWild()) { return error(new FileError("Fundamentally unable to find a truename for any wild pathname.", pathname)); } Pathname result = (Pathname)mergePathnames(pathname, coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), NIL); final File file = result.getFile(); if (file != null && file.exists()) { if (file.isDirectory()) { result = Pathname.getDirectoryPathname(file); } else { try { result = (Pathname)Pathname.create(file.getCanonicalPath()); } catch (IOException e) { return error(new FileError(e.getMessage(), pathname)); } } if (Utilities.isPlatformUnix) { result.setDevice(Keyword.UNSPECIFIC); } return result; } return doTruenameExit(pathname, errorIfDoesNotExist); } static LispObject doTruenameExit(Pathname pathname, boolean errorIfDoesNotExist) { if (errorIfDoesNotExist) { StringBuilder sb = new StringBuilder("The file "); sb.append(pathname.princToString()); sb.append(" does not exist."); return error(new FileError(sb.toString(), pathname)); } return NIL; } public static final Primitive GET_INPUT_STREAM = new pf_get_input_stream(); @DocString(name="get-input-stream", args="pathname", doc="Returns a java.io.InputStream for resource denoted by PATHNAME.") private static final class pf_get_input_stream extends Primitive { pf_get_input_stream() { super(Symbol.GET_INPUT_STREAM, "pathname"); } @Override public LispObject execute(LispObject pathname) { Pathname p = (Pathname) coerceToPathname(pathname); return new JavaObject(p.getInputStream()); } }; public InputStream getInputStream() { InputStream result = null; File file = getFile(); try { result = new FileInputStream(file); } catch (IOException e) { simple_error("Failed to get InputStream from ~a because ~a", this, e); } return result; } /** @return Time in milliseconds since the UNIX epoch at which the * resource was last modified, or 0 if the time is unknown. */ public long getLastModified() { File f = getFile(); return f.lastModified(); } private static final Primitive MKDIR = new pf_mkdir(); @DocString(name="mkdir", args="pathname", returns="generalized-boolean", doc="Attempts to create directory at PATHNAME returning the success or failure.") private static class pf_mkdir extends Primitive { pf_mkdir() { super("mkdir", PACKAGE_SYS, false, "pathname"); } @Override public LispObject execute(LispObject arg) { final Pathname pathname = coerceToPathname(arg); if (pathname.isWild()) { error(new FileError("Bad place for a wild pathname.", pathname)); } Pathname defaultedPathname = (Pathname)mergePathnames(pathname, coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), NIL); if (defaultedPathname.isURL() || defaultedPathname.isJar()) { return new FileError("Cannot mkdir with a " + (defaultedPathname.isURL() ? "URL" : "jar") + " Pathname.", defaultedPathname); } File file = defaultedPathname.getFile(); return file.mkdir() ? T : NIL; } } private static final Primitive RENAME_FILE = new pf_rename_file(); @DocString(name="rename-file", args="filespec new-name", returns="defaulted-new-name, old-truename, new-truename", doc = "Modifies the file system in such a way that the file indicated by FILESPEC is renamed to DEFAULTED-NEW-NAME.\n" + "\n" + "Returns three values if successful. The primary value, DEFAULTED-NEW-NAME, is \n" + "the resulting name which is composed of NEW-NAME with any missing components filled in by \n" + "performing a merge-pathnames operation using filespec as the defaults. The secondary \n" + "value, OLD-TRUENAME, is the truename of the file before it was renamed. The tertiary \n" + "value, NEW-TRUENAME, is the truename of the file after it was renamed.\n") private static class pf_rename_file extends Primitive { pf_rename_file() { super("rename-file", "filespec new-name"); } @Override public LispObject execute(LispObject first, LispObject second) { Pathname oldPathname = coerceToPathname(first); Pathname oldTruename = (Pathname) Symbol.TRUENAME.execute(oldPathname); Pathname newName = coerceToPathname(second); if (newName.isWild()) { error(new FileError("Bad place for a wild pathname.", newName)); } if (oldTruename.isJar()) { error(new FileError("Bad place for a jar pathname.", oldTruename)); } if (newName.isJar()) { error(new FileError("Bad place for a jar pathname.", newName)); } if (oldTruename.isURL()) { error(new FileError("Bad place for a URL pathname.", oldTruename)); } if (newName.isURL()) { error(new FileError("Bad place for a jar pathname.", newName)); } Pathname defaultedNewName = (Pathname)mergePathnames(newName, oldTruename, NIL); File source = oldTruename.getFile(); File destination = null; if (defaultedNewName instanceof LogicalPathname) { destination = LogicalPathname.translateLogicalPathname((LogicalPathname)defaultedNewName) .getFile(); } else { destination = defaultedNewName.getFile(); } if (Utilities.isPlatformWindows) { if (destination.isFile()) { //if (destination.isJar()) { // By default, MSDOG doesn't allow one to remove files that are open, so we need to close // any open jar references // FIXME // ZipCache.remove(destination); // } destination.delete(); } } if (source.renameTo(destination)) { // Success! Pathname newTruename = (Pathname)truename(defaultedNewName, true); return LispThread.currentThread().setValues(defaultedNewName, oldTruename, newTruename); } return error(new FileError("Unable to rename " + oldTruename.princToString() + " to " + newName.princToString() + ".", oldTruename)); } } // TODO clarify uri encoding cases in implementation and document private static final Primitive FILE_NAMESTRING = new pf_file_namestring(); @DocString(name="file-namestring", args="pathname", returns="namestring", doc="Returns just the name, type, and version components of PATHNAME.") private static class pf_file_namestring extends Primitive { pf_file_namestring() { super(Symbol.FILE_NAMESTRING, "pathname"); } @Override public LispObject execute(LispObject arg) { Pathname p = coerceToPathname(arg); StringBuilder sb = new StringBuilder(); if (p.getName() instanceof AbstractString) { sb.append(p.getName().getStringValue()); } else if (p.getName() == Keyword.WILD) { sb.append('*'); } else { return NIL; } if (p.getType() instanceof AbstractString) { sb.append('.'); sb.append(p.getType().getStringValue()); } else if (p.getType() == Keyword.WILD) { sb.append(".*"); } return new SimpleString(sb); } } private static final Primitive HOST_NAMESTRING = new pf_host_namestring(); @DocString(name="host-namestring", args="pathname", returns="namestring", doc="Returns the host name of PATHNAME.") private static class pf_host_namestring extends Primitive { pf_host_namestring() { super("host-namestring", "pathname"); } @Override public LispObject execute(LispObject arg) { return coerceToPathname(arg).getHost(); // XXX URL-PATHNAME } } static { LispObject obj = Symbol.DEFAULT_PATHNAME_DEFAULTS.getSymbolValue(); Symbol.DEFAULT_PATHNAME_DEFAULTS.setSymbolValue(coerceToPathname(obj)); } File getFile() { String namestring = getNamestring(); // XXX UNC pathnames currently have no namestring if (namestring != null) { return new File(namestring); } error(new FileError("Pathname has no namestring: " + princToString(), this)); return (File)UNREACHED; } public static Pathname getDirectoryPathname(File file) { try { String namestring = file.getCanonicalPath(); if (namestring != null && namestring.length() > 0) { // ??? do we really want the platform dependent separatorChar? if (namestring.charAt(namestring.length() - 1) != File.separatorChar) { namestring = namestring.concat(File.separator); } } return (Pathname)Pathname.create(namestring); } catch (IOException e) { error(new LispError(e.getMessage())); // Not reached. return null; } } // Whether this pathname represents a file on the filesystem, not // addressed as a JAR-PATHNAME public boolean isLocalFile() { if (getHost().equals(NIL) || Symbol.GETF.execute(getHost(), URLPathname.SCHEME, NIL).equals(URLPathname.FILE)) { return true; } return false; } Pathname getEntryPath() { return Pathname.create(asEntryPath()); } /** @return The representation of the DIRECTORY/NAME/TYPE elements * of pathname suitable for referencing an entry in a Zip/JAR file. * * This representation is always a relative path. */ String asEntryPath() { Pathname p = Pathname.create(); p.setDirectory(getDirectory()) .setName(getName()) .setType(getType()); String path = p.getNamestring(); StringBuilder result = new StringBuilder(); result.append(path); // ZipEntry syntax is always relative if (result.length() > 1 && result.substring(0, 1).equals("/")) { return result.substring(1); } return result.toString(); } boolean isRemote() { if (this instanceof URLPathname) { URLPathname p = (URLPathname) this; LispObject scheme = Symbol.GETF.execute(p.getHost(), URLPathname.SCHEME, NIL); if (scheme.equals(NIL) || p.getHost().getStringValue().equals("file")) { return false; } return true; } else if (this instanceof JarPathname) { Pathname root = (Pathname) ((JarPathname)this).getRootJar(); return root.isRemote(); } else { return false; } } } abcl-src-1.9.0/src/org/armedbear/lisp/Primitive.java0100644 0000000 0000000 00000013643 14202767264 021041 0ustar000000000 0000000 /* * Primitive.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public class Primitive extends Function { public Primitive(LispObject name) { super(name); } public Primitive(String name) { super(name); } public Primitive(Symbol symbol) { super(symbol); } public Primitive(Symbol symbol, String arglist) { super(symbol, arglist); } public Primitive(Symbol symbol, String arglist, String docstring) { super(symbol, arglist, docstring); } public Primitive(String name, String arglist) { super(name, arglist); } public Primitive(LispObject name, LispObject lambdaList) { super(name, lambdaList); } public Primitive(String name, Package pkg) { super(name, pkg); } public Primitive(String name, Package pkg, boolean exported) { super(name, pkg, exported); } public Primitive(String name, Package pkg, boolean exported, String arglist) { super(name, pkg, exported, arglist); } public Primitive(String name, Package pkg, boolean exported, String arglist, String docstring) { super(name, pkg, exported, arglist, docstring); } @Override public LispObject typeOf() { return Symbol.COMPILED_FUNCTION; } @Override public LispObject execute() { LispObject[] args = new LispObject[0]; return execute(args); } @Override public LispObject execute(LispObject arg) { LispObject[] args = new LispObject[1]; args[0] = arg; return execute(args); } @Override public LispObject execute(LispObject first, LispObject second) { LispObject[] args = new LispObject[2]; args[0] = first; args[1] = second; return execute(args); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { LispObject[] args = new LispObject[3]; args[0] = first; args[1] = second; args[2] = third; return execute(args); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { LispObject[] args = new LispObject[4]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; return execute(args); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { LispObject[] args = new LispObject[5]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; args[4] = fifth; return execute(args); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { LispObject[] args = new LispObject[6]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; args[4] = fifth; args[5] = sixth; return execute(args); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { LispObject[] args = new LispObject[7]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; args[4] = fifth; args[5] = sixth; args[6] = seventh; return execute(args); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { LispObject[] args = new LispObject[8]; args[0] = first; args[1] = second; args[2] = third; args[3] = fourth; args[4] = fifth; args[5] = sixth; args[6] = seventh; args[7] = eighth; return execute(args); } } abcl-src-1.9.0/src/org/armedbear/lisp/Primitives.java0100644 0000000 0000000 00000607751 14212332540 021217 0ustar000000000 0000000 /* * Primitives.java * * Copyright (C) 2002-2007 Peter Graves * Copyright (C) 2011 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.Serializable; import java.math.BigInteger; import java.util.ArrayList; import org.armedbear.lisp.util.Finalizer; public final class Primitives { // ### * public static final Primitive MULTIPLY = new pf_multiply(); private static final class pf_multiply extends Primitive { pf_multiply() { super(Symbol.STAR, "&rest numbers"); } @Override public LispObject execute() { return Fixnum.ONE; } @Override public LispObject execute(LispObject arg) { if (arg.numberp()) return arg; return type_error(arg, Symbol.NUMBER); } @Override public LispObject execute(LispObject first, LispObject second) { return first.multiplyBy(second); } @Override public LispObject execute(LispObject[] args) { LispObject result = Fixnum.ONE; for (int i = 0; i < args.length; i++) result = result.multiplyBy(args[i]); return result; } }; // ### / public static final Primitive DIVIDE = new pf_divide(); private static final class pf_divide extends Primitive { pf_divide() { super(Symbol.SLASH, "numerator &rest denominators"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return Fixnum.ONE.divideBy(arg); } @Override public LispObject execute(LispObject first, LispObject second) { return first.divideBy(second); } @Override public LispObject execute(LispObject[] args) { LispObject result = args[0]; for (int i = 1; i < args.length; i++) result = result.divideBy(args[i]); return result; } }; // ### min public static final Primitive MIN = new pf_min(); private static final class pf_min extends Primitive { pf_min() { super(Symbol.MIN, "&rest reals"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { if (arg.realp()) return arg; return type_error(arg, Symbol.REAL); } @Override public LispObject execute(LispObject first, LispObject second) { return first.isLessThan(second) ? first : second; } @Override public LispObject execute(LispObject[] args) { LispObject result = args[0]; if (!result.realp()) type_error(result, Symbol.REAL); for (int i = 1; i < args.length; i++) { if (args[i].isLessThan(result)) result = args[i]; } return result; } }; // ### max public static final Primitive MAX = new pf_max(); private static final class pf_max extends Primitive { pf_max() { super(Symbol.MAX, "&rest reals"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { if (arg.realp()) return arg; return type_error(arg, Symbol.REAL); } @Override public LispObject execute(LispObject first, LispObject second) { return first.isGreaterThan(second) ? first : second; } @Override public LispObject execute(LispObject[] args) { LispObject result = args[0]; if (!result.realp()) type_error(result, Symbol.REAL); for (int i = 1; i < args.length; i++) { if (args[i].isGreaterThan(result)) result = args[i]; } return result; } }; // ### identity private static final Primitive IDENTITY = new pf_identity(); private static final class pf_identity extends Primitive { pf_identity() { super(Symbol.IDENTITY, "object"); } @Override public LispObject execute(LispObject arg) { return arg; } }; // ### compiled-function-p private static final Primitive COMPILED_FUNCTION_P = new pf_compiled_function_p(); private static final class pf_compiled_function_p extends Primitive { pf_compiled_function_p() { super(Symbol.COMPILED_FUNCTION_P, "object"); } @Override public LispObject execute(LispObject arg) { return arg.typep(Symbol.COMPILED_FUNCTION); } }; // ### compiled-lisp-function-p private static final Primitive COMPILED_LISP_FUNCTION_P = new pf_compiled_lisp_function_p(); private static final class pf_compiled_lisp_function_p extends Primitive { pf_compiled_lisp_function_p() { super(Symbol.COMPILED_LISP_FUNCTION_P, "object"); } @Override public LispObject execute(LispObject arg) { return (arg instanceof CompiledClosure || arg instanceof CompiledPrimitive) ? T : NIL; } } // ### consp private static final Primitive CONSP = new pf_consp(); private static final class pf_consp extends Primitive { pf_consp() { super(Symbol.CONSP, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof Cons ? T : NIL; } }; // ### listp private static final Primitive LISTP = new pf_listp(); private static final class pf_listp extends Primitive { pf_listp() { super(Symbol.LISTP, "object"); } @Override public LispObject execute(LispObject arg) { return arg.LISTP(); } }; // ### abs private static final Primitive ABS = new pf_abs(); private static final class pf_abs extends Primitive { pf_abs() { super(Symbol.ABS, "number"); } @Override public LispObject execute(LispObject arg) { return arg.ABS(); } }; // ### arrayp private static final Primitive ARRAYP = new pf_arrayp(); private static final class pf_arrayp extends Primitive { pf_arrayp() { super(Symbol.ARRAYP, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof AbstractArray ? T : NIL; } }; // ### array-has-fill-pointer-p private static final Primitive ARRAY_HAS_FILL_POINTER_P = new pf_array_has_fill_pointer_p(); private static final class pf_array_has_fill_pointer_p extends Primitive { pf_array_has_fill_pointer_p() { super(Symbol.ARRAY_HAS_FILL_POINTER_P, "array"); } @Override public LispObject execute(LispObject arg) { return checkArray(arg).hasFillPointer() ? T : NIL; } }; // ### vectorp private static final Primitive VECTORP = new pf_vectorp(); private static final class pf_vectorp extends Primitive { pf_vectorp() { super(Symbol.VECTORP, "object"); } @Override public LispObject execute(LispObject arg) { return arg.VECTORP(); } }; // ### simple-vector-p private static final Primitive SIMPLE_VECTOR_P = new pf_simple_vector_p(); private static final class pf_simple_vector_p extends Primitive { pf_simple_vector_p() { super(Symbol.SIMPLE_VECTOR_P, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof SimpleVector ? T : NIL; } }; // ### bit-vector-p private static final Primitive BIT_VECTOR_P = new pf_bit_vector_p(); private static final class pf_bit_vector_p extends Primitive { pf_bit_vector_p() { super(Symbol.BIT_VECTOR_P, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof AbstractBitVector ? T : NIL; } }; // ### simple-bit-vector-p private static final Primitive SIMPLE_BIT_VECTOR_P = new pf_simple_bit_vector_p(); private static final class pf_simple_bit_vector_p extends Primitive { pf_simple_bit_vector_p() { super(Symbol.SIMPLE_BIT_VECTOR_P, "object"); } @Override public LispObject execute(LispObject arg) { return arg.typep(Symbol.SIMPLE_BIT_VECTOR); } }; // ### %eval private static final Primitive _EVAL = new pf__eval(); private static final class pf__eval extends Primitive { pf__eval() { super("%eval", PACKAGE_SYS, false, "form"); } @Override public LispObject execute(LispObject arg) { return eval(arg, new Environment(), LispThread.currentThread()); } }; // ### eq private static final Primitive EQ = new pf_eq(); private static final class pf_eq extends Primitive { pf_eq() { super(Symbol.EQ, "x y"); } @Override public LispObject execute(LispObject first, LispObject second) { return first == second ? T : NIL; } }; // ### eql static final Primitive EQL = new pf_eql(); private static final class pf_eql extends Primitive { pf_eql() { super(Symbol.EQL, "x y"); } @Override public LispObject execute(LispObject first, LispObject second) { return first.eql(second) ? T : NIL; } }; // ### equal private static final Primitive EQUAL = new pf_equal(); private static final class pf_equal extends Primitive { pf_equal() { super(Symbol.EQUAL, "x y"); } @Override public LispObject execute(LispObject first, LispObject second) { return first.equal(second) ? T : NIL; } }; // ### equalp private static final Primitive EQUALP = new pf_equalp(); private static final class pf_equalp extends Primitive { pf_equalp() { super(Symbol.EQUALP, "x y"); } @Override public LispObject execute(LispObject first, LispObject second) { return first.equalp(second) ? T : NIL; } }; // ### values public static final Primitive VALUES = new pf_values(); private static final class pf_values extends Primitive { pf_values() { super(Symbol.VALUES, "&rest object"); } @Override public LispObject execute() { return LispThread.currentThread().setValues(); } @Override public LispObject execute(LispObject arg) { return LispThread.currentThread().setValues(arg); } @Override public LispObject execute(LispObject first, LispObject second) { return LispThread.currentThread().setValues(first, second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return LispThread.currentThread().setValues(first, second, third); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return LispThread.currentThread().setValues(first, second, third, fourth); } @Override public LispObject execute(LispObject[] args) { return LispThread.currentThread().setValues(args); } }; // ### values-list list => element* // Returns the elements of the list as multiple values. private static final Primitive VALUES_LIST = new pf_values_list(); private static final class pf_values_list extends Primitive { pf_values_list() { super(Symbol.VALUES_LIST, "list"); } @Override public LispObject execute(LispObject arg) { if (arg == NIL) return LispThread.currentThread().setValues(); if (arg.cdr() == NIL) return arg.car(); return LispThread.currentThread().setValues(arg.copyToArray()); } }; // ### cons private static final Primitive CONS = new pf_cons(); private static final class pf_cons extends Primitive { pf_cons() { super(Symbol.CONS, "object-1 object-2"); } @Override public LispObject execute(LispObject first, LispObject second) { return new Cons(first, second); } }; // ### length private static final Primitive LENGTH = new pf_length(); private static final class pf_length extends Primitive { pf_length() { super("%LENGTH", PACKAGE_SYS, false, "sequence"); } @Override public LispObject execute(LispObject arg) { return arg.LENGTH(); } }; // ### elt private static final Primitive ELT = new pf_elt(); private static final class pf_elt extends Primitive { pf_elt() { super("%ELT", PACKAGE_SYS, false, "sequence index"); } @Override public LispObject execute(LispObject first, LispObject second) { return first.elt(Fixnum.getValue(second)); } }; // ### atom private static final Primitive ATOM = new pf_atom(); private static final class pf_atom extends Primitive { pf_atom() { super(Symbol.ATOM, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof Cons ? NIL : T; } }; // ### constantp private static final Primitive CONSTANTP = new pf_constantp(); private static final class pf_constantp extends Primitive { pf_constantp() { super(Symbol.CONSTANTP, "form &optional environment"); } @Override public LispObject execute(LispObject arg) { return arg.constantp() ? T : NIL; } @Override public LispObject execute(LispObject first, LispObject second) { return first.constantp() ? T : NIL; } }; // ### functionp private static final Primitive FUNCTIONP = new pf_functionp(); private static final class pf_functionp extends Primitive { pf_functionp() { super(Symbol.FUNCTIONP, "object"); } @Override public LispObject execute(LispObject arg) { return (arg instanceof Function || arg instanceof FuncallableStandardObject) ? T : NIL; } }; // ### special-operator-p private static final Primitive SPECIAL_OPERATOR_P = new pf_special_operator_p(); private static final class pf_special_operator_p extends Primitive { pf_special_operator_p() { super(Symbol.SPECIAL_OPERATOR_P, "symbol"); } @Override public LispObject execute(LispObject arg) { return arg.isSpecialOperator() ? T : NIL; } }; // ### symbolp private static final Primitive SYMBOLP = new pf_symbolp(); private static final class pf_symbolp extends Primitive { pf_symbolp() { super(Symbol.SYMBOLP, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof Symbol ? T : NIL; } }; // ### endp private static final Primitive ENDP = new pf_endp(); private static final class pf_endp extends Primitive { pf_endp() { super(Symbol.ENDP, "list"); } @Override public LispObject execute(LispObject arg) { return arg.endp() ? T : NIL; } }; // ### null private static final Primitive NULL = new pf_null(); private static final class pf_null extends Primitive { pf_null() { super(Symbol.NULL, "object"); } @Override public LispObject execute(LispObject arg) { return arg == NIL ? T : NIL; } }; // ### not private static final Primitive NOT = new pf_not(); private static final class pf_not extends Primitive { pf_not() { super(Symbol.NOT, "x"); } @Override public LispObject execute(LispObject arg) { return arg == NIL ? T : NIL; } }; // ### plusp private static final Primitive PLUSP = new pf_plusp(); private static final class pf_plusp extends Primitive { pf_plusp() { super(Symbol.PLUSP, "real"); } @Override public LispObject execute(LispObject arg) { return arg.PLUSP(); } }; // ### minusp private static final Primitive MINUSP = new pf_minusp(); private static final class pf_minusp extends Primitive { pf_minusp() { super(Symbol.MINUSP, "real"); } @Override public LispObject execute(LispObject arg) { return arg.MINUSP(); } }; // ### zerop private static final Primitive ZEROP = new pf_zerop(); private static final class pf_zerop extends Primitive { pf_zerop() { super(Symbol.ZEROP, "number"); } @Override public LispObject execute(LispObject arg) { return arg.ZEROP(); } }; // ### fixnump private static final Primitive FIXNUMP = new pf_fixnump(); private static final class pf_fixnump extends Primitive { pf_fixnump() { super("fixnump", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { return arg instanceof Fixnum ? T : NIL; } }; // ### symbol-value private static final Primitive SYMBOL_VALUE = new pf_symbol_value(); private static final class pf_symbol_value extends Primitive { pf_symbol_value() { super(Symbol.SYMBOL_VALUE, "symbol"); } @Override public LispObject execute(LispObject arg) { final LispObject value; value = checkSymbol(arg).symbolValue(); return value; } }; // ### set symbol value => value private static final Primitive SET = new pf_set(); private static final class pf_set extends Primitive { pf_set() { super(Symbol.SET, "symbol value"); } @Override public LispObject execute(LispObject first, LispObject second) { return LispThread.currentThread().setSpecialVariable(checkSymbol(first), second); } }; // ### rplaca private static final Primitive RPLACA = new pf_rplaca(); private static final class pf_rplaca extends Primitive { pf_rplaca() { super(Symbol.RPLACA, "cons object"); } @Override public LispObject execute(LispObject first, LispObject second) { first.setCar(second); return first; } }; // ### rplacd private static final Primitive RPLACD = new pf_rplacd(); private static final class pf_rplacd extends Primitive { pf_rplacd() { super(Symbol.RPLACD, "cons object"); } @Override public LispObject execute(LispObject first, LispObject second) { first.setCdr(second); return first; } }; // ### + private static final Primitive ADD = new pf_add(); private static final class pf_add extends Primitive { pf_add() { super(Symbol.PLUS, "&rest numbers"); } @Override public LispObject execute() { return Fixnum.ZERO; } @Override public LispObject execute(LispObject arg) { if (arg.numberp()) return arg; return type_error(arg, Symbol.NUMBER); } @Override public LispObject execute(LispObject first, LispObject second) { return first.add(second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return first.add(second).add(third); } @Override public LispObject execute(LispObject[] args) { LispObject result = Fixnum.ZERO; final int length = args.length; for (int i = 0; i < length; i++) result = result.add(args[i]); return result; } }; // ### 1+ private static final Primitive ONE_PLUS = new pf_one_plus(); private static final class pf_one_plus extends Primitive { pf_one_plus() { super(Symbol.ONE_PLUS, "number"); } @Override public LispObject execute(LispObject arg) { return arg.incr(); } }; // ### - private static final Primitive SUBTRACT = new pf_subtract(); private static final class pf_subtract extends Primitive { pf_subtract() { super(Symbol.MINUS, "minuend &rest subtrahends"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return arg.negate(); } @Override public LispObject execute(LispObject first, LispObject second) { return first.subtract(second); } @Override public LispObject execute(LispObject[] args) { LispObject result = args[0]; for (int i = 1; i < args.length; i++) result = result.subtract(args[i]); return result; } }; // ### 1- private static final Primitive ONE_MINUS = new pf_one_minus(); private static final class pf_one_minus extends Primitive { pf_one_minus() { super(Symbol.ONE_MINUS, "number"); } @Override public LispObject execute(LispObject arg) { return arg.decr(); } }; // ### when private static final SpecialOperator WHEN = new sf_when(); private static final class sf_when extends SpecialOperator { sf_when() { super(Symbol.WHEN); } @Override public LispObject execute(LispObject args, Environment env) { if (args == NIL) return error(new WrongNumberOfArgumentsException(this, 1, -1)); final LispThread thread = LispThread.currentThread(); if (eval(args.car(), env, thread) != NIL) { args = args.cdr(); thread.clearValues(); return progn(args, env, thread); } return thread.setValues(NIL); } }; // ### unless private static final SpecialOperator UNLESS = new sf_unless(); private static final class sf_unless extends SpecialOperator { sf_unless() { super(Symbol.UNLESS); } @Override public LispObject execute(LispObject args, Environment env) { if (args == NIL) return error(new WrongNumberOfArgumentsException(this, 1, -1)); final LispThread thread = LispThread.currentThread(); if (eval(args.car(), env, thread) == NIL) { args = args.cdr(); thread.clearValues(); return progn(args, env, thread); } return thread.setValues(NIL); } }; // ### %stream-output-object object stream => object private static final Primitive _STREAM_OUTPUT_OBJECT = new pf__stream_output_object(); private static final class pf__stream_output_object extends Primitive { pf__stream_output_object() { super("%stream-output-object", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { checkStream(second)._writeString(first.printObject()); return first; } }; // ### %output-object object stream => object private static final Primitive _OUTPUT_OBJECT = new pf__output_object(); private static final class pf__output_object extends Primitive { pf__output_object() { super("%output-object", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { final LispObject out; if (second == T) out = Symbol.TERMINAL_IO.symbolValue(); else if (second == NIL) out = Symbol.STANDARD_OUTPUT.symbolValue(); else out = second; String output = first.printObject(); checkStream(out)._writeString(output); return first; } }; // ### %write-to-string object => string private static final Primitive _WRITE_TO_STRING = new pf__write_to_string(); private static final class pf__write_to_string extends Primitive { pf__write_to_string() { super("%write-to-string", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject arg) { return new SimpleString(arg.printObject()); } }; // ### %stream-terpri output-stream => nil private static final Primitive _STREAM_TERPRI = new pf__stream_terpri(); private static final class pf__stream_terpri extends Primitive { pf__stream_terpri() { super("%stream-terpri", PACKAGE_SYS, true, "output-stream"); } @Override public LispObject execute(LispObject arg) { checkStream(arg)._writeChar('\n'); return NIL; } }; // ### %terpri output-stream => nil private static final Primitive _TERPRI = new pf__terpri(); private static final class pf__terpri extends Primitive { pf__terpri() { super("%terpri", PACKAGE_SYS, false, "output-stream"); } @Override public LispObject execute(LispObject arg) { if (arg == T) arg = Symbol.TERMINAL_IO.symbolValue(); else if (arg == NIL) arg = Symbol.STANDARD_OUTPUT.symbolValue(); final Stream stream; stream = checkStream(arg); return stream.terpri(); } }; // ### %fresh-line // %fresh-line &optional output-stream => generalized-boolean private static final Primitive _FRESH_LINE = new pf__fresh_line(); private static final class pf__fresh_line extends Primitive { pf__fresh_line() { super("%fresh-line", PACKAGE_SYS, false, "output-stream"); } @Override public LispObject execute(LispObject arg) { if (arg == T) arg = Symbol.TERMINAL_IO.symbolValue(); else if (arg == NIL) arg = Symbol.STANDARD_OUTPUT.symbolValue(); final Stream stream; stream = checkStream(arg); return stream.freshLine(); } }; // ### boundp // Determines only whether a symbol has a value in the global environment; // any lexical bindings are ignored. private static final Primitive BOUNDP = new pf_boundp(); private static final class pf_boundp extends Primitive { pf_boundp() { super(Symbol.BOUNDP, "symbol"); } @Override public LispObject execute(LispObject arg) { final Symbol symbol; symbol = checkSymbol(arg); // PROGV: "If too few values are supplied, the remaining symbols // are bound and then made to have no value." So BOUNDP must // explicitly check for a binding with no value. SpecialBinding binding = LispThread.currentThread().getSpecialBinding(symbol); if (binding != null) return binding.value != null ? T : NIL; // No binding. return symbol.getSymbolValue() != null ? T : NIL; } }; // ### fboundp private static final Primitive FBOUNDP = new pf_fboundp(); private static final class pf_fboundp extends Primitive { pf_fboundp() { super(Symbol.FBOUNDP, "name"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Symbol) return arg.getSymbolFunction() != null ? T : NIL; if (isValidSetfFunctionName(arg)) { LispObject f = get(arg.cadr(), Symbol.SETF_FUNCTION, null); return f != null ? T : NIL; } return type_error(arg, FUNCTION_NAME); } }; // ### fmakunbound name => name private static final Primitive FMAKUNBOUND = new pf_fmakunbound(); private static final class pf_fmakunbound extends Primitive { pf_fmakunbound() { super(Symbol.FMAKUNBOUND, "name"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Symbol) { checkSymbol(arg).setSymbolFunction(null); return arg; } if (isValidSetfFunctionName(arg)) { remprop((Symbol)arg.cadr(), Symbol.SETF_FUNCTION); return arg; } return type_error(arg, FUNCTION_NAME); } }; // ### setf-function-name-p private static final Primitive SETF_FUNCTION_NAME_P = new pf_setf_function_name_p(); private static final class pf_setf_function_name_p extends Primitive { pf_setf_function_name_p() { super("setf-function-name-p", PACKAGE_SYS, true, "thing"); } @Override public LispObject execute(LispObject arg) { return isValidSetfFunctionName(arg) ? T : NIL; } }; // ### remprop private static final Primitive REMPROP = new pf_remprop(); private static final class pf_remprop extends Primitive { pf_remprop() { super(Symbol.REMPROP, "symbol indicator"); } @Override public LispObject execute(LispObject first, LispObject second) { return remprop(checkSymbol(first), second); } }; // ### append public static final Primitive APPEND = new pf_append(); private static final class pf_append extends Primitive { pf_append() { super(Symbol.APPEND, "&rest lists"); } @Override public LispObject execute() { return NIL; } @Override public LispObject execute(LispObject arg) { return arg; } @Override public LispObject execute(LispObject first, LispObject second) { if (first == NIL) return second; // APPEND is required to copy its first argument. Cons result = new Cons(first.car()); Cons splice = result; first = first.cdr(); while (first != NIL) { Cons temp = new Cons(first.car()); splice.cdr = temp; splice = temp; first = first.cdr(); } splice.cdr = second; return result; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first == NIL) return execute(second, third); Cons result = new Cons(first.car()); Cons splice = result; first = first.cdr(); while (first != NIL) { Cons temp = new Cons(first.car()); splice.cdr = temp; splice = temp; first = first.cdr(); } while (second != NIL) { Cons temp = new Cons(second.car()); splice.cdr = temp; splice = temp; second = second.cdr(); } splice.cdr = third; return result; } @Override public LispObject execute(LispObject[] args) { Cons result = null; Cons splice = null; final int limit = args.length - 1; int i; for (i = 0; i < limit; i++) { LispObject top = args[i]; if (top == NIL) continue; result = new Cons(top.car()); splice = result; top = top.cdr(); while (top != NIL) { Cons temp = new Cons(top.car()); splice.cdr = temp; splice = temp; top = top.cdr(); } break; } if (result == null) return args[i]; for (++i; i < limit; i++) { LispObject top = args[i]; while (top != NIL) { Cons temp = new Cons(top.car()); splice.cdr = temp; splice = temp; top = top.cdr(); } } splice.cdr = args[i]; return result; } }; // ### nconc private static final Primitive NCONC = new pf_nconc(); private static final class pf_nconc extends Primitive { pf_nconc() { super(Symbol.NCONC, "&rest lists"); } @Override public LispObject execute() { return NIL; } @Override public LispObject execute(LispObject arg) { return arg; } @Override public LispObject execute(LispObject first, LispObject second) { if (first == NIL) return second; if (first instanceof Cons) { LispObject result = first; Cons splice = null; while (first instanceof Cons) { splice = (Cons) first; first = splice.cdr; } splice.cdr = second; return result; } return type_error(first, Symbol.LIST); } @Override public LispObject execute(LispObject[] array) { LispObject result = null; Cons splice = null; final int limit = array.length - 1; int i; for (i = 0; i < limit; i++) { LispObject list = array[i]; if (list == NIL) continue; if (list instanceof Cons) { if (splice != null) { splice.cdr = list; splice = (Cons) list; } while (list instanceof Cons) { if (result == null) { result = list; splice = (Cons) result; } else splice = (Cons) list; list = splice.cdr; } } else type_error(list, Symbol.LIST); } if (result == null) return array[i]; splice.cdr = array[i]; return result; } }; // ### = // Numeric equality. private static final Primitive EQUALS = new pf_equals(); private static final class pf_equals extends Primitive { pf_equals() { super(Symbol.EQUALS, "&rest numbers"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return T; } @Override public LispObject execute(LispObject first, LispObject second) { return first.isEqualTo(second) ? T : NIL; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first.isEqualTo(second) && second.isEqualTo(third)) return T; else return NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; final LispObject obj = array[0]; for (int i = 1; i < length; i++) { if (array[i].isNotEqualTo(obj)) return NIL; } return T; } }; // ### /= // Returns true if no two numbers are the same; otherwise returns false. private static final Primitive NOT_EQUALS = new pf_not_equals(); private static final class pf_not_equals extends Primitive { pf_not_equals() { super(Symbol.NOT_EQUALS, "&rest numbers"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return T; } @Override public LispObject execute(LispObject first, LispObject second) { return first.isNotEqualTo(second) ? T : NIL; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first.isEqualTo(second)) return NIL; if (first.isEqualTo(third)) return NIL; if (second.isEqualTo(third)) return NIL; return T; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; for (int i = 0; i < length; i++) { final LispObject obj = array[i]; for (int j = i+1; j < length; j++) { if (array[j].isEqualTo(obj)) return NIL; } } return T; } }; // ### < // Numeric comparison. private static final Primitive LT = new pf_lt(); private static final class pf_lt extends Primitive { pf_lt() { super(Symbol.LT, "&rest numbers"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return T; } @Override public LispObject execute(LispObject first, LispObject second) { return first.isLessThan(second) ? T : NIL; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first.isLessThan(second) && second.isLessThan(third)) return T; else return NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; for (int i = 1; i < length; i++) { if (array[i].isLessThanOrEqualTo(array[i-1])) return NIL; } return T; } }; // ### <= private static final Primitive LE = new pf_le(); private static final class pf_le extends Primitive { pf_le() { super(Symbol.LE, "&rest numbers"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return T; } @Override public LispObject execute(LispObject first, LispObject second) { return first.isLessThanOrEqualTo(second) ? T : NIL; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first.isLessThanOrEqualTo(second) && second.isLessThanOrEqualTo(third)) return T; else return NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; for (int i = 1; i < length; i++) { if (array[i].isLessThan(array[i-1])) return NIL; } return T; } }; // ### > private static final Primitive GT = new pf_gt(); private static final class pf_gt extends Primitive { pf_gt() { super(Symbol.GT, "&rest numbers"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return T; } @Override public LispObject execute(LispObject first, LispObject second) { return first.isGreaterThan(second) ? T : NIL; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first.isGreaterThan(second) && second.isGreaterThan(third)) return T; else return NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; for (int i = 1; i < length; i++) { if (array[i].isGreaterThanOrEqualTo(array[i-1])) return NIL; } return T; } }; // ### >= private static final Primitive GE = new pf_ge(); private static final class pf_ge extends Primitive { pf_ge() { super(Symbol.GE, "&rest numbers"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return T; } @Override public LispObject execute(LispObject first, LispObject second) { return first.isGreaterThanOrEqualTo(second) ? T : NIL; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first.isGreaterThanOrEqualTo(second) && second.isGreaterThanOrEqualTo(third)) return T; else return NIL; } @Override public LispObject execute(LispObject[] array) { final int length = array.length; for (int i = 1; i < length; i++) { if (array[i].isGreaterThan(array[i-1])) return NIL; } return T; } }; // ### nth n list => object private static final Primitive NTH = new pf_nth(); private static final class pf_nth extends Primitive { pf_nth() { super(Symbol.NTH, "n list"); } @Override public LispObject execute(LispObject first, LispObject second) { return second.NTH(first); } }; // ### %set-nth n list new-object => new-object private static final Primitive _SET_NTH = new pf__set_nth(); private static final class pf__set_nth extends Primitive { pf__set_nth() { super("%set-nth", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { int index = Fixnum.getValue(first); if (index < 0) error(new TypeError("(SETF NTH): invalid index " + index + ".")); int i = 0; while (true) { if (i == index) { second.setCar(third); return third; } second = second.cdr(); if (second == NIL) { return error(new LispError("(SETF NTH): the index " + index + "is too large.")); } ++i; } } }; // ### nthcdr private static final Primitive NTHCDR = new pf_nthcdr(); private static final class pf_nthcdr extends Primitive { pf_nthcdr() { super(Symbol.NTHCDR, "n list"); } @Override public LispObject execute(LispObject first, LispObject second) { final int index = Fixnum.getValue(first); if (index < 0) return type_error(first, list(Symbol.INTEGER, Fixnum.ZERO)); for (int i = 0; i < index; i++) { second = second.cdr(); if (second == NIL) return NIL; } return second; } }; /** Stub to be replaced later when signal.lisp has been loaded. */ // ### error private static final Primitive ERROR = new pf_error(); private static final class pf_error extends Primitive { pf_error() { super(Symbol.ERROR, "datum &rest arguments"); } @Override @SuppressWarnings("CallToThreadDumpStack") public LispObject execute(LispObject[] args) { Error e = new IntegrityError(); e.printStackTrace(); System.out.println("ERROR placeholder called with arguments:"); if (args.length == 1 && args[0] instanceof Condition) { System.out.println(args[0].princToString()); System.out.println(((Condition)args[0]).getConditionReport()); } else for (LispObject a : args) System.out.println(a.princToString()); throw e; } }; /** Stub replaced when compiler-pass2.lisp has been loaded */ // ### autocompile private static final Primitive AUTOCOMPILE = new pf_autocompile(); private static final class pf_autocompile extends Primitive { pf_autocompile() { super(Symbol.AUTOCOMPILE, "function"); } @Override public LispObject execute(LispObject function) { return NIL; } }; // ### signal /** Placeholder function, to be replaced by the function * defined in signal.lisp * * Calling this function is an error: we're not set up for * signalling yet. */ private static final Primitive SIGNAL = new pf_signal(); private static final class pf_signal extends Primitive { pf_signal() { super(Symbol.SIGNAL, "datum &rest arguments"); } @Override public LispObject execute(LispObject[] args) { if (args.length < 1) return error(new WrongNumberOfArgumentsException(this, 1, -1)); if (args[0] instanceof Condition) return error((Condition)args[0]); return error(new SimpleCondition()); } }; // ### undefined-function-called // Redefined in restart.lisp. private static final Primitive UNDEFINED_FUNCTION_CALLED = new pf_undefined_function_called(); private static final class pf_undefined_function_called extends Primitive { pf_undefined_function_called() { super(Symbol.UNDEFINED_FUNCTION_CALLED, "name arguments"); } @Override public LispObject execute(LispObject first, LispObject second) { return error(new UndefinedFunction(first)); } }; // ### %format private static final Primitive _FORMAT = new pf__format(); private static final class pf__format extends Primitive { pf__format() { super("%format", PACKAGE_SYS, false, "destination control-string &rest args"); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { LispObject destination = first; // Copy remaining arguments. LispObject[] _args = new LispObject[2]; _args[0] = second; _args[1] = third; String s = _format(_args); return outputFormattedString(s, destination); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { LispObject destination = first; // Copy remaining arguments. LispObject[] _args = new LispObject[3]; _args[0] = second; _args[1] = third; _args[2] = fourth; String s = _format(_args); return outputFormattedString(s, destination); } @Override public LispObject execute(LispObject[] args) { if (args.length < 2) return error(new WrongNumberOfArgumentsException(this, 2, -1)); LispObject destination = args[0]; // Copy remaining arguments. LispObject[] _args = new LispObject[args.length - 1]; for (int i = 0; i < _args.length; i++) _args[i] = args[i+1]; String s = _format(_args); return outputFormattedString(s, destination); } private final String _format(LispObject[] args) { LispObject formatControl = args[0]; LispObject formatArguments = NIL; for (int i = 1; i < args.length; i++) formatArguments = new Cons(args[i], formatArguments); formatArguments = formatArguments.nreverse(); return format(formatControl, formatArguments); } private final LispObject outputFormattedString(String s, LispObject destination) { if (destination == T) { checkCharacterOutputStream(Symbol.STANDARD_OUTPUT.symbolValue())._writeString(s); return NIL; } if (destination == NIL) return new SimpleString(s); if (destination instanceof TwoWayStream) { Stream out = ((TwoWayStream)destination).getOutputStream(); if (out instanceof Stream) { (out)._writeString(s); return NIL; } error(new TypeError("The value " + destination.princToString() + " is not a character output stream.")); } if (destination instanceof Stream) { ((Stream)destination)._writeString(s); return NIL; } return NIL; } }; static void checkRedefinition(LispObject arg) { final LispThread thread = LispThread.currentThread(); if (_WARN_ON_REDEFINITION_.symbolValue(thread) != NIL) { if (arg instanceof Symbol) { LispObject oldDefinition = arg.getSymbolFunction(); if (oldDefinition != null && !(oldDefinition instanceof Autoload)) { LispObject oldSource = Extensions.SOURCE_PATHNAME.execute(arg); LispObject currentSource = _SOURCE_.symbolValue(thread); if (currentSource == NIL) currentSource = Keyword.TOP_LEVEL; if (oldSource != NIL) { if (currentSource.equal(oldSource)) return; // OK } if (currentSource == Keyword.TOP_LEVEL) { Symbol.STYLE_WARN.execute(new SimpleString("redefining ~S at top level"), arg); } else { SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol._PACKAGE_, PACKAGE_CL); try { Symbol.STYLE_WARN.execute(new SimpleString("redefining ~S in ~S"), arg, currentSource); } finally { thread.resetSpecialBindings(mark); } } } } } } // ### %defun name definition => name private static final Primitive _DEFUN = new pf__defun(); private static final class pf__defun extends Primitive { pf__defun() { super("%defun", PACKAGE_SYS, true, "name definition"); } @Override public LispObject execute(LispObject name, LispObject definition) { if (name instanceof Symbol) { Symbol symbol = (Symbol) name; if (symbol.getSymbolFunction() instanceof SpecialOperator) { return program_error(symbol.getName() + " is a special operator and may not be redefined."); } } else if (!isValidSetfFunctionName(name)) return type_error(name, FUNCTION_NAME); if (definition instanceof Function) { Symbol.FSET.execute(name, definition, NIL, ((Function)definition).getLambdaList()); return name; } return type_error(definition, Symbol.FUNCTION); } }; // ### fdefinition-block-name private static final Primitive FDEFINITION_BLOCK_NAME = new pf_fdefinition_block_name(); private static final class pf_fdefinition_block_name extends Primitive { pf_fdefinition_block_name() { super("fdefinition-block-name", PACKAGE_SYS, true, "function-name"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Symbol) return arg; if (isValidSetfFunctionName(arg)) return arg.cadr(); return type_error(arg, FUNCTION_NAME); } }; // ### macro-function private static final Primitive MACRO_FUNCTION = new pf_macro_function(); private static final class pf_macro_function extends Primitive { pf_macro_function() { super(Symbol.MACRO_FUNCTION, "symbol &optional environment"); } @Override public LispObject execute(LispObject arg) { LispObject obj = arg.getSymbolFunction(); if (obj instanceof AutoloadMacro) { ((AutoloadMacro)obj).load(); obj = arg.getSymbolFunction(); } if (obj instanceof MacroObject) return ((MacroObject)obj).expander; if (obj instanceof SpecialOperator) { obj = get(arg, Symbol.MACROEXPAND_MACRO, NIL); if (obj instanceof AutoloadMacro) { ((AutoloadMacro)obj).load(); obj = get(arg, Symbol.MACROEXPAND_MACRO, NIL); } if (obj instanceof MacroObject) return ((MacroObject)obj).expander; } return NIL; } @Override public LispObject execute(LispObject first, LispObject second) { LispObject obj; if (second != NIL) { Environment env = checkEnvironment(second); obj = env.lookupFunction(first); } else obj = first.getSymbolFunction(); if (obj instanceof AutoloadMacro) { ((AutoloadMacro)obj).load(); obj = first.getSymbolFunction(); } if (obj instanceof MacroObject) return ((MacroObject)obj).expander; if (obj instanceof SpecialOperator) { obj = get(first, Symbol.MACROEXPAND_MACRO, NIL); if (obj instanceof AutoloadMacro) { ((AutoloadMacro)obj).load(); obj = get(first, Symbol.MACROEXPAND_MACRO, NIL); } if (obj instanceof MacroObject) return ((MacroObject)obj).expander; } return NIL; } }; // ### defmacro private static final SpecialOperator DEFMACRO = new sf_defmacro(); private static final class sf_defmacro extends SpecialOperator { sf_defmacro() { super(Symbol.DEFMACRO); } @Override public LispObject execute(LispObject args, Environment env) { Symbol symbol = checkSymbol(args.car()); LispObject expander = MAKE_MACRO_EXPANDER.execute(args); Closure expansionFunction = new Closure(expander, env); MacroObject macroObject = new MacroObject(symbol, expansionFunction); if (symbol.getSymbolFunction() instanceof SpecialOperator) put(symbol, Symbol.MACROEXPAND_MACRO, macroObject); else symbol.setSymbolFunction(macroObject); macroObject.setLambdaList(args.cadr()); LispThread.currentThread()._values = null; return symbol; } }; // ### make-macro private static final Primitive MAKE_MACRO = new pf_make_macro(); private static final class pf_make_macro extends Primitive { pf_make_macro() { super("make-macro", PACKAGE_SYS, true, "name expansion-function"); } @Override public LispObject execute(LispObject first, LispObject second) { return new MacroObject(first, second); } }; // ### macro-function-p private static final Primitive MACRO_FUNCTION_P = new pf_macro_function_p(); private static final class pf_macro_function_p extends Primitive { pf_macro_function_p() { super("macro-function-p", PACKAGE_SYS, true, "value"); } @Override public LispObject execute(LispObject arg) { return (arg instanceof MacroObject) ? T : NIL; } }; // ### make-symbol-macro private static final Primitive MAKE_SYMBOL_MACRO = new pf_make_symbol_macro(); private static final class pf_make_symbol_macro extends Primitive { pf_make_symbol_macro() { super("make-symbol-macro", PACKAGE_SYS, true, "expansion"); } @Override public LispObject execute(LispObject arg) { return new SymbolMacro(arg); } }; // ### %set-symbol-macro private static final Primitive SET_SYMBOL_MACRO = new pf_set_symbol_macro(); private static final class pf_set_symbol_macro extends Primitive { pf_set_symbol_macro() { super("%set-symbol-macro", PACKAGE_SYS, false, "symbol symbol-macro"); } @Override public LispObject execute(LispObject sym, LispObject symbolMacro) { checkSymbol(sym).setSymbolMacro((SymbolMacro) symbolMacro); return symbolMacro; } }; // ### symbol-macro-p private static final Primitive SYMBOL_MACRO_P = new pf_symbol_macro_p(); private static final class pf_symbol_macro_p extends Primitive { pf_symbol_macro_p() { super("symbol-macro-p", PACKAGE_SYS, true, "value"); } @Override public LispObject execute(LispObject arg) { return (arg instanceof SymbolMacro) ? T : NIL; } }; // ### %defparameter private static final Primitive _DEFPARAMETER = new pf__defparameter(); private static final class pf__defparameter extends Primitive { pf__defparameter() { super("%defparameter", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { final Symbol symbol; symbol = checkSymbol(first); if (third instanceof AbstractString) symbol.setDocumentation(Symbol.VARIABLE, third); else if (third != NIL) type_error(third, Symbol.STRING); symbol.initializeSpecial(second); return symbol; } }; // ### %defvar private static final Primitive _DEFVAR = new pf__defvar(); private static final class pf__defvar extends Primitive { pf__defvar() { super("%defvar", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject arg) { final Symbol symbol; symbol = checkSymbol(arg); symbol.setSpecial(true); return symbol; } @Override public LispObject execute(LispObject first, LispObject second) { final Symbol symbol; symbol = checkSymbol(first); symbol.initializeSpecial(second); return symbol; } }; // ### %defconstant name initial-value documentation => name private static final Primitive _DEFCONSTANT = new pf__defconstant(); private static final class pf__defconstant extends Primitive { pf__defconstant() { super("%defconstant", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { final Symbol symbol; symbol = checkSymbol(first); if (third != NIL) { if (third instanceof AbstractString) symbol.setDocumentation(Symbol.VARIABLE, third); else return type_error(third, Symbol.STRING); } symbol.initializeConstant(second); return symbol; } }; // ### cond private static final SpecialOperator COND = new sf_cond(); private static final class sf_cond extends SpecialOperator { sf_cond() { super(Symbol.COND, "&rest clauses"); } @Override public LispObject execute(LispObject args, Environment env) { final LispThread thread = LispThread.currentThread(); LispObject result = NIL; while (args != NIL) { LispObject clause = args.car(); if (! (clause instanceof Cons)) return error(new ProgramError("COND clause is not a non-empty list: " + clause.princToString())); result = eval(clause.car(), env, thread); thread._values = null; if (result != NIL) { LispObject body = clause.cdr(); while (body != NIL) { result = eval(body.car(), env, thread); body = ((Cons)body).cdr; } return result; } args = ((Cons)args).cdr; } return result; } }; // ### case private static final SpecialOperator CASE = new sf_case(); private static final class sf_case extends SpecialOperator { sf_case() { super(Symbol.CASE, "keyform &body cases"); } @Override public LispObject execute(LispObject args, Environment env) { final LispThread thread = LispThread.currentThread(); LispObject key = eval(args.car(), env, thread); args = args.cdr(); while (args != NIL) { LispObject clause = args.car(); LispObject keys = clause.car(); boolean match = false; if (keys.listp()) { while (keys != NIL) { LispObject candidate = keys.car(); if (key.eql(candidate)) { match = true; break; } keys = keys.cdr(); } } else { LispObject candidate = keys; if (candidate == T || candidate == Symbol.OTHERWISE) match = true; else if (key.eql(candidate)) match = true; } if (match) { return progn(clause.cdr(), env, thread); } args = args.cdr(); } return NIL; } }; // ### ecase private static final SpecialOperator ECASE = new sf_ecase(); private static final class sf_ecase extends SpecialOperator { sf_ecase() { super(Symbol.ECASE, "keyform &body cases"); } @Override public LispObject execute(LispObject args, Environment env) { final LispThread thread = LispThread.currentThread(); LispObject key = eval(args.car(), env, thread); LispObject clauses = args.cdr(); while (clauses != NIL) { LispObject clause = clauses.car(); LispObject keys = clause.car(); boolean match = false; if (keys.listp()) { while (keys != NIL) { LispObject candidate = keys.car(); if (key.eql(candidate)) { match = true; break; } keys = keys.cdr(); } } else { LispObject candidate = keys; if (key.eql(candidate)) match = true; } if (match) { return progn(clause.cdr(), env, thread); } clauses = clauses.cdr(); } LispObject expectedType = NIL; clauses = args.cdr(); while (clauses != NIL) { LispObject clause = clauses.car(); LispObject keys = clause.car(); if (keys.listp()) { while (keys != NIL) { expectedType = expectedType.push(keys.car()); keys = keys.cdr(); } } else expectedType = expectedType.push(keys); clauses = clauses.cdr(); } expectedType = expectedType.nreverse(); expectedType = expectedType.push(Symbol.MEMBER); return type_error(key, expectedType); } }; // ### upgraded-array-element-type typespec &optional environment // => upgraded-typespec private static final Primitive UPGRADED_ARRAY_ELEMENT_TYPE = new pf_upgraded_array_element_type(); private static final class pf_upgraded_array_element_type extends Primitive { pf_upgraded_array_element_type() { super(Symbol.UPGRADED_ARRAY_ELEMENT_TYPE, "typespec &optional environment"); } @Override public LispObject execute(LispObject arg) { return getUpgradedArrayElementType(arg); } @Override public LispObject execute(LispObject first, LispObject second) { // Ignore environment. return getUpgradedArrayElementType(first); } }; // ### array-rank array => rank private static final Primitive ARRAY_RANK = new pf_array_rank(); private static final class pf_array_rank extends Primitive { pf_array_rank() { super(Symbol.ARRAY_RANK, "array"); } @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(checkArray(arg).getRank()); } }; // ### array-dimensions array => dimensions // Returns a list of integers. Fill pointer (if any) is ignored. private static final Primitive ARRAY_DIMENSIONS = new pf_array_dimensions(); private static final class pf_array_dimensions extends Primitive { pf_array_dimensions() { super(Symbol.ARRAY_DIMENSIONS, "array"); } @Override public LispObject execute(LispObject arg) { return checkArray(arg).getDimensions(); } }; // ### array-dimension array axis-number => dimension private static final Primitive ARRAY_DIMENSION = new pf_array_dimension(); private static final class pf_array_dimension extends Primitive { pf_array_dimension() { super(Symbol.ARRAY_DIMENSION, "array axis-number"); } @Override public LispObject execute(LispObject first, LispObject second) { final AbstractArray array = checkArray(first); return Fixnum.getInstance(array.getDimension(Fixnum.getValue(second))); } }; // ### array-total-size array => size private static final Primitive ARRAY_TOTAL_SIZE = new pf_array_total_size(); private static final class pf_array_total_size extends Primitive { pf_array_total_size() { super(Symbol.ARRAY_TOTAL_SIZE, "array"); } @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(checkArray(arg).getTotalSize()); } }; // ### array-element-type // array-element-type array => typespec private static final Primitive ARRAY_ELEMENT_TYPE = new pf_array_element_type(); private static final class pf_array_element_type extends Primitive { pf_array_element_type() { super(Symbol.ARRAY_ELEMENT_TYPE, "array"); } @Override public LispObject execute(LispObject arg) { return checkArray(arg).getElementType(); } }; // ### adjustable-array-p private static final Primitive ADJUSTABLE_ARRAY_P = new pf_adjustable_array_p(); private static final class pf_adjustable_array_p extends Primitive { pf_adjustable_array_p() { super(Symbol.ADJUSTABLE_ARRAY_P, "array"); } @Override public LispObject execute(LispObject arg) { return checkArray(arg).isAdjustable() ? T : NIL; } }; // ### array-displacement array => displaced-to, displaced-index-offset private static final Primitive ARRAY_DISPLACEMENT = new pf_array_displacement(); private static final class pf_array_displacement extends Primitive { pf_array_displacement() { super(Symbol.ARRAY_DISPLACEMENT, "array"); } @Override public LispObject execute(LispObject arg) { return checkArray(arg).arrayDisplacement(); } }; // ### array-in-bounds-p array &rest subscripts => generalized-boolean private static final Primitive ARRAY_IN_BOUNDS_P = new pf_array_in_bounds_p(); private static final class pf_array_in_bounds_p extends Primitive { pf_array_in_bounds_p() { super(Symbol.ARRAY_IN_BOUNDS_P, "array &rest subscripts"); } @Override public LispObject execute(LispObject[] args) { if (args.length < 1) return error(new WrongNumberOfArgumentsException(this, 1, -1)); final AbstractArray array; LispObject r = args[0]; array = checkArray(r); int rank = array.getRank(); if (rank != args.length - 1) { StringBuilder sb = new StringBuilder("ARRAY-IN-BOUNDS-P: "); sb.append("wrong number of subscripts ("); sb.append(args.length - 1); sb.append(") for array of rank "); sb.append(rank); sb.append("."); program_error(sb.toString()); } for (int i = 0; i < rank; i++) { LispObject arg = args[i+1]; if (arg instanceof Fixnum) { int subscript = ((Fixnum)arg).value; if (subscript < 0 || subscript >= array.getDimension(i)) return NIL; } else if (arg instanceof Bignum) return NIL; else type_error(arg, Symbol.INTEGER); } return T; } }; // ### %array-row-major-index array subscripts => index private static final Primitive _ARRAY_ROW_MAJOR_INDEX = new pf__array_row_major_index(); private static final class pf__array_row_major_index extends Primitive { pf__array_row_major_index() { super("%array-row-major-index", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { final AbstractArray array; array = checkArray(first); LispObject[] subscripts = second.copyToArray(); return number(array.getRowMajorIndex(subscripts)); } }; // ### aref array &rest subscripts => element private static final Primitive AREF = new pf_aref(); private static final class pf_aref extends Primitive { pf_aref() { super(Symbol.AREF, "array &rest subscripts"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { final AbstractArray array; array = checkArray( arg); if (array.getRank() == 0) return array.AREF(0); StringBuilder sb = new StringBuilder("Wrong number of subscripts (0) for array of rank "); sb.append(array.getRank()); sb.append('.'); return program_error(sb.toString()); } @Override public LispObject execute(LispObject first, LispObject second) { return first.AREF(second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return checkArray(first).get(new int[] {Fixnum.getValue(second),Fixnum.getValue(third)} ); } @Override public LispObject execute(LispObject[] args) { final AbstractArray array = checkArray(args[0]); final int[] subs = new int[args.length - 1]; for (int i = subs.length; i-- > 0;) { subs[i] = Fixnum.getValue(args[i+1]); } return array.get(subs); } }; // ### aset array subscripts new-element => new-element private static final Primitive ASET = new pf_aset(); private static final class pf_aset extends Primitive { pf_aset() { super("aset", PACKAGE_SYS, true, "array subscripts new-element"); } @Override public LispObject execute(LispObject first, LispObject second) { // Rank zero array. final ZeroRankArray array; if (first instanceof ZeroRankArray) { array = (ZeroRankArray) first; } else { return error(new TypeError("The value " + first.princToString() + " is not an array of rank 0.")); } array.aset(0, second); return second; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { first.aset(second, third); return third; } @Override public LispObject execute(LispObject[] args) { final AbstractArray array = checkArray(args[0]); final int nsubs = args.length - 2; final int[] subs = new int[nsubs]; for (int i = nsubs; i-- > 0;) subs[i] = Fixnum.getValue(args[i+1]); final LispObject newValue = args[args.length - 1]; array.set(subs, newValue); return newValue; } }; // ### row-major-aref array index => element private static final Primitive ROW_MAJOR_AREF = new pf_row_major_aref(); private static final class pf_row_major_aref extends Primitive { pf_row_major_aref() { super(Symbol.ROW_MAJOR_AREF, "array index"); } @Override public LispObject execute(LispObject first, LispObject second) { return checkArray(first).AREF(Fixnum.getValue(second)); } }; // ### vector private static final Primitive VECTOR = new pf_vector(); private static final class pf_vector extends Primitive { pf_vector() { super(Symbol.VECTOR, "&rest objects"); } @Override public LispObject execute(LispObject[] args) { return new SimpleVector(args); } }; // ### fill-pointer private static final Primitive FILL_POINTER = new pf_fill_pointer(); private static final class pf_fill_pointer extends Primitive { pf_fill_pointer() { super(Symbol.FILL_POINTER, "vector"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof AbstractArray) { AbstractArray aa = (AbstractArray)arg; if (aa.hasFillPointer()) return Fixnum.getInstance(aa.getFillPointer()); } return type_error(arg, list(Symbol.AND, Symbol.VECTOR, list(Symbol.SATISFIES, Symbol.ARRAY_HAS_FILL_POINTER_P))); } }; // ### %set-fill-pointer vector new-fill-pointer private static final Primitive _SET_FILL_POINTER = new pf__set_fill_pointer(); private static final class pf__set_fill_pointer extends Primitive { pf__set_fill_pointer() { super("%set-fill-pointer", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof AbstractVector) { AbstractVector v = (AbstractVector) first; if (v.hasFillPointer()) v.setFillPointer(second); else v.noFillPointer(); return second; } return type_error(first, list(Symbol.AND, Symbol.VECTOR, list(Symbol.SATISFIES, Symbol.ARRAY_HAS_FILL_POINTER_P))); } }; // ### vector-push new-element vector => index-of-new-element private static final Primitive VECTOR_PUSH = new pf_vector_push(); private static final class pf_vector_push extends Primitive { pf_vector_push() { super(Symbol.VECTOR_PUSH, "new-element vector"); } @Override public LispObject execute(LispObject first, LispObject second) { final AbstractVector v = checkVector(second); int fillPointer = v.getFillPointer(); if (fillPointer < 0) v.noFillPointer(); if (fillPointer >= v.capacity()) return NIL; v.aset(fillPointer, first); v.setFillPointer(fillPointer + 1); return Fixnum.getInstance(fillPointer); } }; // ### vector-push-extend new-element vector &optional extension // => index-of-new-element private static final Primitive VECTOR_PUSH_EXTEND = new pf_vector_push_extend(); private static final class pf_vector_push_extend extends Primitive { pf_vector_push_extend() { super(Symbol.VECTOR_PUSH_EXTEND, "new-element vector &optional extension"); } @Override public LispObject execute(LispObject first, LispObject second) { return second.VECTOR_PUSH_EXTEND(first); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return second.VECTOR_PUSH_EXTEND(first, third); } }; // ### vector-pop vector => element private static final Primitive VECTOR_POP = new pf_vector_pop(); private static final class pf_vector_pop extends Primitive { pf_vector_pop() { super(Symbol.VECTOR_POP, "vector"); } @Override public LispObject execute(LispObject arg) { final AbstractVector v = checkVector( arg); int fillPointer = v.getFillPointer(); if (fillPointer < 0) v.noFillPointer(); if (fillPointer == 0) error(new LispError("nothing left to pop")); int newFillPointer = v.checkIndex(fillPointer - 1); LispObject element = v.AREF(newFillPointer); v.setFillPointer(newFillPointer); return element; } }; // ### type-of private static final Primitive TYPE_OF = new pf_type_of(); private static final class pf_type_of extends Primitive { pf_type_of() { super(Symbol.TYPE_OF, "object"); } @Override public LispObject execute(LispObject arg) { return arg.typeOf(); } }; // ### class-of private static final Primitive CLASS_OF = new pf_class_of(); private static final class pf_class_of extends Primitive { pf_class_of() { super(Symbol.CLASS_OF, "object"); } @Override public LispObject execute(LispObject arg) { return arg.classOf(); } }; // ### simple-typep private static final Primitive SIMPLE_TYPEP = new pf_simple_typep(); private static final class pf_simple_typep extends Primitive { pf_simple_typep() { super("simple-typep", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { return first.typep(second); } }; // ### function-lambda-expression function => // lambda-expression, closure-p, name private static final Primitive FUNCTION_LAMBDA_EXPRESSION = new pf_function_lambda_expression(); private static final class pf_function_lambda_expression extends Primitive { pf_function_lambda_expression() { super(Symbol.FUNCTION_LAMBDA_EXPRESSION, "function"); } @Override public LispObject execute(LispObject arg) { final LispObject value1, value2, value3; if (arg instanceof CompiledClosure) { value1 = NIL; value2 = T; LispObject name = ((CompiledClosure)arg).getLambdaName(); value3 = name != null ? name : NIL; } else if (arg instanceof Closure) { Closure closure = (Closure) arg; LispObject expr = closure.getBody(); expr = new Cons(closure.getLambdaList(), expr); expr = new Cons(Symbol.LAMBDA, expr); value1 = expr; Environment env = closure.getEnvironment(); if (env == null || env.isEmpty()) value2 = NIL; else value2 = env; // Return environment as closure-p. LispObject name = ((Closure)arg).getLambdaName(); value3 = name != null ? name : NIL; } else if (arg instanceof Function) { value1 = NIL; value2 = T; value3 = ((Function)arg).getLambdaName(); } else if (arg.typep(Symbol.GENERIC_FUNCTION) != NIL) { value1 = NIL; value2 = T; value3 = Symbol.GENERIC_FUNCTION_NAME.execute(arg); } else if (arg instanceof FuncallableStandardObject) { return this.execute(((FuncallableStandardObject)arg).function); } else { return type_error(arg, Symbol.FUNCTION); } return LispThread.currentThread().setValues(value1, value2, value3); } }; // ### funcall // This needs to be public for LispAPI.java. public static final Primitive FUNCALL = new pf_funcall(); private static final class pf_funcall extends Primitive { pf_funcall() { super(Symbol.FUNCALL, "function &rest args"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return LispThread.currentThread().execute(arg); } @Override public LispObject execute(LispObject first, LispObject second) { return LispThread.currentThread().execute(first, second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return LispThread.currentThread().execute(first, second, third); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return LispThread.currentThread().execute(first, second, third, fourth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { return LispThread.currentThread().execute(first, second, third, fourth, fifth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { return LispThread.currentThread().execute(first, second, third, fourth, fifth, sixth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { return LispThread.currentThread().execute(first, second, third, fourth, fifth, sixth, seventh); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eigth) { return LispThread.currentThread().execute(first, second, third, fourth, fifth, sixth, seventh, eigth); } @Override public LispObject execute(LispObject[] args) { final int length = args.length - 1; // Number of arguments. if (length == 8) { return LispThread.currentThread().execute(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); } else { LispObject[] newArgs = new LispObject[length]; System.arraycopy(args, 1, newArgs, 0, length); return LispThread.currentThread().execute(args[0], newArgs); } } }; // ### apply public static final Primitive APPLY = new pf_apply(); private static final class pf_apply extends Primitive { pf_apply() { super(Symbol.APPLY, "function &rest args"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 2, -1)); } @Override public LispObject execute(LispObject arg) { return error(new WrongNumberOfArgumentsException(this, 2, -1)); } @Override public LispObject execute(LispObject fun, LispObject args) { final LispThread thread = LispThread.currentThread(); final int length = args.length(); switch (length) { case 0: return thread.execute(fun); case 1: return thread.execute(fun, ((Cons)args).car); case 2: { Cons cons = (Cons) args; return thread.execute(fun, cons.car, ((Cons)cons.cdr).car); } case 3: return thread.execute(fun, args.car(), args.cadr(), args.cdr().cdr().car()); default: { final LispObject[] funArgs = new LispObject[length]; int j = 0; while (args != NIL) { funArgs[j++] = args.car(); args = args.cdr(); } return funcall(fun, funArgs, thread); } } } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (third.listp()) { final int numFunArgs = 1 + third.length(); final LispObject[] funArgs = new LispObject[numFunArgs]; funArgs[0] = second; int j = 1; while (third != NIL) { funArgs[j++] = third.car(); third = third.cdr(); } return funcall(first, funArgs, LispThread.currentThread()); } return type_error(third, Symbol.LIST); } @Override public LispObject execute(final LispObject[] args) { final int numArgs = args.length; LispObject spread = args[numArgs - 1]; if (spread.listp()) { final int numFunArgs = numArgs - 2 + spread.length(); final LispObject[] funArgs = new LispObject[numFunArgs]; int j = 0; for (int i = 1; i < numArgs - 1; i++) funArgs[j++] = args[i]; while (spread != NIL) { funArgs[j++] = spread.car(); spread = spread.cdr(); } return funcall(args[0], funArgs, LispThread.currentThread()); } return type_error(spread, Symbol.LIST); } }; // ### mapcar private static final Primitive MAPCAR = new pf_mapcar(); private static final class pf_mapcar extends Primitive { pf_mapcar() { super(Symbol.MAPCAR, "function &rest lists"); } @Override public LispObject execute(LispObject fun, LispObject list) { final LispThread thread = LispThread.currentThread(); LispObject result = NIL; Cons splice = null; while (list != NIL) { Cons cons; if (list instanceof Cons) cons = (Cons) list; else return type_error(list, Symbol.LIST); LispObject obj = thread.execute(fun, cons.car); if (splice == null) { splice = new Cons(obj, result); result = splice; } else { Cons c = new Cons(obj); splice.cdr = c; splice = c; } list = cons.cdr; } thread._values = null; return result; } @Override public LispObject execute(LispObject fun, LispObject list1, LispObject list2) { final LispThread thread = LispThread.currentThread(); LispObject result = NIL; Cons splice = null; while (list1 != NIL && list2 != NIL) { LispObject obj = thread.execute(fun, list1.car(), list2.car()); if (splice == null) { splice = new Cons(obj, result); result = splice; } else { Cons cons = new Cons(obj); splice.cdr = cons; splice = cons; } list1 = list1.cdr(); list2 = list2.cdr(); } thread._values = null; return result; } @Override public LispObject execute(final LispObject[] args) { final int numArgs = args.length; if (numArgs < 2) return error(new WrongNumberOfArgumentsException(this, 2, -1)); int commonLength = -1; for (int i = 1; i < numArgs; i++) { if (!args[i].listp()) type_error(args[i], Symbol.LIST); int len = args[i].length(); if (commonLength < 0) commonLength = len; else if (commonLength > len) commonLength = len; } final LispThread thread = LispThread.currentThread(); LispObject[] results = new LispObject[commonLength]; final int numFunArgs = numArgs - 1; final LispObject[] funArgs = new LispObject[numFunArgs]; for (int i = 0; i < commonLength; i++) { for (int j = 0; j < numFunArgs; j++) funArgs[j] = args[j+1].car(); results[i] = funcall(args[0], funArgs, thread); for (int j = 1; j < numArgs; j++) args[j] = args[j].cdr(); } thread._values = null; LispObject result = NIL; for (int i = commonLength; i-- > 0;) result = new Cons(results[i], result); return result; } }; // ### mapc private static final Primitive MAPC = new pf_mapc(); private static final class pf_mapc extends Primitive { pf_mapc() { super(Symbol.MAPC, "function &rest lists"); } @Override public LispObject execute(LispObject fun, LispObject list) { final LispThread thread = LispThread.currentThread(); LispObject result = list; while (list != NIL) { Cons cons; if (list instanceof Cons) cons = (Cons) list; else return type_error(list, Symbol.LIST); thread.execute(fun, cons.car); list = cons.cdr; } thread._values = null; return result; } @Override public LispObject execute(LispObject fun, LispObject list1, LispObject list2) { final LispThread thread = LispThread.currentThread(); LispObject result = list1; while (list1 != NIL && list2 != NIL) { thread.execute(fun, list1.car(), list2.car()); list1 = ((Cons)list1).cdr; list2 = ((Cons)list2).cdr; } thread._values = null; return result; } @Override public LispObject execute(final LispObject[] args) { final int numArgs = args.length; if (numArgs < 2) return error(new WrongNumberOfArgumentsException(this, 2, -1)); int commonLength = -1; for (int i = 1; i < numArgs; i++) { if (!args[i].listp()) type_error(args[i], Symbol.LIST); int len = args[i].length(); if (commonLength < 0) commonLength = len; else if (commonLength > len) commonLength = len; } final LispThread thread = LispThread.currentThread(); LispObject result = args[1]; final int numFunArgs = numArgs - 1; final LispObject[] funArgs = new LispObject[numFunArgs]; for (int i = 0; i < commonLength; i++) { for (int j = 0; j < numFunArgs; j++) funArgs[j] = args[j+1].car(); funcall(args[0], funArgs, thread); for (int j = 1; j < numArgs; j++) args[j] = args[j].cdr(); } thread._values = null; return result; } }; // ### macroexpand private static final Primitive MACROEXPAND = new pf_macroexpand(); private static final class pf_macroexpand extends Primitive { pf_macroexpand() { super(Symbol.MACROEXPAND, "form &optional env"); } @Override public LispObject execute(LispObject form) { return macroexpand(form, new Environment(), LispThread.currentThread()); } @Override public LispObject execute(LispObject form, LispObject env) { return macroexpand(form, env != NIL ? checkEnvironment(env) : new Environment(), LispThread.currentThread()); } }; // ### macroexpand-1 private static final Primitive MACROEXPAND_1 = new pf_macroexpand_1(); private static final class pf_macroexpand_1 extends Primitive { pf_macroexpand_1() { super(Symbol.MACROEXPAND_1, "form &optional env"); } @Override public LispObject execute(LispObject form) { return macroexpand_1(form, new Environment(), LispThread.currentThread()); } @Override public LispObject execute(LispObject form, LispObject env) { return macroexpand_1(form, env != NIL ? checkEnvironment(env) : new Environment(), LispThread.currentThread()); } }; // ### gensym public static final Primitive GENSYM = new pf_gensym(); private static final class pf_gensym extends Primitive { pf_gensym() { super(Symbol.GENSYM, "&optional x"); } @Override public LispObject execute() { return gensym("G", LispThread.currentThread()); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Fixnum) { int n = ((Fixnum)arg).value; if (n >= 0) { StringBuilder sb = new StringBuilder("G"); sb.append(n); // Decimal representation. return new Symbol(new SimpleString(sb)); } } else if (arg instanceof Bignum) { BigInteger n = ((Bignum)arg).value; if (n.signum() >= 0) { StringBuilder sb = new StringBuilder("G"); sb.append(n.toString()); // Decimal representation. return new Symbol(new SimpleString(sb)); } } else if (arg instanceof AbstractString) return gensym(arg.getStringValue(), LispThread.currentThread()); return type_error(arg, list(Symbol.OR, Symbol.STRING, Symbol.UNSIGNED_BYTE)); } }; // ### string private static final Primitive STRING = new pf_string(); private static final class pf_string extends Primitive { pf_string() { super(Symbol.STRING, "x"); } @Override public LispObject execute(LispObject arg) { return arg.STRING(); } }; // ### intern string &optional package => symbol, status // STATUS is one of :INHERITED, :EXTERNAL, :INTERNAL or NIL. // "It is implementation-dependent whether the string that becomes the new // symbol's name is the given string or a copy of it." private static final Primitive INTERN = new pf_intern(); private static final class pf_intern extends Primitive { pf_intern() { super(Symbol.INTERN, "string &optional package"); } @Override public LispObject execute(LispObject arg) { final SimpleString s; if (arg instanceof SimpleString) s = (SimpleString) arg; else s = new SimpleString(arg.getStringValue()); final LispThread thread = LispThread.currentThread(); Package pkg = (Package) Symbol._PACKAGE_.symbolValue(thread); return pkg.intern(s, thread); } @Override public LispObject execute(LispObject first, LispObject second) { final SimpleString s; if (first instanceof SimpleString) s = (SimpleString) first; else s = new SimpleString(first.getStringValue()); Package pkg = coerceToPackage(second); return pkg.intern(s, LispThread.currentThread()); } }; // ### unintern // unintern symbol &optional package => generalized-boolean private static final Primitive UNINTERN = new pf_unintern(); private static final class pf_unintern extends Primitive { pf_unintern() { super(Symbol.UNINTERN, "symbol &optional package"); } @Override public LispObject execute(LispObject[] args) { if (args.length == 0 || args.length > 2) return error(new WrongNumberOfArgumentsException(this, 1, 2)); Symbol symbol = checkSymbol(args[0]); Package pkg; if (args.length == 2) pkg = coerceToPackage(args[1]); else pkg = getCurrentPackage(); return pkg.unintern(symbol); } }; // ### find-package private static final Primitive FIND_PACKAGE = new pf_find_package(); private static final class pf_find_package extends Primitive { pf_find_package() { super(Symbol.FIND_PACKAGE, "name"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Package) return arg; if (arg instanceof AbstractString) { Package pkg = getCurrentPackage().findPackage(arg.getStringValue()); return pkg != null ? pkg : NIL; } if (arg instanceof Symbol) { Package pkg = getCurrentPackage().findPackage(checkSymbol(arg).getName()); return pkg != null ? pkg : NIL; } if (arg instanceof LispCharacter) { String packageName = String.valueOf(new char[] {((LispCharacter)arg).getValue()}); Package pkg = getCurrentPackage().findPackage(packageName); return pkg != null ? pkg : NIL; } return NIL; } }; // ### %make-package // %make-package package-name nicknames use => package private static final Primitive _MAKE_PACKAGE = new pf__make_package(); private static final class pf__make_package extends Primitive { pf__make_package() { super("%make-package", PACKAGE_SYS, false); } /** * This invocation is solely used to be able to create * a package to bind to *FASL-ANONYMOUS-PACKAGE* */ @Override public LispObject execute() { return new Package(); } /** * This invocation is used by MAKE-PACKAGE to create a package */ @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { String packageName = javaString(first); Package currentpkg = getCurrentPackage(); Package pkg = currentpkg.findPackage(packageName); if (pkg != null) error(new LispError("Package " + packageName + " already exists.")); LispObject nicknames = checkList(second); if (nicknames != NIL) { LispObject list = nicknames; while (list != NIL) { LispObject lispNick = list.car(); String nick = javaString(lispNick); if (currentpkg.findPackage(nick) != null) { error(new PackageError("A package named " + nick + " already exists.", lispNick)); } list = list.cdr(); } } LispObject use = checkList(third); if (use != NIL) { LispObject list = use; while (list != NIL) { LispObject obj = list.car(); if (obj instanceof Package) { // OK. } else { String s = javaString(obj); Package p = currentpkg.findPackage(s); if (p == null) { error(new LispError(obj.princToString() + " is not the name of a package.")); return NIL; } } list = list.cdr(); } } // Now create the package. pkg = Packages.createPackage(packageName); // Add the nicknames. while (nicknames != NIL) { String nick = javaString(nicknames.car()); pkg.addNickname(nick); nicknames = nicknames.cdr(); } // Create the use list. while (use != NIL) { LispObject obj = use.car(); if (obj instanceof Package) pkg.usePackage((Package)obj); else { String s = javaString(obj); Package p = currentpkg.findPackage(s); if (p == null) { error(new LispError(obj.princToString() + " is not the name of a package.")); return NIL; } pkg.usePackage(p); } use = use.cdr(); } return pkg; } }; // ### %in-package private static final Primitive _IN_PACKAGE = new pf__in_package(); private static final class pf__in_package extends Primitive { pf__in_package() { super("%in-package", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { final String packageName = javaString(arg); final Package pkg = getCurrentPackage().findPackage(packageName); if (pkg == null) return error(new PackageError("The name " + packageName + " does not designate any package.", arg)); SpecialBinding binding = LispThread.currentThread().getSpecialBinding(Symbol._PACKAGE_); if (binding != null) binding.value = pkg; else // No dynamic binding. Symbol._PACKAGE_.setSymbolValue(pkg); return pkg; } }; // ### use-package packages-to-use &optional package => t private static final Primitive USE_PACKAGE = new pf_use_package(); private static final class pf_use_package extends Primitive { pf_use_package() { super(Symbol.USE_PACKAGE, "packages-to-use &optional package"); } @Override public LispObject execute(LispObject[] args) { if (args.length < 1 || args.length > 2) return error(new WrongNumberOfArgumentsException(this, 1, 2)); Package pkg; if (args.length == 2) pkg = coerceToPackage(args[1]); else pkg = getCurrentPackage(); if (args[0].listp()) { LispObject list = args[0]; while (list != NIL) { pkg.usePackage(coerceToPackage(list.car())); list = list.cdr(); } } else pkg.usePackage(coerceToPackage(args[0])); return T; } }; // ### package-symbols private static final Primitive PACKAGE_SYMBOLS = new pf_package_symbols(); private static final class pf_package_symbols extends Primitive { pf_package_symbols() { super("package-symbols", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).getSymbols(); } }; // ### package-internal-symbols private static final Primitive PACKAGE_INTERNAL_SYMBOLS = new pf_package_internal_symbols(); private static final class pf_package_internal_symbols extends Primitive { pf_package_internal_symbols() { super("package-internal-symbols", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).PACKAGE_INTERNAL_SYMBOLS(); } }; // ### package-external-symbols private static final Primitive PACKAGE_EXTERNAL_SYMBOLS = new pf_package_external_symbols(); private static final class pf_package_external_symbols extends Primitive { pf_package_external_symbols() { super("package-external-symbols", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).PACKAGE_EXTERNAL_SYMBOLS(); } }; // ### package-inherited-symbols private static final Primitive PACKAGE_INHERITED_SYMBOLS = new pf_package_inherited_symbols(); private static final class pf_package_inherited_symbols extends Primitive { pf_package_inherited_symbols() { super("package-inherited-symbols", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return coerceToPackage(arg).PACKAGE_INHERITED_SYMBOLS(); } }; // ### export symbols &optional package private static final Primitive EXPORT = new pf_export(); private static final class pf_export extends Primitive { pf_export() { super(Symbol.EXPORT, "symbols &optional package"); } @Override public LispObject execute(LispObject arg) { final Package pkg = (Package) Symbol._PACKAGE_.symbolValue(); if (arg instanceof Cons) { for (LispObject list = arg; list != NIL; list = list.cdr()) pkg.export(checkSymbol(list.car())); } else pkg.export(checkSymbol(arg)); return T; } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Cons) { Package pkg = coerceToPackage(second); for (LispObject list = first; list != NIL; list = list.cdr()) pkg.export(checkSymbol(list.car())); } else coerceToPackage(second).export(checkSymbol(first)); return T; } }; // ### find-symbol string &optional package => symbol, status private static final Primitive FIND_SYMBOL = new pf_find_symbol(); private static final class pf_find_symbol extends Primitive { pf_find_symbol() { super(Symbol.FIND_SYMBOL, "string &optional package"); } @Override public LispObject execute(LispObject arg) { return getCurrentPackage() .findSymbol(checkString(arg).getStringValue()); } @Override public LispObject execute(LispObject first, LispObject second) { return coerceToPackage(second) .findSymbol(checkString(first).getStringValue()); } }; // ### fset name function &optional source-position arglist documentation // => function private static final Primitive FSET = new pf_fset(); private static final class pf_fset extends Primitive { pf_fset() { super("fset", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { return execute(first, second, NIL, NIL, NIL); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return execute(first, second, third, NIL, NIL); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return execute(first, second, third, fourth, NIL); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { if (first instanceof Symbol) { checkRedefinition(first); Symbol symbol = checkSymbol(first); symbol.setSymbolFunction(second); final LispThread thread = LispThread.currentThread(); LispObject sourcePathname = _SOURCE_.symbolValue(thread); LispObject sourcePosition = third; if (sourcePathname != NIL) sourcePosition = _SOURCE_POSITION_.symbolValue(thread); if (sourcePathname == NIL) sourcePathname = Keyword.TOP_LEVEL; if (sourcePathname != Keyword.TOP_LEVEL) put(symbol, Symbol._SOURCE, new Cons(sourcePathname, third)); else put(symbol, Symbol._SOURCE, sourcePathname); } else if (isValidSetfFunctionName(first)) { // SETF function checkRedefinition(first); Symbol symbol = checkSymbol(first.cadr()); put(symbol, Symbol.SETF_FUNCTION, second); } else return type_error(first, FUNCTION_NAME); if (second instanceof Operator) { Operator op = (Operator) second; op.setLambdaName(first); if (fourth != NIL) op.setLambdaList(fourth); if (fifth != NIL) op.setDocumentation(Symbol.FUNCTION, fifth); } return second; } }; // ### %set-symbol-plist private static final Primitive _SET_SYMBOL_PLIST = new pf__set_symbol_plist(); private static final class pf__set_symbol_plist extends Primitive { pf__set_symbol_plist() { super("%set-symbol-plist", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { checkSymbol(first).setPropertyList(checkList(second)); return second; } }; // ### getf plist indicator &optional default => value private static final Primitive GETF = new pf_getf(); private static final class pf_getf extends Primitive { pf_getf() { super(Symbol.GETF, "plist indicator &optional default"); } @Override public LispObject execute(LispObject plist, LispObject indicator) { return getf(plist, indicator, NIL); } @Override public LispObject execute(LispObject plist, LispObject indicator, LispObject defaultValue) { return getf(plist, indicator, defaultValue); } }; // ### get symbol indicator &optional default => value private static final Primitive GET = new pf_get(); private static final class pf_get extends Primitive { pf_get() { super(Symbol.GET, "symbol indicator &optional default"); } @Override public LispObject execute(LispObject symbol, LispObject indicator) { return get(symbol, indicator, NIL); } @Override public LispObject execute(LispObject symbol, LispObject indicator, LispObject defaultValue) { return get(symbol, indicator, defaultValue); } }; // ### put symbol indicator value => value public static final Primitive PUT = new pf_put(); private static final class pf_put extends Primitive { pf_put() { super("put", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject symbol, LispObject indicator, LispObject value) { return put(checkSymbol(symbol), indicator, value); } @Override public LispObject execute(LispObject symbol, LispObject indicator, LispObject defaultValue, LispObject value) { return put(checkSymbol(symbol), indicator, value); } }; // ### macrolet private static final SpecialOperator MACROLET = new sf_macrolet(); private static final class sf_macrolet extends SpecialOperator { sf_macrolet() { super(Symbol.MACROLET, "definitions &rest body"); } @Override public LispObject execute(LispObject args, Environment env) { LispObject defs = checkList(args.car()); final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); Environment ext = new Environment(env); thread.envStack.push(ext); try { while (defs != NIL) { LispObject def = checkList(defs.car()); Symbol symbol = checkSymbol(def.car()); Symbol make_expander_for_macrolet = PACKAGE_SYS.intern("MAKE-MACRO-EXPANDER"); LispObject expander = make_expander_for_macrolet.execute(def); Closure expansionFunction = new Closure(expander, env); MacroObject macroObject = new MacroObject(symbol, expansionFunction); ext.addFunctionBinding(symbol, macroObject); defs = defs.cdr(); } return progn(ext.processDeclarations(args.cdr()), ext, thread); } finally { thread.resetSpecialBindings(mark); while (thread.envStack.pop() != ext) {}; } } }; private static final Primitive MAKE_MACRO_EXPANDER = new pf_make_macro_expander(); private static final class pf_make_macro_expander extends Primitive { pf_make_macro_expander() { super("make-macro-expander", PACKAGE_SYS, true, "definition"); } @Override public LispObject execute(LispObject definition) { /* Create an expansion function * `(lambda (,formArg ,envArg) * (apply (function (macro-function ,lambdaList * (block ,symbol ,@body))) * (cdr ,formArg))) */ Symbol symbol = checkSymbol(definition.car()); LispObject lambdaList = definition.cadr(); LispObject body = definition.cddr(); LispObject block = new Cons(Symbol.BLOCK, new Cons(symbol, body)); LispObject toBeApplied = list(Symbol.FUNCTION, list(Symbol.MACRO_FUNCTION, lambdaList, block)); final LispThread thread = LispThread.currentThread(); LispObject formArg = gensym("WHOLE-", thread); LispObject envArg = gensym("ENVIRONMENT-", thread); // Ignored. LispObject expander = list(Symbol.LAMBDA, list(formArg, envArg), list(Symbol.APPLY, toBeApplied, list(Symbol.CDR, formArg))); return expander; } }; // ### tagbody private static final SpecialOperator TAGBODY = new sf_tagbody(); private static final class sf_tagbody extends SpecialOperator { sf_tagbody() { super(Symbol.TAGBODY, "&rest statements"); } @Override public LispObject execute(LispObject args, Environment env) { Environment ext = new Environment(env); LispThread thread = LispThread.currentThread(); try { thread.envStack.push(ext); return processTagBody(args, preprocessTagBody(args, ext), ext); } finally { ext.inactive = true; while (thread.envStack.pop() != ext) {}; } } }; // ### go private static final SpecialOperator GO = new sf_go(); private static final class sf_go extends SpecialOperator { sf_go() { super(Symbol.GO, "tag"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() != 1) return error(new WrongNumberOfArgumentsException(this, 1)); Binding binding = env.getTagBinding(args.car()); if (binding == null) return error(new ControlError("No tag named " + args.car().princToString() + " is currently visible.")); return nonLocalGo(binding, args.car()); } }; // ### block private static class BlockMarker extends LispObject implements Serializable {} private static final SpecialOperator BLOCK = new sf_block(); private static final class sf_block extends SpecialOperator { sf_block() { super(Symbol.BLOCK, "name &rest forms"); } @Override public LispObject execute(LispObject args, Environment env) { if (args == NIL) return error(new WrongNumberOfArgumentsException(this, 1, -1)); LispObject tag; tag = checkSymbol(args.car()); LispObject body = ((Cons)args).cdr(); Environment ext = new Environment(env); final LispObject block = new BlockMarker(); ext.addBlock(tag, block); LispObject result = NIL; final LispThread thread = LispThread.currentThread(); try { thread.envStack.push(ext); return progn(body, ext, thread); } catch (Return ret) { if (ret.getBlock() == block) { return ret.getResult(); } throw ret; } finally { while (thread.envStack.pop() != ext) {}; ext.inactive = true; } } }; // ### return-from private static final SpecialOperator RETURN_FROM = new sf_return_from(); private static final class sf_return_from extends SpecialOperator { sf_return_from() { super(Symbol.RETURN_FROM, "name &optional value"); } @Override public LispObject execute(LispObject args, Environment env) { final int length = args.length(); if (length < 1 || length > 2) return error(new WrongNumberOfArgumentsException(this, 1, 2)); Symbol symbol; symbol = checkSymbol(args.car()); return nonLocalReturn(env.getBlockBinding(symbol), symbol, (length == 2) ? eval(args.cadr(), env, LispThread.currentThread()) : NIL); } }; // ### catch private static final SpecialOperator CATCH = new sf_catch(); private static final class sf_catch extends SpecialOperator { sf_catch() { super(Symbol.CATCH, "tag &body body"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() < 1) return error(new WrongNumberOfArgumentsException(this, 1, -1)); final LispThread thread = LispThread.currentThread(); LispObject tag = eval(args.car(), env, thread); thread.pushCatchTag(tag); LispObject body = args.cdr(); LispObject result = NIL; Environment ext = new Environment(env,Keyword.CATCH,tag); try { thread.envStack.push(ext); return progn(body, env, thread); } catch (Throw t) { if (t.tag == tag) { return t.getResult(thread); } throw t; } catch (Return ret) { throw ret; } finally { while (thread.envStack.pop() != ext) {}; thread.popCatchTag(); } } }; // ### throw private static final SpecialOperator THROW = new sf_throw(); private static final class sf_throw extends SpecialOperator { sf_throw() { super(Symbol.THROW, "tag result"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() != 2) return error(new WrongNumberOfArgumentsException(this, 2)); final LispThread thread = LispThread.currentThread(); thread.throwToTag(eval(args.car(), env, thread), eval(args.cadr(), env, thread)); // Not reached. return NIL; } }; // ### unwind-protect private static final SpecialOperator UNWIND_PROTECT = new sf_unwind_protect(); private static final class sf_unwind_protect extends SpecialOperator { sf_unwind_protect() { super(Symbol.UNWIND_PROTECT, "protected &body cleanup"); } @Override public LispObject execute(LispObject args, Environment env) { final LispThread thread = LispThread.currentThread(); LispObject result; LispObject[] values; try { result = eval(args.car(), env, thread); } finally { values = thread._values; LispObject body = args.cdr(); while (body != NIL) { eval(body.car(), env, thread); body = ((Cons)body).cdr; } thread._values = values; } if (values != null) thread.setValues(values); else thread._values = null; return result; } }; // ### eval-when private static final SpecialOperator EVAL_WHEN = new sf_eval_when(); private static final class sf_eval_when extends SpecialOperator { sf_eval_when() { super(Symbol.EVAL_WHEN, "situations &rest forms"); } @Override public LispObject execute(LispObject args, Environment env) { LispObject situations = args.car(); if (situations != NIL) { if (memq(Keyword.EXECUTE, situations) || memq(Symbol.EVAL, situations)) { return progn(args.cdr(), env, LispThread.currentThread()); } } return NIL; } }; // ### multiple-value-bind // multiple-value-bind (var*) values-form declaration* form* // Should be a macro. private static final SpecialOperator MULTIPLE_VALUE_BIND = new sf_multiple_value_bind(); private static final class sf_multiple_value_bind extends SpecialOperator { sf_multiple_value_bind() { super(Symbol.MULTIPLE_VALUE_BIND, "vars value-form &body body"); } @Override public LispObject execute(LispObject args, Environment env) { LispObject vars = args.car(); args = args.cdr(); LispObject valuesForm = args.car(); LispObject body = args.cdr(); final LispThread thread = LispThread.currentThread(); LispObject value = eval(valuesForm, env, thread); LispObject[] values = thread._values; if (values == null) { // eval() did not return multiple values. values = new LispObject[1]; values[0] = value; } // Process declarations. LispObject bodyAndDecls = parseBody(body, false); LispObject specials = parseSpecials(bodyAndDecls.NTH(1)); body = bodyAndDecls.car(); final SpecialBindingsMark mark = thread.markSpecialBindings(); final Environment ext = new Environment(env); int i = 0; LispObject var = vars.car(); while (var != NIL) { final Symbol sym; sym = checkSymbol(var); LispObject val = i < values.length ? values[i] : NIL; if (specials != NIL && memq(sym, specials)) { thread.bindSpecial(sym, val); ext.declareSpecial(sym); } else if (sym.isSpecialVariable()) { thread.bindSpecial(sym, val); } else ext.bind(sym, val); vars = vars.cdr(); var = vars.car(); ++i; } // Make sure free special declarations are visible in the body. // "The scope of free declarations specifically does not include // initialization forms for bindings established by the form // containing the declarations." (3.3.4) while (specials != NIL) { Symbol symbol = (Symbol) specials.car(); ext.declareSpecial(symbol); specials = ((Cons)specials).cdr; } thread._values = null; LispObject result = NIL; try { thread.envStack.push(ext); result = progn(body, ext, thread); } finally { thread.resetSpecialBindings(mark); while (thread.envStack.pop() != ext) {}; } return result; } }; // ### multiple-value-prog1 private static final SpecialOperator MULTIPLE_VALUE_PROG1 = new sf_multiple_value_prog1(); private static final class sf_multiple_value_prog1 extends SpecialOperator { sf_multiple_value_prog1() { super(Symbol.MULTIPLE_VALUE_PROG1, "values-form &rest forms"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() == 0) return error(new WrongNumberOfArgumentsException(this, 1, -1)); final LispThread thread = LispThread.currentThread(); LispObject result = eval(args.car(), env, thread); LispObject[] values = thread._values; while ((args = args.cdr()) != NIL) eval(args.car(), env, thread); if (values != null) thread.setValues(values); else thread._values = null; return result; } }; // ### multiple-value-call private static final SpecialOperator MULTIPLE_VALUE_CALL = new sf_multiple_value_call(); private static final class sf_multiple_value_call extends SpecialOperator { sf_multiple_value_call() { super(Symbol.MULTIPLE_VALUE_CALL, "fun &rest args"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() == 0) return error(new WrongNumberOfArgumentsException(this, 1, -1)); final LispThread thread = LispThread.currentThread(); LispObject function; LispObject obj = eval(args.car(), env, thread); args = args.cdr(); if (obj instanceof Symbol) { function = obj.getSymbolFunction(); if (function == null) error(new UndefinedFunction(obj)); } else if (obj instanceof Function) { function = obj; } else { error(new LispError(obj.princToString() + " is not a function name.")); return NIL; } ArrayList arrayList = new ArrayList(); while (args != NIL) { LispObject form = args.car(); LispObject result = eval(form, env, thread); LispObject[] values = thread._values; if (values != null) { for (int i = 0; i < values.length; i++) arrayList.add(values[i]); } else arrayList.add(result); args = ((Cons)args).cdr; } LispObject[] argv = new LispObject[arrayList.size()]; arrayList.toArray(argv); return funcall(function, argv, thread); } }; // ### and // Should be a macro. private static final SpecialOperator AND = new sf_and(); private static final class sf_and extends SpecialOperator { sf_and() { super(Symbol.AND, "&rest forms"); } @Override public LispObject execute(LispObject args, Environment env) { final LispThread thread = LispThread.currentThread(); LispObject result = T; while (args != NIL) { result = eval(args.car(), env, thread); if (result == NIL) { if (((Cons)args).cdr != NIL) { // Not the last form. thread._values = null; } break; } args = ((Cons)args).cdr; } return result; } }; // ### or // Should be a macro. private static final SpecialOperator OR = new sf_or(); private static final class sf_or extends SpecialOperator { sf_or() { super(Symbol.OR, "&rest forms"); } @Override public LispObject execute(LispObject args, Environment env) { final LispThread thread = LispThread.currentThread(); LispObject result = NIL; while (args != NIL) { result = eval(args.car(), env, thread); if (result != NIL) { if (((Cons)args).cdr != NIL) { // Not the last form. thread._values = null; } break; } args = ((Cons)args).cdr; } return result; } }; // ### multiple-value-list form => list // Evaluates form and creates a list of the multiple values it returns. // Should be a macro. private static final SpecialOperator MULTIPLE_VALUE_LIST = new sf_multiple_value_list(); private static final class sf_multiple_value_list extends SpecialOperator { sf_multiple_value_list() { super(Symbol.MULTIPLE_VALUE_LIST, "value-form"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() != 1) return error(new WrongNumberOfArgumentsException(this, 1)); final LispThread thread = LispThread.currentThread(); LispObject result = eval(((Cons)args).car, env, thread); LispObject[] values = thread._values; if (values == null) return new Cons(result); thread._values = null; LispObject list = NIL; for (int i = values.length; i-- > 0;) list = new Cons(values[i], list); return list; } }; // ### nth-value n form => object // Evaluates n and then form and returns the nth value returned by form, or // NIL if n >= number of values returned. // Should be a macro. private static final SpecialOperator NTH_VALUE = new sf_nth_value(); private static final class sf_nth_value extends SpecialOperator { sf_nth_value() { super(Symbol.NTH_VALUE, "n form"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() != 2) return error(new WrongNumberOfArgumentsException(this, 2)); final LispThread thread = LispThread.currentThread(); int n = Fixnum.getValue(eval(args.car(), env, thread)); if (n < 0) n = 0; LispObject result = eval(args.cadr(), env, thread); LispObject[] values = thread._values; thread._values = null; if (values == null) { // A single value was returned. return n == 0 ? result : NIL; } if (n < values.length) return values[n]; return NIL; } }; // ### call-count private static final Primitive CALL_COUNT = new pf_call_count(); private static final class pf_call_count extends Primitive { pf_call_count() { super("call-count", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(arg.getCallCount()); } }; // ### set-call-count private static final Primitive SET_CALL_COUNT = new pf_set_call_count(); private static final class pf_set_call_count extends Primitive { pf_set_call_count() { super("set-call-count", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { first.setCallCount(Fixnum.getValue(second)); return second; } }; // ### hot-count private static final Primitive HOT_COUNT = new pf_hot_count(); private static final class pf_hot_count extends Primitive { pf_hot_count() { super("hot-count", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(arg.getHotCount()); } }; // ### set-hot-count private static final Primitive SET_HOT_COUNT = new pf_set_hot_count(); private static final class pf_set_hot_count extends Primitive { pf_set_hot_count() { super("set-hot-count", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { first.setHotCount(Fixnum.getValue(second)); return second; } }; // ### lambda-name private static final Primitive LAMBDA_NAME = new pf_lambda_name(); private static final class pf_lambda_name extends Primitive { pf_lambda_name() { super("lambda-name", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Operator) { return ((Operator)arg).getLambdaName(); } if (arg.typep(Symbol.GENERIC_FUNCTION) != NIL) { return Symbol.GENERIC_FUNCTION_NAME.execute(arg); } if (arg instanceof FuncallableStandardObject) { return this.execute(((FuncallableStandardObject)arg).function); } return type_error(arg, Symbol.FUNCTION); } }; // ### %set-lambda-name private static final Primitive _SET_LAMBDA_NAME = new pf__set_lambda_name(); private static final class pf__set_lambda_name extends Primitive { pf__set_lambda_name() { super("%set-lambda-name", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Operator) { ((Operator)first).setLambdaName(second); return second; } // KLUDGE: this isn't fully general, but lots of other stuff // will break for generic functions that aren't subclasses // of standard-generic-function as well. if (first.typep(Symbol.STANDARD_GENERIC_FUNCTION) != NIL) { ((StandardObject)first).setInstanceSlotValue(Symbol.NAME, second); return second; } if (first instanceof FuncallableStandardObject) { return this.execute(((FuncallableStandardObject)first).function, second); } return type_error(first, Symbol.FUNCTION); } }; // ### shrink-vector vector new-size => vector // Destructively alters the vector, changing its length to NEW-SIZE, which // must be less than or equal to its current length. // shrink-vector vector new-size => vector private static final Primitive SHRINK_VECTOR = new pf_shrink_vector(); private static final class pf_shrink_vector extends Primitive { pf_shrink_vector() { super("shrink-vector", PACKAGE_SYS, true, "vector new-size"); } @Override public LispObject execute(LispObject first, LispObject second) { checkVector(first).shrink(Fixnum.getValue(second)); return first; } }; // ### subseq sequence start &optional end private static final Primitive SUBSEQ = new pf_subseq(); private static final class pf_subseq extends Primitive { pf_subseq() { super(PACKAGE_SYS.intern("%SUBSEQ"), "sequence start &optional end"); } @Override public LispObject execute(LispObject first, LispObject second) { return execute(first, second, NIL); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { final int start = Fixnum.getValue(second); if (start < 0) { StringBuilder sb = new StringBuilder("Bad start index ("); sb.append(start); sb.append(")."); error(new TypeError(sb.toString())); } int end; if (third != NIL) { end = Fixnum.getValue(third); if (start > end) { StringBuilder sb = new StringBuilder("Start index ("); sb.append(start); sb.append(") is greater than end index ("); sb.append(end); sb.append(") for SUBSEQ."); error(new TypeError(sb.toString())); } } else end = -1; if (first.listp()) return list_subseq(first, start, end); if (first instanceof AbstractVector) { final AbstractVector v = (AbstractVector) first; if (end < 0) end = v.length(); if (start > end) { StringBuilder sb = new StringBuilder("Start index ("); sb.append(start); sb.append(") is greater than length of vector ("); sb.append(end); sb.append(") for SUBSEQ."); error(new TypeError(sb.toString())); } return v.subseq(start, end); } return type_error(first, Symbol.SEQUENCE); } }; static final LispObject list_subseq(LispObject list, int start, int end) { int index = 0; LispObject result = NIL; while (list != NIL) { if (end >= 0 && index == end) return result.nreverse(); if (index++ >= start) result = new Cons(list.car(), result); list = list.cdr(); } return result.nreverse(); } // ### list private static final Primitive LIST = new pf_list(); private static final class pf_list extends Primitive { pf_list() { super(Symbol.LIST, "&rest objects"); } @Override public LispObject execute() { return NIL; } @Override public LispObject execute(LispObject arg) { return new Cons(arg); } @Override public LispObject execute(LispObject first, LispObject second) { return new Cons(first, new Cons(second)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return new Cons(first, new Cons(second, new Cons(third))); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return new Cons(first, new Cons(second, new Cons(third, new Cons(fourth)))); } @Override public LispObject execute(LispObject[] args) { LispObject result = NIL; for (int i = args.length; i-- > 0;) result = new Cons(args[i], result); return result; } }; // ### list* private static final Primitive LIST_STAR = new pf_list_star(); private static final class pf_list_star extends Primitive { pf_list_star() { super(Symbol.LIST_STAR, "&rest objects"); } @Override public LispObject execute() { return error(new WrongNumberOfArgumentsException(this, 1, -1)); } @Override public LispObject execute(LispObject arg) { return arg; } @Override public LispObject execute(LispObject first, LispObject second) { return new Cons(first, second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return new Cons(first, new Cons(second, third)); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return new Cons(first, new Cons(second, new Cons(third, fourth))); } @Override public LispObject execute(LispObject[] args) { int i = args.length - 1; LispObject result = args[i]; while (i-- > 0) result = new Cons(args[i], result); return result; } }; // ### nreverse public static final Primitive NREVERSE = new pf_nreverse(); private static final class pf_nreverse extends Primitive { pf_nreverse() { super("%NREVERSE", PACKAGE_SYS, false, "sequence"); } @Override public LispObject execute (LispObject arg) { return arg.nreverse(); } }; // ### nreconc private static final Primitive NRECONC = new pf_nreconc(); private static final class pf_nreconc extends Primitive { pf_nreconc() { super(Symbol.NRECONC, "list tail"); } @Override public LispObject execute(LispObject list, LispObject obj) { if (list instanceof Cons) { LispObject list3 = list.cdr(); if (list3 instanceof Cons) { if (list3.cdr() instanceof Cons) { LispObject list1 = list3; LispObject list2 = NIL; do { LispObject h = list3.cdr(); list3.setCdr(list2); list2 = list3; list3 = h; } while (list3.cdr() instanceof Cons); list.setCdr(list2); list1.setCdr(list3); } LispObject h = list.car(); list.setCar(list3.car()); list3.setCar(h); list3.setCdr(obj); } else if (list3 == NIL) { list.setCdr(obj); } else type_error(list3, Symbol.LIST); return list; } else if (list == NIL) return obj; else return type_error(list, Symbol.LIST); } }; // ### reverse private static final Primitive REVERSE = new pf_reverse(); private static final class pf_reverse extends Primitive { pf_reverse() { super("%reverse", PACKAGE_SYS, false, "sequence"); } @Override public LispObject execute(LispObject arg) { return arg.reverse(); } }; // ### delete-eq item sequence => result-sequence private static final Primitive DELETE_EQ = new pf_delete_eq(); private static final class pf_delete_eq extends Primitive { pf_delete_eq() { super("delete-eq", PACKAGE_SYS, true, "item sequence"); } @Override public LispObject execute(LispObject item, LispObject sequence) { if (sequence instanceof AbstractVector) return ((AbstractVector)sequence).deleteEq(item); else return LIST_DELETE_EQ.execute(item, sequence); } }; // ### delete-eql item seqluence => result-seqluence private static final Primitive DELETE_EQL = new pf_delete_eql(); private static final class pf_delete_eql extends Primitive { pf_delete_eql() { super("delete-eql", PACKAGE_SYS, true, "item sequence"); } @Override public LispObject execute(LispObject item, LispObject sequence) { if (sequence instanceof AbstractVector) return ((AbstractVector)sequence).deleteEql(item); else return LIST_DELETE_EQL.execute(item, sequence); } }; // ### list-delete-eq item list => result-list static final Primitive LIST_DELETE_EQ = new pf_list_delete_eq(); private static final class pf_list_delete_eq extends Primitive { pf_list_delete_eq() { super("list-delete-eq", PACKAGE_SYS, true, "item list"); } @Override public LispObject execute(LispObject item, LispObject list) { if (list instanceof Cons) { LispObject tail = list; LispObject splice = list; while (tail instanceof Cons) { LispObject car = tail.car(); if (car == item) { if (tail.cdr() != NIL) { LispObject temp = tail; tail.setCar(temp.cadr()); tail.setCdr(temp.cddr()); } else { // Last item. if (tail == list) return NIL; splice.setCdr(NIL); return list; } } else { splice = tail; tail = tail.cdr(); } } if (tail == NIL) return list; else return type_error(tail, Symbol.LIST); } else if (list == NIL) return list; else return type_error(list, Symbol.LIST); } }; // ### list-delete-eql item list => result-list static final Primitive LIST_DELETE_EQL = new pf_list_delete_eql(); private static final class pf_list_delete_eql extends Primitive { pf_list_delete_eql() { super("list-delete-eql", PACKAGE_SYS, true, "item list"); } @Override public LispObject execute(LispObject item, LispObject list) { if (list instanceof Cons) { LispObject tail = list; LispObject splice = list; while (tail instanceof Cons) { LispObject car = tail.car(); if (car.eql(item)) { if (tail.cdr() != NIL) { LispObject temp = tail; tail.setCar(temp.cadr()); tail.setCdr(temp.cddr()); } else { // Last item. if (tail == list) return NIL; splice.setCdr(NIL); return list; } } else { splice = tail; tail = tail.cdr(); } } if (tail == NIL) return list; else return type_error(tail, Symbol.LIST); } else if (list == NIL) return list; else return type_error(list, Symbol.LIST); } }; // ### vector-delete-eq item vector => result-vector private static final Primitive VECTOR_DELETE_EQ = new pf_vector_delete_eq(); private static final class pf_vector_delete_eq extends Primitive { pf_vector_delete_eq() { super("vector-delete-eq", PACKAGE_SYS, true, "item vector"); } @Override public LispObject execute(LispObject item, LispObject vector) { checkVector(vector).deleteEq(item); return vector; } }; // ### vector-delete-eql item vector => result-vector private static final Primitive VECTOR_DELETE_EQL = new pf_vector_delete_eql(); private static final class pf_vector_delete_eql extends Primitive { pf_vector_delete_eql() { super("vector-delete-eql", PACKAGE_SYS, true, "item vector"); } @Override public LispObject execute(LispObject item, LispObject vector) { checkVector(vector).deleteEql(item); return vector; } }; // ### %set-elt // %setelt sequence index newval => newval private static final Primitive _SET_ELT = new pf__set_elt(); private static final class pf__set_elt extends Primitive { pf__set_elt() { super("%set-elt", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first instanceof AbstractVector) { ((AbstractVector)first).aset(Fixnum.getValue(second), third); return third; } if (first instanceof Cons) { int index = Fixnum.getValue(second); if (index < 0) error(new TypeError()); LispObject list = first; int i = 0; while (true) { if (i == index) { list.setCar(third); return third; } list = list.cdr(); if (list == NIL) error(new TypeError()); ++i; } } return type_error(first, Symbol.SEQUENCE); } }; // ### %make-list private static final Primitive _MAKE_LIST = new pf__make_list(); private static final class pf__make_list extends Primitive { pf__make_list() { super("%make-list", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { int size = Fixnum.getValue(first); if (size < 0) return type_error(first, list(Symbol.INTEGER, Fixnum.ZERO, Symbol.MOST_POSITIVE_FIXNUM.getSymbolValue())); LispObject result = NIL; for (int i = size; i-- > 0;) result = new Cons(second, result); return result; } }; // ### %member item list key test test-not => tail private static final Primitive _MEMBER = new pf__member(); private static final class pf__member extends Primitive { pf__member() { super("%member", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject item, LispObject list, LispObject key, LispObject test, LispObject testNot) { LispObject tail = checkList(list); if (test != NIL && testNot != NIL) error(new LispError("MEMBER: test and test-not both supplied")); if (testNot == NIL) { if (test == NIL || test == Symbol.EQL) test = EQL; } if (key == NIL) { if (test == EQL) { while (tail instanceof Cons) { if (item.eql(((Cons)tail).car)) return tail; tail = ((Cons)tail).cdr; } } else if (test != NIL) { while (tail instanceof Cons) { LispObject candidate = ((Cons)tail).car; if (test.execute(item, candidate) != NIL) return tail; tail = ((Cons)tail).cdr; } } else { // test == NIL while (tail instanceof Cons) { LispObject candidate = ((Cons)tail).car; if (testNot.execute(item, candidate) == NIL) return tail; tail = ((Cons)tail).cdr; } } } else { // key != NIL while (tail instanceof Cons) { LispObject candidate = key.execute(((Cons)tail).car); if (test != NIL) { if (test.execute(item, candidate) != NIL) return tail; } else { if (testNot.execute(item, candidate) == NIL) return tail; } tail = ((Cons)tail).cdr; } } if (tail != NIL) type_error(tail, Symbol.LIST); return NIL; } }; // ### funcall-key function-or-nil element private static final Primitive FUNCALL_KEY = new pf_funcall_key(); private static final class pf_funcall_key extends Primitive { pf_funcall_key() { super("funcall-key", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { if (first != NIL) return LispThread.currentThread().execute(first, second); return second; } }; // ### coerce-to-function private static final Primitive COERCE_TO_FUNCTION = new pf_coerce_to_function(); private static final class pf_coerce_to_function extends Primitive { pf_coerce_to_function() { super("coerce-to-function", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return coerceToFunction(arg); } }; // ### make-closure lambda-form environment => closure private static final Primitive MAKE_CLOSURE = new pf_make_closure(); private static final class pf_make_closure extends Primitive { pf_make_closure() { super("make-closure", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Cons && ((Cons)first).car == Symbol.LAMBDA) { final Environment env; if (second == NIL) env = new Environment(); else env = checkEnvironment(second); return new Closure(first, env); } return error(new TypeError("The argument to MAKE-CLOSURE is not a lambda form.")); } }; // ### streamp private static final Primitive STREAMP = new pf_streamp(); private static final class pf_streamp extends Primitive { pf_streamp() { super(Symbol.STREAMP, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof Stream ? T : NIL; } }; // ### integerp private static final Primitive INTEGERP = new pf_integerp(); private static final class pf_integerp extends Primitive { pf_integerp() { super(Symbol.INTEGERP, "object"); } @Override public LispObject execute(LispObject arg) { return arg.INTEGERP(); } }; // ### evenp private static final Primitive EVENP = new pf_evenp(); private static final class pf_evenp extends Primitive { pf_evenp() { super(Symbol.EVENP, "integer"); } @Override public LispObject execute(LispObject arg) { return arg.EVENP(); } }; // ### oddp private static final Primitive ODDP = new pf_oddp(); private static final class pf_oddp extends Primitive { pf_oddp() { super(Symbol.ODDP, "integer"); } @Override public LispObject execute(LispObject arg) { return arg.ODDP(); } }; // ### numberp private static final Primitive NUMBERP = new pf_numberp(); private static final class pf_numberp extends Primitive { pf_numberp() { super(Symbol.NUMBERP, "object"); } @Override public LispObject execute(LispObject arg) { return arg.NUMBERP(); } }; // ### realp private static final Primitive REALP = new pf_realp(); private static final class pf_realp extends Primitive { pf_realp() { super(Symbol.REALP, "object"); } @Override public LispObject execute(LispObject arg) { return arg.REALP(); } }; // ### rationalp private static final Primitive RATIONALP = new pf_rationalp(); private static final class pf_rationalp extends Primitive { pf_rationalp() { super(Symbol.RATIONALP,"object"); } @Override public LispObject execute(LispObject arg) { return arg.RATIONALP(); } }; // ### complex private static final Primitive COMPLEX = new pf_complex(); private static final class pf_complex extends Primitive { pf_complex() { super(Symbol.COMPLEX, "realpart &optional imagpart"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) return Complex.getInstance(arg, SingleFloat.ZERO); if (arg instanceof DoubleFloat) return Complex.getInstance(arg, DoubleFloat.ZERO); if (arg.realp()) return arg; return type_error(arg, Symbol.REAL); } @Override public LispObject execute(LispObject first, LispObject second) { return Complex.getInstance(first, second); } }; // ### complexp private static final Primitive COMPLEXP = new pf_complexp(); private static final class pf_complexp extends Primitive { pf_complexp() { super(Symbol.COMPLEXP, "object"); } @Override public LispObject execute(LispObject arg) { return arg.COMPLEXP(); } }; // ### numerator private static final Primitive NUMERATOR = new pf_numerator(); private static final class pf_numerator extends Primitive { pf_numerator() { super(Symbol.NUMERATOR, "rational"); } @Override public LispObject execute(LispObject arg) { return arg.NUMERATOR(); } }; // ### denominator private static final Primitive DENOMINATOR = new pf_denominator(); private static final class pf_denominator extends Primitive { pf_denominator() { super(Symbol.DENOMINATOR, "rational"); } @Override public LispObject execute(LispObject arg) { return arg.DENOMINATOR(); } }; // ### realpart private static final Primitive REALPART = new pf_realpart(); private static final class pf_realpart extends Primitive { pf_realpart() { super(Symbol.REALPART, "number"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Complex) return ((Complex)arg).getRealPart(); if (arg.numberp()) return arg; return type_error(arg, Symbol.NUMBER); } }; // ### imagpart private static final Primitive IMAGPART = new pf_imagpart(); private static final class pf_imagpart extends Primitive { pf_imagpart() { super(Symbol.IMAGPART, "number"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Complex) return ((Complex)arg).getImaginaryPart(); return arg.multiplyBy(Fixnum.ZERO); } }; // ### integer-length private static final Primitive INTEGER_LENGTH = new pf_integer_length(); private static final class pf_integer_length extends Primitive { pf_integer_length() { super(Symbol.INTEGER_LENGTH, "integer"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Fixnum) { int n = ((Fixnum)arg).value; if (n < 0) n = ~n; int count = 0; while (n > 0) { n = n >>> 1; ++count; } return Fixnum.getInstance(count); } if (arg instanceof Bignum) return Fixnum.getInstance(((Bignum)arg).value.bitLength()); return type_error(arg, Symbol.INTEGER); } }; // ### gcd-2 private static final Primitive GCD_2 = new pf_gcd_2(); private static final class pf_gcd_2 extends Primitive { pf_gcd_2() { super("gcd-2", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { BigInteger n1, n2; if (first instanceof Fixnum) n1 = BigInteger.valueOf(((Fixnum)first).value); else if (first instanceof Bignum) n1 = ((Bignum)first).value; else return type_error(first, Symbol.INTEGER); if (second instanceof Fixnum) n2 = BigInteger.valueOf(((Fixnum)second).value); else if (second instanceof Bignum) n2 = ((Bignum)second).value; else return type_error(second, Symbol.INTEGER); return number(n1.gcd(n2)); } }; // ### identity-hash-code private static final Primitive IDENTITY_HASH_CODE = new pf_identity_hash_code(); private static final class pf_identity_hash_code extends Primitive { pf_identity_hash_code() { super("identity-hash-code", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(System.identityHashCode(arg)); } }; // ### simple-vector-search pattern vector => position // Searches vector for pattern. private static final Primitive SIMPLE_VECTOR_SEARCH = new pf_simple_vector_search(); private static final class pf_simple_vector_search extends Primitive { pf_simple_vector_search() { super("simple-vector-search", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject first, LispObject second) { AbstractVector v = checkVector(second); if (first.length() == 0) return Fixnum.ZERO; final int patternLength = first.length(); final int limit = v.length() - patternLength; if (first instanceof AbstractVector) { AbstractVector pattern = (AbstractVector) first; LispObject element = pattern.AREF(0); for (int i = 0; i <= limit; i++) { if (v.AREF(i).eql(element)) { // Found match for first element of pattern. boolean match = true; // We've already checked the first element. int j = i + 1; for (int k = 1; k < patternLength; k++) { if (v.AREF(j).eql(pattern.AREF(k))) { ++j; } else { match = false; break; } } if (match) return Fixnum.getInstance(i); } } } else { // Pattern is a list. LispObject element = first.car(); for (int i = 0; i <= limit; i++) { if (v.AREF(i).eql(element)) { // Found match for first element of pattern. boolean match = true; // We've already checked the first element. int j = i + 1; for (LispObject rest = first.cdr(); rest != NIL; rest = rest.cdr()) { if (v.AREF(j).eql(rest.car())) { ++j; } else { match = false; break; } } if (match) return Fixnum.getInstance(i); } } } return NIL; } }; // ### uptime private static final Primitive UPTIME = new pf_uptime(); private static final class pf_uptime extends Primitive { pf_uptime() { super("uptime", PACKAGE_EXT, true); } @Override public LispObject execute() { return number(System.currentTimeMillis() - Main.startTimeMillis); } }; // ### built-in-function-p private static final Primitive BUILT_IN_FUNCTION_P = new pf_built_in_function_p(); private static final class pf_built_in_function_p extends Primitive { pf_built_in_function_p() { super("built-in-function-p", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return checkSymbol(arg).isBuiltInFunction() ? T : NIL; } }; // ### inspected-parts private static final Primitive INSPECTED_PARTS = new pf_inspected_parts(); private static final class pf_inspected_parts extends Primitive { pf_inspected_parts() { super("inspected-parts", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return arg.getParts(); } }; // ### inspected-description private static final Primitive INSPECTED_DESCRIPTION = new pf_inspected_description(); private static final class pf_inspected_description extends Primitive { pf_inspected_description() { super("inspected-description", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject arg) { return arg.getDescription(); } }; // ### symbol-name public static final Primitive SYMBOL_NAME = new pf_symbol_name(); private static final class pf_symbol_name extends Primitive { pf_symbol_name() { super(Symbol.SYMBOL_NAME, "symbol"); } @Override public LispObject execute(LispObject arg) { return checkSymbol(arg).name; } }; // ### symbol-package public static final Primitive SYMBOL_PACKAGE = new pf_symbol_package(); private static final class pf_symbol_package extends Primitive { pf_symbol_package() { super(Symbol.SYMBOL_PACKAGE, "symbol"); } @Override public LispObject execute(LispObject arg) { return checkSymbol(arg).getPackage(); } }; // ### symbol-function public static final Primitive SYMBOL_FUNCTION = new pf_symbol_function(); private static final class pf_symbol_function extends Primitive { pf_symbol_function() { super(Symbol.SYMBOL_FUNCTION, "symbol"); } @Override public LispObject execute(LispObject arg) { LispObject function = checkSymbol(arg).getSymbolFunction(); if (function != null) return function; return error(new UndefinedFunction(arg)); } }; // ### %set-symbol-function public static final Primitive _SET_SYMBOL_FUNCTION = new pf__set_symbol_function(); private static final class pf__set_symbol_function extends Primitive { pf__set_symbol_function() { super("%set-symbol-function", PACKAGE_SYS, false, "symbol function"); } @Override public LispObject execute(LispObject first, LispObject second) { checkSymbol(first).setSymbolFunction(second); return second; } }; // ### symbol-plist public static final Primitive SYMBOL_PLIST = new pf_symbol_plist(); private static final class pf_symbol_plist extends Primitive { pf_symbol_plist() { super(Symbol.SYMBOL_PLIST, "symbol"); } @Override public LispObject execute(LispObject arg) { return checkSymbol(arg).getPropertyList(); } }; // ### keywordp public static final Primitive KEYWORDP = new pf_keywordp(); private static final class pf_keywordp extends Primitive { pf_keywordp() { super(Symbol.KEYWORDP, "object"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Symbol) { if (checkSymbol(arg).getPackage() == PACKAGE_KEYWORD) return T; } return NIL; } }; // ### make-symbol public static final Primitive MAKE_SYMBOL = new pf_make_symbol(); private static final class pf_make_symbol extends Primitive { pf_make_symbol() { super(Symbol.MAKE_SYMBOL, "name"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof SimpleString) return new Symbol((SimpleString)arg); // Not a simple string. if (arg instanceof AbstractString) return new Symbol(arg.getStringValue()); return type_error(arg, Symbol.STRING); } }; // ### makunbound public static final Primitive MAKUNBOUND = new pf_makunbound(); private static final class pf_makunbound extends Primitive { pf_makunbound() { super(Symbol.MAKUNBOUND, "symbol"); } @Override public LispObject execute(LispObject arg) { checkSymbol(arg).setSymbolValue(null); return arg; } }; // ### %class-name private static final Primitive _CLASS_NAME = new pf__class_name(); private static final class pf__class_name extends Primitive { pf__class_name() { super("%class-name", PACKAGE_SYS, true, "class"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispClass) return ((LispClass)arg).getName(); return ((StandardObject)arg).getInstanceSlotValue(StandardClass.symName); } }; // ### %set-class-name private static final Primitive _SET_CLASS_NAME = new pf__set_class_name(); private static final class pf__set_class_name extends Primitive { pf__set_class_name() { super("%set-class-name", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof LispClass) ((LispClass)second).setName(checkSymbol(first)); else ((StandardObject)second).setInstanceSlotValue(StandardClass.symName, checkSymbol(first)); return first; } }; // ### class-layout private static final Primitive CLASS_LAYOUT = new pf__class_layout(); private static final class pf__class_layout extends Primitive { pf__class_layout() { super("%class-layout", PACKAGE_SYS, true, "class"); } @Override public LispObject execute(LispObject arg) { Layout layout; if (arg instanceof LispClass) layout = ((LispClass)arg).getClassLayout(); else layout = (Layout)((StandardObject)arg).getInstanceSlotValue(StandardClass.symLayout); return layout != null ? layout : NIL; } }; // ### %set-class-layout private static final Primitive _SET_CLASS_LAYOUT = new pf__set_class_layout(); private static final class pf__set_class_layout extends Primitive { pf__set_class_layout() { super("%set-class-layout", PACKAGE_SYS, true, "class layout"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first == NIL || first instanceof Layout) { if (second instanceof LispClass) ((LispClass)second).setClassLayout(first); else ((StandardObject)second).setInstanceSlotValue(StandardClass.symLayout, first); return first; } return type_error(first, Symbol.LAYOUT); } }; // ### %class-direct-superclasses private static final Primitive _CLASS_DIRECT_SUPERCLASSES = new pf__class_direct_superclasses(); private static final class pf__class_direct_superclasses extends Primitive { pf__class_direct_superclasses() { super("%class-direct-superclasses", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispClass) return ((LispClass)arg).getDirectSuperclasses(); else return ((StandardObject)arg).getInstanceSlotValue(StandardClass.symDirectSuperclasses); } }; // ### %set-class-direct-superclasses private static final Primitive _SET_CLASS_DIRECT_SUPERCLASSES = new pf__set_class_direct_superclasses(); private static final class pf__set_class_direct_superclasses extends Primitive { pf__set_class_direct_superclasses() { super("%set-class-direct-superclasses", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof LispClass) ((LispClass)second).setDirectSuperclasses(first); else ((StandardObject)second).setInstanceSlotValue(StandardClass.symDirectSuperclasses, first); return first; } }; // ### %class-direct-subclasses private static final Primitive _CLASS_DIRECT_SUBCLASSES = new pf__class_direct_subclasses(); private static final class pf__class_direct_subclasses extends Primitive { pf__class_direct_subclasses() { super("%class-direct-subclasses", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispClass) return ((LispClass)arg).getDirectSubclasses(); else return ((StandardObject)arg).getInstanceSlotValue(StandardClass.symDirectSubclasses); } }; // ### %set-class-direct-subclasses private static final Primitive _SET_CLASS_DIRECT_SUBCLASSES = new pf__set_class_direct_subclasses(); private static final class pf__set_class_direct_subclasses extends Primitive { pf__set_class_direct_subclasses() { super("%set-class-direct-subclasses", PACKAGE_SYS, true, "class direct-subclasses"); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof LispClass) ((LispClass)second).setDirectSubclasses(first); else ((StandardObject)second).setInstanceSlotValue(StandardClass.symDirectSubclasses, first); return first; } }; // ### %class-precedence-list private static final Primitive _CLASS_PRECEDENCE_LIST = new pf__class_precedence_list(); private static final class pf__class_precedence_list extends Primitive { pf__class_precedence_list() { super("%class-precedence-list", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispClass) return ((LispClass)arg).getCPL(); else return ((StandardObject)arg).getInstanceSlotValue(StandardClass.symPrecedenceList); } }; // ### %set-class-precedence-list private static final Primitive _SET_CLASS_PRECEDENCE_LIST = new pf__set_class_precedence_list(); private static final class pf__set_class_precedence_list extends Primitive { pf__set_class_precedence_list() { super("%set-class-precedence-list", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof LispClass) ((LispClass)second).setCPL(first); else ((StandardObject)second).setInstanceSlotValue(StandardClass.symPrecedenceList, first); return first; } }; // ### %class-direct-methods private static final Primitive _CLASS_DIRECT_METHODS = new pf__class_direct_methods(); private static final class pf__class_direct_methods extends Primitive { pf__class_direct_methods() { super("%class-direct-methods", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispClass) return ((LispClass)arg).getDirectMethods(); else return ((StandardObject)arg).getInstanceSlotValue(StandardClass.symDirectMethods); } }; // ### %set-class-direct-methods private static final Primitive _SET_CLASS_DIRECT_METHODS = new pf__set_class_direct_methods(); private static final class pf__set_class_direct_methods extends Primitive { pf__set_class_direct_methods() { super("%set-class-direct-methods", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof LispClass) ((LispClass)second).setDirectMethods(first); else ((StandardObject)second).setInstanceSlotValue(StandardClass.symDirectMethods, first); return first; } }; // ### class-documentation private static final Primitive CLASS_DOCUMENTATION = new pf_class_documentation(); private static final class pf_class_documentation extends Primitive { pf_class_documentation() { super("class-documentation", PACKAGE_MOP, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispClass) return ((LispClass)arg).getDocumentation(); else return ((StandardObject)arg).getInstanceSlotValue(Symbol._DOCUMENTATION); } }; // ### %set-class-documentation private static final Primitive _SET_CLASS_DOCUMENTATION = new pf__set_class_documentation(); private static final class pf__set_class_documentation extends Primitive { pf__set_class_documentation() { super("%set-class-documentation", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof LispClass) ((LispClass)first).setDocumentation(second); else ((StandardObject)first).setInstanceSlotValue(Symbol._DOCUMENTATION, second); return second; } }; // ### %class-finalized-p private static final Primitive _CLASS_FINALIZED_P = new pf__class_finalized_p(); private static final class pf__class_finalized_p extends Primitive { pf__class_finalized_p() { super("%class-finalized-p", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof LispClass) return ((LispClass)arg).isFinalized() ? T : NIL; else return ((StandardObject)arg).getInstanceSlotValue(StandardClass.symFinalizedP); } }; // ### %set-class-finalized-p private static final Primitive _SET_CLASS_FINALIZED_P = new pf__set_class_finalized_p(); private static final class pf__set_class_finalized_p extends Primitive { pf__set_class_finalized_p() { super("%set-class-finalized-p", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof LispClass) ((LispClass)second).setFinalized(first != NIL); else ((StandardObject)second).setInstanceSlotValue(StandardClass.symFinalizedP, first); return first; } }; // ### classp private static final Primitive CLASSP = new pf_classp(); private static final class pf_classp extends Primitive { pf_classp() { super("classp", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { return (arg instanceof LispClass) ? T : arg.typep(Symbol.CLASS); } }; // ### char-to-utf8 char => octets private static final Primitive CHAR_TO_UTF8 = new pf_char_to_utf8(); private static final class pf_char_to_utf8 extends Primitive { pf_char_to_utf8() { super("char-to-utf8", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { final LispCharacter c; c = checkCharacter( arg); char[] chars = new char[1]; chars[0] = c.value; String s = new String(chars); final byte[] bytes; try { bytes = s.getBytes("UTF8"); } catch (java.io.UnsupportedEncodingException e) { return error(new LispError("UTF8 is not a supported encoding.")); } LispObject[] objects = new LispObject[bytes.length]; for (int i = bytes.length; i-- > 0;) { int n = bytes[i]; if (n < 0) n += 256; objects[i] = Fixnum.getInstance(n); } return new SimpleVector(objects); } }; // ### %documentation private static final Primitive _DOCUMENTATION = new pf__documentation(); private static final class pf__documentation extends Primitive { pf__documentation() { super("%documentation", PACKAGE_SYS, true, "object doc-type"); } @Override public LispObject execute(LispObject object, LispObject docType) { LispObject doc = object.getDocumentation(docType); if (doc == NIL) { if (docType == Symbol.FUNCTION && object instanceof Symbol) { // Generic functions are handled at lisp-level, not here LispObject function = object.getSymbolFunction(); if (function != null) doc = function.getDocumentation(docType); } } return doc; } }; // ### %set-documentation private static final Primitive _SET_DOCUMENTATION = new pf__set_documentation(); private static final class pf__set_documentation extends Primitive { pf__set_documentation() { super("%set-documentation", PACKAGE_SYS, true, "object doc-type documentation"); } @Override public LispObject execute(LispObject object, LispObject docType, LispObject documentation) { // Generic functions are handled at lisp-level, not here object.setDocumentation(docType, documentation); return documentation; } }; // ### %putf private static final Primitive _PUTF = new pf__putf(); private static final class pf__putf extends Primitive { pf__putf() { super("%putf", PACKAGE_SYS, true, "plist indicator new-value"); } @Override public LispObject execute(LispObject plist, LispObject indicator, LispObject newValue) { return putf(plist, indicator, newValue); } }; // ### function-plist private static final Primitive FUNCTION_PLIST = new pf_function_plist(); private static final class pf_function_plist extends Primitive { pf_function_plist() { super("function-plist", PACKAGE_SYS, true, "function"); } @Override public LispObject execute(LispObject arg) { return checkFunction(arg).getPropertyList(); } }; // ### make-keyword private static final Primitive MAKE_KEYWORD = new pf_make_keyword(); private static final class pf_make_keyword extends Primitive { pf_make_keyword() { super("make-keyword", PACKAGE_SYS, true, "symbol"); } @Override public LispObject execute(LispObject arg) { return PACKAGE_KEYWORD.intern(checkSymbol(arg).name); } }; // ### standard-object-p object => generalized-boolean private static final Primitive STANDARD_OBJECT_P = new pf_standard_object_p(); private static final class pf_standard_object_p extends Primitive { pf_standard_object_p() { super("standard-object-p", PACKAGE_SYS, true, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof StandardObject ? T : NIL; } }; // ### copy-tree private static final Primitive COPY_TREE = new pf_copy_tree(); private static final class pf_copy_tree extends Primitive { pf_copy_tree() { super(Symbol.COPY_TREE, "object"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Cons) { Cons cons = (Cons) arg; return new Cons(execute(cons.car), execute(cons.cdr)); } else return arg; } }; /* Added to ABCL because Maxima wants to be able to turn off * underflow conditions. However, the Hyperspec says we have to * signal them. So, we went for CLHS compliant with a switch for * Maxima. */ // ### float-underflow-mode private static final Primitive FLOAT_UNDERFLOW_MODE = new pf_float_underflow_mode(); private static final class pf_float_underflow_mode extends Primitive { pf_float_underflow_mode() { super(Symbol.FLOAT_UNDERFLOW_MODE, "&optional boolean"); } @Override public LispObject execute() { return Lisp.TRAP_UNDERFLOW ? T : NIL; } @Override public LispObject execute(LispObject arg) { Lisp.TRAP_UNDERFLOW = (arg != NIL); return arg; } }; /* Implemented for symmetry with the underflow variant. */ // ### float-overflow-mode private static final Primitive FLOAT_OVERFLOW_MODE = new pf_float_overflow_mode(); private static final class pf_float_overflow_mode extends Primitive { pf_float_overflow_mode() { super(Symbol.FLOAT_OVERFLOW_MODE, "&optional boolean"); } @Override public LispObject execute() { return Lisp.TRAP_OVERFLOW ? T : NIL; } @Override public LispObject execute(LispObject arg) { Lisp.TRAP_OVERFLOW = (arg != NIL); return arg; } }; // ### finalize private static final Primitive FINALIZE = new pf_finalize(); private static final class pf_finalize extends Primitive { pf_finalize() { super("finalize", PACKAGE_EXT, true, "object function"); } @Override public LispObject execute(LispObject obj, final LispObject fun) { Finalizer.addFinalizer(obj, new Runnable() { @Override public void run() { fun.execute(); } }); return obj; } }; // ### cancel-finalization private static final Primitive CANCEL_FINALIZATION = new pf_cancel_finalization(); private static final class pf_cancel_finalization extends Primitive { pf_cancel_finalization() { super("cancel-finalization", PACKAGE_EXT, true, "object"); } @Override public LispObject execute(LispObject obj) { Finalizer.clearFinalizers(obj); return obj; } }; private static final Primitive GET_FASL_READTABLE = new pf_get_fasl_readtable(); private static class pf_get_fasl_readtable extends Primitive { pf_get_fasl_readtable() { super("get-fasl-readtable", PACKAGE_SYS, false); } @Override public LispObject execute() { return FaslReadtable.getInstance(); } } } abcl-src-1.9.0/src/org/armedbear/lisp/PrintNotReadable.java0100644 0000000 0000000 00000007020 14202767264 022256 0ustar000000000 0000000 /* * PrintNotReadable.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class PrintNotReadable extends LispError { public PrintNotReadable(LispObject initArgs) { super(StandardClass.PRINT_NOT_READABLE); super.initialize(initArgs); LispObject object = null; while (initArgs != NIL) { LispObject first = initArgs.car(); initArgs = initArgs.cdr(); LispObject second = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.OBJECT) { object = second; break; } } if (object != null) setInstanceSlotValue(Symbol.OBJECT, object); } @Override public LispObject typeOf() { return Symbol.PRINT_NOT_READABLE; } @Override public LispObject classOf() { return StandardClass.PRINT_NOT_READABLE; } @Override public LispObject typep(LispObject type) { if (type == Symbol.PRINT_NOT_READABLE) return T; if (type == StandardClass.PRINT_NOT_READABLE) return T; return super.typep(type); } @Override public String getMessage() { StringBuilder sb = new StringBuilder(); LispObject object = UNBOUND_VALUE; object = getInstanceSlotValue(Symbol.OBJECT); if (object != UNBOUND_VALUE) { sb.append(object.princToString()); } else sb.append("Object"); sb.append(" cannot be printed readably."); return sb.toString(); } // ### print-not-readable-object private static final Primitive PRINT_NOT_READABLE_OBJECT = new Primitive("print-not-readable-object", "condition") { @Override public LispObject execute(LispObject arg) { if (arg instanceof PrintNotReadable) return ((PrintNotReadable)arg).getInstanceSlotValue(Symbol.OBJECT); return type_error(arg, Symbol.PRINT_NOT_READABLE); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/ProcessingTerminated.java0100644 0000000 0000000 00000004066 14202767264 023221 0ustar000000000 0000000 /* * ProcessingTerminated.java * * Copyright (C) 2011 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; /** This error is thrown when the EXT:EXIT or EXT:QUIT function * is being invoked. In the stand-alone case, it terminates the * entire JVM, if caught in Interpreter.run(). * * In the embedding case, it's up to the embedder what to do with it. */ public class ProcessingTerminated extends Error { private int status; public ProcessingTerminated() { } public ProcessingTerminated(int status) { this.status = status; } public int getStatus() { return status; } } abcl-src-1.9.0/src/org/armedbear/lisp/Profiler.java0100644 0000000 0000000 00000013410 14202767264 020643 0ustar000000000 0000000 /* * Profiler.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class Profiler { static int sleep = 1; // ### %start-profiler // %start-profiler type granularity public static final Primitive _START_PROFILER = new Primitive("%start-profiler", PACKAGE_PROF, false) { @Override public LispObject execute(LispObject first, LispObject second) { final LispThread thread = LispThread.currentThread(); Stream out = getStandardOutput(); out.freshLine(); if (profiling) { out._writeLine("; Profiler already started."); } else { if (first == Keyword.TIME) sampling = true; else if (first == Keyword.COUNT_ONLY) sampling = false; else return error(new LispError( "%START-PROFILER: argument must be either :TIME or :COUNT-ONLY")); Package[] packages = Packages.getAllPackages(); for (int i = 0; i < packages.length; i++) { Package pkg = packages[i]; Symbol[] symbols = pkg.symbols(); for (int j = 0; j < symbols.length; j++) { Symbol symbol = symbols[j]; LispObject object = symbol.getSymbolFunction(); if (object != null) { object.setCallCount(0); object.setHotCount(0); LispObject methods = null; if (object.typep(Symbol.STANDARD_GENERIC_FUNCTION) != NIL) { methods = Symbol.GENERIC_FUNCTION_METHODS.execute(object); } while (methods != null && methods != NIL) { LispObject method = methods.car(); LispObject function = Symbol.METHOD_FUNCTION.execute(method); if (function != NIL) { function.setCallCount(0); function.setHotCount(0); methods = methods.cdr(); } } } } } if (sampling) { sleep = Fixnum.getValue(second); Runnable profilerRunnable = new Runnable() { public void run() { profiling = true; // make sure we don't fall through on the first iteration while (profiling) { try { thread.incrementCallCounts(); Thread.sleep(sleep); } //### FIXME exception catch (InterruptedException e) { Debug.trace(e); } } } }; Thread t = new Thread(profilerRunnable); // Maximum priority doesn't hurt: // we're sleeping all the time anyway t.setPriority(Thread.MAX_PRIORITY); new Thread(profilerRunnable).start(); } out._writeLine("; Profiler started."); } return thread.nothing(); } }; // ### stop-profiler public static final Primitive STOP_PROFILER = new Primitive("stop-profiler", PACKAGE_PROF, true) { @Override public LispObject execute() { Stream out = getStandardOutput(); out.freshLine(); if (profiling) { profiling = false; out._writeLine("; Profiler stopped."); } else out._writeLine("; Profiler was not started."); out._finishOutput(); return LispThread.currentThread().nothing(); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/ProgramError.java0100644 0000000 0000000 00000005165 14223403213 021472 0ustar000000000 0000000 /* * ProgramError.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class ProgramError extends LispError { protected ProgramError(LispClass cls) { super(cls); } public ProgramError(LispObject initArgs) { super(StandardClass.PROGRAM_ERROR); initialize(initArgs); if (initArgs.listp() && initArgs.car().stringp()) { setFormatControl(initArgs.car().getStringValue()); setFormatArguments(initArgs.cdr()); } } public ProgramError(String message) { super(StandardClass.PROGRAM_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); } @Override public LispObject typeOf() { return Symbol.PROGRAM_ERROR; } @Override public LispObject classOf() { return StandardClass.PROGRAM_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.PROGRAM_ERROR) return T; if (type == StandardClass.PROGRAM_ERROR) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/RandomState.java0100644 0000000 0000000 00000021311 14202767264 021301 0ustar000000000 0000000 /* * RandomState.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.math.BigInteger; import java.util.Random; public final class RandomState extends LispObject { private Random random; public RandomState() { random = new Random(); } public RandomState(RandomState rs) { try { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(rs.random); out.close(); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(byteIn); random = (Random) in.readObject(); in.close(); } catch (Throwable t) { // ANY exception gets converted to a lisp error error(new LispError("Unable to copy random state.")); } } public RandomState(SimpleVector v) { int length = v.capacity; byte[] bytes = new byte[length]; for (int i = 0; i < length; ++i) { LispObject obj = v.data[i]; if (obj instanceof Fixnum) { bytes[i] = (byte)((Fixnum)obj).value; } else { error(type_error(obj, Symbol.FIXNUM)); } } try { ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes); ObjectInputStream in = new ObjectInputStream(byteIn); random = (Random) in.readObject(); in.close(); } catch (Throwable t) { // ANY exception gets converted to a lisp error error(new LispError("Unable to read random state.")); } } @Override public LispObject typeOf() { return Symbol.RANDOM_STATE; } @Override public LispObject classOf() { return BuiltInClass.RANDOM_STATE; } @Override public LispObject typep(LispObject type) { if (type == Symbol.RANDOM_STATE) return T; if (type == BuiltInClass.RANDOM_STATE) return T; return super.typep(type); } @Override public String printObject() { LispThread thread = LispThread.currentThread(); StringBuilder sb = new StringBuilder(); if (Symbol.PRINT_READABLY.symbolValue(thread) != NIL) { // we need the #. reader macro for now if (Symbol.READ_EVAL.symbolValue(thread) == NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue(thread)); ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); try { sb.append("#.(SYSTEM::READ-RANDOM-STATE #("); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(random); out.close(); } catch (Throwable t) { // ANY exception gets converted to a lisp error error(new LispError("Unable to copy random state.")); } byte[] bytes = byteOut.toByteArray(); for (int i = 0; i < bytes.length; ++i) { if (i != 0) { sb.append(" "); } sb.append(Integer.toString(bytes[i], base).toUpperCase()); } sb.append("))"); } else { return unreadableString("RANDOM-STATE"); } return sb.toString(); } public LispObject random(LispObject arg) { if (arg instanceof Fixnum) { int limit = ((Fixnum)arg).value; if (limit > 0) { int n = random.nextInt((int)limit); return Fixnum.getInstance(n); } } else if (arg instanceof Bignum) { BigInteger limit = ((Bignum)arg).value; if (limit.signum() > 0) { int bitLength = limit.bitLength(); BigInteger rand = new BigInteger(bitLength + 1, random); BigInteger remainder = rand.remainder(limit); return number(remainder); } } else if (arg instanceof SingleFloat) { float limit = ((SingleFloat)arg).value; if (limit > 0) { float rand = random.nextFloat(); return new SingleFloat(rand * limit); } } else if (arg instanceof DoubleFloat) { double limit = ((DoubleFloat)arg).value; if (limit > 0) { double rand = random.nextDouble(); return new DoubleFloat(rand * limit); } } return type_error(arg, list(Symbol.OR, list(Symbol.INTEGER, Fixnum.ONE), list(Symbol.FLOAT, list(Fixnum.ZERO)))); } // ### random limit &optional random-state => random-number private static final Primitive RANDOM = new Primitive(Symbol.RANDOM, "limit &optional random-state") { @Override public LispObject execute(LispObject arg) { RandomState randomState = (RandomState) Symbol._RANDOM_STATE_.symbolValue(); return randomState.random(arg); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof RandomState) { RandomState randomState = (RandomState) second; return randomState.random(first); } return type_error(first, Symbol.RANDOM_STATE); } }; // ### make-random-state &optional state private static final Primitive MAKE_RANDOM_STATE = new Primitive(Symbol.MAKE_RANDOM_STATE, "&optional state") { @Override public LispObject execute() { return new RandomState((RandomState)Symbol._RANDOM_STATE_.symbolValue()); } @Override public LispObject execute(LispObject arg) { if (arg == NIL) return new RandomState((RandomState)Symbol._RANDOM_STATE_.symbolValue()); if (arg == T) return new RandomState(); if (arg instanceof RandomState) return new RandomState((RandomState)arg); return type_error(arg, Symbol.RANDOM_STATE); } }; private static final Primitive READ_RANDOM_STATE = new Primitive(Symbol.READ_RANDOM_STATE, "state") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SimpleVector) return new RandomState((SimpleVector)arg); return type_error(arg, Symbol.RANDOM_STATE); } }; // ### random-state-p private static final Primitive RANDOM_STATE_P = new Primitive(Symbol.RANDOM_STATE_P, "object") { @Override public LispObject execute(LispObject arg) { return arg instanceof RandomState ? T : NIL; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Ratio.java0100644 0000000 0000000 00000050016 14223403213 020122 0ustar000000000 0000000 /* * Ratio.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; public final class Ratio extends LispObject { private BigInteger numerator; private BigInteger denominator; public Ratio(BigInteger numerator, BigInteger denominator) { this.numerator = numerator; this.denominator = denominator; } public BigInteger numerator() { return numerator; } @Override public LispObject NUMERATOR() { return number(numerator); } public BigInteger denominator() { return denominator; } @Override public LispObject DENOMINATOR() { return number(denominator); } @Override public LispObject typeOf() { return Symbol.RATIO; } @Override public LispObject classOf() { return BuiltInClass.RATIO; } @Override public LispObject typep(LispObject type) { if (type == Symbol.RATIO) return T; if (type == Symbol.RATIONAL) return T; if (type == Symbol.REAL) return T; if (type == Symbol.NUMBER) return T; if (type == BuiltInClass.RATIO) return T; return super.typep(type); } @Override public boolean numberp() { return true; } @Override public boolean rationalp() { return true; } @Override public boolean realp() { return true; } @Override public boolean eql(LispObject obj) { if (this == obj) return true; if (obj instanceof Ratio) { return (numerator.equals(((Ratio)obj).numerator) && denominator.equals(((Ratio)obj).denominator)); } return false; } @Override public boolean equal(LispObject obj) { return eql(obj); } @Override public boolean equalp(LispObject obj) { if (obj != null && obj.numberp()) return isEqualTo(obj); return false; } @Override public LispObject ABS() { if (numerator.signum() > 0 && denominator.signum() > 0) return this; if (numerator.signum() < 0 && denominator.signum() < 0) return this; return new Ratio(numerator.negate(), denominator); } @Override public boolean plusp() { return numerator.signum() == denominator.signum(); } @Override public boolean minusp() { return numerator.signum() != denominator.signum(); } @Override public boolean zerop() { return false; } @Override public float floatValue() { float result = (float) doubleValue(); if (Float.isInfinite(result) && TRAP_OVERFLOW) type_error(this, Symbol.SINGLE_FLOAT); return (float) doubleValue(); } @Override public double doubleValue() { double result = numerator.doubleValue() / denominator.doubleValue(); if (result != 0 && !Double.isNaN(result) && !Double.isInfinite(result)) return result; final boolean negative = numerator.signum() < 0; final BigInteger num = negative ? numerator.negate() : numerator; final BigInteger den = denominator; final int numLen = num.bitLength(); final int denLen = den.bitLength(); int length = Math.min(numLen, denLen); if (length <= 1) { // A precision of 512 is overkill for DOUBLE-FLOAT types // based on java.lang.Double TODO: optimize for space/time final MathContext mathContext = new MathContext(512, RoundingMode.HALF_EVEN); BigDecimal p = new BigDecimal(numerator, mathContext); BigDecimal q = new BigDecimal(denominator, mathContext); BigDecimal r = p.divide(q, mathContext); result = r.doubleValue(); return result; } BigInteger n = num; BigInteger d = den; final int digits = 54; if (length > digits) { n = n.shiftRight(length - digits); d = d.shiftRight(length - digits); length -= digits; } else { n = n.shiftRight(1); d = d.shiftRight(1); --length; } for (int i = 0; i < length; i++) { result = n.doubleValue() / d.doubleValue(); if (result != 0 && !Double.isNaN(result) && !Double.isInfinite(result)) break; n = n.shiftRight(1); d = d.shiftRight(1); } if (Double.isInfinite(result) && TRAP_OVERFLOW) type_error(this, Symbol.DOUBLE_FLOAT); return negative ? -result : result; } @Override public final LispObject incr() { return new Ratio(numerator.add(denominator), denominator); } @Override public final LispObject decr() { return new Ratio(numerator.subtract(denominator), denominator); } @Override public LispObject add(LispObject obj) { if (obj instanceof Fixnum) { BigInteger n = numerator.add(BigInteger.valueOf(((Fixnum)obj).value).multiply(denominator)); return number(n, denominator); } if (obj instanceof Bignum) { BigInteger n = ((Bignum)obj).value; return number(numerator.add(n.multiply(denominator)), denominator); } if (obj instanceof Ratio) { BigInteger n = ((Ratio)obj).numerator; BigInteger d = ((Ratio)obj).denominator; if (denominator.equals(d)) return number(numerator.add(n), denominator); BigInteger common = denominator.multiply(d); return number(numerator.multiply(d).add(n.multiply(denominator)), common); } if (obj instanceof SingleFloat) { return new SingleFloat(floatValue() + ((SingleFloat)obj).value); } if (obj instanceof DoubleFloat) { return new DoubleFloat(doubleValue() + ((DoubleFloat)obj).value); } if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart()); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject subtract(LispObject obj) { if (obj instanceof Fixnum) { BigInteger n = numerator.subtract(BigInteger.valueOf(((Fixnum)obj).value).multiply(denominator)); return number(n, denominator); } if (obj instanceof Bignum) { BigInteger n = ((Bignum)obj).value; return number(numerator.subtract(n.multiply(denominator)), denominator); } if (obj instanceof Ratio) { BigInteger n = ((Ratio)obj).numerator; BigInteger d = ((Ratio)obj).denominator; if (denominator.equals(d)) return number(numerator.subtract(n), denominator); BigInteger common = denominator.multiply(d); return number(numerator.multiply(d).subtract(n.multiply(denominator)), common); } if (obj instanceof SingleFloat) { return new SingleFloat(floatValue() - ((SingleFloat)obj).value); } if (obj instanceof DoubleFloat) { return new DoubleFloat(doubleValue() - ((DoubleFloat)obj).value); } if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(subtract(c.getRealPart()), Fixnum.ZERO.subtract(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject multiplyBy(LispObject obj) { if (obj instanceof Fixnum) { BigInteger n = ((Fixnum)obj).getBigInteger(); return number(numerator.multiply(n), denominator); } if (obj instanceof Bignum) { BigInteger n = ((Bignum)obj).value; return number(numerator.multiply(n), denominator); } if (obj instanceof Ratio) { BigInteger n = ((Ratio)obj).numerator; BigInteger d = ((Ratio)obj).denominator; return number(numerator.multiply(n), denominator.multiply(d)); } if (obj instanceof SingleFloat) { return new SingleFloat(floatValue() * ((SingleFloat)obj).value); } if (obj instanceof DoubleFloat) { return new DoubleFloat(doubleValue() * ((DoubleFloat)obj).value); } if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(multiplyBy(c.getRealPart()), multiplyBy(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject divideBy(LispObject obj) { if (obj.zerop()) { LispObject operands = new Cons(this, new Cons(obj)); LispObject args = new Cons(Keyword.OPERATION, new Cons(Symbol.SLASH, new Cons(Keyword.OPERANDS, new Cons(operands)))); return error(new DivisionByZero(args)); } if (obj instanceof Fixnum) { BigInteger n = ((Fixnum)obj).getBigInteger(); return number(numerator, denominator.multiply(n)); } if (obj instanceof Bignum) { BigInteger n = ((Bignum)obj).value; return number(numerator, denominator.multiply(n)); } if (obj instanceof Ratio) { BigInteger n = ((Ratio)obj).numerator; BigInteger d = ((Ratio)obj).denominator; return number(numerator.multiply(d), denominator.multiply(n)); } if (obj instanceof SingleFloat) { return new SingleFloat(floatValue() / ((SingleFloat)obj).value); } if (obj instanceof DoubleFloat) { return new DoubleFloat(doubleValue() / ((DoubleFloat)obj).value); } if (obj instanceof Complex) { Complex c = (Complex) obj; // numerator LispObject realPart = this.multiplyBy(c.getRealPart()); LispObject imagPart = Fixnum.ZERO.subtract(this).multiplyBy(c.getImaginaryPart()); // denominator LispObject d = c.getRealPart().multiplyBy(c.getRealPart()); d = d.add(c.getImaginaryPart().multiplyBy(c.getImaginaryPart())); return Complex.getInstance(realPart.divideBy(d), imagPart.divideBy(d)); } return type_error(obj, Symbol.NUMBER); } @Override public boolean isEqualTo(LispObject obj) { if (obj instanceof Ratio) return (numerator.equals(((Ratio)obj).numerator) && denominator.equals(((Ratio)obj).denominator)); if (obj instanceof SingleFloat) return isEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isEqualTo(((DoubleFloat)obj).rational()); if (obj.numberp()) return false; type_error(obj, Symbol.NUMBER); // Not reached. return false; } @Override public boolean isNotEqualTo(LispObject obj) { return !isEqualTo(obj); } @Override public boolean isLessThan(LispObject obj) { if (obj instanceof Fixnum) { BigInteger n2 = ((Fixnum)obj).getBigInteger().multiply(denominator); return numerator.compareTo(n2) < 0; } if (obj instanceof Bignum) { BigInteger n = ((Bignum)obj).value.multiply(denominator); return numerator.compareTo(n) < 0; } if (obj instanceof Ratio) { BigInteger n1 = numerator.multiply(((Ratio)obj).denominator); BigInteger n2 = ((Ratio)obj).numerator.multiply(denominator); return n1.compareTo(n2) < 0; } if (obj instanceof SingleFloat) return isLessThan(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isLessThan(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThan(LispObject obj) { if (obj instanceof Fixnum) { BigInteger n2 = ((Fixnum)obj).getBigInteger().multiply(denominator); return numerator.compareTo(n2) > 0; } if (obj instanceof Bignum) { BigInteger n = ((Bignum)obj).value.multiply(denominator); return numerator.compareTo(n) > 0; } if (obj instanceof Ratio) { BigInteger n1 = numerator.multiply(((Ratio)obj).denominator); BigInteger n2 = ((Ratio)obj).numerator.multiply(denominator); return n1.compareTo(n2) > 0; } if (obj instanceof SingleFloat) return isGreaterThan(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isGreaterThan(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isLessThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) { BigInteger n2 = ((Fixnum)obj).getBigInteger().multiply(denominator); return numerator.compareTo(n2) <= 0; } if (obj instanceof Bignum) { BigInteger n = ((Bignum)obj).value.multiply(denominator); return numerator.compareTo(n) <= 0; } if (obj instanceof Ratio) { BigInteger n1 = numerator.multiply(((Ratio)obj).denominator); BigInteger n2 = ((Ratio)obj).numerator.multiply(denominator); return n1.compareTo(n2) <= 0; } if (obj instanceof SingleFloat) return isLessThanOrEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isLessThanOrEqualTo(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) { BigInteger n2 = ((Fixnum)obj).getBigInteger().multiply(denominator); return numerator.compareTo(n2) >= 0; } if (obj instanceof Bignum) { BigInteger n = ((Bignum)obj).value.multiply(denominator); return numerator.compareTo(n) >= 0; } if (obj instanceof Ratio) { BigInteger n1 = numerator.multiply(((Ratio)obj).denominator); BigInteger n2 = ((Ratio)obj).numerator.multiply(denominator); return n1.compareTo(n2) >= 0; } if (obj instanceof SingleFloat) return isGreaterThanOrEqualTo(((SingleFloat)obj).rational()); if (obj instanceof DoubleFloat) return isGreaterThanOrEqualTo(((DoubleFloat)obj).rational()); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public LispObject truncate(LispObject obj) { // "When rationals and floats are combined by a numerical function, // the rational is first converted to a float of the same format." // 12.1.4.1 if (obj instanceof SingleFloat) return new SingleFloat(floatValue()).truncate(obj); if (obj instanceof DoubleFloat) return new DoubleFloat(doubleValue()).truncate(obj); BigInteger n, d; try { if (obj instanceof Fixnum) { n = ((Fixnum)obj).getBigInteger(); d = BigInteger.ONE; } else if (obj instanceof Bignum) { n = ((Bignum)obj).value; d = BigInteger.ONE; } else if (obj instanceof Ratio) { n = ((Ratio)obj).numerator(); d = ((Ratio)obj).denominator(); } else { return type_error(obj, Symbol.NUMBER); } // Invert and multiply. BigInteger num = numerator.multiply(d); BigInteger den = denominator.multiply(n); BigInteger quotient = num.divide(den); // Multiply quotient by divisor. LispObject product = number(quotient.multiply(n), d); // Subtract to get remainder. LispObject remainder = subtract(product); return LispThread.currentThread().setValues(number(quotient), remainder); } catch (ArithmeticException e) { if (obj.zerop()) { LispObject operands = new Cons(this, new Cons(obj)); LispObject args = new Cons(Keyword.OPERATION, new Cons(Symbol.TRUNCATE, new Cons(Keyword.OPERANDS, new Cons(operands)))); return error(new DivisionByZero(args)); } return error(new ArithmeticError(e.getMessage())); } } @Override public int hashCode() { return numerator.hashCode() ^ denominator.hashCode(); } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue(thread)); StringBuffer sb = new StringBuffer(numerator.toString(base)); sb.append('/'); sb.append(denominator.toString(base)); String s = sb.toString().toUpperCase(); if (Symbol.PRINT_RADIX.symbolValue(thread) != NIL) { sb.setLength(0); switch (base) { case 2: sb.append("#b"); sb.append(s); break; case 8: sb.append("#o"); sb.append(s); break; case 10: sb.append("#10r"); sb.append(s); break; case 16: sb.append("#x"); sb.append(s); break; default: sb.append('#'); sb.append(String.valueOf(base)); sb.append('r'); sb.append(s); break; } s = sb.toString(); } return s; } } abcl-src-1.9.0/src/org/armedbear/lisp/ReaderError.java0100644 0000000 0000000 00000006040 14202767264 021276 0ustar000000000 0000000 /* * ReaderError.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ReaderError extends StreamError { public ReaderError(String message) { super(StandardClass.READER_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); } public ReaderError(String message, Stream stream) { super(StandardClass.READER_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); setStream(stream); } public ReaderError(String message, Stream stream, LispObject arg1, LispObject arg2) { super(StandardClass.READER_ERROR); setFormatControl(message); setFormatArguments(list(arg1, arg2)); setStream(stream); } public ReaderError(LispObject initArgs) { super(StandardClass.READER_ERROR); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.READER_ERROR; } @Override public LispObject classOf() { return StandardClass.READER_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.READER_ERROR) return T; if (type == StandardClass.READER_ERROR) return T; if (type == Symbol.PARSE_ERROR) return T; if (type == StandardClass.PARSE_ERROR) return T; return super.typep(type); } @Override public String getMessage() { return message; } } abcl-src-1.9.0/src/org/armedbear/lisp/ReaderMacroFunction.java0100644 0000000 0000000 00000004764 14202767264 022767 0ustar000000000 0000000 /* * ReaderMacroFunction.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class ReaderMacroFunction extends Function { public ReaderMacroFunction(String name) { super(name); } public ReaderMacroFunction(String name, String arglist) { super(name, arglist); } public ReaderMacroFunction(String name, Package pkg) { super(name, pkg); } public ReaderMacroFunction(String name, Package pkg, boolean exported) { super(name, pkg, exported); } public ReaderMacroFunction(String name, Package pkg, boolean exported, String arglist) { super(name, pkg, exported, arglist); } @Override public LispObject execute(LispObject first, LispObject second) { Stream stream = inSynonymOf(first); char c = LispCharacter.getValue(second); return execute(stream, c); } public abstract LispObject execute(Stream stream, char c) ; } abcl-src-1.9.0/src/org/armedbear/lisp/Readtable.java0100644 0000000 0000000 00000046406 14223403213 020737 0ustar000000000 0000000 /* * Readtable.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.Iterator; public class Readtable extends LispObject { public static final byte SYNTAX_TYPE_CONSTITUENT = 0; public static final byte SYNTAX_TYPE_WHITESPACE = 1; public static final byte SYNTAX_TYPE_TERMINATING_MACRO = 2; public static final byte SYNTAX_TYPE_NON_TERMINATING_MACRO = 3; public static final byte SYNTAX_TYPE_SINGLE_ESCAPE = 4; public static final byte SYNTAX_TYPE_MULTIPLE_ESCAPE = 5; protected final CharHashMap syntax = new CharHashMap(Byte.class,SYNTAX_TYPE_CONSTITUENT); protected final CharHashMap readerMacroFunctions = new CharHashMap(LispObject.class,null); protected final CharHashMap dispatchTables = new CharHashMap(DispatchTable.class,null); protected LispObject readtableCase; public Readtable() { initialize(); } protected void initialize() { Byte[] syntax = this.syntax.constants; syntax[9] = SYNTAX_TYPE_WHITESPACE; // tab syntax[10] = SYNTAX_TYPE_WHITESPACE; // linefeed syntax[12] = SYNTAX_TYPE_WHITESPACE; // form feed syntax[13] = SYNTAX_TYPE_WHITESPACE; // return syntax[' '] = SYNTAX_TYPE_WHITESPACE; syntax['"'] = SYNTAX_TYPE_TERMINATING_MACRO; syntax['\''] = SYNTAX_TYPE_TERMINATING_MACRO; syntax['('] = SYNTAX_TYPE_TERMINATING_MACRO; syntax[')'] = SYNTAX_TYPE_TERMINATING_MACRO; syntax[','] = SYNTAX_TYPE_TERMINATING_MACRO; syntax[';'] = SYNTAX_TYPE_TERMINATING_MACRO; syntax['`'] = SYNTAX_TYPE_TERMINATING_MACRO; syntax['#'] = SYNTAX_TYPE_NON_TERMINATING_MACRO; syntax['\\'] = SYNTAX_TYPE_SINGLE_ESCAPE; syntax['|'] = SYNTAX_TYPE_MULTIPLE_ESCAPE; LispObject[] readerMacroFunctions = this.readerMacroFunctions.constants; readerMacroFunctions[';'] = LispReader.READ_COMMENT; readerMacroFunctions['"'] = LispReader.READ_STRING; readerMacroFunctions['('] = LispReader.READ_LIST; readerMacroFunctions[')'] = LispReader.READ_RIGHT_PAREN; readerMacroFunctions['\''] = LispReader.READ_QUOTE; readerMacroFunctions['#'] = LispReader.READ_DISPATCH_CHAR; // BACKQUOTE-MACRO and COMMA-MACRO are defined in backquote.lisp. readerMacroFunctions['`'] = Symbol.BACKQUOTE_MACRO; readerMacroFunctions[','] = Symbol.COMMA_MACRO; DispatchTable dt = new DispatchTable(); LispObject[] dtfunctions = dt.functions.constants; dtfunctions['('] = LispReader.SHARP_LEFT_PAREN; dtfunctions['*'] = LispReader.SHARP_STAR; dtfunctions['.'] = LispReader.SHARP_DOT; dtfunctions[':'] = LispReader.SHARP_COLON; dtfunctions['A'] = LispReader.SHARP_A; dtfunctions['B'] = LispReader.SHARP_B; dtfunctions['C'] = LispReader.SHARP_C; dtfunctions['O'] = LispReader.SHARP_O; dtfunctions['P'] = LispReader.SHARP_P; dtfunctions['R'] = LispReader.SHARP_R; dtfunctions['S'] = LispReader.SHARP_S; dtfunctions['X'] = LispReader.SHARP_X; dtfunctions['\''] = LispReader.SHARP_QUOTE; dtfunctions['\\'] = LispReader.SHARP_BACKSLASH; dtfunctions['|'] = LispReader.SHARP_VERTICAL_BAR; dtfunctions[')'] = LispReader.SHARP_ILLEGAL; dtfunctions['<'] = LispReader.SHARP_ILLEGAL; dtfunctions[' '] = LispReader.SHARP_ILLEGAL; dtfunctions[8] = LispReader.SHARP_ILLEGAL; // backspace dtfunctions[9] = LispReader.SHARP_ILLEGAL; // tab dtfunctions[10] = LispReader.SHARP_ILLEGAL; // newline, linefeed dtfunctions[12] = LispReader.SHARP_ILLEGAL; // page dtfunctions[13] = LispReader.SHARP_ILLEGAL; // return dispatchTables.constants['#'] = dt; readtableCase = Keyword.UPCASE; } public Readtable(LispObject obj) { Readtable rt; if (obj == NIL) rt = checkReadtable(STANDARD_READTABLE.symbolValue()); else rt = checkReadtable(obj); synchronized (rt) { copyReadtable(rt, this); } } // FIXME synchronization static void copyReadtable(Readtable from, Readtable to) { Iterator charIterator = from.syntax.getCharIterator(); while (charIterator.hasNext()) { char c = charIterator.next(); Byte dt = from.syntax.get(c); if (dt!=null) { to.syntax.put(c, dt); } else { to.syntax.put(c, null); } } charIterator = from.readerMacroFunctions.getCharIterator(); while (charIterator.hasNext()) { char c = charIterator.next(); LispObject dt = from.readerMacroFunctions.get(c); if (dt!=null) { to.readerMacroFunctions.put(c, dt); } else { to.readerMacroFunctions.put(c, null); } } charIterator = from.dispatchTables.getCharIterator(); while (charIterator.hasNext()) { char c = charIterator.next(); DispatchTable dt = from.dispatchTables.get(c); if (dt!=null) { to.dispatchTables.put(c, new DispatchTable(dt)); } else { to.dispatchTables.put(c, null); } } to.readtableCase = from.readtableCase; } @Override public final LispObject typeOf() { return Symbol.READTABLE; } @Override public final LispObject classOf() { return BuiltInClass.READTABLE; } @Override public final LispObject typep(LispObject type) { if (type == Symbol.READTABLE) return T; if (type == BuiltInClass.READTABLE) return T; return super.typep(type); } public final LispObject getReadtableCase() { return readtableCase; } public final boolean isWhitespace(char c) { return getSyntaxType(c) == SYNTAX_TYPE_WHITESPACE; } public final byte getSyntaxType(char c) { return syntax.get(c); } public final boolean isInvalid(char c) { switch (c) { case 8: case 9: case 10: case 12: case 13: case 32: case 127: return true; default: return false; } } public final void checkInvalid(char c, Stream stream) { // "... no mechanism is provided for changing the constituent trait of a // character." (2.1.4.2) if (isInvalid(c)) { String name = LispCharacter.charToName(c); StringBuilder sb = new StringBuilder("Invalid character"); if (name != null) { sb.append(" #\\"); sb.append(name); } error(new ReaderError(sb.toString(), stream)); } } public final LispObject getReaderMacroFunction(char c) { return readerMacroFunctions.get(c); } final LispObject getMacroCharacter(char c) { LispObject function = getReaderMacroFunction(c); LispObject non_terminating_p; if (function != null) { if (syntax.get(c) == SYNTAX_TYPE_NON_TERMINATING_MACRO) non_terminating_p = T; else non_terminating_p = NIL; } else { function = NIL; non_terminating_p = NIL; } return LispThread.currentThread().setValues(function, non_terminating_p); } final void makeDispatchMacroCharacter(char dispChar, LispObject non_terminating_p) { byte syntaxType; if (non_terminating_p != NIL) syntaxType = SYNTAX_TYPE_NON_TERMINATING_MACRO; else syntaxType = SYNTAX_TYPE_TERMINATING_MACRO; // FIXME synchronization syntax.put(dispChar,syntaxType); readerMacroFunctions.put(dispChar, LispReader.READ_DISPATCH_CHAR); dispatchTables.put(dispChar, new DispatchTable()); } public final LispObject getDispatchMacroCharacter(char dispChar, char subChar) { DispatchTable dispatchTable = dispatchTables.get(dispChar); if (dispatchTable == null) { LispCharacter c = LispCharacter.getInstance(dispChar); return error(new LispError(c.princToString() + " is not a dispatch character.")); } LispObject function = dispatchTable.functions.get(LispCharacter.toUpperCase(subChar)); return (function != null) ? function : NIL; } public final void setDispatchMacroCharacter(char dispChar, char subChar, LispObject function) { DispatchTable dispatchTable = dispatchTables.get(dispChar); if (dispatchTable == null) { LispCharacter c = LispCharacter.getInstance(dispChar); error(new LispError(c.princToString() + " is not a dispatch character.")); } dispatchTable.functions.put(LispCharacter.toUpperCase(subChar), function); } protected static class DispatchTable { protected final CharHashMap functions; public DispatchTable() { functions = new CharHashMap(LispObject.class,null); } @SuppressWarnings("unchecked") public DispatchTable(DispatchTable dt) { functions = (CharHashMap) dt.functions.clone(); } } // ### readtablep private static final Primitive READTABLEP = new Primitive("readtablep", "object") { @Override public LispObject execute(LispObject arg) { return arg instanceof Readtable ? T : NIL; } }; // ### copy-readtable private static final Primitive COPY_READTABLE = new Primitive("copy-readtable", "&optional from-readtable to-readtable") { @Override public LispObject execute() { return new Readtable(currentReadtable()); } @Override public LispObject execute(LispObject arg) { return new Readtable(arg); } @Override public LispObject execute(LispObject first, LispObject second) { Readtable from = designator_readtable(first); if (second == NIL) return new Readtable(from); Readtable to = checkReadtable(second); copyReadtable(from, to); return to; } }; // ### get-macro-character char &optional readtable // => function, non-terminating-p private static final Primitive GET_MACRO_CHARACTER = new Primitive("get-macro-character", "char &optional readtable") { @Override public LispObject execute(LispObject arg) { char c = LispCharacter.getValue(arg); Readtable rt = currentReadtable(); return rt.getMacroCharacter(c); } @Override public LispObject execute(LispObject first, LispObject second) { char c = LispCharacter.getValue(first); Readtable rt = designator_readtable(second); return rt.getMacroCharacter(c); } }; // ### set-macro-character char new-function &optional non-terminating-p readtable // => t private static final Primitive SET_MACRO_CHARACTER = new Primitive("set-macro-character", "char new-function &optional non-terminating-p readtable") { @Override public LispObject execute(LispObject first, LispObject second) { return execute(first, second, NIL, currentReadtable()); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return execute(first, second, third, currentReadtable()); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { char c = LispCharacter.getValue(first); final LispObject designator; if (second instanceof Function || second instanceof FuncallableStandardObject) designator = second; else if (second instanceof Symbol) designator = second; else return error(new LispError(second.princToString() + " does not designate a function.")); byte syntaxType; if (third != NIL) syntaxType = SYNTAX_TYPE_NON_TERMINATING_MACRO; else syntaxType = SYNTAX_TYPE_TERMINATING_MACRO; Readtable rt = designator_readtable(fourth); // REVIEW synchronization rt.syntax.put(c, syntaxType); rt.readerMacroFunctions.put(c, designator); return T; } }; // ### make-dispatch-macro-character char &optional non-terminating-p readtable // => t private static final Primitive MAKE_DISPATCH_MACRO_CHARACTER = new Primitive("make-dispatch-macro-character", "char &optional non-terminating-p readtable") { @Override public LispObject execute(LispObject[] args) { if (args.length < 1 || args.length > 3) return error(new WrongNumberOfArgumentsException(this, 1, 3)); char dispChar = LispCharacter.getValue(args[0]); LispObject non_terminating_p; if (args.length > 1) non_terminating_p = args[1]; else non_terminating_p = NIL; Readtable readtable; if (args.length == 3) readtable = checkReadtable(args[2]); else readtable = currentReadtable(); readtable.makeDispatchMacroCharacter(dispChar, non_terminating_p); return T; } }; // ### get-dispatch-macro-character disp-char sub-char &optional readtable // => function private static final Primitive GET_DISPATCH_MACRO_CHARACTER = new Primitive("get-dispatch-macro-character", "disp-char sub-char &optional readtable") { @Override public LispObject execute(LispObject[] args) { if (args.length < 2 || args.length > 3) return error(new WrongNumberOfArgumentsException(this, 1, 3)); char dispChar = LispCharacter.getValue(args[0]); char subChar = LispCharacter.getValue(args[1]); Readtable readtable; if (args.length == 3) readtable = designator_readtable(args[2]); else readtable = currentReadtable(); return readtable.getDispatchMacroCharacter(dispChar, subChar); } }; // ### set-dispatch-macro-character disp-char sub-char new-function &optional readtable // => t private static final Primitive SET_DISPATCH_MACRO_CHARACTER = new Primitive("set-dispatch-macro-character", "disp-char sub-char new-function &optional readtable") { @Override public LispObject execute(LispObject[] args) { if (args.length < 3 || args.length > 4) return error(new WrongNumberOfArgumentsException(this, 3, 4)); char dispChar = LispCharacter.getValue(args[0]); char subChar = LispCharacter.getValue(args[1]); LispObject function = coerceToFunction(args[2]); Readtable readtable; if (args.length == 4) readtable = designator_readtable(args[3]); else readtable = currentReadtable(); readtable.setDispatchMacroCharacter(dispChar, subChar, function); return T; } }; // ### set-syntax-from-char to-char from-char &optional to-readtable from-readtable // => t private static final Primitive SET_SYNTAX_FROM_CHAR = new Primitive("set-syntax-from-char", "to-char from-char &optional to-readtable from-readtable") { @Override public LispObject execute(LispObject[] args) { if (args.length < 2 || args.length > 4) return error(new WrongNumberOfArgumentsException(this, 2, 4)); char toChar = LispCharacter.getValue(args[0]); char fromChar = LispCharacter.getValue(args[1]); Readtable toReadtable; if (args.length > 2) toReadtable = checkReadtable(args[2]); else toReadtable = currentReadtable(); Readtable fromReadtable; if (args.length > 3) fromReadtable = designator_readtable(args[3]); else fromReadtable = checkReadtable(STANDARD_READTABLE.symbolValue()); // REVIEW synchronization toReadtable.syntax.put(toChar, fromReadtable.syntax.get(fromChar)); toReadtable.readerMacroFunctions.put(toChar, fromReadtable.readerMacroFunctions.get(fromChar)); // "If the character is a dispatching macro character, its entire // dispatch table of reader macro functions is copied." DispatchTable found = fromReadtable.dispatchTables.get(fromChar); if (found!=null) toReadtable.dispatchTables.put(toChar, new DispatchTable(found)); else // Don't leave behind dispatch tables when fromChar // doesn't have one toReadtable.dispatchTables.put(toChar, null); return T; } }; // ### readtable-case readtable => mode private static final Primitive READTABLE_CASE = new Primitive("readtable-case", "readtable") { @Override public LispObject execute(LispObject arg) { return checkReadtable(arg).readtableCase; } }; // ### %set-readtable-case readtable new-mode => new-mode private static final Primitive _SET_READTABLE_CASE = new Primitive("%set-readtable-case", PACKAGE_SYS, false, "readtable new-mode") { @Override public LispObject execute(LispObject first, LispObject second) { final Readtable readtable = checkReadtable(first); if (second == Keyword.UPCASE || second == Keyword.DOWNCASE || second == Keyword.INVERT || second == Keyword.PRESERVE) { readtable.readtableCase = second; return second; } return type_error(second, list(Symbol.MEMBER, Keyword.INVERT, Keyword.PRESERVE, Keyword.DOWNCASE, Keyword.UPCASE)); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/Return.java0100644 0000000 0000000 00000004710 14202767264 020343 0ustar000000000 0000000 /* * Return.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class Return extends ControlTransfer { public final LispObject tag; public final LispObject block; public final LispObject result; public Return(LispObject tag, LispObject block, LispObject result) { this.tag = tag; this.block = block; this.result = result; } public Return(LispObject tag, LispObject result) { this.tag = tag; this.block = null; this.result = result; } public LispObject getTag() { return tag; } public LispObject getBlock() { return block; } public LispObject getResult() { return result; } @Override public LispObject getCondition() { StringBuilder sb = new StringBuilder("No block named "); sb.append(tag.princToString()); sb.append(" is currently visible."); return new ControlError(sb.toString()); } } abcl-src-1.9.0/src/org/armedbear/lisp/RuntimeClass.java0100644 0000000 0000000 00000014727 14223403213 021466 0ustar000000000 0000000 /* * RuntimeClass.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.util.Map; import java.util.HashMap; public class RuntimeClass { static Map classes = new HashMap(); private Map methods = new HashMap(); // ### %jnew-runtime-class // %jnew-runtime-class class-name &rest method-names-and-defs private static final Primitive _JNEW_RUNTIME_CLASS = new Primitive("%jnew-runtime-class", PACKAGE_JAVA, false, "class-name &rest method-names-and-defs") { @Override public LispObject execute(LispObject[] args) { int length = args.length; if (length < 3 || length % 2 != 1) return error(new WrongNumberOfArgumentsException(this)); RuntimeClass rc = new RuntimeClass(); String className = args[0].getStringValue(); for (int i = 1; i < length; i = i+2) { String methodName = args[i].getStringValue(); rc.addLispMethod(methodName, (Function)args[i+1]); } classes.put(className, rc); return T; } }; // ### jredefine-method // %jredefine-method class-name method-name method-def private static final Primitive _JREDEFINE_METHOD = new Primitive("%jredefine-method", PACKAGE_JAVA, false, "class-name method-name method-def") { @Override public LispObject execute(LispObject className, LispObject methodName, LispObject methodDef) { String cn = className.getStringValue(); String mn = methodName.getStringValue(); Function def = (Function) methodDef; RuntimeClass rc = null; if (classes.containsKey(cn)) { rc = (RuntimeClass) classes.get(cn); rc.addLispMethod(mn, def); return T; } else { error(new LispError("undefined Java class: " + cn)); return NIL; } } }; // ### %load-java-class-from-byte-array private static final Primitive _LOAD_JAVA_CLASS_FROM_BYTE_ARRAY = new Primitive("%load-java-class-from-byte-array", PACKAGE_JAVA, false, "classname bytearray") { @Override public LispObject execute(LispObject className, LispObject classBytes) { String cn = className.getStringValue(); String pn = cn.substring(0,cn.lastIndexOf('.')); byte[] cb = (byte[]) classBytes.javaInstance(); try { JavaClassLoader loader = JavaClassLoader.getPersistentInstance(pn); Class c = loader.loadClassFromByteArray(cn, cb); if (c != null) { return T; } } catch (VerifyError e) { return error(new LispError("class verification failed: " + e.getMessage())); } catch (LinkageError e) { return error(new LispError("class could not be linked: " + e.getMessage())); } return error( new LispError("unable to load ".concat(cn))); } }; public static final LispObject evalC(LispObject function, LispObject args, Environment env, LispThread thread) { return evalCall(function, args, env, thread); } public static RuntimeClass getRuntimeClass(String className) { return (RuntimeClass) classes.get(className); } public Function getLispMethod(String methodName) { return (Function) methods.get(methodName); } void addLispMethod(String methodName, Function def) { methods.put(methodName, def); } public static final LispObject makeLispObject(Object obj) { return new JavaObject(obj); } public static final Fixnum makeLispObject(byte i) { return Fixnum.getInstance(i); } public static final Fixnum makeLispObject(short i) { return Fixnum.getInstance(i); } public static final Fixnum makeLispObject(int i) { return Fixnum.getInstance(i); } public static final LispInteger makeLispObject(long i) { return Bignum.getInstance(i); } public static final SingleFloat makeLispObject(float i) { return new SingleFloat(i); } public static final DoubleFloat makeLispObject(double i) { return new DoubleFloat(i); } public static final LispCharacter makeLispObject(char i) { return LispCharacter.getInstance(i); } public static final LispObject makeLispObject(boolean i) { return i ? T : NIL; } } abcl-src-1.9.0/src/org/armedbear/lisp/SeekableStringWriter.java0100644 0000000 0000000 00000010440 14202767264 023160 0ustar000000000 0000000 /* * SeekableStringWriter.java * * Copyright (C) 2016 Olof-Joachim Frahm * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.Writer; import java.text.MessageFormat; public final class SeekableStringWriter extends Writer { private final StringBuffer stringBuffer; private int offset = 0; public SeekableStringWriter() { stringBuffer = new StringBuffer(); } public SeekableStringWriter(int initialSize) { stringBuffer = new StringBuffer(initialSize); } public SeekableStringWriter append(char c) { write(c); return this; } public SeekableStringWriter append(CharSequence csq) { write(csq.toString()); return this; } public SeekableStringWriter append(CharSequence csq, int start, int end) { write(csq.subSequence(start, end).toString()); return this; } @Override public void write(char[] cbuf) { _write(cbuf, 0, cbuf.length); } @Override public void write(char[] cbuf, int off, int len) { int bufLen = cbuf.length; if (off < 0 || off > bufLen || len < 0 || off + len > bufLen) throw new IllegalArgumentException(); _write(cbuf, off, len); } @Override public void write(int c) { try { if (offset == stringBuffer.length()) stringBuffer.append((char) c); else stringBuffer.setCharAt(offset, (char) c); ++offset; } catch (IndexOutOfBoundsException e) { error(new JavaException(e)); } } @Override public void write(String str) { write(str, 0, str.length()); } @Override public void write(String str, int off, int len) { write(str.toCharArray(), off, len); } private void _write(char[] cbuf, int off, int len) { int strLen = stringBuffer.length(); int space = strLen - offset; int written = Math.min(len, space); if (written > 0) stringBuffer.replace(offset, offset + written, new String(cbuf, off, written)); if (written < len) stringBuffer.append(cbuf, off + written, len - written); offset += len; } public void seek(int offset) { if (offset < 0 || offset > stringBuffer.length()) throw new IllegalArgumentException(); this.offset = offset; } public StringBuffer getBuffer() { return stringBuffer; } public int getOffset() { return offset; } @Override public String toString() { return stringBuffer.toString(); } @Override public void close() {} @Override public void flush() {} public String toStringAndClear() { String result = stringBuffer.toString(); stringBuffer.delete(0, stringBuffer.length()); offset = 0; return result; } } abcl-src-1.9.0/src/org/armedbear/lisp/SeriousCondition.java0100644 0000000 0000000 00000004561 14202767264 022370 0ustar000000000 0000000 /* * SeriousCondition.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class SeriousCondition extends Condition { public SeriousCondition() { } protected SeriousCondition(LispClass cls) { super(cls); } public SeriousCondition(LispObject initArgs) { super(initArgs); } public SeriousCondition(String message) { super(message); } @Override public LispObject typeOf() { return Symbol.SERIOUS_CONDITION; } @Override public LispObject classOf() { return StandardClass.SERIOUS_CONDITION; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SERIOUS_CONDITION) return T; if (type == StandardClass.SERIOUS_CONDITION) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/ShellCommand.java0100644 0000000 0000000 00000023035 14202767264 021433 0ustar000000000 0000000 /* * ShellCommand.java * * Copyright (C) 2000-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public final class ShellCommand implements Runnable { private final String command; private final String directory; private final Stream outputStream; private final StringBuffer output; private int exitValue = -1; public ShellCommand(String command, String directory, Stream outputStream) { this.command = command; this.directory = directory; this.outputStream = outputStream; this.output = (outputStream == null) ? new StringBuffer() : null; } public final String getOutput() { return (output != null) ? output.toString() : ""; } final int exitValue() { return exitValue; } void processOutput(String s) { if (outputStream != null) outputStream._writeString(s); else output.append(s); } public void run() { Process process = null; try { if (command != null) { if (Utilities.isPlatformUnix) { if (directory != null) { StringBuilder sb = new StringBuilder("\\cd \""); sb.append(directory); sb.append("\" && "); sb.append(command); String[] cmdarray = {"/bin/sh", "-c", sb.toString()}; process = Runtime.getRuntime().exec(cmdarray); } else { String[] cmdarray = {"/bin/sh", "-c", command}; process = Runtime.getRuntime().exec(cmdarray); } } else if (Utilities.isPlatformWindows) { ArrayList list = new ArrayList(); list.add("cmd.exe"); list.add("/c"); if (directory != null) { StringBuilder sb = new StringBuilder("cd /d \""); sb.append(directory); sb.append("\" && "); sb.append(command); list.addAll(tokenize(sb.toString())); } else list.addAll(tokenize(command)); final int size = list.size(); String[] cmdarray = new String[size]; for (int i = 0; i < size; i++) cmdarray[i] = (String) list.get(i); process = Runtime.getRuntime().exec(cmdarray); } } } catch (IOException e) { Debug.trace(e); } if (process != null) { ReaderThread stdoutThread = new ReaderThread(process.getInputStream()); stdoutThread.start(); ReaderThread stderrThread = new ReaderThread(process.getErrorStream()); stderrThread.start(); try { exitValue = process.waitFor(); } catch (InterruptedException e) { Debug.trace(e); } try { stdoutThread.join(); } catch (InterruptedException e) { Debug.trace(e); } try { stderrThread.join(); } catch (InterruptedException e) { Debug.trace(e); } } } // Does not handle embedded single-quoted strings. private static List tokenize(String s) { ArrayList list = new ArrayList(); StringBuffer sb = new StringBuffer(); boolean inQuote = false; final int limit = s.length(); for (int i = 0; i < limit; i++) { char c = s.charAt(i); switch (c) { case ' ': if (inQuote) sb.append(c); else if (sb.length() > 0) { list.add(sb.toString()); sb.setLength(0); } break; case '"': if (inQuote) { if (sb.length() > 0) { list.add(sb.toString()); sb.setLength(0); } inQuote = false; } else inQuote = true; break; default: sb.append(c); break; } } if (sb.length() > 0) list.add(sb.toString()); return list; } private class ReaderThread extends Thread { private char[] buf = new char[4096]; private final InputStream inputStream; private final BufferedReader reader; private boolean done = false; public ReaderThread(InputStream inputStream) { this.inputStream = inputStream; reader = new BufferedReader(new InputStreamReader(inputStream)); } @Override public void run() { while (!done) { String s = read(); if (s == null) return; processOutput(s); } } private String read() { StringBuffer sb = new StringBuffer(); try { do { int numChars = reader.read(buf, 0, buf.length); // Blocks. if (numChars < 0) { done = true; break; } if (numChars > 0) sb.append(buf, 0, numChars); Thread.sleep(10); } while (reader.ready()); } catch (IOException e) { return null; } catch (InterruptedException e) { return null; } return sb.toString(); } } // run-shell-command command &key directory (output *standard-output*) // ### %run-shell-command command directory output => exit-code private static final Primitive _RUN_SHELL_COMMAND = new pf_run_shell_command(); private static class pf_run_shell_command extends Primitive { pf_run_shell_command() { super("%run-shell-command", PACKAGE_SYS, false, "command directory output => exit-code"); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (!(Utilities.isPlatformUnix || Utilities.isPlatformWindows)) { return error(new LispError("run-shell-command not implemented for " + System.getProperty("os.name"))); } else { String command = first.getStringValue(); String namestring = null; Stream outputStream = null; if (second != NIL) { Pathname pathname = coerceToPathname(second); namestring = pathname.getNamestring(); if (namestring == null) { return error(new FileError("Pathname has no namestring: " + pathname.princToString(), pathname)); } } if (third != NIL) outputStream = checkStream(third); ShellCommand shellCommand = new ShellCommand(command, namestring, outputStream); shellCommand.run(); if (outputStream != null) outputStream._finishOutput(); return number(shellCommand.exitValue()); } } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleArray_ByteBuffer.java0100644 0000000 0000000 00000024142 14202767264 023432 0ustar000000000 0000000 /* * SimpleArray_ByteBuffer.java * * Copyright (C) 2020 easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; public final class SimpleArray_ByteBuffer extends AbstractArray { private final int[] dimv; private final int totalSize; final ByteBuffer data; private boolean directAllocation; public SimpleArray_ByteBuffer(int[] dimv) { this(dimv, false); } public SimpleArray_ByteBuffer(int[] dimv, boolean directAllocation) { this.dimv = dimv; this.directAllocation = directAllocation; totalSize = computeTotalSize(dimv); if (directAllocation) { data = ByteBuffer.allocateDirect(totalSize); } else { data = ByteBuffer.allocate(totalSize); } } public SimpleArray_ByteBuffer(int[] dimv, LispObject initialContents) { this(dimv, initialContents, false); } public SimpleArray_ByteBuffer(int[] dimv, LispObject initialContents, boolean directAllocation) { this.dimv = dimv; final int rank = dimv.length; this.directAllocation = directAllocation; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); if (directAllocation) { data = ByteBuffer.allocateDirect(totalSize); } else { data = ByteBuffer.allocate(totalSize); } setInitialContents(0, dimv, initialContents, 0); } public SimpleArray_ByteBuffer(int rank, LispObject initialContents) { this(rank, initialContents, false); } public SimpleArray_ByteBuffer(int rank, LispObject initialContents, boolean directAllocation) { if (rank < 2) { Debug.assertTrue(false); } dimv = new int[rank]; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); if (rest == NIL || rest.length() == 0) break; rest = rest.elt(0); } totalSize = computeTotalSize(dimv); if (directAllocation) { data = ByteBuffer.allocateDirect(totalSize); } else { data = ByteBuffer.allocate(totalSize); } setInitialContents(0, dimv, initialContents, 0); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data.put(index, coerceToJavaByte(contents)); } catch (IndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_8, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_ARRAY; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SIMPLE_ARRAY) return T; if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(typeSpecifier); } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_8; } @Override public int getTotalSize() { return totalSize; } @Override public boolean isAdjustable() { return false; } @Override public LispObject AREF(int index) { try { return coerceFromJavaByte(data.get(index)); } catch (IndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } @Override public void aset(int index, LispObject newValue) { try { data.put(index, coerceToJavaByte(newValue)); } catch (IndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } @Override public int getRowMajorIndex(int[] subscripts) { final int rank = dimv.length; if (rank != subscripts.length) { StringBuffer sb = new StringBuffer("Wrong number of subscripts ("); sb.append(subscripts.length); sb.append(") for array of rank "); sb.append(rank); sb.append('.'); program_error(sb.toString()); } int sum = 0; int size = 1; for (int i = rank; i-- > 0;) { final int dim = dimv[i]; final int lastSize = size; size *= dim; int n = subscripts[i]; if (n < 0 || n >= dim) { StringBuffer sb = new StringBuffer("Invalid index "); sb.append(n); sb.append(" for array "); sb.append(this); sb.append('.'); program_error(sb.toString()); } sum += n * lastSize; } return sum; } @Override public LispObject get(int[] subscripts) { try { return coerceFromJavaByte(data.get(getRowMajorIndex(subscripts))); } catch (IndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void set(int[] subscripts, LispObject newValue) { try { data.put(getRowMajorIndex(subscripts),coerceToJavaByte(newValue)); } catch (IndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 255) { type_error(obj, UNSIGNED_BYTE_8); // Not reached. return; } for (int i = totalSize; i-- > 0;) data.put(i, (byte) n); } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } return printObject(dimv); } public AbstractArray adjustArray(int[] dimv, LispObject initialElement, LispObject initialContents) { if (initialContents != null) return new SimpleArray_ByteBuffer(dimv, initialContents); for (int i = 0; i < dimv.length; i++) { if (dimv[i] != this.dimv[i]) { SimpleArray_ByteBuffer newArray = new SimpleArray_ByteBuffer(dimv); if (initialElement != null) newArray.fill(initialElement); copyArray(this, newArray); return newArray; } } // New dimensions are identical to old dimensions. return this; } // Copy a1 to a2 for index tuples that are valid for both arrays. static void copyArray(AbstractArray a1, AbstractArray a2) { Debug.assertTrue(a1.getRank() == a2.getRank()); int[] subscripts = new int[a1.getRank()]; int axis = 0; copySubArray(a1, a2, subscripts, axis); } private static void copySubArray(AbstractArray a1, AbstractArray a2, int[] subscripts, int axis) { if (axis < subscripts.length) { final int limit = Math.min(a1.getDimension(axis), a2.getDimension(axis)); for (int i = 0; i < limit; i++) { subscripts[axis] = i; copySubArray(a1, a2, subscripts, axis + 1); } } else { int i1 = a1.getRowMajorIndex(subscripts); int i2 = a2.getRowMajorIndex(subscripts); a2.aset(i2, a1.AREF(i1)); } } public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo, int displacement) { return new ComplexArray(dimv, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleArray_CharBuffer.java0100644 0000000 0000000 00000025135 14202767264 023407 0ustar000000000 0000000 /* * SimpleArray_CharBuffer.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; import java.nio.CharBuffer; public final class SimpleArray_CharBuffer extends AbstractArray { private final int[] dimv; private final int totalSize; final CharBuffer data; boolean directAllocation; public SimpleArray_CharBuffer(int[] dimv) { this(dimv, false); } public SimpleArray_CharBuffer(int[] dimv, boolean directAllocation) { this.dimv = dimv; totalSize = computeTotalSize(dimv); this.directAllocation = directAllocation; if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(totalSize * 2); data = b.asCharBuffer(); } else { data = CharBuffer.allocate(totalSize); } } public SimpleArray_CharBuffer(int[] dimv, LispObject initialContents) { this(dimv, initialContents, false); } public SimpleArray_CharBuffer(int[] dimv, LispObject initialContents, boolean directAllocation) { this.dimv = dimv; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } this.directAllocation = directAllocation; totalSize = computeTotalSize(dimv); if (directAllocation) { ByteBuffer b = ByteBuffer.allocate(totalSize * 2); data = b.asCharBuffer(); } else { data = CharBuffer.allocate(totalSize); } setInitialContents(0, dimv, initialContents, 0); } public SimpleArray_CharBuffer(int rank, LispObject initialContents) { this(rank, initialContents, false); } public SimpleArray_CharBuffer(int rank, LispObject initialContents, boolean directAllocation) { if (rank < 2) { Debug.assertTrue(false); } dimv = new int[rank]; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); if (rest == NIL || rest.length() == 0) { break; } rest = rest.elt(0); } this.directAllocation = directAllocation; totalSize = computeTotalSize(dimv); if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(totalSize * 2); data = b.asCharBuffer(); } else { data = CharBuffer.allocate(totalSize); } setInitialContents(0, dimv, initialContents, 0); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data.put(index, coerceToJavaChar(contents)); } catch (IndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) { newDims[i-1] = dims[i]; } if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_16, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_ARRAY; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SIMPLE_ARRAY) return T; if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(typeSpecifier); } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) { result = new Cons(Fixnum.getInstance(dimv[i]), result); } return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_16; } @Override public int getTotalSize() { return totalSize; } @Override public boolean isAdjustable() { return false; } @Override public int aref(int index) { try { return data.get(index); } catch (IndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); // Not reached. return 0; } } @Override public LispObject AREF(int index) { try { return Fixnum.getInstance(data.get(index)); } catch (IndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } @Override public void aset(int index, LispObject obj) { try { data.put(index, (char)Fixnum.getValue(obj)); } catch (IndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } @Override public int getRowMajorIndex(int[] subscripts) { final int rank = dimv.length; if (rank != subscripts.length) { StringBuffer sb = new StringBuffer("Wrong number of subscripts ("); sb.append(subscripts.length); sb.append(") for array of rank "); sb.append(rank); sb.append('.'); program_error(sb.toString()); } int sum = 0; int size = 1; for (int i = rank; i-- > 0;) { final int dim = dimv[i]; final int lastSize = size; size *= dim; int n = subscripts[i]; if (n < 0 || n >= dim) { StringBuffer sb = new StringBuffer("Invalid index "); sb.append(n); sb.append(" for array "); sb.append(this); sb.append('.'); program_error(sb.toString()); } sum += n * lastSize; } return sum; } @Override public LispObject get(int[] subscripts) { try { return Fixnum.getInstance(data.get(getRowMajorIndex(subscripts))); } catch (IndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void set(int[] subscripts, LispObject obj) { try { data.put(getRowMajorIndex(subscripts), (char) Fixnum.getValue(obj)); } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 65535) { type_error(obj, UNSIGNED_BYTE_16); // Not reached. return; } for (int i = totalSize; i-- > 0;) { data.put(i, (char)n); } } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } return printObject(dimv); } public AbstractArray adjustArray(int[] dimv, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { return new SimpleArray_CharBuffer(dimv, initialContents); } for (int i = 0; i < dimv.length; i++) { if (dimv[i] != this.dimv[i]) { SimpleArray_CharBuffer newArray = new SimpleArray_CharBuffer(dimv); if (initialElement != null) { newArray.fill(initialElement); } copyArray(this, newArray); return newArray; } } // New dimensions are identical to old dimensions. return this; } // Copy a1 to a2 for index tuples that are valid for both arrays. private static void copyArray(AbstractArray a1, AbstractArray a2) { Debug.assertTrue(a1.getRank() == a2.getRank()); int[] subscripts = new int[a1.getRank()]; int axis = 0; copySubArray(a1, a2, subscripts, axis); } private static void copySubArray(AbstractArray a1, AbstractArray a2, int[] subscripts, int axis) { if (axis < subscripts.length) { final int limit = Math.min(a1.getDimension(axis), a2.getDimension(axis)); for (int i = 0; i < limit; i++) { subscripts[axis] = i; copySubArray(a1, a2, subscripts, axis + 1); } } else { int i1 = a1.getRowMajorIndex(subscripts); int i2 = a2.getRowMajorIndex(subscripts); a2.aset(i2, a1.AREF(i1)); } } public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo, int displacement) { return new ComplexArray(dimv, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleArray_IntBuffer.java0100644 0000000 0000000 00000025273 14202767264 023267 0ustar000000000 0000000 /* * SimpleArray_IntBuffer.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.nio.ByteBuffer; import java.nio.IntBuffer; public final class SimpleArray_IntBuffer extends AbstractArray { private final int[] dimv; private final int totalSize; final IntBuffer data; private boolean directAllocation; public SimpleArray_IntBuffer(int[] dimv) { this(dimv, false); } public SimpleArray_IntBuffer(int [] dimv, boolean directAllocation) { this.dimv = dimv; this.directAllocation = directAllocation; totalSize = computeTotalSize(dimv); if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(totalSize * 4); data = b.asIntBuffer(); } else { data = IntBuffer.allocate(totalSize); } } public SimpleArray_IntBuffer(int[] dimv, LispObject initialContents) { this(dimv, initialContents, false); } public SimpleArray_IntBuffer(int[] dimv, LispObject initialContents, boolean directAllocation) { this.dimv = dimv; final int rank = dimv.length; this.directAllocation = directAllocation; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(totalSize * 4); data = b.asIntBuffer(); } else { data = IntBuffer.allocate(totalSize); } setInitialContents(0, dimv, initialContents, 0); } public SimpleArray_IntBuffer(int rank, LispObject initialContents) { this(rank, initialContents, false); } public SimpleArray_IntBuffer(int rank, LispObject initialContents, boolean directAllocation) { if (rank < 2) { Debug.assertTrue(false); } dimv = new int[rank]; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); if (rest == NIL || rest.length() == 0) break; rest = rest.elt(0); } totalSize = computeTotalSize(dimv); if (directAllocation) { ByteBuffer b = ByteBuffer.allocateDirect(totalSize * 4); data = b.asIntBuffer(); } else { data = IntBuffer.allocate(totalSize); } setInitialContents(0, dimv, initialContents, 0); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data.put(index, (int)(contents.longValue() & 0xffffffffL)); } catch (IndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_32, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_ARRAY; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SIMPLE_ARRAY) return T; if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(typeSpecifier); } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_32; } @Override public int getTotalSize() { return totalSize; } @Override public boolean isAdjustable() { return false; } @Override public LispObject AREF(int index) { try { return number(((long)data.get(index)) & 0xffffffffL); } catch (IndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } @Override public void aset(int index, LispObject newValue) { try { if (newValue.isLessThan(Fixnum.ZERO) || newValue.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(newValue, UNSIGNED_BYTE_32); } data.put(index, (int)(newValue.longValue() & 0xffffffffL)); } catch (IndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } @Override public int getRowMajorIndex(int[] subscripts) { final int rank = dimv.length; if (rank != subscripts.length) { StringBuffer sb = new StringBuffer("Wrong number of subscripts ("); sb.append(subscripts.length); sb.append(") for array of rank "); sb.append(rank); sb.append('.'); program_error(sb.toString()); } int sum = 0; int size = 1; for (int i = rank; i-- > 0;) { final int dim = dimv[i]; final int lastSize = size; size *= dim; int n = subscripts[i]; if (n < 0 || n >= dim) { StringBuffer sb = new StringBuffer("Invalid index "); sb.append(n); sb.append(" for array "); sb.append(this); sb.append('.'); program_error(sb.toString()); } sum += n * lastSize; } return sum; } @Override public LispObject get(int[] subscripts) { try { return number(((long)data.get(getRowMajorIndex(subscripts))) & 0xffffffffL); } catch (IndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void set(int[] subscripts, LispObject newValue) { try { if (newValue.isLessThan(Fixnum.ZERO) || newValue.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(newValue, UNSIGNED_BYTE_32); } data.put(getRowMajorIndex(subscripts), (int)(newValue.longValue() & 0xffffffffL)); } catch (IndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof LispInteger)) { type_error(obj, Symbol.INTEGER); // Not reached. return; } if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(obj, UNSIGNED_BYTE_32); } for (int i = totalSize; i-- > 0;) data.put(i, (int) (obj.longValue() & 0xffffffffL));; } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } return printObject(dimv); } public AbstractArray adjustArray(int[] dimv, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { return new SimpleArray_IntBuffer(dimv, initialContents); } for (int i = 0; i < dimv.length; i++) { if (dimv[i] != this.dimv[i]) { SimpleArray_IntBuffer newArray = new SimpleArray_IntBuffer(dimv, directAllocation); if (initialElement != null) { newArray.fill(initialElement); } copyArray(this, newArray); return newArray; } } // New dimensions are identical to old dimensions. return this; } // Copy a1 to a2 for index tuples that are valid for both arrays. static void copyArray(AbstractArray a1, AbstractArray a2) { Debug.assertTrue(a1.getRank() == a2.getRank()); int[] subscripts = new int[a1.getRank()]; int axis = 0; copySubArray(a1, a2, subscripts, axis); } private static void copySubArray(AbstractArray a1, AbstractArray a2, int[] subscripts, int axis) { if (axis < subscripts.length) { final int limit = Math.min(a1.getDimension(axis), a2.getDimension(axis)); for (int i = 0; i < limit; i++) { subscripts[axis] = i; copySubArray(a1, a2, subscripts, axis + 1); } } else { int i1 = a1.getRowMajorIndex(subscripts); int i2 = a2.getRowMajorIndex(subscripts); a2.aset(i2, a1.AREF(i1)); } } public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo, int displacement) { return new ComplexArray(dimv, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleArray_T.java0100644 0000000 0000000 00000023772 14202767264 021610 0ustar000000000 0000000 /* * SimpleArray_T.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SimpleArray_T extends AbstractArray { private final int[] dimv; private final LispObject elementType; private final int totalSize; final LispObject[] data; public SimpleArray_T(int[] dimv, LispObject elementType) { this.dimv = dimv; this.elementType = elementType; totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; for (int i = totalSize; i-- > 0;) data[i] = Fixnum.ZERO; } public SimpleArray_T(int[] dimv, LispObject elementType, LispObject initialContents) { this.dimv = dimv; this.elementType = elementType; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; setInitialContents(0, dimv, initialContents, 0); } public SimpleArray_T(int rank, LispObject initialContents) { if (rank < 2) Debug.assertTrue(false); dimv = new int[rank]; this.elementType = T; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); if (rest == NIL || rest.length() == 0) break; rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; setInitialContents(0, dimv, initialContents, 0); } public SimpleArray_T(final int[] dimv, final LispObject[] initialData, final LispObject elementType) { this.dimv = dimv; this.elementType = elementType; this.data = initialData; this.totalSize = computeTotalSize(dimv); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data[index] = contents; } catch (ArrayIndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, elementType, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_ARRAY; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SIMPLE_ARRAY) return T; if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(typeSpecifier); } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return elementType; } @Override public int getTotalSize() { return totalSize; } @Override public boolean isAdjustable() { return false; } @Override public LispObject AREF(int index) { try { return data[index]; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } @Override public void aset(int index, LispObject newValue) { try { data[index] = newValue; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } @Override public int getRowMajorIndex(int[] subscripts) { final int rank = dimv.length; if (rank != subscripts.length) { StringBuilder sb = new StringBuilder("Wrong number of subscripts ("); sb.append(subscripts.length); sb.append(") for array of rank "); sb.append(rank); sb.append('.'); program_error(sb.toString()); } int sum = 0; int size = 1; for (int i = rank; i-- > 0;) { final int dim = dimv[i]; final int lastSize = size; size *= dim; int n = subscripts[i]; if (n < 0 || n >= dim) { StringBuilder sb = new StringBuilder("Invalid index "); sb.append(n); sb.append(" for array "); sb.append(this); sb.append('.'); program_error(sb.toString()); } sum += n * lastSize; } return sum; } @Override public LispObject get(int[] subscripts) { try { return data[getRowMajorIndex(subscripts)]; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void set(int[] subscripts, LispObject newValue) { try { data[getRowMajorIndex(subscripts)] = newValue; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void fill(LispObject obj) { for (int i = totalSize; i-- > 0;) data[i] = obj; } @Override public String printObject() { return printObject(dimv); } @Override public AbstractArray adjustArray(int[] dimv, LispObject initialElement, LispObject initialContents) { if (initialContents != null) return new SimpleArray_T(dimv, elementType, initialContents); for (int i = 0; i < dimv.length; i++) { if (dimv[i] != this.dimv[i]) { SimpleArray_T newArray = new SimpleArray_T(dimv, elementType); if (initialElement != null) newArray.fill(initialElement); copyArray(this, newArray); return newArray; } } // New dimensions are identical to old dimensions, yet // we're not mutable, so, we need to return a new array return new SimpleArray_T(dimv, data.clone(), elementType); } // Copy a1 to a2 for index tuples that are valid for both arrays. static void copyArray(AbstractArray a1, AbstractArray a2) { Debug.assertTrue(a1.getRank() == a2.getRank()); int[] subscripts = new int[a1.getRank()]; int axis = 0; copySubArray(a1, a2, subscripts, axis); } private static void copySubArray(AbstractArray a1, AbstractArray a2, int[] subscripts, int axis) { if (axis < subscripts.length) { final int limit = Math.min(a1.getDimension(axis), a2.getDimension(axis)); for (int i = 0; i < limit; i++) { subscripts[axis] = i; copySubArray(a1, a2, subscripts, axis + 1); } } else { int i1 = a1.getRowMajorIndex(subscripts); int i2 = a2.getRowMajorIndex(subscripts); a2.aset(i2, a1.AREF(i1)); } } @Override public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo, int displacement) { return new ComplexArray(dimv, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleArray_UnsignedByte16.java0100644 0000000 0000000 00000025570 14202767264 024152 0ustar000000000 0000000 /* * SimpleArray_UnsignedByte16.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SimpleArray_UnsignedByte16 extends AbstractArray { private final int[] dimv; private final int totalSize; private final int[] data; public SimpleArray_UnsignedByte16(int[] dimv) { this.dimv = dimv; totalSize = computeTotalSize(dimv); data = new int[totalSize]; } public SimpleArray_UnsignedByte16(int[] dimv, LispObject initialContents) { this.dimv = dimv; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new int[totalSize]; setInitialContents(0, dimv, initialContents, 0); } public SimpleArray_UnsignedByte16(int rank, LispObject initialContents) { if (rank < 2) Debug.assertTrue(false); dimv = new int[rank]; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); if (rest == NIL || rest.length() == 0) break; rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new int[totalSize]; setInitialContents(0, dimv, initialContents, 0); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data[index] = coerceToJavaByte(contents); // This has to be wrong! } catch (ArrayIndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_16, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_ARRAY; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SIMPLE_ARRAY) return T; if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(typeSpecifier); } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_16; } @Override public int getTotalSize() { return totalSize; } @Override public boolean isAdjustable() { return false; } @Override public int aref(int index) { try { return data[index]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); // Not reached. return 0; } } @Override public LispObject AREF(int index) { try { return Fixnum.getInstance(data[index]); } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } @Override public void aset(int index, LispObject obj) { try { data[index] = Fixnum.getValue(obj); } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } @Override public int getRowMajorIndex(int[] subscripts) { final int rank = dimv.length; if (rank != subscripts.length) { StringBuffer sb = new StringBuffer("Wrong number of subscripts ("); sb.append(subscripts.length); sb.append(") for array of rank "); sb.append(rank); sb.append('.'); program_error(sb.toString()); } int sum = 0; int size = 1; for (int i = rank; i-- > 0;) { final int dim = dimv[i]; final int lastSize = size; size *= dim; int n = subscripts[i]; if (n < 0 || n >= dim) { StringBuffer sb = new StringBuffer("Invalid index "); sb.append(n); sb.append(" for array "); sb.append(this); sb.append('.'); program_error(sb.toString()); } sum += n * lastSize; } return sum; } @Override public LispObject get(int[] subscripts) { try { return Fixnum.getInstance(data[getRowMajorIndex(subscripts)]); } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void set(int[] subscripts, LispObject obj) { try { data[getRowMajorIndex(subscripts)] = Fixnum.getValue(obj); } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 65535) { type_error(obj, UNSIGNED_BYTE_16); // Not reached. return; } for (int i = totalSize; i-- > 0;) data[i] = n; } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } return printObject(dimv); } public AbstractArray adjustArray(int[] dimv, LispObject initialElement, LispObject initialContents) { if (initialContents != null) return new SimpleArray_UnsignedByte16(dimv, initialContents); for (int i = 0; i < dimv.length; i++) { if (dimv[i] != this.dimv[i]) { SimpleArray_UnsignedByte16 newArray = new SimpleArray_UnsignedByte16(dimv); if (initialElement != null) newArray.fill(initialElement); copyArray(this, newArray); return newArray; } } // New dimensions are identical to old dimensions. return this; } // Copy a1 to a2 for index tuples that are valid for both arrays. private static void copyArray(AbstractArray a1, AbstractArray a2) { Debug.assertTrue(a1.getRank() == a2.getRank()); int[] subscripts = new int[a1.getRank()]; int axis = 0; copySubArray(a1, a2, subscripts, axis); } private static void copySubArray(AbstractArray a1, AbstractArray a2, int[] subscripts, int axis) { if (axis < subscripts.length) { final int limit = Math.min(a1.getDimension(axis), a2.getDimension(axis)); for (int i = 0; i < limit; i++) { subscripts[axis] = i; copySubArray(a1, a2, subscripts, axis + 1); } } else { int i1 = a1.getRowMajorIndex(subscripts); int i2 = a2.getRowMajorIndex(subscripts); a2.aset(i2, a1.AREF(i1)); } } public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo, int displacement) { return new ComplexArray(dimv, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleArray_UnsignedByte32.java0100644 0000000 0000000 00000026646 14202767264 024155 0ustar000000000 0000000 /* * SimpleArray_UnsignedByte32.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; /* N.b. this implementation has problems somewhere with converting bytes Not fixing currently, as this type is unused with NIO (let* ((unspecialized #(2025373960 3099658457 3238582529 148439321 3099658456 3238582528 3000000000 1000000000 2000000000 2900000000 2400000000 2800000000 0 1)) (array (make-array (length unspecialized) :element-type '(unsigned-byte 32) :initial-contents unspecialized))) (prove:plan (length array)) (loop :for i :below (length array) :doing (let ((x0 (elt unspecialized i)) (x1 (elt array i))) (prove:ok (equal x0 x1) (format nil "~a: ~a equals ~a" i x0 x1))))) */ public final class SimpleArray_UnsignedByte32 extends AbstractArray { private final int[] dimv; private final int totalSize; // FIXME We should really use an array of unboxed values! final LispObject[] data; public SimpleArray_UnsignedByte32(int[] dimv) { this.dimv = dimv; totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; for (int i = totalSize; i-- > 0;) data[i] = Fixnum.ZERO; } public SimpleArray_UnsignedByte32(int[] dimv, LispObject initialContents) { this.dimv = dimv; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; setInitialContents(0, dimv, initialContents, 0); } public SimpleArray_UnsignedByte32(int rank, LispObject initialContents) { if (rank < 2) Debug.assertTrue(false); dimv = new int[rank]; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); if (rest == NIL || rest.length() == 0) break; rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new LispObject[totalSize]; setInitialContents(0, dimv, initialContents, 0); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data[index] = contents; } catch (ArrayIndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_32, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_ARRAY; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SIMPLE_ARRAY) return T; if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(typeSpecifier); } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_32; } @Override public int getTotalSize() { return totalSize; } @Override public boolean isAdjustable() { return false; } @Override public LispObject AREF(int index) { try { return data[index]; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } @Override public void aset(int index, LispObject newValue) { try { data[index] = newValue; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } @Override public int getRowMajorIndex(int[] subscripts) { final int rank = dimv.length; if (rank != subscripts.length) { StringBuffer sb = new StringBuffer("Wrong number of subscripts ("); sb.append(subscripts.length); sb.append(") for array of rank "); sb.append(rank); sb.append('.'); program_error(sb.toString()); } int sum = 0; int size = 1; for (int i = rank; i-- > 0;) { final int dim = dimv[i]; final int lastSize = size; size *= dim; int n = subscripts[i]; if (n < 0 || n >= dim) { StringBuffer sb = new StringBuffer("Invalid index "); sb.append(n); sb.append(" for array "); sb.append(this); sb.append('.'); program_error(sb.toString()); } sum += n * lastSize; } return sum; } @Override public LispObject get(int[] subscripts) { try { return data[getRowMajorIndex(subscripts)]; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void set(int[] subscripts, LispObject newValue) { try { data[getRowMajorIndex(subscripts)] = newValue; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof LispInteger)) { type_error(obj, Symbol.INTEGER); // Not reached. return; } if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { type_error(obj, UNSIGNED_BYTE_32); } for (int i = totalSize; i-- > 0;) data[i] = obj; } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } return printObject(dimv); } public AbstractArray adjustArray(int[] dimv, LispObject initialElement, LispObject initialContents) { if (initialContents != null) return new SimpleArray_UnsignedByte32(dimv, initialContents); for (int i = 0; i < dimv.length; i++) { if (dimv[i] != this.dimv[i]) { SimpleArray_UnsignedByte32 newArray = new SimpleArray_UnsignedByte32(dimv); if (initialElement != null) newArray.fill(initialElement); copyArray(this, newArray); return newArray; } } // New dimensions are identical to old dimensions. return this; } // Copy a1 to a2 for index tuples that are valid for both arrays. static void copyArray(AbstractArray a1, AbstractArray a2) { Debug.assertTrue(a1.getRank() == a2.getRank()); int[] subscripts = new int[a1.getRank()]; int axis = 0; copySubArray(a1, a2, subscripts, axis); } private static void copySubArray(AbstractArray a1, AbstractArray a2, int[] subscripts, int axis) { if (axis < subscripts.length) { final int limit = Math.min(a1.getDimension(axis), a2.getDimension(axis)); for (int i = 0; i < limit; i++) { subscripts[axis] = i; copySubArray(a1, a2, subscripts, axis + 1); } } else { int i1 = a1.getRowMajorIndex(subscripts); int i2 = a2.getRowMajorIndex(subscripts); a2.aset(i2, a1.AREF(i1)); } } public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo, int displacement) { return new ComplexArray(dimv, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleArray_UnsignedByte8.java0100644 0000000 0000000 00000025074 14202767264 024072 0ustar000000000 0000000 /* * SimpleArray_UnsignedByte8.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SimpleArray_UnsignedByte8 extends AbstractArray { private final int[] dimv; private final int totalSize; final byte[] data; public SimpleArray_UnsignedByte8(int[] dimv) { this.dimv = dimv; totalSize = computeTotalSize(dimv); data = new byte[totalSize]; } public SimpleArray_UnsignedByte8(int[] dimv, LispObject initialContents) { this.dimv = dimv; final int rank = dimv.length; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new byte[totalSize]; setInitialContents(0, dimv, initialContents, 0); } public SimpleArray_UnsignedByte8(int rank, LispObject initialContents) { if (rank < 2) Debug.assertTrue(false); dimv = new int[rank]; LispObject rest = initialContents; for (int i = 0; i < rank; i++) { dimv[i] = rest.length(); if (rest == NIL || rest.length() == 0) break; rest = rest.elt(0); } totalSize = computeTotalSize(dimv); data = new byte[totalSize]; setInitialContents(0, dimv, initialContents, 0); } private int setInitialContents(int axis, int[] dims, LispObject contents, int index) { if (dims.length == 0) { try { data[index] = coerceToJavaByte(contents); } catch (ArrayIndexOutOfBoundsException e) { error(new LispError("Bad initial contents for array.")); return -1; } ++index; } else { int dim = dims[0]; if (dim != contents.length()) { error(new LispError("Bad initial contents for array.")); return -1; } int[] newDims = new int[dims.length-1]; for (int i = 1; i < dims.length; i++) newDims[i-1] = dims[i]; if (contents.listp()) { for (int i = contents.length();i-- > 0;) { LispObject content = contents.car(); index = setInitialContents(axis + 1, newDims, content, index); contents = contents.cdr(); } } else { AbstractVector v = checkVector(contents); final int length = v.length(); for (int i = 0; i < length; i++) { LispObject content = v.AREF(i); index = setInitialContents(axis + 1, newDims, content, index); } } } return index; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_8, getDimensions()); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_ARRAY; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SIMPLE_ARRAY) return T; if (typeSpecifier == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(typeSpecifier); } @Override public int getRank() { return dimv.length; } @Override public LispObject getDimensions() { LispObject result = NIL; for (int i = dimv.length; i-- > 0;) result = new Cons(Fixnum.getInstance(dimv[i]), result); return result; } @Override public int getDimension(int n) { try { return dimv[n]; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad array dimension " + n + ".")); return -1; } } @Override public LispObject getElementType() { return UNSIGNED_BYTE_8; } @Override public int getTotalSize() { return totalSize; } @Override public boolean isAdjustable() { return false; } @Override public LispObject AREF(int index) { try { return coerceFromJavaByte(data[index]); } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + index + ".")); } } @Override public void aset(int index, LispObject newValue) { try { data[index] = coerceToJavaByte(newValue); } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + index + ".")); } } @Override public int getRowMajorIndex(int[] subscripts) { final int rank = dimv.length; if (rank != subscripts.length) { StringBuffer sb = new StringBuffer("Wrong number of subscripts ("); sb.append(subscripts.length); sb.append(") for array of rank "); sb.append(rank); sb.append('.'); program_error(sb.toString()); } int sum = 0; int size = 1; for (int i = rank; i-- > 0;) { final int dim = dimv[i]; final int lastSize = size; size *= dim; int n = subscripts[i]; if (n < 0 || n >= dim) { StringBuffer sb = new StringBuffer("Invalid index "); sb.append(n); sb.append(" for array "); sb.append(this); sb.append('.'); program_error(sb.toString()); } sum += n * lastSize; } return sum; } @Override public LispObject get(int[] subscripts) { try { return coerceFromJavaByte(data[getRowMajorIndex(subscripts)]); } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void set(int[] subscripts, LispObject newValue) { try { data[getRowMajorIndex(subscripts)] = coerceToJavaByte(newValue); } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Bad row major index " + getRowMajorIndex(subscripts) + ".")); } } @Override public void fill(LispObject obj) { if (!(obj instanceof Fixnum)) { type_error(obj, Symbol.FIXNUM); // Not reached. return; } int n = ((Fixnum) obj).value; if (n < 0 || n > 255) { type_error(obj, UNSIGNED_BYTE_8); // Not reached. return; } for (int i = totalSize; i-- > 0;) data[i] = (byte) n; } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue() != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } return printObject(dimv); } public AbstractArray adjustArray(int[] dimv, LispObject initialElement, LispObject initialContents) { if (initialContents != null) return new SimpleArray_UnsignedByte8(dimv, initialContents); for (int i = 0; i < dimv.length; i++) { if (dimv[i] != this.dimv[i]) { SimpleArray_UnsignedByte8 newArray = new SimpleArray_UnsignedByte8(dimv); if (initialElement != null) newArray.fill(initialElement); copyArray(this, newArray); return newArray; } } // New dimensions are identical to old dimensions. return this; } // Copy a1 to a2 for index tuples that are valid for both arrays. static void copyArray(AbstractArray a1, AbstractArray a2) { Debug.assertTrue(a1.getRank() == a2.getRank()); int[] subscripts = new int[a1.getRank()]; int axis = 0; copySubArray(a1, a2, subscripts, axis); } private static void copySubArray(AbstractArray a1, AbstractArray a2, int[] subscripts, int axis) { if (axis < subscripts.length) { final int limit = Math.min(a1.getDimension(axis), a2.getDimension(axis)); for (int i = 0; i < limit; i++) { subscripts[axis] = i; copySubArray(a1, a2, subscripts, axis + 1); } } else { int i1 = a1.getRowMajorIndex(subscripts); int i2 = a2.getRowMajorIndex(subscripts); a2.aset(i2, a1.AREF(i1)); } } public AbstractArray adjustArray(int[] dimv, AbstractArray displacedTo, int displacement) { return new ComplexArray(dimv, displacedTo, displacement); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleBitVector.java0100644 0000000 0000000 00000040343 14202767264 022141 0ustar000000000 0000000 /* * SimpleBitVector.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // "The type of a bit vector that is not displaced to another array, has no // fill pointer, and is not expressly adjustable is a subtype of type SIMPLE- // BIT-VECTOR." public final class SimpleBitVector extends AbstractBitVector { public SimpleBitVector(int capacity) { this.capacity = capacity; int size = capacity >>> 6; // 64 bits in a long // If the capacity is not an integral multiple of 64, we'll need one // more long. if ((capacity & LONG_MASK) != 0) ++size; bits = new long[size]; } public SimpleBitVector(String s) { this(s.length()); for (int i = capacity; i-- > 0;) { char c = s.charAt(i); if (c == '0') { } else if (c == '1') setBit(i); else Debug.assertTrue(false); } } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_BIT_VECTOR, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_BIT_VECTOR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_BIT_VECTOR) return T; if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_BIT_VECTOR) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public boolean isSimpleVector() { return true; } @Override public int length() { return capacity; } @Override public LispObject elt(int index) { if (index < 0 || index >= length()) badIndex(index, length()); int offset = index >> 6; // Divide by 64. return (bits[offset] & (1L << (index & LONG_MASK))) != 0 ? Fixnum.ONE : Fixnum.ZERO; } @Override public LispObject AREF(int index) { if (index < 0 || index >= capacity) badIndex(index, capacity); int offset = index >> 6; return (bits[offset] & (1L << (index & LONG_MASK))) != 0 ? Fixnum.ONE : Fixnum.ZERO; } @Override public void aset(int index, LispObject newValue) { if (index < 0 || index >= capacity) badIndex(index, capacity); final int offset = index >> 6; if (newValue instanceof Fixnum) { switch (((Fixnum)newValue).value) { case 0: bits[offset] &= ~(1L << (index & LONG_MASK)); return; case 1: bits[offset] |= 1L << (index & LONG_MASK); return; } } // Fall through... type_error(newValue, Symbol.BIT); } @Override protected int getBit(int index) { int offset = index >> 6; return (bits[offset] & (1L << (index & LONG_MASK))) != 0 ? 1 : 0; } @Override protected void setBit(int index) { int offset = index >> 6; bits[offset] |= 1L << (index & LONG_MASK); } @Override protected void clearBit(int index) { int offset = index >> 6; bits[offset] &= ~(1L << (index & LONG_MASK)); } @Override public void shrink(int n) { if (n < capacity) { int size = n >>> 6; if ((n & LONG_MASK) != 0) ++size; if (size < bits.length) { long[] newbits = new long[size]; System.arraycopy(bits, 0, newbits, 0, size); bits = newbits; } capacity = n; return; } if (n == capacity) return; error(new LispError()); } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { SimpleBitVector v = new SimpleBitVector(newCapacity); if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { v.aset(i, list.car()); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) v.aset(i, initialContents.elt(i)); } else type_error(initialContents, Symbol.SEQUENCE); return v; } if (capacity != newCapacity) { SimpleBitVector v = new SimpleBitVector(newCapacity); final int limit = Math.min(capacity, newCapacity); for (int i = limit; i-- > 0;) { if (getBit(i) == 1) v.setBit(i); else v.clearBit(i); } if (initialElement != null && capacity < newCapacity) { int n = Fixnum.getValue(initialElement); if (n == 1) for (int i = capacity; i < newCapacity; i++) v.setBit(i); else for (int i = capacity; i < newCapacity; i++) v.clearBit(i); } return v; } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexBitVector(newCapacity, displacedTo, displacement); } SimpleBitVector and(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = bits[i] & v.bits[i]; return result; } SimpleBitVector ior(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = bits[i] | v.bits[i]; return result; } SimpleBitVector xor(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = bits[i] ^ v.bits[i]; return result; } SimpleBitVector eqv(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = ~(bits[i] ^ v.bits[i]); return result; } SimpleBitVector nand(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = ~(bits[i] & v.bits[i]); return result; } SimpleBitVector nor(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = ~(bits[i] | v.bits[i]); return result; } SimpleBitVector andc1(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = ~bits[i] & v.bits[i]; return result; } SimpleBitVector andc2(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = bits[i] & ~v.bits[i]; return result; } SimpleBitVector orc1(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = ~bits[i] | v.bits[i]; return result; } SimpleBitVector orc2(SimpleBitVector v, SimpleBitVector result) { if (result == null) result = new SimpleBitVector(capacity); for (int i = bits.length; i-- > 0;) result.bits[i] = bits[i] | ~v.bits[i]; return result; } // ### %simple-bit-vector-bit-and private static final Primitive _SIMPLE_BIT_VECTOR_BIT_AND = new Primitive("%simple-bit-vector-bit-and", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).and((SimpleBitVector)second, ((SimpleBitVector)third)); } }; // ### %simple-bit-vector-bit-ior private static final Primitive _SIMPLE_BIT_VECTOR_BIT_IOR = new Primitive("%simple-bit-vector-bit-ior", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).ior((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-xor private static final Primitive _SIMPLE_BIT_VECTOR_BIT_XOR = new Primitive("%simple-bit-vector-bit-xor", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).xor((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-eqv private static final Primitive _SIMPLE_BIT_VECTOR_BIT_EQV = new Primitive("%simple-bit-vector-bit-eqv", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).eqv((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-nand private static final Primitive _SIMPLE_BIT_VECTOR_BIT_NAND = new Primitive("%simple-bit-vector-bit-nand", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).nand((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-nor private static final Primitive _SIMPLE_BIT_VECTOR_BIT_NOR = new Primitive("%simple-bit-vector-bit-nor", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).nor((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-andc1 private static final Primitive _SIMPLE_BIT_VECTOR_BIT_ANDC1 = new Primitive("%simple-bit-vector-bit-andc1", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).andc1((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-andc2 private static final Primitive _SIMPLE_BIT_VECTOR_BIT_ANDC2 = new Primitive("%simple-bit-vector-bit-andc2", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).andc2((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-orc1 private static final Primitive _SIMPLE_BIT_VECTOR_BIT_ORC1 = new Primitive("%simple-bit-vector-bit-orc1", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).orc1((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-orc2 private static final Primitive _SIMPLE_BIT_VECTOR_BIT_ORC2 = new Primitive("%simple-bit-vector-bit-orc2", PACKAGE_SYS, false, "bit-vector1 bit-vector2 result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return ((SimpleBitVector)first).orc2((SimpleBitVector)second, (SimpleBitVector)third); } }; // ### %simple-bit-vector-bit-not private static final Primitive _SIMPLE_BIT_VECTOR_BIT_NOT = new Primitive("%simple-bit-vector-bit-not", PACKAGE_SYS, false, "bit-vector result-bit-vector") { @Override public LispObject execute(LispObject first, LispObject second) { SimpleBitVector v = (SimpleBitVector) first; SimpleBitVector result = (SimpleBitVector) second; for (int i = v.bits.length; i-- > 0;) result.bits[i] = ~v.bits[i]; return result; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleCondition.java0100644 0000000 0000000 00000006364 14202767264 022173 0ustar000000000 0000000 /* * SimpleCondition.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class SimpleCondition extends Condition { public SimpleCondition() { setFormatControl(NIL); setFormatArguments(NIL); } public SimpleCondition(LispObject formatControl, LispObject formatArguments) { setFormatControl(formatControl); setFormatArguments(formatArguments); } public SimpleCondition(LispObject initArgs) { super(initArgs); } public SimpleCondition(String message) { super(message); } @Override public LispObject typeOf() { return Symbol.SIMPLE_CONDITION; } @Override public LispObject classOf() { return StandardClass.SIMPLE_CONDITION; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_CONDITION) return T; if (type == StandardClass.SIMPLE_CONDITION) return T; return super.typep(type); } // ### simple-condition-format-control private static final Primitive SIMPLE_CONDITION_FORMAT_CONTROL = new Primitive(Symbol.SIMPLE_CONDITION_FORMAT_CONTROL, "condition") { @Override public LispObject execute(LispObject arg) { return Symbol.STD_SLOT_VALUE.execute(arg, Symbol.FORMAT_CONTROL); } }; // ### simple-condition-format-arguments private static final Primitive SIMPLE_CONDITION_FORMAT_ARGUMENTS = new Primitive(Symbol.SIMPLE_CONDITION_FORMAT_ARGUMENTS, "condition") { @Override public LispObject execute(LispObject arg) { return Symbol.STD_SLOT_VALUE.execute(arg, Symbol.FORMAT_ARGUMENTS); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleError.java0100644 0000000 0000000 00000005332 14202767264 021330 0ustar000000000 0000000 /* * SimpleError.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SimpleError extends LispError { public SimpleError(LispObject formatControl, LispObject formatArguments) { super(StandardClass.SIMPLE_ERROR); setFormatControl(formatControl); setFormatArguments(formatArguments); } public SimpleError(LispObject initArgs) { super(StandardClass.SIMPLE_ERROR); initialize(initArgs); } public SimpleError(String message) { super(StandardClass.SIMPLE_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); } @Override public LispObject typeOf() { return Symbol.SIMPLE_ERROR; } @Override public LispObject classOf() { return StandardClass.SIMPLE_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_ERROR) return T; if (type == StandardClass.SIMPLE_ERROR) return T; if (type == Symbol.SIMPLE_CONDITION) return T; if (type == StandardClass.SIMPLE_CONDITION) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleString.java0100644 0000000 0000000 00000031556 14202767264 021514 0ustar000000000 0000000 /* * SimpleString.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SimpleString extends AbstractString { private int capacity; private char[] chars; public SimpleString(LispCharacter c) { chars = new char[1]; chars[0] = c.value; capacity = 1; } public SimpleString(char c) { chars = new char[1]; chars[0] = c; capacity = 1; } public SimpleString(int capacity) { this.capacity = capacity; chars = new char[capacity]; } public SimpleString(String s) { capacity = s.length(); chars = s.toCharArray(); } public SimpleString(StringBuffer sb) { chars = new char[capacity = sb.length()]; sb.getChars(0, capacity, chars, 0); } public SimpleString(StringBuilder sb) { chars = sb.toString().toCharArray(); capacity = chars.length; } public SimpleString(char[] chars) { this.chars = chars; capacity = chars.length; } @Override public char[] chars() { return chars; } @Override public char[] getStringChars() { return chars; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_BASE_STRING, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_BASE_STRING; } @Override public LispObject getDescription() { StringBuilder sb = new StringBuilder("A simple-string ("); sb.append(capacity); sb.append(") \""); sb.append(chars); sb.append('"'); return new SimpleString(sb); } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_STRING) return T; if (type == Symbol.SIMPLE_ARRAY) return T; if (type == Symbol.SIMPLE_BASE_STRING) return T; if (type == BuiltInClass.SIMPLE_STRING) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_BASE_STRING) return T; return super.typep(type); } @Override public LispObject SIMPLE_STRING_P() { return T; } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof SimpleString) { SimpleString string = (SimpleString) obj; if (string.capacity != capacity) return false; for (int i = capacity; i-- > 0;) if (string.chars[i] != chars[i]) return false; return true; } if (obj instanceof AbstractString) { AbstractString string = (AbstractString) obj; if (string.length() != capacity) return false; for (int i = length(); i-- > 0;) if (string.charAt(i) != chars[i]) return false; return true; } if (obj instanceof NilVector) return obj.equal(this); return false; } @Override public boolean equalp(LispObject obj) { if (this == obj) return true; if (obj instanceof SimpleString) { SimpleString string = (SimpleString) obj; if (string.capacity != capacity) return false; for (int i = capacity; i-- > 0;) { if (string.chars[i] != chars[i]) { if (LispCharacter.toLowerCase(string.chars[i]) != LispCharacter.toLowerCase(chars[i])) return false; } } return true; } if (obj instanceof AbstractString) { AbstractString string = (AbstractString) obj; if (string.length() != capacity) return false; for (int i = length(); i-- > 0;) { if (string.charAt(i) != chars[i]) { if (LispCharacter.toLowerCase(string.charAt(i)) != LispCharacter.toLowerCase(chars[i])) return false; } } return true; } if (obj instanceof AbstractBitVector) return false; if (obj instanceof AbstractArray) return obj.equalp(this); return false; } public final SimpleString substring(int start) { return substring(start, capacity); } public final SimpleString substring(int start, int end) { SimpleString s = new SimpleString(end - start); int i = start, j = 0; try { while (i < end) s.chars[j++] = chars[i++]; return s; } catch (ArrayIndexOutOfBoundsException e) { error(new TypeError("Array index out of bounds: " + i)); // Not reached. return null; } } @Override public final LispObject subseq(int start, int end) { return substring(start, end); } @Override public void fill(LispObject obj) { fill(LispCharacter.getValue(obj)); } @Override public void fill(char c) { for (int i = capacity; i-- > 0;) chars[i] = c; } @Override public void shrink(int n) { if (n < capacity) { char[] newArray = new char[n]; System.arraycopy(chars, 0, newArray, 0, n); chars = newArray; capacity = n; return; } if (n == capacity) return; error(new LispError()); } @Override public LispObject reverse() { SimpleString result = new SimpleString(capacity); int i, j; for (i = 0, j = capacity - 1; i < capacity; i++, j--) result.chars[i] = chars[j]; return result; } @Override public LispObject nreverse() { int i = 0; int j = capacity - 1; while (i < j) { char temp = chars[i]; chars[i] = chars[j]; chars[j] = temp; ++i; --j; } return this; } @Override public String getStringValue() { return String.valueOf(chars); } @Override public Object javaInstance() { return String.valueOf(chars); } @Override public Object javaInstance(Class c) { return javaInstance(); } @Override public final int capacity() { return capacity; } @Override public final int length() { return capacity; } @Override public char charAt(int index) { try { return chars[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return 0; // Not reached. } } @Override public void setCharAt(int index, char c) { try { chars[index] = c; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public LispObject elt(int index) { try { return LispCharacter.getInstance(chars[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public LispObject CHAR(int index) { try { return LispCharacter.getInstance(chars[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public LispObject SCHAR(int index) { try { return LispCharacter.getInstance(chars[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public LispObject AREF(int index) { try { return LispCharacter.getInstance(chars[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public void aset(int index, LispObject obj) { try { chars[index] = LispCharacter.getValue(obj); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public int sxhash() { if(capacity == 0) return 0; int hashCode = randomStringHashBase; for (int i = 0; i < capacity; i++) { hashCode += chars[i]; hashCode += (hashCode << 10); hashCode ^= (hashCode >> 6); } hashCode += (hashCode << 3); hashCode ^= (hashCode >> 11); hashCode += (hashCode << 15); return (hashCode & 0x7fffffff); } // For EQUALP hash tables. @Override public int psxhash() { if(capacity == 0) return 0; int hashCode = randomStringHashBase; for (int i = 0; i < capacity; i++) { hashCode += Character.toUpperCase(chars[i]); hashCode += (hashCode << 10); hashCode ^= (hashCode >> 6); } hashCode += (hashCode << 3); hashCode ^= (hashCode >> 11); hashCode += (hashCode << 15); return (hashCode & 0x7fffffff); } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { char[] newChars = new char[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newChars[i] = LispCharacter.getValue(list.car()); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newChars[i] = LispCharacter.getValue(initialContents.elt(i)); } else type_error(initialContents, Symbol.SEQUENCE); return new SimpleString(newChars); } if (capacity != newCapacity) { char[] newChars = new char[newCapacity]; System.arraycopy(chars, 0, newChars, 0, Math.min(newCapacity, capacity)); if (initialElement != null && capacity < newCapacity) { final char c = LispCharacter.getValue(initialElement); for (int i = capacity; i < newCapacity; i++) newChars[i] = c; } return new SimpleString(newChars); } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexString(newCapacity, displacedTo, displacement); } @Override public String toString() { return String.valueOf(chars); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleTypeError.java0100644 0000000 0000000 00000006073 14202767264 022175 0ustar000000000 0000000 /* * SimpleTypeError.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SimpleTypeError extends TypeError { public SimpleTypeError(LispObject initArgs) { super(StandardClass.SIMPLE_TYPE_ERROR); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.SIMPLE_TYPE_ERROR; } @Override public LispObject classOf() { return StandardClass.SIMPLE_TYPE_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_TYPE_ERROR) return T; if (type == StandardClass.SIMPLE_TYPE_ERROR) return T; if (type == Symbol.SIMPLE_CONDITION) return T; if (type == StandardClass.SIMPLE_CONDITION) return T; return super.typep(type); } @Override public String getMessage() { LispObject formatControl = getFormatControl(); if (formatControl != NIL) { LispObject formatArguments = getFormatArguments(); // (apply 'format (append '(nil format-control) format-arguments)) LispObject result = Primitives.APPLY.execute(Symbol.FORMAT, Primitives.APPEND.execute(list(NIL, formatControl), formatArguments)); return result.getStringValue(); } return super.getMessage(); } } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleVector.java0100644 0000000 0000000 00000024512 14202767264 021502 0ustar000000000 0000000 /* * SimpleVector.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // "The type of a vector that is not displaced to another array, has no fill // pointer, is not expressly adjustable and is able to hold elements of any // type is a subtype of type SIMPLE-VECTOR." public final class SimpleVector extends AbstractVector { int capacity; LispObject[] data; public SimpleVector(int capacity) { data = new LispObject[capacity]; for (int i = capacity; i-- > 0;) data[i] = Fixnum.ZERO; this.capacity = capacity; } public SimpleVector(LispObject obj) { if (obj.listp()) { data = obj.copyToArray(); capacity = data.length; } else if (obj instanceof AbstractVector) { capacity = obj.length(); data = new LispObject[capacity]; for (int i = 0; i < capacity; i++) data[i] = obj.elt(i); } else Debug.assertTrue(false); } public SimpleVector(LispObject[] array) { data = array; capacity = array.length; } @Override public LispObject typeOf() { return list(Symbol.SIMPLE_VECTOR, Fixnum.getInstance(capacity)); } @Override public LispObject classOf() { return BuiltInClass.SIMPLE_VECTOR; } @Override public LispObject getDescription() { StringBuffer sb = new StringBuffer("A simple vector with "); sb.append(capacity); sb.append(" elements"); return new SimpleString(sb); } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_VECTOR) return T; if (type == Symbol.SIMPLE_ARRAY) return T; if (type == BuiltInClass.SIMPLE_VECTOR) return T; if (type == BuiltInClass.SIMPLE_ARRAY) return T; return super.typep(type); } @Override public LispObject getElementType() { return T; } @Override public boolean isSimpleVector() { return true; } @Override public boolean hasFillPointer() { return false; } @Override public boolean isAdjustable() { return false; } @Override public int capacity() { return capacity; } @Override public int length() { return capacity; } @Override public LispObject elt(int index) { try { return data[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); return NIL; // Not reached. } } @Override public LispObject AREF(int index) { try { return data[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, data.length); return NIL; // Not reached. } } @Override public void aset(int index, LispObject newValue) { try { data[index] = newValue; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public LispObject SVREF(int index) { try { return data[index]; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, data.length); return NIL; // Not reached. } } @Override public void svset(int index, LispObject newValue) { try { data[index] = newValue; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index, capacity); } } @Override public LispObject subseq(int start, int end) { SimpleVector v = new SimpleVector(end - start); int i = start, j = 0; try { while (i < end) v.data[j++] = data[i++]; return v; } catch (ArrayIndexOutOfBoundsException e) { return error(new TypeError("Array index out of bounds: " + i + ".")); } } @Override public void fill(LispObject obj) { for (int i = capacity; i-- > 0;) data[i] = obj; } @Override public LispObject deleteEq(LispObject item) { final int limit = capacity; int i = 0; int j = 0; while (i < limit) { LispObject obj = data[i++]; if (obj != item) data[j++] = obj; } if (j < limit) shrink(j); return this; } @Override public LispObject deleteEql(LispObject item) { final int limit = capacity; int i = 0; int j = 0; while (i < limit) { LispObject obj = data[i++]; if (!obj.eql(item)) data[j++] = obj; } if (j < limit) shrink(j); return this; } @Override public void shrink(int n) { if (n < capacity) { LispObject[] newData = new LispObject[n]; System.arraycopy(data, 0, newData, 0, n); data = newData; capacity = n; return; } if (n == capacity) return; error(new LispError()); } @Override public LispObject reverse() { SimpleVector result = new SimpleVector(capacity); int i, j; for (i = 0, j = capacity - 1; i < capacity; i++, j--) result.data[i] = data[j]; return result; } @Override public LispObject nreverse() { int i = 0; int j = capacity - 1; while (i < j) { LispObject temp = data[i]; data[i] = data[j]; data[j] = temp; ++i; --j; } return this; } @Override public AbstractVector adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents) { if (initialContents != null) { LispObject[] newData = new LispObject[newCapacity]; if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < newCapacity; i++) { newData[i] = list.car(); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < newCapacity; i++) newData[i] = initialContents.elt(i); } else type_error(initialContents, Symbol.SEQUENCE); return new SimpleVector(newData); } if (capacity != newCapacity) { LispObject[] newData = new LispObject[newCapacity]; System.arraycopy(data, 0, newData, 0, Math.min(capacity, newCapacity)); if (initialElement != null) for (int i = capacity; i < newCapacity; i++) newData[i] = initialElement; return new SimpleVector(newData); } // No change. return this; } @Override public AbstractVector adjustArray(int newCapacity, AbstractArray displacedTo, int displacement) { return new ComplexVector(newCapacity, displacedTo, displacement); } // ### svref // svref simple-vector index => element private static final Primitive SVREF = new Primitive("svref", "simple-vector index") { @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof SimpleVector) { final SimpleVector sv = (SimpleVector)first; int index = Fixnum.getValue(second); try { return sv.data[index]; } catch (ArrayIndexOutOfBoundsException e) { int capacity = sv.capacity; sv.badIndex(index, capacity); // Not reached. return NIL; } } return type_error(first, Symbol.SIMPLE_VECTOR); } }; // ### svset simple-vector index new-value => new-value private static final Primitive SVSET = new Primitive("svset", PACKAGE_SYS, true, "simple-vector index new-value") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first instanceof SimpleVector) { final SimpleVector sv = (SimpleVector)first; int index = Fixnum.getValue(second); try { sv.data[index] = third; return third; } catch (ArrayIndexOutOfBoundsException e) { int capacity = sv.capacity; sv.badIndex(index, capacity); // Not reached. return NIL; } } return type_error(first, Symbol.SIMPLE_VECTOR); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SimpleWarning.java0100644 0000000 0000000 00000005064 14202767264 021646 0ustar000000000 0000000 /* * SimpleWarning.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SimpleWarning extends Warning { public SimpleWarning(LispObject initArgs) { super(StandardClass.SIMPLE_WARNING); initialize(initArgs); } public SimpleWarning(LispObject formatControl, LispObject formatArguments) { super(StandardClass.SIMPLE_WARNING); setFormatControl(formatControl); setFormatArguments(formatArguments); } @Override public LispObject typeOf() { return Symbol.SIMPLE_WARNING; } @Override public LispObject classOf() { return StandardClass.SIMPLE_WARNING; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_WARNING) return T; if (type == StandardClass.SIMPLE_WARNING) return T; if (type == Symbol.SIMPLE_CONDITION) return T; if (type == StandardClass.SIMPLE_CONDITION) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/SingleFloat.java0100644 0000000 0000000 00000051275 14202767264 021303 0ustar000000000 0000000 /* * SingleFloat.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; public final class SingleFloat extends LispObject { public static final SingleFloat ZERO = new SingleFloat(0); public static final SingleFloat MINUS_ZERO = new SingleFloat(-0.0f); public static final SingleFloat ONE = new SingleFloat(1); public static final SingleFloat MINUS_ONE = new SingleFloat(-1); public static final SingleFloat SINGLE_FLOAT_POSITIVE_INFINITY = new SingleFloat(Float.POSITIVE_INFINITY); public static final SingleFloat SINGLE_FLOAT_NEGATIVE_INFINITY = new SingleFloat(Float.NEGATIVE_INFINITY); static { Symbol.SINGLE_FLOAT_POSITIVE_INFINITY.initializeConstant(SINGLE_FLOAT_POSITIVE_INFINITY); Symbol.SINGLE_FLOAT_NEGATIVE_INFINITY.initializeConstant(SINGLE_FLOAT_NEGATIVE_INFINITY); } public static SingleFloat getInstance(float f) { if (f == 0) { int bits = Float.floatToRawIntBits(f); if (bits < 0) return MINUS_ZERO; else return ZERO; } else if (f == 1) return ONE; else if (f == -1) return MINUS_ONE; else return new SingleFloat(f); } public final float value; public SingleFloat(float value) { this.value = value; } @Override public LispObject typeOf() { return Symbol.SINGLE_FLOAT; } @Override public LispObject classOf() { return BuiltInClass.SINGLE_FLOAT; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.FLOAT) return T; if (typeSpecifier == Symbol.REAL) return T; if (typeSpecifier == Symbol.NUMBER) return T; if (typeSpecifier == Symbol.SINGLE_FLOAT) return T; if (typeSpecifier == Symbol.SHORT_FLOAT) return T; if (typeSpecifier == BuiltInClass.FLOAT) return T; if (typeSpecifier == BuiltInClass.SINGLE_FLOAT) return T; return super.typep(typeSpecifier); } @Override public boolean numberp() { return true; } @Override public boolean realp() { return true; } @Override public boolean eql(LispObject obj) { if (this == obj) return true; if (obj instanceof SingleFloat) { if (value == 0) { // "If an implementation supports positive and negative zeros // as distinct values, then (EQL 0.0 -0.0) returns false." float f = ((SingleFloat)obj).value; int bits = Float.floatToRawIntBits(f); return bits == Float.floatToRawIntBits(value); } if (value == ((SingleFloat)obj).value) return true; } return false; } @Override public boolean equal(LispObject obj) { if (this == obj) return true; if (obj instanceof SingleFloat) { if (value == 0) { // same as EQL float f = ((SingleFloat)obj).value; int bits = Float.floatToRawIntBits(f); return bits == Float.floatToRawIntBits(value); } if (value == ((SingleFloat)obj).value) return true; } return false; } @Override public boolean equalp(int n) { // "If two numbers are the same under =." return value == n; } @Override public boolean equalp(LispObject obj) { if (obj != null && obj.numberp()) return isEqualTo(obj); return false; } @Override public LispObject ABS() { if (value > 0) return this; if (value == 0) // 0.0 or -0.0 return ZERO; return new SingleFloat(- value); } @Override public boolean plusp() { return value > 0; } @Override public boolean minusp() { return value < 0; } @Override public boolean zerop() { return value == 0; } @Override public boolean floatp() { return true; } public static double getValue(LispObject obj) { if (obj instanceof SingleFloat) return ((SingleFloat)obj).value; type_error(obj, Symbol.FLOAT); // not reached return 0.0D; } public final float getValue() { return value; } @Override public float floatValue() { return value; } @Override public double doubleValue() { return value; } @Override public Object javaInstance() { return Float.valueOf(value); } @Override public Object javaInstance(Class c) { if (c == Float.class || c == float.class) return Float.valueOf(value); return javaInstance(); } @Override public final LispObject incr() { return new SingleFloat(value + 1); } @Override public final LispObject decr() { return new SingleFloat(value - 1); } @Override public LispObject add(LispObject obj) { if (obj instanceof Fixnum) return new SingleFloat(value + ((Fixnum)obj).value); if (obj instanceof SingleFloat) return new SingleFloat(value + ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value + ((DoubleFloat)obj).value); if (obj instanceof Bignum) return new SingleFloat(value + ((Bignum)obj).floatValue()); if (obj instanceof Ratio) return new SingleFloat(value + ((Ratio)obj).floatValue()); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart()); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject negate() { if (value == 0) { int bits = Float.floatToRawIntBits(value); return (bits < 0) ? ZERO : MINUS_ZERO; } return new SingleFloat(-value); } @Override public LispObject subtract(LispObject obj) { if (obj instanceof Fixnum) return new SingleFloat(value - ((Fixnum)obj).value); if (obj instanceof SingleFloat) return new SingleFloat(value - ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value - ((DoubleFloat)obj).value); if (obj instanceof Bignum) return new SingleFloat(value - ((Bignum)obj).floatValue()); if (obj instanceof Ratio) return new SingleFloat(value - ((Ratio)obj).floatValue()); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(subtract(c.getRealPart()), ZERO.subtract(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject multiplyBy(LispObject obj) { if (obj instanceof Fixnum) return new SingleFloat(value * ((Fixnum)obj).value); if (obj instanceof SingleFloat) return new SingleFloat(value * ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value * ((DoubleFloat)obj).value); if (obj instanceof Bignum) return new SingleFloat(value * ((Bignum)obj).floatValue()); if (obj instanceof Ratio) return new SingleFloat(value * ((Ratio)obj).floatValue()); if (obj instanceof Complex) { Complex c = (Complex) obj; return Complex.getInstance(multiplyBy(c.getRealPart()), multiplyBy(c.getImaginaryPart())); } return type_error(obj, Symbol.NUMBER); } @Override public LispObject divideBy(LispObject obj) { if (obj instanceof Fixnum) return new SingleFloat(value / ((Fixnum)obj).value); if (obj instanceof SingleFloat) return new SingleFloat(value / ((SingleFloat)obj).value); if (obj instanceof DoubleFloat) return new DoubleFloat(value / ((DoubleFloat)obj).value); if (obj instanceof Bignum) return new SingleFloat(value / ((Bignum)obj).floatValue()); if (obj instanceof Ratio) return new SingleFloat(value / ((Ratio)obj).floatValue()); if (obj instanceof Complex) { Complex c = (Complex) obj; LispObject re = c.getRealPart(); LispObject im = c.getImaginaryPart(); LispObject denom = re.multiplyBy(re).add(im.multiplyBy(im)); LispObject resX = multiplyBy(re).divideBy(denom); LispObject resY = multiplyBy(Fixnum.MINUS_ONE).multiplyBy(im).divideBy(denom); return Complex.getInstance(resX, resY); } return type_error(obj, Symbol.NUMBER); } @Override public boolean isEqualTo(LispObject obj) { if (obj instanceof Fixnum) return rational().isEqualTo(obj); if (obj instanceof SingleFloat) return value == ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value == ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isEqualTo(obj); if (obj instanceof Ratio) return rational().isEqualTo(obj); if (obj instanceof Complex) return obj.isEqualTo(this); type_error(obj, Symbol.NUMBER); // Not reached. return false; } @Override public boolean isNotEqualTo(LispObject obj) { return !isEqualTo(obj); } @Override public boolean isLessThan(LispObject obj) { if (obj instanceof Fixnum) return rational().isLessThan(obj); if (obj instanceof SingleFloat) return value < ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value < ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isLessThan(obj); if (obj instanceof Ratio) return rational().isLessThan(obj); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThan(LispObject obj) { if (obj instanceof Fixnum) return rational().isGreaterThan(obj); if (obj instanceof SingleFloat) return value > ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value > ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isGreaterThan(obj); if (obj instanceof Ratio) return rational().isGreaterThan(obj); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isLessThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) return rational().isLessThanOrEqualTo(obj); if (obj instanceof SingleFloat) return value <= ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value <= ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isLessThanOrEqualTo(obj); if (obj instanceof Ratio) return rational().isLessThanOrEqualTo(obj); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public boolean isGreaterThanOrEqualTo(LispObject obj) { if (obj instanceof Fixnum) return rational().isGreaterThanOrEqualTo(obj); if (obj instanceof SingleFloat) return value >= ((SingleFloat)obj).value; if (obj instanceof DoubleFloat) return value >= ((DoubleFloat)obj).value; if (obj instanceof Bignum) return rational().isGreaterThanOrEqualTo(obj); if (obj instanceof Ratio) return rational().isGreaterThanOrEqualTo(obj); type_error(obj, Symbol.REAL); // Not reached. return false; } @Override public LispObject truncate(LispObject obj) { // "When rationals and floats are combined by a numerical function, // the rational is first converted to a float of the same format." // 12.1.4.1 if (obj instanceof Fixnum) { return truncate(new SingleFloat(((Fixnum)obj).value)); } if (obj instanceof Bignum) { return truncate(new SingleFloat(((Bignum)obj).floatValue())); } if (obj instanceof Ratio) { return truncate(new SingleFloat(((Ratio)obj).floatValue())); } if (obj instanceof SingleFloat) { final LispThread thread = LispThread.currentThread(); float divisor = ((SingleFloat)obj).value; float quotient = value / divisor; if (value != 0) MathFunctions.OverUnderFlowCheck(quotient); if (quotient >= Integer.MIN_VALUE && quotient <= Integer.MAX_VALUE) { int q = (int) quotient; return thread.setValues(Fixnum.getInstance(q), new SingleFloat(value - q * divisor)); } // We need to convert the quotient to a bignum. int bits = Float.floatToRawIntBits(quotient); int s = ((bits >> 31) == 0) ? 1 : -1; int e = (int) ((bits >> 23) & 0xff); long m; if (e == 0) m = (bits & 0x7fffff) << 1; else m = (bits & 0x7fffff) | 0x800000; LispObject significand = number(m); Fixnum exponent = Fixnum.getInstance(e - 150); Fixnum sign = Fixnum.getInstance(s); LispObject result = significand; result = result.multiplyBy(MathFunctions.EXPT.execute(Fixnum.TWO, exponent)); result = result.multiplyBy(sign); // Calculate remainder. LispObject product = result.multiplyBy(obj); LispObject remainder = subtract(product); return thread.setValues(result, remainder); } if (obj instanceof DoubleFloat) { final LispThread thread = LispThread.currentThread(); double divisor = ((DoubleFloat)obj).value; double quotient = value / divisor; if (value != 0) MathFunctions.OverUnderFlowCheck(quotient); if (quotient >= Integer.MIN_VALUE && quotient <= Integer.MAX_VALUE) { int q = (int) quotient; return thread.setValues(Fixnum.getInstance(q), new DoubleFloat(value - q * divisor)); } // We need to convert the quotient to a bignum. long bits = Double.doubleToRawLongBits((double)quotient); int s = ((bits >> 63) == 0) ? 1 : -1; int e = (int) ((bits >> 52) & 0x7ffL); long m; if (e == 0) m = (bits & 0xfffffffffffffL) << 1; else m = (bits & 0xfffffffffffffL) | 0x10000000000000L; LispObject significand = number(m); Fixnum exponent = Fixnum.getInstance(e - 1075); Fixnum sign = Fixnum.getInstance(s); LispObject result = significand; result = result.multiplyBy(MathFunctions.EXPT.execute(Fixnum.TWO, exponent)); result = result.multiplyBy(sign); // Calculate remainder. LispObject product = result.multiplyBy(obj); LispObject remainder = subtract(product); return thread.setValues(result, remainder); } return type_error(obj, Symbol.REAL); } @Override public int hashCode() { return Float.floatToIntBits(value); } @Override public int psxhash() { if ((value % 1) == 0) return (((int)value) & 0x7fffffff); else return (hashCode() & 0x7fffffff); } @Override public String printObject() { if (value == Float.POSITIVE_INFINITY) { StringBuffer sb = new StringBuffer("#."); sb.append(Symbol.SINGLE_FLOAT_POSITIVE_INFINITY.printObject()); return sb.toString(); } if (value == Float.NEGATIVE_INFINITY) { StringBuffer sb = new StringBuffer("#."); sb.append(Symbol.SINGLE_FLOAT_NEGATIVE_INFINITY.printObject()); return sb.toString(); } LispThread thread = LispThread.currentThread(); boolean printReadably = Symbol.PRINT_READABLY.symbolValue(thread) != NIL; if (value != value) { if (printReadably) return "#.(CL:PROGN \"Comment: create a NaN.\" (CL:/ 0.0s0 0.0s0))"; else return unreadableString("SINGLE-FLOAT NaN", false); } String s1 = String.valueOf(value); if (printReadably || !memq(Symbol.READ_DEFAULT_FLOAT_FORMAT.symbolValue(thread), list(Symbol.SINGLE_FLOAT, Symbol.SHORT_FLOAT))) { if (s1.indexOf('E') >= 0) return s1.replace('E', 'f'); else return s1.concat("f0"); } else return s1; } public LispObject rational() { final int bits = Float.floatToRawIntBits(value); int sign = ((bits >> 31) == 0) ? 1 : -1; int storedExponent = ((bits >> 23) & 0xff); long mantissa; if (storedExponent == 0) mantissa = (bits & 0x7fffff) << 1; else mantissa = (bits & 0x7fffff) | 0x800000; if (mantissa == 0) return Fixnum.ZERO; if (sign < 0) mantissa = -mantissa; // Subtract bias. final int exponent = storedExponent - 127; BigInteger numerator, denominator; if (exponent < 0) { numerator = BigInteger.valueOf(mantissa); denominator = BigInteger.valueOf(1).shiftLeft(23 - exponent); } else { numerator = BigInteger.valueOf(mantissa).shiftLeft(exponent); denominator = BigInteger.valueOf(0x800000); // (ash 1 23) } return number(numerator, denominator); } public static SingleFloat coerceToFloat(LispObject obj) { if (obj instanceof Fixnum) return new SingleFloat(((Fixnum)obj).value); if (obj instanceof SingleFloat) return (SingleFloat) obj; if (obj instanceof DoubleFloat) { float result = (float)((DoubleFloat)obj).value; if (Float.isInfinite(result) && TRAP_OVERFLOW) type_error(obj, Symbol.SINGLE_FLOAT); return new SingleFloat(result); } if (obj instanceof Bignum) return new SingleFloat(((Bignum)obj).floatValue()); if (obj instanceof Ratio) return new SingleFloat(((Ratio)obj).floatValue()); error(new TypeError("The value " + obj.princToString() + " cannot be converted to type SINGLE-FLOAT.")); // Not reached. return null; } } abcl-src-1.9.0/src/org/armedbear/lisp/Site.java0100644 0000000 0000000 00000005566 14202767264 020002 0ustar000000000 0000000 /* * Site.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.URL; public final class Site { private static LispObject LISP_HOME; private static void init() { String s = System.getProperty("abcl.home"); if (s != null) { String fileSeparator = System.getProperty("file.separator"); if (!s.endsWith(fileSeparator)) { s += fileSeparator; } LISP_HOME = Pathname.create(s); return; } URL url = Lisp.class.getResource("boot.lisp"); // what if this was "__loader__._"?!! if (url != null) { if (!Pathname.isSupportedProtocol(url.getProtocol())) { LISP_HOME = NIL; } else { Pathname p = (Pathname)URLPathname.create(url); p.setName(NIL).setType(NIL); LISP_HOME = p; } return; } simple_error("Unable to determine LISP_HOME."); } public static final LispObject getLispHome() { if (LISP_HOME == null) { init(); } return LISP_HOME; } // ### *lisp-home* private static final Symbol _LISP_HOME_ = exportSpecial("*LISP-HOME*", PACKAGE_EXT, NIL); static { LispObject p = Site.getLispHome(); if (p != null) _LISP_HOME_.setSymbolValue(p); } } abcl-src-1.9.0/src/org/armedbear/lisp/SiteName.java0100644 0000000 0000000 00000005273 14202767264 020576 0ustar000000000 0000000 /* * SiteName.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.InetAddress; import java.net.UnknownHostException; public final class SiteName { static LispObject getHostName() { String hostName = null; InetAddress addr; try { addr = InetAddress.getLocalHost(); } catch (UnknownHostException e) { addr = null; } if (addr != null) hostName = addr.getHostName(); return hostName != null ? new SimpleString(hostName) : NIL; } private static final Primitive MACHINE_INSTANCE = new Primitive("machine-instance") { @Override public LispObject execute() { return getHostName(); } }; private static final Primitive LONG_SITE_NAME = new Primitive("long-site-name") { @Override public LispObject execute() { return getHostName(); } }; private static final Primitive SHORT_SITE_NAME = new Primitive("short-site-name") { @Override public LispObject execute() { return getHostName(); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SlimeInputStream.java0100644 0000000 0000000 00000010676 14202767264 022341 0ustar000000000 0000000 /* * SlimeInputStream.java * * Copyright (C) 2004 Andras Simon, Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class SlimeInputStream extends Stream { String s; int length; final Function f; final Stream ostream; public SlimeInputStream(Function f, Stream ostream) { super(Symbol.SLIME_INPUT_STREAM); elementType = Symbol.CHARACTER; isInputStream = true; isOutputStream = false; isCharacterStream = true; isBinaryStream = false; eolStyle = EolStyle.LF; this.f = f; this.ostream = ostream; } @Override public LispObject typeOf() { return Symbol.SLIME_INPUT_STREAM; } @Override public LispObject classOf() { return BuiltInClass.SLIME_INPUT_STREAM; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SLIME_INPUT_STREAM) return T; if (type == Symbol.STRING_STREAM) return T; if (type == BuiltInClass.SLIME_INPUT_STREAM) return T; if (type == BuiltInClass.STRING_STREAM) return T; return super.typep(type); } @Override public LispObject close(LispObject abort) { setOpen(false); return T; } @Override public LispObject listen() { return offset < length ? T : NIL; } @Override protected int _readChar() { if (offset >= length) { ostream.finishOutput(); s = LispThread.currentThread().execute(f).getStringValue(); if (s.length() == 0) return -1; offset = 0; length = s.length(); } int n = s.charAt(offset); ++offset; if (n == '\n') ++lineNumber; return n; } @Override protected void _unreadChar(int n) { if (offset > 0) { --offset; if (n == '\n') --lineNumber; } } @Override protected boolean _charReady() { return offset < length; } @Override public void _clearInput() { super._clearInput(); s = ""; offset = 0; length = 0; lineNumber = 0; } // ### make-slime-input-stream // make-slime-input-stream function output-stream => slime-input-stream private static final Primitive MAKE_SLIME_INPUT_STREAM = new Primitive("make-slime-input-stream", PACKAGE_EXT, true, "function output-stream") { @Override public LispObject execute(LispObject first, LispObject second) { final Function fun; final Stream os; if (first instanceof Symbol) fun = (Function)first.getSymbolFunction(); else fun = (Function)first; os = checkCharacterOutputStream(second); return new SlimeInputStream(fun, os); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SlimeOutputStream.java0100644 0000000 0000000 00000010766 14202767264 022542 0ustar000000000 0000000 /* * SlimeOutputStream.java * * Copyright (C) 2004-2005 Andras Simon, Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.StringWriter; public final class SlimeOutputStream extends Stream { private final StringWriter stringWriter; final Function f; SlimeOutputStream(Function f) { super(Symbol.SLIME_OUTPUT_STREAM); this.elementType = Symbol.CHARACTER; isInputStream = false; isOutputStream = true; isCharacterStream = true; isBinaryStream = false; eolStyle = EolStyle.LF; setWriter(stringWriter = new StringWriter()); this.f = f; } @Override public LispObject typeOf() { return Symbol.SLIME_OUTPUT_STREAM; } @Override public LispObject classOf() { return BuiltInClass.SLIME_OUTPUT_STREAM; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SLIME_OUTPUT_STREAM) return T; if (type == Symbol.STRING_STREAM) return T; if (type == BuiltInClass.SLIME_OUTPUT_STREAM) return T; if (type == BuiltInClass.STRING_STREAM) return T; return super.typep(type); } @Override public void _writeChar(char c) { if (elementType == NIL) writeError(); super._writeChar(c); } @Override public void _writeChars(char[] chars, int start, int end) { if (elementType == NIL) writeError(); super._writeChars(chars, start, end); } @Override public void _writeString(String s) { if (elementType == NIL) writeError(); super._writeString(s); } @Override public void _writeLine(String s) { if (elementType == NIL) writeError(); super._writeLine(s); } private void writeError() { error(new TypeError("Attempt to write to a string output stream of element type NIL.")); } @Override protected long _getFilePosition() { if (elementType == NIL) return 0; return stringWriter.toString().length(); } @Override public void _finishOutput() { super._finishOutput (); if (stringWriter.getBuffer().length() > 0) { String s = stringWriter.toString(); stringWriter.getBuffer().setLength(0); LispThread.currentThread().execute(f, new SimpleString(s)); } } // ### %make-slime-output-stream // %make-slime-output-stream function => stream private static final Primitive MAKE_SLIME_OUTPUT_STREAM = new Primitive("make-slime-output-stream", PACKAGE_EXT, true, "function") { @Override public LispObject execute(LispObject arg) { final Function fun; if (arg instanceof Symbol) fun = (Function)arg.getSymbolFunction(); else fun = (Function)arg; return new SlimeOutputStream(fun); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SlotClass.java0100644 0000000 0000000 00000027041 14202767264 020775 0ustar000000000 0000000 /* * SlotClass.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class SlotClass extends LispClass { private LispObject directSlotDefinitions = NIL; private LispObject slotDefinitions = NIL; private LispObject directDefaultInitargs = NIL; private LispObject defaultInitargs = NIL; public SlotClass(Layout layout) { super(layout); } public SlotClass(Symbol symbol, LispObject directSuperclasses) { this(null, symbol, directSuperclasses); } public SlotClass(Layout layout, Symbol symbol, LispObject directSuperclasses) { super(layout, symbol, directSuperclasses); } @Override public LispObject getParts() { LispObject result = super.getParts().nreverse(); result = result.push(new Cons("DIRECT-SLOTS", getDirectSlotDefinitions())); result = result.push(new Cons("SLOTS", getSlotDefinitions())); result = result.push(new Cons("DIRECT-DEFAULT-INITARGS", getDirectDefaultInitargs())); result = result.push(new Cons("DEFAULT-INITARGS", getDefaultInitargs())); return result.nreverse(); } @Override public LispObject typep(LispObject type) { return super.typep(type); } public LispObject getDirectSlotDefinitions() { return directSlotDefinitions; } public void setDirectSlotDefinitions(LispObject directSlotDefinitions) { this.directSlotDefinitions = directSlotDefinitions; } public LispObject getSlotDefinitions() { return slotDefinitions; } public void setSlotDefinitions(LispObject slotDefinitions) { this.slotDefinitions = slotDefinitions; } public LispObject getDirectDefaultInitargs() { return directDefaultInitargs; } public void setDirectDefaultInitargs(LispObject directDefaultInitargs) { this.directDefaultInitargs = directDefaultInitargs; } public LispObject getDefaultInitargs() { return defaultInitargs; } public void setDefaultInitargs(LispObject defaultInitargs) { this.defaultInitargs = defaultInitargs; } LispObject computeDefaultInitargs() { // KLUDGE (rudi 2012-06-02): duplicate initargs are not removed // here, but this does not hurt us since no Lisp class we define // Java-side has non-nil direct default initargs. LispObject result = NIL; LispObject cpl = getCPL(); while (cpl != NIL) { LispClass c = (LispClass) cpl.car(); if (c instanceof StandardClass) { LispObject obj = ((StandardClass)c).getDirectDefaultInitargs(); if (obj != NIL) result = Symbol.APPEND.execute(result, obj); } cpl = cpl.cdr(); } return result; } public void finalizeClass() { if (isFinalized()) return; LispObject defs = getSlotDefinitions(); Debug.assertTrue(defs == NIL); LispObject cpl = getCPL(); Debug.assertTrue(cpl != null); Debug.assertTrue(cpl.listp()); cpl = cpl.reverse(); while (cpl != NIL) { LispObject car = cpl.car(); if (car instanceof StandardClass) { StandardClass cls = (StandardClass) car; LispObject directDefs = cls.getDirectSlotDefinitions(); Debug.assertTrue(directDefs != null); Debug.assertTrue(directDefs.listp()); while (directDefs != NIL) { defs = defs.push(directDefs.car()); directDefs = directDefs.cdr(); } } cpl = cpl.cdr(); } setSlotDefinitions(defs.nreverse()); LispObject[] instanceSlotNames = new LispObject[defs.length()]; int i = 0; LispObject tail = getSlotDefinitions(); while (tail != NIL) { SlotDefinition slotDefinition = (SlotDefinition) tail.car(); slotDefinition.setInstanceSlotValue(Symbol.LOCATION, Fixnum.getInstance(i)); instanceSlotNames[i++] = slotDefinition.getInstanceSlotValue(Symbol.NAME); tail = tail.cdr(); } setClassLayout(new Layout(this, instanceSlotNames, NIL)); setDefaultInitargs(computeDefaultInitargs()); setFinalized(true); } @DocString(name="%class-direct-slots") private static final Primitive CLASS_DIRECT_SLOTS = new pf__class_direct_slots(); private static final class pf__class_direct_slots extends Primitive { pf__class_direct_slots() { super("%class-direct-slots", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof SlotClass) return ((SlotClass)arg).getDirectSlotDefinitions(); if (arg instanceof BuiltInClass) return NIL; return type_error(arg, Symbol.STANDARD_CLASS); } }; @DocString(name="%set-class-direct-slots") private static final Primitive _SET_CLASS_DIRECT_SLOT = new pf__set_class_direct_slots(); private static final class pf__set_class_direct_slots extends Primitive { pf__set_class_direct_slots() { super("%set-class-direct-slots", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof SlotClass) { ((SlotClass)second).setDirectSlotDefinitions(first); return first; } else { return type_error(second, Symbol.STANDARD_CLASS); } } }; @DocString(name="%class-slots", args="class") private static final Primitive _CLASS_SLOTS = new pf__class_slots(); private static final class pf__class_slots extends Primitive { pf__class_slots() { super(Symbol._CLASS_SLOTS, "class"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof SlotClass) return ((SlotClass)arg).getSlotDefinitions(); if (arg instanceof BuiltInClass) return NIL; return type_error(arg, Symbol.STANDARD_CLASS); } }; @DocString(name="%set-class-slots", args="class slot-definitions") private static final Primitive _SET_CLASS_SLOTS = new pf__set_class_slots(); private static final class pf__set_class_slots extends Primitive { pf__set_class_slots() { super(Symbol._SET_CLASS_SLOTS, "class slot-definitions"); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof SlotClass) { ((SlotClass)second).setSlotDefinitions(first); return first; } else { return type_error(second, Symbol.STANDARD_CLASS); } } }; @DocString(name="%class-direct-default-initargs") private static final Primitive CLASS_DIRECT_DEFAULT_INITARGS = new pf__class_direct_default_initargs(); private static final class pf__class_direct_default_initargs extends Primitive { pf__class_direct_default_initargs() { super("%class-direct-default-initargs", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof SlotClass) return ((SlotClass)arg).getDirectDefaultInitargs(); if (arg instanceof BuiltInClass) return NIL; return type_error(arg, Symbol.STANDARD_CLASS); } }; @DocString(name="%set-class-direct-default-initargs") private static final Primitive _SET_CLASS_DIRECT_DEFAULT_INITARGS = new pf__set_class_direct_default_initargs(); private static final class pf__set_class_direct_default_initargs extends Primitive { pf__set_class_direct_default_initargs() { super("%set-class-direct-default-initargs", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof SlotClass) { ((SlotClass)second).setDirectDefaultInitargs(first); return first; } return type_error(second, Symbol.STANDARD_CLASS); } }; @DocString(name="%class-default-initargs") private static final Primitive CLASS_DEFAULT_INITARGS = new pf__class_default_initargs(); private static final class pf__class_default_initargs extends Primitive { pf__class_default_initargs() { super("%class-default-initargs", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { if (arg instanceof SlotClass) return ((SlotClass)arg).getDefaultInitargs(); if (arg instanceof BuiltInClass) return NIL; return type_error(arg, Symbol.STANDARD_CLASS); } }; @DocString(name="%set-class-default-initargs") private static final Primitive _SET_CLASS_DEFAULT_INITARGS = new pf__set_class_default_initargs(); private static final class pf__set_class_default_initargs extends Primitive { pf__set_class_default_initargs() { super("%set-class-default-initargs", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (second instanceof SlotClass) { ((SlotClass)second).setDefaultInitargs(first); return first; } return type_error(second, Symbol.STANDARD_CLASS); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SlotDefinition.java0100644 0000000 0000000 00000014405 14202767264 022020 0ustar000000000 0000000 /* * SlotDefinition.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SlotDefinition extends StandardObject { private SlotDefinition() { super(StandardClass.STANDARD_SLOT_DEFINITION, StandardClass.STANDARD_SLOT_DEFINITION.getClassLayout().getLength()); setInstanceSlotValue(Symbol.LOCATION, NIL); setInstanceSlotValue(Symbol._TYPE, T); setInstanceSlotValue(Symbol._DOCUMENTATION, NIL); } private SlotDefinition(StandardClass clazz) { // clazz layout needs to have SlotDefinitionClass layout as prefix // or indexed slot access won't work super(clazz, clazz.getClassLayout().getLength()); setInstanceSlotValue(Symbol.LOCATION, NIL); } public SlotDefinition(StandardClass clazz, LispObject name) { // clazz layout needs to have SlotDefinitionClass layout as prefix // or indexed slot access won't work super(clazz, clazz.getClassLayout().getLength()); Debug.assertTrue(name instanceof Symbol); setInstanceSlotValue(Symbol.NAME, name); setInstanceSlotValue(Symbol.INITFUNCTION, NIL); setInstanceSlotValue(Symbol.INITARGS, new Cons(PACKAGE_KEYWORD.intern(((Symbol)name).getName()))); setInstanceSlotValue(Symbol.READERS, NIL); setInstanceSlotValue(Symbol.ALLOCATION, Keyword.INSTANCE); setInstanceSlotValue(Symbol.LOCATION, NIL); setInstanceSlotValue(Symbol._TYPE, T); setInstanceSlotValue(Symbol._DOCUMENTATION, NIL); } public SlotDefinition(LispObject name, LispObject readers) { this(); Debug.assertTrue(name instanceof Symbol); setInstanceSlotValue(Symbol.NAME, name); setInstanceSlotValue(Symbol.INITFUNCTION, NIL); setInstanceSlotValue(Symbol.INITARGS, new Cons(PACKAGE_KEYWORD.intern(((Symbol)name).getName()))); setInstanceSlotValue(Symbol.READERS, readers); setInstanceSlotValue(Symbol.ALLOCATION, Keyword.INSTANCE); } public SlotDefinition(LispObject name, LispObject readers, LispObject initForm) { this(); Debug.assertTrue(name instanceof Symbol); setInstanceSlotValue(Symbol.NAME, name); setInstanceSlotValue(Symbol.INITFUNCTION, NIL); setInstanceSlotValue(Symbol.INITFORM, initForm); setInstanceSlotValue(Symbol.INITARGS, new Cons(PACKAGE_KEYWORD.intern(((Symbol)name).getName()))); setInstanceSlotValue(Symbol.READERS, readers); setInstanceSlotValue(Symbol.ALLOCATION, Keyword.INSTANCE); } public SlotDefinition(LispObject name, LispObject readers, Function initFunction) { this(); Debug.assertTrue(name instanceof Symbol); setInstanceSlotValue(Symbol.NAME, name); setInstanceSlotValue(Symbol.INITFUNCTION, initFunction); setInstanceSlotValue(Symbol.INITFORM, NIL); setInstanceSlotValue(Symbol.INITARGS, new Cons(PACKAGE_KEYWORD.intern(((Symbol)name).getName()))); setInstanceSlotValue(Symbol.READERS, readers); setInstanceSlotValue(Symbol.ALLOCATION, Keyword.INSTANCE); } public SlotDefinition(LispObject name, LispObject readers, Function initFunction, LispObject initargs) { this(); Debug.assertTrue(name instanceof Symbol); setInstanceSlotValue(Symbol.NAME, name); setInstanceSlotValue(Symbol.INITFUNCTION, initFunction); setInstanceSlotValue(Symbol.INITFORM, NIL); setInstanceSlotValue(Symbol.INITARGS, initargs); setInstanceSlotValue(Symbol.READERS, readers); setInstanceSlotValue(Symbol.ALLOCATION, Keyword.INSTANCE); } @Override public String printObject() { StringBuilder sb = new StringBuilder(Symbol.SLOT_DEFINITION.printObject()); LispObject name = getInstanceSlotValue(Symbol.NAME); if (name != null && name != NIL) { sb.append(' '); sb.append(name.printObject()); } return unreadableString(sb.toString()); } private static final Primitive MAKE_SLOT_DEFINITION = new pf_make_slot_definition(); @DocString(name="%make-slot-definition", args="slot-class", doc="Argument must be a subclass of standard-slot-definition") private static final class pf_make_slot_definition extends Primitive { pf_make_slot_definition() { super("%make-slot-definition", PACKAGE_SYS, true, "slot-class"); } @Override public LispObject execute(LispObject slotDefinitionClass) { if (!(slotDefinitionClass instanceof StandardClass)) return type_error(slotDefinitionClass, StandardClass.STANDARD_SLOT_DEFINITION); // we could check whether slotClass is a subtype of // standard-slot-definition here, but subtypep doesn't work early // in the build process return new SlotDefinition((StandardClass)slotDefinitionClass); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/SlotDefinitionClass.java0100644 0000000 0000000 00000007256 14202767264 023014 0ustar000000000 0000000 /* * SlotDefinitionClass.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SlotDefinitionClass extends StandardClass { public SlotDefinitionClass(Symbol symbol, LispObject cpl) { super(symbol, cpl); LispObject[] instanceSlotNames = { Symbol.NAME, Symbol.INITFUNCTION, Symbol.INITFORM, Symbol.INITARGS, Symbol.READERS, Symbol.WRITERS, Symbol.ALLOCATION, Symbol.ALLOCATION_CLASS, Symbol.LOCATION, Symbol._TYPE, Symbol._DOCUMENTATION }; setClassLayout(new Layout(this, instanceSlotNames, NIL)); //Set up slot definitions so that this class can be extended by users LispObject slotDefinitions = NIL; for(int i = instanceSlotNames.length - 1; i >= 0; i--) { slotDefinitions = slotDefinitions.push(new SlotDefinition(this, instanceSlotNames[i])); } // The Java class SlotDefinition sets the location slot to NIL // in its constructor; here we make Lisp-side subclasses of // standard-*-slot-definition do the same. StandardObject locationSlot = checkSlotDefinition(slotDefinitions.nthcdr(8).car()); locationSlot.setInstanceSlotValue(Symbol.INITFORM, NIL); locationSlot.setInstanceSlotValue(Symbol.INITFUNCTION, StandardClass.constantlyNil); // Fix initargs of TYPE, DOCUMENTATION slots. StandardObject typeSlot = checkSlotDefinition(slotDefinitions.nthcdr(9).car()); typeSlot.setInstanceSlotValue(Symbol.INITARGS, list(internKeyword("TYPE"))); StandardObject documentationSlot = checkSlotDefinition(slotDefinitions.nthcdr(10).car()); documentationSlot.setInstanceSlotValue(Symbol.INITARGS, list(internKeyword("DOCUMENTATION"))); setDirectSlotDefinitions(slotDefinitions); setSlotDefinitions(slotDefinitions); setFinalized(true); } private static StandardObject checkSlotDefinition(LispObject obj) { if (obj instanceof StandardObject) return (StandardObject)obj; return (StandardObject)type_error(obj, Symbol.SLOT_DEFINITION); } } abcl-src-1.9.0/src/org/armedbear/lisp/SocketStream.java0100644 0000000 0000000 00000004775 14223403213 021463 0ustar000000000 0000000 /* * SocketStream.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.Socket; public final class SocketStream extends TwoWayStream { private final Socket socket; public SocketStream(Socket socket, Stream in, Stream out) { super(in, out); this.socket = socket; } @Override public LispObject typeOf() { return Symbol.SOCKET_STREAM; } @Override public LispObject classOf() { return BuiltInClass.SOCKET_STREAM; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SOCKET_STREAM) return T; if (type == BuiltInClass.SOCKET_STREAM) return T; return super.typep(type); } @Override public LispObject close(LispObject abort) { try { socket.close(); setOpen(false); return T; } catch (Exception e) { return error(new LispError(e.getMessage())); } } } abcl-src-1.9.0/src/org/armedbear/lisp/SpecialBinding.java0100644 0000000 0000000 00000005034 14202767264 021737 0ustar000000000 0000000 /* * SpecialBinding.java * * Copyright (C) 2002-2008 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; final public class SpecialBinding { /** The index in the specials array of the symbol * to which this value belongs. */ final int idx; /** The value bound */ public LispObject value; SpecialBinding(int idx, LispObject value) { this.idx = idx; this.value = value; } /** Return the value of the binding, * checking a valid binding. * * If the binding is invalid, an unbound variable error * is raised. */ final public LispObject getValue() { if (value == null) // return or not: error doesn't return anyway Lisp.error(new UnboundVariable(LispThread.specialNames.get(Integer.valueOf(idx)).get())); return value; } /** Sets the value of the binding. * * Note: this method can only be called when the * binding is the one which is currently visible. */ final public void setValue(LispObject value) { this.value = value; } } abcl-src-1.9.0/src/org/armedbear/lisp/SpecialBindingsMark.java0100644 0000000 0000000 00000004430 14202767264 022734 0ustar000000000 0000000 /* * SpecialBindingsMark.java * * Copyright (C) 2009 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; /** Class used to mark special bindings state. * Returned by LispThread.markSpecialBindings() and consumed by * LispThread.resetSpecialBindings() to abstract from the implementation. */ final public class SpecialBindingsMark { /** The index in the specials array of the saved binding. */ int idx; /** Special binding state to be restored */ // package level access SpecialBinding binding; SpecialBindingsMark next; /** Constructor to be called by LispThread.markSpecialBindings() only */ // package level access SpecialBindingsMark(int idx, SpecialBinding binding, SpecialBindingsMark next) { this.idx = idx; this.binding = binding; this.next = next; } } abcl-src-1.9.0/src/org/armedbear/lisp/SpecialOperator.java0100644 0000000 0000000 00000012556 14202767264 022167 0ustar000000000 0000000 /* * SpecialOperator.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class SpecialOperator extends Operator { private int callCount; private int hotCount; public SpecialOperator(Symbol symbol) { symbol.setSymbolFunction(this); setLambdaName(symbol); } public SpecialOperator(Symbol symbol, String arglist) { symbol.setSymbolFunction(this); setLambdaName(symbol); setLambdaList(new SimpleString(arglist)); } public SpecialOperator(String name, Package pkg, boolean exported, String arglist) { Symbol symbol; if (exported) symbol = pkg.internAndExport(name.toUpperCase()); else symbol = pkg.intern(name.toUpperCase()); symbol.setSymbolFunction(this); setLambdaName(symbol); setLambdaList(new SimpleString(arglist)); } @Override public LispObject execute() { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject arg) { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject first, LispObject second) { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { return error(new UndefinedFunction(getLambdaName())); } @Override public LispObject execute(LispObject[] args) { return error(new UndefinedFunction(getLambdaName())); } @Override public String printObject() { StringBuilder sb = new StringBuilder("SPECIAL-OPERATOR "); sb.append(lambdaName.princToString()); return unreadableString(sb.toString(), false); } // Profiling. @Override public final int getCallCount() { return callCount; } @Override public final void setCallCount(int n) { callCount = n; } @Override public final void incrementCallCount() { ++callCount; } @Override public final int getHotCount() { return hotCount; } @Override public final void setHotCount(int n) { callCount = n; } @Override public final void incrementHotCount() { ++hotCount; } } abcl-src-1.9.0/src/org/armedbear/lisp/SpecialOperators.java0100644 0000000 0000000 00000053020 14223403213 022321 0ustar000000000 0000000 /* * SpecialOperators.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.ArrayList; import java.util.LinkedList; public final class SpecialOperators { // ### quote private static final SpecialOperator QUOTE = new sf_quote(); private static final class sf_quote extends SpecialOperator { sf_quote() { super(Symbol.QUOTE, "thing"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.cdr() != NIL) return error(new WrongNumberOfArgumentsException(this, 1)); return args.car(); } }; // ### if private static final SpecialOperator IF = new sf_if(); private static final class sf_if extends SpecialOperator { sf_if() { super(Symbol.IF, "test then &optional else"); } @Override public LispObject execute(LispObject args, Environment env) { final LispThread thread = LispThread.currentThread(); switch (args.length()) { case 2: { if (eval(((Cons)args).car, env, thread) != NIL) return eval(args.cadr(), env, thread); thread.clearValues(); return NIL; } case 3: { if (eval(((Cons)args).car, env, thread) != NIL) return eval(args.cadr(), env, thread); return eval((((Cons)args).cdr).cadr(), env, thread); } default: return error(new WrongNumberOfArgumentsException(this, 2, 3)); } } }; // ### let private static final SpecialOperator LET = new sf_let(); private static final class sf_let extends SpecialOperator { sf_let() { super(Symbol.LET, "bindings &body body"); } @Override public LispObject execute(LispObject args, Environment env) { if (args == NIL) return error(new WrongNumberOfArgumentsException(this, 1, -1)); return _let(args, env, false); } }; // ### let* private static final SpecialOperator LET_STAR = new sf_let_star(); private static final class sf_let_star extends SpecialOperator { sf_let_star() { super(Symbol.LET_STAR, "bindings &body body"); } @Override public LispObject execute(LispObject args, Environment env) { if (args == NIL) return error(new WrongNumberOfArgumentsException(this, 1, -1)); return _let(args, env, true); } }; static final LispObject _let(LispObject args, Environment env, boolean sequential) { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); Environment ext = new Environment(env); thread.envStack.push(ext); try { LispObject varList = checkList(args.car()); LispObject bodyAndDecls = parseBody(args.cdr(), false); LispObject specials = parseSpecials(bodyAndDecls.NTH(1)); LispObject body = bodyAndDecls.car(); LinkedList nonSequentialVars = new LinkedList(); while (varList != NIL) { final Symbol symbol; LispObject value; LispObject obj = varList.car(); if (obj instanceof Cons) { if (obj.length() > 2) return error(new LispError("The " + (sequential ? "LET*" : "LET") + " binding specification " + obj.princToString() + " is invalid.")); symbol = checkSymbol(((Cons)obj).car); value = eval(obj.cadr(), sequential ? ext : env, thread); } else { symbol = checkSymbol(obj); value = NIL; } if (sequential) { ext = new Environment(ext); thread.envStack.push(ext); bindArg(specials, symbol, value, ext, thread); } else nonSequentialVars.add(new Cons(symbol, value)); varList = ((Cons)varList).cdr; } if (!sequential) for (Cons x : nonSequentialVars) bindArg(specials, (Symbol)x.car(), x.cdr(), ext, thread); // Make sure free special declarations are visible in the body. // "The scope of free declarations specifically does not include // initialization forms for bindings established by the form // containing the declarations." (3.3.4) for (; specials != NIL; specials = specials.cdr()) ext.declareSpecial((Symbol)specials.car()); return progn(body, ext, thread); } finally { thread.resetSpecialBindings(mark); while (thread.envStack.pop() != ext) {}; } } // ### symbol-macrolet private static final SpecialOperator SYMBOL_MACROLET = new sf_symbol_macrolet(); private static final class sf_symbol_macrolet extends SpecialOperator { sf_symbol_macrolet() { super(Symbol.SYMBOL_MACROLET, "macrobindings &body body"); } @Override public LispObject execute(LispObject args, Environment env) { LispObject varList = checkList(args.car()); final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); Environment ext = new Environment(env); try { thread.envStack.push(ext); // Declare our free specials, this will correctly raise LispObject body = ext.processDeclarations(args.cdr()); for (int i = varList.length(); i-- > 0;) { LispObject obj = varList.car(); varList = varList.cdr(); if (obj instanceof Cons && obj.length() == 2) { Symbol symbol = checkSymbol(obj.car()); if (symbol.isSpecialVariable() || ext.isDeclaredSpecial(symbol)) { return program_error("Attempt to bind the special variable " + symbol.princToString() + " with SYMBOL-MACROLET."); } ext.bind(symbol, new SymbolMacro(obj.cadr())); } else { return program_error("Malformed symbol-expansion pair in SYMBOL-MACROLET: " + obj.princToString() + "."); } } return progn(body, ext, thread); } finally { thread.resetSpecialBindings(mark); while (thread.envStack.pop() != ext) {}; } } }; // ### load-time-value form &optional read-only-p => object private static final SpecialOperator LOAD_TIME_VALUE = new sf_load_time_value(); private static final class sf_load_time_value extends SpecialOperator { sf_load_time_value() { super(Symbol.LOAD_TIME_VALUE, "form &optional read-only-p"); } @Override public LispObject execute(LispObject args, Environment env) { switch (args.length()) { case 1: case 2: return eval(args.car(), new Environment(), LispThread.currentThread()); default: return error(new WrongNumberOfArgumentsException(this, 1, 2)); } } }; // ### locally private static final SpecialOperator LOCALLY = new sf_locally(); private static final class sf_locally extends SpecialOperator { sf_locally() { super(Symbol.LOCALLY, "&body body"); } @Override public LispObject execute(LispObject args, Environment env) { final LispThread thread = LispThread.currentThread(); final Environment ext = new Environment(env); try { thread.envStack.push(ext); args = ext.processDeclarations(args); return progn(args, ext, thread); } finally { while (thread.envStack.pop() != ext) {}; } } }; // ### progn private static final SpecialOperator PROGN = new sf_progn(); private static final class sf_progn extends SpecialOperator { sf_progn() { super(Symbol.PROGN, "&rest forms"); } @Override public LispObject execute(LispObject args, Environment env) { LispThread thread = LispThread.currentThread(); return progn(args, env, thread); } }; // ### flet private static final SpecialOperator FLET = new sf_flet(); private static final class sf_flet extends SpecialOperator { sf_flet() { super(Symbol.FLET, "definitions &body body"); } @Override public LispObject execute(LispObject args, Environment env) { return _flet(args, env, false); } }; // ### labels private static final SpecialOperator LABELS = new sf_labels(); private static final class sf_labels extends SpecialOperator { sf_labels() { super(Symbol.LABELS, "definitions &body body"); } @Override public LispObject execute(LispObject args, Environment env) { return _flet(args, env, true); } }; static final LispObject _flet(LispObject args, Environment env, boolean recursive) { // First argument is a list of local function definitions. LispObject defs = checkList(args.car()); final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); final Environment funEnv = new Environment(env); while (defs != NIL) { final LispObject def = checkList(defs.car()); final LispObject name = def.car(); final Symbol symbol; if (name instanceof Symbol) { symbol = checkSymbol(name); if (symbol.getSymbolFunction() instanceof SpecialOperator) { return program_error(symbol.getName() + " is a special operator and may not be redefined."); } } else if (isValidSetfFunctionName(name)) symbol = checkSymbol(name.cadr()); else return type_error(name, FUNCTION_NAME); LispObject rest = def.cdr(); LispObject parameters = rest.car(); LispObject body = rest.cdr(); LispObject decls = NIL; while (body.car() instanceof Cons && body.car().car() == Symbol.DECLARE) { decls = new Cons(body.car(), decls); body = body.cdr(); } body = new Cons(symbol, body); body = new Cons(Symbol.BLOCK, body); body = new Cons(body, NIL); while (decls != NIL) { body = new Cons(decls.car(), body); decls = decls.cdr(); } LispObject lambda_expression = new Cons(Symbol.LAMBDA, new Cons(parameters, body)); LispObject lambda_name = list(recursive ? Symbol.LABELS : Symbol.FLET, name); Closure closure = new Closure(lambda_name, lambda_expression, recursive ? funEnv : env); funEnv.addFunctionBinding(name, closure); defs = defs.cdr(); } try { final Environment ext = new Environment(funEnv); LispObject body = args.cdr(); body = ext.processDeclarations(body); return progn(body, ext, thread); } finally { thread.resetSpecialBindings(mark); } } // ### the value-type form => result* private static final SpecialOperator THE = new sf_the(); private static final class sf_the extends SpecialOperator { sf_the() { super(Symbol.THE, "type value"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() != 2) return error(new WrongNumberOfArgumentsException(this, 2)); LispObject rv = eval(args.cadr(), env, LispThread.currentThread()); // check only the most simple types: single symbols // (class type specifiers/primitive types) // DEFTYPE-d types need expansion; // doing so would slow down our execution too much // An implementation is allowed not to check the type, // the fact that we do so here is mainly driven by the // requirement to verify argument types in structure-slot // accessors (defstruct.lisp) // The policy below is in line with the level of verification // in the compiler at *safety* levels below 3 LispObject type = args.car(); if ((type instanceof Symbol && get(type, Symbol.DEFTYPE_DEFINITION) == NIL) || type instanceof BuiltInClass) if (rv.typep(type) == NIL) type_error(rv, type); return rv; } }; // ### progv private static final SpecialOperator PROGV = new sf_progv(); private static final class sf_progv extends SpecialOperator { sf_progv() { super(Symbol.PROGV, "symbols values &body body"); } @Override public LispObject execute(LispObject args, Environment env) { if (args.length() < 2) return error(new WrongNumberOfArgumentsException(this, 2, -1)); final LispThread thread = LispThread.currentThread(); final LispObject symbols = checkList(eval(args.car(), env, thread)); LispObject values = checkList(eval(args.cadr(), env, thread)); final SpecialBindingsMark mark = thread.markSpecialBindings(); try { // Set up the new bindings. progvBindVars(symbols, values, thread); // Implicit PROGN. return progn(args.cdr().cdr(), env, thread); } finally { thread.resetSpecialBindings(mark); } } }; // ### declare private static final SpecialOperator DECLARE = new sf_declare(); private static final class sf_declare extends SpecialOperator { sf_declare() { super(Symbol.DECLARE, "&rest declaration-specifiers"); } @Override public LispObject execute(LispObject args, Environment env) { return NIL; } }; // ### function private static final SpecialOperator FUNCTION = new sf_function(); private static final class sf_function extends SpecialOperator { sf_function() { super(Symbol.FUNCTION, "thing"); } @Override public LispObject execute(LispObject args, Environment env) { final LispObject arg = args.car(); if (arg instanceof Symbol) { LispObject operator = env.lookupFunction(arg); if (operator instanceof Autoload) { Autoload autoload = (Autoload) operator; autoload.load(); operator = autoload.getSymbol().getSymbolFunction(); } if (operator instanceof Function) return operator; if (operator instanceof FuncallableStandardObject) return operator; return error(new UndefinedFunction(arg)); } if (arg instanceof Cons) { LispObject car = ((Cons)arg).car; if (car == Symbol.SETF) { LispObject f = env.lookupFunction(arg); if (f != null) return f; Symbol symbol = checkSymbol(arg.cadr()); f = get(symbol, Symbol.SETF_FUNCTION, null); if (f != null) return f; f = get(symbol, Symbol.SETF_INVERSE, null); if (f != null) return f; } if (car == Symbol.LAMBDA) return new Closure(arg, env); if (car == Symbol.NAMED_LAMBDA) { LispObject name = arg.cadr(); if (name instanceof Symbol || isValidSetfFunctionName(name)) { return new Closure(name, new Cons(Symbol.LAMBDA, arg.cddr()), env); } return type_error(name, FUNCTION_NAME); } if (car == Symbol.MACRO_FUNCTION) return new Closure(arg, env); } return error(new UndefinedFunction(list(Keyword.NAME, arg))); } }; // ### setq private static final SpecialOperator SETQ = new sf_setq(); private static final class sf_setq extends SpecialOperator { sf_setq() { super(Symbol.SETQ, "&rest vars-and-values"); } @Override public LispObject execute(LispObject args, Environment env) { LispObject value = Nil.NIL; final LispThread thread = LispThread.currentThread(); while (args != NIL) { Symbol symbol = checkSymbol(args.car()); if (symbol.isConstant()) { return program_error(symbol.princToString() + " is a constant and thus cannot be set."); } args = args.cdr(); if (symbol.isSpecialVariable() || env.isDeclaredSpecial(symbol)) { SpecialBinding binding = thread.getSpecialBinding(symbol); value = eval(args.car(), env, thread); if (binding != null) { binding.value = value; } else { symbol.setSymbolValue(value); } } else { // Not special. Binding binding = env.getBinding(symbol); if (binding != null) { if (binding.value instanceof SymbolMacro) { LispObject expansion = ((SymbolMacro)binding.value).getExpansion(); LispObject form = list(Symbol.SETF, expansion, args.car()); value = eval(form, env, thread); } else { value = eval(args.car(), env, thread); binding.value = value; } } else { if (symbol.getSymbolMacro() != null) { LispObject expansion = symbol.getSymbolMacro().getExpansion(); LispObject form = list(Symbol.SETF, expansion, args.car()); value = eval(form, env, thread); } else { value = eval(args.car(), env, thread); symbol.setSymbolValue(value); } } } args = args.cdr(); } // Return primary value only! thread._values = null; return value; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/StackFrame.java0100644 0000000 0000000 00000004730 14202767264 021106 0ustar000000000 0000000 /* * StackFrame.java * * Copyright (C) 2009 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public abstract class StackFrame extends LispObject { @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.STACK_FRAME) return T; if (typeSpecifier == BuiltInClass.STACK_FRAME) return T; return super.typep(typeSpecifier); } StackFrame next; Environment env = null; void setNext(StackFrame nextFrame) { this.next = nextFrame; } StackFrame getNext() { return this.next; } /** Sets the applicable environment for this stack frame to 'env', * returning the last value. */ public Environment setEnv(Environment env) { Environment e = this.env; this.env = env; return e; } /** Gets the current lexical environment of this stack frame. */ public Environment getEnv() { return env; } public abstract LispObject toLispList(); public abstract SimpleString toLispString(); } abcl-src-1.9.0/src/org/armedbear/lisp/StandardClass.java0100644 0000000 0000000 00000077622 14202767264 021626 0ustar000000000 0000000 /* * StandardClass.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class StandardClass extends SlotClass { // Slot names for standard-class. Must agree with // redefine-class-forwarder calls in clos.lisp. public static Symbol symName = Symbol.NAME; public static Symbol symLayout = Symbol.LAYOUT; public static Symbol symDirectSuperclasses = Symbol.DIRECT_SUPERCLASSES; public static Symbol symDirectSubclasses = Symbol.DIRECT_SUBCLASSES; public static Symbol symPrecedenceList = Symbol.PRECEDENCE_LIST; public static Symbol symDirectMethods = Symbol.DIRECT_METHODS; public static Symbol symDirectSlots = Symbol.DIRECT_SLOTS; public static Symbol symSlots = Symbol.SLOTS; public static Symbol symDirectDefaultInitargs = Symbol.DIRECT_DEFAULT_INITARGS; public static Symbol symDefaultInitargs = Symbol.DEFAULT_INITARGS; public static Symbol symFinalizedP = Symbol.FINALIZED_P; // used as init-function for slots in this file. static Function constantlyNil = new Function() { @Override public LispObject execute() { return NIL; } }; static Layout layoutStandardClass = new Layout(null, list(symName, symLayout, symDirectSuperclasses, symDirectSubclasses, symPrecedenceList, symDirectMethods, symDirectSlots, symSlots, symDirectDefaultInitargs, symDefaultInitargs, symFinalizedP, Symbol._DOCUMENTATION), NIL) { @Override public LispClass getLispClass() { return STANDARD_CLASS; } }; static Layout layoutFuncallableStandardClass = new Layout(null, list(symName, symLayout, symDirectSuperclasses, symDirectSubclasses, symPrecedenceList, symDirectMethods, symDirectSlots, symSlots, symDirectDefaultInitargs, symDefaultInitargs, symFinalizedP, Symbol._DOCUMENTATION), NIL) { @Override public LispClass getLispClass() { return FUNCALLABLE_STANDARD_CLASS; } }; public StandardClass() { super(layoutStandardClass); setDirectSuperclasses(NIL); setDirectSubclasses(NIL); setClassLayout(layoutStandardClass); setCPL(NIL); setDirectMethods(NIL); setDocumentation(NIL); setDirectSlotDefinitions(NIL); setSlotDefinitions(NIL); setDirectDefaultInitargs(NIL); setDefaultInitargs(NIL); setFinalized(false); } public StandardClass(Symbol symbol, LispObject directSuperclasses) { super(layoutStandardClass, symbol, directSuperclasses); setDirectSubclasses(NIL); setClassLayout(layoutStandardClass); setCPL(NIL); setDirectMethods(NIL); setDocumentation(NIL); setDirectSlotDefinitions(NIL); setSlotDefinitions(NIL); setDirectDefaultInitargs(NIL); setDefaultInitargs(NIL); setFinalized(false); } public StandardClass(Layout layout) { super(layout); setDirectSuperclasses(NIL); setDirectSubclasses(NIL); setClassLayout(layout); setCPL(NIL); setDirectMethods(NIL); setDocumentation(NIL); setDirectSlotDefinitions(NIL); setSlotDefinitions(NIL); setDirectDefaultInitargs(NIL); setDefaultInitargs(NIL); setFinalized(false); } public StandardClass(Layout layout, Symbol symbol, LispObject directSuperclasses) { super(layout, symbol, directSuperclasses); setDirectSubclasses(NIL); setClassLayout(layout); setCPL(NIL); setDirectMethods(NIL); setDocumentation(NIL); setDirectSlotDefinitions(NIL); setSlotDefinitions(NIL); setDirectDefaultInitargs(NIL); setDefaultInitargs(NIL); setFinalized(false); } @Override public LispObject getName() { return getInstanceSlotValue(symName); } @Override public void setName(LispObject newName) { setInstanceSlotValue(symName, newName); } @Override public Layout getClassLayout() { LispObject layout = getInstanceSlotValue(symLayout); if (layout == UNBOUND_VALUE) return null; if (! (layout instanceof Layout)) { // (new Error()).printStackTrace(); // LispThread.currentThread().printBacktrace(); // System.err.println("Class: " + this.princToString()); return (Layout)Lisp.error(Symbol.TYPE_ERROR, new SimpleString("The value " + layout.princToString() + " is not of expected type " + Symbol.LAYOUT.princToString() + " in class " + this.princToString() + ".")); } return (layout == UNBOUND_VALUE) ? null : (Layout)layout; } @Override public void setClassLayout(LispObject newLayout) { setInstanceSlotValue(symLayout, newLayout); } @Override public LispObject getDirectSuperclasses() { return getInstanceSlotValue(symDirectSuperclasses); } @Override public void setDirectSuperclasses(LispObject directSuperclasses) { setInstanceSlotValue(symDirectSuperclasses, directSuperclasses); } @Override public final boolean isFinalized() { return getInstanceSlotValue(symFinalizedP) != NIL; } @Override public final void setFinalized(boolean b) { setInstanceSlotValue(symFinalizedP, b ? T : NIL); } @Override public LispObject getDirectSubclasses() { return getInstanceSlotValue(symDirectSubclasses); } @Override public void setDirectSubclasses(LispObject directSubclasses) { setInstanceSlotValue(symDirectSubclasses, directSubclasses); } @Override public LispObject getCPL() { return getInstanceSlotValue(symPrecedenceList); } @Override public void setCPL(LispObject... cpl) { LispObject obj1 = cpl[0]; if (obj1.listp() && cpl.length == 1) setInstanceSlotValue(symPrecedenceList, obj1); else { Debug.assertTrue(obj1 == this); LispObject l = NIL; for (int i = cpl.length; i-- > 0;) l = new Cons(cpl[i], l); setInstanceSlotValue(symPrecedenceList, l); } } @Override public LispObject getDirectMethods() { return getInstanceSlotValue(symDirectMethods); } @Override public void setDirectMethods(LispObject methods) { setInstanceSlotValue(symDirectMethods, methods); } @Override public LispObject getDocumentation() { return getInstanceSlotValue(Symbol._DOCUMENTATION); } @Override public void setDocumentation(LispObject doc) { setInstanceSlotValue(Symbol._DOCUMENTATION, doc); } @Override public LispObject getDirectSlotDefinitions() { return getInstanceSlotValue(symDirectSlots); } @Override public void setDirectSlotDefinitions(LispObject directSlotDefinitions) { setInstanceSlotValue(symDirectSlots, directSlotDefinitions); } @Override public LispObject getSlotDefinitions() { return getInstanceSlotValue(symSlots); } @Override public void setSlotDefinitions(LispObject slotDefinitions) { setInstanceSlotValue(symSlots, slotDefinitions); } @Override public LispObject getDirectDefaultInitargs() { return getInstanceSlotValue(symDirectDefaultInitargs); } @Override public void setDirectDefaultInitargs(LispObject directDefaultInitargs) { setInstanceSlotValue(symDirectDefaultInitargs, directDefaultInitargs); } @Override public LispObject getDefaultInitargs() { return getInstanceSlotValue(symDefaultInitargs); } @Override public void setDefaultInitargs(LispObject defaultInitargs) { setInstanceSlotValue(symDefaultInitargs, defaultInitargs); } @Override public LispObject typeOf() { return Symbol.STANDARD_CLASS; } @Override public LispObject classOf() { return STANDARD_CLASS; } @Override public LispObject typep(LispObject type) { if (type == Symbol.STANDARD_CLASS) return T; if (type == STANDARD_CLASS) return T; return super.typep(type); } @Override public String printObject() { StringBuilder sb = new StringBuilder(Symbol.STANDARD_CLASS.printObject()); if (getName() != null) { sb.append(' '); sb.append(getName().printObject()); } return unreadableString(sb.toString()); } private static final LispObject standardClassSlotDefinitions() { return list(new SlotDefinition(symName, list(Symbol.CLASS_NAME), constantlyNil), new SlotDefinition(symLayout, list(Symbol.CLASS_LAYOUT), constantlyNil), new SlotDefinition(symDirectSuperclasses, list(Symbol.CLASS_DIRECT_SUPERCLASSES), constantlyNil), new SlotDefinition(symDirectSubclasses, list(Symbol.CLASS_DIRECT_SUBCLASSES), constantlyNil), new SlotDefinition(symPrecedenceList, list(Symbol.CLASS_PRECEDENCE_LIST), constantlyNil), new SlotDefinition(symDirectMethods, list(Symbol.CLASS_DIRECT_METHODS), constantlyNil), new SlotDefinition(symDirectSlots, list(Symbol.CLASS_DIRECT_SLOTS), constantlyNil), new SlotDefinition(symSlots, list(Symbol.CLASS_SLOTS), constantlyNil), new SlotDefinition(symDirectDefaultInitargs, list(Symbol.CLASS_DIRECT_DEFAULT_INITARGS), constantlyNil), new SlotDefinition(symDefaultInitargs, list(Symbol.CLASS_DEFAULT_INITARGS), constantlyNil), new SlotDefinition(symFinalizedP, list(Symbol.CLASS_FINALIZED_P), constantlyNil), new SlotDefinition(Symbol._DOCUMENTATION, list(Symbol.CLASS_DOCUMENTATION), constantlyNil, list(internKeyword("DOCUMENTATION")))); } private static final StandardClass addStandardClass(Symbol name, LispObject directSuperclasses) { StandardClass c = new StandardClass(name, directSuperclasses); addClass(name, c); return c; } private static final FuncallableStandardClass addFuncallableStandardClass (Symbol name, LispObject directSuperclasses) { FuncallableStandardClass c = new FuncallableStandardClass(name, directSuperclasses); addClass(name, c); return c; } // At this point, BuiltInClass.java has not been completely loaded yet, and // BuiltInClass.CLASS_T is null. So we need to call setDirectSuperclass() // for STANDARD_CLASS and STANDARD_OBJECT in initializeStandardClasses() // below. public static final StandardClass STANDARD_CLASS = addStandardClass(Symbol.STANDARD_CLASS, list(BuiltInClass.CLASS_T)); public static final StandardClass STANDARD_OBJECT = addStandardClass(Symbol.STANDARD_OBJECT, list(BuiltInClass.CLASS_T)); public static final StandardClass METAOBJECT = addStandardClass(Symbol.METAOBJECT, list(STANDARD_OBJECT)); public static final StandardClass SPECIALIZER = addStandardClass(Symbol.SPECIALIZER, list(METAOBJECT)); public static final StandardClass SLOT_DEFINITION = addStandardClass(Symbol.SLOT_DEFINITION, list(METAOBJECT)); public static final StandardClass STANDARD_SLOT_DEFINITION = addClass(Symbol.STANDARD_SLOT_DEFINITION, new SlotDefinitionClass(Symbol.STANDARD_SLOT_DEFINITION, list(SLOT_DEFINITION))); static { SLOT_DEFINITION.finalizeClass(); STANDARD_CLASS.setClassLayout(layoutStandardClass); STANDARD_CLASS.setDirectSlotDefinitions(standardClassSlotDefinitions()); } public static final StandardClass DIRECT_SLOT_DEFINITION = addStandardClass(Symbol.DIRECT_SLOT_DEFINITION, list(SLOT_DEFINITION)); public static final StandardClass EFFECTIVE_SLOT_DEFINITION = addStandardClass(Symbol.EFFECTIVE_SLOT_DEFINITION, list(SLOT_DEFINITION)); // addStandardClass(Symbol.STANDARD_SLOT_DEFINITION, list(SLOT_DEFINITION)); public static final StandardClass STANDARD_DIRECT_SLOT_DEFINITION = addClass(Symbol.STANDARD_DIRECT_SLOT_DEFINITION, new SlotDefinitionClass(Symbol.STANDARD_DIRECT_SLOT_DEFINITION, list(STANDARD_SLOT_DEFINITION, DIRECT_SLOT_DEFINITION))); public static final StandardClass STANDARD_EFFECTIVE_SLOT_DEFINITION = addClass(Symbol.STANDARD_EFFECTIVE_SLOT_DEFINITION, new SlotDefinitionClass(Symbol.STANDARD_EFFECTIVE_SLOT_DEFINITION, list(STANDARD_SLOT_DEFINITION, EFFECTIVE_SLOT_DEFINITION))); // BuiltInClass.FUNCTION is also null here (see previous comment). // Following SBCL's lead, we make funcallable-standard-object a // funcallable-standard-class. public static final StandardClass FUNCALLABLE_STANDARD_OBJECT = addFuncallableStandardClass(Symbol.FUNCALLABLE_STANDARD_OBJECT, list(STANDARD_OBJECT, BuiltInClass.FUNCTION)); public static final StandardClass CLASS = addStandardClass(Symbol.CLASS, list(SPECIALIZER)); public static final StandardClass BUILT_IN_CLASS = addStandardClass(Symbol.BUILT_IN_CLASS, list(CLASS)); public static final StandardClass FUNCALLABLE_STANDARD_CLASS = addStandardClass(Symbol.FUNCALLABLE_STANDARD_CLASS, list(CLASS)); public static final StandardClass CONDITION = addStandardClass(Symbol.CONDITION, list(STANDARD_OBJECT)); public static final StandardClass SIMPLE_CONDITION = addStandardClass(Symbol.SIMPLE_CONDITION, list(CONDITION)); public static final StandardClass WARNING = addStandardClass(Symbol.WARNING, list(CONDITION)); public static final StandardClass SIMPLE_WARNING = addStandardClass(Symbol.SIMPLE_WARNING, list(SIMPLE_CONDITION, WARNING)); public static final StandardClass STYLE_WARNING = addStandardClass(Symbol.STYLE_WARNING, list(WARNING)); public static final StandardClass SERIOUS_CONDITION = addStandardClass(Symbol.SERIOUS_CONDITION, list(CONDITION)); public static final StandardClass STORAGE_CONDITION = addStandardClass(Symbol.STORAGE_CONDITION, list(SERIOUS_CONDITION)); public static final StandardClass ERROR = addStandardClass(Symbol.ERROR, list(SERIOUS_CONDITION)); public static final StandardClass ARITHMETIC_ERROR = addStandardClass(Symbol.ARITHMETIC_ERROR, list(ERROR)); public static final StandardClass CELL_ERROR = addStandardClass(Symbol.CELL_ERROR, list(ERROR)); public static final StandardClass CONTROL_ERROR = addStandardClass(Symbol.CONTROL_ERROR, list(ERROR)); public static final StandardClass FILE_ERROR = addStandardClass(Symbol.FILE_ERROR, list(ERROR)); public static final StandardClass DIVISION_BY_ZERO = addStandardClass(Symbol.DIVISION_BY_ZERO, list(ARITHMETIC_ERROR)); public static final StandardClass FLOATING_POINT_INEXACT = addStandardClass(Symbol.FLOATING_POINT_INEXACT, list(ARITHMETIC_ERROR)); public static final StandardClass FLOATING_POINT_INVALID_OPERATION = addStandardClass(Symbol.FLOATING_POINT_INVALID_OPERATION, list(ARITHMETIC_ERROR)); public static final StandardClass FLOATING_POINT_OVERFLOW = addStandardClass(Symbol.FLOATING_POINT_OVERFLOW, list(ARITHMETIC_ERROR)); public static final StandardClass FLOATING_POINT_UNDERFLOW = addStandardClass(Symbol.FLOATING_POINT_UNDERFLOW, list(ARITHMETIC_ERROR)); public static final StandardClass PROGRAM_ERROR = addStandardClass(Symbol.PROGRAM_ERROR, list(ERROR)); public static final StandardClass PACKAGE_ERROR = addStandardClass(Symbol.PACKAGE_ERROR, list(ERROR)); public static final StandardClass STREAM_ERROR = addStandardClass(Symbol.STREAM_ERROR, list(ERROR)); public static final StandardClass PARSE_ERROR = addStandardClass(Symbol.PARSE_ERROR, list(ERROR)); public static final StandardClass PRINT_NOT_READABLE = addStandardClass(Symbol.PRINT_NOT_READABLE, list(ERROR)); public static final StandardClass READER_ERROR = addStandardClass(Symbol.READER_ERROR, list(PARSE_ERROR, STREAM_ERROR)); public static final StandardClass END_OF_FILE = addStandardClass(Symbol.END_OF_FILE, list(STREAM_ERROR)); public static final StandardClass SIMPLE_ERROR = addStandardClass(Symbol.SIMPLE_ERROR, list(SIMPLE_CONDITION, ERROR)); public static final StandardClass TYPE_ERROR = addStandardClass(Symbol.TYPE_ERROR, list(ERROR)); public static final StandardClass SIMPLE_TYPE_ERROR = addStandardClass(Symbol.SIMPLE_TYPE_ERROR, list(SIMPLE_CONDITION, TYPE_ERROR)); public static final StandardClass UNBOUND_SLOT = addStandardClass(Symbol.UNBOUND_SLOT, list(CELL_ERROR)); public static final StandardClass UNBOUND_VARIABLE = addStandardClass(Symbol.UNBOUND_VARIABLE, list(CELL_ERROR)); public static final StandardClass UNDEFINED_FUNCTION = addStandardClass(Symbol.UNDEFINED_FUNCTION, list(CELL_ERROR)); public static final StandardClass JAVA_EXCEPTION = addStandardClass(Symbol.JAVA_EXCEPTION, list(ERROR)); public static final StandardClass METHOD = addStandardClass(Symbol.METHOD, list(METAOBJECT)); public static final StandardClass STANDARD_METHOD = addStandardClass(Symbol.STANDARD_METHOD, list(METHOD)); public static void initializeStandardClasses() { // We need to call setDirectSuperclass() here for classes that have a // BuiltInClass as a superclass. See comment above (at first mention of // STANDARD_OBJECT). STANDARD_CLASS.setDirectSuperclass(CLASS); STANDARD_OBJECT.setDirectSuperclass(BuiltInClass.CLASS_T); FUNCALLABLE_STANDARD_OBJECT.setDirectSuperclasses(list(STANDARD_OBJECT, BuiltInClass.FUNCTION)); ARITHMETIC_ERROR.setCPL(ARITHMETIC_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); ARITHMETIC_ERROR.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.OPERATION, list(Symbol.ARITHMETIC_ERROR_OPERATION)), new SlotDefinition(Symbol.OPERANDS, list(Symbol.ARITHMETIC_ERROR_OPERANDS)))); BUILT_IN_CLASS.setCPL(BUILT_IN_CLASS, CLASS, SPECIALIZER, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); CELL_ERROR.setCPL(CELL_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); CELL_ERROR.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.NAME, list(Symbol.CELL_ERROR_NAME)))); CLASS.setCPL(CLASS, SPECIALIZER, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); CONDITION.setCPL(CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); CONDITION.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.FORMAT_CONTROL, list(Symbol.SIMPLE_CONDITION_FORMAT_CONTROL)), new SlotDefinition(Symbol.FORMAT_ARGUMENTS, list(Symbol.SIMPLE_CONDITION_FORMAT_ARGUMENTS), NIL))); CONDITION.setDirectDefaultInitargs(list(list(Keyword.FORMAT_ARGUMENTS, NIL, constantlyNil))); CONTROL_ERROR.setCPL(CONTROL_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); DIVISION_BY_ZERO.setCPL(DIVISION_BY_ZERO, ARITHMETIC_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); END_OF_FILE.setCPL(END_OF_FILE, STREAM_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); ERROR.setCPL(ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); FILE_ERROR.setCPL(FILE_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); FILE_ERROR.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.PATHNAME, list(Symbol.FILE_ERROR_PATHNAME)))); FLOATING_POINT_INEXACT.setCPL(FLOATING_POINT_INEXACT, ARITHMETIC_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); FLOATING_POINT_INVALID_OPERATION.setCPL(FLOATING_POINT_INVALID_OPERATION, ARITHMETIC_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); FLOATING_POINT_OVERFLOW.setCPL(FLOATING_POINT_OVERFLOW, ARITHMETIC_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); FLOATING_POINT_UNDERFLOW.setCPL(FLOATING_POINT_UNDERFLOW, ARITHMETIC_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); FUNCALLABLE_STANDARD_OBJECT.setCPL(FUNCALLABLE_STANDARD_OBJECT, STANDARD_OBJECT, BuiltInClass.FUNCTION, BuiltInClass.CLASS_T); JAVA_EXCEPTION.setCPL(JAVA_EXCEPTION, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); JAVA_EXCEPTION.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.CAUSE, list(Symbol.JAVA_EXCEPTION_CAUSE)))); METAOBJECT.setCPL(METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); SPECIALIZER.setCPL(SPECIALIZER, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); METHOD.setCPL(METHOD, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); STANDARD_METHOD.setCPL(STANDARD_METHOD, METHOD, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); STANDARD_METHOD.setDirectSlotDefinitions( list(new SlotDefinition(Symbol._GENERIC_FUNCTION, NIL, constantlyNil, list(internKeyword("GENERIC-FUNCTION"))), new SlotDefinition(Symbol.LAMBDA_LIST, NIL, constantlyNil), new SlotDefinition(Symbol.KEYWORDS, NIL, constantlyNil), new SlotDefinition(Symbol.OTHER_KEYWORDS_P, NIL, constantlyNil), new SlotDefinition(Symbol.SPECIALIZERS, NIL, constantlyNil), new SlotDefinition(Symbol.QUALIFIERS, NIL, constantlyNil), new SlotDefinition(Symbol._FUNCTION, NIL, constantlyNil, list(internKeyword("FUNCTION"))), new SlotDefinition(Symbol.FAST_FUNCTION, NIL, constantlyNil), new SlotDefinition(Symbol._DOCUMENTATION, NIL, constantlyNil, list(internKeyword("DOCUMENTATION"))))); PACKAGE_ERROR.setCPL(PACKAGE_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); PACKAGE_ERROR.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.PACKAGE, list(Symbol.PACKAGE_ERROR_PACKAGE)))); PARSE_ERROR.setCPL(PARSE_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); PRINT_NOT_READABLE.setCPL(PRINT_NOT_READABLE, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); PRINT_NOT_READABLE.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.OBJECT, list(Symbol.PRINT_NOT_READABLE_OBJECT)))); PROGRAM_ERROR.setCPL(PROGRAM_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); READER_ERROR.setCPL(READER_ERROR, PARSE_ERROR, STREAM_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); SERIOUS_CONDITION.setCPL(SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); SIMPLE_CONDITION.setCPL(SIMPLE_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); SIMPLE_ERROR.setCPL(SIMPLE_ERROR, SIMPLE_CONDITION, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); SIMPLE_TYPE_ERROR.setDirectSuperclasses(list(SIMPLE_CONDITION, TYPE_ERROR)); SIMPLE_TYPE_ERROR.setCPL(SIMPLE_TYPE_ERROR, SIMPLE_CONDITION, TYPE_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); SIMPLE_WARNING.setDirectSuperclasses(list(SIMPLE_CONDITION, WARNING)); SIMPLE_WARNING.setCPL(SIMPLE_WARNING, SIMPLE_CONDITION, WARNING, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); STANDARD_CLASS.setCPL(STANDARD_CLASS, CLASS, SPECIALIZER, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); FUNCALLABLE_STANDARD_CLASS.setCPL(FUNCALLABLE_STANDARD_CLASS, CLASS, SPECIALIZER, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); // funcallable-standard-class has the same interface as // standard-class. FUNCALLABLE_STANDARD_CLASS.setClassLayout(layoutStandardClass); FUNCALLABLE_STANDARD_CLASS.setDirectSlotDefinitions(standardClassSlotDefinitions()); STANDARD_OBJECT.setCPL(STANDARD_OBJECT, BuiltInClass.CLASS_T); STORAGE_CONDITION.setCPL(STORAGE_CONDITION, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); STREAM_ERROR.setCPL(STREAM_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); STREAM_ERROR.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.STREAM, list(Symbol.STREAM_ERROR_STREAM)))); STYLE_WARNING.setCPL(STYLE_WARNING, WARNING, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); TYPE_ERROR.setCPL(TYPE_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); TYPE_ERROR.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.DATUM, list(Symbol.TYPE_ERROR_DATUM)), new SlotDefinition(Symbol.EXPECTED_TYPE, list(Symbol.TYPE_ERROR_EXPECTED_TYPE)))); UNBOUND_SLOT.setCPL(UNBOUND_SLOT, CELL_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); UNBOUND_SLOT.setDirectSlotDefinitions( list(new SlotDefinition(Symbol.INSTANCE, list(Symbol.UNBOUND_SLOT_INSTANCE)))); UNBOUND_VARIABLE.setCPL(UNBOUND_VARIABLE, CELL_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); UNDEFINED_FUNCTION.setCPL(UNDEFINED_FUNCTION, CELL_ERROR, ERROR, SERIOUS_CONDITION, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); WARNING.setCPL(WARNING, CONDITION, STANDARD_OBJECT, BuiltInClass.CLASS_T); // Condition classes. STANDARD_CLASS.finalizeClass(); STANDARD_OBJECT.finalizeClass(); FUNCALLABLE_STANDARD_OBJECT.finalizeClass(); FUNCALLABLE_STANDARD_CLASS.finalizeClass(); ARITHMETIC_ERROR.finalizeClass(); CELL_ERROR.finalizeClass(); CONDITION.finalizeClass(); CONTROL_ERROR.finalizeClass(); DIVISION_BY_ZERO.finalizeClass(); END_OF_FILE.finalizeClass(); ERROR.finalizeClass(); FILE_ERROR.finalizeClass(); FLOATING_POINT_INEXACT.finalizeClass(); FLOATING_POINT_INVALID_OPERATION.finalizeClass(); FLOATING_POINT_OVERFLOW.finalizeClass(); FLOATING_POINT_UNDERFLOW.finalizeClass(); JAVA_EXCEPTION.finalizeClass(); METAOBJECT.finalizeClass(); METHOD.finalizeClass(); STANDARD_METHOD.finalizeClass(); SPECIALIZER.finalizeClass(); CLASS.finalizeClass(); BUILT_IN_CLASS.finalizeClass(); PACKAGE_ERROR.finalizeClass(); PARSE_ERROR.finalizeClass(); PRINT_NOT_READABLE.finalizeClass(); PROGRAM_ERROR.finalizeClass(); READER_ERROR.finalizeClass(); SERIOUS_CONDITION.finalizeClass(); SIMPLE_CONDITION.finalizeClass(); SIMPLE_ERROR.finalizeClass(); SIMPLE_TYPE_ERROR.finalizeClass(); SIMPLE_WARNING.finalizeClass(); STORAGE_CONDITION.finalizeClass(); STREAM_ERROR.finalizeClass(); STYLE_WARNING.finalizeClass(); TYPE_ERROR.finalizeClass(); UNBOUND_SLOT.finalizeClass(); UNBOUND_VARIABLE.finalizeClass(); UNDEFINED_FUNCTION.finalizeClass(); WARNING.finalizeClass(); // SYS:SLOT-DEFINITION is constructed and finalized in // SlotDefinitionClass.java, but we need to fill in a few things here. Debug.assertTrue(SLOT_DEFINITION.isFinalized()); SLOT_DEFINITION.setCPL(SLOT_DEFINITION, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); SLOT_DEFINITION.setDirectSlotDefinitions(SLOT_DEFINITION.getClassLayout().generateSlotDefinitions()); // There are no inherited slots. SLOT_DEFINITION.setSlotDefinitions(SLOT_DEFINITION.getDirectSlotDefinitions()); DIRECT_SLOT_DEFINITION.setCPL(DIRECT_SLOT_DEFINITION, SLOT_DEFINITION, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); DIRECT_SLOT_DEFINITION.finalizeClass(); EFFECTIVE_SLOT_DEFINITION.setCPL(EFFECTIVE_SLOT_DEFINITION, SLOT_DEFINITION, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); EFFECTIVE_SLOT_DEFINITION.finalizeClass(); STANDARD_SLOT_DEFINITION.setCPL(STANDARD_SLOT_DEFINITION, SLOT_DEFINITION, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); STANDARD_SLOT_DEFINITION.finalizeClass(); STANDARD_DIRECT_SLOT_DEFINITION.setCPL(STANDARD_DIRECT_SLOT_DEFINITION, STANDARD_SLOT_DEFINITION, DIRECT_SLOT_DEFINITION, SLOT_DEFINITION, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); STANDARD_DIRECT_SLOT_DEFINITION.finalizeClass(); STANDARD_EFFECTIVE_SLOT_DEFINITION.setCPL(STANDARD_EFFECTIVE_SLOT_DEFINITION, STANDARD_SLOT_DEFINITION, EFFECTIVE_SLOT_DEFINITION, SLOT_DEFINITION, METAOBJECT, STANDARD_OBJECT, BuiltInClass.CLASS_T); STANDARD_EFFECTIVE_SLOT_DEFINITION.finalizeClass(); } } abcl-src-1.9.0/src/org/armedbear/lisp/StandardObject.java0100644 0000000 0000000 00000052227 14202767264 021761 0ustar000000000 0000000 /* * StandardObject.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class StandardObject extends LispObject { protected Layout layout; protected LispObject[] slots; protected StandardObject() { layout = new Layout(StandardClass.STANDARD_OBJECT, NIL, NIL); } protected StandardObject(Layout layout) { this(layout, layout.getLength()); } protected StandardObject(Layout layout, int length) { this.layout = layout; slots = new LispObject[length]; for (int i = slots.length; i-- > 0;) slots[i] = UNBOUND_VALUE; } protected StandardObject(LispClass cls, int length) { layout = cls == null ? null : cls.getClassLayout(); slots = new LispObject[length]; for (int i = slots.length; i-- > 0;) slots[i] = UNBOUND_VALUE; } protected StandardObject(LispClass cls) { layout = cls == null ? null : cls.getClassLayout(); slots = new LispObject[layout == null ? 0 : layout.getLength()]; for (int i = slots.length; i-- > 0;) slots[i] = UNBOUND_VALUE; } @Override public LispObject getParts() { LispObject parts = NIL; if (layout != null) { if (layout.isInvalid()) { // Update instance. layout = updateLayout(); } } parts = parts.push(new Cons("LAYOUT", layout)); if (layout != null) { LispObject[] slotNames = layout.getSlotNames(); if (slotNames != null) { for (int i = 0; i < slotNames.length; i++) { parts = parts.push(new Cons(slotNames[i], slots[i])); } } } return parts.nreverse(); } public final LispObject getLispClass() { return layout.getLispClass(); } private LispObject helperGetClassName() { final LispObject c1 = layout.getLispClass(); if (c1 instanceof LispClass) return ((LispClass)c1).getName(); else return LispThread.currentThread().execute(Symbol.CLASS_NAME, c1); } private LispObject helperGetCPL() { final LispObject c1 = layout.getLispClass(); if (c1 instanceof LispClass) return ((LispClass)c1).getCPL(); else return LispThread.currentThread().execute(Symbol.CLASS_PRECEDENCE_LIST, c1); } @Override public LispObject typeOf() { // "For objects of metaclass STRUCTURE-CLASS or STANDARD-CLASS, and for // conditions, TYPE-OF returns the proper name of the class returned by // CLASS-OF if it has a proper name, and otherwise returns the class // itself." final LispObject c1 = layout.getLispClass(); LispObject name; if (c1 instanceof LispClass) name = ((LispClass)c1).getName(); else name = LispThread.currentThread().execute(Symbol.CLASS_NAME, c1); // The proper name of a class is "a symbol that names the class whose // name is that symbol". if (name != NIL && name != UNBOUND_VALUE) { // TYPE-OF.9 final LispObject c2 = LispClass.findClass(name, false); if (c2 == c1) return name; } return c1; } @Override public LispObject classOf() { return layout.getLispClass(); } @Override public LispObject typep(LispObject type) { if (type == Symbol.STANDARD_OBJECT) return T; if (type == StandardClass.STANDARD_OBJECT) return T; LispObject cls = layout != null ? layout.getLispClass() : null; if (cls != null) { if (type == cls) return T; if (type == helperGetClassName()) return T; LispObject cpl = helperGetCPL(); while (cpl != NIL) { if (type == cpl.car()) return T; LispObject otherName; LispObject otherClass = cpl.car(); if (otherClass instanceof LispClass) { if (type == ((LispClass)otherClass).getName()) return T; } else if (type == LispThread .currentThread().execute(Symbol.CLASS_NAME, otherClass)) return T; cpl = cpl.cdr(); } } return super.typep(type); } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); int maxLevel = Integer.MAX_VALUE; LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread); if (printLevel instanceof Fixnum) maxLevel = ((Fixnum)printLevel).value; LispObject currentPrintLevel = _CURRENT_PRINT_LEVEL_.symbolValue(thread); int currentLevel = Fixnum.getValue(currentPrintLevel); if (currentLevel >= maxLevel) return "#"; return unreadableString(typeOf().printObject()); } synchronized Layout updateLayout() { if (!layout.isInvalid()) return layout; Layout oldLayout = layout; LispObject cls = oldLayout.getLispClass(); Layout newLayout; if (cls instanceof LispClass) newLayout = ((LispClass)cls).getClassLayout(); else newLayout = (Layout)Symbol.CLASS_LAYOUT.execute(cls); Debug.assertTrue(!newLayout.isInvalid()); StandardObject newInstance = new StandardObject(newLayout); Debug.assertTrue(newInstance.layout == newLayout); LispObject added = NIL; LispObject discarded = NIL; LispObject plist = NIL; // Old local slots. LispObject[] oldSlotNames = oldLayout.getSlotNames(); for (int i = 0; i < oldSlotNames.length; i++) { LispObject slotName = oldSlotNames[i]; int j = newLayout.getSlotIndex(slotName); if (j >= 0) newInstance.slots[j] = slots[i]; else { discarded = discarded.push(slotName); if (slots[i] != UNBOUND_VALUE) { plist = plist.push(slotName); plist = plist.push(slots[i]); } } } // Old shared slots. LispObject rest = oldLayout.getSharedSlots(); // A list. if (rest != null) { while (rest != NIL) { LispObject location = rest.car(); LispObject slotName = location.car(); int i = newLayout.getSlotIndex(slotName); if (i >= 0) newInstance.slots[i] = location.cdr(); rest = rest.cdr(); } } // Go through all the new local slots to compute the added slots. LispObject[] newSlotNames = newLayout.getSlotNames(); for (int i = 0; i < newSlotNames.length; i++) { LispObject slotName = newSlotNames[i]; int j = oldLayout.getSlotIndex(slotName); if (j >= 0) continue; LispObject location = oldLayout.getSharedSlotLocation(slotName); if (location != null) continue; // Not found. added = added.push(slotName); } // Swap slots. LispObject[] tempSlots = slots; slots = newInstance.slots; newInstance.slots = tempSlots; // Swap layouts. Layout tempLayout = layout; layout = newInstance.layout; newInstance.layout = tempLayout; Debug.assertTrue(!layout.isInvalid()); // Call UPDATE-INSTANCE-FOR-REDEFINED-CLASS. Symbol.UPDATE_INSTANCE_FOR_REDEFINED_CLASS.execute(this, added, discarded, plist); return newLayout; } // Only handles instance slots (not shared slots). public LispObject getInstanceSlotValue(LispObject slotName) { Debug.assertTrue(layout != null); if (layout.isInvalid()) { // Update instance. layout = updateLayout(); } Debug.assertTrue(layout != null); int index = layout.getSlotIndex(slotName); if (index < 0) { // Not found. final LispThread thread = LispThread.currentThread(); // If the operation is slot-value, only the primary value [of // slot-missing] will be used by the caller, and all other values // will be ignored. LispObject value = thread.execute(Symbol.SLOT_MISSING, this.getLispClass(), this, slotName, Symbol.SLOT_VALUE); thread._values = null; return value; } return slots[index]; } // Only handles instance slots (not shared slots). public void setInstanceSlotValue(LispObject slotName, LispObject newValue) { Debug.assertTrue(layout != null); if (layout.isInvalid()) { // Update instance. layout = updateLayout(); } Debug.assertTrue(layout != null); int index = layout.getSlotIndex(slotName); if (index < 0) { // Not found. final LispThread thread = LispThread.currentThread(); // If the operation is setf or slot-makunbound, any values // [returned by slot-missing] will be ignored by the caller. thread.execute(Symbol.SLOT_MISSING, this.getLispClass(), this, slotName, Symbol.SETF, newValue); thread._values = null; } slots[index] = newValue; } final public static StandardObject checkStandardObject(LispObject first) { if (first instanceof StandardObject) return (StandardObject) first; return (StandardObject) type_error(first, Symbol.STANDARD_OBJECT); } private static final Primitive SWAP_SLOTS = new pf_swap_slots(); @DocString(name="swap-slots", args="instance-1 instance-2", returns="nil") private static final class pf_swap_slots extends Primitive { pf_swap_slots() { super("swap-slots", PACKAGE_SYS, true, "instance-1 instance-2"); } @Override public LispObject execute(LispObject first, LispObject second) { final StandardObject obj1 = checkStandardObject(first); final StandardObject obj2 = checkStandardObject(second); LispObject[] temp = obj1.slots; obj1.slots = obj2.slots; obj2.slots = temp; return NIL; } }; private static final Primitive STD_INSTANCE_LAYOUT = new pf_std_instance_layout(); @DocString(name="std-instance-layout") private static final class pf_std_instance_layout extends Primitive { pf_std_instance_layout() { super("std-instance-layout", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { final StandardObject instance = checkStandardObject(arg); Layout layout = instance.layout; if (layout.isInvalid()) { // Update instance. layout = instance.updateLayout(); } return layout; } }; private static final Primitive _SET_STD_INSTANCE_LAYOUT = new pf__set_std_instance_layout(); @DocString(name="%set-std-instance-layout") private static final class pf__set_std_instance_layout extends Primitive { pf__set_std_instance_layout() { super("%set-std-instance-layout", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { checkStandardObject(first).layout = checkLayout(second); return second; } }; private static final Primitive STD_INSTANCE_CLASS = new pf_std_instance_class(); @DocString(name="std-instance-class") private static final class pf_std_instance_class extends Primitive { pf_std_instance_class() { super("std-instance-class", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject arg) { return checkStandardObject(arg).layout.getLispClass(); } }; private static final Primitive STANDARD_INSTANCE_ACCESS = new pf_standard_instance_access(); @DocString(name="standard-instance-access", args="instance location", returns="value") private static final class pf_standard_instance_access extends Primitive { pf_standard_instance_access() { super("standard-instance-access", PACKAGE_SYS, true, "instance location"); } @Override public LispObject execute(LispObject first, LispObject second) { final StandardObject instance = checkStandardObject(first); if (instance.layout.isInvalid()) { // Update instance. instance.updateLayout(); } final int index; if (second instanceof Fixnum) { index = ((Fixnum)second).value; } else { return type_error(second, Symbol.INTEGER); } LispObject value; try { value = instance.slots[index]; } catch (ArrayIndexOutOfBoundsException e) { if (instance.slots.length > 0) return type_error(second, list(Symbol.INTEGER, Fixnum.ZERO, Fixnum.getInstance(instance.slots.length - 1))); else return program_error("The object " + instance.princToString() + " has no slots."); } // We let UNBOUND_VALUE escape here, since invoking // standard-instance-access on an unbound slot has undefined // consequences (AMOP pg. 239), and we use this behavior to // implement slot-boundp-using-class. return value; } }; private static final Primitive _SET_STANDARD_INSTANCE_ACCESS = new pf__set_standard_instance_access(); @DocString(name="%set-standard-instance-access", args="instance location new-value", returns="new-value") private static final class pf__set_standard_instance_access extends Primitive { pf__set_standard_instance_access() { super("%set-standard-instance-access", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { final StandardObject instance = checkStandardObject(first); if (instance.layout.isInvalid()) { // Update instance. instance.updateLayout(); } final int index; if (second instanceof Fixnum) { index = ((Fixnum)second).value; } else { return type_error(second, Symbol.INTEGER); } try { instance.slots[index] = third; } catch (ArrayIndexOutOfBoundsException e) { if (instance.slots.length > 0) return type_error(second, list(Symbol.INTEGER, Fixnum.ZERO, Fixnum.getInstance(instance.slots.length - 1))); else return program_error("The object " + instance.princToString() + " has no slots."); } return third; } }; private static final Primitive STD_SLOT_BOUNDP = new pf_std_slot_boundp(); @DocString(name="std-slot-boundp") private static final class pf_std_slot_boundp extends Primitive { pf_std_slot_boundp() { super(Symbol.STD_SLOT_BOUNDP, "instance slot-name"); } @Override public LispObject execute(LispObject first, LispObject second) { final StandardObject instance = checkStandardObject(first); Layout layout = instance.layout; if (layout.isInvalid()) { // Update instance. layout = instance.updateLayout(); } final LispObject index = layout.slotTable.get(second); if (index != null) { // Found instance slot. return instance.slots[((Fixnum)index).value] != UNBOUND_VALUE ? T : NIL; } // Check for shared slot. final LispObject location = layout.getSharedSlotLocation(second); if (location != null) return location.cdr() != UNBOUND_VALUE ? T : NIL; // Not found. final LispThread thread = LispThread.currentThread(); LispObject value = thread.execute(Symbol.SLOT_MISSING, instance.getLispClass(), instance, second, Symbol.SLOT_BOUNDP); // "If SLOT-MISSING is invoked and returns a value, a boolean // equivalent to its primary value is returned by SLOT-BOUNDP." thread._values = null; return value != NIL ? T : NIL; } }; @Override public LispObject SLOT_VALUE(LispObject slotName) { if (layout.isInvalid()) { // Update instance. layout = updateLayout(); } LispObject value; final LispObject index = layout.slotTable.get(slotName); if (index != null) { // Found instance slot. value = slots[((Fixnum)index).value]; } else { // Check for shared slot. LispObject location = layout.getSharedSlotLocation(slotName); if (location == null) return Symbol.SLOT_MISSING.execute(getLispClass(), this, slotName, Symbol.SLOT_VALUE); value = location.cdr(); } if (value == UNBOUND_VALUE) { value = Symbol.SLOT_UNBOUND.execute(getLispClass(), this, slotName); LispThread.currentThread()._values = null; } return value; } private static final Primitive STD_SLOT_VALUE = new pf_std_slot_value(); @DocString(name="std-slot-value") private static final class pf_std_slot_value extends Primitive { pf_std_slot_value() { super(Symbol.STD_SLOT_VALUE, "instance slot-name"); } @Override public LispObject execute(LispObject first, LispObject second) { return first.SLOT_VALUE(second); } }; @Override public void setSlotValue(LispObject slotName, LispObject newValue) { if (layout.isInvalid()) { // Update instance. layout = updateLayout(); } final LispObject index = layout.slotTable.get(slotName); if (index != null) { // Found instance slot. slots[((Fixnum)index).value] = newValue; return; } // Check for shared slot. LispObject location = layout.getSharedSlotLocation(slotName); if (location != null) { location.setCdr(newValue); return; } LispObject[] args = new LispObject[5]; args[0] = getLispClass(); args[1] = this; args[2] = slotName; args[3] = Symbol.SETF; args[4] = newValue; Symbol.SLOT_MISSING.execute(args); } private static final Primitive SET_STD_SLOT_VALUE = new pf_set_std_slot_value(); @DocString(name="set-std-slot-value") private static final class pf_set_std_slot_value extends Primitive { pf_set_std_slot_value() { super(Symbol.SET_STD_SLOT_VALUE, "instance slot-name new-value"); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { first.setSlotValue(second, third); return third; } }; private static final Primitive _STD_ALLOCATE_INSTANCE = new pf__std_allocate_instance(); @DocString(name="%std-allocate-instance", args="class", returns="instance") private static final class pf__std_allocate_instance extends Primitive { pf__std_allocate_instance() { super("%std-allocate-instance", PACKAGE_SYS, true, "class"); } @Override public LispObject execute(LispObject arg) { if (arg == StandardClass.FUNCALLABLE_STANDARD_CLASS) { return new FuncallableStandardClass(); } else if (arg == StandardClass.STANDARD_CLASS) { return new StandardClass(); } else if (arg instanceof StandardClass) { StandardClass cls = (StandardClass)arg; Layout layout = cls.getClassLayout(); if (layout == null) { program_error("No layout for class " + cls.princToString() + "."); } return new StandardObject(cls, layout.getLength()); } else if (arg.typep(StandardClass.STANDARD_CLASS) != NIL) { LispObject l = Symbol.CLASS_LAYOUT.execute(arg); if (! (l instanceof Layout)) { program_error("Invalid standard class layout for class " + arg.princToString() + "."); } return new StandardObject((Layout)l); } else { return type_error(arg, Symbol.STANDARD_CLASS); } } }; } abcl-src-1.9.0/src/org/armedbear/lisp/StorageCondition.java0100644 0000000 0000000 00000004333 14202767264 022340 0ustar000000000 0000000 /* * StorageCondition.java * * Copyright (C) 2004-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class StorageCondition extends SeriousCondition { public StorageCondition() { } public StorageCondition(LispObject initArgs) { super(initArgs); } public StorageCondition(String message) { super(message); } @Override public LispObject typeOf() { return Symbol.STORAGE_CONDITION; } @Override public LispObject classOf() { return StandardClass.STORAGE_CONDITION; } @Override public LispObject typep(LispObject type) { if (type == Symbol.STORAGE_CONDITION) return T; if (type == StandardClass.STORAGE_CONDITION) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/Stream.java0100644 0000000 0000000 00000266267 14202767264 020340 0ustar000000000 0000000 /* * Stream.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.PushbackReader; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; import java.math.BigInteger; import java.nio.charset.Charset; import java.util.BitSet; import java.util.List; import java.util.LinkedList; import java.util.SortedMap; import java.util.Set; import org.armedbear.lisp.util.DecodingReader; /** The stream class * * A base class for all Lisp built-in streams. * */ public class Stream extends StructureObject { protected LispObject elementType; protected boolean isInputStream; protected boolean isOutputStream; protected boolean isCharacterStream; protected boolean isBinaryStream; private boolean pastEnd = false; private boolean interactive; private boolean open = true; // Character input. protected PushbackReader reader; protected int offset; protected int lineNumber; // Character output. private Writer writer; /** The number of characters on the current line of output * * Used to determine whether additional line feeds are * required when calling FRESH-LINE */ protected int charPos; public enum EolStyle { RAW, CR, CRLF, LF } static final protected Symbol keywordDefault = internKeyword("DEFAULT"); static final private Symbol keywordCodePage = internKeyword("CODE-PAGE"); static final private Symbol keywordID = internKeyword("ID"); static final private Symbol keywordEolStyle = internKeyword("EOL-STYLE"); static final private Symbol keywordCR = internKeyword("CR"); static final private Symbol keywordLF = internKeyword("LF"); static final private Symbol keywordCRLF = internKeyword("CRLF"); static final private Symbol keywordRAW = internKeyword("RAW"); public final static EolStyle platformEolStyle = Utilities.isPlatformWindows ? EolStyle.CRLF : EolStyle.LF; protected EolStyle eolStyle = platformEolStyle; protected char eolChar = (eolStyle == EolStyle.CR) ? '\r' : '\n'; protected LispObject externalFormat = keywordDefault; protected String encoding = null; protected char lastChar = 0; // Binary input. private InputStream in; // Binary output. private OutputStream out; protected Stream(Symbol structureClass) { super(structureClass); } public Stream(Symbol structureClass, InputStream stream) { this(structureClass); initAsBinaryInputStream(stream); } public Stream(Symbol structureClass, Reader r) { this(structureClass); initAsCharacterInputStream(r); } public Stream(Symbol structureClass, OutputStream stream) { this(structureClass); initAsBinaryOutputStream(stream); } public Stream(Symbol structureClass, Writer w) { this(structureClass); initAsCharacterOutputStream(w); } public Stream(Symbol structureClass, InputStream inputStream, LispObject elementType) { this(structureClass, inputStream, elementType, keywordDefault); } // Input stream constructors. public Stream(Symbol structureClass, InputStream inputStream, LispObject elementType, LispObject format) { this(structureClass); this.elementType = elementType; setExternalFormat(format); if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) { Reader r = new DecodingReader(inputStream, 4096, (encoding == null) ? Charset.defaultCharset() : Charset.forName(encoding)); initAsCharacterInputStream(r); } else { isBinaryStream = true; InputStream stream = new BufferedInputStream(inputStream); initAsBinaryInputStream(stream); } } public Stream(Symbol structureClass, InputStream inputStream, LispObject elementType, boolean interactive) { this(structureClass, inputStream, elementType); setInteractive(interactive); } public Stream(Symbol structureClass, OutputStream outputStream, LispObject elementType) { this(structureClass, outputStream, elementType, keywordDefault); } // Output stream constructors. public Stream(Symbol structureClass, OutputStream outputStream, LispObject elementType, LispObject format) { this(structureClass); this.elementType = elementType; setExternalFormat(format); if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) { Writer w = (encoding == null) ? new OutputStreamWriter(outputStream) : new OutputStreamWriter(outputStream, Charset.forName(encoding).newEncoder()); initAsCharacterOutputStream(w); } else { OutputStream stream = new BufferedOutputStream(outputStream); initAsBinaryOutputStream(stream); } } public Stream(Symbol structureClass, OutputStream outputStream, LispObject elementType, boolean interactive) { this(structureClass, outputStream, elementType); setInteractive(interactive); } protected void initAsCharacterInputStream(Reader reader) { if (! (reader instanceof PushbackReader)) this.reader = new PushbackReader(reader, 5); else this.reader = (PushbackReader)reader; isInputStream = true; isCharacterStream = true; } protected void initAsBinaryInputStream(InputStream in) { this.in = in; isInputStream = true; isBinaryStream = true; } protected void initAsCharacterOutputStream(Writer writer) { this.writer = writer; isOutputStream = true; isCharacterStream = true; } protected void initAsBinaryOutputStream(OutputStream out) { this.out = out; isOutputStream = true; isBinaryStream = true; } public boolean isInputStream() { return isInputStream; } public boolean isOutputStream() { return isOutputStream; } public boolean isCharacterInputStream() { return isCharacterStream && isInputStream; } public boolean isBinaryInputStream() { return isBinaryStream && isInputStream; } public boolean isCharacterOutputStream() { return isCharacterStream && isOutputStream; } public boolean isBinaryOutputStream() { return isBinaryStream && isOutputStream; } public boolean isInteractive() { return interactive; } public void setInteractive(boolean b) { interactive = b; } public LispObject getExternalFormat() { return externalFormat; } public String getEncoding() { return encoding; } public void setExternalFormat(LispObject format) { // make sure we encode any remaining buffers with the current format finishOutput(); if (format == keywordDefault) { encoding = null; eolStyle = platformEolStyle; eolChar = (eolStyle == EolStyle.CR) ? '\r' : '\n'; externalFormat = format; return; } LispObject enc; boolean encIsCp = false; if (format instanceof Cons) { // meaning a non-empty list enc = format.car(); if (enc == keywordCodePage) { encIsCp = true; enc = getf(format.cdr(), keywordID, null); } LispObject eol = getf(format.cdr(), keywordEolStyle, keywordRAW); if (eol == keywordCR) eolStyle = EolStyle.CR; else if (eol == keywordLF) eolStyle = EolStyle.LF; else if (eol == keywordCRLF) eolStyle = EolStyle.CRLF; else if (eol != keywordRAW) ; //###FIXME: raise an error } else enc = format; if (enc.numberp()) encoding = enc.toString(); else if (enc instanceof AbstractString) encoding = enc.getStringValue(); else if (enc == keywordDefault) // This allows the user to use the encoding determined by // Java to be the default for the current environment // while still being able to set other stream options // (e.g. :EOL-STYLE) encoding = null; else if (enc instanceof Symbol) encoding = ((Symbol)enc).getName(); else ; //###FIXME: raise an error! if (encIsCp) encoding = "Cp" + encoding; eolChar = (eolStyle == EolStyle.CR) ? '\r' : '\n'; externalFormat = format; if (reader != null && reader instanceof DecodingReader) ((DecodingReader)reader).setCharset(Charset.forName(encoding)); } public static final Primitive STREAM_EXTERNAL_FORMAT = new pf_stream_external_format(); @DocString( name="stream-external-format", args="stream", doc="Returns the external format of STREAM." ) private static final class pf_stream_external_format extends Primitive { pf_stream_external_format() { super("stream-external-format", "stream"); } public LispObject execute(LispObject arg) { if (arg instanceof Stream) { return ((Stream)arg).getExternalFormat(); } else { return type_error(arg, Symbol.STREAM); } } } // DEFSETF-ed in 'setf.lisp' public static final Primitive SET_STREAM_EXTERNAL_FORMAT = new pf__set_stream_external_format(); @DocString( name="%set-stream-external-format", args="stream format" ) private static final class pf__set_stream_external_format extends Primitive { pf__set_stream_external_format() { super("%set-stream-external-format", PACKAGE_SYS, false, "stream external-format"); } public LispObject execute(LispObject stream, LispObject format) { Stream s = checkStream(stream); s.setExternalFormat(format); return format; } }; public static final Primitive AVAILABLE_ENCODINGS = new pf_available_encodings(); @DocString(name="available-encodings", returns="encodings", doc="Returns all charset encodings suitable for passing to a stream constructor available at runtime.") private static final class pf_available_encodings extends Primitive { pf_available_encodings() { super("available-encodings", PACKAGE_SYS, true); } public LispObject execute() { LispObject result = NIL; for (Symbol encoding : availableEncodings()) { result = result.push(encoding); } return result.nreverse(); } } static public List availableEncodings() { List result = new LinkedList(); SortedMap available = Charset.availableCharsets(); Set encodings = available.keySet(); for (String charset : encodings) { result.add (PACKAGE_KEYWORD.intern (charset)); } return result; } public boolean isOpen() { return open; } public void setOpen(boolean b) { open = b; } @Override public LispObject typeOf() { return Symbol.SYSTEM_STREAM; } @Override public LispObject classOf() { return BuiltInClass.SYSTEM_STREAM; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SYSTEM_STREAM) return T; if (typeSpecifier == Symbol.STREAM) return T; if (typeSpecifier == BuiltInClass.STREAM) return T; return super.typep(typeSpecifier); } public LispObject getElementType() { return elementType; } // Character input. public int getOffset() { return offset; } // Character input. public final int getLineNumber() { return lineNumber; } protected void setWriter(Writer writer) { this.writer = writer; } // Character output. public int getCharPos() { return charPos; } // Character output. public void setCharPos(int n) { charPos = n; } /** Class to abstract readtable access * * Many of the functions below (used to) exist in 2 variants. * One with hardcoded access to the FaslReadtable, the other * with hardcoded access to the *readtable* variable. * * In order to prevent code duplication, * this class abstracts access. */ public static abstract class ReadtableAccessor { /** Given the thread passed, return the applicable readtable. */ public abstract Readtable rt(LispThread thread); } /** pre-instantiated readtable accessor for the *readtable*. */ public static ReadtableAccessor currentReadtable = new ReadtableAccessor() { public Readtable rt(LispThread thread) { return (Readtable)Symbol.CURRENT_READTABLE.symbolValue(thread); } }; /** pre-instantiated readtable accessor for the fasl readtable. */ public static ReadtableAccessor faslReadtable = new ReadtableAccessor() { public Readtable rt(LispThread thread) { return FaslReadtable.getInstance(); } }; public LispObject read(boolean eofError, LispObject eofValue, boolean recursive, LispThread thread, ReadtableAccessor rta) { LispObject result = readPreservingWhitespace(eofError, eofValue, recursive, thread, rta); if (result != eofValue && !recursive) { try { if (_charReady()) { int n = _readChar(); if (n >= 0) { char c = (char) n; // ### BUG: Codepoint conversion Readtable rt = rta.rt(thread); if (!rt.isWhitespace(c)) _unreadChar(c); } } } catch (IOException e) { return error(new StreamError(this, e)); } } if (!eofError && result == eofValue) return result; if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; else return result; } // ### *sharp-equal-alist* // internal symbol private static final Symbol _SHARP_EQUAL_ALIST_ = internSpecial("*SHARP-EQUAL-ALIST*", PACKAGE_SYS, NIL); private static final Symbol _SHARP_SHARP_ALIST_ = internSpecial("*SHARP-SHARP-ALIST*", PACKAGE_SYS, NIL); public LispObject readPreservingWhitespace(boolean eofError, LispObject eofValue, boolean recursive, LispThread thread, ReadtableAccessor rta) { if (recursive) { final Readtable rt = rta.rt(thread); while (true) { int n = -1; try { n = _readChar(); } catch (IOException e) { Debug.trace(e); error(new StreamError(this, e)); } if (n < 0) { if (eofError) return error(new EndOfFile(this)); else return eofValue; } char c = (char) n; // ### BUG: Codepoint conversion if (rt.isWhitespace(c)) continue; LispObject result = processChar(thread, c, rt); if (result != null) return result; } } else { final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(_SHARP_EQUAL_ALIST_, NIL); thread.bindSpecial(_SHARP_SHARP_ALIST_, NIL); try { return readPreservingWhitespace(eofError, eofValue, true, thread, rta); } finally { thread.resetSpecialBindings(mark); } } } /** Dispatch macro function if 'c' has one associated, * read a token otherwise. * * When the macro function returns zero values, this function * returns null or the token or returned value otherwise. */ private final LispObject processChar(LispThread thread, char c, Readtable rt) { final LispObject handler = rt.getReaderMacroFunction(c); LispObject value; if (handler instanceof ReaderMacroFunction) { thread._values = null; value = ((ReaderMacroFunction)handler).execute(this, c); } else if (handler != null && handler != NIL) { thread._values = null; value = handler.execute(this, LispCharacter.getInstance(c)); } else return readToken(c, rt); // If we're looking at zero return values, set 'value' to null if (value == NIL) { LispObject[] values = thread._values; if (values != null && values.length == 0) { value = null; thread._values = null; // reset 'no values' indicator } } return value; } public LispObject readPathname(ReadtableAccessor rta) { LispObject obj = read(true, NIL, false, LispThread.currentThread(), rta); if (obj instanceof AbstractString) { return Pathname.parseNamestring((AbstractString)obj); } if (obj.listp()) return Pathname.makePathname(obj); return error(new TypeError("#p requires a string argument.")); } public LispObject readSymbol() { final Readtable rt = (Readtable) Symbol.CURRENT_READTABLE.symbolValue(LispThread.currentThread()); return readSymbol(rt); } public LispObject readSymbol(Readtable rt) { final StringBuilder sb = new StringBuilder(); final BitSet flags = _readToken(sb, rt); return new Symbol(rt.getReadtableCase() == Keyword.INVERT ? invert(sb.toString(), flags) : sb.toString()); } public LispObject readStructure(ReadtableAccessor rta) { final LispThread thread = LispThread.currentThread(); LispObject obj = read(true, NIL, true, thread, rta); if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; if (obj.listp()) { Symbol structure = checkSymbol(obj.car()); LispClass c = LispClass.findClass(structure); if (!(c instanceof StructureClass)) return error(new ReaderError(structure.getName() + " is not a defined structure type.", this)); LispObject args = obj.cdr(); Symbol DEFSTRUCT_DEFAULT_CONSTRUCTOR = PACKAGE_SYS.intern("DEFSTRUCT-DEFAULT-CONSTRUCTOR"); LispObject constructor = DEFSTRUCT_DEFAULT_CONSTRUCTOR.getSymbolFunctionOrDie().execute(structure); final int length = args.length(); if ((length % 2) != 0) return error(new ReaderError("Odd number of keyword arguments following #S: " + obj.princToString(), this)); LispObject[] array = new LispObject[length]; LispObject rest = args; for (int i = 0; i < length; i += 2) { LispObject key = rest.car(); if (key instanceof Symbol && ((Symbol)key).getPackage() == PACKAGE_KEYWORD) { array[i] = key; } else { array[i] = PACKAGE_KEYWORD.intern(javaString(key)); } array[i + 1] = rest.cadr(); rest = rest.cddr(); } return funcall(constructor.getSymbolFunctionOrDie(), array, thread); } return error(new ReaderError("Non-list following #S: " + obj.princToString(), this)); } public LispObject readString(char terminator, ReadtableAccessor rta) { final LispThread thread = LispThread.currentThread(); final Readtable rt = rta.rt(thread); StringBuilder sb = new StringBuilder(); try { while (true) { int n = _readChar(); if (n < 0) return error(new EndOfFile(this)); char c = (char) n; // ### BUG: Codepoint conversion if (rt.getSyntaxType(c) == Readtable.SYNTAX_TYPE_SINGLE_ESCAPE) { // Single escape. n = _readChar(); if (n < 0) return error(new EndOfFile(this)); sb.append((char)n); // ### BUG: Codepoint conversion continue; } if (c == terminator) break; // Default. sb.append(c); } } catch (java.io.IOException e) { //error(new EndOfFile(stream)); return new SimpleString(sb); } return new SimpleString(sb); } public LispObject readList(boolean requireProperList, ReadtableAccessor rta) { final LispThread thread = LispThread.currentThread(); Cons first = null; Cons last = null; Readtable rt; try { while (true) { rt = rta.rt(thread); char c = flushWhitespace(rt); if (c == ')') { return first == null ? NIL : first; } if (c == '.') { int n = _readChar(); if (n < 0) return error(new EndOfFile(this)); char nextChar = (char) n; // ### BUG: Codepoint conversion if (isTokenDelimiter(nextChar, rt)) { if (last == null) { if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; else return error(new ReaderError("Nothing appears before . in list.", this)); } _unreadChar(nextChar); LispObject obj = read(true, NIL, true, thread, rta); if (requireProperList) { if (!obj.listp()) error(new ReaderError("The value " + obj.princToString() + " is not of type " + Symbol.LIST.princToString() + ".", this)); } last.cdr = obj; continue; } // normal token beginning with '.' _unreadChar(nextChar); } LispObject obj = processChar(thread, c, rt); if (obj == null) continue; if (first == null) { first = new Cons(obj); last = first; } else { Cons newCons = new Cons(obj); last.cdr = newCons; last = newCons; } } } catch (IOException e) { error(new StreamError(this, e)); return null; } } private static final boolean isTokenDelimiter(char c, Readtable rt) { byte type = rt.getSyntaxType(c); return type == Readtable.SYNTAX_TYPE_TERMINATING_MACRO || type == Readtable.SYNTAX_TYPE_WHITESPACE; } public LispObject readDispatchChar(char dispChar, ReadtableAccessor rta) { int numArg = -1; char c = 0; try { while (true) { int n = _readChar(); if (n < 0) return error(new EndOfFile(this)); c = (char) n; // ### BUG: Codepoint conversion if (c < '0' || c > '9') break; if (numArg < 0) numArg = 0; numArg = numArg * 10 + c - '0'; } } catch (IOException e) { error(new StreamError(this, e)); } final LispThread thread = LispThread.currentThread(); final Readtable rt = rta.rt(thread); LispObject fun = rt.getDispatchMacroCharacter(dispChar, c); if (fun != NIL) { LispObject result; thread._values = null; if (fun instanceof DispatchMacroFunction) return ((DispatchMacroFunction)fun).execute(this, c, numArg); else return thread.execute(fun, this, LispCharacter.getInstance(c), (numArg < 0) ? NIL : Fixnum.getInstance(numArg)); } if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return null; return error(new ReaderError("No dispatch function defined for #\\" + c, this)); } public LispObject readSharpLeftParen(char c, int n, ReadtableAccessor rta) { final LispThread thread = LispThread.currentThread(); LispObject list = readList(true, rta); if (_BACKQUOTE_COUNT_.symbolValue(thread).zerop()) { if (n >= 0) { LispObject[] array = new LispObject[n]; for (int i = 0; i < n; i++) { array[i] = list.car(); if (list.cdr() != NIL) list = list.cdr(); } return new SimpleVector(array); } else return new SimpleVector(list); } return new Cons(_BQ_VECTOR_FLAG_.symbolValue(thread), list); } public LispObject readSharpStar(char ignored, int n, ReadtableAccessor rta) { final LispThread thread = LispThread.currentThread(); final Readtable rt = rta.rt(thread); final boolean suppress = (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL); StringBuilder sb = new StringBuilder(); try { while (true) { int ch = _readChar(); if (ch < 0) break; char c = (char) ch; if (c == '0' || c == '1') sb.append(c); else { int syntaxType = rt.getSyntaxType(c); if (syntaxType == Readtable.SYNTAX_TYPE_WHITESPACE || syntaxType == Readtable.SYNTAX_TYPE_TERMINATING_MACRO) { _unreadChar(c); break; } else if (!suppress) { String name = LispCharacter.charToName(c); if (name == null) name = "#\\" + c; error(new ReaderError("Illegal element for bit-vector: " + name, this)); } } } } catch (java.io.IOException e) { error(new ReaderError("IO error: ", this)); return NIL; } if (suppress) return NIL; if (n >= 0) { // n was supplied. final int length = sb.length(); if (length == 0) { if (n > 0) return error(new ReaderError("No element specified for bit vector of length " + n + '.', this)); } if (n > length) { final char c = sb.charAt(length - 1); for (int i = length; i < n; i++) sb.append(c); } else if (n < length) { return error(new ReaderError("Bit vector is longer than specified length: #" + n + '*' + sb.toString(), this)); } } return new SimpleBitVector(sb.toString()); } public LispObject readSharpDot(char c, int n, ReadtableAccessor rta) { final LispThread thread = LispThread.currentThread(); if (Symbol.READ_EVAL.symbolValue(thread) == NIL) return error(new ReaderError("Can't read #. when *READ-EVAL* is NIL.", this)); else return eval(read(true, NIL, true, thread, rta), new Environment(), thread); } public LispObject readCharacterLiteral(Readtable rt, LispThread thread) { try { int n = _readChar(); if (n < 0) return error(new EndOfFile(this)); char c = (char) n; // ### BUG: Codepoint conversion StringBuilder sb = new StringBuilder(String.valueOf(c)); while (true) { n = _readChar(); if (n < 0) break; c = (char) n; // ### BUG: Codepoint conversion if (rt.isWhitespace(c)) break; if (rt.getSyntaxType(c) == Readtable.SYNTAX_TYPE_TERMINATING_MACRO) { _unreadChar(c); break; } sb.append(c); } if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; if (sb.length() == 1) return LispCharacter.getInstance(sb.charAt(0)); String token = sb.toString(); n = LispCharacter.nameToChar(token); if (n >= 0) return LispCharacter.getInstance((char)n); // ### BUG: Codepoint conversion return error(new LispError("Unrecognized character name: \"" + token + '"')); } catch (IOException e) { return error(new StreamError(this, e)); } } public void skipBalancedComment() { try { while (true) { int n = _readChar(); if (n < 0) return; if (n == '|') { n = _readChar(); if (n == '#') return; else _unreadChar(n); } else if (n == '#') { n = _readChar(); if (n == '|') skipBalancedComment(); // Nested comment. Recurse! else _unreadChar(n); } } } catch (IOException e) { error(new StreamError(this, e)); } } public LispObject readArray(int rank, ReadtableAccessor rta) { final LispThread thread = LispThread.currentThread(); LispObject obj = read(true, NIL, true, thread, rta); if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; switch (rank) { case -1: return error(new ReaderError("No dimensions argument to #A.", this)); case 0: return new ZeroRankArray(T, obj, false); case 1: { if (obj.listp() || obj instanceof AbstractVector) return new SimpleVector(obj); return error(new ReaderError(obj.princToString() + " is not a sequence.", this)); } default: return new SimpleArray_T(rank, obj); } } public LispObject readComplex(ReadtableAccessor rta) { final LispThread thread = LispThread.currentThread(); LispObject obj = read(true, NIL, true, thread, rta); if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; if (obj instanceof Cons && obj.length() == 2) return Complex.getInstance(obj.car(), obj.cadr()); // Error. StringBuilder sb = new StringBuilder("Invalid complex number format"); if (this instanceof FileStream) { Pathname p = ((FileStream)this).getPathname(); if (p != null) { String namestring = p.getNamestring(); if (namestring != null) { sb.append(" in #P\""); sb.append(namestring); sb.append('"'); } } sb.append(" at offset "); sb.append(_getFilePosition()); } sb.append(": #C"); sb.append(obj.printObject()); return error(new ReaderError(sb.toString(), this)); } private String readMultipleEscape(Readtable rt) { StringBuilder sb = new StringBuilder(); try { while (true) { int n = _readChar(); if (n < 0) return serror(new EndOfFile(this)); char c = (char) n; // ### BUG: Codepoint conversion byte syntaxType = rt.getSyntaxType(c); if (syntaxType == Readtable.SYNTAX_TYPE_SINGLE_ESCAPE) { n = _readChar(); if (n < 0) return serror(new EndOfFile(this)); sb.append((char)n); // ### BUG: Codepoint conversion continue; } if (syntaxType == Readtable.SYNTAX_TYPE_MULTIPLE_ESCAPE) break; sb.append(c); } } catch (IOException e) { return serror(new StreamError(this, e)); } return sb.toString(); } private static final int findUnescapedSingleColon(String s, BitSet flags) { if (flags == null) return s.indexOf(':'); final int limit = s.length(); for (int i = 0; i < limit; i++) { if (s.charAt(i) == ':' && !flags.get(i)) { return i; } } return -1; } private static final int findUnescapedDoubleColon(String s, BitSet flags) { if (flags == null) return s.indexOf("::"); final int limit = s.length() - 1; for (int i = 0; i < limit; i++) { if (s.charAt(i) == ':' && !flags.get(i)) { if (s.charAt(i + 1) == ':' && !flags.get(i + 1)) { return i; } } } return -1; } private final LispObject readToken(char c, Readtable rt) { StringBuilder sb = new StringBuilder(String.valueOf(c)); final LispThread thread = LispThread.currentThread(); BitSet flags = _readToken(sb, rt); if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; final LispObject readtableCase = rt.getReadtableCase(); final String token = sb.toString(); final boolean invert = readtableCase == Keyword.INVERT; final int length = token.length(); if (length > 0) { final char firstChar = token.charAt(0); if (flags == null) { if (firstChar == '.') { // Section 2.3.3: "If a token consists solely of dots (with // no escape characters), then an error of type READER- // ERROR is signaled, except in one circumstance: if the // token is a single dot and appears in a situation where // dotted pair notation permits a dot, then it is accepted // as part of such syntax and no error is signaled." boolean ok = false; for (int i = length; i-- > 1;) { if (token.charAt(i) != '.') { ok = true; break; } } if (!ok) { final String message; if (length > 1) message = "Too many dots."; else message = "Dot context error."; return error(new ReaderError(message, this)); } } final int radix = getReadBase(thread); if ("+-.0123456789".indexOf(firstChar) >= 0) { LispObject number = makeNumber(token, length, radix); if (number != null) return number; } else if (Character.digit(firstChar, radix) >= 0) { LispObject number = makeNumber(token, length, radix); if (number != null) return number; } } String symbolName; String packageName = null; BitSet symbolFlags; BitSet packageFlags = null; Package pkg = null; boolean internSymbol = true; if (firstChar == ':' && (flags == null || !flags.get(0))) { symbolName = token.substring(1); pkg = PACKAGE_KEYWORD; if (flags != null) symbolFlags = flags.get(1, flags.size()); else symbolFlags = null; } else { int index = findUnescapedDoubleColon(token, flags); if (index > 0) { packageName = token.substring(0, index); packageFlags = (flags != null) ? flags.get(0, index) : null; symbolName = token.substring(index + 2); symbolFlags = (flags != null) ? flags.get(index+2, flags.size()) : null; } else { index = findUnescapedSingleColon(token, flags); if (index > 0) { packageName = token.substring(0, index); packageFlags = (flags != null) ? flags.get(0, index) : null; symbolName = token.substring(index + 1); symbolFlags = (flags != null) ? flags.get(index+2, flags.size()) : null; internSymbol = false; } else { pkg = (Package)Symbol._PACKAGE_.symbolValue(thread); symbolName = token; symbolFlags = flags; } } } if (pkg == null) { if (invert) packageName = invert(packageName, packageFlags); pkg = getCurrentPackage().findPackage(packageName); if (pkg == null) return error(new ReaderError("The package \"" + packageName + "\" can't be found.", this)); } if (invert) symbolName = invert(symbolName, symbolFlags); if (internSymbol) { return pkg.intern(symbolName); } else { Symbol symbol = pkg.findExternalSymbol(symbolName); if (symbol != null) return symbol; // Error! if (pkg.findInternalSymbol(symbolName) != null) { return error(new ReaderError("The symbol \"~A\" is not external in package ~A.", this, new SimpleString(symbolName), new SimpleString(packageName))); } else { return error(new ReaderError("The symbol \"~A\" was not found in package ~A.", this, new SimpleString(symbolName), new SimpleString(packageName))); } } } else { // token.length == 0 Package pkg = (Package)Symbol._PACKAGE_.symbolValue(thread); return pkg.intern(""); } } private final BitSet _readToken(StringBuilder sb, Readtable rt) { BitSet flags = null; final LispObject readtableCase = rt.getReadtableCase(); if (sb.length() > 0) { Debug.assertTrue(sb.length() == 1); char c = sb.charAt(0); byte syntaxType = rt.getSyntaxType(c); if (syntaxType == Readtable.SYNTAX_TYPE_SINGLE_ESCAPE) { int n = -1; try { n = _readChar(); } catch (IOException e) { error(new StreamError(this, e)); return flags; } if (n < 0) { error(new EndOfFile(this)); return null; // Not reached } sb.setCharAt(0, (char) n); // ### BUG: Codepoint conversion flags = new BitSet(1); flags.set(0); } else if (syntaxType == Readtable.SYNTAX_TYPE_MULTIPLE_ESCAPE) { sb.setLength(0); sb.append(readMultipleEscape(rt)); flags = new BitSet(sb.length()); flags.set(0, sb.length()); } else if (rt.isInvalid(c)) { rt.checkInvalid(c, this); // Signals a reader-error. } else if (readtableCase == Keyword.UPCASE) { sb.setCharAt(0, LispCharacter.toUpperCase(c)); } else if (readtableCase == Keyword.DOWNCASE) { sb.setCharAt(0, LispCharacter.toLowerCase(c)); } } try { while (true) { int n = _readChar(); if (n < 0) break; char c = (char) n; // ### BUG: Codepoint conversion if (rt.isWhitespace(c)) { _unreadChar(n); break; } byte syntaxType = rt.getSyntaxType(c); if (syntaxType == Readtable.SYNTAX_TYPE_TERMINATING_MACRO) { _unreadChar(c); break; } rt.checkInvalid(c, this); if (syntaxType == Readtable.SYNTAX_TYPE_SINGLE_ESCAPE) { n = _readChar(); if (n < 0) break; sb.append((char)n); // ### BUG: Codepoint conversion if (flags == null) flags = new BitSet(sb.length()); flags.set(sb.length() - 1); continue; } if (syntaxType == Readtable.SYNTAX_TYPE_MULTIPLE_ESCAPE) { int begin = sb.length(); sb.append(readMultipleEscape(rt)); int end = sb.length(); if (flags == null) flags = new BitSet(sb.length()); flags.set(begin, end); continue; } if (readtableCase == Keyword.UPCASE) c = LispCharacter.toUpperCase(c); else if (readtableCase == Keyword.DOWNCASE) c = LispCharacter.toLowerCase(c); sb.append(c); } } catch (IOException e) { error(new StreamError(this, e)); return flags; } return flags; } public static final String invert(String s, BitSet flags) { // Section 23.1.2: "When the readtable case is :INVERT, then if all of // the unescaped letters in the extended token are of the same case, // those (unescaped) letters are converted to the opposite case." final int limit = s.length(); final int LOWER = 1; final int UPPER = 2; int state = 0; for (int i = 0; i < limit; i++) { // We only care about unescaped characters. if (flags != null && flags.get(i)) continue; char c = s.charAt(i); if (Character.isUpperCase(c)) { if (state == LOWER) return s; // Mixed case. state = UPPER; } if (Character.isLowerCase(c)) { if (state == UPPER) return s; // Mixed case. state = LOWER; } } StringBuilder sb = new StringBuilder(limit); for (int i = 0; i < limit; i++) { char c = s.charAt(i); if (flags != null && flags.get(i)) // Escaped. sb.append(c); else if (Character.isUpperCase(c)) sb.append(Character.toLowerCase(c)); else if (Character.isLowerCase(c)) sb.append(Character.toUpperCase(c)); else sb.append(c); } return sb.toString(); } private static final int getReadBase(LispThread thread) { final int readBase; final LispObject readBaseObject = Symbol.READ_BASE.symbolValue(thread); if (readBaseObject instanceof Fixnum) { readBase = ((Fixnum)readBaseObject).value; } else // The value of *READ-BASE* is not a Fixnum. return ierror(new LispError("The value of *READ-BASE* is not " + "of type '(INTEGER 2 36).")); if (readBase < 2 || readBase > 36) return ierror(new LispError("The value of *READ-BASE* is not " + "of type '(INTEGER 2 36).")); return readBase; } private final LispObject makeNumber(String token, int length, int radix) { if (length == 0) return null; if (token.indexOf('/') >= 0) return makeRatio(token, radix); if (token.charAt(length - 1) == '.') { radix = 10; token = token.substring(0, --length); } boolean numeric = true; if (radix == 10) { for (int i = length; i-- > 0;) { char c = token.charAt(i); if (c < '0' || c > '9') { if (i > 0 || (c != '-' && c != '+')) { numeric = false; break; } } } } else { for (int i = length; i-- > 0;) { char c = token.charAt(i); if (Character.digit(c, radix) < 0) { if (i > 0 || (c != '-' && c != '+')) { numeric = false; break; } } } } if (!numeric) // Can't be an integer. return makeFloat(token, length); if (token.charAt(0) == '+') token = token.substring(1); try { int n = Integer.parseInt(token, radix); return (n >= 0 && n <= 255) ? Fixnum.constants[n] : Fixnum.getInstance(n); } catch (NumberFormatException e) {} // parseInt() failed. try { return Bignum.getInstance(token, radix); } catch (NumberFormatException e) {} // Not a number. return null; } private final LispObject makeRatio(String token, int radix) { final int index = token.indexOf('/'); if (index < 0) return null; try { BigInteger numerator = new BigInteger(token.substring(0, index), radix); BigInteger denominator = new BigInteger(token.substring(index + 1), radix); // Check the denominator here, before calling number(), so we can // signal a READER-ERROR, as required by ANSI, instead of DIVISION- // BY-ZERO. if (denominator.signum() == 0) error(new ReaderError("Division by zero.", this)); return number(numerator, denominator); } catch (NumberFormatException e) { return null; } } private static final LispObject makeFloat(final String token, final int length) { if (length == 0) return null; StringBuilder sb = new StringBuilder(); int i = 0; boolean maybe = false; char marker = 0; char c = token.charAt(i); if (c == '-' || c == '+') { sb.append(c); ++i; } while (i < length) { c = token.charAt(i); if (c == '.' || (c >= '0' && c <= '9')) { if (c == '.') maybe = true; sb.append(c); ++i; } else break; } if (i < length) { c = token.charAt(i); if ("esfdlESFDL".indexOf(c) >= 0) { // Exponent marker. maybe = true; marker = LispCharacter.toUpperCase(c); if (marker == 'S') marker = 'F'; else if (marker == 'L') marker = 'D'; else if (marker == 'E') { LispObject format = Symbol.READ_DEFAULT_FLOAT_FORMAT.symbolValue(); if (format == Symbol.SINGLE_FLOAT || format == Symbol.SHORT_FLOAT) marker = 'F'; else marker = 'D'; } sb.append('E'); ++i; } } if (!maybe) return null; // Append rest of token. sb.append(token.substring(i)); c = sb.charAt(sb.length()-1); if (! ('0' <= c && c <= '9')) // we need to check that the last item is a number: // the Double.parseDouble routine accepts numbers ending in 'D' // like 1e2d. The same is true for Float.parseFloat and the 'F' // character. However, these are not valid Lisp floats. return null; try { if (marker == 0) { LispObject format = Symbol.READ_DEFAULT_FLOAT_FORMAT.symbolValue(); if (format == Symbol.SINGLE_FLOAT || format == Symbol.SHORT_FLOAT) marker = 'F'; else marker = 'D'; } if (marker == 'D') return new DoubleFloat(Double.parseDouble(sb.toString())); else return new SingleFloat(Float.parseFloat(sb.toString())); } catch (NumberFormatException e) { return null; } } public LispObject readRadix(int radix, ReadtableAccessor rta) { StringBuilder sb = new StringBuilder(); final LispThread thread = LispThread.currentThread(); final Readtable rt = rta.rt(thread); boolean escaped = (_readToken(sb, rt) != null); if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; if (escaped) return error(new ReaderError("Illegal syntax for number.", this)); String s = sb.toString(); if (s.indexOf('/') >= 0) return makeRatio(s, radix); // Integer.parseInt() below handles a prefixed '-' character correctly, but // does not accept a prefixed '+' character, so we skip over it here if (s.charAt(0) == '+') s = s.substring(1); try { int n = Integer.parseInt(s, radix); return (n >= 0 && n <= 255) ? Fixnum.constants[n] : Fixnum.getInstance(n); } catch (NumberFormatException e) {} // parseInt() failed. try { return Bignum.getInstance(s, radix); } catch (NumberFormatException e) {} // Not a number. return error(new LispError()); } private char flushWhitespace(Readtable rt) { try { while (true) { int n = _readChar(); if (n < 0) return (char)ierror(new EndOfFile(this)); char c = (char) n; // ### BUG: Codepoint conversion if (!rt.isWhitespace(c)) return c; } } catch (IOException e) { error(new StreamError(this, e)); return 0; } } public LispObject readDelimitedList(char delimiter) { final LispThread thread = LispThread.currentThread(); LispObject result = NIL; while (true) { Readtable rt = (Readtable) Symbol.CURRENT_READTABLE.symbolValue(thread); char c = flushWhitespace(rt); if (c == delimiter) break; LispObject obj = processChar(thread, c, rt); if (obj != null) result = new Cons(obj, result); } if (Symbol.READ_SUPPRESS.symbolValue(thread) != NIL) return NIL; else return result.nreverse(); } // read-line &optional stream eof-error-p eof-value recursive-p // => line, missing-newline-p // recursive-p is ignored public LispObject readLine(boolean eofError, LispObject eofValue) { final LispThread thread = LispThread.currentThread(); StringBuilder sb = new StringBuilder(); try { while (true) { int n = _readChar(); if (n < 0) { if (sb.length() == 0) { if (eofError) return error(new EndOfFile(this)); return thread.setValues(eofValue, T); } return thread.setValues(new SimpleString(sb), T); } if (n == '\n') return thread.setValues(new SimpleString(sb), NIL); else sb.append((char)n); // ### BUG: Codepoint conversion } } catch (IOException e) { return error(new StreamError(this, e)); } } // read-char &optional stream eof-error-p eof-value recursive-p => char // recursive-p is ignored public LispObject readChar() { try { int n = _readChar(); if (n < 0) return error(new EndOfFile(this)); return LispCharacter.getInstance((char)n); // ### BUG: Codepoint conversion } catch (IOException e) { return error(new StreamError(this, e)); } } public LispObject readChar(boolean eofError, LispObject eofValue) { try { int n = _readChar(); if (n < 0) { if (eofError) return error(new EndOfFile(this)); else return eofValue; } return LispCharacter.getInstance((char)n); // ### BUG: Codepoint conversion } catch (IOException e) { return error(new StreamError(this, e)); } } // read-char-no-hang &optional stream eof-error-p eof-value recursive-p => char // recursive-p is ignored public LispObject readCharNoHang(boolean eofError, LispObject eofValue) { try { return _charReady() ? readChar(eofError, eofValue) : NIL; } catch (IOException e) { return error(new StreamError(this, e)); } } // unread-char character &optional input-stream => nil public LispObject unreadChar(LispCharacter c) { try { _unreadChar(c.value); return NIL; } catch (IOException e) { return error(new StreamError(this, e)); } } public LispObject finishOutput() { _finishOutput(); return NIL; } // clear-input &optional input-stream => nil public LispObject clearInput() { _clearInput(); return NIL; } public LispObject getFilePosition() { long pos = _getFilePosition(); return pos >= 0 ? number(pos) : NIL; } public LispObject setFilePosition(LispObject arg) { return _setFilePosition(arg) ? T : NIL; } // close stream &key abort => result // Must return true if stream was open, otherwise implementation-dependent. public LispObject close(LispObject abort) { _close(); return T; } // read-byte stream &optional eof-error-p eof-value => byte // Reads an 8-bit byte. public LispObject readByte(boolean eofError, LispObject eofValue) { int n = _readByte(); if (n < 0) { if (eofError) return error(new EndOfFile(this)); else return eofValue; } return Fixnum.constants[n]; } public LispObject terpri() { _writeChar('\n'); return NIL; } public LispObject freshLine() { if (charPos == 0) return NIL; _writeChar('\n'); return T; } public void print(char c) { _writeChar(c); } // PRIN1 produces output suitable for input to READ. // Binds *PRINT-ESCAPE* to true. public void prin1(LispObject obj) { LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, T); try { _writeString(obj.printObject()); } finally { thread.resetSpecialBindings(mark); } } public LispObject listen() { if (pastEnd) return NIL; try { if (isCharacterInputStream()) { if (! _charReady()) return NIL; int n = _readChar(); if (n < 0) return NIL; _unreadChar(n); return T; } else if (isInputStream()) { if (! _byteReady()) return NIL; return T; } else return error(new StreamError(this, "Not an input stream")); } catch (IOException e) { return error(new StreamError(this, e)); } } public LispObject fileLength() { return type_error(this, Symbol.FILE_STREAM); } public LispObject fileStringLength(LispObject arg) { if (arg instanceof LispCharacter) { if (Utilities.isPlatformWindows) { if (((LispCharacter)arg).value == '\n') return Fixnum.TWO; } return Fixnum.ONE; } if (arg instanceof AbstractString) { if (Utilities.isPlatformWindows) { int fileStringLength = 0; char[] chars = ((AbstractString)arg).getStringChars(); for (int i = chars.length; i-- > 0;) { if (chars[i] == '\n') fileStringLength += 2; else ++fileStringLength; } return number(fileStringLength); } return number(arg.length()); } return error(new TypeError(arg.princToString() + " is neither a string nor a character.")); } /** Reads a character off an underlying stream * * @return a character, or -1 at end-of-file */ protected int _readChar() throws IOException { if (reader == null) streamNotCharacterInputStream(); int n = reader.read(); if (n < 0) { pastEnd = true; return -1; } ++offset; if (n == '\r' && eolStyle == EolStyle.CRLF) { n = _readChar(); if (n != '\n') { _unreadChar(n); return '\r'; } else return '\n'; } if (n == eolChar) { ++lineNumber; return '\n'; } return n; } /** Puts a character back into the (underlying) stream * * @param n */ protected void _unreadChar(int n) throws IOException { if (reader == null) streamNotCharacterInputStream(); --offset; if (n == '\n') { n = eolChar; --lineNumber; } reader.unread(n); pastEnd = false; } /** Returns a boolean indicating input readily available * * @return true if a character is available */ protected boolean _charReady() throws IOException { if (reader == null) streamNotCharacterInputStream(); return reader.ready(); } protected boolean _byteReady() throws IOException { if (in == null) streamNotInputStream(); return (in.available() != 0); } /** Writes a character into the underlying stream, * updating charPos while doing so * * @param c */ public void _writeChar(char c) { try { if (c == '\n') { if (eolStyle == EolStyle.CRLF && lastChar != '\r') writer.write('\r'); writer.write(eolChar); lastChar = eolChar; writer.flush(); charPos = 0; } else { writer.write(c); lastChar = c; ++charPos; } } catch (NullPointerException e) { // writer is null streamNotCharacterOutputStream(); } catch (IOException e) { error(new StreamError(this, e)); } } /** Writes a series of characters in the underlying stream, * updating charPos while doing so * * @param chars * @param start * @param end */ public void _writeChars(char[] chars, int start, int end) { try { if (eolStyle != EolStyle.RAW) { for (int i = start; i < end; i++) //###FIXME: the number of writes can be greatly reduced by // writing the space between newlines as chunks. _writeChar(chars[i]); return; } writer.write(chars, start, end - start); if (start < end) lastChar = chars[end-1]; int index = -1; for (int i = end; i-- > start;) { if (chars[i] == '\n') { index = i; break; } } if (index < 0) { // No newline. charPos += (end - start); } else { charPos = end - (index + 1); writer.flush(); } } catch (NullPointerException e) { if (writer == null) streamNotCharacterOutputStream(); else throw e; } catch (IOException e) { error(new StreamError(this, e)); } } /** Writes a string to the underlying stream, * updating charPos while doing so * * @param s */ public void _writeString(String s) { try { _writeChars(s.toCharArray(), 0, s.length()); } catch (NullPointerException e) { if (writer == null) streamNotCharacterOutputStream(); else throw e; } } /** Writes a string to the underlying stream, appending * a new line and updating charPos while doing so * * @param s */ public void _writeLine(String s) { try { _writeString(s); _writeChar('\n'); } catch (NullPointerException e) { // writer is null streamNotCharacterOutputStream(); } } // Reads an 8-bit byte. /** Reads an 8-bit byte off the underlying stream * * @return */ public int _readByte() { try { int n = in.read(); if (n < 0) pastEnd = true; return n; // Reads an 8-bit byte. } catch (IOException e) { return ierror(new StreamError(this, e)); } } // Writes an 8-bit byte. /** Writes an 8-bit byte off the underlying stream * * @param n */ public void _writeByte(int n) { try { out.write(n); // Writes an 8-bit byte. } catch (NullPointerException e) { // out is null streamNotBinaryOutputStream(); } catch (IOException e) { error(new StreamError(this, e)); } } /** Flushes any buffered output in the (underlying) stream * */ public void _finishOutput() { try { if (writer != null) writer.flush(); if (out != null) out.flush(); } catch (IOException e) { error(new StreamError(this, e)); } } /** Reads all input from the underlying stream, * until _charReady() indicates no more input to be available * */ public void _clearInput() { if (reader != null) { int c = 0; try { while (_charReady() && (c >= 0)) c = _readChar(); } catch (IOException e) { error(new StreamError(this, e)); } } else if (in != null) { try { int n = 0; while (in.available() > 0) n = in.read(); if (n < 0) pastEnd = true; } catch (IOException e) { error(new StreamError(this, e)); } } } /** Returns a (non-negative) file position integer or a negative value * if the position cannot be determined. * * @return non-negative value as a position spec * @return negative value for 'unspecified' */ protected long _getFilePosition() { return -1; } /** Sets the file position based on a position designator passed in arg * * @param arg File position specifier as described in the CLHS * @return true on success, false on failure */ protected boolean _setFilePosition(LispObject arg) { return false; } /** Closes the stream and underlying streams * */ public void _close() { try { if (reader != null) reader.close(); if (in != null) in.close(); if (writer != null) writer.close(); if (out != null) out.close(); setOpen(false); } catch (IOException e) { error(new StreamError(this, e)); } } public void printStackTrace(Throwable t) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); t.printStackTrace(pw); try { writer.write(sw.toString()); writer.write('\n'); lastChar = '\n'; writer.flush(); charPos = 0; } catch (IOException e) { error(new StreamError(this, e)); } } protected LispObject streamNotInputStream() { return error(new StreamError(this, princToString() + " is not an input stream.")); } protected LispObject streamNotCharacterInputStream() { return error(new StreamError(this, princToString() + " is not a character input stream.")); } protected LispObject streamNotOutputStream() { return error(new StreamError(this, princToString() + " is not an output stream.")); } protected LispObject streamNotBinaryOutputStream() { return error(new StreamError(this, princToString() + " is not a binary output stream.")); } protected LispObject streamNotCharacterOutputStream() { return error(new StreamError(this, princToString() + " is not a character output stream.")); } // ### %stream-write-char character output-stream => character // OUTPUT-STREAM must be a real stream, not an output stream designator! private static final Primitive _WRITE_CHAR = new Primitive("%stream-write-char", PACKAGE_SYS, true, "character output-stream") { @Override public LispObject execute(LispObject first, LispObject second) { checkStream(second)._writeChar(LispCharacter.getValue(first)); return first; } }; // ### %write-char character output-stream => character private static final Primitive _STREAM_WRITE_CHAR = new Primitive("%write-char", PACKAGE_SYS, false, "character output-stream") { @Override public LispObject execute(LispObject first, LispObject second) { final char c = LispCharacter.getValue(first); if (second == T) second = Symbol.TERMINAL_IO.symbolValue(); else if (second == NIL) second = Symbol.STANDARD_OUTPUT.symbolValue(); final Stream stream = checkStream(second); stream._writeChar(c); return first; } }; // ### %write-string string output-stream start end => string private static final Primitive _WRITE_STRING = new Primitive("%write-string", PACKAGE_SYS, false, "string output-stream start end") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { final AbstractString s = checkString(first); char[] chars = s.chars(); final Stream out = outSynonymOf(second); final int start = Fixnum.getValue(third); final int end; if (fourth == NIL) end = chars.length; else { end = Fixnum.getValue(fourth); } checkBounds(start, end, chars.length); out._writeChars(chars, start, end); return first; } }; // ### %finish-output output-stream => nil private static final Primitive _FINISH_OUTPUT = new Primitive("%finish-output", PACKAGE_SYS, false, "output-stream") { @Override public LispObject execute(LispObject arg) { return finishOutput(arg); } }; // ### %force-output output-stream => nil private static final Primitive _FORCE_OUTPUT = new Primitive("%force-output", PACKAGE_SYS, false, "output-stream") { @Override public LispObject execute(LispObject arg) { return finishOutput(arg); } }; static final LispObject finishOutput(LispObject arg) { final LispObject out; if (arg == T) out = Symbol.TERMINAL_IO.symbolValue(); else if (arg == NIL) out = Symbol.STANDARD_OUTPUT.symbolValue(); else out = arg; return checkStream(out).finishOutput(); } // ### clear-input &optional input-stream => nil private static final Primitive CLEAR_INPUT = new Primitive(Symbol.CLEAR_INPUT, "&optional input-stream") { @Override public LispObject execute(LispObject[] args) { if (args.length > 1) return error(new WrongNumberOfArgumentsException(this, -1, 1)); final Stream in; if (args.length == 0) in = checkCharacterInputStream(Symbol.STANDARD_INPUT.symbolValue()); else in = inSynonymOf(args[0]); in.clearInput(); return NIL; } }; // ### %clear-output output-stream => nil // "If any of these operations does not make sense for output-stream, then // it does nothing." private static final Primitive _CLEAR_OUTPUT = new Primitive("%clear-output", PACKAGE_SYS, false, "output-stream") { @Override public LispObject execute(LispObject arg) { if (arg == T) // *TERMINAL-IO* return NIL; if (arg == NIL) // *STANDARD-OUTPUT* return NIL; if (arg instanceof Stream) return NIL; return type_error(arg, Symbol.STREAM); } }; // ### close stream &key abort => result private static final Primitive CLOSE = new Primitive(Symbol.CLOSE, "stream &key abort") { @Override public LispObject execute(LispObject arg) { return checkStream(arg).close(NIL); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { final Stream stream = checkStream(first); if (second == Keyword.ABORT) return stream.close(third); return program_error("Unrecognized keyword argument " + second.princToString() + "."); } }; // ### out-synonym-of stream-designator => stream private static final Primitive OUT_SYNONYM_OF = new Primitive("out-synonym-of", PACKAGE_SYS, true, "stream-designator") { @Override public LispObject execute (LispObject arg) { if (arg instanceof Stream) return arg; if (arg == T) return Symbol.TERMINAL_IO.symbolValue(); if (arg == NIL) return Symbol.STANDARD_OUTPUT.symbolValue(); return arg; } }; // ### write-8-bits // write-8-bits byte stream => nil private static final Primitive WRITE_8_BITS = new Primitive("write-8-bits", PACKAGE_SYS, true, "byte stream") { @Override public LispObject execute (LispObject first, LispObject second) { int n = Fixnum.getValue(first); if (n < 0 || n > 255) return type_error(first, UNSIGNED_BYTE_8); checkStream(second)._writeByte(n); return NIL; } }; // ### read-8-bits // read-8-bits stream &optional eof-error-p eof-value => byte private static final Primitive READ_8_BITS = new Primitive("read-8-bits", PACKAGE_SYS, true, "stream &optional eof-error-p eof-value") { @Override public LispObject execute (LispObject first, LispObject second, LispObject third) { return checkBinaryInputStream(first).readByte((second != NIL), third); } @Override public LispObject execute (LispObject[] args) { int length = args.length; if (length < 1 || length > 3) return error(new WrongNumberOfArgumentsException(this, 1, 3)); final Stream in = checkBinaryInputStream(args[0]); boolean eofError = length > 1 ? (args[1] != NIL) : true; LispObject eofValue = length > 2 ? args[2] : NIL; return in.readByte(eofError, eofValue); } }; // ### read-line &optional input-stream eof-error-p eof-value recursive-p // => line, missing-newline-p private static final Primitive READ_LINE = new Primitive(Symbol.READ_LINE, "&optional input-stream eof-error-p eof-value recursive-p") { @Override public LispObject execute() { final LispObject obj = Symbol.STANDARD_INPUT.symbolValue(); final Stream stream = checkStream(obj); return stream.readLine(true, NIL); } @Override public LispObject execute(LispObject arg) { if (arg == T) arg = Symbol.TERMINAL_IO.symbolValue(); else if (arg == NIL) arg = Symbol.STANDARD_INPUT.symbolValue(); final Stream stream = checkStream(arg); return stream.readLine(true, NIL); } @Override public LispObject execute(LispObject first, LispObject second) { if (first == T) first = Symbol.TERMINAL_IO.symbolValue(); else if (first == NIL) first = Symbol.STANDARD_INPUT.symbolValue(); final Stream stream = checkStream(first); return stream.readLine(second != NIL, NIL); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first == T) first = Symbol.TERMINAL_IO.symbolValue(); else if (first == NIL) first = Symbol.STANDARD_INPUT.symbolValue(); final Stream stream = checkStream(first); return stream.readLine(second != NIL, third); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { // recursive-p is ignored if (first == T) first = Symbol.TERMINAL_IO.symbolValue(); else if (first == NIL) first = Symbol.STANDARD_INPUT.symbolValue(); final Stream stream = checkStream(first); return stream.readLine(second != NIL, third); } }; // ### %read-from-string string eof-error-p eof-value start end preserve-whitespace // => object, position private static final Primitive _READ_FROM_STRING = new Primitive("%read-from-string", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { String s = first.getStringValue(); boolean eofError = (second != NIL); boolean preserveWhitespace = (sixth != NIL); final int startIndex; if (fourth != NIL) startIndex = Fixnum.getValue(fourth); else startIndex = 0; final int endIndex; if (fifth != NIL) endIndex = Fixnum.getValue(fifth); else endIndex = s.length(); StringInputStream in = new StringInputStream(s, startIndex, endIndex); final LispThread thread = LispThread.currentThread(); LispObject result; if (preserveWhitespace) result = in.readPreservingWhitespace(eofError, third, false, thread, currentReadtable); else result = in.read(eofError, third, false, thread, currentReadtable); return thread.setValues(result, Fixnum.getInstance(in.getOffset())); } }; // ### read &optional input-stream eof-error-p eof-value recursive-p => object private static final Primitive READ = new Primitive(Symbol.READ, "&optional input-stream eof-error-p eof-value recursive-p") { @Override public LispObject execute() { final LispThread thread = LispThread.currentThread(); final LispObject obj = Symbol.STANDARD_INPUT.symbolValue(thread); final Stream stream = checkStream(obj); return stream.read(true, NIL, false, thread, currentReadtable); } @Override public LispObject execute(LispObject arg) { final LispThread thread = LispThread.currentThread(); if (arg == T) arg = Symbol.TERMINAL_IO.symbolValue(thread); else if (arg == NIL) arg = Symbol.STANDARD_INPUT.symbolValue(thread); final Stream stream = checkStream(arg); return stream.read(true, NIL, false, thread, currentReadtable); } @Override public LispObject execute(LispObject first, LispObject second) { final LispThread thread = LispThread.currentThread(); if (first == T) first = Symbol.TERMINAL_IO.symbolValue(thread); else if (first == NIL) first = Symbol.STANDARD_INPUT.symbolValue(thread); final Stream stream = checkStream(first); return stream.read(second != NIL, NIL, false, thread, currentReadtable); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { final LispThread thread = LispThread.currentThread(); if (first == T) first = Symbol.TERMINAL_IO.symbolValue(thread); else if (first == NIL) first = Symbol.STANDARD_INPUT.symbolValue(thread); final Stream stream = checkStream(first); return stream.read(second != NIL, third, false, thread, currentReadtable); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { final LispThread thread = LispThread.currentThread(); if (first == T) first = Symbol.TERMINAL_IO.symbolValue(thread); else if (first == NIL) first = Symbol.STANDARD_INPUT.symbolValue(thread); final Stream stream = checkStream(first); return stream.read(second != NIL, third, fourth != NIL, thread, currentReadtable); } }; // ### read-preserving-whitespace // &optional input-stream eof-error-p eof-value recursive-p => object private static final Primitive READ_PRESERVING_WHITESPACE = new Primitive(Symbol.READ_PRESERVING_WHITESPACE, "&optional input-stream eof-error-p eof-value recursive-p") { @Override public LispObject execute(LispObject[] args) { int length = args.length; if (length > 4) return error(new WrongNumberOfArgumentsException(this, -1, 4)); Stream stream = length > 0 ? inSynonymOf(args[0]) : getStandardInput(); boolean eofError = length > 1 ? (args[1] != NIL) : true; LispObject eofValue = length > 2 ? args[2] : NIL; boolean recursive = length > 3 ? (args[3] != NIL) : false; return stream.readPreservingWhitespace(eofError, eofValue, recursive, LispThread.currentThread(), currentReadtable); } }; // ### read-char &optional input-stream eof-error-p eof-value recursive-p // => char private static final Primitive READ_CHAR = new Primitive(Symbol.READ_CHAR, "&optional input-stream eof-error-p eof-value recursive-p") { @Override public LispObject execute() { return checkCharacterInputStream(Symbol.STANDARD_INPUT.symbolValue()).readChar(); } @Override public LispObject execute(LispObject arg) { return inSynonymOf(arg).readChar(); } @Override public LispObject execute(LispObject first, LispObject second) { return inSynonymOf(first).readChar(second != NIL, NIL); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return inSynonymOf(first).readChar(second != NIL, third); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return inSynonymOf(first).readChar(second != NIL, third); } }; // ### read-char-no-hang &optional input-stream eof-error-p eof-value // recursive-p => char private static final Primitive READ_CHAR_NO_HANG = new Primitive("read-char-no-hang", "&optional input-stream eof-error-p eof-value recursive-p") { @Override public LispObject execute(LispObject[] args) { int length = args.length; if (length > 4) error(new WrongNumberOfArgumentsException(this, -1, 4)); Stream stream = length > 0 ? inSynonymOf(args[0]) : getStandardInput(); boolean eofError = length > 1 ? (args[1] != NIL) : true; LispObject eofValue = length > 2 ? args[2] : NIL; // recursive-p is ignored // boolean recursive = length > 3 ? (args[3] != NIL) : false; return stream.readCharNoHang(eofError, eofValue); } }; // ### read-delimited-list char &optional input-stream recursive-p => list private static final Primitive READ_DELIMITED_LIST = new Primitive("read-delimited-list", "char &optional input-stream recursive-p") { @Override public LispObject execute(LispObject[] args) { int length = args.length; if (length < 1 || length > 3) error(new WrongNumberOfArgumentsException(this, 1, 3)); char c = LispCharacter.getValue(args[0]); Stream stream = length > 1 ? inSynonymOf(args[1]) : getStandardInput(); return stream.readDelimitedList(c); } }; // ### unread-char character &optional input-stream => nil private static final Primitive UNREAD_CHAR = new Primitive(Symbol.UNREAD_CHAR, "character &optional input-stream") { @Override public LispObject execute(LispObject arg) { return getStandardInput().unreadChar(checkCharacter(arg)); } @Override public LispObject execute(LispObject first, LispObject second) { Stream stream = inSynonymOf(second); return stream.unreadChar(checkCharacter(first)); } }; // ### write-vector-unsigned-byte-8 private static final Primitive WRITE_VECTOR_UNSIGNED_BYTE_8 = new Primitive("write-vector-unsigned-byte-8", PACKAGE_SYS, true, "vector stream start end") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { final AbstractVector v = checkVector(first); final Stream stream = checkStream(second); int start = Fixnum.getValue(third); int end = Fixnum.getValue(fourth); for (int i = start; i < end; i++) stream._writeByte(v.aref(i)); return v; } }; // ### read-vector-unsigned-byte-8 vector stream start end => position private static final Primitive READ_VECTOR_UNSIGNED_BYTE_8 = new Primitive("read-vector-unsigned-byte-8", PACKAGE_SYS, true, "vector stream start end") { @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { AbstractVector v = checkVector(first); Stream stream = checkBinaryInputStream(second); int start = Fixnum.getValue(third); int end = Fixnum.getValue(fourth); if (!v.getElementType().equal(UNSIGNED_BYTE_8)) return type_error(first, list(Symbol.VECTOR, UNSIGNED_BYTE_8)); for (int i = start; i < end; i++) { int n = stream._readByte(); if (n < 0) { // End of file. return Fixnum.getInstance(i); } v.aset(i, n); } return fourth; } }; // ### file-position private static final Primitive FILE_POSITION = new Primitive("file-position", "stream &optional position-spec") { @Override public LispObject execute(LispObject arg) { return checkStream(arg).getFilePosition(); } @Override public LispObject execute(LispObject first, LispObject second) { return checkStream(first).setFilePosition(second); } }; // ### stream-line-number private static final Primitive STREAM_LINE_NUMBER = new Primitive("stream-line-number", PACKAGE_SYS, false, "stream") { @Override public LispObject execute(LispObject arg) { return Fixnum.getInstance(checkStream(arg).getLineNumber() + 1); } }; // ### stream-offset private static final Primitive STREAM_OFFSET = new Primitive("stream-offset", PACKAGE_SYS, false, "stream") { @Override public LispObject execute(LispObject arg) { return number(checkStream(arg).getOffset()); } }; // ### stream-charpos stream => position private static final Primitive STREAM_CHARPOS = new Primitive("stream-charpos", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject arg) { Stream stream = checkCharacterOutputStream(arg); return Fixnum.getInstance(stream.getCharPos()); } }; // ### stream-%set-charpos stream newval => newval private static final Primitive STREAM_SET_CHARPOS = new Primitive("stream-%set-charpos", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject first, LispObject second) { Stream stream = checkCharacterOutputStream(first); stream.setCharPos(Fixnum.getValue(second)); return second; } }; public InputStream getWrappedInputStream() { return in; } public OutputStream getWrappedOutputStream() { return out; } public Writer getWrappedWriter() { return writer; } public PushbackReader getWrappedReader() { return reader; } } abcl-src-1.9.0/src/org/armedbear/lisp/StreamError.java0100644 0000000 0000000 00000011711 14202767264 021330 0ustar000000000 0000000 /* * StreamError.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class StreamError extends LispError { private final Throwable cause; protected StreamError(LispClass cls) { super(cls); cause = null; } public StreamError(String message) { super(StandardClass.STREAM_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); setStream(NIL); cause = null; } public StreamError(Stream stream) { super(StandardClass.STREAM_ERROR); setStream(stream != null ? stream : NIL); cause = null; } public StreamError(String message, Stream stream) { super(StandardClass.STREAM_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); setStream(stream != null ? stream : NIL); cause = null; } public StreamError(LispObject initArgs) { super(StandardClass.STREAM_ERROR); initialize(initArgs); cause = null; } @Override protected void initialize(LispObject initArgs) { super.initialize(initArgs); while (initArgs != NIL) { LispObject first = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.STREAM) { setStream(initArgs.car()); break; } initArgs = initArgs.cdr(); } } public StreamError(Stream stream, String message) { super(StandardClass.STREAM_ERROR); setFormatControl(message.replaceAll("~","~~")); setFormatArguments(NIL); setStream(stream != null ? stream : NIL); cause = null; } public StreamError(Stream stream, Throwable cause) { super(StandardClass.STREAM_ERROR); setStream(stream != null ? stream : NIL); String message = cause.getMessage(); setFormatControl(message != null ? message.replaceAll("~","~~") : cause.toString().replaceAll("~","~~")); setFormatArguments(NIL); this.cause = cause; } public final LispObject getStream() { return getInstanceSlotValue(Symbol.STREAM); } protected final void setStream(LispObject stream) { setInstanceSlotValue(Symbol.STREAM, stream); } @Override public LispObject typeOf() { return Symbol.STREAM_ERROR; } @Override public LispObject classOf() { return StandardClass.STREAM_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.STREAM_ERROR) return T; if (type == StandardClass.STREAM_ERROR) return T; return super.typep(type); } @Override public String getMessage() { if (cause != null) { String s = cause.getMessage(); if (s != null && s.length() > 0) return s; } return null; } // ### stream-error-stream private static final Primitive STREAM_ERROR_STREAM = new Primitive("stream-error-stream", "condition") { @Override public LispObject execute(LispObject arg) { if (arg.typep(Symbol.STREAM_ERROR) == NIL) { return type_error(arg, Symbol.STREAM_ERROR); } final StandardObject obj = (StandardObject) arg; return obj.getInstanceSlotValue(Symbol.STREAM); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/StringFunctions.java0100644 0000000 0000000 00000103652 14202767264 022230 0ustar000000000 0000000 /* * StringFunctions.java * * Copyright (C) 2003-2005 Peter Graves * Copyright (C) 2010 Ville Voutilainen * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.util.Arrays; public final class StringFunctions { final static class StringIndicesAndChars { public AbstractString string1; public boolean convertCase = false; public char[] array1; public char[] array2; public int start1 = 0; public int end1 = 0; public int start2 = 0; public int end2 = 0; }; private final static void checkParams(StringIndicesAndChars indicesAndChars) { if (indicesAndChars.start1 < 0 || indicesAndChars.start1 > indicesAndChars.array1.length) error(new TypeError("Invalid start position " + indicesAndChars.start1 + ".")); if (indicesAndChars.end1 < 0 || indicesAndChars.end1 > indicesAndChars.array1.length) error(new TypeError("Invalid end position " + indicesAndChars.end1 + ".")); if (indicesAndChars.start1 > indicesAndChars.end1) error(new TypeError("Start (" + indicesAndChars.start1 + ") is greater than end (" + indicesAndChars.end1 + ").")); if (indicesAndChars.array2 != null) { if (indicesAndChars.start2 < 0 || indicesAndChars.start2 > indicesAndChars.array2.length) error(new TypeError("Invalid start2 position " + indicesAndChars.start2 + ".")); if (indicesAndChars.end2 < 0 || indicesAndChars.end2 > indicesAndChars.array2.length) error(new TypeError("Invalid end2 position " + indicesAndChars.end2 + ".")); if (indicesAndChars.start2 > indicesAndChars.end2) error(new TypeError("Start2 (" + indicesAndChars.start2 + ") is greater than end2 (" + indicesAndChars.end2 + ").")); } } private final static char upcaseIfNeeded(char c, boolean convert) { return convert ? LispCharacter.toUpperCase(c) : c; } final static StringIndicesAndChars stringIndicesAndChars(LispObject... params) { StringIndicesAndChars retVal = new StringIndicesAndChars(); retVal.string1 = checkString(params[0].STRING()); retVal.array1 = retVal.string1.getStringChars(); retVal.end1 = retVal.array1.length; if (params.length == 3) { if (params[1] != NIL) { retVal.start1 = Fixnum.getValue(params[1]); } if (params[2] != NIL) { retVal.end1 = Fixnum.getValue(params[2]); } } else { retVal.array2 = params[1].STRING().getStringChars(); retVal.end2 = retVal.array2.length; if (params.length > 2) { if (params[2] != NIL) { retVal.start1 = Fixnum.getValue(params[2]); } if (params[3] != NIL) { retVal.end1 = Fixnum.getValue(params[3]); } if (params[4] != NIL) { retVal.start2 = Fixnum.getValue(params[4]); } if (params[5] != NIL) { retVal.end2 = Fixnum.getValue(params[5]); } } } checkParams(retVal); return retVal; } // ### %%string= // Case sensitive. private static final Primitive __STRING_EQUAL = new pf___string_equal(); private static final class pf___string_equal extends Primitive { pf___string_equal() { super("%%string=", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject string1, LispObject string2) { StringIndicesAndChars chars = stringIndicesAndChars(string1, string2); return Arrays.equals(chars.array1, chars.array2) ? T : NIL; }; } // ### %string= // Case sensitive. private static final Primitive _STRING_EQUAL = new pf__string_equal(); private static final class pf__string_equal extends Primitive { pf__string_equal() { super("%string=", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { return (_STRING_NOT_EQUAL.execute(string1, string2, start1, end1, start2, end2) == NIL) ? T : NIL; } }; static final int notEqual(StringIndicesAndChars indicesAndChars) { int i = indicesAndChars.start1; int j = indicesAndChars.start2; while (true) { if (i == indicesAndChars.end1) { // Reached end of string1. if (j == indicesAndChars.end2) return -1; // Strings are identical. return i; } if (j == indicesAndChars.end2) { // Reached end of string2 before end of string1. return i; } if (upcaseIfNeeded(indicesAndChars.array1[i], indicesAndChars.convertCase) != upcaseIfNeeded(indicesAndChars.array2[j], indicesAndChars.convertCase)) return i; ++i; ++j; } } // ### %string/= // Case sensitive. static final Primitive _STRING_NOT_EQUAL = new pf__string_not_equal(); private static final class pf__string_not_equal extends Primitive { pf__string_not_equal() { super("%string/=", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string1, string2, start1, end1, start2, end2); int tmp = notEqual(indicesAndChars); return (tmp >= 0) ? Fixnum.getInstance(tmp) : NIL; } }; // ### %string-equal // Case insensitive. private static final Primitive _STRING_EQUAL_IGNORE_CASE = new pf__string_equal_ignore_case(); private static final class pf__string_equal_ignore_case extends Primitive { pf__string_equal_ignore_case() { super("%string-equal", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { return (_STRING_NOT_EQUAL_IGNORE_CASE.execute(string1, string2, start1, end1, start2, end2) == NIL) ? T : NIL; } }; // ### %string-not-equal // Case insensitive. static final Primitive _STRING_NOT_EQUAL_IGNORE_CASE = new pf__string_not_equal_ignore_case(); private static final class pf__string_not_equal_ignore_case extends Primitive { pf__string_not_equal_ignore_case() { super("%string-not-equal", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string1, string2, start1, end1, start2, end2); indicesAndChars.convertCase = true; int tmp = notEqual(indicesAndChars); return (tmp >= 0) ? Fixnum.getInstance(tmp) : NIL; } }; static final int lessThan(StringIndicesAndChars indicesAndChars) { int i = indicesAndChars.start1; int j = indicesAndChars.start2; while (true) { if (i == indicesAndChars.end1) { // Reached end of string1. if (j == indicesAndChars.end2) return -1; // Strings are identical. return i; } if (j == indicesAndChars.end2) { // Reached end of string2. return -1; } char c1 = upcaseIfNeeded(indicesAndChars.array1[i], indicesAndChars.convertCase); char c2 = upcaseIfNeeded(indicesAndChars.array2[j], indicesAndChars.convertCase); if (c1 == c2) { ++i; ++j; continue; } if (c1 < c2) return (i); // c1 > c2 return -1; } } // ### %string< // Case sensitive. private static final Primitive _STRING_LESS_THAN = new pf__string_less_than(); private static final class pf__string_less_than extends Primitive { pf__string_less_than() { super("%string<", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string1, string2, start1, end1, start2, end2); int retVal = lessThan(indicesAndChars); return (retVal >= 0) ? Fixnum.getInstance(retVal) : NIL; } }; static LispObject swapReturnValue(int original, StringIndicesAndChars indicesAndChars) { if (original < 0) { return NIL; } int delta = original - indicesAndChars.start1; int retVal = indicesAndChars.start2 + delta; return Fixnum.getInstance(retVal); } // ### %string> // Case sensitive. private static final Primitive _STRING_GREATER_THAN = new pf__string_greater_than(); private static final class pf__string_greater_than extends Primitive { pf__string_greater_than() { super("%string>", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { // note the swap of the strings and lengths here.. StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string2, string1, start2, end2, start1, end1); int tmp = lessThan(indicesAndChars); return swapReturnValue(tmp, indicesAndChars); } }; static final int lessThanOrEqual(StringIndicesAndChars indicesAndChars) { int i = indicesAndChars.start1; int j = indicesAndChars.start2; while (true) { if (i == indicesAndChars.end1) { // Reached end of string1. return i; } if (j == indicesAndChars.end2) { // Reached end of string2. return -1; } char c1 = upcaseIfNeeded(indicesAndChars.array1[i], indicesAndChars.convertCase); char c2 = upcaseIfNeeded(indicesAndChars.array2[j], indicesAndChars.convertCase); if (c1 == c2) { ++i; ++j; continue; } if (c1 > c2) return -1; // c1 < c2 return (i); } } // ### %string<= // Case sensitive. private static final Primitive _STRING_LE = new pf__string_le(); private static final class pf__string_le extends Primitive { pf__string_le() { super("%string<=", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string1, string2, start1, end1, start2, end2); int retVal = lessThanOrEqual(indicesAndChars); return (retVal >= 0) ? Fixnum.getInstance(retVal) : NIL; } }; // ### %string>= // Case sensitive. private static final Primitive _STRING_GE = new pf__string_ge(); private static final class pf__string_ge extends Primitive { pf__string_ge() { super("%string>=", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { // note the swap of the strings and lengths here.. StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string2, string1, start2, end2, start1, end1); int tmp = lessThanOrEqual(indicesAndChars); return swapReturnValue(tmp, indicesAndChars); } }; // ### %string-lessp // Case insensitive. private static final Primitive _STRING_LESSP = new pf__string_lessp(); private static final class pf__string_lessp extends Primitive { pf__string_lessp() { super("%string-lessp", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string1, string2, start1, end1, start2, end2); indicesAndChars.convertCase = true; int retVal = lessThan(indicesAndChars); return (retVal >= 0) ? Fixnum.getInstance(retVal) : NIL; } }; // ### %string-greaterp // Case insensitive. private static final Primitive _STRING_GREATERP = new pf__string_greaterp(); private static final class pf__string_greaterp extends Primitive { pf__string_greaterp() { super("%string-greaterp", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { // note the swap of the strings and lengths here.. StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string2, string1, start2, end2, start1, end1); indicesAndChars.convertCase = true; int tmp = lessThan(indicesAndChars); return swapReturnValue(tmp, indicesAndChars); } }; // ### %string-not-lessp // Case insensitive. private static final Primitive _STRING_NOT_LESSP = new pf__string_not_lessp(); private static final class pf__string_not_lessp extends Primitive { pf__string_not_lessp() { super("%string-not-lessp", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { // note the swap of the strings and lengths here.. StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string2, string1, start2, end2, start1, end1); indicesAndChars.convertCase = true; int tmp = lessThanOrEqual(indicesAndChars); return swapReturnValue(tmp, indicesAndChars); } }; // ### %string-not-greaterp // Case insensitive. private static final Primitive _STRING_NOT_GREATERP = new pf__string_not_greaterp(); private static final class pf__string_not_greaterp extends Primitive { pf__string_not_greaterp() { super("%string-not-greaterp", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string1, LispObject string2, LispObject start1, LispObject end1, LispObject start2, LispObject end2) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string1, string2, start1, end1, start2, end2); indicesAndChars.convertCase = true; int tmp = lessThanOrEqual(indicesAndChars); return (tmp >= 0) ? Fixnum.getInstance(tmp) : NIL; } }; // ### %string-upcase private static final Primitive _STRING_UPCASE = new pf__string_upcase(); private static final class pf__string_upcase extends Primitive { pf__string_upcase() { super("%string-upcase", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string, LispObject start, LispObject end) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string, start, end); char[] array = new char[indicesAndChars.array1.length]; System.arraycopy(indicesAndChars.array1, 0, array, 0, indicesAndChars.start1); for (int i = indicesAndChars.start1; i < indicesAndChars.end1; i++) array[i] = LispCharacter.toUpperCase(indicesAndChars.array1[i]); System.arraycopy(indicesAndChars.array1, indicesAndChars.end1, array, indicesAndChars.end1, indicesAndChars.array1.length - indicesAndChars.end1); return new SimpleString(array); } }; // ### %string-downcase private static final Primitive _STRING_DOWNCASE = new pf__string_downcase(); private static final class pf__string_downcase extends Primitive { pf__string_downcase() { super("%string-downcase", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string, LispObject start, LispObject end) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string, start, end); char[] array = new char[indicesAndChars.array1.length]; System.arraycopy(indicesAndChars.array1, 0, array, 0, indicesAndChars.start1); for (int i = indicesAndChars.start1; i < indicesAndChars.end1; i++) array[i] = LispCharacter.toLowerCase(indicesAndChars.array1[i]); System.arraycopy(indicesAndChars.array1, indicesAndChars.end1, array, indicesAndChars.end1, indicesAndChars.array1.length - indicesAndChars.end1); return new SimpleString(array); } }; // ### %string-capitalize private static final Primitive _STRING_CAPITALIZE = new pf__string_capitalize(); private static final class pf__string_capitalize extends Primitive { pf__string_capitalize() { super("%string-capitalize", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string, LispObject start, LispObject end) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string, start, end); char[] array = new char[indicesAndChars.array1.length]; boolean lastCharWasAlphanumeric = false; System.arraycopy(indicesAndChars.array1, 0, array, 0, indicesAndChars.start1); for (int i = indicesAndChars.start1; i < indicesAndChars.end1; i++) { char c = indicesAndChars.array1[i]; if (Character.isLowerCase(c)) { array[i] = lastCharWasAlphanumeric ? c : LispCharacter.toUpperCase(c); lastCharWasAlphanumeric = true; } else if (Character.isUpperCase(c)) { array[i] = lastCharWasAlphanumeric ? LispCharacter.toLowerCase(c) : c; lastCharWasAlphanumeric = true; } else { array[i] = c; lastCharWasAlphanumeric = Character.isDigit(c); } } System.arraycopy(indicesAndChars.array1, indicesAndChars.end1, array, indicesAndChars.end1, indicesAndChars.array1.length - indicesAndChars.end1); return new SimpleString(array); } }; // ### %nstring-upcase private static final Primitive _NSTRING_UPCASE = new pf__nstring_upcase(); private static final class pf__nstring_upcase extends Primitive { pf__nstring_upcase() { super("%nstring-upcase", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string, LispObject start, LispObject end) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string, start, end); AbstractString retString = indicesAndChars.string1; for (int i = indicesAndChars.start1; i < indicesAndChars.end1; i++) retString.setCharAt(i, LispCharacter. toUpperCase( retString.charAt(i))); return retString; } }; // ### %nstring-downcase private static final Primitive _NSTRING_DOWNCASE = new pf__nstring_downcase(); private static final class pf__nstring_downcase extends Primitive { pf__nstring_downcase() { super("%nstring-downcase", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string, LispObject start, LispObject end) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string, start, end); AbstractString retString = indicesAndChars.string1; for (int i = indicesAndChars.start1; i < indicesAndChars.end1; i++) retString.setCharAt(i, LispCharacter. toLowerCase(retString.charAt(i))); return retString; } }; // ### %nstring-capitalize private static final Primitive _NSTRING_CAPITALIZE = new pf__nstring_capitalize(); private static final class pf__nstring_capitalize extends Primitive { pf__nstring_capitalize() { super("%nstring-capitalize", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject string, LispObject start, LispObject end) { StringIndicesAndChars indicesAndChars = stringIndicesAndChars(string, start, end); boolean lastCharWasAlphanumeric = false; AbstractString retString = indicesAndChars.string1; for (int i = indicesAndChars.start1; i < indicesAndChars.end1; i++) { char c = retString.charAt(i); if (Character.isLowerCase(c)) { if (!lastCharWasAlphanumeric) retString.setCharAt(i, LispCharacter.toUpperCase(c)); lastCharWasAlphanumeric = true; } else if (Character.isUpperCase(c)) { if (lastCharWasAlphanumeric) retString.setCharAt(i, LispCharacter.toLowerCase(c)); lastCharWasAlphanumeric = true; } else lastCharWasAlphanumeric = Character.isDigit(c); } return retString; } }; // ### stringp public static final Primitive STRINGP = new pf_stringp(); private static final class pf_stringp extends Primitive { pf_stringp() { super("stringp", "object"); } @Override public LispObject execute(LispObject arg) { return arg.STRINGP(); } }; // ### simple-string-p public static final Primitive SIMPLE_STRING_P = new pf_simple_string_p(); private static final class pf_simple_string_p extends Primitive { pf_simple_string_p() { super("simple-string-p", "object"); } @Override public LispObject execute(LispObject arg) { return arg.SIMPLE_STRING_P(); } }; // ### %make-string // %make-string size initial-element element-type => string // Returns a simple string. private static final Primitive _MAKE_STRING = new pf__make_string(); private static final class pf__make_string extends Primitive { pf__make_string() { super("%make-string", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject size, LispObject initialElement, LispObject elementType) { final int n = Fixnum.getValue(size); if (n < 0 || n >= ARRAY_DIMENSION_MAX) { StringBuilder sb = new StringBuilder(); sb.append("The size specified for this string ("); sb.append(n); sb.append(')'); if (n >= ARRAY_DIMENSION_MAX) { sb.append(" is >= ARRAY-DIMENSION-LIMIT ("); sb.append(ARRAY_DIMENSION_MAX); sb.append(")."); } else sb.append(" is negative."); return error(new LispError(sb.toString())); } // Ignore elementType. SimpleString string = new SimpleString(n); if (initialElement != NIL) { // Initial element was specified. char c = checkCharacter(initialElement).getValue(); string.fill(c); } return string; } }; // ### char private static final Primitive CHAR = new pf_char(); private static final class pf_char extends Primitive { pf_char() { super(Symbol.CHAR, "string index"); } @Override public LispObject execute(LispObject first, LispObject second) { return first.CHAR(Fixnum.getValue(second)); } }; // ### schar private static final Primitive SCHAR = new pf_schar(); private static final class pf_schar extends Primitive { pf_schar() { super(Symbol.SCHAR, "string index"); } @Override public LispObject execute(LispObject first, LispObject second) { return first.SCHAR(Fixnum.getValue(second)); } }; // ### set-char private static final Primitive SET_CHAR = new pf_set_char(); private static final class pf_set_char extends Primitive { pf_set_char() { super(Symbol.SET_CHAR, "string index character"); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { checkString(first).setCharAt(Fixnum.getValue(second), LispCharacter.getValue(third)); return third; } }; // ### set-schar private static final Primitive SET_SCHAR = new pf_set_schar(); private static final class pf_set_schar extends Primitive { pf_set_schar() { super(Symbol.SET_SCHAR, "string index character"); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first instanceof SimpleString) { ((SimpleString)first).setCharAt(Fixnum.getValue(second), LispCharacter.getValue(third)); return third; } return type_error(first, Symbol.SIMPLE_STRING); } }; // ### string-position private static final Primitive STRING_POSITION = new pf_string_position(); private static final class pf_string_position extends Primitive { pf_string_position() { super("string-position", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { char c = LispCharacter.getValue(first); AbstractString string = checkString(second); int start = Fixnum.getValue(third); for (int i = start, limit = string.length(); i < limit; i++) { if (string.charAt(i) == c) return number(i); } return NIL; } }; // ### string-find private static final Primitive STRING_FIND = new pf_string_find(); private static final class pf_string_find extends Primitive { pf_string_find() { super("string-find", PACKAGE_EXT, true, "char string"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof LispCharacter) { final char c = ((LispCharacter)first).value; AbstractString string = Lisp.checkString(second); final int limit = string.length(); for (int i = 0; i < limit; i++) { if (string.charAt(i) == c) return first; } } return NIL; } }; // ### simple-string-search pattern string => position // Searches string for a substring that matches pattern. private static final Primitive SIMPLE_STRING_SEARCH = new pf_simple_string_search(); private static final class pf_simple_string_search extends Primitive { pf_simple_string_search() { super("simple-string-search", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject first, LispObject second) { // FIXME Don't call getStringValue() here! (Just look at the chars.) int index = second.getStringValue().indexOf(first.getStringValue()); return index >= 0 ? Fixnum.getInstance(index) : NIL; } }; // ### simple-string-fill string character => string private static final Primitive STRING_FILL = new pf_string_fill(); private static final class pf_string_fill extends Primitive { pf_string_fill() { super("simple-string-fill", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof AbstractString) { AbstractString s = (AbstractString) first; s.fill(LispCharacter.getValue(second)); return first; } return type_error(first, Symbol.SIMPLE_STRING); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/StringInputStream.java0100644 0000000 0000000 00000013151 14202767264 022525 0ustar000000000 0000000 /* * StringInputStream.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.IOException; import java.io.StringReader; public final class StringInputStream extends Stream { private final StringReader stringReader; private final int start; private final String subString; public StringInputStream(String s) { this(s, 0, s.length()); } public StringInputStream(String s, int start) { this(s, start, s.length()); } public StringInputStream(String s, int start, int end) { super(Symbol.STRING_INPUT_STREAM); elementType = Symbol.CHARACTER; setExternalFormat(keywordDefault); eolStyle = EolStyle.RAW; this.start = start; subString = s.substring(start, end); stringReader = new StringReader(subString); initAsCharacterInputStream(stringReader); } @Override public LispObject typeOf() { return Symbol.STRING_INPUT_STREAM; } @Override public LispObject classOf() { return BuiltInClass.STRING_INPUT_STREAM; } @Override public LispObject typep(LispObject type) { if (type == Symbol.STRING_INPUT_STREAM) return T; if (type == Symbol.STRING_STREAM) return T; if (type == BuiltInClass.STRING_INPUT_STREAM) return T; if (type == BuiltInClass.STRING_STREAM) return T; return super.typep(type); } @Override public int getOffset() { return start + offset; } @Override protected long _getFilePosition() { return getOffset(); } @Override protected boolean _setFilePosition(LispObject arg) { try { int offset; if (arg == Keyword.START) offset = 0; else if (arg == Keyword.END) offset = subString.length(); else { long n = Fixnum.getValue(arg); if (n < 0 || n > subString.length()) error(new StreamError(this, "FILE-POSITION got out of bounds argument.")); offset = (int) n; // FIXME arg might be a bignum } stringReader.reset(); stringReader.skip(offset); initAsCharacterInputStream(stringReader); this.offset = offset; } catch (IOException e) { error(new StreamError(this, e)); } return true; } // ### make-string-input-stream // make-string-input-stream string &optional start end => string-stream private static final Primitive MAKE_STRING_INPUT_STREAM = new Primitive("make-string-input-stream", "string &optional start end") { @Override public LispObject execute(LispObject arg) { return new StringInputStream(arg.getStringValue()); } @Override public LispObject execute(LispObject first, LispObject second) { String s = first.getStringValue(); int start = Fixnum.getValue(second); return new StringInputStream(s, start); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { String s = first.getStringValue(); int start = Fixnum.getValue(second); if (third == NIL) return new StringInputStream(s, start); int end = Fixnum.getValue(third); return new StringInputStream(s, start, end); } }; // ### string-input-stream-current private static final Primitive STRING_INPUT_STREAM_CURRENT = new Primitive("string-input-stream-current", PACKAGE_EXT, true, "stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof StringInputStream) return Fixnum.getInstance(((StringInputStream)arg).getOffset()); return error(new TypeError(String.valueOf(arg) + " is not a string input stream.")); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/StringOutputStream.java0100644 0000000 0000000 00000011765 14202767264 022737 0ustar000000000 0000000 /* * StringOutputStream.java * * Copyright (C) 2002-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.IOException; import java.io.StringWriter; public final class StringOutputStream extends Stream { private final SeekableStringWriter stringWriter; public StringOutputStream() { this(Symbol.CHARACTER); } StringOutputStream(LispObject elementType) { super(Symbol.STRING_OUTPUT_STREAM); this.elementType = elementType; this.eolStyle = EolStyle.RAW; initAsCharacterOutputStream(stringWriter = new SeekableStringWriter()); } @Override public LispObject typeOf() { return Symbol.STRING_OUTPUT_STREAM; } @Override public LispObject classOf() { return BuiltInClass.STRING_OUTPUT_STREAM; } @Override public LispObject typep(LispObject type) { if (type == Symbol.STRING_OUTPUT_STREAM) return T; if (type == Symbol.STRING_STREAM) return T; if (type == BuiltInClass.STRING_OUTPUT_STREAM) return T; if (type == BuiltInClass.STRING_STREAM) return T; return super.typep(type); } @Override protected long _getFilePosition() { if (elementType == NIL) return 0; return stringWriter.getOffset(); } @Override protected boolean _setFilePosition(LispObject arg) { if (elementType == NIL) return false; try { int offset; if (arg == Keyword.START) offset = 0; else if (arg == Keyword.END) offset = stringWriter.getBuffer().length(); else { long n = Fixnum.getValue(arg); offset = (int) n; // FIXME arg might be a bignum } stringWriter.seek(offset); // FixME super.offset needs to be maintained differently? this.offset = offset; } catch (IllegalArgumentException e) { error(new StreamError(this, e)); } return true; } public LispObject getString() { if (elementType == NIL) { return new NilVector(0); } StringBuffer sb = stringWriter.getBuffer(); SimpleString s = new SimpleString(sb); sb.setLength(0); return s; } public LispObject getSimpleStringAndClear() { if (elementType == NIL) return new NilVector(0); String contents = stringWriter.toStringAndClear(); return new SimpleString(contents); } // ### %make-string-output-stream // %make-string-output-stream element-type => string-stream private static final Primitive MAKE_STRING_OUTPUT_STREAM = new Primitive("%make-string-output-stream", PACKAGE_SYS, false, "element-type") { @Override public LispObject execute(LispObject arg) { return new StringOutputStream(arg); } }; // ### get-output-stream-string // get-output-stream-string string-output-stream => string private static final Primitive GET_OUTPUT_STREAM_STRING = new Primitive("get-output-stream-string", "string-output-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof StringOutputStream) { return ((StringOutputStream)arg).getSimpleStringAndClear(); } return type_error(this, Symbol.STRING_OUTPUT_STREAM); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/StructureClass.java0100644 0000000 0000000 00000010613 14202767264 022051 0ustar000000000 0000000 /* * StructureClass.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class StructureClass extends SlotClass { StructureClass(Symbol symbol) { super(symbol, new Cons(BuiltInClass.STRUCTURE_OBJECT)); } public StructureClass(Symbol symbol, LispObject directSuperclasses) { super(symbol, directSuperclasses); } @Override public LispObject typeOf() { return Symbol.STRUCTURE_CLASS; } @Override public LispObject classOf() { return LispClass.findClass(Symbol.STRUCTURE_CLASS); } @Override public LispObject typep(LispObject type) { if (type == Symbol.STRUCTURE_CLASS) return T; if (type == LispClass.findClass(Symbol.STRUCTURE_CLASS)) return T; return super.typep(type); } @Override public LispObject getDescription() { return new SimpleString(princToString()); } @Override public String printObject() { StringBuilder sb = new StringBuilder("STRUCTURE-CLASS "); sb.append(getName().princToString()); return unreadableString(sb.toString(), false); } // ### make-structure-class name direct-slots slots include => class private static final Primitive MAKE_STRUCTURE_CLASS = new Primitive("make-structure-class", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { Symbol symbol = checkSymbol(first); LispClass existingClass = LispClass.findClass(symbol); if (existingClass instanceof StructureClass) // DEFSTRUCT-REDEFINITION write-up // states the effects from re-definition are undefined // we punt: our compiler bootstrapping depends on // the class not being redefined (remaining in the // same location in the class hierarchy) return existingClass; LispObject directSlots = checkList(second); LispObject slots = checkList(third); Symbol include = checkSymbol(fourth); StructureClass c = new StructureClass(symbol); if (include != NIL) { LispClass includedClass = LispClass.findClass(include); if (includedClass == null) return error(new SimpleError("Class " + include + " is undefined.")); c.setCPL(new Cons(c, includedClass.getCPL())); } else c.setCPL(c, BuiltInClass.STRUCTURE_OBJECT, BuiltInClass.CLASS_T); c.setDirectSlotDefinitions(directSlots); c.setSlotDefinitions(slots); c.setFinalized(true); addClass(symbol, c); return c; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/StructureObject.java0100644 0000000 0000000 00000047360 14223403213 022203 0ustar000000000 0000000 /* * StructureObject.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class StructureObject extends LispObject { private final StructureClass structureClass; final LispObject[] slots; public StructureObject(Symbol symbol) { structureClass = (StructureClass) LispClass.findClass(symbol/*, true*/); // Might return null. if (structureClass == null) { System.err.println("No mitens sitten: " + BuiltInClass.SYSTEM_STREAM.toString()); System.err.println("joopa joo:" + Symbol.SYSTEM_STREAM.name); System.err.println("Oh noes, structure object got a null class:" + symbol.toString() + ", symbol name:" + symbol.name ); } slots = new LispObject[0]; } public StructureObject(Symbol symbol, LispObject[] slots) { structureClass = (StructureClass) LispClass.findClass(symbol); // Might return null. this.slots = slots; } public StructureObject(Symbol symbol, LispObject obj0) { structureClass = (StructureClass) LispClass.findClass(symbol); // Might return null. LispObject[] slots = new LispObject[1]; slots[0] = obj0; this.slots = slots; } public StructureObject(Symbol symbol, LispObject obj0, LispObject obj1) { structureClass = (StructureClass) LispClass.findClass(symbol); // Might return null. LispObject[] slots = new LispObject[2]; slots[0] = obj0; slots[1] = obj1; this.slots = slots; } public StructureObject(Symbol symbol, LispObject obj0, LispObject obj1, LispObject obj2) { structureClass = (StructureClass) LispClass.findClass(symbol); // Might return null. LispObject[] slots = new LispObject[3]; slots[0] = obj0; slots[1] = obj1; slots[2] = obj2; this.slots = slots; } public StructureObject(Symbol symbol, LispObject obj0, LispObject obj1, LispObject obj2, LispObject obj3) { structureClass = (StructureClass) LispClass.findClass(symbol); // Might return null. LispObject[] slots = new LispObject[4]; slots[0] = obj0; slots[1] = obj1; slots[2] = obj2; slots[3] = obj3; this.slots = slots; } public StructureObject(Symbol symbol, LispObject obj0, LispObject obj1, LispObject obj2, LispObject obj3, LispObject obj4) { structureClass = (StructureClass) LispClass.findClass(symbol); // Might return null. LispObject[] slots = new LispObject[5]; slots[0] = obj0; slots[1] = obj1; slots[2] = obj2; slots[3] = obj3; slots[4] = obj4; this.slots = slots; } public StructureObject(Symbol symbol, LispObject obj0, LispObject obj1, LispObject obj2, LispObject obj3, LispObject obj4, LispObject obj5) { structureClass = (StructureClass) LispClass.findClass(symbol); // Might return null. LispObject[] slots = new LispObject[6]; slots[0] = obj0; slots[1] = obj1; slots[2] = obj2; slots[3] = obj3; slots[4] = obj4; slots[5] = obj5; this.slots = slots; } public StructureObject(StructureObject obj) { this.structureClass = obj.structureClass; slots = new LispObject[obj.slots.length]; for (int i = slots.length; i-- > 0;) slots[i] = obj.slots[i]; } @Override public LispObject typeOf() { return structureClass.getName(); } @Override public LispObject classOf() { return structureClass; } protected int getSlotIndex(LispObject slotName) { LispObject effectiveSlots = structureClass.getSlotDefinitions(); LispObject[] effectiveSlotsArray = effectiveSlots.copyToArray(); for (int i = 0; i < slots.length; i++) { SimpleVector slotDefinition = (SimpleVector) effectiveSlotsArray[i]; LispObject candidateSlotName = slotDefinition.AREF(1); if(slotName == candidateSlotName) { return i; } } return -1; } @Override public LispObject SLOT_VALUE(LispObject slotName) { LispObject value; final int index = getSlotIndex(slotName); if (index >= 0) { value = slots[index]; } else { value = UNBOUND_VALUE; value = Symbol.SLOT_UNBOUND.execute(structureClass, this, slotName); LispThread.currentThread()._values = null; } return value; } public void setSlotValue(LispObject slotName, LispObject newValue) { final int index = getSlotIndex(slotName); if (index >= 0) { slots[index] = newValue; } else { LispObject[] args = new LispObject[5]; args[0] = structureClass; args[1] = this; args[2] = slotName; args[3] = Symbol.SETF; args[4] = newValue; Symbol.SLOT_MISSING.execute(args); } } @Override public LispObject getParts() { LispObject result = NIL; result = result.push(new Cons("class", structureClass)); LispObject effectiveSlots = structureClass.getSlotDefinitions(); LispObject[] effectiveSlotsArray = effectiveSlots.copyToArray(); Debug.assertTrue(effectiveSlotsArray.length == slots.length); for (int i = 0; i < slots.length; i++) { SimpleVector slotDefinition = (SimpleVector) effectiveSlotsArray[i]; LispObject slotName = slotDefinition.AREF(1); result = result.push(new Cons(slotName, slots[i])); } return result.nreverse(); } @Override public LispObject typep(LispObject type) { if (type instanceof StructureClass) return memq(type, structureClass.getCPL()) ? T : NIL; if (type == structureClass.getName()) return T; if (type == Symbol.STRUCTURE_OBJECT) return T; if (type == BuiltInClass.STRUCTURE_OBJECT) return T; if (type instanceof Symbol) { LispClass c = LispClass.findClass((Symbol)type); if (c != null) return memq(c, structureClass.getCPL()) ? T : NIL; } return super.typep(type); } @Override public boolean equalp(LispObject obj) { if (this == obj) return true; if (obj instanceof StructureObject) { StructureObject o = (StructureObject) obj; if (structureClass != o.structureClass) return false; for (int i = 0; i < slots.length; i++) { if (!slots[i].equalp(o.slots[i])) return false; } return true; } return false; } @Override public LispObject getSlotValue_0() { try { return slots[0]; } catch (ArrayIndexOutOfBoundsException e) { return badIndex(0); } } @Override public LispObject getSlotValue_1() { try { return slots[1]; } catch (ArrayIndexOutOfBoundsException e) { return badIndex(1); } } @Override public LispObject getSlotValue_2() { try { return slots[2]; } catch (ArrayIndexOutOfBoundsException e) { return badIndex(2); } } @Override public LispObject getSlotValue_3() { try { return slots[3]; } catch (ArrayIndexOutOfBoundsException e) { return badIndex(3); } } @Override public LispObject getSlotValue(int index) { try { return slots[index]; } catch (ArrayIndexOutOfBoundsException e) { return badIndex(index); } } @Override public int getFixnumSlotValue(int index) { try { return Fixnum.getValue(slots[index]); } catch (ArrayIndexOutOfBoundsException e) { badIndex(index); // Not reached. return 0; } } @Override public boolean getSlotValueAsBoolean(int index) { try { return slots[index] != NIL; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index); // Not reached. return false; } } @Override public void setSlotValue_0(LispObject value) { try { slots[0] = value; } catch (ArrayIndexOutOfBoundsException e) { badIndex(0); } } @Override public void setSlotValue_1(LispObject value) { try { slots[1] = value; } catch (ArrayIndexOutOfBoundsException e) { badIndex(1); } } @Override public void setSlotValue_2(LispObject value) { try { slots[2] = value; } catch (ArrayIndexOutOfBoundsException e) { badIndex(2); } } @Override public void setSlotValue_3(LispObject value) { try { slots[3] = value; } catch (ArrayIndexOutOfBoundsException e) { badIndex(3); } } @Override public void setSlotValue(int index, LispObject value) { try { slots[index] = value; } catch (ArrayIndexOutOfBoundsException e) { badIndex(index); } } private LispObject badIndex(int n) { StringBuilder sb = new StringBuilder("Invalid slot index "); sb.append(Fixnum.getInstance(n).princToString()); sb.append(" for "); sb.append(princToString()); return error(new LispError(sb.toString())); } @Override public final int psxhash() { return psxhash(4); } @Override public final int psxhash(int depth) { int result = mix(structureClass.sxhash(), 7814971); if (depth > 0) { int limit = slots.length; if (limit > 4) limit = 4; for (int i = 0; i < limit; i++) result = mix(slots[i].psxhash(depth - 1), result); } return result & 0x7fffffff; } @Override public String printObject() { try { final LispThread thread = LispThread.currentThread(); // FIXME if (typep(Symbol.RESTART) != NIL) { Symbol PRINT_RESTART = PACKAGE_SYS.intern("PRINT-RESTART"); LispObject fun = PRINT_RESTART.getSymbolFunction(); StringOutputStream stream = new StringOutputStream(); thread.execute(fun, this, stream); return stream.getString().getStringValue(); } if (_PRINT_STRUCTURE_.symbolValue(thread) == NIL) return unreadableString(structureClass.getName().printObject()); int maxLevel = Integer.MAX_VALUE; LispObject printLevel = Symbol.PRINT_LEVEL.symbolValue(thread); if (printLevel instanceof Fixnum) maxLevel = ((Fixnum)printLevel).value; LispObject currentPrintLevel = _CURRENT_PRINT_LEVEL_.symbolValue(thread); int currentLevel = Fixnum.getValue(currentPrintLevel); if (currentLevel >= maxLevel && slots.length > 0) return "#"; StringBuilder sb = new StringBuilder("#S("); sb.append(structureClass.getName().printObject()); if (currentLevel < maxLevel) { LispObject effectiveSlots = structureClass.getSlotDefinitions(); LispObject[] effectiveSlotsArray = effectiveSlots.copyToArray(); Debug.assertTrue(effectiveSlotsArray.length == slots.length); final LispObject printLength = Symbol.PRINT_LENGTH.symbolValue(thread); final int limit; if (printLength instanceof Fixnum) limit = Math.min(slots.length, ((Fixnum)printLength).value); else limit = slots.length; final boolean printCircle = (Symbol.PRINT_CIRCLE.symbolValue(thread) != NIL); for (int i = 0; i < limit; i++) { sb.append(' '); SimpleVector slotDefinition = (SimpleVector) effectiveSlotsArray[i]; // FIXME AREF(1) LispObject slotName = slotDefinition.AREF(1); Debug.assertTrue(slotName instanceof Symbol); sb.append(':'); sb.append(((Symbol)slotName).name.getStringValue()); sb.append(' '); if (printCircle) { StringOutputStream stream = new StringOutputStream(); thread.execute(Symbol.OUTPUT_OBJECT.getSymbolFunction(), slots[i], stream); sb.append(stream.getString().getStringValue()); } else sb.append(slots[i].printObject()); } if (limit < slots.length) sb.append(" ..."); } sb.append(')'); return sb.toString(); } catch (StackOverflowError e) { error(new StorageCondition("Stack overflow.")); return null; // Not reached. } } private static final Primitive STRUCTURE_OBJECT_P = new pf_structure_object_p(); @DocString(name="structure-object-p", args="object", returns="generalized-boolean") private static final class pf_structure_object_p extends Primitive { pf_structure_object_p() { super("structure-object-p", PACKAGE_SYS, true, "object"); } @Override public LispObject execute(LispObject arg) { return arg instanceof StructureObject ? T : NIL; } }; private static final Primitive STRUCTURE_LENGTH = new pf_structure_length(); @DocString(name="structure-length", args="instance", returns="length") private static final class pf_structure_length extends Primitive { pf_structure_length() { super("structure-length", PACKAGE_SYS, true, "instance"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof StructureObject) return Fixnum.getInstance(((StructureObject)arg).slots.length); return type_error(arg, Symbol.STRUCTURE_OBJECT); } }; private static final Primitive STRUCTURE_REF = new pf_structure_ref(); @DocString(name="structure-ref", args="instance index", returns="value") private static final class pf_structure_ref extends Primitive { pf_structure_ref() { super("structure-ref", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof StructureObject) try { return ((StructureObject)first).slots[Fixnum.getValue(second)]; } catch (ArrayIndexOutOfBoundsException e) { // Shouldn't happen. return error(new LispError("Internal error.")); } return type_error(first, Symbol.STRUCTURE_OBJECT); } }; private static final Primitive STRUCTURE_SET = new pf_structure_set(); @DocString(name="structure-set", args="instance index new-value", returns="new-value") private static final class pf_structure_set extends Primitive { pf_structure_set() { super("structure-set", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { if (first instanceof StructureObject) try { ((StructureObject)first).slots[Fixnum.getValue(second)] = third; return third; } catch (ArrayIndexOutOfBoundsException e) { // Shouldn't happen. return error(new LispError("Internal error.")); } return type_error(first, Symbol.STRUCTURE_OBJECT); } }; private static final Primitive MAKE_STRUCTURE = new pf_make_structure(); @DocString(name="make-structure") private static final class pf_make_structure extends Primitive { pf_make_structure() { super("make-structure", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { return new StructureObject(checkSymbol(first), second); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { return new StructureObject(checkSymbol(first), second, third); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { return new StructureObject(checkSymbol(first), second, third, fourth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { return new StructureObject(checkSymbol(first), second, third, fourth, fifth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { return new StructureObject(checkSymbol(first), second, third, fourth, fifth, sixth); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { return new StructureObject(checkSymbol(first), second, third, fourth, fifth, sixth, seventh); } }; private static final Primitive _MAKE_STRUCTURE = new pf__make_structure(); @DocString(name="%make-structure", args="name slot-values", returns="object") private static final class pf__make_structure extends Primitive { pf__make_structure() { super("%make-structure", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { return new StructureObject(checkSymbol(first), second.copyToArray()); } }; private static final Primitive COPY_STRUCTURE = new pf_copy_structure(); @DocString(name="copy-structure", args="structure", returns="copy") private static final class pf_copy_structure extends Primitive { pf_copy_structure() { super(Symbol.COPY_STRUCTURE, "structure"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof StructureObject) return new StructureObject((StructureObject)arg); return type_error(arg, Symbol.STRUCTURE_OBJECT); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/StyleWarning.java0100644 0000000 0000000 00000004277 14202767264 021522 0ustar000000000 0000000 /* * StyleWarning.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class StyleWarning extends Warning { public StyleWarning(LispObject initArgs) { super(StandardClass.STYLE_WARNING); initialize(initArgs); } @Override public LispObject typeOf() { return Symbol.STYLE_WARNING; } @Override public LispObject classOf() { return StandardClass.STYLE_WARNING; } @Override public LispObject typep(LispObject type) { if (type == Symbol.STYLE_WARNING) return T; if (type == StandardClass.STYLE_WARNING) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/Symbol.java0100644 0000000 0000000 00000411322 14223403213 020312 0ustar000000000 0000000 /* * Symbol.java * * Copyright (C) 2002-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class Symbol extends LispObject implements java.io.Serializable { // Bit flags. private static final int FLAG_SPECIAL = 0x0001; private static final int FLAG_CONSTANT = 0x0002; private static final int FLAG_BUILT_IN_FUNCTION = 0x0004; public static final Symbol addFunction(String name, LispObject obj) { Symbol symbol = PACKAGE_CL.internAndExport(name); symbol.function = obj; return symbol; } public final SimpleString name; private int hash = -1; /** To be accessed by LispThread only: * used to find the index in the LispThread.specials array */ transient int specialIndex = LispThread.UNASSIGNED_SPECIAL_INDEX; private LispObject pkg; // Either a package object or NIL. private transient LispObject value; private transient LispObject function; private transient LispObject propertyList; private int flags; // Construct an uninterned symbol. public Symbol(String s) { name = new SimpleString(s); pkg = NIL; } public Symbol(SimpleString string) { name = string; pkg = NIL; } public Symbol(String s, Package pkg) { name = new SimpleString(s); this.pkg = pkg; } public Symbol(SimpleString string, Package pkg) { name = string; this.pkg = pkg; } public Symbol(SimpleString string, int hash, Package pkg) { name = string; this.hash = hash; this.pkg = pkg; } @Override @SuppressWarnings("FinalizeDeclaration") protected void finalize() throws Throwable { try { if (specialIndex != LispThread.UNASSIGNED_SPECIAL_INDEX) LispThread.releaseSpecialIndex(this); } finally { super.finalize(); } } @Override public LispObject typeOf() { if (pkg == PACKAGE_KEYWORD) return Symbol.KEYWORD; if (this == T) return Symbol.BOOLEAN; return Symbol.SYMBOL; } @Override public LispObject classOf() { return BuiltInClass.SYMBOL; } @Override public LispObject getDescription() { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, NIL); try { StringBuilder sb = new StringBuilder("The symbol "); sb.append(name.princToString()); sb.append(" at #x"); sb.append(Integer.toHexString(System.identityHashCode(this)).toUpperCase()); if (pkg instanceof Package) { sb.append(", an "); Symbol sym = ((Package)pkg).findExternalSymbol(name); sb.append(sym == this ? "external" : "internal"); sb.append(" symbol in the "); sb.append(((Package)pkg).getName()); sb.append(" package"); } return new SimpleString(sb); } finally { thread.resetSpecialBindings(mark); } } @Override public LispObject getParts() { LispObject parts = NIL; parts = parts.push(new Cons("name", name)); parts = parts.push(new Cons("package", pkg)); parts = parts.push(new Cons("value", value)); parts = parts.push(new Cons("function", function)); parts = parts.push(new Cons("plist", propertyList)); parts = parts.push(new Cons("flags", Fixnum.getInstance(flags))); parts = parts.push(new Cons("hash", Fixnum.getInstance(hash))); return parts.nreverse(); } @Override public LispObject typep(LispObject type) { if (type == Symbol.SYMBOL) return T; if (type == BuiltInClass.SYMBOL) return T; if (type == Symbol.KEYWORD) return pkg == PACKAGE_KEYWORD ? T : NIL; if (type == Symbol.BOOLEAN) return this == T ? T : NIL; return super.typep(type); } @Override public boolean constantp() { return (flags & FLAG_CONSTANT) != 0; } @Override public final LispObject STRING() { return name; } public final LispObject getPackage() { return pkg; } public final void setPackage(LispObject obj) { pkg = obj; } @Override public final boolean isSpecialOperator() { return (function instanceof SpecialOperator); } @Override public final boolean isSpecialVariable() { return (flags & FLAG_SPECIAL) != 0; } public final void setSpecial(boolean b) { if (b) flags |= FLAG_SPECIAL; else flags &= ~FLAG_SPECIAL; } public final void initializeSpecial(LispObject value) { flags |= FLAG_SPECIAL; this.value = value; } public final boolean isConstant() { return (flags & FLAG_CONSTANT) != 0; } public final void initializeConstant(LispObject value) { flags |= (FLAG_SPECIAL | FLAG_CONSTANT); this.value = value; } public final boolean isBuiltInFunction() { return (flags & FLAG_BUILT_IN_FUNCTION) != 0; } public final void setBuiltInFunction(boolean b) { if (b) flags |= FLAG_BUILT_IN_FUNCTION; else flags &= ~FLAG_BUILT_IN_FUNCTION; } public final String getName() { return name.getStringValue(); } public final String getQualifiedName() { final String n = name.getStringValue(); if (pkg == NIL) return("#:".concat(n)); if (pkg == PACKAGE_KEYWORD) return ":".concat(n); StringBuilder sb = new StringBuilder(((Package)pkg).getName()); if (((Package)pkg).findExternalSymbol(name) != null) sb.append(':'); else sb.append("::"); sb.append(n); return sb.toString(); } /** Gets the value associated with the symbol * as set by SYMBOL-VALUE. * * @return The associated value, or null if unbound. * * @see Symbol#symbolValue */ @Override public LispObject getSymbolValue() { return value; } /** Sets the value associated with the symbol * as if set by SYMBOL-VALUE. * * @return The associated value, or null if unbound. * * @see Symbol#symbolValue */ public final void setSymbolValue(LispObject value) { if (isConstant()) // Complement the check already done in SpecialOperators.sf_setq program_error("Can't change value of constant symbol " + princToString() + "."); this.value = value; } public SymbolMacro getSymbolMacro() { LispObject symbolMacro = get(this, SYMBOL_MACRO, null); if(symbolMacro instanceof SymbolMacro) { return (SymbolMacro) symbolMacro; } else if(symbolMacro != null) { error(new TypeError("The object " + symbolMacro + " is not a symbol macro")); } return null; } public void setSymbolMacro(SymbolMacro symbolMacro) { if(isSpecialVariable()) { program_error("Symbol " + princToString() + " names a special variable; can't install symbol macro."); } put(this, SYMBOL_MACRO, symbolMacro); } /** Returns the value associated with this symbol in the current * thread context when it is treated as a special variable. * * A lisp error is thrown if the symbol is unbound. * * @return The associated value * * @see LispThread#lookupSpecial * @see Symbol#getSymbolValue() * */ public final LispObject symbolValue() { return symbolValue(LispThread.currentThread()); } /** Returns the value associated with this symbol in the specified * thread context when it is treated as a special variable. * * A lisp error is thrown if the symbol is unbound. * * @return The associated value * * @see LispThread#lookupSpecial * @see Symbol#getSymbolValue() * */ public final LispObject symbolValue(LispThread thread) { LispObject val = thread.lookupSpecial(this); if (val != null) return val; if (value != null) return value; return error(new UnboundVariable(this)); } /** Returns the value of the symbol in the current thread context; * if the symbol has been declared special, the value of the innermost * binding is returned. Otherwise, the SYMBOL-VALUE is returned, or * null if unbound. * * @return A lisp object, or null if unbound * * @see LispThread#lookupSpecial * @see Symbol#getSymbolValue() * */ public final LispObject symbolValueNoThrow() { return symbolValueNoThrow(LispThread.currentThread()); } /** Returns the value of the symbol in the current thread context; * if the symbol has been declared special, the value of the innermost * binding is returned. Otherwise, the SYMBOL-VALUE is returned, or * null if unbound. * * @return A lisp object, or null if unbound * * @see LispThread#lookupSpecial * @see Symbol#getSymbolValue() * */ public final LispObject symbolValueNoThrow(LispThread thread) { if ((flags & FLAG_SPECIAL) != 0) { LispObject val = thread.lookupSpecial(this); if (val != null) return val; } return value; } @Override public LispObject getSymbolFunction() { return function; } @Override public final LispObject getSymbolFunctionOrDie() { if (function == null) return error(new UndefinedFunction(this)); if (function instanceof Autoload) { Autoload autoload = (Autoload) function; autoload.load(); } return function; } @Override public final LispObject getSymbolSetfFunction() { return get(this, Symbol.SETF_FUNCTION, NIL); } @Override public final LispObject getSymbolSetfFunctionOrDie() { LispObject obj = get(this, Symbol.SETF_FUNCTION, null); if (obj == null) error(new UndefinedFunction(list(Keyword.NAME, list(Symbol.SETF, this)))); return obj; } public final void setSymbolFunction(LispObject obj) { this.function = obj; } /** See LispObject.getStringValue() */ @Override public String getStringValue() { return name.getStringValue(); } @Override public final LispObject getPropertyList() { if (propertyList == null) propertyList = NIL; return propertyList; } @Override public final void setPropertyList(LispObject obj) { if (obj == null) throw new NullPointerException(); propertyList = obj; } @Override public String printObject() { final String n = name.getStringValue(); final LispThread thread = LispThread.currentThread(); boolean printEscape = (PRINT_ESCAPE.symbolValue(thread) != NIL); LispObject printCase = PRINT_CASE.symbolValue(thread); final LispObject readtableCase = ((Readtable)CURRENT_READTABLE.symbolValue(thread)).getReadtableCase(); boolean printReadably = (PRINT_READABLY.symbolValue(thread) != NIL); if (printReadably) { if (readtableCase != Keyword.UPCASE || printCase != Keyword.UPCASE) { StringBuilder sb = new StringBuilder(); if (pkg == PACKAGE_KEYWORD) { sb.append(':'); } else if (pkg instanceof Package) { sb.append(multipleEscape(((Package)pkg).getName())); sb.append("::"); } else { sb.append("#:"); } sb.append(multipleEscape(n)); return sb.toString(); } else { printEscape = true; } } if (!printEscape) { if (pkg == PACKAGE_KEYWORD) { if (printCase == Keyword.DOWNCASE) return n.toLowerCase(); if (printCase == Keyword.CAPITALIZE) return capitalize(n, readtableCase); return n; } // Printer escaping is disabled. if (readtableCase == Keyword.UPCASE) { if (printCase == Keyword.DOWNCASE) return n.toLowerCase(); if (printCase == Keyword.CAPITALIZE) return capitalize(n, readtableCase); return n; } else if (readtableCase == Keyword.DOWNCASE) { // "When the readtable case is :DOWNCASE, uppercase characters // are printed in their own case, and lowercase characters are // printed in the case specified by *PRINT-CASE*." (22.1.3.3.2) if (printCase == Keyword.DOWNCASE) return n; if (printCase == Keyword.UPCASE) return n.toUpperCase(); if (printCase == Keyword.CAPITALIZE) return capitalize(n, readtableCase); return n; } else if (readtableCase == Keyword.PRESERVE) { return n; } else // INVERT return invert(n); } // Printer escaping is enabled. final boolean escapeSymbolName = needsEscape(n, readtableCase, thread); String symbolName = escapeSymbolName ? multipleEscape(n) : n; if (!escapeSymbolName) { if (readtableCase == Keyword.PRESERVE) { // nothing to do } else if (readtableCase == Keyword.INVERT) { symbolName = invert(symbolName); } else if (printCase == Keyword.DOWNCASE) { symbolName = symbolName.toLowerCase(); } else if (printCase == Keyword.UPCASE) { symbolName = symbolName.toUpperCase(); } else if (printCase == Keyword.CAPITALIZE) { symbolName = capitalize(symbolName, readtableCase); } } if (pkg == NIL) { if (printReadably || PRINT_GENSYM.symbolValue(thread) != NIL) { return "#:".concat(symbolName); } else { return symbolName; } } if (pkg == PACKAGE_KEYWORD) { return ":".concat(symbolName); } // "Package prefixes are printed if necessary." (22.1.3.3.1) // Here we also use a package-local nickname if appropriate. final Package currentPackage = (Package) _PACKAGE_.symbolValue(thread); if (pkg == currentPackage) { return symbolName; } if (currentPackage != null && currentPackage.uses(pkg)) { // Check for name conflict in current package. if (currentPackage.findExternalSymbol(name) == null) if (currentPackage.findInternalSymbol(name) == null) if (((Package)pkg).findExternalSymbol(name) != null) return symbolName; } // Has this symbol been imported into the current package? if (currentPackage.findExternalSymbol(name) == this) return symbolName; if (currentPackage.findInternalSymbol(name) == this) return symbolName; if (currentPackage.findAccessibleSymbol(name) == this) return symbolName; // Package prefix is necessary. String packageName = ((Package)pkg).getName(); if (currentPackage.getLocallyNicknamedPackages().contains(pkg)) { LispObject nicknames = currentPackage.getLocalPackageNicknames(); while (nicknames != NIL) { if (nicknames.car().cdr() == pkg) { packageName = javaString(nicknames.car().car()); nicknames = NIL; } else { nicknames = nicknames.cdr(); } } } final boolean escapePackageName = needsEscape(packageName, readtableCase, thread); if (escapePackageName) { packageName = multipleEscape(packageName); } else { if (readtableCase == Keyword.UPCASE) { if (printCase == Keyword.DOWNCASE) packageName = packageName.toLowerCase(); else if (printCase == Keyword.CAPITALIZE) packageName = capitalize(packageName, readtableCase); } else if (readtableCase == Keyword.DOWNCASE) { if (printCase == Keyword.UPCASE) packageName = packageName.toUpperCase(); else if (printCase == Keyword.CAPITALIZE) packageName = capitalize(packageName, readtableCase); } else if (readtableCase == Keyword.INVERT) { packageName = invert(packageName); } } StringBuilder sb = new StringBuilder(packageName); if (((Package)pkg).findExternalSymbol(name) != null && DOUBLE_COLON_PACKAGE_SEPARATORS.symbolValue(thread) == NIL) sb.append(':'); else sb.append("::"); sb.append(symbolName); return sb.toString(); } private static final String invert(String s) { // "When the readtable case is :INVERT, the case of all alphabetic // characters in single case symbol names is inverted. Mixed-case // symbol names are printed as is." (22.1.3.3.2) final int limit = s.length(); final int LOWER = 1; final int UPPER = 2; int state = 0; for (int i = 0; i < limit; i++) { char c = s.charAt(i); if (Character.isUpperCase(c)) { if (state == LOWER) return s; // Mixed case. state = UPPER; } if (Character.isLowerCase(c)) { if (state == UPPER) return s; // Mixed case. state = LOWER; } } StringBuilder sb = new StringBuilder(limit); for (int i = 0; i < limit; i++) { char c = s.charAt(i); if (Character.isUpperCase(c)) sb.append(Character.toLowerCase(c)); else if (Character.isLowerCase(c)) sb.append(Character.toUpperCase(c)); else sb.append(c); } return sb.toString(); } private static final boolean needsEscape(String s, LispObject readtableCase, LispThread thread) { boolean escape = false; final int length = s.length(); if (length == 0) return true; if (s.charAt(0) == '#') return true; int radix; LispObject printBaseBinding = PRINT_BASE.symbolValue(thread); if (printBaseBinding instanceof Fixnum) { radix = ((Fixnum)printBaseBinding).value; } else { error(new TypeError("The value of *PRINT-BASE* is not of type (INTEGER 2 36).")); // Not reached. return false; } if (radix < 2 || radix > 36) { error(new TypeError("The value of *PRINT-BASE* is not of type (INTEGER 2 36).")); // Not reached. return false; } boolean seenNonDigit = false; for (int i = length; i-- > 0;) { char c = s.charAt(i); if ("(),|\\`'\";:".indexOf(c) >= 0) return true; if (Character.isWhitespace(c)) return true; if (readtableCase == Keyword.UPCASE) { if (Character.isLowerCase(c)) return true; } else if (readtableCase == Keyword.DOWNCASE) { if (Character.isUpperCase(c)) return true; } if (!escape && !seenNonDigit) { if (Character.digit(c, radix) < 0) seenNonDigit = true; } } if (!seenNonDigit) return true; if (s.charAt(0) == '.') { boolean allDots = true; for (int i = length; i-- > 1;) { if (s.charAt(i) != '.') { allDots = false; break; } } if (allDots) return true; } return false; } private static final String multipleEscape(String s) { StringBuilder sb = new StringBuilder("|"); final int limit = s.length(); for (int i = 0; i < limit; i++) { char c = s.charAt(i); if (c == '|' || c == '\\') sb.append('\\'); sb.append(c); } sb.append('|'); return sb.toString(); } private static final String capitalize(String s, LispObject readtableCase) { if (readtableCase == Keyword.INVERT || readtableCase == Keyword.PRESERVE) return s; final int limit = s.length(); StringBuilder sb = new StringBuilder(limit); boolean lastCharWasAlphanumeric = false; for (int i = 0; i < limit; i++) { char c = s.charAt(i); if (Character.isLowerCase(c)) { if (readtableCase == Keyword.UPCASE) sb.append(c); else // DOWNCASE sb.append(lastCharWasAlphanumeric ? c : LispCharacter.toUpperCase(c)); lastCharWasAlphanumeric = true; } else if (Character.isUpperCase(c)) { if (readtableCase == Keyword.UPCASE) sb.append(lastCharWasAlphanumeric ? LispCharacter.toLowerCase(c) : c); else // DOWNCASE sb.append(c); lastCharWasAlphanumeric = true; } else { sb.append(c); lastCharWasAlphanumeric = Character.isDigit(c); } } return sb.toString(); } @Override public final int sxhash() { int h = hash; if (h < 0) { h = name.sxhash(); hash = h; } return h; } @Override final public LispObject execute() { LispObject fun; if ((fun = function) == null) return undefinedFunction(NIL); return fun.execute(); } @Override final public LispObject execute(LispObject arg) { LispObject fun; if ((fun = function) == null) return undefinedFunction(list(arg)); return fun.execute(arg); } @Override final public LispObject execute(LispObject first, LispObject second) { LispObject fun; if ((fun = function) == null) return undefinedFunction(list(first, second)); return fun.execute(first, second); } @Override final public LispObject execute(LispObject first, LispObject second, LispObject third) { LispObject fun; if ((fun = function) == null) return undefinedFunction(list(first, second, third)); return fun.execute(first, second, third); } @Override final public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth) { LispObject fun; if ((fun = function) == null) return undefinedFunction(list(first, second, third, fourth)); return fun.execute(first, second, third, fourth); } @Override final public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth) { LispObject fun; if ((fun = function) == null) return undefinedFunction(list(first, second, third, fourth, fifth)); return fun.execute(first, second, third, fourth, fifth); } @Override final public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth) { LispObject fun; if ((fun = function) == null) return undefinedFunction(list(first, second, third, fourth, fifth, sixth)); return fun.execute(first, second, third, fourth, fifth, sixth); } @Override final public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh) { LispObject fun; if ((fun = function) == null) return undefinedFunction(list(first, second, third, fourth, fifth, sixth, seventh)); return fun.execute(first, second, third, fourth, fifth, sixth, seventh); } @Override final public LispObject execute(LispObject first, LispObject second, LispObject third, LispObject fourth, LispObject fifth, LispObject sixth, LispObject seventh, LispObject eighth) { LispObject fun; if ((fun = function) == null) return undefinedFunction(list(first, second, third, fourth, fifth, sixth, seventh, eighth)); return fun.execute(first, second, third, fourth, fifth, sixth, seventh, eighth); } @Override final public LispObject execute(LispObject[] args) { LispObject fun; if ((fun = function) == null) { LispObject list = NIL; for (int i = args.length; i-- > 0;) list = new Cons(args[i], list); return undefinedFunction(list); } return fun.execute(args); } private final LispObject undefinedFunction(LispObject args) { return LispThread.currentThread().execute(Symbol.UNDEFINED_FUNCTION_CALLED, this, args); } @Override public void incrementCallCount() { if (function != null) function.incrementCallCount(); } @Override public void incrementHotCount() { if (function != null) function.incrementHotCount(); } public Object readResolve() throws java.io.ObjectStreamException { if(pkg instanceof Package) { Symbol s = ((Package) pkg).intern(name.getStringValue()); return s; } else { return this; } } @Override public String toString() { StringBuilder sb = new StringBuilder(); if (pkg instanceof Package) { sb.append(((Package)pkg).getName()); sb.append(":"); } else { sb.append("#:"); } sb.append(name); return sb.toString(); } // External symbols in CL package. public static final Symbol AND_ALLOW_OTHER_KEYS = PACKAGE_CL.addExternalSymbol("&ALLOW-OTHER-KEYS"); public static final Symbol AND_AUX = PACKAGE_CL.addExternalSymbol("&AUX"); public static final Symbol AND_BODY = PACKAGE_CL.addExternalSymbol("&BODY"); public static final Symbol AND_ENVIRONMENT = PACKAGE_CL.addExternalSymbol("&ENVIRONMENT"); public static final Symbol AND_KEY = PACKAGE_CL.addExternalSymbol("&KEY"); public static final Symbol AND_OPTIONAL = PACKAGE_CL.addExternalSymbol("&OPTIONAL"); public static final Symbol AND_REST = PACKAGE_CL.addExternalSymbol("&REST"); public static final Symbol AND_WHOLE = PACKAGE_CL.addExternalSymbol("&WHOLE"); public static final Symbol STAR = PACKAGE_CL.addExternalSymbol("*"); public static final Symbol STAR_STAR = PACKAGE_CL.addExternalSymbol("**"); public static final Symbol STAR_STAR_STAR = PACKAGE_CL.addExternalSymbol("***"); public static final Symbol BREAK_ON_SIGNALS = PACKAGE_CL.addExternalSymbol("*BREAK-ON-SIGNALS*"); public static final Symbol _COMPILE_FILE_PATHNAME_ = PACKAGE_CL.addExternalSymbol("*COMPILE-FILE-PATHNAME*"); public static final Symbol COMPILE_FILE_TRUENAME = PACKAGE_CL.addExternalSymbol("*COMPILE-FILE-TRUENAME*"); public static final Symbol COMPILE_PRINT = PACKAGE_CL.addExternalSymbol("*COMPILE-PRINT*"); public static final Symbol COMPILE_VERBOSE = PACKAGE_CL.addExternalSymbol("*COMPILE-VERBOSE*"); public static final Symbol DEBUG_IO = PACKAGE_CL.addExternalSymbol("*DEBUG-IO*"); public static final Symbol DEBUGGER_HOOK = PACKAGE_CL.addExternalSymbol("*DEBUGGER-HOOK*"); public static final Symbol DEFAULT_PATHNAME_DEFAULTS = PACKAGE_CL.addExternalSymbol("*DEFAULT-PATHNAME-DEFAULTS*"); public static final Symbol ERROR_OUTPUT = PACKAGE_CL.addExternalSymbol("*ERROR-OUTPUT*"); public static final Symbol FEATURES = PACKAGE_CL.addExternalSymbol("*FEATURES*"); public static final Symbol GENSYM_COUNTER = PACKAGE_CL.addExternalSymbol("*GENSYM-COUNTER*"); public static final Symbol LOAD_PATHNAME = PACKAGE_CL.addExternalSymbol("*LOAD-PATHNAME*"); public static final Symbol LOAD_PRINT = PACKAGE_CL.addExternalSymbol("*LOAD-PRINT*"); public static final Symbol LOAD_TRUENAME = PACKAGE_CL.addExternalSymbol("*LOAD-TRUENAME*"); public static final Symbol LOAD_VERBOSE = PACKAGE_CL.addExternalSymbol("*LOAD-VERBOSE*"); public static final Symbol MACROEXPAND_HOOK = PACKAGE_CL.addExternalSymbol("*MACROEXPAND-HOOK*"); public static final Symbol MODULES = PACKAGE_CL.addExternalSymbol("*MODULES*"); public static final Symbol _PACKAGE_ = PACKAGE_CL.addExternalSymbol("*PACKAGE*"); public static final Symbol PRINT_ARRAY = PACKAGE_CL.addExternalSymbol("*PRINT-ARRAY*"); public static final Symbol PRINT_BASE = PACKAGE_CL.addExternalSymbol("*PRINT-BASE*"); public static final Symbol PRINT_CASE = PACKAGE_CL.addExternalSymbol("*PRINT-CASE*"); public static final Symbol PRINT_CIRCLE = PACKAGE_CL.addExternalSymbol("*PRINT-CIRCLE*"); public static final Symbol PRINT_ESCAPE = PACKAGE_CL.addExternalSymbol("*PRINT-ESCAPE*"); public static final Symbol PRINT_GENSYM = PACKAGE_CL.addExternalSymbol("*PRINT-GENSYM*"); public static final Symbol PRINT_LENGTH = PACKAGE_CL.addExternalSymbol("*PRINT-LENGTH*"); public static final Symbol PRINT_LEVEL = PACKAGE_CL.addExternalSymbol("*PRINT-LEVEL*"); public static final Symbol PRINT_LINES = PACKAGE_CL.addExternalSymbol("*PRINT-LINES*"); public static final Symbol PRINT_MISER_WIDTH = PACKAGE_CL.addExternalSymbol("*PRINT-MISER-WIDTH*"); public static final Symbol PRINT_PPRINT_DISPATCH = PACKAGE_CL.addExternalSymbol("*PRINT-PPRINT-DISPATCH*"); public static final Symbol PRINT_PRETTY = PACKAGE_CL.addExternalSymbol("*PRINT-PRETTY*"); public static final Symbol PRINT_RADIX = PACKAGE_CL.addExternalSymbol("*PRINT-RADIX*"); public static final Symbol PRINT_READABLY = PACKAGE_CL.addExternalSymbol("*PRINT-READABLY*"); public static final Symbol PRINT_RIGHT_MARGIN = PACKAGE_CL.addExternalSymbol("*PRINT-RIGHT-MARGIN*"); public static final Symbol QUERY_IO = PACKAGE_CL.addExternalSymbol("*QUERY-IO*"); public static final Symbol _RANDOM_STATE_ = PACKAGE_CL.addExternalSymbol("*RANDOM-STATE*"); public static final Symbol READ_BASE = PACKAGE_CL.addExternalSymbol("*READ-BASE*"); public static final Symbol READ_DEFAULT_FLOAT_FORMAT = PACKAGE_CL.addExternalSymbol("*READ-DEFAULT-FLOAT-FORMAT*"); public static final Symbol READ_EVAL = PACKAGE_CL.addExternalSymbol("*READ-EVAL*"); public static final Symbol READ_SUPPRESS = PACKAGE_CL.addExternalSymbol("*READ-SUPPRESS*"); public static final Symbol CURRENT_READTABLE = PACKAGE_CL.addExternalSymbol("*READTABLE*"); public static final Symbol STANDARD_INPUT = PACKAGE_CL.addExternalSymbol("*STANDARD-INPUT*"); public static final Symbol STANDARD_OUTPUT = PACKAGE_CL.addExternalSymbol("*STANDARD-OUTPUT*"); public static final Symbol TERMINAL_IO = PACKAGE_CL.addExternalSymbol("*TERMINAL-IO*"); public static final Symbol TRACE_OUTPUT = PACKAGE_CL.addExternalSymbol("*TRACE-OUTPUT*"); public static final Symbol PLUS = PACKAGE_CL.addExternalSymbol("+"); public static final Symbol PLUS_PLUS = PACKAGE_CL.addExternalSymbol("++"); public static final Symbol PLUS_PLUS_PLUS = PACKAGE_CL.addExternalSymbol("+++"); public static final Symbol MINUS = PACKAGE_CL.addExternalSymbol("-"); public static final Symbol SLASH = PACKAGE_CL.addExternalSymbol("/"); public static final Symbol SLASH_SLASH = PACKAGE_CL.addExternalSymbol("//"); public static final Symbol SLASH_SLASH_SLASH = PACKAGE_CL.addExternalSymbol("///"); public static final Symbol NOT_EQUALS = PACKAGE_CL.addExternalSymbol("/="); public static final Symbol ONE_PLUS = PACKAGE_CL.addExternalSymbol("1+"); public static final Symbol ONE_MINUS = PACKAGE_CL.addExternalSymbol("1-"); public static final Symbol LT = PACKAGE_CL.addExternalSymbol("<"); public static final Symbol LE = PACKAGE_CL.addExternalSymbol("<="); public static final Symbol EQUALS = PACKAGE_CL.addExternalSymbol("="); public static final Symbol GT = PACKAGE_CL.addExternalSymbol(">"); public static final Symbol GE = PACKAGE_CL.addExternalSymbol(">="); public static final Symbol ABORT = PACKAGE_CL.addExternalSymbol("ABORT"); public static final Symbol ABS = PACKAGE_CL.addExternalSymbol("ABS"); public static final Symbol ACONS = PACKAGE_CL.addExternalSymbol("ACONS"); public static final Symbol ACOS = PACKAGE_CL.addExternalSymbol("ACOS"); public static final Symbol ACOSH = PACKAGE_CL.addExternalSymbol("ACOSH"); public static final Symbol ADD_METHOD = PACKAGE_CL.addExternalSymbol("ADD-METHOD"); public static final Symbol ADJOIN = PACKAGE_CL.addExternalSymbol("ADJOIN"); public static final Symbol ADJUST_ARRAY = PACKAGE_CL.addExternalSymbol("ADJUST-ARRAY"); public static final Symbol ADJUSTABLE_ARRAY_P = PACKAGE_CL.addExternalSymbol("ADJUSTABLE-ARRAY-P"); public static final Symbol ALLOCATE_INSTANCE = PACKAGE_CL.addExternalSymbol("ALLOCATE-INSTANCE"); public static final Symbol ALPHA_CHAR_P = PACKAGE_CL.addExternalSymbol("ALPHA-CHAR-P"); public static final Symbol ALPHANUMERICP = PACKAGE_CL.addExternalSymbol("ALPHANUMERICP"); public static final Symbol AND = PACKAGE_CL.addExternalSymbol("AND"); public static final Symbol APPEND = PACKAGE_CL.addExternalSymbol("APPEND"); public static final Symbol APPLY = PACKAGE_CL.addExternalSymbol("APPLY"); public static final Symbol APROPOS = PACKAGE_CL.addExternalSymbol("APROPOS"); public static final Symbol APROPOS_LIST = PACKAGE_CL.addExternalSymbol("APROPOS-LIST"); public static final Symbol AREF = PACKAGE_CL.addExternalSymbol("AREF"); public static final Symbol ARITHMETIC_ERROR = PACKAGE_CL.addExternalSymbol("ARITHMETIC-ERROR"); public static final Symbol ARITHMETIC_ERROR_OPERANDS = PACKAGE_CL.addExternalSymbol("ARITHMETIC-ERROR-OPERANDS"); public static final Symbol ARITHMETIC_ERROR_OPERATION = PACKAGE_CL.addExternalSymbol("ARITHMETIC-ERROR-OPERATION"); public static final Symbol ARRAY = PACKAGE_CL.addExternalSymbol("ARRAY"); public static final Symbol ARRAY_DIMENSION = PACKAGE_CL.addExternalSymbol("ARRAY-DIMENSION"); public static final Symbol ARRAY_DIMENSION_LIMIT = PACKAGE_CL.addExternalSymbol("ARRAY-DIMENSION-LIMIT"); public static final Symbol ARRAY_DIMENSIONS = PACKAGE_CL.addExternalSymbol("ARRAY-DIMENSIONS"); public static final Symbol ARRAY_DISPLACEMENT = PACKAGE_CL.addExternalSymbol("ARRAY-DISPLACEMENT"); public static final Symbol ARRAY_ELEMENT_TYPE = PACKAGE_CL.addExternalSymbol("ARRAY-ELEMENT-TYPE"); public static final Symbol ARRAY_HAS_FILL_POINTER_P = PACKAGE_CL.addExternalSymbol("ARRAY-HAS-FILL-POINTER-P"); public static final Symbol ARRAY_IN_BOUNDS_P = PACKAGE_CL.addExternalSymbol("ARRAY-IN-BOUNDS-P"); public static final Symbol ARRAY_RANK = PACKAGE_CL.addExternalSymbol("ARRAY-RANK"); public static final Symbol ARRAY_RANK_LIMIT = PACKAGE_CL.addExternalSymbol("ARRAY-RANK-LIMIT"); public static final Symbol ARRAY_ROW_MAJOR_INDEX = PACKAGE_CL.addExternalSymbol("ARRAY-ROW-MAJOR-INDEX"); public static final Symbol ARRAY_TOTAL_SIZE = PACKAGE_CL.addExternalSymbol("ARRAY-TOTAL-SIZE"); public static final Symbol ARRAY_TOTAL_SIZE_LIMIT = PACKAGE_CL.addExternalSymbol("ARRAY-TOTAL-SIZE-LIMIT"); public static final Symbol ARRAYP = PACKAGE_CL.addExternalSymbol("ARRAYP"); public static final Symbol ASH = PACKAGE_CL.addExternalSymbol("ASH"); public static final Symbol ASIN = PACKAGE_CL.addExternalSymbol("ASIN"); public static final Symbol ASINH = PACKAGE_CL.addExternalSymbol("ASINH"); public static final Symbol ASSERT = PACKAGE_CL.addExternalSymbol("ASSERT"); public static final Symbol ASSOC = PACKAGE_CL.addExternalSymbol("ASSOC"); public static final Symbol ASSOC_IF = PACKAGE_CL.addExternalSymbol("ASSOC-IF"); public static final Symbol ASSOC_IF_NOT = PACKAGE_CL.addExternalSymbol("ASSOC-IF-NOT"); public static final Symbol ATAN = PACKAGE_CL.addExternalSymbol("ATAN"); public static final Symbol ATANH = PACKAGE_CL.addExternalSymbol("ATANH"); public static final Symbol ATOM = PACKAGE_CL.addExternalSymbol("ATOM"); public static final Symbol BASE_CHAR = PACKAGE_CL.addExternalSymbol("BASE-CHAR"); public static final Symbol BASE_STRING = PACKAGE_CL.addExternalSymbol("BASE-STRING"); public static final Symbol BIGNUM = PACKAGE_CL.addExternalSymbol("BIGNUM"); public static final Symbol BIT = PACKAGE_CL.addExternalSymbol("BIT"); public static final Symbol BIT_AND = PACKAGE_CL.addExternalSymbol("BIT-AND"); public static final Symbol BIT_ANDC1 = PACKAGE_CL.addExternalSymbol("BIT-ANDC1"); public static final Symbol BIT_ANDC2 = PACKAGE_CL.addExternalSymbol("BIT-ANDC2"); public static final Symbol BIT_EQV = PACKAGE_CL.addExternalSymbol("BIT-EQV"); public static final Symbol BIT_IOR = PACKAGE_CL.addExternalSymbol("BIT-IOR"); public static final Symbol BIT_NAND = PACKAGE_CL.addExternalSymbol("BIT-NAND"); public static final Symbol BIT_NOR = PACKAGE_CL.addExternalSymbol("BIT-NOR"); public static final Symbol BIT_NOT = PACKAGE_CL.addExternalSymbol("BIT-NOT"); public static final Symbol BIT_ORC1 = PACKAGE_CL.addExternalSymbol("BIT-ORC1"); public static final Symbol BIT_ORC2 = PACKAGE_CL.addExternalSymbol("BIT-ORC2"); public static final Symbol BIT_VECTOR = PACKAGE_CL.addExternalSymbol("BIT-VECTOR"); public static final Symbol BIT_VECTOR_P = PACKAGE_CL.addExternalSymbol("BIT-VECTOR-P"); public static final Symbol BIT_XOR = PACKAGE_CL.addExternalSymbol("BIT-XOR"); public static final Symbol BLOCK = PACKAGE_CL.addExternalSymbol("BLOCK"); public static final Symbol BOOLE = PACKAGE_CL.addExternalSymbol("BOOLE"); public static final Symbol BOOLE_1 = PACKAGE_CL.addExternalSymbol("BOOLE-1"); public static final Symbol BOOLE_2 = PACKAGE_CL.addExternalSymbol("BOOLE-2"); public static final Symbol BOOLE_AND = PACKAGE_CL.addExternalSymbol("BOOLE-AND"); public static final Symbol BOOLE_ANDC1 = PACKAGE_CL.addExternalSymbol("BOOLE-ANDC1"); public static final Symbol BOOLE_ANDC2 = PACKAGE_CL.addExternalSymbol("BOOLE-ANDC2"); public static final Symbol BOOLE_C1 = PACKAGE_CL.addExternalSymbol("BOOLE-C1"); public static final Symbol BOOLE_C2 = PACKAGE_CL.addExternalSymbol("BOOLE-C2"); public static final Symbol BOOLE_CLR = PACKAGE_CL.addExternalSymbol("BOOLE-CLR"); public static final Symbol BOOLE_EQV = PACKAGE_CL.addExternalSymbol("BOOLE-EQV"); public static final Symbol BOOLE_IOR = PACKAGE_CL.addExternalSymbol("BOOLE-IOR"); public static final Symbol BOOLE_NAND = PACKAGE_CL.addExternalSymbol("BOOLE-NAND"); public static final Symbol BOOLE_NOR = PACKAGE_CL.addExternalSymbol("BOOLE-NOR"); public static final Symbol BOOLE_ORC1 = PACKAGE_CL.addExternalSymbol("BOOLE-ORC1"); public static final Symbol BOOLE_ORC2 = PACKAGE_CL.addExternalSymbol("BOOLE-ORC2"); public static final Symbol BOOLE_SET = PACKAGE_CL.addExternalSymbol("BOOLE-SET"); public static final Symbol BOOLE_XOR = PACKAGE_CL.addExternalSymbol("BOOLE-XOR"); public static final Symbol BOOLEAN = PACKAGE_CL.addExternalSymbol("BOOLEAN"); public static final Symbol BOTH_CASE_P = PACKAGE_CL.addExternalSymbol("BOTH-CASE-P"); public static final Symbol BOUNDP = PACKAGE_CL.addExternalSymbol("BOUNDP"); public static final Symbol BREAK = PACKAGE_CL.addExternalSymbol("BREAK"); public static final Symbol BROADCAST_STREAM = PACKAGE_CL.addExternalSymbol("BROADCAST-STREAM"); public static final Symbol BROADCAST_STREAM_STREAMS = PACKAGE_CL.addExternalSymbol("BROADCAST-STREAM-STREAMS"); public static final Symbol BUILT_IN_CLASS = PACKAGE_CL.addExternalSymbol("BUILT-IN-CLASS"); public static final Symbol BUTLAST = PACKAGE_CL.addExternalSymbol("BUTLAST"); public static final Symbol BYTE = PACKAGE_CL.addExternalSymbol("BYTE"); public static final Symbol BYTE_POSITION = PACKAGE_CL.addExternalSymbol("BYTE-POSITION"); public static final Symbol BYTE_SIZE = PACKAGE_CL.addExternalSymbol("BYTE-SIZE"); public static final Symbol CAAAAR = PACKAGE_CL.addExternalSymbol("CAAAAR"); public static final Symbol CAAADR = PACKAGE_CL.addExternalSymbol("CAAADR"); public static final Symbol CAAAR = PACKAGE_CL.addExternalSymbol("CAAAR"); public static final Symbol CAADAR = PACKAGE_CL.addExternalSymbol("CAADAR"); public static final Symbol CAADDR = PACKAGE_CL.addExternalSymbol("CAADDR"); public static final Symbol CAADR = PACKAGE_CL.addExternalSymbol("CAADR"); public static final Symbol CAAR = PACKAGE_CL.addExternalSymbol("CAAR"); public static final Symbol CADAAR = PACKAGE_CL.addExternalSymbol("CADAAR"); public static final Symbol CADADR = PACKAGE_CL.addExternalSymbol("CADADR"); public static final Symbol CADAR = PACKAGE_CL.addExternalSymbol("CADAR"); public static final Symbol CADDAR = PACKAGE_CL.addExternalSymbol("CADDAR"); public static final Symbol CADDDR = PACKAGE_CL.addExternalSymbol("CADDDR"); public static final Symbol CADDR = PACKAGE_CL.addExternalSymbol("CADDR"); public static final Symbol CADR = PACKAGE_CL.addExternalSymbol("CADR"); public static final Symbol CALL_ARGUMENTS_LIMIT = PACKAGE_CL.addExternalSymbol("CALL-ARGUMENTS-LIMIT"); public static final Symbol CALL_METHOD = PACKAGE_CL.addExternalSymbol("CALL-METHOD"); public static final Symbol CALL_NEXT_METHOD = PACKAGE_CL.addExternalSymbol("CALL-NEXT-METHOD"); public static final Symbol CAR = PACKAGE_CL.addExternalSymbol("CAR"); public static final Symbol CASE = PACKAGE_CL.addExternalSymbol("CASE"); public static final Symbol CATCH = PACKAGE_CL.addExternalSymbol("CATCH"); public static final Symbol CCASE = PACKAGE_CL.addExternalSymbol("CCASE"); public static final Symbol CDAAAR = PACKAGE_CL.addExternalSymbol("CDAAAR"); public static final Symbol CDAADR = PACKAGE_CL.addExternalSymbol("CDAADR"); public static final Symbol CDAAR = PACKAGE_CL.addExternalSymbol("CDAAR"); public static final Symbol CDADAR = PACKAGE_CL.addExternalSymbol("CDADAR"); public static final Symbol CDADDR = PACKAGE_CL.addExternalSymbol("CDADDR"); public static final Symbol CDADR = PACKAGE_CL.addExternalSymbol("CDADR"); public static final Symbol CDAR = PACKAGE_CL.addExternalSymbol("CDAR"); public static final Symbol CDDAAR = PACKAGE_CL.addExternalSymbol("CDDAAR"); public static final Symbol CDDADR = PACKAGE_CL.addExternalSymbol("CDDADR"); public static final Symbol CDDAR = PACKAGE_CL.addExternalSymbol("CDDAR"); public static final Symbol CDDDAR = PACKAGE_CL.addExternalSymbol("CDDDAR"); public static final Symbol CDDDDR = PACKAGE_CL.addExternalSymbol("CDDDDR"); public static final Symbol CDDDR = PACKAGE_CL.addExternalSymbol("CDDDR"); public static final Symbol CDDR = PACKAGE_CL.addExternalSymbol("CDDR"); public static final Symbol CDR = PACKAGE_CL.addExternalSymbol("CDR"); public static final Symbol CEILING = PACKAGE_CL.addExternalSymbol("CEILING"); public static final Symbol CELL_ERROR = PACKAGE_CL.addExternalSymbol("CELL-ERROR"); public static final Symbol CELL_ERROR_NAME = PACKAGE_CL.addExternalSymbol("CELL-ERROR-NAME"); public static final Symbol CERROR = PACKAGE_CL.addExternalSymbol("CERROR"); public static final Symbol CHANGE_CLASS = PACKAGE_CL.addExternalSymbol("CHANGE-CLASS"); public static final Symbol CHAR = PACKAGE_CL.addExternalSymbol("CHAR"); public static final Symbol CHAR_CODE = PACKAGE_CL.addExternalSymbol("CHAR-CODE"); public static final Symbol CHAR_CODE_LIMIT = PACKAGE_CL.addExternalSymbol("CHAR-CODE-LIMIT"); public static final Symbol CHAR_DOWNCASE = PACKAGE_CL.addExternalSymbol("CHAR-DOWNCASE"); public static final Symbol CHAR_EQUAL = PACKAGE_CL.addExternalSymbol("CHAR-EQUAL"); public static final Symbol CHAR_GREATERP = PACKAGE_CL.addExternalSymbol("CHAR-GREATERP"); public static final Symbol CHAR_INT = PACKAGE_CL.addExternalSymbol("CHAR-INT"); public static final Symbol CHAR_LESSP = PACKAGE_CL.addExternalSymbol("CHAR-LESSP"); public static final Symbol CHAR_NAME = PACKAGE_CL.addExternalSymbol("CHAR-NAME"); public static final Symbol CHAR_NOT_EQUAL = PACKAGE_CL.addExternalSymbol("CHAR-NOT-EQUAL"); public static final Symbol CHAR_NOT_GREATERP = PACKAGE_CL.addExternalSymbol("CHAR-NOT-GREATERP"); public static final Symbol CHAR_NOT_LESSP = PACKAGE_CL.addExternalSymbol("CHAR-NOT-LESSP"); public static final Symbol CHAR_UPCASE = PACKAGE_CL.addExternalSymbol("CHAR-UPCASE"); public static final Symbol CHAR_NE = PACKAGE_CL.addExternalSymbol("CHAR/="); public static final Symbol CHAR_LT = PACKAGE_CL.addExternalSymbol("CHAR<"); public static final Symbol CHAR_LE = PACKAGE_CL.addExternalSymbol("CHAR<="); public static final Symbol CHAR_EQUALS = PACKAGE_CL.addExternalSymbol("CHAR="); public static final Symbol CHAR_GT = PACKAGE_CL.addExternalSymbol("CHAR>"); public static final Symbol CHAR_GE = PACKAGE_CL.addExternalSymbol("CHAR>="); public static final Symbol CHARACTER = PACKAGE_CL.addExternalSymbol("CHARACTER"); public static final Symbol CHARACTERP = PACKAGE_CL.addExternalSymbol("CHARACTERP"); public static final Symbol CHECK_TYPE = PACKAGE_CL.addExternalSymbol("CHECK-TYPE"); public static final Symbol CIS = PACKAGE_CL.addExternalSymbol("CIS"); public static final Symbol CLASS = PACKAGE_CL.addExternalSymbol("CLASS"); public static final Symbol CLASS_NAME = PACKAGE_CL.addExternalSymbol("CLASS-NAME"); public static final Symbol CLASS_OF = PACKAGE_CL.addExternalSymbol("CLASS-OF"); public static final Symbol CLEAR_INPUT = PACKAGE_CL.addExternalSymbol("CLEAR-INPUT"); public static final Symbol CLEAR_OUTPUT = PACKAGE_CL.addExternalSymbol("CLEAR-OUTPUT"); public static final Symbol CLOSE = PACKAGE_CL.addExternalSymbol("CLOSE"); public static final Symbol CLRHASH = PACKAGE_CL.addExternalSymbol("CLRHASH"); public static final Symbol CODE_CHAR = PACKAGE_CL.addExternalSymbol("CODE-CHAR"); public static final Symbol COERCE = PACKAGE_CL.addExternalSymbol("COERCE"); public static final Symbol COMPILATION_SPEED = PACKAGE_CL.addExternalSymbol("COMPILATION-SPEED"); public static final Symbol COMPILE = PACKAGE_CL.addExternalSymbol("COMPILE"); public static final Symbol COMPILE_FILE = PACKAGE_CL.addExternalSymbol("COMPILE-FILE"); public static final Symbol COMPILE_FILE_PATHNAME = PACKAGE_CL.addExternalSymbol("COMPILE-FILE-PATHNAME"); public static final Symbol COMPILED_FUNCTION = PACKAGE_CL.addExternalSymbol("COMPILED-FUNCTION"); public static final Symbol COMPILED_FUNCTION_P = PACKAGE_CL.addExternalSymbol("COMPILED-FUNCTION-P"); public static final Symbol COMPILER_MACRO = PACKAGE_CL.addExternalSymbol("COMPILER-MACRO"); public static final Symbol COMPILER_MACRO_FUNCTION = PACKAGE_CL.addExternalSymbol("COMPILER-MACRO-FUNCTION"); public static final Symbol COMPLEMENT = PACKAGE_CL.addExternalSymbol("COMPLEMENT"); public static final Symbol COMPLEX = PACKAGE_CL.addExternalSymbol("COMPLEX"); public static final Symbol COMPLEXP = PACKAGE_CL.addExternalSymbol("COMPLEXP"); public static final Symbol COMPUTE_APPLICABLE_METHODS = PACKAGE_CL.addExternalSymbol("COMPUTE-APPLICABLE-METHODS"); public static final Symbol COMPUTE_RESTARTS = PACKAGE_CL.addExternalSymbol("COMPUTE-RESTARTS"); public static final Symbol CONCATENATE = PACKAGE_CL.addExternalSymbol("CONCATENATE"); public static final Symbol CONCATENATED_STREAM = PACKAGE_CL.addExternalSymbol("CONCATENATED-STREAM"); public static final Symbol CONCATENATED_STREAM_STREAMS = PACKAGE_CL.addExternalSymbol("CONCATENATED-STREAM-STREAMS"); public static final Symbol COND = PACKAGE_CL.addExternalSymbol("COND"); public static final Symbol CONDITION = PACKAGE_CL.addExternalSymbol("CONDITION"); public static final Symbol CONJUGATE = PACKAGE_CL.addExternalSymbol("CONJUGATE"); public static final Symbol CONS = PACKAGE_CL.addExternalSymbol("CONS"); public static final Symbol CONSP = PACKAGE_CL.addExternalSymbol("CONSP"); public static final Symbol CONSTANTLY = PACKAGE_CL.addExternalSymbol("CONSTANTLY"); public static final Symbol CONSTANTP = PACKAGE_CL.addExternalSymbol("CONSTANTP"); public static final Symbol CONTINUE = PACKAGE_CL.addExternalSymbol("CONTINUE"); public static final Symbol CONTROL_ERROR = PACKAGE_CL.addExternalSymbol("CONTROL-ERROR"); public static final Symbol COPY_ALIST = PACKAGE_CL.addExternalSymbol("COPY-ALIST"); public static final Symbol COPY_LIST = PACKAGE_CL.addExternalSymbol("COPY-LIST"); public static final Symbol COPY_PPRINT_DISPATCH = PACKAGE_CL.addExternalSymbol("COPY-PPRINT-DISPATCH"); public static final Symbol COPY_READTABLE = PACKAGE_CL.addExternalSymbol("COPY-READTABLE"); public static final Symbol COPY_SEQ = PACKAGE_CL.addExternalSymbol("COPY-SEQ"); public static final Symbol COPY_STRUCTURE = PACKAGE_CL.addExternalSymbol("COPY-STRUCTURE"); public static final Symbol COPY_SYMBOL = PACKAGE_CL.addExternalSymbol("COPY-SYMBOL"); public static final Symbol COPY_TREE = PACKAGE_CL.addExternalSymbol("COPY-TREE"); public static final Symbol COS = PACKAGE_CL.addExternalSymbol("COS"); public static final Symbol COSH = PACKAGE_CL.addExternalSymbol("COSH"); public static final Symbol COUNT = PACKAGE_CL.addExternalSymbol("COUNT"); public static final Symbol COUNT_IF = PACKAGE_CL.addExternalSymbol("COUNT-IF"); public static final Symbol COUNT_IF_NOT = PACKAGE_CL.addExternalSymbol("COUNT-IF-NOT"); public static final Symbol CTYPECASE = PACKAGE_CL.addExternalSymbol("CTYPECASE"); public static final Symbol DEBUG = PACKAGE_CL.addExternalSymbol("DEBUG"); public static final Symbol DECF = PACKAGE_CL.addExternalSymbol("DECF"); public static final Symbol DECLAIM = PACKAGE_CL.addExternalSymbol("DECLAIM"); public static final Symbol DECLARATION = PACKAGE_CL.addExternalSymbol("DECLARATION"); public static final Symbol DECLARE = PACKAGE_CL.addExternalSymbol("DECLARE"); public static final Symbol DECODE_FLOAT = PACKAGE_CL.addExternalSymbol("DECODE-FLOAT"); public static final Symbol DECODE_UNIVERSAL_TIME = PACKAGE_CL.addExternalSymbol("DECODE-UNIVERSAL-TIME"); public static final Symbol DEFCLASS = PACKAGE_CL.addExternalSymbol("DEFCLASS"); public static final Symbol DEFCONSTANT = PACKAGE_CL.addExternalSymbol("DEFCONSTANT"); public static final Symbol DEFGENERIC = PACKAGE_CL.addExternalSymbol("DEFGENERIC"); public static final Symbol DEFINE_COMPILER_MACRO = PACKAGE_CL.addExternalSymbol("DEFINE-COMPILER-MACRO"); public static final Symbol DEFINE_CONDITION = PACKAGE_CL.addExternalSymbol("DEFINE-CONDITION"); public static final Symbol DEFINE_METHOD_COMBINATION = PACKAGE_CL.addExternalSymbol("DEFINE-METHOD-COMBINATION"); public static final Symbol DEFINE_MODIFY_MACRO = PACKAGE_CL.addExternalSymbol("DEFINE-MODIFY-MACRO"); public static final Symbol DEFINE_SETF_EXPANDER = PACKAGE_CL.addExternalSymbol("DEFINE-SETF-EXPANDER"); public static final Symbol DEFINE_SYMBOL_MACRO = PACKAGE_CL.addExternalSymbol("DEFINE-SYMBOL-MACRO"); public static final Symbol DEFMACRO = PACKAGE_CL.addExternalSymbol("DEFMACRO"); public static final Symbol DEFMETHOD = PACKAGE_CL.addExternalSymbol("DEFMETHOD"); public static final Symbol DEFPACKAGE = PACKAGE_CL.addExternalSymbol("DEFPACKAGE"); public static final Symbol DEFPARAMETER = PACKAGE_CL.addExternalSymbol("DEFPARAMETER"); public static final Symbol DEFSETF = PACKAGE_CL.addExternalSymbol("DEFSETF"); public static final Symbol DEFSTRUCT = PACKAGE_CL.addExternalSymbol("DEFSTRUCT"); public static final Symbol DEFTYPE = PACKAGE_CL.addExternalSymbol("DEFTYPE"); public static final Symbol DEFUN = PACKAGE_CL.addExternalSymbol("DEFUN"); public static final Symbol DEFVAR = PACKAGE_CL.addExternalSymbol("DEFVAR"); public static final Symbol DELETE = PACKAGE_CL.addExternalSymbol("DELETE"); public static final Symbol DELETE_DUPLICATES = PACKAGE_CL.addExternalSymbol("DELETE-DUPLICATES"); public static final Symbol DELETE_FILE = PACKAGE_CL.addExternalSymbol("DELETE-FILE"); public static final Symbol DELETE_IF = PACKAGE_CL.addExternalSymbol("DELETE-IF"); public static final Symbol DELETE_IF_NOT = PACKAGE_CL.addExternalSymbol("DELETE-IF-NOT"); public static final Symbol DELETE_PACKAGE = PACKAGE_CL.addExternalSymbol("DELETE-PACKAGE"); public static final Symbol DENOMINATOR = PACKAGE_CL.addExternalSymbol("DENOMINATOR"); public static final Symbol DEPOSIT_FIELD = PACKAGE_CL.addExternalSymbol("DEPOSIT-FIELD"); public static final Symbol DESCRIBE = PACKAGE_CL.addExternalSymbol("DESCRIBE"); public static final Symbol DESCRIBE_OBJECT = PACKAGE_CL.addExternalSymbol("DESCRIBE-OBJECT"); public static final Symbol DESTRUCTURING_BIND = PACKAGE_CL.addExternalSymbol("DESTRUCTURING-BIND"); public static final Symbol DIGIT_CHAR = PACKAGE_CL.addExternalSymbol("DIGIT-CHAR"); public static final Symbol DIGIT_CHAR_P = PACKAGE_CL.addExternalSymbol("DIGIT-CHAR-P"); public static final Symbol DIRECTORY = PACKAGE_CL.addExternalSymbol("DIRECTORY"); public static final Symbol DIRECTORY_NAMESTRING = PACKAGE_CL.addExternalSymbol("DIRECTORY-NAMESTRING"); public static final Symbol DISASSEMBLE = PACKAGE_CL.addExternalSymbol("DISASSEMBLE"); public static final Symbol DIVISION_BY_ZERO = PACKAGE_CL.addExternalSymbol("DIVISION-BY-ZERO"); public static final Symbol DO = PACKAGE_CL.addExternalSymbol("DO"); public static final Symbol DO_STAR = PACKAGE_CL.addExternalSymbol("DO*"); public static final Symbol DO_ALL_SYMBOLS = PACKAGE_CL.addExternalSymbol("DO-ALL-SYMBOLS"); public static final Symbol DO_EXTERNAL_SYMBOLS = PACKAGE_CL.addExternalSymbol("DO-EXTERNAL-SYMBOLS"); public static final Symbol DO_SYMBOLS = PACKAGE_CL.addExternalSymbol("DO-SYMBOLS"); public static final Symbol DOCUMENTATION = PACKAGE_CL.addExternalSymbol("DOCUMENTATION"); public static final Symbol DOLIST = PACKAGE_CL.addExternalSymbol("DOLIST"); public static final Symbol DOTIMES = PACKAGE_CL.addExternalSymbol("DOTIMES"); public static final Symbol DOUBLE_FLOAT = PACKAGE_CL.addExternalSymbol("DOUBLE-FLOAT"); public static final Symbol DOUBLE_FLOAT_EPSILON = PACKAGE_CL.addExternalSymbol("DOUBLE-FLOAT-EPSILON"); public static final Symbol DOUBLE_FLOAT_NEGATIVE_EPSILON = PACKAGE_CL.addExternalSymbol("DOUBLE-FLOAT-NEGATIVE-EPSILON"); public static final Symbol DPB = PACKAGE_CL.addExternalSymbol("DPB"); public static final Symbol DRIBBLE = PACKAGE_CL.addExternalSymbol("DRIBBLE"); public static final Symbol DYNAMIC_EXTENT = PACKAGE_CL.addExternalSymbol("DYNAMIC-EXTENT"); public static final Symbol ECASE = PACKAGE_CL.addExternalSymbol("ECASE"); public static final Symbol ECHO_STREAM = PACKAGE_CL.addExternalSymbol("ECHO-STREAM"); public static final Symbol ECHO_STREAM_INPUT_STREAM = PACKAGE_CL.addExternalSymbol("ECHO-STREAM-INPUT-STREAM"); public static final Symbol ECHO_STREAM_OUTPUT_STREAM = PACKAGE_CL.addExternalSymbol("ECHO-STREAM-OUTPUT-STREAM"); public static final Symbol ED = PACKAGE_CL.addExternalSymbol("ED"); public static final Symbol EIGHTH = PACKAGE_CL.addExternalSymbol("EIGHTH"); public static final Symbol ELT = PACKAGE_CL.addExternalSymbol("ELT"); public static final Symbol ENCODE_UNIVERSAL_TIME = PACKAGE_CL.addExternalSymbol("ENCODE-UNIVERSAL-TIME"); public static final Symbol END_OF_FILE = PACKAGE_CL.addExternalSymbol("END-OF-FILE"); public static final Symbol ENDP = PACKAGE_CL.addExternalSymbol("ENDP"); public static final Symbol ENOUGH_NAMESTRING = PACKAGE_CL.addExternalSymbol("ENOUGH-NAMESTRING"); public static final Symbol ENSURE_DIRECTORIES_EXIST = PACKAGE_CL.addExternalSymbol("ENSURE-DIRECTORIES-EXIST"); public static final Symbol ENSURE_GENERIC_FUNCTION = PACKAGE_CL.addExternalSymbol("ENSURE-GENERIC-FUNCTION"); public static final Symbol EQ = PACKAGE_CL.addExternalSymbol("EQ"); public static final Symbol EQL = PACKAGE_CL.addExternalSymbol("EQL"); public static final Symbol EQUAL = PACKAGE_CL.addExternalSymbol("EQUAL"); public static final Symbol EQUALP = PACKAGE_CL.addExternalSymbol("EQUALP"); public static final Symbol ERROR = PACKAGE_CL.addExternalSymbol("ERROR"); public static final Symbol ETYPECASE = PACKAGE_CL.addExternalSymbol("ETYPECASE"); public static final Symbol EVAL = PACKAGE_CL.addExternalSymbol("EVAL"); public static final Symbol EVAL_WHEN = PACKAGE_CL.addExternalSymbol("EVAL-WHEN"); public static final Symbol EVENP = PACKAGE_CL.addExternalSymbol("EVENP"); public static final Symbol EVERY = PACKAGE_CL.addExternalSymbol("EVERY"); public static final Symbol EXP = PACKAGE_CL.addExternalSymbol("EXP"); public static final Symbol EXPORT = PACKAGE_CL.addExternalSymbol("EXPORT"); public static final Symbol EXPT = PACKAGE_CL.addExternalSymbol("EXPT"); public static final Symbol EXTENDED_CHAR = PACKAGE_CL.addExternalSymbol("EXTENDED-CHAR"); public static final Symbol FBOUNDP = PACKAGE_CL.addExternalSymbol("FBOUNDP"); public static final Symbol FCEILING = PACKAGE_CL.addExternalSymbol("FCEILING"); public static final Symbol FDEFINITION = PACKAGE_CL.addExternalSymbol("FDEFINITION"); public static final Symbol FFLOOR = PACKAGE_CL.addExternalSymbol("FFLOOR"); public static final Symbol FIFTH = PACKAGE_CL.addExternalSymbol("FIFTH"); public static final Symbol FILE_AUTHOR = PACKAGE_CL.addExternalSymbol("FILE-AUTHOR"); public static final Symbol FILE_ERROR = PACKAGE_CL.addExternalSymbol("FILE-ERROR"); public static final Symbol FILE_ERROR_PATHNAME = PACKAGE_CL.addExternalSymbol("FILE-ERROR-PATHNAME"); public static final Symbol FILE_LENGTH = PACKAGE_CL.addExternalSymbol("FILE-LENGTH"); public static final Symbol FILE_NAMESTRING = PACKAGE_CL.addExternalSymbol("FILE-NAMESTRING"); public static final Symbol FILE_POSITION = PACKAGE_CL.addExternalSymbol("FILE-POSITION"); public static final Symbol FILE_STREAM = PACKAGE_CL.addExternalSymbol("FILE-STREAM"); public static final Symbol FILE_STRING_LENGTH = PACKAGE_CL.addExternalSymbol("FILE-STRING-LENGTH"); public static final Symbol FILE_WRITE_DATE = PACKAGE_CL.addExternalSymbol("FILE-WRITE-DATE"); public static final Symbol FILL = PACKAGE_CL.addExternalSymbol("FILL"); public static final Symbol FILL_POINTER = PACKAGE_CL.addExternalSymbol("FILL-POINTER"); public static final Symbol FIND = PACKAGE_CL.addExternalSymbol("FIND"); public static final Symbol FIND_ALL_SYMBOLS = PACKAGE_CL.addExternalSymbol("FIND-ALL-SYMBOLS"); public static final Symbol FIND_CLASS = PACKAGE_CL.addExternalSymbol("FIND-CLASS"); public static final Symbol FIND_IF = PACKAGE_CL.addExternalSymbol("FIND-IF"); public static final Symbol FIND_IF_NOT = PACKAGE_CL.addExternalSymbol("FIND-IF-NOT"); public static final Symbol FIND_METHOD = PACKAGE_CL.addExternalSymbol("FIND-METHOD"); public static final Symbol FIND_PACKAGE = PACKAGE_CL.addExternalSymbol("FIND-PACKAGE"); public static final Symbol FIND_RESTART = PACKAGE_CL.addExternalSymbol("FIND-RESTART"); public static final Symbol FIND_SYMBOL = PACKAGE_CL.addExternalSymbol("FIND-SYMBOL"); public static final Symbol FINISH_OUTPUT = PACKAGE_CL.addExternalSymbol("FINISH-OUTPUT"); public static final Symbol FIRST = PACKAGE_CL.addExternalSymbol("FIRST"); public static final Symbol FIXNUM = PACKAGE_CL.addExternalSymbol("FIXNUM"); public static final Symbol FLET = PACKAGE_CL.addExternalSymbol("FLET"); public static final Symbol FLOAT = PACKAGE_CL.addExternalSymbol("FLOAT"); public static final Symbol FLOAT_DIGITS = PACKAGE_CL.addExternalSymbol("FLOAT-DIGITS"); public static final Symbol FLOAT_PRECISION = PACKAGE_CL.addExternalSymbol("FLOAT-PRECISION"); public static final Symbol FLOAT_RADIX = PACKAGE_CL.addExternalSymbol("FLOAT-RADIX"); public static final Symbol FLOAT_SIGN = PACKAGE_CL.addExternalSymbol("FLOAT-SIGN"); public static final Symbol FLOATING_POINT_INEXACT = PACKAGE_CL.addExternalSymbol("FLOATING-POINT-INEXACT"); public static final Symbol FLOATING_POINT_INVALID_OPERATION = PACKAGE_CL.addExternalSymbol("FLOATING-POINT-INVALID-OPERATION"); public static final Symbol FLOATING_POINT_OVERFLOW = PACKAGE_CL.addExternalSymbol("FLOATING-POINT-OVERFLOW"); public static final Symbol FLOATING_POINT_UNDERFLOW = PACKAGE_CL.addExternalSymbol("FLOATING-POINT-UNDERFLOW"); public static final Symbol FLOATP = PACKAGE_CL.addExternalSymbol("FLOATP"); public static final Symbol FLOOR = PACKAGE_CL.addExternalSymbol("FLOOR"); public static final Symbol FMAKUNBOUND = PACKAGE_CL.addExternalSymbol("FMAKUNBOUND"); public static final Symbol FORCE_OUTPUT = PACKAGE_CL.addExternalSymbol("FORCE-OUTPUT"); public static final Symbol FORMAT = PACKAGE_CL.addExternalSymbol("FORMAT"); public static final Symbol FORMATTER = PACKAGE_CL.addExternalSymbol("FORMATTER"); public static final Symbol FOURTH = PACKAGE_CL.addExternalSymbol("FOURTH"); public static final Symbol FRESH_LINE = PACKAGE_CL.addExternalSymbol("FRESH-LINE"); public static final Symbol FROUND = PACKAGE_CL.addExternalSymbol("FROUND"); public static final Symbol FTRUNCATE = PACKAGE_CL.addExternalSymbol("FTRUNCATE"); public static final Symbol FTYPE = PACKAGE_CL.addExternalSymbol("FTYPE"); public static final Symbol FUNCALL = PACKAGE_CL.addExternalSymbol("FUNCALL"); public static final Symbol FUNCTION = PACKAGE_CL.addExternalSymbol("FUNCTION"); public static final Symbol FUNCTION_KEYWORDS = PACKAGE_CL.addExternalSymbol("FUNCTION-KEYWORDS"); public static final Symbol FUNCTION_LAMBDA_EXPRESSION = PACKAGE_CL.addExternalSymbol("FUNCTION-LAMBDA-EXPRESSION"); public static final Symbol FUNCTIONP = PACKAGE_CL.addExternalSymbol("FUNCTIONP"); public static final Symbol GCD = PACKAGE_CL.addExternalSymbol("GCD"); public static final Symbol GENERIC_FUNCTION = PACKAGE_CL.addExternalSymbol("GENERIC-FUNCTION"); public static final Symbol GENSYM = PACKAGE_CL.addExternalSymbol("GENSYM"); public static final Symbol GENTEMP = PACKAGE_CL.addExternalSymbol("GENTEMP"); public static final Symbol GET = PACKAGE_CL.addExternalSymbol("GET"); public static final Symbol GET_DECODED_TIME = PACKAGE_CL.addExternalSymbol("GET-DECODED-TIME"); public static final Symbol GET_DISPATCH_MACRO_CHARACTER = PACKAGE_CL.addExternalSymbol("GET-DISPATCH-MACRO-CHARACTER"); public static final Symbol GET_INTERNAL_REAL_TIME = PACKAGE_CL.addExternalSymbol("GET-INTERNAL-REAL-TIME"); public static final Symbol GET_INTERNAL_RUN_TIME = PACKAGE_CL.addExternalSymbol("GET-INTERNAL-RUN-TIME"); public static final Symbol GET_MACRO_CHARACTER = PACKAGE_CL.addExternalSymbol("GET-MACRO-CHARACTER"); public static final Symbol GET_OUTPUT_STREAM_STRING = PACKAGE_CL.addExternalSymbol("GET-OUTPUT-STREAM-STRING"); public static final Symbol GET_PROPERTIES = PACKAGE_CL.addExternalSymbol("GET-PROPERTIES"); public static final Symbol GET_SETF_EXPANSION = PACKAGE_CL.addExternalSymbol("GET-SETF-EXPANSION"); public static final Symbol GET_UNIVERSAL_TIME = PACKAGE_CL.addExternalSymbol("GET-UNIVERSAL-TIME"); public static final Symbol GETF = PACKAGE_CL.addExternalSymbol("GETF"); public static final Symbol GETHASH = PACKAGE_CL.addExternalSymbol("GETHASH"); public static final Symbol GO = PACKAGE_CL.addExternalSymbol("GO"); public static final Symbol GRAPHIC_CHAR_P = PACKAGE_CL.addExternalSymbol("GRAPHIC-CHAR-P"); public static final Symbol HANDLER_BIND = PACKAGE_CL.addExternalSymbol("HANDLER-BIND"); public static final Symbol HANDLER_CASE = PACKAGE_CL.addExternalSymbol("HANDLER-CASE"); public static final Symbol HASH_TABLE = PACKAGE_CL.addExternalSymbol("HASH-TABLE"); public static final Symbol HASH_TABLE_COUNT = PACKAGE_CL.addExternalSymbol("HASH-TABLE-COUNT"); public static final Symbol HASH_TABLE_P = PACKAGE_CL.addExternalSymbol("HASH-TABLE-P"); public static final Symbol HASH_TABLE_REHASH_SIZE = PACKAGE_CL.addExternalSymbol("HASH-TABLE-REHASH-SIZE"); public static final Symbol HASH_TABLE_REHASH_THRESHOLD = PACKAGE_CL.addExternalSymbol("HASH-TABLE-REHASH-THRESHOLD"); public static final Symbol HASH_TABLE_SIZE = PACKAGE_CL.addExternalSymbol("HASH-TABLE-SIZE"); public static final Symbol HASH_TABLE_TEST = PACKAGE_CL.addExternalSymbol("HASH-TABLE-TEST"); public static final Symbol HOST_NAMESTRING = PACKAGE_CL.addExternalSymbol("HOST-NAMESTRING"); public static final Symbol IDENTITY = PACKAGE_CL.addExternalSymbol("IDENTITY"); public static final Symbol IF = PACKAGE_CL.addExternalSymbol("IF"); public static final Symbol IGNORABLE = PACKAGE_CL.addExternalSymbol("IGNORABLE"); public static final Symbol IGNORE = PACKAGE_CL.addExternalSymbol("IGNORE"); public static final Symbol IGNORE_ERRORS = PACKAGE_CL.addExternalSymbol("IGNORE-ERRORS"); public static final Symbol IMAGPART = PACKAGE_CL.addExternalSymbol("IMAGPART"); public static final Symbol IMPORT = PACKAGE_CL.addExternalSymbol("IMPORT"); public static final Symbol IN_PACKAGE = PACKAGE_CL.addExternalSymbol("IN-PACKAGE"); public static final Symbol INCF = PACKAGE_CL.addExternalSymbol("INCF"); public static final Symbol INITIALIZE_INSTANCE = PACKAGE_CL.addExternalSymbol("INITIALIZE-INSTANCE"); public static final Symbol INLINE = PACKAGE_CL.addExternalSymbol("INLINE"); public static final Symbol INPUT_STREAM_P = PACKAGE_CL.addExternalSymbol("INPUT-STREAM-P"); public static final Symbol INSPECT = PACKAGE_CL.addExternalSymbol("INSPECT"); public static final Symbol INTEGER = PACKAGE_CL.addExternalSymbol("INTEGER"); public static final Symbol INTEGER_DECODE_FLOAT = PACKAGE_CL.addExternalSymbol("INTEGER-DECODE-FLOAT"); public static final Symbol INTEGER_LENGTH = PACKAGE_CL.addExternalSymbol("INTEGER-LENGTH"); public static final Symbol INTEGERP = PACKAGE_CL.addExternalSymbol("INTEGERP"); public static final Symbol INTERACTIVE_STREAM_P = PACKAGE_CL.addExternalSymbol("INTERACTIVE-STREAM-P"); public static final Symbol INTERN = PACKAGE_CL.addExternalSymbol("INTERN"); public static final Symbol INTERNAL_TIME_UNITS_PER_SECOND = PACKAGE_CL.addExternalSymbol("INTERNAL-TIME-UNITS-PER-SECOND"); public static final Symbol INTERSECTION = PACKAGE_CL.addExternalSymbol("INTERSECTION"); public static final Symbol INVALID_METHOD_ERROR = PACKAGE_CL.addExternalSymbol("INVALID-METHOD-ERROR"); public static final Symbol INVOKE_DEBUGGER = PACKAGE_CL.addExternalSymbol("INVOKE-DEBUGGER"); public static final Symbol INVOKE_RESTART = PACKAGE_CL.addExternalSymbol("INVOKE-RESTART"); public static final Symbol INVOKE_RESTART_INTERACTIVELY = PACKAGE_CL.addExternalSymbol("INVOKE-RESTART-INTERACTIVELY"); public static final Symbol ISQRT = PACKAGE_CL.addExternalSymbol("ISQRT"); public static final Symbol KEYWORD = PACKAGE_CL.addExternalSymbol("KEYWORD"); public static final Symbol KEYWORDP = PACKAGE_CL.addExternalSymbol("KEYWORDP"); public static final Symbol LABELS = PACKAGE_CL.addExternalSymbol("LABELS"); public static final Symbol LAMBDA = PACKAGE_CL.addExternalSymbol("LAMBDA"); public static final Symbol LAMBDA_LIST_KEYWORDS = PACKAGE_CL.addExternalSymbol("LAMBDA-LIST-KEYWORDS"); public static final Symbol LAMBDA_PARAMETERS_LIMIT = PACKAGE_CL.addExternalSymbol("LAMBDA-PARAMETERS-LIMIT"); public static final Symbol LAST = PACKAGE_CL.addExternalSymbol("LAST"); public static final Symbol LCM = PACKAGE_CL.addExternalSymbol("LCM"); public static final Symbol LDB = PACKAGE_CL.addExternalSymbol("LDB"); public static final Symbol LDB_TEST = PACKAGE_CL.addExternalSymbol("LDB-TEST"); public static final Symbol LDIFF = PACKAGE_CL.addExternalSymbol("LDIFF"); public static final Symbol LEAST_NEGATIVE_DOUBLE_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-NEGATIVE-DOUBLE-FLOAT"); public static final Symbol LEAST_NEGATIVE_LONG_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-NEGATIVE-LONG-FLOAT"); public static final Symbol LEAST_NEGATIVE_NORMALIZED_DOUBLE_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-NEGATIVE-NORMALIZED-DOUBLE-FLOAT"); public static final Symbol LEAST_NEGATIVE_NORMALIZED_LONG_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-NEGATIVE-NORMALIZED-LONG-FLOAT"); public static final Symbol LEAST_NEGATIVE_NORMALIZED_SHORT_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-NEGATIVE-NORMALIZED-SHORT-FLOAT"); public static final Symbol LEAST_NEGATIVE_NORMALIZED_SINGLE_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-NEGATIVE-NORMALIZED-SINGLE-FLOAT"); public static final Symbol LEAST_NEGATIVE_SHORT_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-NEGATIVE-SHORT-FLOAT"); public static final Symbol LEAST_NEGATIVE_SINGLE_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-NEGATIVE-SINGLE-FLOAT"); public static final Symbol LEAST_POSITIVE_DOUBLE_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-POSITIVE-DOUBLE-FLOAT"); public static final Symbol LEAST_POSITIVE_LONG_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-POSITIVE-LONG-FLOAT"); public static final Symbol LEAST_POSITIVE_NORMALIZED_DOUBLE_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-POSITIVE-NORMALIZED-DOUBLE-FLOAT"); public static final Symbol LEAST_POSITIVE_NORMALIZED_LONG_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-POSITIVE-NORMALIZED-LONG-FLOAT"); public static final Symbol LEAST_POSITIVE_NORMALIZED_SHORT_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-POSITIVE-NORMALIZED-SHORT-FLOAT"); public static final Symbol LEAST_POSITIVE_NORMALIZED_SINGLE_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-POSITIVE-NORMALIZED-SINGLE-FLOAT"); public static final Symbol LEAST_POSITIVE_SHORT_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-POSITIVE-SHORT-FLOAT"); public static final Symbol LEAST_POSITIVE_SINGLE_FLOAT = PACKAGE_CL.addExternalSymbol("LEAST-POSITIVE-SINGLE-FLOAT"); public static final Symbol LENGTH = PACKAGE_CL.addExternalSymbol("LENGTH"); public static final Symbol LET = PACKAGE_CL.addExternalSymbol("LET"); public static final Symbol LET_STAR = PACKAGE_CL.addExternalSymbol("LET*"); public static final Symbol LISP_IMPLEMENTATION_TYPE = PACKAGE_CL.addExternalSymbol("LISP-IMPLEMENTATION-TYPE"); public static final Symbol LISP_IMPLEMENTATION_VERSION = PACKAGE_CL.addExternalSymbol("LISP-IMPLEMENTATION-VERSION"); public static final Symbol LIST = PACKAGE_CL.addExternalSymbol("LIST"); public static final Symbol LIST_STAR = PACKAGE_CL.addExternalSymbol("LIST*"); public static final Symbol LIST_ALL_PACKAGES = PACKAGE_CL.addExternalSymbol("LIST-ALL-PACKAGES"); public static final Symbol LIST_LENGTH = PACKAGE_CL.addExternalSymbol("LIST-LENGTH"); public static final Symbol LISTEN = PACKAGE_CL.addExternalSymbol("LISTEN"); public static final Symbol LISTP = PACKAGE_CL.addExternalSymbol("LISTP"); public static final Symbol LOAD = PACKAGE_CL.addExternalSymbol("LOAD"); public static final Symbol LOAD_LOGICAL_PATHNAME_TRANSLATIONS = PACKAGE_CL.addExternalSymbol("LOAD-LOGICAL-PATHNAME-TRANSLATIONS"); public static final Symbol LOAD_TIME_VALUE = PACKAGE_CL.addExternalSymbol("LOAD-TIME-VALUE"); public static final Symbol LOCALLY = PACKAGE_CL.addExternalSymbol("LOCALLY"); public static final Symbol LOG = PACKAGE_CL.addExternalSymbol("LOG"); public static final Symbol LOGAND = PACKAGE_CL.addExternalSymbol("LOGAND"); public static final Symbol LOGANDC1 = PACKAGE_CL.addExternalSymbol("LOGANDC1"); public static final Symbol LOGANDC2 = PACKAGE_CL.addExternalSymbol("LOGANDC2"); public static final Symbol LOGBITP = PACKAGE_CL.addExternalSymbol("LOGBITP"); public static final Symbol LOGCOUNT = PACKAGE_CL.addExternalSymbol("LOGCOUNT"); public static final Symbol LOGEQV = PACKAGE_CL.addExternalSymbol("LOGEQV"); public static final Symbol LOGICAL_PATHNAME = PACKAGE_CL.addExternalSymbol("LOGICAL-PATHNAME"); public static final Symbol LOGICAL_PATHNAME_TRANSLATIONS = PACKAGE_CL.addExternalSymbol("LOGICAL-PATHNAME-TRANSLATIONS"); public static final Symbol LOGIOR = PACKAGE_CL.addExternalSymbol("LOGIOR"); public static final Symbol LOGNAND = PACKAGE_CL.addExternalSymbol("LOGNAND"); public static final Symbol LOGNOR = PACKAGE_CL.addExternalSymbol("LOGNOR"); public static final Symbol LOGNOT = PACKAGE_CL.addExternalSymbol("LOGNOT"); public static final Symbol LOGORC1 = PACKAGE_CL.addExternalSymbol("LOGORC1"); public static final Symbol LOGORC2 = PACKAGE_CL.addExternalSymbol("LOGORC2"); public static final Symbol LOGTEST = PACKAGE_CL.addExternalSymbol("LOGTEST"); public static final Symbol LOGXOR = PACKAGE_CL.addExternalSymbol("LOGXOR"); public static final Symbol LONG_FLOAT = PACKAGE_CL.addExternalSymbol("LONG-FLOAT"); public static final Symbol LONG_FLOAT_EPSILON = PACKAGE_CL.addExternalSymbol("LONG-FLOAT-EPSILON"); public static final Symbol LONG_FLOAT_NEGATIVE_EPSILON = PACKAGE_CL.addExternalSymbol("LONG-FLOAT-NEGATIVE-EPSILON"); public static final Symbol LONG_SITE_NAME = PACKAGE_CL.addExternalSymbol("LONG-SITE-NAME"); public static final Symbol LOOP = PACKAGE_CL.addExternalSymbol("LOOP"); public static final Symbol LOOP_FINISH = PACKAGE_CL.addExternalSymbol("LOOP-FINISH"); public static final Symbol LOWER_CASE_P = PACKAGE_CL.addExternalSymbol("LOWER-CASE-P"); public static final Symbol MACHINE_INSTANCE = PACKAGE_CL.addExternalSymbol("MACHINE-INSTANCE"); public static final Symbol MACHINE_TYPE = PACKAGE_CL.addExternalSymbol("MACHINE-TYPE"); public static final Symbol MACHINE_VERSION = PACKAGE_CL.addExternalSymbol("MACHINE-VERSION"); public static final Symbol MACRO_FUNCTION = PACKAGE_CL.addExternalSymbol("MACRO-FUNCTION"); public static final Symbol MACROEXPAND = PACKAGE_CL.addExternalSymbol("MACROEXPAND"); public static final Symbol MACROEXPAND_1 = PACKAGE_CL.addExternalSymbol("MACROEXPAND-1"); public static final Symbol MACROLET = PACKAGE_CL.addExternalSymbol("MACROLET"); public static final Symbol MAKE_ARRAY = PACKAGE_CL.addExternalSymbol("MAKE-ARRAY"); public static final Symbol MAKE_BROADCAST_STREAM = PACKAGE_CL.addExternalSymbol("MAKE-BROADCAST-STREAM"); public static final Symbol MAKE_CONCATENATED_STREAM = PACKAGE_CL.addExternalSymbol("MAKE-CONCATENATED-STREAM"); public static final Symbol MAKE_CONDITION = PACKAGE_CL.addExternalSymbol("MAKE-CONDITION"); public static final Symbol MAKE_DISPATCH_MACRO_CHARACTER = PACKAGE_CL.addExternalSymbol("MAKE-DISPATCH-MACRO-CHARACTER"); public static final Symbol MAKE_ECHO_STREAM = PACKAGE_CL.addExternalSymbol("MAKE-ECHO-STREAM"); public static final Symbol MAKE_HASH_TABLE = PACKAGE_CL.addExternalSymbol("MAKE-HASH-TABLE"); public static final Symbol MAKE_INSTANCE = PACKAGE_CL.addExternalSymbol("MAKE-INSTANCE"); public static final Symbol MAKE_INSTANCES_OBSOLETE = PACKAGE_CL.addExternalSymbol("MAKE-INSTANCES-OBSOLETE"); public static final Symbol MAKE_LIST = PACKAGE_CL.addExternalSymbol("MAKE-LIST"); public static final Symbol MAKE_LOAD_FORM = PACKAGE_CL.addExternalSymbol("MAKE-LOAD-FORM"); public static final Symbol MAKE_LOAD_FORM_SAVING_SLOTS = PACKAGE_CL.addExternalSymbol("MAKE-LOAD-FORM-SAVING-SLOTS"); public static final Symbol MAKE_METHOD = PACKAGE_CL.addExternalSymbol("MAKE-METHOD"); public static final Symbol MAKE_PACKAGE = PACKAGE_CL.addExternalSymbol("MAKE-PACKAGE"); public static final Symbol MAKE_PATHNAME = PACKAGE_CL.addExternalSymbol("MAKE-PATHNAME"); public static final Symbol MAKE_RANDOM_STATE = PACKAGE_CL.addExternalSymbol("MAKE-RANDOM-STATE"); public static final Symbol MAKE_SEQUENCE = PACKAGE_CL.addExternalSymbol("MAKE-SEQUENCE"); public static final Symbol MAKE_STRING = PACKAGE_CL.addExternalSymbol("MAKE-STRING"); public static final Symbol MAKE_STRING_INPUT_STREAM = PACKAGE_CL.addExternalSymbol("MAKE-STRING-INPUT-STREAM"); public static final Symbol MAKE_STRING_OUTPUT_STREAM = PACKAGE_CL.addExternalSymbol("MAKE-STRING-OUTPUT-STREAM"); public static final Symbol MAKE_SYMBOL = PACKAGE_CL.addExternalSymbol("MAKE-SYMBOL"); public static final Symbol MAKE_SYNONYM_STREAM = PACKAGE_CL.addExternalSymbol("MAKE-SYNONYM-STREAM"); public static final Symbol MAKE_TWO_WAY_STREAM = PACKAGE_CL.addExternalSymbol("MAKE-TWO-WAY-STREAM"); public static final Symbol MAKUNBOUND = PACKAGE_CL.addExternalSymbol("MAKUNBOUND"); public static final Symbol MAP = PACKAGE_CL.addExternalSymbol("MAP"); public static final Symbol MAP_INTO = PACKAGE_CL.addExternalSymbol("MAP-INTO"); public static final Symbol MAPC = PACKAGE_CL.addExternalSymbol("MAPC"); public static final Symbol MAPCAN = PACKAGE_CL.addExternalSymbol("MAPCAN"); public static final Symbol MAPCAR = PACKAGE_CL.addExternalSymbol("MAPCAR"); public static final Symbol MAPCON = PACKAGE_CL.addExternalSymbol("MAPCON"); public static final Symbol MAPHASH = PACKAGE_CL.addExternalSymbol("MAPHASH"); public static final Symbol MAPL = PACKAGE_CL.addExternalSymbol("MAPL"); public static final Symbol MAPLIST = PACKAGE_CL.addExternalSymbol("MAPLIST"); public static final Symbol MASK_FIELD = PACKAGE_CL.addExternalSymbol("MASK-FIELD"); public static final Symbol MAX = PACKAGE_CL.addExternalSymbol("MAX"); public static final Symbol MEMBER = PACKAGE_CL.addExternalSymbol("MEMBER"); public static final Symbol MEMBER_IF = PACKAGE_CL.addExternalSymbol("MEMBER-IF"); public static final Symbol MEMBER_IF_NOT = PACKAGE_CL.addExternalSymbol("MEMBER-IF-NOT"); public static final Symbol MERGE = PACKAGE_CL.addExternalSymbol("MERGE"); public static final Symbol MERGE_PATHNAMES = PACKAGE_CL.addExternalSymbol("MERGE-PATHNAMES"); public static final Symbol METHOD = PACKAGE_CL.addExternalSymbol("METHOD"); public static final Symbol METHOD_COMBINATION = PACKAGE_CL.addExternalSymbol("METHOD-COMBINATION"); public static final Symbol METHOD_COMBINATION_ERROR = PACKAGE_CL.addExternalSymbol("METHOD-COMBINATION-ERROR"); public static final Symbol METHOD_QUALIFIERS = PACKAGE_CL.addExternalSymbol("METHOD-QUALIFIERS"); public static final Symbol MIN = PACKAGE_CL.addExternalSymbol("MIN"); public static final Symbol MINUSP = PACKAGE_CL.addExternalSymbol("MINUSP"); public static final Symbol MISMATCH = PACKAGE_CL.addExternalSymbol("MISMATCH"); public static final Symbol MOD = PACKAGE_CL.addExternalSymbol("MOD"); public static final Symbol MOST_NEGATIVE_DOUBLE_FLOAT = PACKAGE_CL.addExternalSymbol("MOST-NEGATIVE-DOUBLE-FLOAT"); public static final Symbol MOST_NEGATIVE_FIXNUM = PACKAGE_CL.addExternalSymbol("MOST-NEGATIVE-FIXNUM"); public static final Symbol MOST_NEGATIVE_LONG_FLOAT = PACKAGE_CL.addExternalSymbol("MOST-NEGATIVE-LONG-FLOAT"); public static final Symbol MOST_NEGATIVE_SHORT_FLOAT = PACKAGE_CL.addExternalSymbol("MOST-NEGATIVE-SHORT-FLOAT"); public static final Symbol MOST_NEGATIVE_SINGLE_FLOAT = PACKAGE_CL.addExternalSymbol("MOST-NEGATIVE-SINGLE-FLOAT"); public static final Symbol MOST_POSITIVE_DOUBLE_FLOAT = PACKAGE_CL.addExternalSymbol("MOST-POSITIVE-DOUBLE-FLOAT"); public static final Symbol MOST_POSITIVE_FIXNUM = PACKAGE_CL.addExternalSymbol("MOST-POSITIVE-FIXNUM"); public static final Symbol MOST_POSITIVE_LONG_FLOAT = PACKAGE_CL.addExternalSymbol("MOST-POSITIVE-LONG-FLOAT"); public static final Symbol MOST_POSITIVE_SHORT_FLOAT = PACKAGE_CL.addExternalSymbol("MOST-POSITIVE-SHORT-FLOAT"); public static final Symbol MOST_POSITIVE_SINGLE_FLOAT = PACKAGE_CL.addExternalSymbol("MOST-POSITIVE-SINGLE-FLOAT"); public static final Symbol MUFFLE_WARNING = PACKAGE_CL.addExternalSymbol("MUFFLE-WARNING"); public static final Symbol MULTIPLE_VALUE_BIND = PACKAGE_CL.addExternalSymbol("MULTIPLE-VALUE-BIND"); public static final Symbol MULTIPLE_VALUE_CALL = PACKAGE_CL.addExternalSymbol("MULTIPLE-VALUE-CALL"); public static final Symbol MULTIPLE_VALUE_LIST = PACKAGE_CL.addExternalSymbol("MULTIPLE-VALUE-LIST"); public static final Symbol MULTIPLE_VALUE_PROG1 = PACKAGE_CL.addExternalSymbol("MULTIPLE-VALUE-PROG1"); public static final Symbol MULTIPLE_VALUE_SETQ = PACKAGE_CL.addExternalSymbol("MULTIPLE-VALUE-SETQ"); public static final Symbol MULTIPLE_VALUES_LIMIT = PACKAGE_CL.addExternalSymbol("MULTIPLE-VALUES-LIMIT"); public static final Symbol NAME_CHAR = PACKAGE_CL.addExternalSymbol("NAME-CHAR"); public static final Symbol NAMESTRING = PACKAGE_CL.addExternalSymbol("NAMESTRING"); public static final Symbol NBUTLAST = PACKAGE_CL.addExternalSymbol("NBUTLAST"); public static final Symbol NCONC = PACKAGE_CL.addExternalSymbol("NCONC"); public static final Symbol NEXT_METHOD_P = PACKAGE_CL.addExternalSymbol("NEXT-METHOD-P"); // NIL is a special case. // public static final Symbol NIL = // PACKAGE_CL.addExternalSymbol("NIL"); public static final Symbol NINTERSECTION = PACKAGE_CL.addExternalSymbol("NINTERSECTION"); public static final Symbol NINTH = PACKAGE_CL.addExternalSymbol("NINTH"); public static final Symbol NO_APPLICABLE_METHOD = PACKAGE_CL.addExternalSymbol("NO-APPLICABLE-METHOD"); public static final Symbol NO_NEXT_METHOD = PACKAGE_CL.addExternalSymbol("NO-NEXT-METHOD"); public static final Symbol NOT = PACKAGE_CL.addExternalSymbol("NOT"); public static final Symbol NOTANY = PACKAGE_CL.addExternalSymbol("NOTANY"); public static final Symbol NOTEVERY = PACKAGE_CL.addExternalSymbol("NOTEVERY"); public static final Symbol NOTINLINE = PACKAGE_CL.addExternalSymbol("NOTINLINE"); public static final Symbol NRECONC = PACKAGE_CL.addExternalSymbol("NRECONC"); public static final Symbol NREVERSE = PACKAGE_CL.addExternalSymbol("NREVERSE"); public static final Symbol NSET_DIFFERENCE = PACKAGE_CL.addExternalSymbol("NSET-DIFFERENCE"); public static final Symbol NSET_EXCLUSIVE_OR = PACKAGE_CL.addExternalSymbol("NSET-EXCLUSIVE-OR"); public static final Symbol NSTRING_CAPITALIZE = PACKAGE_CL.addExternalSymbol("NSTRING-CAPITALIZE"); public static final Symbol NSTRING_DOWNCASE = PACKAGE_CL.addExternalSymbol("NSTRING-DOWNCASE"); public static final Symbol NSTRING_UPCASE = PACKAGE_CL.addExternalSymbol("NSTRING-UPCASE"); public static final Symbol NSUBLIS = PACKAGE_CL.addExternalSymbol("NSUBLIS"); public static final Symbol NSUBST = PACKAGE_CL.addExternalSymbol("NSUBST"); public static final Symbol NSUBST_IF = PACKAGE_CL.addExternalSymbol("NSUBST-IF"); public static final Symbol NSUBST_IF_NOT = PACKAGE_CL.addExternalSymbol("NSUBST-IF-NOT"); public static final Symbol NSUBSTITUTE = PACKAGE_CL.addExternalSymbol("NSUBSTITUTE"); public static final Symbol NSUBSTITUTE_IF = PACKAGE_CL.addExternalSymbol("NSUBSTITUTE-IF"); public static final Symbol NSUBSTITUTE_IF_NOT = PACKAGE_CL.addExternalSymbol("NSUBSTITUTE-IF-NOT"); public static final Symbol NTH = PACKAGE_CL.addExternalSymbol("NTH"); public static final Symbol NTH_VALUE = PACKAGE_CL.addExternalSymbol("NTH-VALUE"); public static final Symbol NTHCDR = PACKAGE_CL.addExternalSymbol("NTHCDR"); public static final Symbol NULL = PACKAGE_CL.addExternalSymbol("NULL"); public static final Symbol NUMBER = PACKAGE_CL.addExternalSymbol("NUMBER"); public static final Symbol NUMBERP = PACKAGE_CL.addExternalSymbol("NUMBERP"); public static final Symbol NUMERATOR = PACKAGE_CL.addExternalSymbol("NUMERATOR"); public static final Symbol NUNION = PACKAGE_CL.addExternalSymbol("NUNION"); public static final Symbol ODDP = PACKAGE_CL.addExternalSymbol("ODDP"); public static final Symbol OPEN = PACKAGE_CL.addExternalSymbol("OPEN"); public static final Symbol OPEN_STREAM_P = PACKAGE_CL.addExternalSymbol("OPEN-STREAM-P"); public static final Symbol OPTIMIZE = PACKAGE_CL.addExternalSymbol("OPTIMIZE"); public static final Symbol OR = PACKAGE_CL.addExternalSymbol("OR"); public static final Symbol OTHERWISE = PACKAGE_CL.addExternalSymbol("OTHERWISE"); public static final Symbol OUTPUT_STREAM_P = PACKAGE_CL.addExternalSymbol("OUTPUT-STREAM-P"); public static final Symbol PACKAGE = PACKAGE_CL.addExternalSymbol("PACKAGE"); public static final Symbol PACKAGE_ERROR = PACKAGE_CL.addExternalSymbol("PACKAGE-ERROR"); public static final Symbol PACKAGE_ERROR_PACKAGE = PACKAGE_CL.addExternalSymbol("PACKAGE-ERROR-PACKAGE"); public static final Symbol PACKAGE_NAME = PACKAGE_CL.addExternalSymbol("PACKAGE-NAME"); public static final Symbol PACKAGE_NICKNAMES = PACKAGE_CL.addExternalSymbol("PACKAGE-NICKNAMES"); public static final Symbol PACKAGE_SHADOWING_SYMBOLS = PACKAGE_CL.addExternalSymbol("PACKAGE-SHADOWING-SYMBOLS"); public static final Symbol PACKAGE_USE_LIST = PACKAGE_CL.addExternalSymbol("PACKAGE-USE-LIST"); public static final Symbol PACKAGE_USED_BY_LIST = PACKAGE_CL.addExternalSymbol("PACKAGE-USED-BY-LIST"); public static final Symbol PACKAGEP = PACKAGE_CL.addExternalSymbol("PACKAGEP"); public static final Symbol PAIRLIS = PACKAGE_CL.addExternalSymbol("PAIRLIS"); public static final Symbol PARSE_ERROR = PACKAGE_CL.addExternalSymbol("PARSE-ERROR"); public static final Symbol PARSE_INTEGER = PACKAGE_CL.addExternalSymbol("PARSE-INTEGER"); public static final Symbol PARSE_NAMESTRING = PACKAGE_CL.addExternalSymbol("PARSE-NAMESTRING"); public static final Symbol PATHNAME = PACKAGE_CL.addExternalSymbol("PATHNAME"); public static final Symbol PATHNAME_DEVICE = PACKAGE_CL.addExternalSymbol("PATHNAME-DEVICE"); public static final Symbol PATHNAME_DIRECTORY = PACKAGE_CL.addExternalSymbol("PATHNAME-DIRECTORY"); public static final Symbol PATHNAME_HOST = PACKAGE_CL.addExternalSymbol("PATHNAME-HOST"); public static final Symbol PATHNAME_MATCH_P = PACKAGE_CL.addExternalSymbol("PATHNAME-MATCH-P"); public static final Symbol PATHNAME_NAME = PACKAGE_CL.addExternalSymbol("PATHNAME-NAME"); public static final Symbol PATHNAME_TYPE = PACKAGE_CL.addExternalSymbol("PATHNAME-TYPE"); public static final Symbol PATHNAME_VERSION = PACKAGE_CL.addExternalSymbol("PATHNAME-VERSION"); public static final Symbol PATHNAMEP = PACKAGE_CL.addExternalSymbol("PATHNAMEP"); public static final Symbol PEEK_CHAR = PACKAGE_CL.addExternalSymbol("PEEK-CHAR"); public static final Symbol PHASE = PACKAGE_CL.addExternalSymbol("PHASE"); public static final Symbol PI = PACKAGE_CL.addExternalSymbol("PI"); public static final Symbol PLUSP = PACKAGE_CL.addExternalSymbol("PLUSP"); public static final Symbol POP = PACKAGE_CL.addExternalSymbol("POP"); public static final Symbol POSITION = PACKAGE_CL.addExternalSymbol("POSITION"); public static final Symbol POSITION_IF = PACKAGE_CL.addExternalSymbol("POSITION-IF"); public static final Symbol POSITION_IF_NOT = PACKAGE_CL.addExternalSymbol("POSITION-IF-NOT"); public static final Symbol PPRINT = PACKAGE_CL.addExternalSymbol("PPRINT"); public static final Symbol PPRINT_DISPATCH = PACKAGE_CL.addExternalSymbol("PPRINT-DISPATCH"); public static final Symbol PPRINT_EXIT_IF_LIST_EXHAUSTED = PACKAGE_CL.addExternalSymbol("PPRINT-EXIT-IF-LIST-EXHAUSTED"); public static final Symbol PPRINT_FILL = PACKAGE_CL.addExternalSymbol("PPRINT-FILL"); public static final Symbol PPRINT_INDENT = PACKAGE_CL.addExternalSymbol("PPRINT-INDENT"); public static final Symbol PPRINT_LINEAR = PACKAGE_CL.addExternalSymbol("PPRINT-LINEAR"); public static final Symbol PPRINT_LOGICAL_BLOCK = PACKAGE_CL.addExternalSymbol("PPRINT-LOGICAL-BLOCK"); public static final Symbol PPRINT_NEWLINE = PACKAGE_CL.addExternalSymbol("PPRINT-NEWLINE"); public static final Symbol PPRINT_POP = PACKAGE_CL.addExternalSymbol("PPRINT-POP"); public static final Symbol PPRINT_TAB = PACKAGE_CL.addExternalSymbol("PPRINT-TAB"); public static final Symbol PPRINT_TABULAR = PACKAGE_CL.addExternalSymbol("PPRINT-TABULAR"); public static final Symbol PRIN1 = PACKAGE_CL.addExternalSymbol("PRIN1"); public static final Symbol PRIN1_TO_STRING = PACKAGE_CL.addExternalSymbol("PRIN1-TO-STRING"); public static final Symbol PRINC = PACKAGE_CL.addExternalSymbol("PRINC"); public static final Symbol PRINC_TO_STRING = PACKAGE_CL.addExternalSymbol("PRINC-TO-STRING"); public static final Symbol PRINT = PACKAGE_CL.addExternalSymbol("PRINT"); public static final Symbol PRINT_NOT_READABLE = PACKAGE_CL.addExternalSymbol("PRINT-NOT-READABLE"); public static final Symbol PRINT_NOT_READABLE_OBJECT = PACKAGE_CL.addExternalSymbol("PRINT-NOT-READABLE-OBJECT"); public static final Symbol PRINT_OBJECT = PACKAGE_CL.addExternalSymbol("PRINT-OBJECT"); public static final Symbol PRINT_UNREADABLE_OBJECT = PACKAGE_CL.addExternalSymbol("PRINT-UNREADABLE-OBJECT"); public static final Symbol PROBE_FILE = PACKAGE_CL.addExternalSymbol("PROBE-FILE"); public static final Symbol PROCLAIM = PACKAGE_CL.addExternalSymbol("PROCLAIM"); public static final Symbol PROG = PACKAGE_CL.addExternalSymbol("PROG"); public static final Symbol PROG_STAR = PACKAGE_CL.addExternalSymbol("PROG*"); public static final Symbol PROG1 = PACKAGE_CL.addExternalSymbol("PROG1"); public static final Symbol PROG2 = PACKAGE_CL.addExternalSymbol("PROG2"); public static final Symbol PROGN = PACKAGE_CL.addExternalSymbol("PROGN"); public static final Symbol PROGRAM_ERROR = PACKAGE_CL.addExternalSymbol("PROGRAM-ERROR"); public static final Symbol PROGV = PACKAGE_CL.addExternalSymbol("PROGV"); public static final Symbol PROVIDE = PACKAGE_CL.addExternalSymbol("PROVIDE"); public static final Symbol PSETF = PACKAGE_CL.addExternalSymbol("PSETF"); public static final Symbol PSETQ = PACKAGE_CL.addExternalSymbol("PSETQ"); public static final Symbol PUSH = PACKAGE_CL.addExternalSymbol("PUSH"); public static final Symbol PUSHNEW = PACKAGE_CL.addExternalSymbol("PUSHNEW"); public static final Symbol QUOTE = PACKAGE_CL.addExternalSymbol("QUOTE"); public static final Symbol RANDOM = PACKAGE_CL.addExternalSymbol("RANDOM"); public static final Symbol RANDOM_STATE = PACKAGE_CL.addExternalSymbol("RANDOM-STATE"); public static final Symbol RANDOM_STATE_P = PACKAGE_CL.addExternalSymbol("RANDOM-STATE-P"); public static final Symbol RASSOC = PACKAGE_CL.addExternalSymbol("RASSOC"); public static final Symbol RASSOC_IF = PACKAGE_CL.addExternalSymbol("RASSOC-IF"); public static final Symbol RASSOC_IF_NOT = PACKAGE_CL.addExternalSymbol("RASSOC-IF-NOT"); public static final Symbol RATIO = PACKAGE_CL.addExternalSymbol("RATIO"); public static final Symbol RATIONAL = PACKAGE_CL.addExternalSymbol("RATIONAL"); public static final Symbol RATIONALIZE = PACKAGE_CL.addExternalSymbol("RATIONALIZE"); public static final Symbol RATIONALP = PACKAGE_CL.addExternalSymbol("RATIONALP"); public static final Symbol READ = PACKAGE_CL.addExternalSymbol("READ"); public static final Symbol READ_BYTE = PACKAGE_CL.addExternalSymbol("READ-BYTE"); public static final Symbol READ_CHAR = PACKAGE_CL.addExternalSymbol("READ-CHAR"); public static final Symbol READ_CHAR_NO_HANG = PACKAGE_CL.addExternalSymbol("READ-CHAR-NO-HANG"); public static final Symbol READ_DELIMITED_LIST = PACKAGE_CL.addExternalSymbol("READ-DELIMITED-LIST"); public static final Symbol READ_FROM_STRING = PACKAGE_CL.addExternalSymbol("READ-FROM-STRING"); public static final Symbol READ_LINE = PACKAGE_CL.addExternalSymbol("READ-LINE"); public static final Symbol READ_PRESERVING_WHITESPACE = PACKAGE_CL.addExternalSymbol("READ-PRESERVING-WHITESPACE"); public static final Symbol READ_SEQUENCE = PACKAGE_CL.addExternalSymbol("READ-SEQUENCE"); public static final Symbol READER_ERROR = PACKAGE_CL.addExternalSymbol("READER-ERROR"); public static final Symbol READTABLE = PACKAGE_CL.addExternalSymbol("READTABLE"); public static final Symbol READTABLE_CASE = PACKAGE_CL.addExternalSymbol("READTABLE-CASE"); public static final Symbol READTABLEP = PACKAGE_CL.addExternalSymbol("READTABLEP"); public static final Symbol REAL = PACKAGE_CL.addExternalSymbol("REAL"); public static final Symbol REALP = PACKAGE_CL.addExternalSymbol("REALP"); public static final Symbol REALPART = PACKAGE_CL.addExternalSymbol("REALPART"); public static final Symbol REDUCE = PACKAGE_CL.addExternalSymbol("REDUCE"); public static final Symbol REINITIALIZE_INSTANCE = PACKAGE_CL.addExternalSymbol("REINITIALIZE-INSTANCE"); public static final Symbol REM = PACKAGE_CL.addExternalSymbol("REM"); public static final Symbol REMF = PACKAGE_CL.addExternalSymbol("REMF"); public static final Symbol REMHASH = PACKAGE_CL.addExternalSymbol("REMHASH"); public static final Symbol REMOVE = PACKAGE_CL.addExternalSymbol("REMOVE"); public static final Symbol REMOVE_DUPLICATES = PACKAGE_CL.addExternalSymbol("REMOVE-DUPLICATES"); public static final Symbol REMOVE_IF = PACKAGE_CL.addExternalSymbol("REMOVE-IF"); public static final Symbol REMOVE_IF_NOT = PACKAGE_CL.addExternalSymbol("REMOVE-IF-NOT"); public static final Symbol REMOVE_METHOD = PACKAGE_CL.addExternalSymbol("REMOVE-METHOD"); public static final Symbol REMPROP = PACKAGE_CL.addExternalSymbol("REMPROP"); public static final Symbol RENAME_FILE = PACKAGE_CL.addExternalSymbol("RENAME-FILE"); public static final Symbol RENAME_PACKAGE = PACKAGE_CL.addExternalSymbol("RENAME-PACKAGE"); public static final Symbol REPLACE = PACKAGE_CL.addExternalSymbol("REPLACE"); public static final Symbol REQUIRE = PACKAGE_CL.addExternalSymbol("REQUIRE"); public static final Symbol REST = PACKAGE_CL.addExternalSymbol("REST"); public static final Symbol RESTART = PACKAGE_CL.addExternalSymbol("RESTART"); public static final Symbol RESTART_BIND = PACKAGE_CL.addExternalSymbol("RESTART-BIND"); public static final Symbol RESTART_CASE = PACKAGE_CL.addExternalSymbol("RESTART-CASE"); public static final Symbol RESTART_NAME = PACKAGE_CL.addExternalSymbol("RESTART-NAME"); public static final Symbol RETURN = PACKAGE_CL.addExternalSymbol("RETURN"); public static final Symbol RETURN_FROM = PACKAGE_CL.addExternalSymbol("RETURN-FROM"); public static final Symbol REVAPPEND = PACKAGE_CL.addExternalSymbol("REVAPPEND"); public static final Symbol REVERSE = PACKAGE_CL.addExternalSymbol("REVERSE"); public static final Symbol ROOM = PACKAGE_CL.addExternalSymbol("ROOM"); public static final Symbol ROTATEF = PACKAGE_CL.addExternalSymbol("ROTATEF"); public static final Symbol ROUND = PACKAGE_CL.addExternalSymbol("ROUND"); public static final Symbol ROW_MAJOR_AREF = PACKAGE_CL.addExternalSymbol("ROW-MAJOR-AREF"); public static final Symbol RPLACA = PACKAGE_CL.addExternalSymbol("RPLACA"); public static final Symbol RPLACD = PACKAGE_CL.addExternalSymbol("RPLACD"); public static final Symbol SAFETY = PACKAGE_CL.addExternalSymbol("SAFETY"); public static final Symbol SATISFIES = PACKAGE_CL.addExternalSymbol("SATISFIES"); public static final Symbol SBIT = PACKAGE_CL.addExternalSymbol("SBIT"); public static final Symbol SCALE_FLOAT = PACKAGE_CL.addExternalSymbol("SCALE-FLOAT"); public static final Symbol SCHAR = PACKAGE_CL.addExternalSymbol("SCHAR"); public static final Symbol SEARCH = PACKAGE_CL.addExternalSymbol("SEARCH"); public static final Symbol SECOND = PACKAGE_CL.addExternalSymbol("SECOND"); public static final Symbol SEQUENCE = PACKAGE_CL.addExternalSymbol("SEQUENCE"); public static final Symbol SERIOUS_CONDITION = PACKAGE_CL.addExternalSymbol("SERIOUS-CONDITION"); public static final Symbol SET = PACKAGE_CL.addExternalSymbol("SET"); public static final Symbol SET_DIFFERENCE = PACKAGE_CL.addExternalSymbol("SET-DIFFERENCE"); public static final Symbol SET_DISPATCH_MACRO_CHARACTER = PACKAGE_CL.addExternalSymbol("SET-DISPATCH-MACRO-CHARACTER"); public static final Symbol SET_EXCLUSIVE_OR = PACKAGE_CL.addExternalSymbol("SET-EXCLUSIVE-OR"); public static final Symbol SET_MACRO_CHARACTER = PACKAGE_CL.addExternalSymbol("SET-MACRO-CHARACTER"); public static final Symbol SET_PPRINT_DISPATCH = PACKAGE_CL.addExternalSymbol("SET-PPRINT-DISPATCH"); public static final Symbol SET_SYNTAX_FROM_CHAR = PACKAGE_CL.addExternalSymbol("SET-SYNTAX-FROM-CHAR"); public static final Symbol SETF = PACKAGE_CL.addExternalSymbol("SETF"); public static final Symbol SETQ = PACKAGE_CL.addExternalSymbol("SETQ"); public static final Symbol SEVENTH = PACKAGE_CL.addExternalSymbol("SEVENTH"); public static final Symbol SHADOW = PACKAGE_CL.addExternalSymbol("SHADOW"); public static final Symbol SHADOWING_IMPORT = PACKAGE_CL.addExternalSymbol("SHADOWING-IMPORT"); public static final Symbol SHARED_INITIALIZE = PACKAGE_CL.addExternalSymbol("SHARED-INITIALIZE"); public static final Symbol SHIFTF = PACKAGE_CL.addExternalSymbol("SHIFTF"); public static final Symbol SHORT_FLOAT = PACKAGE_CL.addExternalSymbol("SHORT-FLOAT"); public static final Symbol SHORT_FLOAT_EPSILON = PACKAGE_CL.addExternalSymbol("SHORT-FLOAT-EPSILON"); public static final Symbol SHORT_FLOAT_NEGATIVE_EPSILON = PACKAGE_CL.addExternalSymbol("SHORT-FLOAT-NEGATIVE-EPSILON"); public static final Symbol SHORT_SITE_NAME = PACKAGE_CL.addExternalSymbol("SHORT-SITE-NAME"); public static final Symbol SIGNAL = PACKAGE_CL.addExternalSymbol("SIGNAL"); public static final Symbol SIGNED_BYTE = PACKAGE_CL.addExternalSymbol("SIGNED-BYTE"); public static final Symbol SIGNUM = PACKAGE_CL.addExternalSymbol("SIGNUM"); public static final Symbol SIMPLE_ARRAY = PACKAGE_CL.addExternalSymbol("SIMPLE-ARRAY"); public static final Symbol SIMPLE_BASE_STRING = PACKAGE_CL.addExternalSymbol("SIMPLE-BASE-STRING"); public static final Symbol SIMPLE_BIT_VECTOR = PACKAGE_CL.addExternalSymbol("SIMPLE-BIT-VECTOR"); public static final Symbol SIMPLE_BIT_VECTOR_P = PACKAGE_CL.addExternalSymbol("SIMPLE-BIT-VECTOR-P"); public static final Symbol SIMPLE_CONDITION = PACKAGE_CL.addExternalSymbol("SIMPLE-CONDITION"); public static final Symbol SIMPLE_CONDITION_FORMAT_ARGUMENTS = PACKAGE_CL.addExternalSymbol("SIMPLE-CONDITION-FORMAT-ARGUMENTS"); public static final Symbol SIMPLE_CONDITION_FORMAT_CONTROL = PACKAGE_CL.addExternalSymbol("SIMPLE-CONDITION-FORMAT-CONTROL"); public static final Symbol SIMPLE_ERROR = PACKAGE_CL.addExternalSymbol("SIMPLE-ERROR"); public static final Symbol SIMPLE_STRING = PACKAGE_CL.addExternalSymbol("SIMPLE-STRING"); public static final Symbol SIMPLE_STRING_P = PACKAGE_CL.addExternalSymbol("SIMPLE-STRING-P"); public static final Symbol SIMPLE_TYPE_ERROR = PACKAGE_CL.addExternalSymbol("SIMPLE-TYPE-ERROR"); public static final Symbol SIMPLE_VECTOR = PACKAGE_CL.addExternalSymbol("SIMPLE-VECTOR"); public static final Symbol SIMPLE_VECTOR_P = PACKAGE_CL.addExternalSymbol("SIMPLE-VECTOR-P"); public static final Symbol SIMPLE_WARNING = PACKAGE_CL.addExternalSymbol("SIMPLE-WARNING"); public static final Symbol SIN = PACKAGE_CL.addExternalSymbol("SIN"); public static final Symbol SINGLE_FLOAT = PACKAGE_CL.addExternalSymbol("SINGLE-FLOAT"); public static final Symbol SINGLE_FLOAT_EPSILON = PACKAGE_CL.addExternalSymbol("SINGLE-FLOAT-EPSILON"); public static final Symbol SINGLE_FLOAT_NEGATIVE_EPSILON = PACKAGE_CL.addExternalSymbol("SINGLE-FLOAT-NEGATIVE-EPSILON"); public static final Symbol SINH = PACKAGE_CL.addExternalSymbol("SINH"); public static final Symbol SIXTH = PACKAGE_CL.addExternalSymbol("SIXTH"); public static final Symbol SLEEP = PACKAGE_CL.addExternalSymbol("SLEEP"); public static final Symbol SLOT_BOUNDP = PACKAGE_CL.addExternalSymbol("SLOT-BOUNDP"); public static final Symbol SLOT_EXISTS_P = PACKAGE_CL.addExternalSymbol("SLOT-EXISTS-P"); public static final Symbol SLOT_MAKUNBOUND = PACKAGE_CL.addExternalSymbol("SLOT-MAKUNBOUND"); public static final Symbol SLOT_MISSING = PACKAGE_CL.addExternalSymbol("SLOT-MISSING"); public static final Symbol SLOT_UNBOUND = PACKAGE_CL.addExternalSymbol("SLOT-UNBOUND"); public static final Symbol SLOT_VALUE = PACKAGE_CL.addExternalSymbol("SLOT-VALUE"); public static final Symbol SOFTWARE_TYPE = PACKAGE_CL.addExternalSymbol("SOFTWARE-TYPE"); public static final Symbol SOFTWARE_VERSION = PACKAGE_CL.addExternalSymbol("SOFTWARE-VERSION"); public static final Symbol SOME = PACKAGE_CL.addExternalSymbol("SOME"); public static final Symbol SORT = PACKAGE_CL.addExternalSymbol("SORT"); public static final Symbol SPACE = PACKAGE_CL.addExternalSymbol("SPACE"); public static final Symbol SPECIAL = PACKAGE_CL.addExternalSymbol("SPECIAL"); public static final Symbol SPECIAL_OPERATOR_P = PACKAGE_CL.addExternalSymbol("SPECIAL-OPERATOR-P"); public static final Symbol SPEED = PACKAGE_CL.addExternalSymbol("SPEED"); public static final Symbol SQRT = PACKAGE_CL.addExternalSymbol("SQRT"); public static final Symbol STABLE_SORT = PACKAGE_CL.addExternalSymbol("STABLE-SORT"); public static final Symbol STANDARD = PACKAGE_CL.addExternalSymbol("STANDARD"); public static final Symbol STANDARD_CHAR = PACKAGE_CL.addExternalSymbol("STANDARD-CHAR"); public static final Symbol STANDARD_CHAR_P = PACKAGE_CL.addExternalSymbol("STANDARD-CHAR-P"); public static final Symbol STANDARD_CLASS = PACKAGE_CL.addExternalSymbol("STANDARD-CLASS"); public static final Symbol STANDARD_GENERIC_FUNCTION = PACKAGE_CL.addExternalSymbol("STANDARD-GENERIC-FUNCTION"); public static final Symbol STANDARD_METHOD = PACKAGE_CL.addExternalSymbol("STANDARD-METHOD"); public static final Symbol STANDARD_OBJECT = PACKAGE_CL.addExternalSymbol("STANDARD-OBJECT"); public static final Symbol STEP = PACKAGE_CL.addExternalSymbol("STEP"); public static final Symbol STORAGE_CONDITION = PACKAGE_CL.addExternalSymbol("STORAGE-CONDITION"); public static final Symbol STORE_VALUE = PACKAGE_CL.addExternalSymbol("STORE-VALUE"); public static final Symbol STREAM = PACKAGE_CL.addExternalSymbol("STREAM"); public static final Symbol STREAM_ELEMENT_TYPE = PACKAGE_CL.addExternalSymbol("STREAM-ELEMENT-TYPE"); public static final Symbol STREAM_ERROR = PACKAGE_CL.addExternalSymbol("STREAM-ERROR"); public static final Symbol STREAM_ERROR_STREAM = PACKAGE_CL.addExternalSymbol("STREAM-ERROR-STREAM"); public static final Symbol STREAM_EXTERNAL_FORMAT = PACKAGE_CL.addExternalSymbol("STREAM-EXTERNAL-FORMAT"); public static final Symbol STREAMP = PACKAGE_CL.addExternalSymbol("STREAMP"); public static final Symbol STRING = PACKAGE_CL.addExternalSymbol("STRING"); public static final Symbol STRING_CAPITALIZE = PACKAGE_CL.addExternalSymbol("STRING-CAPITALIZE"); public static final Symbol STRING_DOWNCASE = PACKAGE_CL.addExternalSymbol("STRING-DOWNCASE"); public static final Symbol STRING_EQUAL = PACKAGE_CL.addExternalSymbol("STRING-EQUAL"); public static final Symbol STRING_GREATERP = PACKAGE_CL.addExternalSymbol("STRING-GREATERP"); public static final Symbol STRING_LEFT_TRIM = PACKAGE_CL.addExternalSymbol("STRING-LEFT-TRIM"); public static final Symbol STRING_LESSP = PACKAGE_CL.addExternalSymbol("STRING-LESSP"); public static final Symbol STRING_NOT_EQUAL = PACKAGE_CL.addExternalSymbol("STRING-NOT-EQUAL"); public static final Symbol STRING_NOT_GREATERP = PACKAGE_CL.addExternalSymbol("STRING-NOT-GREATERP"); public static final Symbol STRING_NOT_LESSP = PACKAGE_CL.addExternalSymbol("STRING-NOT-LESSP"); public static final Symbol STRING_RIGHT_TRIM = PACKAGE_CL.addExternalSymbol("STRING-RIGHT-TRIM"); public static final Symbol STRING_STREAM = PACKAGE_CL.addExternalSymbol("STRING-STREAM"); public static final Symbol STRING_TRIM = PACKAGE_CL.addExternalSymbol("STRING-TRIM"); public static final Symbol STRING_UPCASE = PACKAGE_CL.addExternalSymbol("STRING-UPCASE"); public static final Symbol STRING_NE = PACKAGE_CL.addExternalSymbol("STRING/="); public static final Symbol STRING_LT = PACKAGE_CL.addExternalSymbol("STRING<"); public static final Symbol STRING_LE = PACKAGE_CL.addExternalSymbol("STRING<="); public static final Symbol STRING_EQUALS = PACKAGE_CL.addExternalSymbol("STRING="); public static final Symbol STRING_GT = PACKAGE_CL.addExternalSymbol("STRING>"); public static final Symbol STRING_GE = PACKAGE_CL.addExternalSymbol("STRING>="); public static final Symbol STRINGP = PACKAGE_CL.addExternalSymbol("STRINGP"); public static final Symbol STRUCTURE = PACKAGE_CL.addExternalSymbol("STRUCTURE"); public static final Symbol STRUCTURE_CLASS = PACKAGE_CL.addExternalSymbol("STRUCTURE-CLASS"); public static final Symbol STRUCTURE_OBJECT = PACKAGE_CL.addExternalSymbol("STRUCTURE-OBJECT"); public static final Symbol STYLE_WARNING = PACKAGE_CL.addExternalSymbol("STYLE-WARNING"); public static final Symbol SUBLIS = PACKAGE_CL.addExternalSymbol("SUBLIS"); public static final Symbol SUBSEQ = PACKAGE_CL.addExternalSymbol("SUBSEQ"); public static final Symbol SUBSETP = PACKAGE_CL.addExternalSymbol("SUBSETP"); public static final Symbol SUBST = PACKAGE_CL.addExternalSymbol("SUBST"); public static final Symbol SUBST_IF = PACKAGE_CL.addExternalSymbol("SUBST-IF"); public static final Symbol SUBST_IF_NOT = PACKAGE_CL.addExternalSymbol("SUBST-IF-NOT"); public static final Symbol SUBSTITUTE = PACKAGE_CL.addExternalSymbol("SUBSTITUTE"); public static final Symbol SUBSTITUTE_IF = PACKAGE_CL.addExternalSymbol("SUBSTITUTE-IF"); public static final Symbol SUBSTITUTE_IF_NOT = PACKAGE_CL.addExternalSymbol("SUBSTITUTE-IF-NOT"); public static final Symbol SUBTYPEP = PACKAGE_CL.addExternalSymbol("SUBTYPEP"); public static final Symbol SVREF = PACKAGE_CL.addExternalSymbol("SVREF"); public static final Symbol SXHASH = PACKAGE_CL.addExternalSymbol("SXHASH"); public static final Symbol SYMBOL = PACKAGE_CL.addExternalSymbol("SYMBOL"); public static final Symbol SYMBOL_FUNCTION = PACKAGE_CL.addExternalSymbol("SYMBOL-FUNCTION"); public static final Symbol SYMBOL_MACROLET = PACKAGE_CL.addExternalSymbol("SYMBOL-MACROLET"); public static final Symbol SYMBOL_NAME = PACKAGE_CL.addExternalSymbol("SYMBOL-NAME"); public static final Symbol SYMBOL_PACKAGE = PACKAGE_CL.addExternalSymbol("SYMBOL-PACKAGE"); public static final Symbol SYMBOL_PLIST = PACKAGE_CL.addExternalSymbol("SYMBOL-PLIST"); public static final Symbol SYMBOL_VALUE = PACKAGE_CL.addExternalSymbol("SYMBOL-VALUE"); public static final Symbol SYMBOLP = PACKAGE_CL.addExternalSymbol("SYMBOLP"); public static final Symbol SYNONYM_STREAM = PACKAGE_CL.addExternalSymbol("SYNONYM-STREAM"); public static final Symbol SYNONYM_STREAM_SYMBOL = PACKAGE_CL.addExternalSymbol("SYNONYM-STREAM-SYMBOL"); public static final Symbol T = PACKAGE_CL.addExternalSymbol("T"); public static final Symbol TAGBODY = PACKAGE_CL.addExternalSymbol("TAGBODY"); public static final Symbol TAILP = PACKAGE_CL.addExternalSymbol("TAILP"); public static final Symbol TAN = PACKAGE_CL.addExternalSymbol("TAN"); public static final Symbol TANH = PACKAGE_CL.addExternalSymbol("TANH"); public static final Symbol TENTH = PACKAGE_CL.addExternalSymbol("TENTH"); public static final Symbol TERPRI = PACKAGE_CL.addExternalSymbol("TERPRI"); public static final Symbol THE = PACKAGE_CL.addExternalSymbol("THE"); public static final Symbol THIRD = PACKAGE_CL.addExternalSymbol("THIRD"); public static final Symbol THROW = PACKAGE_CL.addExternalSymbol("THROW"); public static final Symbol TIME = PACKAGE_CL.addExternalSymbol("TIME"); public static final Symbol TRACE = PACKAGE_CL.addExternalSymbol("TRACE"); public static final Symbol TRANSLATE_LOGICAL_PATHNAME = PACKAGE_CL.addExternalSymbol("TRANSLATE-LOGICAL-PATHNAME"); public static final Symbol TRANSLATE_PATHNAME = PACKAGE_CL.addExternalSymbol("TRANSLATE-PATHNAME"); public static final Symbol TREE_EQUAL = PACKAGE_CL.addExternalSymbol("TREE-EQUAL"); public static final Symbol TRUENAME = PACKAGE_CL.addExternalSymbol("TRUENAME"); public static final Symbol TRUNCATE = PACKAGE_CL.addExternalSymbol("TRUNCATE"); public static final Symbol TWO_WAY_STREAM = PACKAGE_CL.addExternalSymbol("TWO-WAY-STREAM"); public static final Symbol TWO_WAY_STREAM_INPUT_STREAM = PACKAGE_CL.addExternalSymbol("TWO-WAY-STREAM-INPUT-STREAM"); public static final Symbol TWO_WAY_STREAM_OUTPUT_STREAM = PACKAGE_CL.addExternalSymbol("TWO-WAY-STREAM-OUTPUT-STREAM"); public static final Symbol TYPE = PACKAGE_CL.addExternalSymbol("TYPE"); public static final Symbol TYPE_ERROR = PACKAGE_CL.addExternalSymbol("TYPE-ERROR"); public static final Symbol TYPE_ERROR_DATUM = PACKAGE_CL.addExternalSymbol("TYPE-ERROR-DATUM"); public static final Symbol TYPE_ERROR_EXPECTED_TYPE = PACKAGE_CL.addExternalSymbol("TYPE-ERROR-EXPECTED-TYPE"); public static final Symbol TYPE_OF = PACKAGE_CL.addExternalSymbol("TYPE-OF"); public static final Symbol TYPECASE = PACKAGE_CL.addExternalSymbol("TYPECASE"); public static final Symbol TYPEP = PACKAGE_CL.addExternalSymbol("TYPEP"); public static final Symbol UNBOUND_SLOT = PACKAGE_CL.addExternalSymbol("UNBOUND-SLOT"); public static final Symbol UNBOUND_SLOT_INSTANCE = PACKAGE_CL.addExternalSymbol("UNBOUND-SLOT-INSTANCE"); public static final Symbol UNBOUND_VARIABLE = PACKAGE_CL.addExternalSymbol("UNBOUND-VARIABLE"); public static final Symbol UNDEFINED_FUNCTION = PACKAGE_CL.addExternalSymbol("UNDEFINED-FUNCTION"); public static final Symbol UNEXPORT = PACKAGE_CL.addExternalSymbol("UNEXPORT"); public static final Symbol UNINTERN = PACKAGE_CL.addExternalSymbol("UNINTERN"); public static final Symbol UNION = PACKAGE_CL.addExternalSymbol("UNION"); public static final Symbol UNLESS = PACKAGE_CL.addExternalSymbol("UNLESS"); public static final Symbol UNREAD_CHAR = PACKAGE_CL.addExternalSymbol("UNREAD-CHAR"); public static final Symbol UNSIGNED_BYTE = PACKAGE_CL.addExternalSymbol("UNSIGNED-BYTE"); public static final Symbol UNTRACE = PACKAGE_CL.addExternalSymbol("UNTRACE"); public static final Symbol UNUSE_PACKAGE = PACKAGE_CL.addExternalSymbol("UNUSE-PACKAGE"); public static final Symbol UNWIND_PROTECT = PACKAGE_CL.addExternalSymbol("UNWIND-PROTECT"); public static final Symbol UPDATE_INSTANCE_FOR_DIFFERENT_CLASS = PACKAGE_CL.addExternalSymbol("UPDATE-INSTANCE-FOR-DIFFERENT-CLASS"); public static final Symbol UPDATE_INSTANCE_FOR_REDEFINED_CLASS = PACKAGE_CL.addExternalSymbol("UPDATE-INSTANCE-FOR-REDEFINED-CLASS"); public static final Symbol UPGRADED_ARRAY_ELEMENT_TYPE = PACKAGE_CL.addExternalSymbol("UPGRADED-ARRAY-ELEMENT-TYPE"); public static final Symbol UPGRADED_COMPLEX_PART_TYPE = PACKAGE_CL.addExternalSymbol("UPGRADED-COMPLEX-PART-TYPE"); public static final Symbol UPPER_CASE_P = PACKAGE_CL.addExternalSymbol("UPPER-CASE-P"); public static final Symbol USE_PACKAGE = PACKAGE_CL.addExternalSymbol("USE-PACKAGE"); public static final Symbol USE_VALUE = PACKAGE_CL.addExternalSymbol("USE-VALUE"); public static final Symbol USER_HOMEDIR_PATHNAME = PACKAGE_CL.addExternalSymbol("USER-HOMEDIR-PATHNAME"); public static final Symbol VALUES = PACKAGE_CL.addExternalSymbol("VALUES"); public static final Symbol VALUES_LIST = PACKAGE_CL.addExternalSymbol("VALUES-LIST"); public static final Symbol VARIABLE = PACKAGE_CL.addExternalSymbol("VARIABLE"); public static final Symbol VECTOR = PACKAGE_CL.addExternalSymbol("VECTOR"); public static final Symbol VECTOR_POP = PACKAGE_CL.addExternalSymbol("VECTOR-POP"); public static final Symbol VECTOR_PUSH = PACKAGE_CL.addExternalSymbol("VECTOR-PUSH"); public static final Symbol VECTOR_PUSH_EXTEND = PACKAGE_CL.addExternalSymbol("VECTOR-PUSH-EXTEND"); public static final Symbol VECTORP = PACKAGE_CL.addExternalSymbol("VECTORP"); public static final Symbol WARN = PACKAGE_CL.addExternalSymbol("WARN"); public static final Symbol WARNING = PACKAGE_CL.addExternalSymbol("WARNING"); public static final Symbol WHEN = PACKAGE_CL.addExternalSymbol("WHEN"); public static final Symbol WILD_PATHNAME_P = PACKAGE_CL.addExternalSymbol("WILD-PATHNAME-P"); public static final Symbol WITH_ACCESSORS = PACKAGE_CL.addExternalSymbol("WITH-ACCESSORS"); public static final Symbol WITH_COMPILATION_UNIT = PACKAGE_CL.addExternalSymbol("WITH-COMPILATION-UNIT"); public static final Symbol WITH_CONDITION_RESTARTS = PACKAGE_CL.addExternalSymbol("WITH-CONDITION-RESTARTS"); public static final Symbol WITH_HASH_TABLE_ITERATOR = PACKAGE_CL.addExternalSymbol("WITH-HASH-TABLE-ITERATOR"); public static final Symbol WITH_INPUT_FROM_STRING = PACKAGE_CL.addExternalSymbol("WITH-INPUT-FROM-STRING"); public static final Symbol WITH_OPEN_FILE = PACKAGE_CL.addExternalSymbol("WITH-OPEN-FILE"); public static final Symbol WITH_OPEN_STREAM = PACKAGE_CL.addExternalSymbol("WITH-OPEN-STREAM"); public static final Symbol WITH_OUTPUT_TO_STRING = PACKAGE_CL.addExternalSymbol("WITH-OUTPUT-TO-STRING"); public static final Symbol WITH_PACKAGE_ITERATOR = PACKAGE_CL.addExternalSymbol("WITH-PACKAGE-ITERATOR"); public static final Symbol WITH_SIMPLE_RESTART = PACKAGE_CL.addExternalSymbol("WITH-SIMPLE-RESTART"); public static final Symbol WITH_SLOTS = PACKAGE_CL.addExternalSymbol("WITH-SLOTS"); public static final Symbol WITH_STANDARD_IO_SYNTAX = PACKAGE_CL.addExternalSymbol("WITH-STANDARD-IO-SYNTAX"); public static final Symbol WRITE = PACKAGE_CL.addExternalSymbol("WRITE"); public static final Symbol WRITE_BYTE = PACKAGE_CL.addExternalSymbol("WRITE-BYTE"); public static final Symbol WRITE_CHAR = PACKAGE_CL.addExternalSymbol("WRITE-CHAR"); public static final Symbol WRITE_LINE = PACKAGE_CL.addExternalSymbol("WRITE-LINE"); public static final Symbol WRITE_SEQUENCE = PACKAGE_CL.addExternalSymbol("WRITE-SEQUENCE"); public static final Symbol WRITE_STRING = PACKAGE_CL.addExternalSymbol("WRITE-STRING"); public static final Symbol WRITE_TO_STRING = PACKAGE_CL.addExternalSymbol("WRITE-TO-STRING"); public static final Symbol Y_OR_N_P = PACKAGE_CL.addExternalSymbol("Y-OR-N-P"); public static final Symbol YES_OR_NO_P = PACKAGE_CL.addExternalSymbol("YES-OR-NO-P"); public static final Symbol ZEROP = PACKAGE_CL.addExternalSymbol("ZEROP"); // End of CL symbols. // Extensions. public static final Symbol MOST_POSITIVE_JAVA_LONG = PACKAGE_EXT.addExternalSymbol("MOST-POSITIVE-JAVA-LONG"); public static final Symbol MOST_NEGATIVE_JAVA_LONG= PACKAGE_EXT.addExternalSymbol("MOST-NEGATIVE-JAVA-LONG"); public static final Symbol SINGLE_FLOAT_POSITIVE_INFINITY = PACKAGE_EXT.addExternalSymbol("SINGLE-FLOAT-POSITIVE-INFINITY"); public static final Symbol SINGLE_FLOAT_NEGATIVE_INFINITY = PACKAGE_EXT.addExternalSymbol("SINGLE-FLOAT-NEGATIVE-INFINITY"); public static final Symbol DOUBLE_FLOAT_POSITIVE_INFINITY = PACKAGE_EXT.addExternalSymbol("DOUBLE-FLOAT-POSITIVE-INFINITY"); public static final Symbol DOUBLE_FLOAT_NEGATIVE_INFINITY = PACKAGE_EXT.addExternalSymbol("DOUBLE-FLOAT-NEGATIVE-INFINITY"); public static final Symbol STYLE_WARN = PACKAGE_EXT.addExternalSymbol("STYLE-WARN"); public static final Symbol MEMQ = PACKAGE_EXT.addExternalSymbol("MEMQ"); public static final Symbol MEMQL = PACKAGE_EXT.addExternalSymbol("MEMQL"); public static final Symbol NIL_VECTOR = PACKAGE_EXT.addExternalSymbol("NIL-VECTOR"); public static final Symbol MAILBOX = PACKAGE_EXT.addExternalSymbol("MAILBOX"); public static final Symbol MUTEX = PACKAGE_EXT.addExternalSymbol("MUTEX"); public static final Symbol SUPPRESS_COMPILER_WARNINGS = PACKAGE_EXT.addExternalSymbol("*SUPPRESS-COMPILER-WARNINGS*"); public static final Symbol NEQ = PACKAGE_EXT.addExternalSymbol("NEQ"); public static final Symbol ADJOIN_EQL = PACKAGE_EXT.addExternalSymbol("ADJOIN-EQL"); public static final Symbol CHARACTER_DESIGNATOR = PACKAGE_EXT.addExternalSymbol("CHARACTER-DESIGNATOR"); public static final Symbol INTERRUPT_LISP = PACKAGE_EXT.addExternalSymbol("INTERRUPT-LISP"); public static final Symbol GETENV = PACKAGE_EXT.addExternalSymbol("GETENV"); public static final Symbol MACROEXPAND_ALL = PACKAGE_EXT.addExternalSymbol("MACROEXPAND-ALL"); public static final Symbol LOAD_TRUENAME_FASL = PACKAGE_EXT.addExternalSymbol("*LOAD-TRUENAME-FASL*"); public static final Symbol SLIME_INPUT_STREAM = PACKAGE_EXT.addExternalSymbol("SLIME-INPUT-STREAM"); public static final Symbol SLIME_OUTPUT_STREAM = PACKAGE_EXT.addExternalSymbol("SLIME-OUTPUT-STREAM"); public static final Symbol JAR_PATHNAME = PACKAGE_EXT.addExternalSymbol("JAR-PATHNAME"); public static final Symbol URL_PATHNAME = PACKAGE_EXT.addExternalSymbol("URL-PATHNAME"); public static final Symbol WEAK_REFERENCE = PACKAGE_EXT.addExternalSymbol("WEAK-REFERENCE"); public static final Symbol ADD_PACKAGE_LOCAL_NICKNAME = PACKAGE_EXT.addExternalSymbol("ADD-PACKAGE-LOCAL-NICKNAME"); // MOP. public static final Symbol CLASS_LAYOUT = PACKAGE_MOP.addInternalSymbol("CLASS-LAYOUT"); public static final Symbol CLASS_DEFAULT_INITARGS = PACKAGE_MOP.addExternalSymbol("CLASS-DEFAULT_INITARGS"); public static final Symbol CLASS_DIRECT_METHODS = PACKAGE_MOP.addExternalSymbol("CLASS-DIRECT-METHODS"); public static final Symbol CLASS_DIRECT_DEFAULT_INITARGS = PACKAGE_MOP.addExternalSymbol("CLASS-DIRECT-DEFAULT_INITARGS"); public static final Symbol CLASS_DIRECT_SLOTS = PACKAGE_MOP.addExternalSymbol("CLASS-DIRECT-SLOTS"); public static final Symbol CLASS_DIRECT_SUBCLASSES = PACKAGE_MOP.addExternalSymbol("CLASS-DIRECT-SUBCLASSES"); public static final Symbol CLASS_DIRECT_SUPERCLASSES = PACKAGE_MOP.addExternalSymbol("CLASS-DIRECT-SUPERCLASSES"); public static final Symbol CLASS_DOCUMENTATION = PACKAGE_MOP.addExternalSymbol("CLASS-DOCUMENTATION"); public static final Symbol CLASS_FINALIZED_P = PACKAGE_MOP.addExternalSymbol("CLASS-FINALIZED-P"); public static final Symbol CLASS_PRECEDENCE_LIST = PACKAGE_MOP.addExternalSymbol("CLASS-PRECEDENCE-LIST"); public static final Symbol CLASS_SLOTS = PACKAGE_MOP.addExternalSymbol("CLASS-SLOTS"); public static final Symbol EQL_SPECIALIZER = PACKAGE_MOP.addExternalSymbol("EQL-SPECIALIZER"); public static final Symbol EQL_SPECIALIZER_OBJECT = PACKAGE_MOP.addExternalSymbol("EQL-SPECIALIZER-OBJECT"); public static final Symbol FUNCALLABLE_STANDARD_OBJECT = PACKAGE_MOP.addExternalSymbol("FUNCALLABLE-STANDARD-OBJECT"); public static final Symbol FUNCALLABLE_STANDARD_CLASS = PACKAGE_MOP.addExternalSymbol("FUNCALLABLE-STANDARD-CLASS"); public static final Symbol GENERIC_FUNCTION_METHODS = PACKAGE_MOP.addExternalSymbol("GENERIC-FUNCTION-METHODS"); public static final Symbol GENERIC_FUNCTION_NAME = PACKAGE_MOP.addExternalSymbol("GENERIC-FUNCTION-NAME"); public static final Symbol METAOBJECT = PACKAGE_MOP.addExternalSymbol("METAOBJECT"); public static final Symbol METHOD_FUNCTION = PACKAGE_MOP.addExternalSymbol("METHOD-FUNCTION"); public static final Symbol SPECIALIZER = PACKAGE_MOP.addExternalSymbol("SPECIALIZER"); public static final Symbol STANDARD_ACCESSOR_METHOD = PACKAGE_MOP.addExternalSymbol("STANDARD-ACCESSOR-METHOD"); public static final Symbol STANDARD_READER_METHOD = PACKAGE_MOP.addExternalSymbol("STANDARD-READER-METHOD"); public static final Symbol STANDARD_WRITER_METHOD = PACKAGE_MOP.addExternalSymbol("STANDARD-WRITER-METHOD"); public static final Symbol DIRECT_SLOT_DEFINITION = PACKAGE_MOP.addExternalSymbol("DIRECT-SLOT-DEFINITION"); public static final Symbol EFFECTIVE_SLOT_DEFINITION = PACKAGE_MOP.addExternalSymbol("EFFECTIVE-SLOT-DEFINITION"); public static final Symbol STANDARD_SLOT_DEFINITION = PACKAGE_MOP.addExternalSymbol("STANDARD-SLOT-DEFINITION"); public static final Symbol STANDARD_DIRECT_SLOT_DEFINITION = PACKAGE_MOP.addExternalSymbol("STANDARD-DIRECT-SLOT-DEFINITION"); public static final Symbol STANDARD_EFFECTIVE_SLOT_DEFINITION = PACKAGE_MOP.addExternalSymbol("STANDARD-EFFECTIVE-SLOT-DEFINITION"); // MOP method combination readers. public static final Symbol METHOD_COMBINATION_NAME = PACKAGE_MOP.addInternalSymbol("METHOD-COMBINATION-NAME"); public static final Symbol METHOD_COMBINATION_DOCUMENTATION = PACKAGE_MOP.addInternalSymbol("METHOD-COMBINATION-DOCUMENTATION"); // Java interface. public static final Symbol JAVA_EXCEPTION = PACKAGE_JAVA.addExternalSymbol("JAVA-EXCEPTION"); public static final Symbol JAVA_EXCEPTION_CAUSE = PACKAGE_JAVA.addExternalSymbol("JAVA-EXCEPTION-CAUSE"); public static final Symbol JAVA_OBJECT = PACKAGE_JAVA.addExternalSymbol("JAVA-OBJECT"); public static final Symbol JAVA_CLASS = PACKAGE_JAVA.addExternalSymbol("JAVA-CLASS"); public static final Symbol JCALL = PACKAGE_JAVA.addExternalSymbol("JCALL"); public static final Symbol JCALL_RAW = PACKAGE_JAVA.addExternalSymbol("JCALL-RAW"); public static final Symbol JCLASS = PACKAGE_JAVA.addExternalSymbol("JCLASS"); public static final Symbol JCLASS_NAME = PACKAGE_JAVA.addExternalSymbol("JCLASS-NAME"); public static final Symbol JCLASS_OF = PACKAGE_JAVA.addExternalSymbol("JCLASS-OF"); public static final Symbol JINPUT_STREAM = PACKAGE_JAVA.addExternalSymbol("JINPUT-STREAM"); public static final Symbol JMETHOD_RETURN_TYPE = PACKAGE_JAVA.addExternalSymbol("JMETHOD-RETURN-TYPE"); public static final Symbol JRESOLVE_METHOD = PACKAGE_JAVA.addExternalSymbol("JRESOLVE-METHOD"); public static final Symbol ADD_TO_CLASSPATH = PACKAGE_JAVA.addExternalSymbol("ADD-TO-CLASSPATH"); // External symbols in SYSTEM package. public static final Symbol AUTOCOMPILE = PACKAGE_SYS.addExternalSymbol("AUTOCOMPILE"); public static final Symbol CLASS_BYTES = PACKAGE_SYS.addExternalSymbol("CLASS-BYTES"); public static final Symbol _CLASS_SLOTS = PACKAGE_SYS.addExternalSymbol("%CLASS-SLOTS"); public static final Symbol COMPILED_LISP_FUNCTION_P = PACKAGE_SYS.addExternalSymbol("COMPILED-LISP-FUNCTION-P"); public static final Symbol DEFAULT_INITARGS = PACKAGE_SYS.addExternalSymbol("DEFAULT-INITARGS"); public static final Symbol DIRECT_METHODS = PACKAGE_SYS.addExternalSymbol("DIRECT-METHODS"); public static final Symbol DIRECT_SLOTS = PACKAGE_SYS.addExternalSymbol("DIRECT-SLOTS"); public static final Symbol DIRECT_SUBCLASSES = PACKAGE_SYS.addExternalSymbol("DIRECT-SUBCLASSES"); public static final Symbol DIRECT_DEFAULT_INITARGS = PACKAGE_SYS.addExternalSymbol("DIRECT-DEFAULT-INITARGS"); public static final Symbol DIRECT_SUPERCLASSES = PACKAGE_SYS.addExternalSymbol("DIRECT-SUPERCLASSES"); public static final Symbol __DISASSEMBLERS__ = PACKAGE_SYS.addExternalSymbol("*DISASSEMBLERS*"); public static final Symbol CHOOSE_DISASSEMBLER = PACKAGE_SYS.addExternalSymbol("CHOOSE-DISASSEMBLER"); public static final Symbol _DOCUMENTATION = PACKAGE_SYS.addExternalSymbol("%DOCUMENTATION"); public static final Symbol _ENABLE_AUTOCOMPILE_ = PACKAGE_SYS.addExternalSymbol("*ENABLE-AUTOCOMPILE*"); public static final Symbol GET_INPUT_STREAM = PACKAGE_SYS.addExternalSymbol("GET-INPUT-STREAM"); public static final Symbol ENVIRONMENT = PACKAGE_SYS.addExternalSymbol("ENVIRONMENT"); public static final Symbol FINALIZED_P = PACKAGE_SYS.addExternalSymbol("FINALIZED-P"); public static final Symbol FLOAT_UNDERFLOW_MODE = PACKAGE_SYS.addExternalSymbol("FLOAT-UNDERFLOW-MODE"); public static final Symbol FLOAT_OVERFLOW_MODE = PACKAGE_SYS.addExternalSymbol("FLOAT-OVERFLOW-MODE"); public static final Symbol GETHASH1 = PACKAGE_SYS.addExternalSymbol("GETHASH1"); public static final Symbol HASH_TABLE_WEAKNESS = PACKAGE_SYS.addExternalSymbol("HASH-TABLE-WEAKNESS"); public static final Symbol JAR_STREAM = PACKAGE_SYS.addExternalSymbol("JAR-STREAM"); public static final Symbol LAYOUT = PACKAGE_SYS.addExternalSymbol("LAYOUT"); public static final Symbol MATCH_WILD_JAR_PATHNAME = PACKAGE_SYS.addExternalSymbol("MATCH-WILD-JAR-PATHNAME"); public static final Symbol NAME = PACKAGE_SYS.addExternalSymbol("NAME"); public static final Symbol NAMED_LAMBDA = PACKAGE_SYS.addExternalSymbol("NAMED-LAMBDA"); public static final Symbol OUTPUT_OBJECT = PACKAGE_SYS.addExternalSymbol("OUTPUT-OBJECT"); public static final Symbol PRECEDENCE_LIST = PACKAGE_SYS.addExternalSymbol("PRECEDENCE-LIST"); public static final Symbol PUTHASH = PACKAGE_SYS.addExternalSymbol("PUTHASH"); public static final Symbol RECORD_SOURCE_INFORMATION_FOR_TYPE = PACKAGE_SYS.addExternalSymbol("RECORD-SOURCE-INFORMATION-FOR-TYPE"); public static final Symbol SET_CHAR = PACKAGE_SYS.addExternalSymbol("SET-CHAR"); public static final Symbol _SET_CLASS_SLOTS = PACKAGE_SYS.addExternalSymbol("%SET-CLASS-SLOTS"); public static final Symbol SET_SCHAR = PACKAGE_SYS.addExternalSymbol("SET-SCHAR"); public static final Symbol SET_STD_SLOT_VALUE = PACKAGE_SYS.addExternalSymbol("SET-STD-SLOT-VALUE"); public static final Symbol SETF_FUNCTION = PACKAGE_SYS.addExternalSymbol("SETF-FUNCTION"); public static final Symbol SETF_INVERSE = PACKAGE_SYS.addExternalSymbol("SETF-INVERSE"); public static final Symbol SLOTS = PACKAGE_SYS.addExternalSymbol("SLOTS"); public static final Symbol SLOT_DEFINITION = PACKAGE_SYS.addExternalSymbol("SLOT-DEFINITION"); public static final Symbol __SOURCE = PACKAGE_SYS.addInternalSymbol("SOURCE"); public static final Symbol STD_SLOT_BOUNDP = PACKAGE_SYS.addExternalSymbol("STD-SLOT-BOUNDP"); public static final Symbol STD_SLOT_VALUE = PACKAGE_SYS.addExternalSymbol("STD-SLOT-VALUE"); public static final Symbol SUBCLASSP = PACKAGE_SYS.addExternalSymbol("SUBCLASSP"); public static final Symbol SYMBOL_MACRO = PACKAGE_SYS.addExternalSymbol("SYMBOL-MACRO"); public static final Symbol UNDEFINED_FUNCTION_CALLED = PACKAGE_SYS.addExternalSymbol("UNDEFINED-FUNCTION-CALLED"); public static final Symbol URL_STREAM = PACKAGE_SYS.addExternalSymbol("URL-STREAM"); // Internal symbols in SYSTEM package. public static final Symbol ALLOCATION = PACKAGE_SYS.addInternalSymbol("ALLOCATION"); public static final Symbol ALLOCATION_CLASS = PACKAGE_SYS.addInternalSymbol("ALLOCATION-CLASS"); public static final Symbol ARGUMENT_PRECEDENCE_ORDER = PACKAGE_SYS.addInternalSymbol("ARGUMENT-PRECEDENCE-ORDER"); public static final Symbol BACKQUOTE_MACRO = PACKAGE_SYS.addInternalSymbol("BACKQUOTE-MACRO"); public static final Symbol CASE_FROB_STREAM = PACKAGE_SYS.addInternalSymbol("CASE-FROB-STREAM"); public static final Symbol CAUSE = PACKAGE_SYS.addInternalSymbol("CAUSE"); public static final Symbol COMMA_MACRO = PACKAGE_SYS.addInternalSymbol("COMMA-MACRO"); public static final Symbol DATUM = PACKAGE_SYS.addInternalSymbol("DATUM"); public static final Symbol DECLARATIONS = PACKAGE_SYS.addInternalSymbol("DECLARATIONS"); public static final Symbol DEFTYPE_DEFINITION = PACKAGE_SYS.addInternalSymbol("DEFTYPE-DEFINITION"); public static final Symbol EXPECTED_TYPE = PACKAGE_SYS.addInternalSymbol("EXPECTED-TYPE"); public static final Symbol FAST_FUNCTION = PACKAGE_SYS.addInternalSymbol("FAST-FUNCTION"); public static final Symbol FORMAT_ARGUMENTS = PACKAGE_SYS.addInternalSymbol("FORMAT-ARGUMENTS"); public static final Symbol FORMAT_CONTROL = PACKAGE_SYS.addInternalSymbol("FORMAT-CONTROL"); public static final Symbol FSET = PACKAGE_SYS.addInternalSymbol("FSET"); public static final Symbol _FUNCTION = PACKAGE_SYS.addInternalSymbol("%FUNCTION"); public static final Symbol FUNCTION_PRELOAD = PACKAGE_SYS.addInternalSymbol("FUNCTION-PRELOAD"); public static final Symbol _GENERIC_FUNCTION = PACKAGE_SYS.addInternalSymbol("%GENERIC-FUNCTION"); public static final Symbol INITARGS = PACKAGE_SYS.addInternalSymbol("INITARGS"); public static final Symbol INITFORM = PACKAGE_SYS.addInternalSymbol("INITFORM"); public static final Symbol INITFUNCTION = PACKAGE_SYS.addInternalSymbol("INITFUNCTION"); public static final Symbol INITIAL_METHODS = PACKAGE_SYS.addInternalSymbol("INITIAL-METHODS"); public static final Symbol INSTANCE = PACKAGE_SYS.addInternalSymbol("INSTANCE"); public static final Symbol JAVA_STACK_FRAME = PACKAGE_SYS.addInternalSymbol("JAVA-STACK-FRAME"); public static final Symbol KEYWORDS = PACKAGE_SYS.addInternalSymbol("KEYWORDS"); public static final Symbol LAMBDA_LIST = PACKAGE_SYS.addInternalSymbol("LAMBDA-LIST"); public static final Symbol LISP_STACK_FRAME = PACKAGE_SYS.addInternalSymbol("LISP-STACK-FRAME"); public static final Symbol LOCATION = PACKAGE_SYS.addInternalSymbol("LOCATION"); public static final Symbol MACROEXPAND_MACRO = PACKAGE_SYS.addInternalSymbol("MACROEXPAND-MACRO"); public static final Symbol MAKE_FUNCTION_PRELOADING_CONTEXT = PACKAGE_SYS.addInternalSymbol("MAKE-FUNCTION-PRELOADING-CONTEXT"); public static final Symbol METHOD_CLASS = PACKAGE_SYS.addInternalSymbol("METHOD-CLASS"); public static final Symbol _METHOD_COMBINATION = PACKAGE_SYS.addInternalSymbol("%METHOD-COMBINATION"); public static final Symbol METHODS = PACKAGE_SYS.addInternalSymbol("METHODS"); public static final Symbol OBJECT = PACKAGE_SYS.addInternalSymbol("OBJECT"); public static final Symbol OPERANDS = PACKAGE_SYS.addInternalSymbol("OPERANDS"); public static final Symbol OPERATION = PACKAGE_SYS.addInternalSymbol("OPERATION"); public static final Symbol OPTIONAL_ARGS = PACKAGE_SYS.addInternalSymbol("OPTIONAL-ARGS"); public static final Symbol OTHER_KEYWORDS_P = PACKAGE_SYS.addInternalSymbol("OTHER-KEYWORDS-P"); public static final Symbol PROXY_PRELOADED_FUNCTION = PACKAGE_SYS.addInternalSymbol("PROXY-PRELOADED-FUNCTION"); public static final Symbol QUALIFIERS = PACKAGE_SYS.addInternalSymbol("QUALIFIERS"); public static final Symbol READERS = PACKAGE_SYS.addInternalSymbol("READERS"); public static final Symbol REQUIRED_ARGS = PACKAGE_SYS.addInternalSymbol("REQUIRED-ARGS"); public static final Symbol READ_RANDOM_STATE = PACKAGE_SYS.addInternalSymbol("READ-RANDOM-STATE"); // DEPRECATED: to be removed with abcl-1.7 public static final Symbol _SOURCE = PACKAGE_SYS.addInternalSymbol("%SOURCE"); public static final Symbol SOCKET_STREAM = PACKAGE_SYS.addInternalSymbol("SOCKET-STREAM"); public static final Symbol SPECIALIZERS = PACKAGE_SYS.addInternalSymbol("SPECIALIZERS"); public static final Symbol STRING_INPUT_STREAM = PACKAGE_SYS.addInternalSymbol("STRING-INPUT-STREAM"); public static final Symbol STRING_OUTPUT_STREAM = PACKAGE_SYS.addInternalSymbol("STRING-OUTPUT-STREAM"); public static final Symbol SYSTEM_STREAM = PACKAGE_SYS.addInternalSymbol("SYSTEM-STREAM"); public static final Symbol STACK_FRAME = PACKAGE_SYS.addInternalSymbol("STACK-FRAME"); public static final Symbol _TYPE = PACKAGE_SYS.addInternalSymbol("%TYPE"); public static final Symbol WRITERS = PACKAGE_SYS.addInternalSymbol("WRITERS"); // CDR6 public static final Symbol _INSPECTOR_HOOK_ = PACKAGE_EXT.addExternalSymbol("*INSPECTOR-HOOK*"); public static final Symbol COMPILER_LET = PACKAGE_LISP.addExternalSymbol("COMPILER-LET"); // THREADS public static final Symbol THREAD = PACKAGE_THREADS.addExternalSymbol("THREAD"); public static final Symbol _THREADING_MODEL = PACKAGE_THREADS.addExternalSymbol("*THREADING-MODEL*"); // JVM public static final Symbol _RESIGNAL_COMPILER_WARINGS_ = PACKAGE_JVM.addExternalSymbol("*RESIGNAL-COMPILER-WARNINGS*"); } abcl-src-1.9.0/src/org/armedbear/lisp/SymbolMacro.java0100644 0000000 0000000 00000003444 14202767264 021316 0ustar000000000 0000000 /* * SymbolMacro.java * * Copyright (C) 2003 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class SymbolMacro extends LispObject { private LispObject expansion; public SymbolMacro(LispObject expansion) { this.expansion = expansion; } public LispObject getExpansion() { return expansion; } } abcl-src-1.9.0/src/org/armedbear/lisp/SynonymStream.java0100644 0000000 0000000 00000014564 14202767264 021724 0ustar000000000 0000000 /* * SynonymStream.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class SynonymStream extends Stream { final Symbol symbol; SynonymStream(Symbol symbol) { super(Symbol.SYNONYM_STREAM); this.symbol = symbol; } @Override public boolean isInputStream() { return checkStream(symbol.symbolValue()).isInputStream(); } @Override public boolean isOutputStream() { return checkStream(symbol.symbolValue()).isOutputStream(); } @Override public boolean isCharacterInputStream() { return checkStream(symbol.symbolValue()).isCharacterInputStream(); } @Override public boolean isBinaryInputStream() { return checkStream(symbol.symbolValue()).isBinaryInputStream(); } @Override public boolean isCharacterOutputStream() { return checkStream(symbol.symbolValue()).isCharacterOutputStream(); } @Override public boolean isBinaryOutputStream() { return checkStream(symbol.symbolValue()).isBinaryOutputStream(); } @Override public LispObject typeOf() { return Symbol.SYNONYM_STREAM; } @Override public LispObject classOf() { return BuiltInClass.SYNONYM_STREAM; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.SYNONYM_STREAM) return T; if (typeSpecifier == BuiltInClass.SYNONYM_STREAM) return T; return super.typep(typeSpecifier); } @Override public LispObject getElementType() { return checkStream(symbol.symbolValue()).getElementType(); } @Override public LispObject listen() { return checkStream(symbol.symbolValue()).listen(); } @Override public LispObject fileLength() { return checkStream(symbol.symbolValue()).fileLength(); } @Override public LispObject fileStringLength(LispObject arg) { return checkStream(symbol.symbolValue()).fileStringLength(arg); } @Override protected int _readChar() throws java.io.IOException { return checkStream(symbol.symbolValue())._readChar(); } @Override protected void _unreadChar(int n) throws java.io.IOException { checkStream(symbol.symbolValue())._unreadChar(n); } @Override protected boolean _charReady() throws java.io.IOException { return checkStream(symbol.symbolValue())._charReady(); } @Override public void _writeChar(char c) { checkStream(symbol.symbolValue())._writeChar(c); } @Override public void _writeChars(char[] chars, int start, int end) { checkStream(symbol.symbolValue())._writeChars(chars, start, end); } @Override public void _writeString(String s) { checkStream(symbol.symbolValue())._writeString(s); } @Override public void _writeLine(String s) { checkStream(symbol.symbolValue())._writeLine(s); } // Reads an 8-bit byte. @Override public int _readByte() { return checkStream(symbol.symbolValue())._readByte(); } // Writes an 8-bit byte. @Override public void _writeByte(int n) { checkStream(symbol.symbolValue())._writeByte(n); } @Override public void _finishOutput() { checkStream(symbol.symbolValue())._finishOutput(); } @Override public void _clearInput() { checkStream(symbol.symbolValue())._clearInput(); } @Override protected long _getFilePosition() { return checkStream(symbol.symbolValue())._getFilePosition(); } @Override protected boolean _setFilePosition(LispObject arg) { return checkStream(symbol.symbolValue())._setFilePosition(arg); } @Override public void _close() { checkStream(symbol.symbolValue())._close(); } @Override public String printObject() { StringBuffer sb = new StringBuffer("SYNONYM-STREAM "); sb.append(symbol.printObject()); return unreadableString(sb.toString()); } // ### make-synonym-stream symbol => synonym-stream private static final Primitive MAKE_SYNONYM_STREAM = new Primitive("make-synonym-stream", "symbol") { @Override public LispObject execute(LispObject arg) { return new SynonymStream(checkSymbol(arg)); } }; // ### synonym-stream-symbol synonym-stream => symbol private static final Primitive SYNONYM_STREAM_STREAMS = new Primitive("synonym-stream-symbol", "synonym-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof SynonymStream) return ((SynonymStream)arg).symbol; return type_error(arg, Symbol.SYNONYM_STREAM); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/ThreadDestroyed.java0100644 0000000 0000000 00000003176 14202767264 022163 0ustar000000000 0000000 /* * ThreadDestroyed.java * * Copyright (C) 2003 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public class ThreadDestroyed extends Error { public ThreadDestroyed() { } } abcl-src-1.9.0/src/org/armedbear/lisp/Throw.java0100644 0000000 0000000 00000004257 14202767264 020175 0ustar000000000 0000000 /* * Throw.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class Throw extends ControlTransfer { public final LispObject tag; private final LispObject result; private final LispObject[] values; public Throw(LispObject tag, LispObject result, LispThread thread) { this.tag = tag; this.result = result; values = thread._values; } public LispObject getResult(LispThread thread) { thread._values = values; return result; } @Override public LispObject getCondition() { return new ControlError("Attempt to throw to the nonexistent tag " + tag.princToString() + "."); } } abcl-src-1.9.0/src/org/armedbear/lisp/Time.java0100644 0000000 0000000 00000013522 14202767264 017763 0ustar000000000 0000000 /* * Time.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.lang.reflect.Method; import java.util.Date; import java.util.TimeZone; public final class Time { // ### %time public static final Primitive _TIME = new pf__time(); private static final class pf__time extends Primitive { pf__time() { super("%time", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject arg) { Cons.setCount(0); long realStart = System.currentTimeMillis(); try { return arg.execute(); } finally { long realElapsed = System.currentTimeMillis() - realStart; long count = Cons.getCount(); Stream out = checkCharacterOutputStream(Symbol.TRACE_OUTPUT.symbolValue()); out.freshLine(); StringBuilder sb = new StringBuilder(); sb.append(String.valueOf((float)realElapsed / 1000)); sb.append(" seconds real time"); sb.append(System.getProperty("line.separator")); sb.append(count); sb.append(" cons cell"); if (count != 1) sb.append('s'); sb.append(System.getProperty("line.separator")); out._writeString(sb.toString()); out._finishOutput(); } } }; // ### get-internal-real-time private static final Primitive GET_INTERNAL_REAL_TIME = new pf_get_internal_real_time(); private static final class pf_get_internal_real_time extends Primitive { pf_get_internal_real_time() { super("get-internal-real-time", ""); } @Override public LispObject execute() { return number(System.currentTimeMillis()); } }; // ### get-internal-run-time private static final Primitive GET_INTERNAL_RUN_TIME = new pf_get_internal_run_time(); private static final class pf_get_internal_run_time extends Primitive { pf_get_internal_run_time() { super("get-internal-run-time", ""); } @Override public LispObject execute() { return number(System.currentTimeMillis()); } }; // ### get-universal-time private static final Primitive GET_UNIVERSAL_TIME = new pf_get_universal_time(); private static final class pf_get_universal_time extends Primitive { pf_get_universal_time() { super("get-universal-time", ""); } @Override public LispObject execute() { return number(System.currentTimeMillis() / 1000 + 2208988800L); } }; // ### default-time-zone => offset daylight-p private static final Primitive DEFAULT_TIME_ZONE = new pf_default_time_zone(); private static final class pf_default_time_zone extends Primitive { pf_default_time_zone() { super("default-time-zone", PACKAGE_SYS, false); } @Override public LispObject execute() { return getTimeZone(System.currentTimeMillis()); } }; private static final LispObject getTimeZone(long unixTimeMillis) { TimeZone tz = TimeZone.getDefault(); //int offset = tz.getOffset(System.currentTimeMillis()); // Classpath hasn't implemented TimeZone.getOffset(long). int rawOffset = tz.getRawOffset(); final boolean inDaylightTime = tz.inDaylightTime(new Date(unixTimeMillis)); if (inDaylightTime) rawOffset += tz.getDSTSavings(); // "Time zone values increase with motion to the west..." // Convert milliseconds to hours. return LispThread.currentThread() .setValues(Fixnum.getInstance(- rawOffset).divideBy(Fixnum.getInstance(3600000)), inDaylightTime ? T : NIL); } // ### get-time-zone universal-time => hours-west daylight-p private static final Primitive GET_TIME_ZONE = new pf_get_time_zone(); @DocString(name="get-time-zone", args="time-in-millis", returns="hours-west daylight-p", doc= "Returns as the first value the timezone difference in hours from the Greenwich meridian for TIME-IN-MILLIS via the Daylight Savings Time assumptions that were in place at the instant's occurance. Returns as the second value a boolean as to whether daylight savings time was in effect at the occurance.") private static final class pf_get_time_zone extends Primitive { pf_get_time_zone() { super("get-time-zone", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { return getTimeZone((arg.longValue() - 2208988800L) * 1000); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/TwoWayStream.java0100644 0000000 0000000 00000015434 14202767264 021477 0ustar000000000 0000000 /* * TwoWayStream.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class TwoWayStream extends Stream { public final Stream in; public final Stream out; public TwoWayStream(Stream in, Stream out) { super(Symbol.TWO_WAY_STREAM); this.in = in; this.out = out; isInputStream = true; isOutputStream = true; } public TwoWayStream(Stream in, Stream out, boolean interactive) { this(in, out); setInteractive(interactive); } @Override public LispObject getElementType() { LispObject itype = in.getElementType(); LispObject otype = out.getElementType(); if (itype.equal(otype)) return itype; return list(Symbol.AND, itype, otype); } public Stream getInputStream() { return in; } public Stream getOutputStream() { return out; } @Override public boolean isCharacterInputStream() { return in.isCharacterInputStream(); } @Override public boolean isBinaryInputStream() { return in.isBinaryInputStream(); } @Override public boolean isCharacterOutputStream() { return out.isCharacterOutputStream(); } @Override public boolean isBinaryOutputStream() { return out.isBinaryOutputStream(); } @Override public LispObject typeOf() { return Symbol.TWO_WAY_STREAM; } @Override public LispObject classOf() { return BuiltInClass.TWO_WAY_STREAM; } @Override public LispObject typep(LispObject type) { if (type == Symbol.TWO_WAY_STREAM) return T; if (type == BuiltInClass.TWO_WAY_STREAM) return T; return super.typep(type); } // Returns -1 at end of file. @Override protected int _readChar() throws java.io.IOException { return in._readChar(); } @Override protected void _unreadChar(int n) throws java.io.IOException { in._unreadChar(n); } @Override protected boolean _charReady() throws java.io.IOException { return in._charReady(); } @Override public void _writeChar(char c) { out._writeChar(c); } @Override public void _writeChars(char[] chars, int start, int end) { out._writeChars(chars, start, end); } @Override public void _writeString(String s) { out._writeString(s); } @Override public void _writeLine(String s) { out._writeLine(s); } // Reads an 8-bit byte. @Override public int _readByte() { return in._readByte(); } // Writes an 8-bit byte. @Override public void _writeByte(int n) { out._writeByte(n); } @Override public void _finishOutput() { out._finishOutput(); } @Override public void _clearInput() { in._clearInput(); } @Override public LispObject listen() { return in.listen(); } @Override public LispObject freshLine() { return out.freshLine(); } @Override public LispObject close(LispObject abort) { // "The effect of CLOSE on a constructed stream is to close the // argument stream only. There is no effect on the constituents of // composite streams." setOpen(false); return T; } @Override public String printObject() { return unreadableString("TWO-WAY-STREAM"); } // ### make-two-way-stream input-stream output-stream => two-way-stream private static final Primitive MAKE_TWO_WAY_STREAM = new Primitive(Symbol.MAKE_TWO_WAY_STREAM, "input-stream output-stream") { @Override public LispObject execute(LispObject first, LispObject second) { final Stream in = checkStream(first); final Stream out = checkStream(second); if (!in.isInputStream()) return type_error(in, list(Symbol.SATISFIES, Symbol.INPUT_STREAM_P)); if (!out.isOutputStream()) return type_error(out, list(Symbol.SATISFIES, Symbol.OUTPUT_STREAM_P)); return new TwoWayStream(in, out); } }; // ### two-way-stream-input-stream two-way-stream => input-stream private static final Primitive TWO_WAY_STREAM_INPUT_STREAM = new Primitive(Symbol.TWO_WAY_STREAM_INPUT_STREAM, "two-way-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof TwoWayStream) return ((TwoWayStream)arg).in; return type_error(arg, Symbol.TWO_WAY_STREAM); } }; // ### two-way-stream-output-stream two-way-stream => output-stream private static final Primitive TWO_WAY_STREAM_OUTPUT_STREAM = new Primitive(Symbol.TWO_WAY_STREAM_OUTPUT_STREAM, "two-way-stream") { @Override public LispObject execute(LispObject arg) { if (arg instanceof TwoWayStream) return ((TwoWayStream)arg).out; return type_error(arg, Symbol.TWO_WAY_STREAM); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/TypeError.java0100644 0000000 0000000 00000014630 14202767264 021021 0ustar000000000 0000000 /* * TypeError.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class TypeError extends LispError { public TypeError() { super(StandardClass.TYPE_ERROR); } protected TypeError(LispClass cls) { super(cls); } public TypeError(LispObject datum, LispObject expectedType) { super(StandardClass.TYPE_ERROR); setDatum(datum); setExpectedType(expectedType); } public TypeError(LispObject initArgs) { super(StandardClass.TYPE_ERROR); initialize(initArgs); } @Override protected void initialize(LispObject initArgs) { super.initialize(initArgs); LispObject datum = null; LispObject expectedType = null; LispObject first, second; while (initArgs != NIL) { first = initArgs.car(); initArgs = initArgs.cdr(); second = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.DATUM) { if (datum == null) datum = second; } else if (first == Keyword.EXPECTED_TYPE) { if (expectedType == null) expectedType = second; } } if (datum != null) setDatum(datum); if (expectedType != null) setExpectedType(expectedType); } public TypeError(String message) { super(StandardClass.TYPE_ERROR); setFormatControl(message); setDatum(NIL); setExpectedType(NIL); } public TypeError(String message, LispObject datum, LispObject expectedType) { super(StandardClass.TYPE_ERROR); setFormatControl(message); setDatum(datum); setExpectedType(expectedType); } @Override public LispObject typeOf() { return Symbol.TYPE_ERROR; } @Override public LispObject classOf() { return StandardClass.TYPE_ERROR; } @Override public LispObject typep(LispObject type) { if (type == Symbol.TYPE_ERROR) return T; if (type == StandardClass.TYPE_ERROR) return T; return super.typep(type); } @Override public String getMessage() { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, T); try { String s = super.getMessage(); if (s != null) return s; final LispObject datum = getDatum(); final LispObject expectedType = getExpectedType(); StringBuilder sb = new StringBuilder(); String name = datum != null ? datum.princToString() : null; String type = null; if (expectedType != null) type = expectedType.princToString(); if (type != null) { if (name != null) { sb.append("The value "); sb.append(name); } else sb.append("Value"); sb.append(" is not of type "); sb.append(type); } else if (name != null) { sb.append("Wrong type: "); sb.append(name); } sb.append('.'); return sb.toString(); } finally { thread.resetSpecialBindings(mark); } } public final LispObject getDatum() { return getInstanceSlotValue(Symbol.DATUM); } private final void setDatum(LispObject datum) { setInstanceSlotValue(Symbol.DATUM, datum); } public final LispObject getExpectedType() { return getInstanceSlotValue(Symbol.EXPECTED_TYPE); } private final void setExpectedType(LispObject expectedType) { setInstanceSlotValue(Symbol.EXPECTED_TYPE, expectedType); } // ### type-error-datum private static final Primitive TYPE_ERROR_DATUM = new Primitive(Symbol.TYPE_ERROR_DATUM, "condition") { @Override public LispObject execute(LispObject arg) { if (arg.typep(Symbol.TYPE_ERROR) == NIL) { return type_error(arg, Symbol.TYPE_ERROR); } final StandardObject obj = (StandardObject) arg; return obj.getInstanceSlotValue(Symbol.DATUM); } }; // ### type-error-expected-type private static final Primitive TYPE_ERROR_EXPECTED_TYPE = new Primitive(Symbol.TYPE_ERROR_EXPECTED_TYPE, "condition") { @Override public LispObject execute(LispObject arg) { if (arg.typep(Symbol.TYPE_ERROR) == NIL) { return type_error(arg, Symbol.TYPE_ERROR); } final StandardObject obj = (StandardObject) arg; return obj.getInstanceSlotValue(Symbol.EXPECTED_TYPE); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/URLPathname.java0100644 0000000 0000000 00000036555 14223403213 021200 0ustar000000000 0000000 /* * URLPathname.java * * Copyright (C) 2020 @easye * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.net.URL; import java.net.URLConnection; import java.net.URI; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.text.MessageFormat; public class URLPathname extends Pathname { static public final Symbol SCHEME = internKeyword("SCHEME"); static public final Symbol AUTHORITY = internKeyword("AUTHORITY"); static public final Symbol QUERY = internKeyword("QUERY"); static public final Symbol FRAGMENT = internKeyword("FRAGMENT"); protected URLPathname() {} public static URLPathname create() { return new URLPathname(); } public static URLPathname create(Pathname p) { if (p instanceof URLPathname) { URLPathname result = new URLPathname(); result.copyFrom(p); return result; } return (URLPathname)createFromFile((Pathname)p); } public static URLPathname create(URL url) { return URLPathname.create(url.toString()); } public static URLPathname create(URI uri) { return URLPathname.create(uri.toString()); } static public final LispObject FILE = new SimpleString("file"); public static URLPathname createFromFile(Pathname p) { URLPathname result = new URLPathname(); result.copyFrom(p); LispObject scheme = NIL; scheme = scheme.push(FILE).push(SCHEME); result.setHost(scheme); return result; } public static URLPathname create(String s) { if (!isValidURL(s)) { parse_error("Cannot form a PATHNAME-URL from " + s); } if (s.startsWith(JarPathname.JAR_URI_PREFIX)) { return JarPathname.create(s); } URLPathname result = new URLPathname(); URL url = null; try { url = new URL(s); } catch (MalformedURLException e) { parse_error("Malformed URL in namestring '" + s + "': " + e.toString()); return (URLPathname) UNREACHED; } String scheme = url.getProtocol(); if (scheme.equals("file")) { URI uri = null; try { uri = new URI(s); } catch (URISyntaxException ex) { parse_error("Improper URI syntax for " + "'" + url.toString() + "'" + ": " + ex.toString()); return (URLPathname)UNREACHED; } String uriPath = uri.getPath(); if (null == uriPath) { // Under Windows, deal with pathnames containing // devices expressed as "file:z:/foo/path" uriPath = uri.getSchemeSpecificPart(); if (uriPath == null || uriPath.equals("")) { parse_error("The namestring URI has no path: " + uri); return (URLPathname)UNREACHED; } } final File file = new File(uriPath); String path = file.getPath(); if (uri.toString().endsWith("/") && !path.endsWith("/")) { path += "/"; } final Pathname p = (Pathname)Pathname.create(path); LispObject host = NIL.push(FILE).push(SCHEME); result .setHost(host) .setDevice(p.getDevice()) .setDirectory(p.getDirectory()) .setName(p.getName()) .setType(p.getType()) .setVersion(p.getVersion()); return result; } Debug.assertTrue(scheme != null); URI uri = null; try { uri = url.toURI().normalize(); } catch (URISyntaxException e) { parse_error("Couldn't form URI from " + "'" + url + "'" + " because: " + e); return (URLPathname)UNREACHED; } String authority = uri.getAuthority(); if (authority == null) { authority = url.getAuthority(); } LispObject host = NIL; host = host.push(SCHEME).push(new SimpleString(scheme)); if (authority != null) { host = host.push(AUTHORITY).push(new SimpleString(authority)); } String query = uri.getRawQuery(); if (query != null) { host = host.push(QUERY).push(new SimpleString(query)); } String fragment = uri.getRawFragment(); if (fragment != null) { host = host.push(FRAGMENT).push(new SimpleString(fragment)); } host = host.nreverse(); result.setHost(host); // URI encode necessary characters String path = uri.getRawPath(); if (path == null) { path = ""; } Pathname p = (Pathname)Pathname.create(path != null ? path : ""); result .setDirectory(p.getDirectory()) .setName(p.getName()) .setType(p.getType()); return result; } public URI toURI() { String uriString = getNamestringAsURL(); try { URI uri = new URI(uriString); return uri; } catch (URISyntaxException eo) { return null; } } public URL toURL() { URI uri = toURI(); try { if (uri != null) { return uri.toURL(); } } catch (MalformedURLException e) { } return null; } public File getFile() { if (!hasExplicitFile(this)) { return null; // TODO signal that this is not possible? } URI uri = toURI(); if (uri == null) { return null; } File result = new File(uri); return result; } static public boolean isFile(Pathname p) { LispObject scheme = Symbol.GETF.execute(p.getHost(), SCHEME, NIL); if (scheme.equals(NIL) || hasExplicitFile(p)) { return true; } return false; } static public boolean hasExplicitFile(Pathname p) { if (!p.getHost().listp()) { return false; } LispObject scheme = Symbol.GETF.execute(p.getHost(), SCHEME, NIL); return scheme.equalp(FILE); } public String getNamestring() { StringBuilder sb = new StringBuilder(); return getNamestring(sb); } public String getNamestring(StringBuilder sb) { LispObject scheme = Symbol.GETF.execute(getHost(), SCHEME, NIL); LispObject authority = Symbol.GETF.execute(getHost(), AUTHORITY, NIL); // A scheme of NIL is implicitly "file:", for which we don't emit // as part of the usual namestring. getNamestringAsURI() should // emit the 'file:' string boolean percentEncode = true; if (scheme.equals(NIL)) { percentEncode = false; } else { sb.append(scheme.getStringValue()); sb.append(":"); if (authority != NIL) { sb.append("//"); sb.append(authority.getStringValue()); } else if (scheme.equalp(FILE)) { sb.append("//"); } } // if (Utilities.isPlatformWindows && getDevice() instanceof SimpleString) { sb.append("/") .append(getDevice().getStringValue()) .append(":"); } String directoryNamestring = getDirectoryNamestring(); if (percentEncode) { directoryNamestring = uriEncode(directoryNamestring); } sb.append(directoryNamestring); // Use the output of Pathname Pathname p = new Pathname(); p.copyFrom(this) .setHost(NIL) .setDevice(NIL) .setDirectory(NIL); String nameTypeVersion = p.getNamestring(); if (percentEncode) { nameTypeVersion = uriEncode(nameTypeVersion); } sb.append(nameTypeVersion); LispObject o = Symbol.GETF.execute(getHost(), QUERY, NIL); if (o != NIL) { sb.append("?") .append(uriEncode(o.getStringValue())); } o = Symbol.GETF.execute(getHost(), FRAGMENT, NIL); if (o != NIL) { sb.append("#") .append(uriEncode(o.getStringValue())); } return sb.toString(); } // We need our "own" rules for outputting a URL // 1. For DOS drive letters // 2. For relative "file" schemas (??) public String getNamestringAsURL() { LispObject schemeProperty = Symbol.GETF.execute(getHost(), SCHEME, NIL); LispObject authorityProperty = Symbol.GETF.execute(getHost(), AUTHORITY, NIL); LispObject queryProperty = Symbol.GETF.execute(getHost(), QUERY, NIL); LispObject fragmentProperty = Symbol.GETF.execute(getHost(), FRAGMENT, NIL); String scheme; String authority = null; if (!schemeProperty.equals(NIL)) { scheme = schemeProperty.getStringValue(); if (!authorityProperty.equals(NIL)) { authority = authorityProperty.getStringValue(); } } else { scheme = "file"; } String directory = getDirectoryNamestring(); String file = ""; LispObject fileNamestring = Symbol.FILE_NAMESTRING.execute(this); if (!fileNamestring.equals(NIL)) { file = fileNamestring.getStringValue(); } String path = ""; if (!directory.equals("")) { if (Utilities.isPlatformWindows && getDevice() instanceof SimpleString) { path = getDevice().getStringValue() + ":" + directory + file; } else { path = directory + file; } } else { path = file; } path = uriEncode(path); String query = null; if (!queryProperty.equals(NIL)) { query = queryProperty.getStringValue(); } String fragment = null; if (!fragmentProperty.equals(NIL)) { fragment = fragmentProperty.getStringValue(); } StringBuffer result = new StringBuffer(scheme); result.append(":"); result.append("//"); if (authority != null) { result.append(authority); } if (!path.startsWith("/")) { result.append("/"); } result.append(path); if (query != null) { result.append("?").append(query); } if (fragment != null) { result.append("#").append(fragment); } return result.toString(); } public LispObject typeOf() { return Symbol.URL_PATHNAME; } @Override public LispObject classOf() { return BuiltInClass.URL_PATHNAME; } public static LispObject truename(Pathname p, boolean errorIfDoesNotExist) { URLPathname pathnameURL = (URLPathname)URLPathname.createFromFile(p); return URLPathname.truename(pathnameURL, errorIfDoesNotExist); } public static LispObject truename(URLPathname p, boolean errorIfDoesNotExist) { if (p.getHost().equals(NIL) || hasExplicitFile(p)) { LispObject fileTruename = Pathname.truename(p, errorIfDoesNotExist); if (fileTruename.equals(NIL)) { return NIL; } if (!(fileTruename instanceof URLPathname)) { URLPathname urlTruename = URLPathname.createFromFile((Pathname)fileTruename); return urlTruename; } return fileTruename; } if (p.getInputStream() != null) { // If there is no type, query or fragment, we check to // see if there is URL available "underneath". if (p.getName() != NIL && p.getType() == NIL && Symbol.GETF.execute(p.getHost(), URLPathname.QUERY, NIL) == NIL && Symbol.GETF.execute(p.getHost(), URLPathname.FRAGMENT, NIL) == NIL) { if (p.getInputStream() != null) { return p; } } return p; } return Pathname.doTruenameExit(p, errorIfDoesNotExist); } public InputStream getInputStream() { InputStream result = null; if (URLPathname.isFile(this)) { Pathname p = new Pathname(); p.copyFrom(this) .setHost(NIL); return p.getInputStream(); } if (URLPathname.isFile(this)) { Pathname p = new Pathname(); p.copyFrom(this) .setHost(NIL); return p.getInputStream(); } URL url = this.toURL(); try { result = url.openStream(); } catch (IOException e) { Debug.warn("Failed to get InputStream from " + "'" + getNamestring() + "'" + ": " + e); } return result; } URLConnection getURLConnection() { Debug.assertTrue(isURL()); URL url = this.toURL(); URLConnection result = null; try { result = url.openConnection(); } catch (IOException e) { error(new FileError("Failed to open URL connection.", this)); } return result; } public long getLastModified() { return getURLConnection().getLastModified(); } @DocString(name="uri-decode", args="string", returns="string", doc="Decode STRING percent escape sequences in the manner of URI encodings.") private static final Primitive URI_DECODE = new pf_uri_decode(); private static final class pf_uri_decode extends Primitive { pf_uri_decode() { super("uri-decode", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { if (!(arg instanceof AbstractString)) { return type_error(arg, Symbol.STRING); } String result = uriDecode(((AbstractString)arg).toString()); return new SimpleString(result); } }; static String uriDecode(String s) { try { URI uri = new URI("file://foo?" + s); return uri.getQuery(); } catch (URISyntaxException e) {} return null; // Error } @DocString(name="uri-encode", args="string", returns="string", doc="Encode percent escape sequences in the manner of URI encodings.") private static final Primitive URI_ENCODE = new pf_uri_encode(); private static final class pf_uri_encode extends Primitive { pf_uri_encode() { super("uri-encode", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { if (!(arg instanceof AbstractString)) { return type_error(arg, Symbol.STRING); } String result = uriEncode(((AbstractString)arg).toString()); return new SimpleString(result); } }; static String uriEncode(String s) { // The constructor we use here only allows absolute paths, so // we manipulate the input and output correspondingly. String u; if (!s.startsWith("/")) { u = "/" + s; } else { u = new String(s); } try { URI uri = new URI("file", "", u, ""); String result = uri.getRawPath(); if (!s.startsWith("/")) { return result.substring(1); } return result; } catch (URISyntaxException e) { Debug.assertTrue(false); } return null; // Error } } abcl-src-1.9.0/src/org/armedbear/lisp/URLStream.java0100644 0000000 0000000 00000012005 14202767264 020676 0ustar000000000 0000000 /* * URLStream.java * * Copyright (C) 2010 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.BufferedReader; /** * Stream interface for a URL. * * Currently only supports reading from the stream. */ public final class URLStream extends Stream { private final Pathname pathname; private final InputStream input; private final Reader reader; private final int bytesPerUnit; public URLStream(Pathname pathname, LispObject elementType, LispObject direction, LispObject ifExists, LispObject format) throws IOException { super(Symbol.URL_STREAM); Debug.assertTrue(direction == Keyword.INPUT); isInputStream = true; super.setExternalFormat(format); this.pathname = pathname; this.elementType = elementType; this.input = pathname.getInputStream(); if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) { isCharacterStream = true; bytesPerUnit = 1; InputStreamReader isr = new InputStreamReader(input); this.reader = (Reader) new BufferedReader(isr); initAsCharacterInputStream(this.reader); } else { isBinaryStream = true; int width = Fixnum.getValue(elementType.cadr()); bytesPerUnit = width / 8; this.reader = null; initAsBinaryInputStream(this.input); } } @Override public LispObject typeOf() { return Symbol.URL_STREAM; } @Override public LispObject classOf() { return BuiltInClass.URL_STREAM; } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.URL_STREAM) return T; if (typeSpecifier == BuiltInClass.URL_STREAM) return T; return super.typep(typeSpecifier); } @Override public void setExternalFormat(LispObject format) { super.setExternalFormat(format); } public Pathname getPathname() { return pathname; } // unused 20200418 ME public Reader getReader() { return reader; } /** * Accessing the underlying java.io.InputStream can be helpful * when utlizing Java-side frameworks like Apache Jena built on * the java.io abstractions. State should only be mutated if you * know what you are doing. * * c.f. **/ public InputStream getInputStream() { return input; } // unused 20200418 ME public int getBytesPerUnit() { return bytesPerUnit; } @Override public void _close() { try { if (input != null) { input.close(); } if (reader != null) { reader.close(); } setOpen(false); } catch (IOException e) { error(new StreamError(this, e)); } } @Override public String printObject() { StringBuffer sb = new StringBuffer(); sb.append(Symbol.URL_STREAM.printObject()); String namestring = pathname.getNamestring(); if (namestring != null) { sb.append(" "); sb.append(namestring); } return unreadableString(sb.toString()); } } abcl-src-1.9.0/src/org/armedbear/lisp/UnboundSlot.java0100644 0000000 0000000 00000006646 14202767264 021352 0ustar000000000 0000000 /* * UnboundSlot.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class UnboundSlot extends CellError { public UnboundSlot(LispObject initArgs) { super(StandardClass.UNBOUND_SLOT); initialize(initArgs); } @Override protected void initialize(LispObject initArgs) { super.initialize(initArgs); while (initArgs != NIL) { LispObject first = initArgs.car(); initArgs = initArgs.cdr(); if (first == Keyword.INSTANCE) { setInstance(initArgs.car()); break; } initArgs = initArgs.cdr(); } } public LispObject getInstance() { return getInstanceSlotValue(Symbol.INSTANCE); } private void setInstance(LispObject instance) { setInstanceSlotValue(Symbol.INSTANCE, instance); } @Override public String getMessage() { final LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, T); try { StringBuilder sb = new StringBuilder("The slot "); sb.append(getCellName().princToString()); sb.append(" is unbound in the object "); sb.append(getInstance().princToString()); sb.append('.'); return sb.toString(); } finally { thread.resetSpecialBindings(mark); } } @Override public LispObject typeOf() { return Symbol.UNBOUND_SLOT; } @Override public LispObject classOf() { return StandardClass.UNBOUND_SLOT; } @Override public LispObject typep(LispObject type) { if (type == Symbol.UNBOUND_SLOT) return T; if (type == StandardClass.UNBOUND_SLOT) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/UnboundVariable.java0100644 0000000 0000000 00000005331 14202767264 022144 0ustar000000000 0000000 /* * UnboundVariable.java * * Copyright (C) 2002-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class UnboundVariable extends CellError { // obj is either the unbound variable itself or an initArgs list. public UnboundVariable(LispObject obj) { super(StandardClass.UNBOUND_VARIABLE); if (obj instanceof Cons) initialize(obj); else setCellName(obj); } @Override public String getMessage() { LispThread thread = LispThread.currentThread(); final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol.PRINT_ESCAPE, T); StringBuffer sb = new StringBuffer("The variable "); try { sb.append(getCellName().princToString()); } finally { thread.resetSpecialBindings(mark); } sb.append(" is unbound."); return sb.toString(); } @Override public LispObject typeOf() { return Symbol.UNBOUND_VARIABLE; } @Override public LispObject classOf() { return StandardClass.UNBOUND_VARIABLE; } @Override public LispObject typep(LispObject type) { if (type == Symbol.UNBOUND_VARIABLE) return T; if (type == StandardClass.UNBOUND_VARIABLE) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/UndefinedFunction.java0100644 0000000 0000000 00000004772 14202767264 022503 0ustar000000000 0000000 /* * UndefinedFunction.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class UndefinedFunction extends CellError { // obj is either the name of the undefined function or an initArgs list. public UndefinedFunction(LispObject obj) { super(StandardClass.UNDEFINED_FUNCTION); if (obj instanceof Cons) initialize(obj); else setCellName(obj); } @Override public LispObject typeOf() { return Symbol.UNDEFINED_FUNCTION; } @Override public LispObject classOf() { return StandardClass.UNDEFINED_FUNCTION; } @Override public LispObject typep(LispObject type) { if (type == Symbol.UNDEFINED_FUNCTION) return T; if (type == StandardClass.UNDEFINED_FUNCTION) return T; return super.typep(type); } @Override public String getMessage() { StringBuilder sb = new StringBuilder("The function "); sb.append(getCellName().princToString()); sb.append(" is undefined."); return sb.toString(); } } abcl-src-1.9.0/src/org/armedbear/lisp/UpcaseStream.java0100644 0000000 0000000 00000003777 14202767264 021474 0ustar000000000 0000000 /* * UpcaseStream.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; public final class UpcaseStream extends CaseFrobStream { public UpcaseStream(Stream target) { super(target); } @Override public void _writeChar(char c) { target._writeChar(LispCharacter.toUpperCase(c)); } @Override public void _writeString(String s) { target._writeString(s.toUpperCase()); } @Override public void _writeLine(String s) { target._writeLine(s.toUpperCase()); } } abcl-src-1.9.0/src/org/armedbear/lisp/Utilities.java0100644 0000000 0000000 00000006765 14202767264 021053 0ustar000000000 0000000 /* * Utilities.java * * Copyright (C) 2003-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; public final class Utilities { public static final boolean isPlatformUnix; public static final boolean isPlatformWindows; static { String osName = System.getProperty("os.name"); isPlatformUnix = osName.startsWith("Linux") || osName.startsWith("Mac OS X") || osName.startsWith("Darwin") || osName.startsWith("Solaris") || osName.startsWith("SunOS") || osName.startsWith("AIX") || osName.startsWith("FreeBSD") || osName.startsWith("OpenBSD") || osName.startsWith("NetBSD"); isPlatformWindows = osName.startsWith("Windows"); } public static boolean isFilenameAbsolute(String filename) { final int length = filename.length(); if (length > 0) { char c0 = filename.charAt(0); if (c0 == '\\' || c0 == '/') return true; if (length > 2) { if (isPlatformWindows) { // Check for drive letter. char c1 = filename.charAt(1); if (c1 == ':') { if (c0 >= 'a' && c0 <= 'z') return true; if (c0 >= 'A' && c0 <= 'Z') return true; } } else { // Unix. if (filename.equals("~") || filename.startsWith("~/")) return true; } } } return false; } static String escapeFormat(String s) { return s.replace("~", "~~"); } } abcl-src-1.9.0/src/org/armedbear/lisp/Version.java0100644 0000000 0000000 00000004446 14242627550 020514 0ustar000000000 0000000 /* * Version.java * * Copyright (C) 2003-2008 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; public final class Version { private Version() {} static final String baseVersion = "1.9.0"; static void init() { try { InputStream input = Version.class.getResourceAsStream("version"); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String v = reader.readLine().trim(); version = v; } catch (Throwable t) { version = baseVersion; } } static String version = ""; public synchronized static String getVersion() { if ("".equals(version)) { init(); } return version; } public static void main(String args[]) { System.out.println(Version.getVersion()); } } abcl-src-1.9.0/src/org/armedbear/lisp/Warning.java0100644 0000000 0000000 00000004210 14202767264 020464 0ustar000000000 0000000 /* * Warning.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class Warning extends Condition { protected Warning() { } public Warning(LispObject initArgs) { super(initArgs); } @Override public LispObject typeOf() { return Symbol.WARNING; } @Override public LispObject classOf() { return StandardClass.WARNING; } @Override public LispObject typep(LispObject type) { if (type == Symbol.WARNING) return T; if (type == StandardClass.WARNING) return T; return super.typep(type); } } abcl-src-1.9.0/src/org/armedbear/lisp/WeakHashTable.java0100644 0000000 0000000 00000072450 14202767264 021535 0ustar000000000 0000000 /* * HashTable.java * * Copyright (C) 2002-2007 Peter Graves * Copyright (C) 2010 Erik Huelsmann * Copyright (C) 2011 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.lang.ref.WeakReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; // ??? Replace standard Hashtable when this code is working; maybe not // because we have additional places for locking here. // // We can't simply extend HashTable as the methods returning HashEntry // are referring to different types as HashEntry is internal to this // class. // // XXX individuals are invited to figure out how to use Java generics // to simplify/beautify things here, but I couldn't get the // WeakHashTable type to be parameterized on an enclosed type. public class WeakHashTable extends LispObject implements org.armedbear.lisp.protocol.Hashtable { protected static final float loadFactor = 0.75f; protected final LispObject rehashSize; protected final LispObject rehashThreshold; /** * The rounded product of the capacity and the load factor. When the number * of elements exceeds the threshold, the implementation calls rehash(). */ protected int threshold; /** Array containing the actual key-value mappings. */ @SuppressWarnings("VolatileArrayField") protected volatile HashEntry[] buckets; /** The actual current number of key-value pairs. */ protected volatile int count; final Comparator comparator; final private ReentrantLock lock = new ReentrantLock(); HashEntry bucketType; final LispObject weakness; private WeakHashTable(Comparator c, int size, LispObject rehashSize, LispObject rehashThreshold, LispObject weakness) { this.rehashSize = rehashSize; this.rehashThreshold = rehashThreshold; bucketType = null; this.weakness = weakness; if (weakness.equals(Keyword.KEY)) { bucketType = this.new HashEntryWeakKey(); } else if (weakness.equals(Keyword.VALUE)) { bucketType = this.new HashEntryWeakValue(); } else if (weakness.equals(Keyword.KEY_AND_VALUE)) { bucketType = this.new HashEntryWeakKeyAndValue(); } else if (weakness.equals(Keyword.KEY_OR_VALUE)) { bucketType = this.new HashEntryWeakKeyOrValue(); } else { // We handle this check in the wrapping Lisp code. assert false : "Bad weakness argument to WeakHashTable type constructor."; } buckets = bucketType.makeArray(size); threshold = (int) (size * loadFactor); comparator = c; } protected static int calculateInitialCapacity(int size) { int capacity = 1; while (capacity < size) { capacity <<= 1; } return capacity; } // XXX only WEAK references types are implemented for WeakHashTable. // XXX This enum is currently unused in this code enum ReferenceType { NORMAL, WEAK, SOFT } // XXX This enum is currently unused in this code enum WeaknessType { /** KEY means that the key of an entry must be live to guarantee that the entry is preserved. */ KEY, /** VALUE means that the value of an entry must be live to guarantee that the entry is preserved. */ VALUE, /** KEY-AND-VALUE means that both the key and the value must be live to guarantee that the entry is preserved. */ KEY_AND_VALUE, /** KEY-OR-VALUE means that either the key or the value must be live to guarantee that the entry is preserved. */ KEY_OR_VALUE } public static WeakHashTable newEqHashTable(int size, LispObject rehashSize, LispObject rehashThreshold, LispObject weakness) { return new WeakHashTable(new Comparator(), size, rehashSize, rehashThreshold, weakness); } public static WeakHashTable newEqlHashTable(int size, LispObject rehashSize, LispObject rehashThreshold, LispObject weakness) { return new WeakHashTable(new EqlComparator(), size, rehashSize, rehashThreshold, weakness); } public static WeakHashTable newEqualHashTable(int size, LispObject rehashSize, LispObject rehashThreshold, LispObject weakness) { return new WeakHashTable(new EqualComparator(), size, rehashSize, rehashThreshold, weakness); } public static WeakHashTable newEqualpHashTable(int size, LispObject rehashSize, LispObject rehashThreshold, LispObject weakness) { return new WeakHashTable(new EqualpComparator(), size, rehashSize, rehashThreshold, weakness); } public final LispObject getRehashSize() { return rehashSize; } public final LispObject getRehashThreshold() { return rehashThreshold; } /** How many hash buckets exist in the underlying data structure. */ public int getSize() { HashEntry[] b = getTable(); return b.length; } /** Number of entries stored in the hash buckets. */ public int getCount() { getTable(); // To force gc on entries return count; } @Override public LispObject typeOf() { return Symbol.HASH_TABLE; } @Override public LispObject classOf() { return BuiltInClass.HASH_TABLE; } @Override public LispObject typep(LispObject type) { if (type == Symbol.HASH_TABLE) { return T; } if (type == BuiltInClass.HASH_TABLE) { return T; } return super.typep(type); } // XXX Not thread-safe as hash entries can be GCd "out from under" // the invoking thread. But the HashTable implementation // seemingly suffers from the same problem if entries are // removed/added while this method executes. @Override public boolean equalp(LispObject obj) { if (this == obj) { return true; } if (obj instanceof WeakHashTable) { WeakHashTable ht = (WeakHashTable) obj; if (count != ht.count) { return false; } if (getTest() != ht.getTest()) { return false; } LispObject entries = ENTRIES(); while (entries != NIL) { LispObject entry = entries.car(); LispObject key = entry.car(); LispObject value = entry.cdr(); if (!value.equalp(ht.get(key))) { return false; } entries = entries.cdr(); } return true; } return false; } @Override public LispObject getParts() { HashEntry[] b = getTable();; LispObject parts = NIL; for (int i = 0; i < b.length; i++) { HashEntry e = b[i]; while (e != null) { LispObject key = e.getKey(); LispObject value = e.getValue(); if (key != null && value != null) { parts = parts.push(new Cons("KEY [bucket " + i + "]", key)); parts = parts.push(new Cons("VALUE", value)); } else { assert false : "Dangling hash entries encountered."; } e = e.getNext(); } } return parts.nreverse(); } public void clear() { lock.lock(); try { buckets = bucketType.makeArray(buckets.length); count = 0; while (queue.poll() != null) ; } finally { lock.unlock(); } } // gethash key hash-table &optional default => value, present-p public LispObject gethash(LispObject key) { LispObject value = get(key); final LispObject presentp; if (value == null) { value = presentp = NIL; } else { presentp = T; } return LispThread.currentThread().setValues(value, presentp); } // gethash key hash-table &optional default => value, present-p public LispObject gethash(LispObject key, LispObject defaultValue) { LispObject value = get(key); final LispObject presentp; if (value == null) { value = defaultValue; presentp = NIL; } else { presentp = T; } return LispThread.currentThread().setValues(value, presentp); } public LispObject gethash1(LispObject key) { final LispObject value = get(key); return value != null ? value : NIL; } public LispObject puthash(LispObject key, LispObject newValue) { put(key, newValue); return newValue; } // remhash key hash-table => generalized-boolean public LispObject remhash(LispObject key) { // A value in a Lisp hash table can never be null, so... return remove(key) != null ? T : NIL; } @Override public String printObject() { if (Symbol.PRINT_READABLY.symbolValue(LispThread.currentThread()) != NIL) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); return null; // Not reached. } StringBuilder sb = new StringBuilder(getTest().princToString()); sb.append(' '); sb.append(Symbol.HASH_TABLE.princToString()); sb.append(' '); if (bucketType instanceof HashEntryWeakKey) { sb.append("WEAKNESS :KEY"); } else if (bucketType instanceof HashEntryWeakValue) { sb.append("WEAKNESS :VALUE"); } else if (bucketType instanceof HashEntryWeakKeyAndValue) { sb.append("WEAKNESS :KEY-AND-VALUE"); } else if (bucketType instanceof HashEntryWeakKeyOrValue) { sb.append("WEAKNESS :KEY-OR-VALUE"); } sb.append(' '); sb.append(count); if (count == 1) { sb.append(" entry"); } else { sb.append(" entries"); } sb.append(", "); sb.append(buckets.length); sb.append(" buckets"); return unreadableString(sb.toString()); } public Symbol getTest() { return comparator.getTest(); } public LispObject getWeakness() { return weakness; } HashEntry[] getTable() { lock.lock(); try { bucketType.expungeQueue(); return buckets; } finally { lock.unlock(); } } protected HashEntry getEntry(LispObject key) { HashEntry[] b = getTable(); int hash = comparator.hash(key); HashEntry e = b[hash & (b.length - 1)]; while (e != null) { if (hash == e.getHash() && (key == e.getKey() || comparator.keysEqual(key, e.getKey()))) { return e; } e = e.getNext(); } return null; } public LispObject get(LispObject key) { HashEntry e = getEntry(key); LispObject v = (e == null) ? null : e.getValue(); if (e == null || v != null) { return v; } return e.getValue(); } public void put(LispObject key, LispObject value) { HashEntry e = getEntry(key); if (e != null) { e.setValue(value); } else { // Not found. We need to add a new entry. if (++count > threshold) { rehash(); } int hash = comparator.hash(key); int index = hash & (buckets.length - 1); buckets[index] = bucketType.makeInstance(key, hash, value, buckets[index], index); } } public LispObject remove(LispObject key) { lock.lock(); try { bucketType.expungeQueue(); int index = comparator.hash(key) & (buckets.length - 1); HashEntry e = buckets[index]; HashEntry last = null; while (e != null) { LispObject entryKey = e.getKey(); if (entryKey == null) { e.clear(); if (last == null) { buckets[index] = e.getNext(); } else { last.setNext(e.getNext()); } --count; } else if (comparator.keysEqual(key, entryKey)) { e.clear(); if (last == null) { buckets[index] = e.getNext(); } else { last.setNext(e.getNext()); } --count; return e.getValue(); } last = e; e = e.getNext(); } return null; } finally { lock.unlock(); } } /** * Internal removal of the HashEntry associated with the * Reference used for a hashtables with soft/weak references. */ private void remove(Reference ref) { assert lock.isHeldByCurrentThread(); HashEntry entry = entryLookup.get(ref); // assert entry != null // : "Failed to find hash entry for reference."; if (entry == null) { return; // XXX how does this happen? } int index = entry.getSlot(); HashEntry e = this.buckets[index]; HashEntry last = null; while (e != null) { if (e.equals(entry)) { if (last == null) { this.buckets[index] = e.getNext(); } else { last.setNext(e.getNext()); } --count; break; } last = e; e = e.getNext(); } } protected void rehash() { lock.lock(); try { final int newCapacity = buckets.length * 2; threshold = (int) (newCapacity * loadFactor); int mask = newCapacity - 1; HashEntry[] newBuckets = bucketType.makeArray(newCapacity); for (int i = buckets.length; i-- > 0;) { HashEntry e = buckets[i]; while (e != null) { LispObject key = e.getKey(); LispObject value = e.getValue(); if (key == null || value == null) { e.clear(); e = e.getNext(); continue; } final int index = comparator.hash(key) & mask; e.clear(); newBuckets[index] = bucketType.makeInstance(key, e.getHash(), value, newBuckets[index], index); e = e.getNext(); } } buckets = newBuckets; } finally { lock.unlock(); } } @Deprecated public LispObject ENTRIES() { return getEntries(); } /** @returns A list of (key . value) pairs. */ public LispObject getEntries() { HashEntry[] b = getTable(); LispObject list = NIL; for (int i = b.length; i-- > 0;) { HashEntry e = b[i]; while (e != null) { LispObject key = e.getKey(); LispObject value = e.getValue(); if (key != null && value != null) { list = new Cons(new Cons(key, value), list); } else { assert false : "ENTRIES encounted dangling entries."; } e = e.getNext(); } } return list; } public LispObject MAPHASH(LispObject function) { HashEntry[] b = getTable(); for (int i = b.length; i-- > 0;) { HashEntry e = b[i]; while (e != null) { LispObject key = e.getKey(); LispObject value = e.getValue(); if (key != null && value != null) { function.execute(key, value); } else { assert false : "MAPHASH encountered dangling entries."; } e = e.getNext(); } } return NIL; } protected static class Comparator { Symbol getTest() { return Symbol.EQ; } boolean keysEqual(LispObject key1, LispObject key2) { return key1 == key2; } int hash(LispObject key) { return key.sxhash(); } } protected static class EqlComparator extends Comparator { @Override Symbol getTest() { return Symbol.EQL; } @Override boolean keysEqual(LispObject key1, LispObject key2) { return key1.eql(key2); } } protected static class EqualComparator extends Comparator { @Override Symbol getTest() { return Symbol.EQUAL; } @Override boolean keysEqual(LispObject key1, LispObject key2) { return key1.equal(key2); } } protected static class EqualpComparator extends Comparator { @Override Symbol getTest() { return Symbol.EQUALP; } @Override boolean keysEqual(LispObject key1, LispObject key2) { return key1.equalp(key2); } @Override int hash(LispObject key) { return key.psxhash(); } } abstract class HashEntry { LispObject key; int hash; volatile LispObject value; HashEntry next; int slot; public HashEntry() {}; public HashEntry(LispObject key, int hash, LispObject value, HashEntry next, int slot) { this.key = key; this.hash = hash; this.value = value; this.next = next; this.slot = slot; } public LispObject getKey() { return key; } public void setKey(LispObject key) { this.key = key; } public int getHash() { return hash; } public void setHash(int hash) { this.hash = hash; } public LispObject getValue() { return value; } public void setValue(LispObject value) { this.value = value; } public HashEntry getNext() { return next; } public void setNext(HashEntry next) { this.next = next; } public int getSlot() { return slot; } public void setSlot(int slot) { this.slot = slot; } abstract HashEntry[] makeArray(int length); abstract HashEntry makeInstance(LispObject key, int hash, LispObject value, HashEntry next, int slot); abstract void expungeQueue(); abstract void clear(); } ReferenceQueue queue = new ReferenceQueue(); Map entryLookup = Collections.synchronizedMap(new HashMap()); class HashEntryWeakKey extends HashEntry { private WeakReference key; public HashEntryWeakKey() {}; public HashEntryWeakKey(LispObject key, int hash, LispObject value, HashEntry next, int slot) { this.hash = hash; this.value = value; this.next = next; this.slot = slot; this.key = new WeakReference(key, queue); entryLookup.put(this.key, this); } public LispObject getKey() { return key.get(); } public void setKey(LispObject key) { java.lang.ref.WeakReference old = this.key; old.clear(); this.key = new WeakReference(key, queue); entryLookup.put(this.key, this); } HashEntryWeakKey[] makeArray(int length) { return new HashEntryWeakKey[length]; } HashEntry makeInstance(LispObject key, int hash, LispObject value, HashEntry next, int slot) { return new HashEntryWeakKey(key, hash, value, next, slot); } void expungeQueue() { Reference ref = queue.poll(); while (ref != null) { WeakHashTable.this.remove(ref); entryLookup.remove(ref); ref = queue.poll(); } } /** Remove referenced objects from GC queue structures. */ void clear() { key.clear(); assert entryLookup.containsKey(key) : "Key was not in lookup table"; entryLookup.remove(key); } } class HashEntryWeakValue extends HashEntry { private WeakReference value; public HashEntryWeakValue() {}; public HashEntryWeakValue(LispObject key, int hash, LispObject value, HashEntry next, int slot) { this.hash = hash; this.key = key; this.next = next; this.slot = slot; this.value = new WeakReference(value, queue); entryLookup.put(this.value, this); } public LispObject getValue() { return value.get(); } public void setValue(LispObject value) { java.lang.ref.WeakReference old = this.value; old.clear(); this.value = new WeakReference(value, queue); entryLookup.put(this.value, this); } HashEntryWeakValue[] makeArray(int length) { return new HashEntryWeakValue[length]; } HashEntryWeakValue makeInstance(LispObject key, int hash, LispObject value, HashEntry next, int slot) { return new HashEntryWeakValue(key, hash, value, next, slot); } void expungeQueue() { Reference ref = queue.poll(); while (ref != null) { WeakHashTable.this.remove(ref); entryLookup.remove(ref); ref = queue.poll(); } } /** Remove referenced objects from GC queue structures. */ void clear() { value.clear(); assert entryLookup.containsKey(value) : "Value was not in lookup table."; entryLookup.remove(value); } } class HashEntryWeakKeyAndValue extends HashEntry { private WeakReference key; private WeakReference value; public HashEntryWeakKeyAndValue() {}; public HashEntryWeakKeyAndValue(LispObject key, int hash, LispObject value, HashEntry next, int slot) { this.hash = hash; this.next = next; this.slot = slot; this.key = new WeakReference(key, queue); entryLookup.put(this.key, this); this.value = new WeakReference(value, queue); entryLookup.put(this.value, this); } public LispObject getKey() { return key.get(); } public void setKey(LispObject key) { java.lang.ref.WeakReference old = this.key; entryLookup.remove(old); old.clear(); this.key = new WeakReference(key, queue); entryLookup.put(this.key, this); } public LispObject getValue() { return value.get(); } public void setValue(LispObject value) { java.lang.ref.WeakReference old = this.value; entryLookup.remove(old); old.clear(); this.value = new WeakReference(value, queue); entryLookup.put(this.value, this); } HashEntryWeakKeyAndValue[] makeArray(int length) { return new HashEntryWeakKeyAndValue[length]; } HashEntryWeakKeyAndValue makeInstance(LispObject key, int hash, LispObject value, HashEntry next, int slot) { return new HashEntryWeakKeyAndValue(key, hash, value, next, slot); } void expungeQueue() { Reference ref = queue.poll(); while (ref != null) { HashEntry entry = entryLookup.get(ref); if (entry == null) { ref = queue.poll(); continue; } if (entry.getKey() == null && entry.getValue() == null) { WeakHashTable.this.remove(ref); entryLookup.remove(ref); } else { entryLookup.remove(ref); } ref = queue.poll(); } } /** Remove referenced objects from GC queue structures. */ void clear() { key.clear(); value.clear(); entryLookup.remove(key); entryLookup.remove(value); } } class HashEntryWeakKeyOrValue extends HashEntryWeakKeyAndValue { public HashEntryWeakKeyOrValue() {}; public HashEntryWeakKeyOrValue(LispObject key, int hash, LispObject value, HashEntry next, int slot) { super(key, hash, value, next, slot); } HashEntryWeakKeyOrValue[] makeArray(int length) { return new HashEntryWeakKeyOrValue[length]; } HashEntryWeakKeyOrValue makeInstance(LispObject key, int hash, LispObject value, HashEntry next, int slot) { return new HashEntryWeakKeyOrValue(key, hash, value, next, slot); } void expungeQueue() { Reference ref = queue.poll(); while (ref != null) { HashEntry entry = entryLookup.get(ref); if (entry == null) { ref = queue.poll(); continue; } WeakHashTable.this.remove(ref); entryLookup.remove(entry.key); entryLookup.remove(entry.value); ref = queue.poll(); } } } // For EQUALP hash tables. @Override public int psxhash() { long result = 2062775257; // Chosen at random. result = mix(result, count); result = mix(result, getTest().sxhash()); return (int) (result & 0x7fffffff); } } abcl-src-1.9.0/src/org/armedbear/lisp/WeakReference.java0100644 0000000 0000000 00000007571 14223403213 021562 0ustar000000000 0000000 /* * WeakReference.java * * Copyright (C) 2011 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public class WeakReference extends LispObject { java.lang.ref.WeakReference ref; public WeakReference(LispObject ref) { this.ref = new java.lang.ref.WeakReference(ref); } @Override public LispObject typeOf() { return Symbol.WEAK_REFERENCE; } @Override public LispObject classOf() { return BuiltInClass.WEAK_REFERENCE; } @Override public String printObject() { return unreadableString("WEAK-REFERENCE " + toString()); } @Override public LispObject typep(LispObject typeSpecifier) { if (typeSpecifier == Symbol.WEAK_REFERENCE) { return T; } if (typeSpecifier == BuiltInClass.WEAK_REFERENCE) { return T; } return super.typep(typeSpecifier); } private static final Primitive MAKE_WEAK_REFERENCE = new pf_make_weak_reference(); @DocString(name="make-weak-reference", args="obj", doc="Creates a weak reference to 'obj'.") private static final class pf_make_weak_reference extends Primitive { pf_make_weak_reference() { super("make-weak-reference", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject obj) { return new WeakReference(obj); } }; private static final Primitive WEAK_REFERENCE_VALUE = new pf_weak_reference_value(); @DocString(name="weak-reference-value", args="obj", doc="Returns two values, the first being the value of the weak ref," + "the second T if the reference is valid, or NIL if it has" + "been cleared.") private static final class pf_weak_reference_value extends Primitive { pf_weak_reference_value() { super("weak-reference-value", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject obj) { if (! (obj instanceof WeakReference)) return Lisp.type_error(obj, Symbol.WEAK_REFERENCE); LispObject value = ((WeakReference)obj).ref.get(); return LispThread.currentThread().setValues(value == null ? NIL : value, value == null ? NIL : T); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/WrongNumberOfArgumentsException.java0100644 0000000 0000000 00000010677 14223403213 025354 0ustar000000000 0000000 /* * WrongNumberOfArgumentsException.java * * Copyright (C) 2002-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class WrongNumberOfArgumentsException extends ProgramError { private Operator operator; private int expectedMinArgs; private int expectedMaxArgs; private LispObject actualArgs; private String message; public WrongNumberOfArgumentsException(Operator operator) { this(operator, -1); } public WrongNumberOfArgumentsException(Operator operator, LispObject args, int expectedMin, int expectedMax) { // This is really just an ordinary PROGRAM-ERROR, broken out into its // own Java class as a convenience for the implementation. super(StandardClass.PROGRAM_ERROR); this.operator = operator; this.expectedMinArgs = expectedMin; this.expectedMaxArgs = expectedMax; this.actualArgs = args; setFormatControl(getMessage().replaceAll("~","~~")); setFormatArguments(NIL); } public WrongNumberOfArgumentsException(Operator operator, int expectedMin, int expectedMax) { this(operator, null, expectedMin, expectedMax); } public WrongNumberOfArgumentsException(Operator operator, int expectedArgs) { this(operator, expectedArgs, expectedArgs); } public WrongNumberOfArgumentsException(Operator operator, LispObject args, int expectedArgs) { this(operator, args, expectedArgs, expectedArgs); } public WrongNumberOfArgumentsException(String message) { super(StandardClass.PROGRAM_ERROR); if(message == null) { throw new NullPointerException("message can not be null"); } this.message = message; setFormatControl(getMessage().replaceAll("~","~~")); setFormatArguments(NIL); } @Override public String getMessage() { if(message != null) { return message; } StringBuilder sb = new StringBuilder("Wrong number of arguments for " + operator.princToString()); if(expectedMinArgs >= 0 || expectedMaxArgs >= 0) { sb.append("; "); if (expectedMinArgs == expectedMaxArgs) { sb.append(expectedMinArgs); } else if (expectedMaxArgs < 0) { sb.append("at least "); sb.append(expectedMinArgs); } else if (expectedMinArgs < 0) { sb.append("at most "); sb.append(expectedMaxArgs); } else { sb.append("between ").append(expectedMinArgs); sb.append(" and ").append(expectedMaxArgs); } sb.append(" expected"); } if (actualArgs != null) { sb.append(" -- provided: "); sb.append(actualArgs.princToString()); } sb.append('.'); return message = sb.toString(); } } abcl-src-1.9.0/src/org/armedbear/lisp/ZeroRankArray.java0100644 0000000 0000000 00000013424 14202767264 021620 0ustar000000000 0000000 /* * ZeroRankArray.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class ZeroRankArray extends AbstractArray { private final LispObject elementType; private final boolean adjustable; private LispObject data; public ZeroRankArray(LispObject elementType, LispObject data, boolean adjustable) { this.elementType = elementType; this.data = data; this.adjustable = adjustable; } @Override public LispObject typeOf() { if (adjustable) return list(Symbol.ARRAY, elementType, NIL); else return list(Symbol.SIMPLE_ARRAY, elementType, NIL); } @Override public LispObject classOf() { return BuiltInClass.ARRAY; } @Override public LispObject typep(LispObject type) { if (type == Symbol.SIMPLE_ARRAY) return adjustable ? NIL : T; return super.typep(type); } @Override public int getRank() { return 0; } @Override public LispObject getDimensions() { return NIL; } @Override public int getDimension(int n) { error(new TypeError("Bad array dimension (" + n + ") for array of rank 0.")); // Not reached. return -1; } @Override public LispObject getElementType() { return elementType; } @Override public int getTotalSize() { return 1; } @Override public LispObject AREF(int index) { if (index == 0) return data; else return error(new TypeError("Bad row major index " + index + ".")); } @Override public void aset(int index, LispObject obj) { if (obj.typep(elementType) == NIL) type_error(obj, elementType); if (index == 0) data = obj; else error(new TypeError("Bad row major index " + index + ".")); } @Override public void fill(LispObject obj) { if (obj.typep(elementType) == NIL) type_error(obj, elementType); data = obj; } @Override public String printObject() { final LispThread thread = LispThread.currentThread(); boolean printReadably = (Symbol.PRINT_READABLY.symbolValue(thread) != NIL); if (printReadably) { if (elementType != T) { error(new PrintNotReadable(list(Keyword.OBJECT, this))); // Not reached. return null; } } if (printReadably || Symbol.PRINT_ARRAY.symbolValue(thread) != NIL) { StringBuffer sb = new StringBuffer("#0A"); if (data == this && Symbol.PRINT_CIRCLE.symbolValue(thread) != NIL) { StringOutputStream stream = new StringOutputStream(); thread.execute(Symbol.OUTPUT_OBJECT.getSymbolFunction(), data, stream); sb.append(stream.getString().getStringValue()); } else sb.append(data.printObject()); return sb.toString(); } StringBuffer sb = new StringBuffer(); if (!adjustable) sb.append("SIMPLE-"); sb.append("ARRAY "); sb.append(elementType.printObject()); sb.append(" NIL"); return unreadableString(sb.toString()); } @Override public AbstractArray adjustArray(int[] dims, LispObject initialElement, LispObject initialContents) { if (isAdjustable()) { // initial element doesn't matter: // we're not creating new elements if (initialContents != null) data = initialContents; return this; } else { return new ZeroRankArray(elementType, initialContents != null ? initialContents : initialElement != null ? initialElement : data, false); } } @Override public AbstractArray adjustArray(int[] dims, AbstractArray displacedTo, int displacement) { error(new TypeError("Displacement not supported for array of rank 0.")); return null; } } abcl-src-1.9.0/src/org/armedbear/lisp/ZipCache.java0100644 0000000 0000000 00000052166 14202767264 020562 0ustar000000000 0000000 /* * ZipCache.java * * Copyright (C) 2010, 2014 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import org.armedbear.lisp.util.HttpHead; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.JarURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; import java.util.HashMap; import java.util.Locale; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * A cache for all zip/jar file access by JarPathname that uses the last * modified time of the cached resource. * * If you run into problems with caching, use * (SYS::DISABLE-ZIP-CACHE). Once disabled, the caching cannot be * re-enabled. * */ public class ZipCache { public static final boolean checkZipFile(Pathname name) { InputStream input = name.getInputStream(); try { byte[] bytes = new byte[4]; int bytesRead = input.read(bytes); return bytesRead == 4 && bytes[0] == 80 && bytes[1] == 75 && bytes[2] == 3 && bytes[3] == 4; } catch (Throwable t) { // any error probably means 'no' return false; } finally { if (input != null) { try { input.close(); } catch (IOException e) { } // ignore exceptions } } } static InputStream getInputStream(ZipFile jarFile, String entryPath) { ZipEntry entry = jarFile.getEntry(entryPath); if (entry == null) { Debug.trace("Failed to find entry " + "'" + entryPath + "'" + " in " + "'" + jarFile.getName() + "'"); return null; } InputStream result = null; try { result = jarFile.getInputStream(entry); } catch (IOException e) { Debug.trace("Failed to open InputStream for " + "'" + entryPath + "'" + " in " + "'" + jarFile.getName() + "'"); return null; } return result; } public static ZipInputStream getZipInputStream(ZipFile zipfile, String entryName) { return ZipCache.getZipInputStream(zipfile, entryName, false); } public static ZipInputStream getZipInputStream(ZipFile zipfile, String entryName, boolean errorOnFailure) { ZipEntry zipEntry = zipfile.getEntry(entryName); ZipInputStream stream = null; try { stream = new ZipInputStream(zipfile.getInputStream(zipEntry)); } catch (IOException e) { if (errorOnFailure) { simple_error("Failed to open '" + entryName + "' in zipfile '" + zipfile + "': " + e.getMessage()); } return null; } return stream; } public static ByteArrayOutputStream readEntry(ZipInputStream stream) { ByteArrayOutputStream result = new ByteArrayOutputStream(); int count; byte[] buf = new byte[1024]; // What's a decent buffer size? try { while ((count = stream.read(buf, 0, buf.length)) != -1) { result.write(buf, 0, count); } } catch (IOException e) { Debug.trace("Failed to read entry from " + stream + ": " + e); return null; } return result; } public static ZipEntry getEntry(ZipInputStream zipInputStream, String entryName) { return ZipCache.getEntry(zipInputStream, entryName, false); } public static ZipEntry getEntry(ZipInputStream zipInputStream, String entryName, boolean errorOnFailure) { ZipEntry entry = null; do { try { entry = zipInputStream.getNextEntry(); } catch (IOException e) { if (errorOnFailure) { Lisp.error(new FileError("Failed to seek for " + "'" + entryName + "'" + " in " + zipInputStream.toString())); } return null; } } while (entry != null && !entry.getName().equals(entryName)); if (entry != null) { return entry; } if (errorOnFailure) { Lisp.error(new FileError("Failed to find " + "'" + entryName + "'" + " in " + zipInputStream.toString())); } return null; } public static InputStream getEntryAsInputStream(ZipInputStream zipInputStream, String entryName) { ZipEntry entry = getEntry(zipInputStream, entryName); ByteArrayOutputStream bytes = readEntry(zipInputStream); return new ByteArrayInputStream(bytes.toByteArray()); } public static InputStream getEntryAsInputStream(JarPathname archiveEntry) { JarPathname archiveJar = archiveEntry.getArchive(); Archive archive = ZipCache.getArchive(archiveJar); InputStream result = archive.getEntryAsInputStream(archiveEntry); if (result == null) { simple_error("Failed to get InputStream for ~a", archiveEntry); } return result; } // To make this thread safe, we should return a proxy for ZipFile // that keeps track of the number of outstanding references handed // out, not allowing ZipFile.close() to succeed until that count // has been reduced to 1 or the finalizer is executing. // Unfortunately the relatively simple strategy of extending // ZipFile via a CachedZipFile does not work because there is not // a null arg constructor for ZipFile. static HashMap cache = new HashMap(); abstract static public class Archive { JarPathname root; LinkedHashMap entries = new LinkedHashMap(); long lastModified; abstract InputStream getEntryAsInputStream(JarPathname entry); abstract ZipEntry getEntry(JarPathname entry); abstract void populateAllEntries(); abstract void close(); abstract long getLastModified(); } static public class ArchiveStream extends Archive { ZipInputStream source; ZipEntry rootEntry; public ArchiveStream(InputStream stream, JarPathname root, ZipEntry rootEntry) { if (!(stream instanceof ZipInputStream)) { this.source = new ZipInputStream(stream); } else { this.source = (ZipInputStream)stream; } this.root = root; this.rootEntry = rootEntry; this.lastModified = rootEntry.getTime(); // FIXME how to re-check time as modified? } // TODO wrap in a weak reference to allow JVM to possibly reclaim memory LinkedHashMap contents = new LinkedHashMap(); boolean populated = false; public InputStream getEntryAsInputStream(JarPathname entry) { if (!populated) { populateAllEntries(); } entry.setVersion(Keyword.NEWEST); ByteArrayOutputStream bytes = contents.get(entry); if (bytes != null) { return new ByteArrayInputStream(bytes.toByteArray()); } return null; } public ZipEntry getEntry(JarPathname entry) { if (!populated) { populateAllEntries(); } entry.setVersion(Keyword.NEWEST); ZipEntry result = entries.get(entry); return result; } void populateAllEntries() { if (populated) { return; } ZipEntry entry; try { while ((entry = source.getNextEntry()) != null) { String name = entry.getName(); JarPathname entryPathname = (JarPathname)JarPathname.createEntryFromJar(root, name); entries.put(entryPathname, entry); ByteArrayOutputStream bytes = readEntry(source); contents.put(entryPathname, bytes); } populated = true; } catch (IOException e) { simple_error("Failed to read entries from zip archive", root); } } void close () { if (source != null) { try { source.close(); } catch (IOException ex) { {} } } } long getLastModified() { return ((URLPathname)root.getRootJar()).getLastModified(); } } static public class ArchiveURL extends ArchiveFile { JarURLConnection connection; public ArchiveURL(JarPathname jar) throws java.io.IOException { String rootJarURLString = jar.getRootJarAsURLString(); URL rootJarURL = new URL(rootJarURLString); JarURLConnection jarConnection = (JarURLConnection) rootJarURL.openConnection(); this.root = jar; this.connection = jarConnection; this.file = (ZipFile)connection.getJarFile(); this.lastModified = connection.getLastModified(); } void close() { super.close(); // TODO: do we need to clean up from the connection? } } static public class ArchiveFile extends Archive { ZipFile file; ZipFile get() { return file;} ArchiveFile() {} public ArchiveFile(JarPathname jar) throws ZipException, IOException { File f = ((Pathname)jar.getRootJar()).getFile(); this.root = jar; this.file = new ZipFile(f); this.lastModified = f.lastModified(); } long getLastModified() { long result = 0; File f = ((Pathname)root.getRootJar()).getFile(); if (f != null) { result = f.lastModified(); } return result; } public ZipEntry getEntry(JarPathname entryPathname) { entryPathname.setVersion(Keyword.NEWEST); ZipEntry result = entries.get(entryPathname); if (result != null) { return result; } String entryPath = entryPathname.asEntryPath(); result = file.getEntry(entryPath); if (result == null) { return null; } // ZipFile.getEntry() will return directories when asked for // files. if (result.isDirectory() && (!entryPathname.getName().equals(NIL) || !entryPathname.getType().equals(NIL))) { return null; } entries.put(entryPathname, result); return result; } void populateAllEntries() { ZipFile f = file; if (f.size() == entries.size()) { return; } Enumeration e = f.entries(); while (e.hasMoreElements()) { ZipEntry entry = e.nextElement(); String name = entry.getName(); JarPathname entryPathname = (JarPathname)JarPathname.createEntryFromJar(root, name); entries.put(entryPathname, entry); } } InputStream getEntryAsInputStream(JarPathname entry) { InputStream result = null; entry.setVersion(Keyword.NEWEST); ZipEntry zipEntry = getEntry(entry); try { result = file.getInputStream(zipEntry); } catch (IOException e) {} // FIXME how to signal a meaningful error? return result; } void close() { if (file != null) { try { file.close(); } catch (IOException e) {} } } } static boolean cacheEnabled = true; private final static Primitive DISABLE_ZIP_CACHE = new disable_zip_cache(); final static class disable_zip_cache extends Primitive { disable_zip_cache() { super("disable-zip-cache", PACKAGE_SYS, true, "", "Not currently implemented"); } @Override public LispObject execute() { return NIL; } } static public synchronized void disable() { cacheEnabled = false; cache.clear(); } synchronized public static LinkedHashMap getEntries(JarPathname jar) { Archive archive = getArchive(jar); archive.populateAllEntries(); // Very expensive for jars with large number of entries return archive.entries; } synchronized public static Iterator> getEntriesIterator(JarPathname jar) { LinkedHashMap entries = getEntries(jar); Set> set = entries.entrySet(); return set.iterator(); } static ZipEntry getZipEntry(JarPathname archiveEntry) { JarPathname archiveJar = archiveEntry.getArchive(); Archive zip = getArchive(archiveJar); ZipEntry entry = zip.getEntry(archiveEntry); return entry; } // ??? we assume that DIRECTORY, NAME, and TYPE components are NIL synchronized public static Archive getArchive(JarPathname jar) { jar.setVersion(Keyword.NEWEST); Archive result = cache.get(jar); if (result != null) { long time = result.getLastModified(); if (time != result.lastModified) { cache.remove(jar); return getArchive(jar); } return result; } Pathname rootJar = (Pathname) jar.getRootJar(); LispObject innerJars = jar.getJars().cdr(); if (!rootJar.isLocalFile()) { return getArchiveURL(jar); } if (innerJars.equals(NIL)) { return getArchiveFile(jar); } result = getArchiveStreamFromFile(jar); cache.put(result.root, result); JarPathname nextArchive = new JarPathname(); nextArchive .setDevice(new Cons(rootJar, new Cons(innerJars.car(), NIL))) .setDirectory(NIL) .setName(NIL) .setType(NIL) .setVersion(Keyword.NEWEST); innerJars = innerJars.cdr(); while (innerJars.car() != NIL) { Pathname nextJarArchive = (Pathname)innerJars.car(); JarPathname nextAsEntry = new JarPathname(); nextAsEntry .setDevice(nextArchive.getDevice()) .setDirectory(nextJarArchive.getDirectory()) .setName(nextJarArchive.getName()) .setType(nextJarArchive.getType()) .setVersion(Keyword.NEWEST); // FIXME // The pathnames for subsquent entries in a PATHNAME-JAR // are relative. Should they be? LispObject directories = nextAsEntry.getDirectory(); if ( !directories.equals(NIL) && directories.car().equals(Keyword.RELATIVE)) { directories = directories.cdr().push(Keyword.ABSOLUTE); nextAsEntry.setDirectory(directories); } nextArchive.setDevice(nextArchive.getDevice().reverse().push(nextJarArchive).reverse()); ArchiveStream stream = (ArchiveStream) result; ZipEntry entry = stream.getEntry(nextAsEntry); if (entry == null) { return null; } InputStream inputStream = stream.getEntryAsInputStream(nextAsEntry); if (inputStream == null) { return null; } stream = new ArchiveStream(inputStream, nextArchive, entry); result = stream; cache.put(nextArchive, result); innerJars = innerJars.cdr(); if (innerJars.cdr().equals(NIL) && (!jar.getDirectory().equals(NIL) && jar.getName().equals(NIL) && jar.getType().equals(NIL))) { simple_error("Currently unimplemented retrieval of an entry in a nested pathnames"); return (Archive)UNREACHED; } } return result; } static ArchiveStream getArchiveStreamFromFile(JarPathname p) { JarPathname innerArchiveAsEntry = JarPathname.archiveAsEntry(p); JarPathname root = new JarPathname(); root = (JarPathname)root.copyFrom(innerArchiveAsEntry); root .setDirectory(NIL) .setName(NIL) .setType(NIL) .setVersion(Keyword.NEWEST); ArchiveFile rootArchiveFile = (ArchiveFile)getArchiveFile(root); ZipEntry entry = rootArchiveFile.getEntry(innerArchiveAsEntry); if (entry == null) { return null; } InputStream inputStream = rootArchiveFile.getEntryAsInputStream(innerArchiveAsEntry); if (inputStream == null) { return null; } ArchiveStream result = new ArchiveStream(inputStream, p, entry); return result; } public static Archive getArchiveURL(JarPathname jar) { Pathname rootJar = (Pathname) jar.getRootJar(); jar.setVersion(Keyword.NEWEST); URL rootJarURL = null; try { ArchiveURL result = new ArchiveURL(jar); cache.put(jar, result); return result; } catch (MalformedURLException e) { simple_error("Failed to form root URL for ~a", jar); return (Archive)UNREACHED; } catch (IOException e) { simple_error("Failed to fetch ~a: ~a", jar, e); return (Archive)UNREACHED; } } static public Archive getArchiveFile(JarPathname jar) { jar.setVersion(Keyword.NEWEST); try { ArchiveFile result = new ArchiveFile(jar); cache.put(jar, result); return result; } catch (ZipException e) { error(new FileError("Failed to open local zip archive" + " because " + e, jar)); return (Archive)UNREACHED; } catch (IOException e) { error(new FileError("Failed to open local zip archive" + " because " + e, jar)); return (Archive)UNREACHED; } } // unused static void checkRemoteLastModified(ArchiveURL archive) { // Unfortunately, the Apple JDK under OS X doesn't do // HTTP HEAD requests, instead refetching the entire // resource, and I assume this is the case in all // Sun-derived JVMs. So, we use a custom HEAD // implementation only looking for Last-Modified // headers, which if we don't find, we give up and // refetch the resource. String dateString = null; String url = archive.root.getRootJarAsURLString(); try { dateString = HttpHead.get(url, "Last-Modified"); } catch (IOException ex) { Debug.trace(ex); } Date date = null; ParsePosition pos = new ParsePosition(0); final SimpleDateFormat ASCTIME = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy", Locale.US); final SimpleDateFormat RFC_1036 = new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US); final SimpleDateFormat RFC_1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); if (dateString != null) { date = RFC_1123.parse(dateString, pos); if (date == null) { date = RFC_1036.parse(dateString, pos); if (date == null) { date = ASCTIME.parse(dateString, pos); } } } // Replace older item in cache if (date == null || date.getTime() > archive.lastModified) { JarPathname root = archive.root; Archive entry = getArchiveURL(root); cache.put(root, entry); } if (date == null) { if (dateString == null) { Debug.trace("Failed to retrieve request header: " + url.toString()); } else { Debug.trace("Failed to parse Last-Modified date: " + dateString); } } } // ## clear-zip-cache => boolean private static final Primitive CLEAR_ZIP_CACHE = new clear_zip_cache(); private static class clear_zip_cache extends Primitive { clear_zip_cache() { super("clear-zip-cache", PACKAGE_SYS, true); } @Override public LispObject execute() { int size = cache.size(); cache.clear(); return size == 0 ? NIL : T; } } // ## remove-zip-cache-entry pathname => boolean private static final Primitive REMOVE_ZIP_CACHE_ENTRY = new remove_zip_cache_entry(); private static class remove_zip_cache_entry extends Primitive { remove_zip_cache_entry() { super("remove-zip-cache-entry", PACKAGE_SYS, true, "pathname"); } @Override public LispObject execute(LispObject arg) { Pathname p = coerceToPathname(arg); boolean result = false; if (p instanceof JarPathname) { result = ZipCache.remove((JarPathname)p); } return result ? T : NIL; } } synchronized public static boolean remove(Pathname pathname) { JarPathname p = JarPathname.createFromPathname(pathname); return remove(p); } synchronized public static boolean remove(JarPathname p) { p.setVersion(Keyword.NEWEST); Archive archive = cache.get(p); if (archive != null) { archive.close(); cache.remove(p); return true; } return false; } } abcl-src-1.9.0/src/org/armedbear/lisp/abcl-contrib.lisp0100644 0000000 0000000 00000022674 14242627550 021457 0ustar000000000 0000000 ;;;; Mechanisms for finding loadable artifacts from the environment, ;;;; which are then used to locate the Common Lisp systems included as ;;;; `abcl-contrib`. (require :asdf) (in-package :system) (defun boot-classloader () (let ((boot-class (java:jclass "org.armedbear.lisp.Main")) (get-classloader (java:jmethod "java.lang.Class" "getClassLoader"))) (java:jcall get-classloader boot-class))) ;;; java[678] packages the JVM system artifacts as jar files ;;; java11 uses the module system (defun system-artifacts-are-jars-p () (java:jinstance-of-p (boot-classloader) "java.net.URLClassLoader")) (defun system-jar-p (p) (or (named-jar-p "abcl" p) (named-jar-p "abcl-aio" p))) (defun contrib-jar-p (p) (or (named-jar-p "abcl-contrib" p) (named-jar-p "abcl-aio" p))) (defun named-jar-p (name p) (and (pathnamep p) (equal (pathname-type p) "jar") (or (java:jstatic "matches" "java.util.regex.Pattern" (concatenate 'string name "(-[0-9]\\.[0-9]\\.[0-9]([+~-].+)?)?") (pathname-name p)) (java:jstatic "matches" "java.util.regex.Pattern" (concatenate 'string name "(-[0-9]\\.[0-9]\\.[0-9]\\.[0-9]([+~-]+)?)?") (pathname-name p))) p)) (defun find-system () "Find the location of the Armed Bear system implementation Used to determine relative pathname to find 'abcl-contrib.jar'." (or (ignore-errors (find-system-jar)) (ignore-errors (when (system-artifacts-are-jars-p) (some (lambda (u) (probe-file (make-pathname :defaults (java:jcall "toString" u) :name "abcl"))) (java:jcall "getURLs" (boot-classloader))))) ;; Need to test locating the system boot jar over the network, and ;; it would minimally need to check version information. (ignore-errors (pathname "jar:https://abcl.org/releases/1.9.0/abcl.jar!/")))) (defun flatten (list) (labels ((rflatten (list accumluator) (dolist (element list) (if (listp element) (setf accumluator (rflatten element accumluator)) (push element accumluator))) accumluator)) (let (result) (reverse (rflatten list result))))) (defun java.class.path () "Return a list of the directories as pathnames referenced in the JVM classpath." (let* ((separator (java:jstatic "getProperty" "java.lang.System" "path.separator")) (paths (coerce (java:jcall "split" (java:jstatic "getProperty" "java.lang.System" "java.class.path") separator) 'list)) (p (coerce paths 'list))) (flet ((directory-of (p) (make-pathname :defaults p :name nil :type nil))) (values (mapcar #'directory-of p) p)))) (defun enumerate-resource-directories () (flet ((directory-of (p) (make-pathname :defaults p :name nil :type nil))) (let ((result (java.class.path))) (dolist (entry (flatten (java:dump-classpath))) (cond ((java:jinstance-of-p entry "java.net.URLClassLoader") ;; java1.[678] (dolist (url (coerce (java:jcall "getURLs" entry) 'list)) (let ((p (directory-of (pathname (java:jcall "toString" url))))) (when (probe-file p) (pushnew p result :test 'equal))))) ((pathnamep entry) (pushnew (directory-of entry) result :test 'equal)) ((and (stringp entry) (probe-file (pathname (directory-of entry)))) (pushnew (pathname (directory-of entry)) result :test 'equal)) (t #+(or) ;; Possibly informative for debugging new JVM implementations (format *standard-output* "~&Skipping enumeration of resource '~a' with type '~a'.~%" entry (type-of entry))))) result))) (defun find-jar (predicate) (dolist (d (enumerate-resource-directories)) (let ((entries (directory (make-pathname :defaults d :name "*" :type "jar")))) (let ((jar (some predicate entries))) (when (and jar (probe-file jar)) (return-from find-jar (make-pathname :device (list (probe-file jar))))))))) (defun find-system-jar () "Return the pathname of the system jar, one of `abcl.jar` or `abcl-m.n.p.jar` or `abcl-m.n.p[.~-]something.jar`." (find-jar #'system-jar-p)) (defun find-contrib-jar () "Return the pathname of the contrib jar, one of `abcl-contrib.jar` or `abcl-contrib-m.n.p.jar` or `abcl-contrib-m.n.p[.~-]something.jar`." (find-jar #'contrib-jar-p)) (defvar *abcl-contrib* nil "Pathname of the abcl-contrib artifact. Initialized via SYSTEM:FIND-CONTRIB.") ;;; FIXME: stop using the obsolete ASDF:*CENTRAL-REGISTRY* (defun add-contrib (abcl-contrib-jar &key (verbose cl:*load-verbose*)) "Introspects the ABCL-CONTRIB-JAR path for sub-directories which contain asdf definitions, adding those found to asdf." (let ((jar-path (if (ext:pathname-jar-p abcl-contrib-jar) abcl-contrib-jar (make-pathname :device (list abcl-contrib-jar))))) (dolist (asdf-file (directory (merge-pathnames "*/*.asd" jar-path))) (let ((asdf-directory (make-pathname :defaults asdf-file :name nil :type nil))) (unless (find asdf-directory asdf:*central-registry* :test #'equal) (push asdf-directory asdf:*central-registry*) (format verbose "~&; Added ~A to ASDF.~%" asdf-directory)))))) (defun find-and-add-contrib (&key (verbose cl:*load-verbose*)) "Attempt to find the ABCL contrib jar and add its contents to ASDF. returns the pathname of the contrib if it can be found." (if *abcl-contrib* (format verbose "~&; Finding contribs utilizing previously initialized value of SYS:*ABCL-CONTRIB* '~A'.~%" *abcl-contrib*) (progn (let ((contrib (find-contrib))) (when contrib (format verbose "~&; Using probed value of SYS:*ABCL-CONTRIB* '~A'.~%" contrib) (setf *abcl-contrib* contrib))))) (when *abcl-contrib* ;; For bootstrap compile there will be no contrib (add-contrib *abcl-contrib*))) (defun find-name-for-implementation-title (file id) "For a jar FILE containing a manifest, return the name of the section which annotates 'Implementation-Title' whose string value is ID." (declare (type pathname file)) (let* ((jar-file (java:jcall "getFile" (first (pathname-device file)))) (jar (java:jnew "java.util.jar.JarFile" jar-file)) (manifest (java:jcall "getManifest" jar)) (entries (java:jcall "toArray" (java:jcall "entrySet" (java:jcall "getEntries" manifest))))) (dolist (entry (loop :for entry :across entries :collecting entry)) (let ((title (java:jcall "getValue" (java:jcall "getValue" entry) "Implementation-Title"))) (when (string-equal title id) (return-from find-name-for-implementation-title (java:jcall "getKey" entry)))) nil))) (defun find-contrib () "Introspect runtime classpaths to return a pathname containing subdirectories containing ASDF definitions." (or ;; We identify the location of the directory within a jar file ;; containing abcl-contrib ASDF definitions by looking for a section ;; which contains the Implementation-Title "org.abcl-contrib". The ;; name of that section then identifies the relative pathname to the ;; top-most directory in the Jar ;; ;; e.g. for an entry of the form ;; ;; Name: contrib ;; Implementation-Title: org.abcl-contrib ;; ;; the directory 'contrib' would be searched for ASDF definitions. (ignore-errors (let* ((system-jar (find-system-jar)) (relative-pathname (find-name-for-implementation-title system-jar "org.abcl-contrib"))) (when (and system-jar relative-pathname) (merge-pathnames (pathname (concatenate 'string relative-pathname "/")) system-jar)))) (ignore-errors (find-contrib-jar)) (ignore-errors (let ((system-jar (find-system-jar))) (when system-jar (probe-file (make-pathname :defaults system-jar :name (concatenate 'string "abcl-contrib" (subseq (pathname-name system-jar) 4))))))) (when (java:jinstance-of-p (boot-classloader) "java.net.URLClassLoader") (some (lambda (u) (probe-file (make-pathname :defaults (java:jcall "toString" u) :name "abcl-contrib"))) (java:jcall "getURLs" (boot-classloader)))))) (export '(find-system find-contrib system-artifacts-are-jars-p java.class.path *abcl-contrib*) :system) (when (find-and-add-contrib :verbose cl:*load-verbose*) (provide :abcl-contrib)) abcl-src-1.9.0/src/org/armedbear/lisp/adjoin.lisp0100644 0000000 0000000 00000003747 14223403213 020347 0ustar000000000 0000000 ;;; adjoin.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (defun adjoin (item list &key key (test #'eql testp) (test-not nil notp)) "Add `item' to `list' unless it is already a member (as determined by the test function `test'." (when (and testp notp) (error "test and test-not both supplied")) (if (let ((key-val (sys::apply-key key item))) (if notp (member key-val list :test-not test-not :key key) (member key-val list :test test :key key))) list (cons item list))) abcl-src-1.9.0/src/org/armedbear/lisp/adjust_array.java0100644 0000000 0000000 00000013006 14202767264 021552 0ustar000000000 0000000 /* * adjust_array.java * * Copyright (C) 2004-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### %adjust-array array new-dimensions element-type initial-element // initial-element-p initial-contents initial-contents-p fill-pointer // displaced-to displaced-index-offset => new-array public final class adjust_array extends Primitive { public adjust_array() { super("%adjust-array", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject[] args) { if (args.length != 10) return error(new WrongNumberOfArgumentsException(this, 10)); AbstractArray array = checkArray(args[0]); LispObject dimensions = args[1]; LispObject elementType = args[2]; boolean initialElementProvided = args[4] != NIL; boolean initialContentsProvided = args[6] != NIL; LispObject initialElement = initialElementProvided ? args[3] : null; LispObject initialContents = initialContentsProvided ? args[5] : null; LispObject fillPointer = args[7]; LispObject displacedTo = args[8]; LispObject displacedIndexOffset = args[9]; if (initialElementProvided && initialContentsProvided) { return error(new LispError("ADJUST-ARRAY: cannot specify both initial element and initial contents.")); } if (elementType != array.getElementType() && getUpgradedArrayElementType(elementType) != array.getElementType()) { return error(new LispError("ADJUST-ARRAY: incompatible element type.")); } if (array.getRank() == 0) { return array.adjustArray(new int[0], initialElement, initialContents); } if (!initialElementProvided && array.getElementType() == T) initialElement = Fixnum.ZERO; if (array.getRank() == 1) { final int newSize; if (dimensions instanceof Cons && dimensions.length() == 1) newSize = Fixnum.getValue(dimensions.car()); else newSize = Fixnum.getValue(dimensions); if (array instanceof AbstractVector) { AbstractVector v = (AbstractVector) array; AbstractArray v2; if (displacedTo != NIL) { final int displacement; if (displacedIndexOffset == NIL) displacement = 0; else displacement = Fixnum.getValue(displacedIndexOffset); v2 = v.adjustArray(newSize, checkArray(displacedTo), displacement); } else { v2 = v.adjustArray(newSize, initialElement, initialContents); } if (fillPointer != NIL) v2.setFillPointer(fillPointer); return v2; } } // rank > 1 final int rank = dimensions.listp() ? dimensions.length() : 1; int[] dimv = new int[rank]; if (dimensions.listp()) { for (int i = 0; i < rank; i++) { LispObject dim = dimensions.car(); dimv[i] = Fixnum.getValue(dim); dimensions = dimensions.cdr(); } } else dimv[0] = Fixnum.getValue(dimensions); if (displacedTo != NIL) { final int displacement; if (displacedIndexOffset == NIL) displacement = 0; else displacement = Fixnum.getValue(displacedIndexOffset); return array.adjustArray(dimv, checkArray(displacedTo), displacement); } else { return array.adjustArray(dimv, initialElement, initialContents); } } private static final Primitive _ADJUST_ARRAY = new adjust_array(); } abcl-src-1.9.0/src/org/armedbear/lisp/and.lisp0100644 0000000 0000000 00000003405 14223403213 017634 0ustar000000000 0000000 ;;; and.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package "SYSTEM") (defmacro and (&rest forms) (cond ((endp forms) t) ((endp (rest forms)) (first forms)) (t `(if ,(first forms) (and ,@(rest forms)) nil)))) abcl-src-1.9.0/src/org/armedbear/lisp/apropos.lisp0100644 0000000 0000000 00000005630 14202767264 020577 0ustar000000000 0000000 ;;; apropos.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (defun apropos-list (string-designator &optional package-designator external-only) (if package-designator (let ((package (find-package package-designator)) (string (string string-designator)) (result nil)) (dolist (symbol (package-external-symbols package)) (declare (type symbol symbol)) (when (search string (symbol-name symbol) :test #'char-equal) (push symbol result))) (unless external-only (dolist (symbol (package-internal-symbols package)) (declare (type symbol symbol)) (when (search string (symbol-name symbol) :test #'char-equal) (push symbol result)))) result) (mapcan (lambda (package) (apropos-list string-designator package external-only)) (list-all-packages)))) (defun apropos (string-designator &optional package-designator external-only) (dolist (symbol (remove-duplicates (apropos-list string-designator package-designator external-only))) (fresh-line) (prin1 symbol) (when (boundp symbol) (write-string " (bound)")) (when (fboundp symbol) (write-string " (fbound)"))) (values)) abcl-src-1.9.0/src/org/armedbear/lisp/arglist.java0100644 0000000 0000000 00000011411 14202767264 020525 0ustar000000000 0000000 /* * arglist.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class arglist { static final Operator getOperator(LispObject obj) { if (obj instanceof Operator) return (Operator) obj; if (obj instanceof Symbol) { LispObject function = obj.getSymbolFunction(); if (function instanceof Autoload) { Autoload autoload = (Autoload) function; autoload.load(); function = autoload.getSymbol().getSymbolFunction(); } if (function instanceof Operator) { Operator operator = (Operator) function; if (operator.getLambdaList() != null) return operator; LispObject other = get(obj, Symbol.MACROEXPAND_MACRO, null); if (other != null) return getOperator(other); else return null; } } else if (obj instanceof Cons && obj.car() == Symbol.LAMBDA) return new Closure(obj, new Environment()); return null; } // ### arglist private static final Primitive ARGLIST = new Primitive("arglist", PACKAGE_EXT, true, "extended-function-designator") { @Override public LispObject execute(LispObject arg) { LispThread thread = LispThread.currentThread(); Operator operator = getOperator(arg); LispObject arglist = null; if (operator != null) arglist = operator.getLambdaList(); final LispObject value1, value2; if (arglist instanceof AbstractString) { String s = arglist.getStringValue(); // Give the string list syntax. s = "(" + s + ")"; // Bind *PACKAGE* so we use the EXT package if we need // to intern any symbols. final SpecialBindingsMark mark = thread.markSpecialBindings(); thread.bindSpecial(Symbol._PACKAGE_, PACKAGE_EXT); try { arglist = readObjectFromString(s); } finally { thread.resetSpecialBindings(mark); } operator.setLambdaList(arglist); } if (arglist != null) { value1 = arglist; value2 = T; } else { value1 = NIL; value2 = NIL; } return thread.setValues(value1, value2); } }; // ### %set-arglist private static final Primitive _SET_ARGLIST = new Primitive("%set-arglist", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject first, LispObject second) { Operator operator = null; if (first instanceof Operator) { operator = (Operator) first; } else if (first instanceof Symbol) { LispObject function = first.getSymbolFunction(); if (function instanceof Operator) operator = (Operator) function; } if (operator != null) operator.setLambdaList(second); return second; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/arrays.lisp0100644 0000000 0000000 00000007601 14223403213 020375 0ustar000000000 0000000 ;;; arrays.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defconstant array-total-size-limit most-positive-fixnum) (defconstant array-rank-limit 8) (defun make-array (dimensions &key (element-type t) (initial-element nil initial-element-p) initial-contents adjustable fill-pointer displaced-to displaced-index-offset (nio-direct nil nio-direct-p) (nio-buffer nil nio-buffer-p)) (setf element-type (normalize-type element-type)) (%make-array dimensions element-type initial-element initial-element-p initial-contents adjustable fill-pointer displaced-to displaced-index-offset nio-direct nio-direct-p nio-buffer nio-buffer-p)) (defun adjust-array (array new-dimensions &key (element-type (array-element-type array)) (initial-element nil initial-element-p) (initial-contents nil initial-contents-p) fill-pointer displaced-to displaced-index-offset) (%adjust-array array new-dimensions element-type initial-element initial-element-p initial-contents initial-contents-p fill-pointer displaced-to displaced-index-offset)) (defun array-row-major-index (array &rest subscripts) (%array-row-major-index array subscripts)) (defun bit (bit-array &rest subscripts) (row-major-aref bit-array (%array-row-major-index bit-array subscripts))) (defun sbit (simple-bit-array &rest subscripts) (row-major-aref simple-bit-array (%array-row-major-index simple-bit-array subscripts))) (defsetf row-major-aref aset) (defsetf aref aset) (defsetf bit aset) (defsetf sbit aset) ;; (SETF (APPLY #'AREF ... (defun (setf aref) (new-value array &rest subscripts) (aset array (%array-row-major-index array subscripts) new-value)) ;; (SETF (APPLY #'BIT ... (defun (setf bit) (new-value array &rest subscripts) (aset array (%array-row-major-index array subscripts) new-value)) ;; (SETF (APPLY #'SBIT ... (defun (setf sbit) (new-value array &rest subscripts) (aset array (%array-row-major-index array subscripts) new-value)) (push :nio *features*) abcl-src-1.9.0/src/org/armedbear/lisp/asdf.lisp0100644 0000000 0000000 00002545445 14202767264 020050 0ustar000000000 0000000 ;;; -*- mode: Lisp; Base: 10 ; Syntax: ANSI-Common-Lisp ; Package: CL-USER ; buffer-read-only: t; -*- ;;; This is ASDF 3.3.5.7: Another System Definition Facility. ;;; ;;; Feedback, bug reports, and patches are all welcome: ;;; please mail to . ;;; Note first that the canonical source for ASDF is presently ;;; . ;;; ;;; If you obtained this copy from anywhere else, and you experience ;;; trouble using it, or find bugs, you may want to check at the ;;; location above for a more recent version (and for documentation ;;; and test files, if your copy came without them) before reporting ;;; bugs. There are usually two "supported" revisions - the git master ;;; branch is the latest development version, whereas the git release ;;; branch may be slightly older but is considered `stable' ;;; -- LICENSE START ;;; (This is the MIT / X Consortium license as taken from ;;; http://www.opensource.org/licenses/mit-license.html on or about ;;; Monday; July 13, 2009) ;;; ;;; Copyright (c) 2001-2019 Daniel Barlow and contributors ;;; ;;; Permission is hereby granted, free of charge, to any person obtaining ;;; a copy of this software and associated documentation files (the ;;; "Software"), to deal in the Software without restriction, including ;;; without limitation the rights to use, copy, modify, merge, publish, ;;; distribute, sublicense, and/or sell copies of the Software, and to ;;; permit persons to whom the Software is furnished to do so, subject to ;;; the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be ;;; included in all copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ;;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ;;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ;;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ;;; ;;; -- LICENSE END ;;; The problem with writing a defsystem replacement is bootstrapping: ;;; we can't use defsystem to compile it. Hence, all in one file. #+genera (eval-when (:compile-toplevel :load-toplevel :execute) (multiple-value-bind (system-major system-minor) (sct:get-system-version) (multiple-value-bind (is-major is-minor) (sct:get-system-version "Intel-Support") (unless (or (> system-major 452) (and is-major (or (> is-major 3) (and (= is-major 3) (> is-minor 86))))) (error "ASDF requires either System 453 or later or Intel Support 3.87 or later"))))) ;;;; --------------------------------------------------------------------------- ;;;; ASDF package upgrade, including implementation-dependent magic. ;; ;; See https://bugs.launchpad.net/asdf/+bug/485687 ;; ;; CAUTION: The definition of the UIOP/PACKAGE package MUST NOT CHANGE, ;; NOT NOW, NOT EVER, NOT UNDER ANY CIRCUMSTANCE. NEVER. ;; ... and the same goes for UIOP/PACKAGE-LOCAL-NICKNAMES. ;; ;; The entire point of UIOP/PACKAGE is to address the fact that the CL standard ;; *leaves it unspecified what happens when a package is redefined incompatibly*. ;; For instance, SBCL 1.4.2 will signal a full WARNING when this happens, ;; throwing a wrench in upgrading code with ASDF itself, while continuing to ;; export old symbols it now shouldn't as it also exports new ones, ;; causing problems with code that relies on the new/current exports. ;; CLISP and CCL also exports both sets of symbols, though without any WARNING. ;; ABCL 1.6.1 will plainly ignore the new definition. ;; Other implementations may do whatever they want and change their behavior at any time. ;; ***Using DEFPACKAGE twice with different definitions is nasal-demon territory.*** ;; ;; Thus we define UIOP/PACKAGE:DEFINE-PACKAGE with which packages can be defined ;; in an upgrade-friendly way: the new definition is authoritative, and ;; the package will define and export exactly those symbols in the new definition, ;; no more and no fewer, whereas it is well-defined what happens to previous symbols. ;; However, for obvious bootstrap reasons, we cannot use DEFINE-PACKAGE ;; to define UIOP/PACKAGE itself, only DEFPACKAGE. ;; Therefore, unlike the other packages in ASDF, UIOP/PACKAGE is immutable, ;; now and forever. It is frozen for the aeons to come, like the CL package itself, ;; to the same exact state it was defined at its inception, in ASDF 2.27 in 2013. ;; The same goes for UIOP/PACKAGE-LOCAL-NICKNAMES, that we use internally. ;; ;; If you ever must define new symbols in this file, you can and must ;; export them from a different package, possibly defined in the same file, ;; say a package UIOP/PACKAGE* defined at the end of this file with DEFINE-PACKAGE, ;; that might use :import-from to import the symbols from UIOP/PACKAGE, ;; if you must somehow define them in UIOP/PACKAGE. (defpackage :uiop/package ;;; THOU SHALT NOT modify this definition, EVER. See explanations above. (:use :common-lisp) (:export #:find-package* #:find-symbol* #:symbol-call #:intern* #:export* #:import* #:shadowing-import* #:shadow* #:make-symbol* #:unintern* #:symbol-shadowing-p #:home-package-p #:symbol-package-name #:standard-common-lisp-symbol-p #:reify-package #:unreify-package #:reify-symbol #:unreify-symbol #:nuke-symbol-in-package #:nuke-symbol #:rehome-symbol #:ensure-package-unused #:delete-package* #:package-names #:packages-from-names #:fresh-package-name #:rename-package-away #:package-definition-form #:parse-define-package-form #:ensure-package #:define-package )) (in-package :uiop/package) ;;; package local nicknames feature. ;;; This can't be deferred until common-lisp.lisp, where most such features are set. ;;; ABCL and CCL already define this feature appropriately. ;;; Seems to be unconditionally present for SBCL, ACL, and CLASP ;;; Don't know about ECL, or others (eval-when (:load-toplevel :compile-toplevel :execute) ;; ABCL pushes :package-local-nicknames without UIOP interfering, ;; and Lispworks will do so #+(or sbcl clasp) (pushnew :package-local-nicknames *features*) #+allegro (let ((fname (find-symbol (symbol-name '#:add-package-local-nickname) '#:excl))) (when (and fname (fboundp fname)) (pushnew :package-local-nicknames *features*)))) ;;; THOU SHALT NOT modify this definition, EVER, *EXCEPT* to add a new implementation. ;; If you somehow need to modify the API in any way, ;; you will need to create another, differently named, and just as immutable package. #+package-local-nicknames (defpackage :uiop/package-local-nicknames (:use :cl) (:import-from #+allegro #:excl #+sbcl #:sb-ext #+(or clasp abcl ecl) #:ext #+ccl #:ccl #+lispworks #:hcl #-(or allegro sbcl clasp abcl ccl lispworks ecl) (error "Don't know from which package this lisp supplies the local-package-nicknames API.") #:remove-package-local-nickname #:package-local-nicknames #:add-package-local-nickname) (:export #:add-package-local-nickname #:remove-package-local-nickname #:package-local-nicknames)) ;;;; General purpose package utilities (eval-when (:load-toplevel :compile-toplevel :execute) (deftype package-designator () '(and (or package character string symbol) (satisfies find-package))) (define-condition no-such-package-error (type-error) () (:default-initargs :expected-type 'package-designator) (:report (lambda (c s) (format s "No package named ~a" (string (type-error-datum c)))))) (defmethod package-designator ((c no-such-package-error)) (type-error-datum c)) (defun find-package* (package-designator &optional (errorp t)) "Like CL:FIND-PACKAGE, but by default raises a UIOP:NO-SUCH-PACKAGE-ERROR if the package is not found." (let ((package (find-package package-designator))) (cond (package package) (errorp (error 'no-such-package-error :datum package-designator)) (t nil)))) (defun find-symbol* (name package-designator &optional (error t)) "Find a symbol in a package of given string'ified NAME; unlike CL:FIND-SYMBOL, work well with 'modern' case sensitive syntax by letting you supply a symbol or keyword for the name; also works well when the package is not present. If optional ERROR argument is NIL, return NIL instead of an error when the symbol is not found." (block nil (let ((package (find-package* package-designator error))) (when package ;; package error handled by find-package* already (multiple-value-bind (symbol status) (find-symbol (string name) package) (cond (status (return (values symbol status))) (error (error "There is no symbol ~S in package ~S" name (package-name package)))))) (values nil nil)))) (defun symbol-call (package name &rest args) "Call a function associated with symbol of given name in given package, with given ARGS. Useful when the call is read before the package is loaded, or when loading the package is optional." (apply (find-symbol* name package) args)) (defun intern* (name package-designator &optional (error t)) (intern (string name) (find-package* package-designator error))) (defun export* (name package-designator) (let* ((package (find-package* package-designator)) (symbol (intern* name package))) (export (or symbol (list symbol)) package))) (defun import* (symbol package-designator) (import (or symbol (list symbol)) (find-package* package-designator))) (defun shadowing-import* (symbol package-designator) (shadowing-import (or symbol (list symbol)) (find-package* package-designator))) (defun shadow* (name package-designator) (shadow (list (string name)) (find-package* package-designator))) (defun make-symbol* (name) (etypecase name (string (make-symbol name)) (symbol (copy-symbol name)))) (defun unintern* (name package-designator &optional (error t)) (block nil (let ((package (find-package* package-designator error))) (when package (multiple-value-bind (symbol status) (find-symbol* name package error) (cond (status (unintern symbol package) (return (values symbol status))) (error (error "symbol ~A not present in package ~A" (string symbol) (package-name package)))))) (values nil nil)))) (defun symbol-shadowing-p (symbol package) (and (member symbol (package-shadowing-symbols package)) t)) (defun home-package-p (symbol package) (and package (let ((sp (symbol-package symbol))) (and sp (let ((pp (find-package* package))) (and pp (eq sp pp)))))))) (eval-when (:load-toplevel :compile-toplevel :execute) (defun symbol-package-name (symbol) (let ((package (symbol-package symbol))) (and package (package-name package)))) (defun standard-common-lisp-symbol-p (symbol) (multiple-value-bind (sym status) (find-symbol* symbol :common-lisp nil) (and (eq sym symbol) (eq status :external)))) (defun reify-package (package &optional package-context) (if (eq package package-context) t (etypecase package (null nil) ((eql (find-package :cl)) :cl) (package (package-name package))))) (defun unreify-package (package &optional package-context) (etypecase package (null nil) ((eql t) package-context) ((or symbol string) (find-package package)))) (defun reify-symbol (symbol &optional package-context) (etypecase symbol ((or keyword (satisfies standard-common-lisp-symbol-p)) symbol) (symbol (vector (symbol-name symbol) (reify-package (symbol-package symbol) package-context))))) (defun unreify-symbol (symbol &optional package-context) (etypecase symbol (symbol symbol) ((simple-vector 2) (let* ((symbol-name (svref symbol 0)) (package-foo (svref symbol 1)) (package (unreify-package package-foo package-context))) (if package (intern* symbol-name package) (make-symbol* symbol-name))))))) (eval-when (:load-toplevel :compile-toplevel :execute) (defvar *all-package-happiness* '()) (defvar *all-package-fishiness* (list t)) (defun record-fishy (info) ;;(format t "~&FISHY: ~S~%" info) (push info *all-package-fishiness*)) (defmacro when-package-fishiness (&body body) `(when *all-package-fishiness* ,@body)) (defmacro note-package-fishiness (&rest info) `(when-package-fishiness (record-fishy (list ,@info))))) (eval-when (:load-toplevel :compile-toplevel :execute) #+(or clisp clozure) (defun get-setf-function-symbol (symbol) #+clisp (let ((sym (get symbol 'system::setf-function))) (if sym (values sym :setf-function) (let ((sym (get symbol 'system::setf-expander))) (if sym (values sym :setf-expander) (values nil nil))))) #+clozure (gethash symbol ccl::%setf-function-names%)) #+(or clisp clozure) (defun set-setf-function-symbol (new-setf-symbol symbol &optional kind) #+clisp (assert (member kind '(:setf-function :setf-expander))) #+clozure (assert (eq kind t)) #+clisp (cond ((null new-setf-symbol) (remprop symbol 'system::setf-function) (remprop symbol 'system::setf-expander)) ((eq kind :setf-function) (setf (get symbol 'system::setf-function) new-setf-symbol)) ((eq kind :setf-expander) (setf (get symbol 'system::setf-expander) new-setf-symbol)) (t (error "invalid kind of setf-function ~S for ~S to be set to ~S" kind symbol new-setf-symbol))) #+clozure (progn (gethash symbol ccl::%setf-function-names%) new-setf-symbol (gethash new-setf-symbol ccl::%setf-function-name-inverses%) symbol)) #+(or clisp clozure) (defun create-setf-function-symbol (symbol) #+clisp (system::setf-symbol symbol) #+clozure (ccl::construct-setf-function-name symbol)) (defun set-dummy-symbol (symbol reason other-symbol) (setf (get symbol 'dummy-symbol) (cons reason other-symbol))) (defun make-dummy-symbol (symbol) (let ((dummy (copy-symbol symbol))) (set-dummy-symbol dummy 'replacing symbol) (set-dummy-symbol symbol 'replaced-by dummy) dummy)) (defun dummy-symbol (symbol) (get symbol 'dummy-symbol)) (defun get-dummy-symbol (symbol) (let ((existing (dummy-symbol symbol))) (if existing (values (cdr existing) (car existing)) (make-dummy-symbol symbol)))) (defun nuke-symbol-in-package (symbol package-designator) (let ((package (find-package* package-designator)) (name (symbol-name symbol))) (multiple-value-bind (sym stat) (find-symbol name package) (when (and (member stat '(:internal :external)) (eq symbol sym)) (if (symbol-shadowing-p symbol package) (shadowing-import* (get-dummy-symbol symbol) package) (unintern* symbol package)))))) (defun nuke-symbol (symbol &optional (packages (list-all-packages))) #+(or clisp clozure) (multiple-value-bind (setf-symbol kind) (get-setf-function-symbol symbol) (when kind (nuke-symbol setf-symbol))) (loop :for p :in packages :do (nuke-symbol-in-package symbol p))) (defun rehome-symbol (symbol package-designator) "Changes the home package of a symbol, also leaving it present in its old home if any" (let* ((name (symbol-name symbol)) (package (find-package* package-designator)) (old-package (symbol-package symbol)) (old-status (and old-package (nth-value 1 (find-symbol name old-package)))) (shadowing (and old-package (symbol-shadowing-p symbol old-package) (make-symbol name)))) (multiple-value-bind (overwritten-symbol overwritten-symbol-status) (find-symbol name package) (unless (eq package old-package) (let ((overwritten-symbol-shadowing-p (and overwritten-symbol-status (symbol-shadowing-p overwritten-symbol package)))) (note-package-fishiness :rehome-symbol name (when old-package (package-name old-package)) old-status (and shadowing t) (package-name package) overwritten-symbol-status overwritten-symbol-shadowing-p) (when old-package (if shadowing (shadowing-import* shadowing old-package)) (unintern* symbol old-package)) (cond (overwritten-symbol-shadowing-p (shadowing-import* symbol package)) (t (when overwritten-symbol-status (unintern* overwritten-symbol package)) (import* symbol package))) (if shadowing (shadowing-import* symbol old-package) (import* symbol old-package)) #+(or clisp clozure) (multiple-value-bind (setf-symbol kind) (get-setf-function-symbol symbol) (when kind (let* ((setf-function (fdefinition setf-symbol)) (new-setf-symbol (create-setf-function-symbol symbol))) (note-package-fishiness :setf-function name (package-name package) (symbol-name setf-symbol) (symbol-package-name setf-symbol) (symbol-name new-setf-symbol) (symbol-package-name new-setf-symbol)) (when (symbol-package setf-symbol) (unintern* setf-symbol (symbol-package setf-symbol))) (setf (fdefinition new-setf-symbol) setf-function) (set-setf-function-symbol new-setf-symbol symbol kind)))) #+(or clisp clozure) (multiple-value-bind (overwritten-setf foundp) (get-setf-function-symbol overwritten-symbol) (when foundp (unintern overwritten-setf))) (when (eq old-status :external) (export* symbol old-package)) (when (eq overwritten-symbol-status :external) (export* symbol package)))) (values overwritten-symbol overwritten-symbol-status)))) (defun ensure-package-unused (package) (loop :for p :in (package-used-by-list package) :do (unuse-package package p))) (defun delete-package* (package &key nuke) (let ((p (find-package package))) (when p (when nuke (do-symbols (s p) (when (home-package-p s p) (nuke-symbol s)))) (ensure-package-unused p) (delete-package package)))) (defun package-names (package) (cons (package-name package) (package-nicknames package))) (defun packages-from-names (names) (remove-duplicates (remove nil (mapcar #'find-package names)) :from-end t)) (defun fresh-package-name (&key (prefix :%TO-BE-DELETED) separator (index (random most-positive-fixnum))) (loop :for i :from index :for n = (format nil "~A~@[~A~D~]" prefix (and (plusp i) (or separator "")) i) :thereis (and (not (find-package n)) n))) (defun rename-package-away (p &rest keys &key prefix &allow-other-keys) (let ((new-name (apply 'fresh-package-name :prefix (or prefix (format nil "__~A__" (package-name p))) keys))) (record-fishy (list :rename-away (package-names p) new-name)) (rename-package p new-name)))) ;;; Communicable representation of symbol and package information (eval-when (:load-toplevel :compile-toplevel :execute) (defun package-definition-form (package-designator &key (nicknamesp t) (usep t) (shadowp t) (shadowing-import-p t) (exportp t) (importp t) internp (error t)) (let* ((package (or (find-package* package-designator error) (return-from package-definition-form nil))) (name (package-name package)) (nicknames (package-nicknames package)) (use (mapcar #'package-name (package-use-list package))) (shadow ()) (shadowing-import (make-hash-table :test 'equal)) (import (make-hash-table :test 'equal)) (export ()) (intern ())) (when package (loop :for sym :being :the :symbols :in package :for status = (nth-value 1 (find-symbol* sym package)) :do (ecase status ((nil :inherited)) ((:internal :external) (let* ((name (symbol-name sym)) (external (eq status :external)) (home (symbol-package sym)) (home-name (package-name home)) (imported (not (eq home package))) (shadowing (symbol-shadowing-p sym package))) (cond ((and shadowing imported) (push name (gethash home-name shadowing-import))) (shadowing (push name shadow)) (imported (push name (gethash home-name import)))) (cond (external (push name export)) (imported) (t (push name intern))))))) (labels ((sort-names (names) (sort (copy-list names) #'string<)) (table-keys (table) (loop :for k :being :the :hash-keys :of table :collect k)) (when-relevant (key value) (when value (list (cons key value)))) (import-options (key table) (loop :for i :in (sort-names (table-keys table)) :collect `(,key ,i ,@(sort-names (gethash i table)))))) `(defpackage ,name ,@(when-relevant :nicknames (and nicknamesp (sort-names nicknames))) (:use ,@(and usep (sort-names use))) ,@(when-relevant :shadow (and shadowp (sort-names shadow))) ,@(import-options :shadowing-import-from (and shadowing-import-p shadowing-import)) ,@(import-options :import-from (and importp import)) ,@(when-relevant :export (and exportp (sort-names export))) ,@(when-relevant :intern (and internp (sort-names intern))))))))) ;;; ensure-package, define-package (eval-when (:load-toplevel :compile-toplevel :execute) ;; We already have UIOP:SIMPLE-STYLE-WARNING, but it comes from a later ;; package. (define-condition define-package-style-warning #+sbcl (sb-int:simple-style-warning) #-sbcl (simple-condition style-warning) ()) (defun ensure-shadowing-import (name to-package from-package shadowed imported) (check-type name string) (check-type to-package package) (check-type from-package package) (check-type shadowed hash-table) (check-type imported hash-table) (let ((import-me (find-symbol* name from-package))) (multiple-value-bind (existing status) (find-symbol name to-package) (cond ((gethash name shadowed) (unless (eq import-me existing) (error "Conflicting shadowings for ~A" name))) (t (setf (gethash name shadowed) t) (setf (gethash name imported) t) (unless (or (null status) (and (member status '(:internal :external)) (eq existing import-me) (symbol-shadowing-p existing to-package))) (note-package-fishiness :shadowing-import name (package-name from-package) (or (home-package-p import-me from-package) (symbol-package-name import-me)) (package-name to-package) status (and status (or (home-package-p existing to-package) (symbol-package-name existing))))) (shadowing-import* import-me to-package)))))) (defun ensure-imported (import-me into-package &optional from-package) (check-type import-me symbol) (check-type into-package package) (check-type from-package (or null package)) (let ((name (symbol-name import-me))) (multiple-value-bind (existing status) (find-symbol name into-package) (cond ((not status) (import* import-me into-package)) ((eq import-me existing)) (t (let ((shadowing-p (symbol-shadowing-p existing into-package))) (note-package-fishiness :ensure-imported name (and from-package (package-name from-package)) (or (home-package-p import-me from-package) (symbol-package-name import-me)) (package-name into-package) status (and status (or (home-package-p existing into-package) (symbol-package-name existing))) shadowing-p) (cond ((or shadowing-p (eq status :inherited)) (shadowing-import* import-me into-package)) (t (unintern* existing into-package) (import* import-me into-package)))))))) (values)) (defun ensure-import (name to-package from-package shadowed imported) (check-type name string) (check-type to-package package) (check-type from-package package) (check-type shadowed hash-table) (check-type imported hash-table) (multiple-value-bind (import-me import-status) (find-symbol name from-package) (when (null import-status) (note-package-fishiness :import-uninterned name (package-name from-package) (package-name to-package)) (setf import-me (intern* name from-package))) (multiple-value-bind (existing status) (find-symbol name to-package) (cond ((and imported (gethash name imported)) (unless (and status (eq import-me existing)) (error "Can't import ~S from both ~S and ~S" name (package-name (symbol-package existing)) (package-name from-package)))) ((gethash name shadowed) (error "Can't both shadow ~S and import it from ~S" name (package-name from-package))) (t (setf (gethash name imported) t)))) (ensure-imported import-me to-package from-package))) (defun ensure-inherited (name symbol to-package from-package mixp shadowed imported inherited) (check-type name string) (check-type symbol symbol) (check-type to-package package) (check-type from-package package) (check-type mixp (member nil t)) ; no cl:boolean on Genera (check-type shadowed hash-table) (check-type imported hash-table) (check-type inherited hash-table) (multiple-value-bind (existing status) (find-symbol name to-package) (let* ((sp (symbol-package symbol)) (in (gethash name inherited)) (xp (and status (symbol-package existing)))) (when (null sp) (note-package-fishiness :import-uninterned name (package-name from-package) (package-name to-package) mixp) (import* symbol from-package) (setf sp (package-name from-package))) (cond ((gethash name shadowed)) (in (unless (equal sp (first in)) (if mixp (ensure-shadowing-import name to-package (second in) shadowed imported) (error "Can't inherit ~S from ~S, it is inherited from ~S" name (package-name sp) (package-name (first in)))))) ((gethash name imported) (unless (eq symbol existing) (error "Can't inherit ~S from ~S, it is imported from ~S" name (package-name sp) (package-name xp)))) (t (setf (gethash name inherited) (list sp from-package)) (when (and status (not (eq sp xp))) (let ((shadowing (symbol-shadowing-p existing to-package))) (note-package-fishiness :inherited name (package-name from-package) (or (home-package-p symbol from-package) (symbol-package-name symbol)) (package-name to-package) (or (home-package-p existing to-package) (symbol-package-name existing))) (if shadowing (ensure-shadowing-import name to-package from-package shadowed imported) (unintern* existing to-package))))))))) (defun ensure-mix (name symbol to-package from-package shadowed imported inherited) (check-type name string) (check-type symbol symbol) (check-type to-package package) (check-type from-package package) (check-type shadowed hash-table) (check-type imported hash-table) (check-type inherited hash-table) (unless (gethash name shadowed) (multiple-value-bind (existing status) (find-symbol name to-package) (let* ((sp (symbol-package symbol)) (im (gethash name imported)) (in (gethash name inherited))) (cond ((or (null status) (and status (eq symbol existing)) (and in (eq sp (first in)))) (ensure-inherited name symbol to-package from-package t shadowed imported inherited)) (in (remhash name inherited) (ensure-shadowing-import name to-package (second in) shadowed imported)) (im (error "Symbol ~S import from ~S~:[~; actually ~:[uninterned~;~:*from ~S~]~] conflicts with existing symbol in ~S~:[~; actually ~:[uninterned~;from ~:*~S~]~]" name (package-name from-package) (home-package-p symbol from-package) (symbol-package-name symbol) (package-name to-package) (home-package-p existing to-package) (symbol-package-name existing))) (t (ensure-inherited name symbol to-package from-package t shadowed imported inherited))))))) (defun recycle-symbol (name recycle exported) ;; Takes a symbol NAME (a string), a list of package designators for RECYCLE ;; packages, and a hash-table of names (strings) of symbols scheduled to be ;; EXPORTED from the package being defined. It returns two values, the ;; symbol found (if any, or else NIL), and a boolean flag indicating whether ;; a symbol was found. The caller (DEFINE-PACKAGE) will then do the ;; re-homing of the symbol, etc. (check-type name string) (check-type recycle list) (check-type exported hash-table) (when (gethash name exported) ;; don't bother recycling private symbols (let (recycled foundp) (dolist (r recycle (values recycled foundp)) (multiple-value-bind (symbol status) (find-symbol name r) (when (and status (home-package-p symbol r)) (cond (foundp ;; (nuke-symbol symbol)) -- even simple variable names like O or C will do that. (note-package-fishiness :recycled-duplicate name (package-name foundp) (package-name r))) (t (setf recycled symbol foundp r))))))))) (defun symbol-recycled-p (sym recycle) (check-type sym symbol) (check-type recycle list) (and (member (symbol-package sym) recycle) t)) (defun ensure-symbol (name package intern recycle shadowed imported inherited exported) (check-type name string) (check-type package package) (check-type intern (member nil t)) ; no cl:boolean on Genera (check-type shadowed hash-table) (check-type imported hash-table) (check-type inherited hash-table) (unless (or (gethash name shadowed) (gethash name imported) (gethash name inherited)) (multiple-value-bind (existing status) (find-symbol name package) (multiple-value-bind (recycled previous) (recycle-symbol name recycle exported) (cond ((and status (eq existing recycled) (eq previous package))) (previous (rehome-symbol recycled package)) ((and status (eq package (symbol-package existing)))) (t (when status (note-package-fishiness :ensure-symbol name (reify-package (symbol-package existing) package) status intern) (unintern existing)) (when intern (intern* name package)))))))) (declaim (ftype (function (t t t &optional t) t) ensure-exported)) (defun ensure-exported-to-user (name symbol to-package &optional recycle) (check-type name string) (check-type symbol symbol) (check-type to-package package) (check-type recycle list) (assert (equal name (symbol-name symbol))) (multiple-value-bind (existing status) (find-symbol name to-package) (unless (and status (eq symbol existing)) (let ((accessible (or (null status) (let ((shadowing (symbol-shadowing-p existing to-package)) (recycled (symbol-recycled-p existing recycle))) (unless (and shadowing (not recycled)) (note-package-fishiness :ensure-export name (symbol-package-name symbol) (package-name to-package) (or (home-package-p existing to-package) (symbol-package-name existing)) status shadowing) (if (or (eq status :inherited) shadowing) (shadowing-import* symbol to-package) (unintern existing to-package)) t))))) (when (and accessible (eq status :external)) (ensure-exported name symbol to-package recycle)))))) (defun ensure-exported (name symbol from-package &optional recycle) (dolist (to-package (package-used-by-list from-package)) (ensure-exported-to-user name symbol to-package recycle)) (unless (eq from-package (symbol-package symbol)) (ensure-imported symbol from-package)) (export* name from-package)) (defun ensure-export (name from-package &optional recycle) (multiple-value-bind (symbol status) (find-symbol* name from-package) (unless (eq status :external) (ensure-exported name symbol from-package recycle)))) #+package-local-nicknames (defun install-package-local-nicknames (destination-package new-nicknames) ;; First, remove all package-local nicknames. (We'll reinstall any desired ones later.) (dolist (pair-to-remove (uiop/package-local-nicknames:package-local-nicknames destination-package)) (uiop/package-local-nicknames:remove-package-local-nickname (string (car pair-to-remove)) destination-package)) ;; Then, install all desired nicknames. (loop :for (nickname package) :in new-nicknames :do (uiop/package-local-nicknames:add-package-local-nickname (string nickname) (find-package package) destination-package))) (defun ensure-package (name &key nicknames documentation use shadow shadowing-import-from import-from export intern recycle mix reexport unintern local-nicknames) #+genera (declare (ignore documentation)) (let* ((package-name (string name)) (nicknames (mapcar #'string nicknames)) (names (cons package-name nicknames)) (previous (packages-from-names names)) (discarded (cdr previous)) (to-delete ()) (package (or (first previous) (make-package package-name :nicknames nicknames))) (recycle (packages-from-names recycle)) (use (mapcar 'find-package* use)) (mix (mapcar 'find-package* mix)) (reexport (mapcar 'find-package* reexport)) (shadow (mapcar 'string shadow)) (export (mapcar 'string export)) (intern (mapcar 'string intern)) (unintern (mapcar 'string unintern)) (local-nicknames (mapcar #'(lambda (pair) (mapcar 'string pair)) local-nicknames)) (shadowed (make-hash-table :test 'equal)) ; string to bool (imported (make-hash-table :test 'equal)) ; string to bool (exported (make-hash-table :test 'equal)) ; string to bool ;; string to list home package and use package: (inherited (make-hash-table :test 'equal))) #-package-local-nicknames (declare (ignore local-nicknames)) ; if not supported (when-package-fishiness (record-fishy package-name)) ;; if supported, put package documentation #-genera (when documentation (setf (documentation package t) documentation)) ;; remove unwanted packages from use list (loop :for p :in (set-difference (package-use-list package) (append mix use)) :do (note-package-fishiness :over-use name (package-names p)) (unuse-package p package)) ;; mark unwanted packages for deletion (loop :for p :in discarded :for n = (remove-if #'(lambda (x) (member x names :test 'equal)) (package-names p)) :do (note-package-fishiness :nickname name (package-names p)) (cond (n (rename-package p (first n) (rest n))) (t (rename-package-away p) (push p to-delete)))) ;; give package its desired name (rename-package package package-name nicknames) ;; Handle local nicknames #+package-local-nicknames (install-package-local-nicknames package local-nicknames) (dolist (name unintern) (multiple-value-bind (existing status) (find-symbol name package) (when status (unless (eq status :inherited) (note-package-fishiness :unintern (package-name package) name (symbol-package-name existing) status) (unintern* name package nil))))) ;; handle exports (dolist (name export) (setf (gethash name exported) t)) ;; handle reexportss (dolist (p reexport) (do-external-symbols (sym p) (setf (gethash (string sym) exported) t))) ;; unexport symbols not listed in (re)export (do-external-symbols (sym package) (let ((name (symbol-name sym))) (unless (gethash name exported) (note-package-fishiness :over-export (package-name package) name (or (home-package-p sym package) (symbol-package-name sym))) (unexport sym package)))) ;; handle explicitly listed shadowed ssymbols (dolist (name shadow) (setf (gethash name shadowed) t) (multiple-value-bind (existing status) (find-symbol name package) (multiple-value-bind (recycled previous) (recycle-symbol name recycle exported) (let ((shadowing (and status (symbol-shadowing-p existing package)))) (cond ((eq previous package)) (previous (rehome-symbol recycled package)) ((or (member status '(nil :inherited)) (home-package-p existing package))) (t (let ((dummy (make-symbol name))) (note-package-fishiness :shadow-imported (package-name package) name (symbol-package-name existing) status shadowing) (shadowing-import* dummy package) (import* dummy package))))))) (shadow* name package)) ;; handle shadowing imports (loop :for (p . syms) :in shadowing-import-from :for pp = (find-package* p) :do (dolist (sym syms) (ensure-shadowing-import (string sym) package pp shadowed imported))) ;; handle mixed packages (loop :for p :in mix :for pp = (find-package* p) :do (do-external-symbols (sym pp) (ensure-mix (symbol-name sym) sym package pp shadowed imported inherited))) ;; handle import-from packages (loop :for (p . syms) :in import-from ;; FOR NOW suppress errors in the case where the :import-from ;; symbol list is empty (used only to establish a dependency by ;; package-inferred-system users). :for pp = (find-package* p syms) :do (when (null pp) ;; TODO: ASDF 3.4 Change to a full warning. (warn 'define-package-style-warning :format-control "When defining package ~a, attempting to import-from non-existent package ~a. This is deprecated behavior and will be removed from UIOP in the future." :format-arguments (list name p))) (dolist (sym syms) (ensure-import (symbol-name sym) package pp shadowed imported))) ;; handle use-list and mix (dolist (p (append use mix)) (do-external-symbols (sym p) (ensure-inherited (string sym) sym package p nil shadowed imported inherited)) (use-package p package)) (loop :for name :being :the :hash-keys :of exported :do (ensure-symbol name package t recycle shadowed imported inherited exported) (ensure-export name package recycle)) ;; intern dessired symbols (dolist (name intern) (ensure-symbol name package t recycle shadowed imported inherited exported)) (do-symbols (sym package) (ensure-symbol (symbol-name sym) package nil recycle shadowed imported inherited exported)) ;; delete now-deceased packages (map () 'delete-package* to-delete) package))) (eval-when (:load-toplevel :compile-toplevel :execute) (defun parse-define-package-form (package clauses) (loop :with use-p = nil :with recycle-p = nil :with documentation = nil :for (kw . args) :in clauses :when (eq kw :nicknames) :append args :into nicknames :else :when (eq kw :documentation) :do (cond (documentation (error "define-package: can't define documentation twice")) ((or (atom args) (cdr args)) (error "define-package: bad documentation")) (t (setf documentation (car args)))) :else :when (eq kw :use) :append args :into use :and :do (setf use-p t) :else :when (eq kw :shadow) :append args :into shadow :else :when (eq kw :shadowing-import-from) :collect args :into shadowing-import-from :else :when (eq kw :import-from) :collect args :into import-from :else :when (eq kw :export) :append args :into export :else :when (eq kw :intern) :append args :into intern :else :when (eq kw :recycle) :append args :into recycle :and :do (setf recycle-p t) :else :when (eq kw :mix) :append args :into mix :else :when (eq kw :reexport) :append args :into reexport :else :when (eq kw :use-reexport) :append args :into use :and :append args :into reexport :and :do (setf use-p t) :else :when (eq kw :mix-reexport) :append args :into mix :and :append args :into reexport :and :do (setf use-p t) :else :when (eq kw :unintern) :append args :into unintern :else :when (eq kw :local-nicknames) :if (symbol-call '#:uiop '#:featurep :package-local-nicknames) :append args :into local-nicknames :else :do (error ":LOCAL-NICKAMES option is not supported on this lisp implementation.") :end :else :do (error "unrecognized define-package keyword ~S" kw) :finally (return `(',package :nicknames ',nicknames :documentation ',documentation :use ',(if use-p use '(:common-lisp)) :shadow ',shadow :shadowing-import-from ',shadowing-import-from :import-from ',import-from :export ',export :intern ',intern :recycle ',(if recycle-p recycle (cons package nicknames)) :mix ',mix :reexport ',reexport :unintern ',unintern ,@(when local-nicknames `(:local-nicknames ',local-nicknames))))))) (defmacro define-package (package &rest clauses) "DEFINE-PACKAGE takes a PACKAGE and a number of CLAUSES, of the form \(KEYWORD . ARGS\). DEFINE-PACKAGE supports the following keywords: USE, SHADOW, SHADOWING-IMPORT-FROM, IMPORT-FROM, EXPORT, INTERN, NICKNAMES, DOCUMENTATION -- as per CL:DEFPACKAGE. RECYCLE -- Recycle the package's exported symbols from the specified packages, in order. For every symbol scheduled to be exported by the DEFINE-PACKAGE, either through an :EXPORT option or a :REEXPORT option, if the symbol exists in one of the :RECYCLE packages, the first such symbol is re-homed to the package being defined. For the sake of idempotence, it is important that the package being defined should appear in first position if it already exists, and even if it doesn't, ahead of any package that is not going to be deleted afterwards and never created again. In short, except for special cases, always make it the first package on the list if the list is not empty. MIX -- Takes a list of package designators. MIX behaves like \(:USE PKG1 PKG2 ... PKGn\) but additionally uses :SHADOWING-IMPORT-FROM to resolve conflicts in favor of the first found symbol. It may still yield an error if there is a conflict with an explicitly :IMPORT-FROM symbol. REEXPORT -- Takes a list of package designators. For each package, p, in the list, export symbols with the same name as those exported from p. Note that in the case of shadowing, etc. the symbols with the same name may not be the same symbols. UNINTERN -- Remove symbols here from PACKAGE. LOCAL-NICKNAMES -- If the host implementation supports package local nicknames \(check for the :PACKAGE-LOCAL-NICKNAMES feature\), then this should be a list of nickname and package name pairs. Using this option will cause an error if the host CL implementation does not support it. USE-REEXPORT, MIX-REEXPORT -- Use or mix the specified packages as per the USE or MIX directives, and reexport their contents as per the REEXPORT directive." (let ((ensure-form `(prog1 (funcall 'ensure-package ,@(parse-define-package-form package clauses)) #+sbcl (setf (sb-impl::package-source-location (find-package ',package)) (sb-c:source-location))))) `(progn #+(or clasp ecl gcl mkcl) (defpackage ,package (:use)) (eval-when (:compile-toplevel :load-toplevel :execute) ,ensure-form)))) ;; This package, unlike UIOP/PACKAGE, is allowed to evolve and acquire new symbols or drop old ones. (define-package :uiop/package* (:use-reexport :uiop/package #+package-local-nicknames :uiop/package-local-nicknames) (:import-from :uiop/package #:define-package-style-warning #:no-such-package-error #:package-designator) (:export #:define-package-style-warning #:no-such-package-error #:package-designator)) ;;;; ------------------------------------------------------------------------- ;;;; Handle compatibility with multiple implementations. ;;; This file is for papering over the deficiencies and peculiarities ;;; of various Common Lisp implementations. ;;; For implementation-specific access to the system, see os.lisp instead. ;;; A few functions are defined here, but actually exported from utility; ;;; from this package only common-lisp symbols are exported. (uiop/package:define-package :uiop/common-lisp (:nicknames :uiop/cl) (:use :uiop/package) (:use-reexport #-genera :common-lisp #+genera :future-common-lisp) #+allegro (:intern #:*acl-warn-save*) #+cormanlisp (:shadow #:user-homedir-pathname) #+cormanlisp (:export #:logical-pathname #:translate-logical-pathname #:make-broadcast-stream #:file-namestring) #+genera (:shadowing-import-from :scl #:boolean) #+genera (:export #:boolean #:ensure-directories-exist #:read-sequence #:write-sequence) #+(or mcl cmucl) (:shadow #:user-homedir-pathname)) (in-package :uiop/common-lisp) #-(or abcl allegro clasp clisp clozure cmucl cormanlisp ecl gcl genera lispworks mcl mezzano mkcl sbcl scl xcl) (error "ASDF is not supported on your implementation. Please help us port it.") ;; (declaim (optimize (speed 1) (debug 3) (safety 3))) ; DON'T: trust implementation defaults. ;;;; Early meta-level tweaks #+(or allegro clasp clisp clozure cmucl ecl lispworks mezzano mkcl sbcl) (eval-when (:load-toplevel :compile-toplevel :execute) (when (and #+allegro (member :ics *features*) #+(or clasp clisp cmucl ecl lispworks mkcl) (member :unicode *features*) #+clozure (member :openmcl-unicode-strings *features*) #+sbcl (member :sb-unicode *features*)) ;; Check for unicode at runtime, so that a hypothetical FASL compiled with unicode ;; but loaded in a non-unicode setting (e.g. on Allegro) won't tell a lie. (pushnew :asdf-unicode *features*))) #+allegro (eval-when (:load-toplevel :compile-toplevel :execute) ;; We need to disable autoloading BEFORE any mention of package ASDF. ;; In particular, there must NOT be a mention of package ASDF in the defpackage of this file ;; or any previous file. (setf excl::*autoload-package-name-alist* (remove "asdf" excl::*autoload-package-name-alist* :test 'equalp :key 'car)) (defparameter *acl-warn-save* (when (boundp 'excl:*warn-on-nested-reader-conditionals*) excl:*warn-on-nested-reader-conditionals*)) (when (boundp 'excl:*warn-on-nested-reader-conditionals*) (setf excl:*warn-on-nested-reader-conditionals* nil)) (setf *print-readably* nil)) #+clasp (eval-when (:load-toplevel :compile-toplevel :execute) (setf *load-verbose* nil) (defun use-ecl-byte-compiler-p () nil)) #+clozure (in-package :ccl) #+(and clozure windows-target) ;; See http://trac.clozure.com/ccl/ticket/1117 (eval-when (:load-toplevel :compile-toplevel :execute) (unless (fboundp 'external-process-wait) (in-development-mode (defun external-process-wait (proc) (when (and (external-process-pid proc) (eq (external-process-%status proc) :running)) (with-interrupts-enabled (wait-on-semaphore (external-process-completed proc)))) (values (external-process-%exit-code proc) (external-process-%status proc)))))) #+clozure (in-package :uiop/common-lisp) ;; back in this package. #+cmucl (eval-when (:load-toplevel :compile-toplevel :execute) (setf ext:*gc-verbose* nil) (defun user-homedir-pathname () (first (ext:search-list (cl:user-homedir-pathname))))) #+cormanlisp (eval-when (:load-toplevel :compile-toplevel :execute) (deftype logical-pathname () nil) (defun make-broadcast-stream () *error-output*) (defun translate-logical-pathname (x) x) (defun user-homedir-pathname (&optional host) (declare (ignore host)) (parse-namestring (format nil "~A\\" (cl:user-homedir-pathname)))) (defun file-namestring (p) (setf p (pathname p)) (format nil "~@[~A~]~@[.~A~]" (pathname-name p) (pathname-type p)))) #+ecl (eval-when (:load-toplevel :compile-toplevel :execute) (setf *load-verbose* nil) (defun use-ecl-byte-compiler-p () (and (member :ecl-bytecmp *features*) t)) (unless (use-ecl-byte-compiler-p) (require :cmp))) #+gcl (eval-when (:load-toplevel :compile-toplevel :execute) (unless (member :ansi-cl *features*) (error "ASDF only supports GCL in ANSI mode. Aborting.~%")) (setf compiler::*compiler-default-type* (pathname "") compiler::*lsp-ext* "") #.(let ((code ;; Only support very recent GCL 2.7.0 from November 2013 or later. (cond #+gcl ((or (< system::*gcl-major-version* 2) (and (= system::*gcl-major-version* 2) (< system::*gcl-minor-version* 7))) '(error "GCL 2.7 or later required to use ASDF"))))) (eval code) code)) #+genera (eval-when (:load-toplevel :compile-toplevel :execute) (unless (fboundp 'lambda) (defmacro lambda (&whole form &rest bvl-decls-and-body) (declare (ignore bvl-decls-and-body)(zwei::indentation 1 1)) `#',(cons 'lisp::lambda (cdr form)))) (unless (fboundp 'ensure-directories-exist) (defun ensure-directories-exist (path) (fs:create-directories-recursively (pathname path)))) (unless (fboundp 'read-sequence) (defun read-sequence (sequence stream &key (start 0) end) (scl:send stream :string-in nil sequence start end))) (unless (fboundp 'write-sequence) (defun write-sequence (sequence stream &key (start 0) end) (scl:send stream :string-out sequence start end) sequence))) #+lispworks (eval-when (:load-toplevel :compile-toplevel :execute) ;; lispworks 3 and earlier cannot be checked for so we always assume ;; at least version 4 (unless (member :lispworks4 *features*) (pushnew :lispworks5+ *features*) (unless (member :lispworks5 *features*) (pushnew :lispworks6+ *features*) (unless (member :lispworks6 *features*) (pushnew :lispworks7+ *features*))))) #.(or #+mcl ;; the #$ doesn't work on other lisps, even protected by #+mcl, so we use this trick (read-from-string "(eval-when (:load-toplevel :compile-toplevel :execute) (ccl:define-entry-point (_getenv \"getenv\") ((name :string)) :string) (ccl:define-entry-point (_system \"system\") ((name :string)) :int) ;; Note: ASDF may expect user-homedir-pathname to provide ;; the pathname of the current user's home directory, whereas ;; MCL by default provides the directory from which MCL was started. ;; See http://code.google.com/p/mcl/wiki/Portability (defun user-homedir-pathname () (ccl::findfolder #$kuserdomain #$kCurrentUserFolderType)) (defun probe-posix (posix-namestring) \"If a file exists for the posix namestring, return the pathname\" (ccl::with-cstrs ((cpath posix-namestring)) (ccl::rlet ((is-dir :boolean) (fsref :fsref)) (when (eq #$noerr (#_fspathmakeref cpath fsref is-dir)) (ccl::%path-from-fsref fsref is-dir))))))")) #+mkcl (eval-when (:load-toplevel :compile-toplevel :execute) (require :cmp) (setq clos::*redefine-class-in-place* t)) ;; Make sure we have strict ANSI class redefinition semantics ;;;; compatfmt: avoid fancy format directives when unsupported (eval-when (:load-toplevel :compile-toplevel :execute) (defun frob-substrings (string substrings &optional frob) "for each substring in SUBSTRINGS, find occurrences of it within STRING that don't use parts of matched occurrences of previous strings, and FROB them, that is to say, remove them if FROB is NIL, replace by FROB if FROB is a STRING, or if FROB is a FUNCTION, call FROB with the match and a function that emits a string in the output. Return a string made of the parts not omitted or emitted by FROB." (declare (optimize (speed 0) (safety #-gcl 3 #+gcl 0) (debug 3))) (let ((length (length string)) (stream nil)) (labels ((emit-string (x &optional (start 0) (end (length x))) (when (< start end) (unless stream (setf stream (make-string-output-stream))) (write-string x stream :start start :end end))) (emit-substring (start end) (when (and (zerop start) (= end length)) (return-from frob-substrings string)) (emit-string string start end)) (recurse (substrings start end) (cond ((>= start end)) ((null substrings) (emit-substring start end)) (t (let* ((sub-spec (first substrings)) (sub (if (consp sub-spec) (car sub-spec) sub-spec)) (fun (if (consp sub-spec) (cdr sub-spec) frob)) (found (search sub string :start2 start :end2 end)) (more (rest substrings))) (cond (found (recurse more start found) (etypecase fun (null) (string (emit-string fun)) (function (funcall fun sub #'emit-string))) (recurse substrings (+ found (length sub)) end)) (t (recurse more start end)))))))) (recurse substrings 0 length)) (if stream (get-output-stream-string stream) ""))) (defmacro compatfmt (format) #+(or gcl genera) (frob-substrings format `("~3i~_" #+genera ,@'("~@<" "~@;" "~@:>" "~:>"))) #-(or gcl genera) format)) ;;;; ------------------------------------------------------------------------- ;;;; General Purpose Utilities for ASDF (uiop/package:define-package :uiop/utility (:use :uiop/common-lisp :uiop/package) ;; import and reexport a few things defined in :uiop/common-lisp (:import-from :uiop/common-lisp #:compatfmt #:frob-substrings #+(or clasp ecl) #:use-ecl-byte-compiler-p #+mcl #:probe-posix) (:export #:compatfmt #:frob-substrings #:compatfmt #+(or clasp ecl) #:use-ecl-byte-compiler-p #+mcl #:probe-posix) (:export ;; magic helper to define debugging functions: #:uiop-debug #:load-uiop-debug-utility #:*uiop-debug-utility* #:with-upgradability ;; (un)defining functions in an upgrade-friendly way #:nest #:if-let ;; basic flow control #:parse-body ;; macro definition helper #:while-collecting #:appendf #:length=n-p #:ensure-list ;; lists #:remove-plist-keys #:remove-plist-key ;; plists #:emptyp ;; sequences #:+non-base-chars-exist-p+ ;; characters #:+max-character-type-index+ #:character-type-index #:+character-types+ #:base-string-p #:strings-common-element-type #:reduce/strcat #:strcat ;; strings #:first-char #:last-char #:split-string #:stripln #:+cr+ #:+lf+ #:+crlf+ #:string-prefix-p #:string-enclosed-p #:string-suffix-p #:standard-case-symbol-name #:find-standard-case-symbol ;; symbols #:coerce-class ;; CLOS #:timestamp< #:timestamps< #:timestamp*< #:timestamp<= ;; timestamps #:earlier-timestamp #:timestamps-earliest #:earliest-timestamp #:later-timestamp #:timestamps-latest #:latest-timestamp #:latest-timestamp-f #:list-to-hash-set #:ensure-gethash ;; hash-table #:ensure-function #:access-at #:access-at-count ;; functions #:call-function #:call-functions #:register-hook-function #:lexicographic< #:lexicographic<= ;; version #:simple-style-warning #:style-warn ;; simple style warnings #:match-condition-p #:match-any-condition-p ;; conditions #:call-with-muffled-conditions #:with-muffled-conditions #:not-implemented-error #:parameter-error #:symbol-test-to-feature-expression #:boolean-to-feature-expression)) (in-package :uiop/utility) ;;;; Defining functions in a way compatible with hot-upgrade: ;; - The WTIH-UPGRADABILITY infrastructure below ensures that functions are declared NOTINLINE, ;; so that new definitions are always seen by all callers, even those up the stack. ;; - WITH-UPGRADABILITY also uses EVAL-WHEN so that definitions used by ASDF are in a limbo state ;; (especially for gf's) in between the COMPILE-OP and LOAD-OP operations on the defining file. ;; - THOU SHALT NOT redefine a function with a backward-incompatible semantics without renaming it, ;; at least if that function is used by ASDF while performing the plan to load ASDF. ;; - THOU SHALT change the name of a function whenever thou makest an incompatible change. ;; - For instance, when the meanings of NIL and T for timestamps was inverted, ;; functions in the STAMP<, STAMP<=, etc. family had to be renamed to TIMESTAMP<, TIMESTAMP<=, etc., ;; because the change other caused a huge incompatibility during upgrade. ;; - Whenever a function goes from a DEFUN to a DEFGENERIC, or the DEFGENERIC signature changes, etc., ;; even in a backward-compatible way, you MUST precede the definition by FMAKUNBOUND. ;; - Since FMAKUNBOUND will remove all the methods on the generic function, make sure that ;; all the methods required for ASDF to successfully continue compiling itself ;; shall be defined in the same file as the one with the FMAKUNBOUND, *after* the DEFGENERIC. ;; - When a function goes from DEFGENERIC to DEFUN, you may omit to use FMAKUNBOUND. ;; - For safety, you shall put the FMAKUNBOUND just before the DEFUN or DEFGENERIC, ;; in the same WITH-UPGRADABILITY form (and its implicit EVAL-WHEN). ;; - Any time you change a signature, please keep a comment specifying the first release after the change; ;; put that comment on the same line as FMAKUNBOUND, it you use FMAKUNBOUND. (eval-when (:load-toplevel :compile-toplevel :execute) (defun ensure-function-notinline (definition &aux (name (second definition))) (assert (member (first definition) '(defun defgeneric))) `(progn ,(when (and #+(or clasp ecl) (symbolp name)) ; NB: fails for (SETF functions) on ECL `(declaim (notinline ,name))) ,definition)) (defmacro with-upgradability ((&optional) &body body) "Evaluate BODY at compile- load- and run- times, with DEFUN and DEFGENERIC modified to also declare the functions NOTINLINE and to accept a wrapping the function name specification into a list with keyword argument SUPERSEDE (which defaults to T if the name is not wrapped, and NIL if it is wrapped). If SUPERSEDE is true, call UNDEFINE-FUNCTION to supersede any previous definition." `(eval-when (:compile-toplevel :load-toplevel :execute) ,@(loop :for form :in body :collect (if (consp form) (case (first form) ((defun defgeneric) (ensure-function-notinline form)) (otherwise form)) form))))) ;;; Magic debugging help. See contrib/debug.lisp (with-upgradability () (defvar *uiop-debug-utility* '(symbol-call :uiop :subpathname (symbol-call :uiop :uiop-directory) "contrib/debug.lisp") "form that evaluates to the pathname to your favorite debugging utilities") (defmacro uiop-debug (&rest keys) "Load the UIOP debug utility at compile-time as well as runtime" `(eval-when (:compile-toplevel :load-toplevel :execute) (load-uiop-debug-utility ,@keys))) (defun load-uiop-debug-utility (&key package utility-file) "Load the UIOP debug utility in given PACKAGE (default *PACKAGE*). Beware: The utility is located by EVAL'uating the UTILITY-FILE form (default *UIOP-DEBUG-UTILITY*)." (let* ((*package* (if package (find-package package) *package*)) (keyword (read-from-string (format nil ":DBG-~:@(~A~)" (package-name *package*))))) (unless (member keyword *features*) (let* ((utility-file (or utility-file *uiop-debug-utility*)) (file (ignore-errors (probe-file (eval utility-file))))) (if file (load file) (error "Failed to locate debug utility file: ~S" utility-file))))))) ;;; Flow control (with-upgradability () (defmacro nest (&rest things) "Macro to keep code nesting and indentation under control." ;; Thanks to mbaringer (reduce #'(lambda (outer inner) `(,@outer ,inner)) things :from-end t)) (defmacro if-let (bindings &body (then-form &optional else-form)) ;; from alexandria ;; bindings can be (var form) or ((var1 form1) ...) (let* ((binding-list (if (and (consp bindings) (symbolp (car bindings))) (list bindings) bindings)) (variables (mapcar #'car binding-list))) `(let ,binding-list (if (and ,@variables) ,then-form ,else-form))))) ;;; Macro definition helper (with-upgradability () (defun parse-body (body &key documentation whole) ;; from alexandria "Parses BODY into (values remaining-forms declarations doc-string). Documentation strings are recognized only if DOCUMENTATION is true. Syntax errors in body are signalled and WHOLE is used in the signal arguments when given." (let ((doc nil) (decls nil) (current nil)) (tagbody :declarations (setf current (car body)) (when (and documentation (stringp current) (cdr body)) (if doc (error "Too many documentation strings in ~S." (or whole body)) (setf doc (pop body))) (go :declarations)) (when (and (listp current) (eql (first current) 'declare)) (push (pop body) decls) (go :declarations))) (values body (nreverse decls) doc)))) ;;; List manipulation (with-upgradability () (defmacro while-collecting ((&rest collectors) &body body) "COLLECTORS should be a list of names for collections. A collector defines a function that, when applied to an argument inside BODY, will add its argument to the corresponding collection. Returns multiple values, a list for each collection, in order. E.g., \(while-collecting \(foo bar\) \(dolist \(x '\(\(a 1\) \(b 2\) \(c 3\)\)\) \(foo \(first x\)\) \(bar \(second x\)\)\)\) Returns two values: \(A B C\) and \(1 2 3\)." (let ((vars (mapcar #'(lambda (x) (gensym (symbol-name x))) collectors)) (initial-values (mapcar (constantly nil) collectors))) `(let ,(mapcar #'list vars initial-values) (flet ,(mapcar #'(lambda (c v) `(,c (x) (push x ,v) (values))) collectors vars) ,@body (values ,@(mapcar #'(lambda (v) `(reverse ,v)) vars)))))) (define-modify-macro appendf (&rest args) append "Append onto list") ;; only to be used on short lists. (defun length=n-p (x n) ;is it that (= (length x) n) ? (check-type n (integer 0 *)) (loop :for l = x :then (cdr l) :for i :downfrom n :do (cond ((zerop i) (return (null l))) ((not (consp l)) (return nil))))) (defun ensure-list (x) (if (listp x) x (list x)))) ;;; Remove a key from a plist, i.e. for keyword argument cleanup (with-upgradability () (defun remove-plist-key (key plist) "Remove a single key from a plist" (loop :for (k v) :on plist :by #'cddr :unless (eq k key) :append (list k v))) (defun remove-plist-keys (keys plist) "Remove a list of keys from a plist" (loop :for (k v) :on plist :by #'cddr :unless (member k keys) :append (list k v)))) ;;; Sequences (with-upgradability () (defun emptyp (x) "Predicate that is true for an empty sequence" (or (null x) (and (vectorp x) (zerop (length x)))))) ;;; Characters (with-upgradability () ;; base-char != character on ECL, LW, SBCL, Genera. ;; NB: We assume a total order on character types. ;; If that's not true... this code will need to be updated. (defparameter +character-types+ ;; assuming a simple hierarchy #.(coerce (loop :for (type next) :on '(;; In SCL, all characters seem to be 16-bit base-char ;; Yet somehow character fails to be a subtype of base-char #-scl base-char ;; LW6 has BASE-CHAR < SIMPLE-CHAR < CHARACTER ;; LW7 has BASE-CHAR < BMP-CHAR < SIMPLE-CHAR = CHARACTER #+lispworks7+ lw:bmp-char #+lispworks lw:simple-char character) :unless (and next (subtypep next type)) :collect type) 'vector)) (defparameter +max-character-type-index+ (1- (length +character-types+))) (defconstant +non-base-chars-exist-p+ (plusp +max-character-type-index+)) (when +non-base-chars-exist-p+ (pushnew :non-base-chars-exist-p *features*))) (with-upgradability () (defun character-type-index (x) (declare (ignorable x)) #.(case +max-character-type-index+ (0 0) (1 '(etypecase x (character (if (typep x 'base-char) 0 1)) (symbol (if (subtypep x 'base-char) 0 1)))) (otherwise '(or (position-if (etypecase x (character #'(lambda (type) (typep x type))) (symbol #'(lambda (type) (subtypep x type)))) +character-types+) (error "Not a character or character type: ~S" x)))))) ;;; Strings (with-upgradability () (defun base-string-p (string) "Does the STRING only contain BASE-CHARs?" (declare (ignorable string)) (and #+non-base-chars-exist-p (eq 'base-char (array-element-type string)))) (defun strings-common-element-type (strings) "What least subtype of CHARACTER can contain all the elements of all the STRINGS?" (declare (ignorable strings)) #.(if +non-base-chars-exist-p+ `(aref +character-types+ (loop :with index = 0 :for s :in strings :do (flet ((consider (i) (cond ((= i ,+max-character-type-index+) (return i)) ,@(when (> +max-character-type-index+ 1) `(((> i index) (setf index i))))))) (cond ((emptyp s)) ;; NIL or empty string ((characterp s) (consider (character-type-index s))) ((stringp s) (let ((string-type-index (character-type-index (array-element-type s)))) (unless (>= index string-type-index) (loop :for c :across s :for i = (character-type-index c) :do (consider i) ,@(when (> +max-character-type-index+ 1) `((when (= i string-type-index) (return)))))))) (t (error "Invalid string designator ~S for ~S" s 'strings-common-element-type)))) :finally (return index))) ''character)) (defun reduce/strcat (strings &key key start end) "Reduce a list as if by STRCAT, accepting KEY START and END keywords like REDUCE. NIL is interpreted as an empty string. A character is interpreted as a string of length one." (when (or start end) (setf strings (subseq strings start end))) (when key (setf strings (mapcar key strings))) (loop :with output = (make-string (loop :for s :in strings :sum (if (characterp s) 1 (length s))) :element-type (strings-common-element-type strings)) :with pos = 0 :for input :in strings :do (etypecase input (null) (character (setf (char output pos) input) (incf pos)) (string (replace output input :start1 pos) (incf pos (length input)))) :finally (return output))) (defun strcat (&rest strings) "Concatenate strings. NIL is interpreted as an empty string, a character as a string of length one." (reduce/strcat strings)) (defun first-char (s) "Return the first character of a non-empty string S, or NIL" (and (stringp s) (plusp (length s)) (char s 0))) (defun last-char (s) "Return the last character of a non-empty string S, or NIL" (and (stringp s) (plusp (length s)) (char s (1- (length s))))) (defun split-string (string &key max (separator '(#\Space #\Tab))) "Split STRING into a list of components separated by any of the characters in the sequence SEPARATOR. If MAX is specified, then no more than max(1,MAX) components will be returned, starting the separation from the end, e.g. when called with arguments \"a.b.c.d.e\" :max 3 :separator \".\" it will return (\"a.b.c\" \"d\" \"e\")." (block () (let ((list nil) (words 0) (end (length string))) (when (zerop end) (return nil)) (flet ((separatorp (char) (find char separator)) (done () (return (cons (subseq string 0 end) list)))) (loop :for start = (if (and max (>= words (1- max))) (done) (position-if #'separatorp string :end end :from-end t)) :do (when (null start) (done)) (push (subseq string (1+ start) end) list) (incf words) (setf end start)))))) (defun string-prefix-p (prefix string) "Does STRING begin with PREFIX?" (let* ((x (string prefix)) (y (string string)) (lx (length x)) (ly (length y))) (and (<= lx ly) (string= x y :end2 lx)))) (defun string-suffix-p (string suffix) "Does STRING end with SUFFIX?" (let* ((x (string string)) (y (string suffix)) (lx (length x)) (ly (length y))) (and (<= ly lx) (string= x y :start1 (- lx ly))))) (defun string-enclosed-p (prefix string suffix) "Does STRING begin with PREFIX and end with SUFFIX?" (and (string-prefix-p prefix string) (string-suffix-p string suffix))) (defvar +cr+ (coerce #(#\Return) 'string)) (defvar +lf+ (coerce #(#\Linefeed) 'string)) (defvar +crlf+ (coerce #(#\Return #\Linefeed) 'string)) (defun stripln (x) "Strip a string X from any ending CR, LF or CRLF. Return two values, the stripped string and the ending that was stripped, or the original value and NIL if no stripping took place. Since our STRCAT accepts NIL as empty string designator, the two results passed to STRCAT always reconstitute the original string" (check-type x string) (block nil (flet ((c (end) (when (string-suffix-p x end) (return (values (subseq x 0 (- (length x) (length end))) end))))) (when x (c +crlf+) (c +lf+) (c +cr+) (values x nil))))) (defun standard-case-symbol-name (name-designator) "Given a NAME-DESIGNATOR for a symbol, if it is a symbol, convert it to a string using STRING; if it is a string, use STRING-UPCASE on an ANSI CL platform, or STRING on a so-called \"modern\" platform such as Allegro with modern syntax." (check-type name-designator (or string symbol)) (cond ((or (symbolp name-designator) #+allegro (eq excl:*current-case-mode* :case-sensitive-lower)) (string name-designator)) ;; Should we be doing something on CLISP? (t (string-upcase name-designator)))) (defun find-standard-case-symbol (name-designator package-designator &optional (error t)) "Find a symbol designated by NAME-DESIGNATOR in a package designated by PACKAGE-DESIGNATOR, where STANDARD-CASE-SYMBOL-NAME is used to transform them if these designators are strings. If optional ERROR argument is NIL, return NIL instead of an error when the symbol is not found." (find-symbol* (standard-case-symbol-name name-designator) (etypecase package-designator ((or package symbol) package-designator) (string (standard-case-symbol-name package-designator))) error))) ;;; timestamps: a REAL or a boolean where T=-infinity, NIL=+infinity (eval-when (#-lispworks :compile-toplevel :load-toplevel :execute) (deftype timestamp () '(or real boolean))) (with-upgradability () (defun timestamp< (x y) (etypecase x ((eql t) (not (eql y t))) (real (etypecase y ((eql t) nil) (real (< x y)) (null t))) (null nil))) (defun timestamps< (list) (loop :for y :in list :for x = nil :then y :always (timestamp< x y))) (defun timestamp*< (&rest list) (timestamps< list)) (defun timestamp<= (x y) (not (timestamp< y x))) (defun earlier-timestamp (x y) (if (timestamp< x y) x y)) (defun timestamps-earliest (list) (reduce 'earlier-timestamp list :initial-value nil)) (defun earliest-timestamp (&rest list) (timestamps-earliest list)) (defun later-timestamp (x y) (if (timestamp< x y) y x)) (defun timestamps-latest (list) (reduce 'later-timestamp list :initial-value t)) (defun latest-timestamp (&rest list) (timestamps-latest list)) (define-modify-macro latest-timestamp-f (&rest timestamps) latest-timestamp)) ;;; Function designators (with-upgradability () (defun ensure-function (fun &key (package :cl)) "Coerce the object FUN into a function. If FUN is a FUNCTION, return it. If the FUN is a non-sequence literal constant, return constantly that, i.e. for a boolean keyword character number or pathname. Otherwise if FUN is a non-literally constant symbol, return its FDEFINITION. If FUN is a CONS, return the function that applies its CAR to the appended list of the rest of its CDR and the arguments, unless the CAR is LAMBDA, in which case the expression is evaluated. If FUN is a string, READ a form from it in the specified PACKAGE (default: CL) and EVAL that in a (FUNCTION ...) context." (etypecase fun (function fun) ((or boolean keyword character number pathname) (constantly fun)) (hash-table #'(lambda (x) (gethash x fun))) (symbol (fdefinition fun)) (cons (if (eq 'lambda (car fun)) (eval fun) #'(lambda (&rest args) (apply (car fun) (append (cdr fun) args))))) (string (eval `(function ,(with-standard-io-syntax (let ((*package* (find-package package))) (read-from-string fun)))))))) (defun access-at (object at) "Given an OBJECT and an AT specifier, list of successive accessors, call each accessor on the result of the previous calls. An accessor may be an integer, meaning a call to ELT, a keyword, meaning a call to GETF, NIL, meaning identity, a function or other symbol, meaning itself, or a list of a function designator and arguments, interpreted as per ENSURE-FUNCTION. As a degenerate case, the AT specifier may be an atom of a single such accessor instead of a list." (flet ((access (object accessor) (etypecase accessor (function (funcall accessor object)) (integer (elt object accessor)) (keyword (getf object accessor)) (null object) (symbol (funcall accessor object)) (cons (funcall (ensure-function accessor) object))))) (if (listp at) (dolist (accessor at object) (setf object (access object accessor))) (access object at)))) (defun access-at-count (at) "From an AT specification, extract a COUNT of maximum number of sub-objects to read as per ACCESS-AT" (cond ((integerp at) (1+ at)) ((and (consp at) (integerp (first at))) (1+ (first at))))) (defun call-function (function-spec &rest arguments) "Call the function designated by FUNCTION-SPEC as per ENSURE-FUNCTION, with the given ARGUMENTS" (apply (ensure-function function-spec) arguments)) (defun call-functions (function-specs) "For each function in the list FUNCTION-SPECS, in order, call the function as per CALL-FUNCTION" (map () 'call-function function-specs)) (defun register-hook-function (variable hook &optional call-now-p) "Push the HOOK function (a designator as per ENSURE-FUNCTION) onto the hook VARIABLE. When CALL-NOW-P is true, also call the function immediately." (pushnew hook (symbol-value variable) :test 'equal) (when call-now-p (call-function hook)))) ;;; CLOS (with-upgradability () (defun coerce-class (class &key (package :cl) (super t) (error 'error)) "Coerce CLASS to a class that is subclass of SUPER if specified, or invoke ERROR handler as per CALL-FUNCTION. A keyword designates the name a symbol, which when found in either PACKAGE, designates a class. -- for backward compatibility, *PACKAGE* is also accepted for now, but this may go in the future. A string is read as a symbol while in PACKAGE, the symbol designates a class. A class object designates itself. NIL designates itself (no class). A symbol otherwise designates a class by name." (let* ((normalized (typecase class (keyword (or (find-symbol* class package nil) (find-symbol* class *package* nil))) (string (symbol-call :uiop :safe-read-from-string class :package package)) (t class))) (found (etypecase normalized ((or standard-class built-in-class) normalized) ((or null keyword) nil) (symbol (find-class normalized nil nil)))) (super-class (etypecase super ((or standard-class built-in-class) super) ((or null keyword) nil) (symbol (find-class super nil nil))))) #+allegro (when found (mop:finalize-inheritance found)) (or (and found (or (eq super t) (#-cormanlisp subtypep #+cormanlisp cl::subclassp found super-class)) found) (call-function error "Can't coerce ~S to a ~:[class~;subclass of ~:*~S~]" class super))))) ;;; Hash-tables (with-upgradability () (defun ensure-gethash (key table default) "Lookup the TABLE for a KEY as by GETHASH, but if not present, call the (possibly constant) function designated by DEFAULT as per CALL-FUNCTION, set the corresponding entry to the result in the table. Return two values: the entry after its optional computation, and whether it was found" (multiple-value-bind (value foundp) (gethash key table) (values (if foundp value (setf (gethash key table) (call-function default))) foundp))) (defun list-to-hash-set (list &aux (h (make-hash-table :test 'equal))) "Convert a LIST into hash-table that has the same elements when viewed as a set, up to the given equality TEST" (dolist (x list h) (setf (gethash x h) t)))) ;;; Lexicographic comparison of lists of numbers (with-upgradability () (defun lexicographic< (element< x y) "Lexicographically compare two lists of using the function element< to compare elements. element< is a strict total order; the resulting order on X and Y will also be strict." (cond ((null y) nil) ((null x) t) ((funcall element< (car x) (car y)) t) ((funcall element< (car y) (car x)) nil) (t (lexicographic< element< (cdr x) (cdr y))))) (defun lexicographic<= (element< x y) "Lexicographically compare two lists of using the function element< to compare elements. element< is a strict total order; the resulting order on X and Y will be a non-strict total order." (not (lexicographic< element< y x)))) ;;; Simple style warnings (with-upgradability () (define-condition simple-style-warning #+sbcl (sb-int:simple-style-warning) #-sbcl (simple-condition style-warning) ()) (defun style-warn (datum &rest arguments) (etypecase datum (string (warn (make-condition 'simple-style-warning :format-control datum :format-arguments arguments))) (symbol (assert (subtypep datum 'style-warning)) (apply 'warn datum arguments)) (style-warning (apply 'warn datum arguments))))) ;;; Condition control (with-upgradability () (defparameter +simple-condition-format-control-slot+ #+abcl 'system::format-control #+allegro 'excl::format-control #+(or clasp ecl mkcl) 'si::format-control #+clisp 'system::$format-control #+clozure 'ccl::format-control #+(or cmucl scl) 'conditions::format-control #+(or gcl lispworks) 'conditions::format-string #+sbcl 'sb-kernel:format-control #-(or abcl allegro clasp clisp clozure cmucl ecl gcl lispworks mkcl sbcl scl) nil "Name of the slot for FORMAT-CONTROL in simple-condition") (defun match-condition-p (x condition) "Compare received CONDITION to some pattern X: a symbol naming a condition class, a simple vector of length 2, arguments to find-symbol* with result as above, or a string describing the format-control of a simple-condition." (etypecase x (symbol (typep condition x)) ((simple-vector 2) (ignore-errors (typep condition (find-symbol* (svref x 0) (svref x 1) nil)))) (function (funcall x condition)) (string (and (typep condition 'simple-condition) ;; On SBCL, it's always set and the check triggers a warning #+(or allegro clozure cmucl lispworks scl) (slot-boundp condition +simple-condition-format-control-slot+) (ignore-errors (equal (simple-condition-format-control condition) x)))))) (defun match-any-condition-p (condition conditions) "match CONDITION against any of the patterns of CONDITIONS supplied" (loop :for x :in conditions :thereis (match-condition-p x condition))) (defun call-with-muffled-conditions (thunk conditions) "calls the THUNK in a context where the CONDITIONS are muffled" (handler-bind ((t #'(lambda (c) (when (match-any-condition-p c conditions) (muffle-warning c))))) (funcall thunk))) (defmacro with-muffled-conditions ((conditions) &body body) "Shorthand syntax for CALL-WITH-MUFFLED-CONDITIONS" `(call-with-muffled-conditions #'(lambda () ,@body) ,conditions))) ;;; Conditions (with-upgradability () (define-condition not-implemented-error (error) ((functionality :initarg :functionality) (format-control :initarg :format-control) (format-arguments :initarg :format-arguments)) (:report (lambda (condition stream) (format stream "Not (currently) implemented on ~A: ~S~@[ ~?~]" (nth-value 1 (symbol-call :uiop :implementation-type)) (slot-value condition 'functionality) (slot-value condition 'format-control) (slot-value condition 'format-arguments))))) (defun not-implemented-error (functionality &optional format-control &rest format-arguments) "Signal an error because some FUNCTIONALITY is not implemented in the current version of the software on the current platform; it may or may not be implemented in different combinations of version of the software and of the underlying platform. Optionally, report a formatted error message." (error 'not-implemented-error :functionality functionality :format-control format-control :format-arguments format-arguments)) (define-condition parameter-error (error) ((functionality :initarg :functionality) (format-control :initarg :format-control) (format-arguments :initarg :format-arguments)) (:report (lambda (condition stream) (apply 'format stream (slot-value condition 'format-control) (slot-value condition 'functionality) (slot-value condition 'format-arguments))))) ;; Note that functionality MUST be passed as the second argument to parameter-error, just after ;; the format-control. If you want it to not appear in first position in actual message, use ;; ~* and ~:* to adjust parameter order. (defun parameter-error (format-control functionality &rest format-arguments) "Signal an error because some FUNCTIONALITY or its specific implementation on a given underlying platform does not accept a given parameter or combination of parameters. Report a formatted error message, that takes the functionality as its first argument (that can be skipped with ~*)." (error 'parameter-error :functionality functionality :format-control format-control :format-arguments format-arguments))) (with-upgradability () (defun boolean-to-feature-expression (value) "Converts a boolean VALUE to a form suitable for testing with #+." (if value '(:and) '(:or))) (defun symbol-test-to-feature-expression (name package) "Check if a symbol with a given NAME exists in PACKAGE and returns a form suitable for testing with #+." (boolean-to-feature-expression (find-symbol* name package nil)))) (uiop/package:define-package :uiop/version (:recycle :uiop/version :uiop/utility :asdf) (:use :uiop/common-lisp :uiop/package :uiop/utility) (:export #:*uiop-version* #:parse-version #:unparse-version #:version< #:version<= #:version= ;; version support, moved from uiop/utility #:next-version #:deprecated-function-condition #:deprecated-function-name ;; deprecation control #:deprecated-function-style-warning #:deprecated-function-warning #:deprecated-function-error #:deprecated-function-should-be-deleted #:version-deprecation #:with-deprecation)) (in-package :uiop/version) (with-upgradability () (defparameter *uiop-version* "3.3.5.7") (defun unparse-version (version-list) "From a parsed version (a list of natural numbers), compute the version string" (format nil "~{~D~^.~}" version-list)) (defun parse-version (version-string &optional on-error) "Parse a VERSION-STRING as a series of natural numbers separated by dots. Return a (non-null) list of integers if the string is valid; otherwise return NIL. When invalid, ON-ERROR is called as per CALL-FUNCTION before to return NIL, with format arguments explaining why the version is invalid. ON-ERROR is also called if the version is not canonical in that it doesn't print back to itself, but the list is returned anyway." (block nil (unless (stringp version-string) (call-function on-error "~S: ~S is not a string" 'parse-version version-string) (return)) (unless (loop :for prev = nil :then c :for c :across version-string :always (or (digit-char-p c) (and (eql c #\.) prev (not (eql prev #\.)))) :finally (return (and c (digit-char-p c)))) (call-function on-error "~S: ~S doesn't follow asdf version numbering convention" 'parse-version version-string) (return)) (let* ((version-list (mapcar #'parse-integer (split-string version-string :separator "."))) (normalized-version (unparse-version version-list))) (unless (equal version-string normalized-version) (call-function on-error "~S: ~S contains leading zeros" 'parse-version version-string)) version-list))) (defun next-version (version) "When VERSION is not nil, it is a string, then parse it as a version, compute the next version and return it as a string." (when version (let ((version-list (parse-version version))) (incf (car (last version-list))) (unparse-version version-list)))) (defun version< (version1 version2) "Given two version strings, return T if the second is strictly newer" (let ((v1 (parse-version version1 nil)) (v2 (parse-version version2 nil))) (lexicographic< '< v1 v2))) (defun version<= (version1 version2) "Given two version strings, return T if the second is newer or the same" (not (version< version2 version1)))) (defun version= (version1 version2) "Given two version strings, return T if the first is newer or the same and the second is also newer or the same." (and (version<= version1 version2) (version<= version2 version1))) (with-upgradability () (define-condition deprecated-function-condition (condition) ((name :initarg :name :reader deprecated-function-name))) (define-condition deprecated-function-style-warning (deprecated-function-condition style-warning) ()) (define-condition deprecated-function-warning (deprecated-function-condition warning) ()) (define-condition deprecated-function-error (deprecated-function-condition error) ()) (define-condition deprecated-function-should-be-deleted (deprecated-function-condition error) ()) (defun deprecated-function-condition-kind (type) (ecase type ((deprecated-function-style-warning) :style-warning) ((deprecated-function-warning) :warning) ((deprecated-function-error) :error) ((deprecated-function-should-be-deleted) :delete))) (defmethod print-object ((c deprecated-function-condition) stream) (let ((name (deprecated-function-name c))) (cond (*print-readably* (let ((fmt "#.(make-condition '~S :name ~S)") (args (list (type-of c) name))) (if *read-eval* (apply 'format stream fmt args) (error "Can't print ~?" fmt args)))) (*print-escape* (print-unreadable-object (c stream :type t) (format stream ":name ~S" name))) (t (let ((*package* (find-package :cl)) (type (type-of c))) (format stream (if (eq type 'deprecated-function-should-be-deleted) "~A: Still defining deprecated function~:P ~{~S~^ ~} that promised to delete" "~A: Using deprecated function ~S -- please update your code to use a newer API.~ ~@[~%The docstring for this function says:~%~A~%~]") type name (when (symbolp name) (documentation name 'function)))))))) (defun notify-deprecated-function (status name) (ecase status ((nil) nil) ((:style-warning) (style-warn 'deprecated-function-style-warning :name name)) ((:warning) (warn 'deprecated-function-warning :name name)) ((:error) (cerror "USE FUNCTION ANYWAY" 'deprecated-function-error :name name)))) (defun version-deprecation (version &key (style-warning nil) (warning (next-version style-warning)) (error (next-version warning)) (delete (next-version error))) "Given a VERSION string, and the starting versions for notifying the programmer of various levels of deprecation, return the current level of deprecation as per WITH-DEPRECATION that is the highest level that has a declared version older than the specified version. Each start version for a level of deprecation can be specified by a keyword argument, or if left unspecified, will be the NEXT-VERSION of the immediate lower level of deprecation." (cond ((and delete (version<= delete version)) :delete) ((and error (version<= error version)) :error) ((and warning (version<= warning version)) :warning) ((and style-warning (version<= style-warning version)) :style-warning))) (defmacro with-deprecation ((level) &body definitions) "Given a deprecation LEVEL (a form to be EVAL'ed at macro-expansion time), instrument the DEFUN and DEFMETHOD forms in DEFINITIONS to notify the programmer of the deprecation of the function when it is compiled or called. Increasing levels (as result from evaluating LEVEL) are: NIL (not deprecated yet), :STYLE-WARNING (a style warning is issued when used), :WARNING (a full warning is issued when used), :ERROR (a continuable error instead), and :DELETE (it's an error if the code is still there while at that level). Forms other than DEFUN and DEFMETHOD are not instrumented, and you can protect a DEFUN or DEFMETHOD from instrumentation by enclosing it in a PROGN." (let ((level (eval level))) (check-type level (member nil :style-warning :warning :error :delete)) (when (eq level :delete) (error 'deprecated-function-should-be-deleted :name (mapcar 'second (remove-if-not #'(lambda (x) (member x '(defun defmethod))) definitions :key 'first)))) (labels ((instrument (name head body whole) (if level (let ((notifiedp (intern (format nil "*~A-~A-~A-~A*" :deprecated-function level name :notified-p)))) (multiple-value-bind (remaining-forms declarations doc-string) (parse-body body :documentation t :whole whole) `(progn (defparameter ,notifiedp nil) ;; tell some implementations to use the compiler-macro (declaim (inline ,name)) (define-compiler-macro ,name (&whole form &rest args) (declare (ignore args)) (notify-deprecated-function ,level ',name) form) (,@head ,@(when doc-string (list doc-string)) ,@declarations (unless ,notifiedp (setf ,notifiedp t) (notify-deprecated-function ,level ',name)) ,@remaining-forms)))) `(progn (eval-when (:compile-toplevel :load-toplevel :execute) (setf (compiler-macro-function ',name) nil)) (declaim (notinline ,name)) (,@head ,@body))))) `(progn ,@(loop :for form :in definitions :collect (cond ((and (consp form) (eq (car form) 'defun)) (instrument (second form) (subseq form 0 3) (subseq form 3) form)) ((and (consp form) (eq (car form) 'defmethod)) (let ((body-start (if (listp (third form)) 3 4))) (instrument (second form) (subseq form 0 body-start) (subseq form body-start) form))) (t form)))))))) ;;;; --------------------------------------------------------------------------- ;;;; Access to the Operating System (uiop/package:define-package :uiop/os (:use :uiop/common-lisp :uiop/package :uiop/utility) (:export #:featurep #:os-unix-p #:os-macosx-p #:os-windows-p #:os-genera-p #:detect-os ;; features #:os-cond #:getenv #:getenvp ;; environment variables #:implementation-identifier ;; implementation identifier #:implementation-type #:*implementation-type* #:operating-system #:architecture #:lisp-version-string #:hostname #:getcwd #:chdir ;; Windows shortcut support #:read-null-terminated-string #:read-little-endian #:parse-file-location-info #:parse-windows-shortcut)) (in-package :uiop/os) ;;; Features (with-upgradability () (defun featurep (x &optional (*features* *features*)) "Checks whether a feature expression X is true with respect to the *FEATURES* set, as per the CLHS standard for #+ and #-. Beware that just like the CLHS, we assume symbols from the KEYWORD package are used, but that unless you're using #+/#- your reader will not have magically used the KEYWORD package, so you need specify keywords explicitly." (cond ((atom x) (and (member x *features*) t)) ((eq :not (car x)) (assert (null (cddr x))) (not (featurep (cadr x)))) ((eq :or (car x)) (some #'featurep (cdr x))) ((eq :and (car x)) (every #'featurep (cdr x))) (t (parameter-error "~S: malformed feature specification ~S" 'featurep x)))) ;; Starting with UIOP 3.1.5, these are runtime tests. ;; You may bind *features* with a copy of what your target system offers to test its properties. (defun os-macosx-p () "Is the underlying operating system MacOS X?" ;; OS-MACOSX is not mutually exclusive with OS-UNIX, ;; in fact the former implies the latter. (featurep '(:or :darwin (:and :allegro :macosx) (:and :clisp :macos)))) (defun os-unix-p () "Is the underlying operating system some Unix variant?" (or (featurep '(:or :unix :cygwin :haiku)) (os-macosx-p))) (defun os-windows-p () "Is the underlying operating system Microsoft Windows?" (and (not (os-unix-p)) (featurep '(:or :win32 :windows :mswindows :mingw32 :mingw64)))) (defun os-genera-p () "Is the underlying operating system Genera (running on a Symbolics Lisp Machine)?" (featurep :genera)) (defun os-oldmac-p () "Is the underlying operating system an (emulated?) MacOS 9 or earlier?" (featurep :mcl)) (defun os-haiku-p () "Is the underlying operating system Haiku?" (featurep :haiku)) (defun os-mezzano-p () "Is the underlying operating system Mezzano?" (featurep :mezzano)) (defun detect-os () "Detects the current operating system. Only needs be run at compile-time, except on ABCL where it might change between FASL compilation and runtime." (loop :with o :for (feature . detect) :in '((:os-unix . os-unix-p) (:os-macosx . os-macosx-p) (:os-windows . os-windows-p) (:os-genera . os-genera-p) (:os-oldmac . os-oldmac-p) (:os-haiku . os-haiku-p) (:os-mezzano . os-mezzano-p)) :when (and (or (not o) (eq feature :os-macosx) (eq feature :os-haiku)) (funcall detect)) :do (setf o feature) (pushnew feature *features*) :else :do (setf *features* (remove feature *features*)) :finally (return (or o (error "Congratulations for trying ASDF on an operating system~%~ that is neither Unix, nor Windows, nor Genera, nor even old MacOS.~%Now you port it."))))) (defmacro os-cond (&rest clauses) #+abcl `(cond ,@clauses) #-abcl (loop :for (test . body) :in clauses :when (eval test) :return `(progn ,@body))) (detect-os)) ;;;; Environment variables: getting them, and parsing them. (with-upgradability () (defun getenv (x) "Query the environment, as in C getenv. Beware: may return empty string if a variable is present but empty; use getenvp to return NIL in such a case." (declare (ignorable x)) #+(or abcl clasp clisp ecl xcl) (ext:getenv x) #+allegro (sys:getenv x) #+clozure (ccl:getenv x) #+cmucl (unix:unix-getenv x) #+scl (cdr (assoc x ext:*environment-list* :test #'string=)) #+cormanlisp (let* ((buffer (ct:malloc 1)) (cname (ct:lisp-string-to-c-string x)) (needed-size (win:getenvironmentvariable cname buffer 0)) (buffer1 (ct:malloc (1+ needed-size)))) (prog1 (if (zerop (win:getenvironmentvariable cname buffer1 needed-size)) nil (ct:c-string-to-lisp-string buffer1)) (ct:free buffer) (ct:free buffer1))) #+gcl (system:getenv x) #+(or genera mezzano) nil #+lispworks (lispworks:environment-variable x) #+mcl (ccl:with-cstrs ((name x)) (let ((value (_getenv name))) (unless (ccl:%null-ptr-p value) (ccl:%get-cstring value)))) #+mkcl (#.(or (find-symbol* 'getenv :si nil) (find-symbol* 'getenv :mk-ext nil)) x) #+sbcl (sb-ext:posix-getenv x) #-(or abcl allegro clasp clisp clozure cmucl cormanlisp ecl gcl genera lispworks mcl mezzano mkcl sbcl scl xcl) (not-implemented-error 'getenv)) (defsetf getenv (x) (val) "Set an environment variable." (declare (ignorable x val)) #+allegro `(setf (sys:getenv ,x) ,val) #+clasp `(ext:setenv ,x ,val) #+clisp `(system::setenv ,x ,val) #+clozure `(ccl:setenv ,x ,val) #+cmucl `(unix:unix-setenv ,x ,val 1) #+(or ecl clasp) `(ext:setenv ,x ,val) #+lispworks `(setf (lispworks:environment-variable ,x) ,val) #+mkcl `(mkcl:setenv ,x ,val) #+sbcl `(progn (require :sb-posix) (symbol-call :sb-posix :setenv ,x ,val 1)) #-(or allegro clasp clisp clozure cmucl ecl lispworks mkcl sbcl) '(not-implemented-error '(setf getenv))) (defun getenvp (x) "Predicate that is true if the named variable is present in the libc environment, then returning the non-empty string value of the variable" (let ((g (getenv x))) (and (not (emptyp g)) g)))) ;;;; implementation-identifier ;; ;; produce a string to identify current implementation. ;; Initially stolen from SLIME's SWANK, completely rewritten since. ;; We're back to runtime checking, for the sake of e.g. ABCL. (with-upgradability () (defun first-feature (feature-sets) "A helper for various feature detection functions" (dolist (x feature-sets) (multiple-value-bind (short long feature-expr) (if (consp x) (values (first x) (second x) (cons :or (rest x))) (values x x x)) (when (featurep feature-expr) (return (values short long)))))) (defun implementation-type () "The type of Lisp implementation used, as a short UIOP-standardized keyword" (first-feature '(:abcl (:acl :allegro) (:ccl :clozure) :clisp (:corman :cormanlisp) (:cmu :cmucl :cmu) :clasp :ecl :gcl (:lwpe :lispworks-personal-edition) (:lw :lispworks) :mcl :mezzano :mkcl :sbcl :scl (:smbx :symbolics) :xcl))) (defvar *implementation-type* (implementation-type) "The type of Lisp implementation used, as a short UIOP-standardized keyword") (defun operating-system () "The operating system of the current host" (first-feature '(:cygwin (:win :windows :mswindows :win32 :mingw32) ;; try cygwin first! (:linux :linux :linux-target) ;; for GCL at least, must appear before :bsd (:macosx :macosx :darwin :darwin-target :apple) ; also before :bsd (:solaris :solaris :sunos) (:bsd :bsd :freebsd :netbsd :openbsd :dragonfly) :unix :genera :mezzano))) (defun architecture () "The CPU architecture of the current host" (first-feature '((:x64 :x86-64 :x86_64 :x8664-target :amd64 (:and :word-size=64 :pc386)) (:x86 :x86 :i386 :i486 :i586 :i686 :pentium3 :pentium4 :pc386 :iapx386 :x8632-target) (:ppc64 :ppc64 :ppc64-target) (:ppc32 :ppc32 :ppc32-target :ppc :powerpc) :hppa64 :hppa :sparc64 (:sparc32 :sparc32 :sparc) :mipsel :mipseb :mips :alpha (:arm64 :arm64 :aarch64 :armv8l :armv8b :aarch64_be :|aarch64|) (:arm :arm :arm-target) :vlm :imach ;; Java comes last: if someone uses C via CFFI or otherwise JNA or JNI, ;; we may have to segregate the code still by architecture. (:java :java :java-1.4 :java-1.5 :java-1.6 :java-1.7)))) #+clozure (defun ccl-fasl-version () ;; the fasl version is target-dependent from CCL 1.8 on. (or (let ((s 'ccl::target-fasl-version)) (and (fboundp s) (funcall s))) (and (boundp 'ccl::fasl-version) (symbol-value 'ccl::fasl-version)) (error "Can't determine fasl version."))) (defun lisp-version-string () "return a string that identifies the current Lisp implementation version" (let ((s (lisp-implementation-version))) (car ; as opposed to OR, this idiom prevents some unreachable code warning (list #+allegro (format nil "~A~@[~A~]~@[~A~]~@[~A~]" excl::*common-lisp-version-number* ;; M means "modern", as opposed to ANSI-compatible mode (which I consider default) (and (eq excl:*current-case-mode* :case-sensitive-lower) "M") ;; Note if not using International ACL ;; see http://www.franz.com/support/documentation/8.1/doc/operators/excl/ics-target-case.htm (excl:ics-target-case (:-ics "8")) (and (member :smp *features*) "S")) #+armedbear (format nil "~a-fasl~a" s system::*fasl-version*) #+clisp (subseq s 0 (position #\space s)) ; strip build information (date, etc.) #+clozure (format nil "~d.~d-f~d" ; shorten for windows ccl::*openmcl-major-version* ccl::*openmcl-minor-version* (logand (ccl-fasl-version) #xFF)) #+cmucl (substitute #\- #\/ s) #+scl (format nil "~A~A" s ;; ANSI upper case vs lower case. (ecase ext:*case-mode* (:upper "") (:lower "l"))) #+ecl (format nil "~A~@[-~A~]" s (let ((vcs-id (ext:lisp-implementation-vcs-id))) (unless (equal vcs-id "UNKNOWN") (subseq vcs-id 0 (min (length vcs-id) 8))))) #+gcl (subseq s (1+ (position #\space s))) #+genera (multiple-value-bind (major minor) (sct:get-system-version "System") (format nil "~D.~D" major minor)) #+mcl (subseq s 8) ; strip the leading "Version " #+mezzano (format nil "~A-~D" (subseq s 0 (position #\space s)) ; strip commit hash sys.int::*llf-version*) ;; seems like there should be a shorter way to do this, like ACALL. #+mkcl (or (let ((fname (find-symbol* '#:git-describe-this-mkcl :mkcl nil))) (when (and fname (fboundp fname)) (funcall fname))) s) s)))) (defun implementation-identifier () "Return a string that identifies the ABI of the current implementation, suitable for use as a directory name to segregate Lisp FASLs, C dynamic libraries, etc." (substitute-if #\_ #'(lambda (x) (find x " /:;&^\\|?<>(){}[]$#`'\"")) (format nil "~(~a~@{~@[-~a~]~}~)" (or (implementation-type) (lisp-implementation-type)) (lisp-version-string) (or (operating-system) (software-type)) (or (architecture) (machine-type)))))) ;;;; Other system information (with-upgradability () (defun hostname () "return the hostname of the current host" #+(or abcl clasp clozure cmucl ecl genera lispworks mcl mezzano mkcl sbcl scl xcl) (machine-instance) #+cormanlisp "localhost" ;; is there a better way? Does it matter? #+allegro (symbol-call :excl.osi :gethostname) #+clisp (first (split-string (machine-instance) :separator " ")) #+gcl (system:gethostname))) ;;; Current directory (with-upgradability () #+cmucl (defun parse-unix-namestring* (unix-namestring) "variant of LISP::PARSE-UNIX-NAMESTRING that returns a pathname object" (multiple-value-bind (host device directory name type version) (lisp::parse-unix-namestring unix-namestring 0 (length unix-namestring)) (make-pathname :host (or host lisp::*unix-host*) :device device :directory directory :name name :type type :version version))) (defun getcwd () "Get the current working directory as per POSIX getcwd(3), as a pathname object" (or #+(or abcl genera mezzano xcl) (truename *default-pathname-defaults*) ;; d-p-d is canonical! #+allegro (excl::current-directory) #+clisp (ext:default-directory) #+clozure (ccl:current-directory) #+(or cmucl scl) (#+cmucl parse-unix-namestring* #+scl lisp::parse-unix-namestring (strcat (nth-value 1 (unix:unix-current-directory)) "/")) #+cormanlisp (pathname (pl::get-current-directory)) ;; Q: what type does it return? #+(or clasp ecl) (ext:getcwd) #+gcl (let ((*default-pathname-defaults* #p"")) (truename #p"")) #+lispworks (hcl:get-working-directory) #+mkcl (mk-ext:getcwd) #+sbcl (sb-ext:parse-native-namestring (sb-unix:posix-getcwd/)) #+xcl (extensions:current-directory) (not-implemented-error 'getcwd))) (defun chdir (x) "Change current directory, as per POSIX chdir(2), to a given pathname object" (if-let (x (pathname x)) #+(or abcl genera mezzano xcl) (setf *default-pathname-defaults* (truename x)) ;; d-p-d is canonical! #+allegro (excl:chdir x) #+clisp (ext:cd x) #+clozure (setf (ccl:current-directory) x) #+(or cmucl scl) (unix:unix-chdir (ext:unix-namestring x)) #+cormanlisp (unless (zerop (win32::_chdir (namestring x))) (error "Could not set current directory to ~A" x)) #+ecl (ext:chdir x) #+clasp (ext:chdir x t) #+gcl (system:chdir x) #+lispworks (hcl:change-directory x) #+mkcl (mk-ext:chdir x) #+sbcl (progn (require :sb-posix) (symbol-call :sb-posix :chdir (sb-ext:native-namestring x))) #-(or abcl allegro clasp clisp clozure cmucl cormanlisp ecl gcl genera lispworks mkcl sbcl scl xcl) (not-implemented-error 'chdir)))) ;;;; ----------------------------------------------------------------- ;;;; Windows shortcut support. Based on: ;;;; ;;;; Jesse Hager: The Windows Shortcut File Format. ;;;; http://www.wotsit.org/list.asp?fc=13 #-(or clisp genera) ; CLISP doesn't need it, and READ-SEQUENCE annoys old Genera that doesn't need it (with-upgradability () (defparameter *link-initial-dword* 76) (defparameter *link-guid* #(1 20 2 0 0 0 0 0 192 0 0 0 0 0 0 70)) (defun read-null-terminated-string (s) "Read a null-terminated string from an octet stream S" ;; note: doesn't play well with UNICODE (with-output-to-string (out) (loop :for code = (read-byte s) :until (zerop code) :do (write-char (code-char code) out)))) (defun read-little-endian (s &optional (bytes 4)) "Read a number in little-endian format from an byte (octet) stream S, the number having BYTES octets (defaulting to 4)." (loop :for i :from 0 :below bytes :sum (ash (read-byte s) (* 8 i)))) (defun parse-file-location-info (s) "helper to parse-windows-shortcut" (let ((start (file-position s)) (total-length (read-little-endian s)) (end-of-header (read-little-endian s)) (fli-flags (read-little-endian s)) (local-volume-offset (read-little-endian s)) (local-offset (read-little-endian s)) (network-volume-offset (read-little-endian s)) (remaining-offset (read-little-endian s))) (declare (ignore total-length end-of-header local-volume-offset)) (unless (zerop fli-flags) (cond ((logbitp 0 fli-flags) (file-position s (+ start local-offset))) ((logbitp 1 fli-flags) (file-position s (+ start network-volume-offset #x14)))) (strcat (read-null-terminated-string s) (progn (file-position s (+ start remaining-offset)) (read-null-terminated-string s)))))) (defun parse-windows-shortcut (pathname) "From a .lnk windows shortcut, extract the pathname linked to" ;; NB: doesn't do much checking & doesn't look like it will work well with UNICODE. (with-open-file (s pathname :element-type '(unsigned-byte 8)) (handler-case (when (and (= (read-little-endian s) *link-initial-dword*) (let ((header (make-array (length *link-guid*)))) (read-sequence header s) (equalp header *link-guid*))) (let ((flags (read-little-endian s))) (file-position s 76) ;skip rest of header (when (logbitp 0 flags) ;; skip shell item id list (let ((length (read-little-endian s 2))) (file-position s (+ length (file-position s))))) (cond ((logbitp 1 flags) (parse-file-location-info s)) (t (when (logbitp 2 flags) ;; skip description string (let ((length (read-little-endian s 2))) (file-position s (+ length (file-position s))))) (when (logbitp 3 flags) ;; finally, our pathname (let* ((length (read-little-endian s 2)) (buffer (make-array length))) (read-sequence buffer s) (map 'string #'code-char buffer))))))) (end-of-file (c) (declare (ignore c)) nil))))) ;;;; ------------------------------------------------------------------------- ;;;; Portability layer around Common Lisp pathnames ;; This layer allows for portable manipulation of pathname objects themselves, ;; which all is necessary prior to any access the filesystem or environment. (uiop/package:define-package :uiop/pathname (:nicknames :asdf/pathname) ;; deprecated. Used by ceramic (:use :uiop/common-lisp :uiop/package :uiop/utility :uiop/os) (:export ;; Making and merging pathnames, portably #:normalize-pathname-directory-component #:denormalize-pathname-directory-component #:merge-pathname-directory-components #:*unspecific-pathname-type* #:make-pathname* #:make-pathname-component-logical #:make-pathname-logical #:merge-pathnames* #:nil-pathname #:*nil-pathname* #:with-pathname-defaults ;; Predicates #:pathname-equal #:logical-pathname-p #:physical-pathname-p #:physicalize-pathname #:absolute-pathname-p #:relative-pathname-p #:hidden-pathname-p #:file-pathname-p ;; Directories #:pathname-directory-pathname #:pathname-parent-directory-pathname #:directory-pathname-p #:ensure-directory-pathname ;; Parsing filenames #:split-name-type #:parse-unix-namestring #:unix-namestring #:split-unix-namestring-directory-components ;; Absolute and relative pathnames #:subpathname #:subpathname* #:ensure-absolute-pathname #:pathname-root #:pathname-host-pathname #:subpathp #:enough-pathname #:with-enough-pathname #:call-with-enough-pathname ;; Checking constraints #:ensure-pathname ;; implemented in filesystem.lisp to accommodate for existence constraints ;; Wildcard pathnames #:*wild* #:*wild-file* #:*wild-file-for-directory* #:*wild-directory* #:*wild-inferiors* #:*wild-path* #:wilden ;; Translate a pathname #:relativize-directory-component #:relativize-pathname-directory #:directory-separator-for-host #:directorize-pathname-host-device #:translate-pathname* #:*output-translation-function*)) (in-package :uiop/pathname) ;;; Normalizing pathnames across implementations (with-upgradability () (defun normalize-pathname-directory-component (directory) "Convert the DIRECTORY component from a format usable by the underlying implementation's MAKE-PATHNAME and other primitives to a CLHS-standard format that is a list and not a string." (cond #-(or cmucl sbcl scl) ;; these implementations already normalize directory components. ((stringp directory) `(:absolute ,directory)) ((or (null directory) (and (consp directory) (member (first directory) '(:absolute :relative)))) directory) #+gcl ((consp directory) (cons :relative directory)) (t (parameter-error (compatfmt "~@<~S: Unrecognized pathname directory component ~S~@:>") 'normalize-pathname-directory-component directory)))) (defun denormalize-pathname-directory-component (directory-component) "Convert the DIRECTORY-COMPONENT from a CLHS-standard format to a format usable by the underlying implementation's MAKE-PATHNAME and other primitives" directory-component) (defun merge-pathname-directory-components (specified defaults) "Helper for MERGE-PATHNAMES* that handles directory components" (let ((directory (normalize-pathname-directory-component specified))) (ecase (first directory) ((nil) defaults) (:absolute specified) (:relative (let ((defdir (normalize-pathname-directory-component defaults)) (reldir (cdr directory))) (cond ((null defdir) directory) ((not (eq :back (first reldir))) (append defdir reldir)) (t (loop :with defabs = (first defdir) :with defrev = (reverse (rest defdir)) :while (and (eq :back (car reldir)) (or (and (eq :absolute defabs) (null defrev)) (stringp (car defrev)))) :do (pop reldir) (pop defrev) :finally (return (cons defabs (append (reverse defrev) reldir))))))))))) ;; Giving :unspecific as :type argument to make-pathname is not portable. ;; See CLHS make-pathname and 19.2.2.2.3. ;; This will be :unspecific if supported, or NIL if not. (defparameter *unspecific-pathname-type* #+(or abcl allegro clozure cmucl lispworks sbcl scl) :unspecific #+(or genera clasp clisp ecl mkcl gcl xcl #|These haven't been tested:|# cormanlisp mcl mezzano) nil "Unspecific type component to use with the underlying implementation's MAKE-PATHNAME") (defun make-pathname* (&rest keys &key directory host device name type version defaults #+scl &allow-other-keys) "Takes arguments like CL:MAKE-PATHNAME in the CLHS, and tries hard to make a pathname that will actually behave as documented, despite the peculiarities of each implementation. DEPRECATED: just use MAKE-PATHNAME." (declare (ignore host device directory name type version defaults)) (apply 'make-pathname keys)) (defun make-pathname-component-logical (x) "Make a pathname component suitable for use in a logical-pathname" (typecase x ((eql :unspecific) nil) #+clisp (string (string-upcase x)) #+clisp (cons (mapcar 'make-pathname-component-logical x)) (t x))) (defun make-pathname-logical (pathname host) "Take a PATHNAME's directory, name, type and version components, and make a new pathname with corresponding components and specified logical HOST" (make-pathname :host host :directory (make-pathname-component-logical (pathname-directory pathname)) :name (make-pathname-component-logical (pathname-name pathname)) :type (make-pathname-component-logical (pathname-type pathname)) :version (make-pathname-component-logical (pathname-version pathname)))) (defun merge-pathnames* (specified &optional (defaults *default-pathname-defaults*)) "MERGE-PATHNAMES* is like MERGE-PATHNAMES except that if the SPECIFIED pathname does not have an absolute directory, then the HOST and DEVICE both come from the DEFAULTS, whereas if the SPECIFIED pathname does have an absolute directory, then the HOST and DEVICE both come from the SPECIFIED pathname. This is what users want on a modern Unix or Windows operating system, unlike the MERGE-PATHNAMES behavior. Also, if either argument is NIL, then the other argument is returned unmodified; this is unlike MERGE-PATHNAMES which always merges with a pathname, by default *DEFAULT-PATHNAME-DEFAULTS*, which cannot be NIL." (when (null specified) (return-from merge-pathnames* defaults)) (when (null defaults) (return-from merge-pathnames* specified)) #+scl (ext:resolve-pathname specified defaults) #-scl (let* ((specified (pathname specified)) (defaults (pathname defaults)) (directory (normalize-pathname-directory-component (pathname-directory specified))) (name (or (pathname-name specified) (pathname-name defaults))) (type (or (pathname-type specified) (pathname-type defaults))) (version (or (pathname-version specified) (pathname-version defaults)))) (labels ((unspecific-handler (p) (if (typep p 'logical-pathname) #'make-pathname-component-logical #'identity))) (multiple-value-bind (host device directory unspecific-handler) (ecase (first directory) ((:absolute) (values (pathname-host specified) (pathname-device specified) directory (unspecific-handler specified))) ((nil :relative) (values (pathname-host defaults) (pathname-device defaults) (merge-pathname-directory-components directory (pathname-directory defaults)) (unspecific-handler defaults)))) (make-pathname :host host :device device :directory directory :name (funcall unspecific-handler name) :type (funcall unspecific-handler type) :version (funcall unspecific-handler version)))))) (defun logical-pathname-p (x) "is X a logical-pathname?" (typep x 'logical-pathname)) (defun physical-pathname-p (x) "is X a pathname that is not a logical-pathname?" (and (pathnamep x) (not (logical-pathname-p x)))) (defun physicalize-pathname (x) "if X is a logical pathname, use translate-logical-pathname on it." ;; Ought to be the same as translate-logical-pathname, except the latter borks on CLISP (let ((p (when x (pathname x)))) (if (logical-pathname-p p) (translate-logical-pathname p) p))) (defun nil-pathname (&optional (defaults *default-pathname-defaults*)) "A pathname that is as neutral as possible for use as defaults when merging, making or parsing pathnames" ;; 19.2.2.2.1 says a NIL host can mean a default host; ;; see also "valid physical pathname host" in the CLHS glossary, that suggests ;; strings and lists of strings or :unspecific ;; But CMUCL decides to die on NIL. ;; MCL has issues with make-pathname, nil and defaulting (declare (ignorable defaults)) #.`(make-pathname :directory nil :name nil :type nil :version nil :device (or #+(and mkcl os-unix) :unspecific) :host (or #+cmucl lisp::*unix-host* #+(and mkcl os-unix) "localhost") #+scl ,@'(:scheme nil :scheme-specific-part nil :username nil :password nil :parameters nil :query nil :fragment nil) ;; the default shouldn't matter, but we really want something physical #-mcl ,@'(:defaults defaults))) (defvar *nil-pathname* (nil-pathname (physicalize-pathname (user-homedir-pathname))) "A pathname that is as neutral as possible for use as defaults when merging, making or parsing pathnames") (defmacro with-pathname-defaults ((&optional defaults) &body body) "Execute BODY in a context where the *DEFAULT-PATHNAME-DEFAULTS* is as specified, where leaving the defaults NIL or unspecified means a (NIL-PATHNAME), except on ABCL, Genera and XCL, where it remains unchanged for it doubles as current-directory." `(let ((*default-pathname-defaults* ,(or defaults #-(or abcl genera xcl) '*nil-pathname* #+(or abcl genera xcl) '*default-pathname-defaults*))) ,@body))) ;;; Some pathname predicates (with-upgradability () (defun pathname-equal (p1 p2) "Are the two pathnames P1 and P2 reasonably equal in the paths they denote?" (when (stringp p1) (setf p1 (pathname p1))) (when (stringp p2) (setf p2 (pathname p2))) (flet ((normalize-component (x) (unless (member x '(nil :unspecific :newest (:relative)) :test 'equal) x))) (macrolet ((=? (&rest accessors) (flet ((frob (x) (reduce 'list (cons 'normalize-component accessors) :initial-value x :from-end t))) `(equal ,(frob 'p1) ,(frob 'p2))))) (or (and (null p1) (null p2)) (and (pathnamep p1) (pathnamep p2) (and (=? pathname-host) #-(and mkcl os-unix) (=? pathname-device) (=? normalize-pathname-directory-component pathname-directory) (=? pathname-name) (=? pathname-type) #-mkcl (=? pathname-version))))))) (defun absolute-pathname-p (pathspec) "If PATHSPEC is a pathname or namestring object that parses as a pathname possessing an :ABSOLUTE directory component, return the (parsed) pathname. Otherwise return NIL" (and pathspec (typep pathspec '(or null pathname string)) (let ((pathname (pathname pathspec))) (and (eq :absolute (car (normalize-pathname-directory-component (pathname-directory pathname)))) pathname)))) (defun relative-pathname-p (pathspec) "If PATHSPEC is a pathname or namestring object that parses as a pathname possessing a :RELATIVE or NIL directory component, return the (parsed) pathname. Otherwise return NIL" (and pathspec (typep pathspec '(or null pathname string)) (let* ((pathname (pathname pathspec)) (directory (normalize-pathname-directory-component (pathname-directory pathname)))) (when (or (null directory) (eq :relative (car directory))) pathname)))) (defun hidden-pathname-p (pathname) "Return a boolean that is true if the pathname is hidden as per Unix style, i.e. its name starts with a dot." (and pathname (equal (first-char (pathname-name pathname)) #\.))) (defun file-pathname-p (pathname) "Does PATHNAME represent a file, i.e. has a non-null NAME component? Accepts NIL, a string (converted through PARSE-NAMESTRING) or a PATHNAME. Note that this does _not_ check to see that PATHNAME points to an actually-existing file. Returns the (parsed) PATHNAME when true" (when pathname (let ((pathname (pathname pathname))) (unless (and (member (pathname-name pathname) '(nil :unspecific "") :test 'equal) (member (pathname-type pathname) '(nil :unspecific "") :test 'equal)) pathname))))) ;;; Directory pathnames (with-upgradability () (defun pathname-directory-pathname (pathname) "Returns a new pathname with same HOST, DEVICE, DIRECTORY as PATHNAME, and NIL NAME, TYPE and VERSION components" (when pathname (make-pathname :name nil :type nil :version nil :defaults pathname))) (defun pathname-parent-directory-pathname (pathname) "Returns a new pathname that corresponds to the parent of the current pathname's directory, i.e. removing one level of depth in the DIRECTORY component. e.g. if pathname is Unix pathname /foo/bar/baz/file.type then return /foo/bar/" (when pathname (make-pathname :name nil :type nil :version nil :directory (merge-pathname-directory-components '(:relative :back) (pathname-directory pathname)) :defaults pathname))) (defun directory-pathname-p (pathname) "Does PATHNAME represent a directory? A directory-pathname is a pathname _without_ a filename. The three ways that the filename components can be missing are for it to be NIL, :UNSPECIFIC or the empty string. Note that this does _not_ check to see that PATHNAME points to an actually-existing directory." (when pathname ;; I tried using Allegro's excl:file-directory-p, but this cannot be done, ;; because it rejects apparently legal pathnames as ;; ill-formed. [2014/02/10:rpg] (let ((pathname (pathname pathname))) (flet ((check-one (x) (member x '(nil :unspecific) :test 'equal))) (and (not (wild-pathname-p pathname)) (check-one (pathname-name pathname)) (check-one (pathname-type pathname)) t))))) (defun ensure-directory-pathname (pathspec &optional (on-error 'error)) "Converts the non-wild pathname designator PATHSPEC to directory form." (cond ((stringp pathspec) (ensure-directory-pathname (pathname pathspec))) ((not (pathnamep pathspec)) (call-function on-error (compatfmt "~@") pathspec)) ((wild-pathname-p pathspec) (call-function on-error (compatfmt "~@") pathspec)) ((directory-pathname-p pathspec) pathspec) (t (handler-case (make-pathname :directory (append (or (normalize-pathname-directory-component (pathname-directory pathspec)) (list :relative)) (list #-genera (file-namestring pathspec) ;; On Genera's native filesystem (LMFS), ;; directories have a type and version ;; which must be ignored when converting ;; to a directory pathname #+genera (if (typep pathspec 'fs:lmfs-pathname) (pathname-name pathspec) (file-namestring pathspec)))) :name nil :type nil :version nil :defaults pathspec) (error (c) (call-function on-error (compatfmt "~@") pathspec c))))))) ;;; Parsing filenames (with-upgradability () (declaim (ftype function ensure-pathname)) ; forward reference (defun split-unix-namestring-directory-components (unix-namestring &key ensure-directory dot-dot) "Splits the path string UNIX-NAMESTRING, returning four values: A flag that is either :absolute or :relative, indicating how the rest of the values are to be interpreted. A directory path --- a list of strings and keywords, suitable for use with MAKE-PATHNAME when prepended with the flag value. Directory components with an empty name or the name . are removed. Any directory named .. is read as DOT-DOT, or :BACK if it's NIL (not :UP). A last-component, either a file-namestring including type extension, or NIL in the case of a directory pathname. A flag that is true iff the unix-style-pathname was just a file-namestring without / path specification. ENSURE-DIRECTORY forces the namestring to be interpreted as a directory pathname: the third return value will be NIL, and final component of the namestring will be treated as part of the directory path. An empty string is thus read as meaning a pathname object with all fields nil. Note that colon characters #\: will NOT be interpreted as host specification. Absolute pathnames are only appropriate on Unix-style systems. The intention of this function is to support structured component names, e.g., \(:file \"foo/bar\"\), which will be unpacked to relative pathnames." (check-type unix-namestring string) (check-type dot-dot (member nil :back :up)) (if (and (not (find #\/ unix-namestring)) (not ensure-directory) (plusp (length unix-namestring))) (values :relative () unix-namestring t) (let* ((components (split-string unix-namestring :separator "/")) (last-comp (car (last components)))) (multiple-value-bind (relative components) (if (equal (first components) "") (if (equal (first-char unix-namestring) #\/) (values :absolute (cdr components)) (values :relative nil)) (values :relative components)) (setf components (remove-if #'(lambda (x) (member x '("" ".") :test #'equal)) components)) (setf components (substitute (or dot-dot :back) ".." components :test #'equal)) (cond ((equal last-comp "") (values relative components nil nil)) ; "" already removed from components (ensure-directory (values relative components nil nil)) (t (values relative (butlast components) last-comp nil))))))) (defun split-name-type (filename) "Split a filename into two values NAME and TYPE that are returned. We assume filename has no directory component. The last . if any separates name and type from from type, except that if there is only one . and it is in first position, the whole filename is the NAME with an empty type. NAME is always a string. For an empty type, *UNSPECIFIC-PATHNAME-TYPE* is returned." (check-type filename string) (assert (plusp (length filename))) (destructuring-bind (name &optional (type *unspecific-pathname-type*)) (split-string filename :max 2 :separator ".") (if (equal name "") (values filename *unspecific-pathname-type*) (values name type)))) (defun parse-unix-namestring (name &rest keys &key type defaults dot-dot ensure-directory &allow-other-keys) "Coerce NAME into a PATHNAME using standard Unix syntax. Unix syntax is used whether or not the underlying system is Unix; on such non-Unix systems it is reliably usable only for relative pathnames. This function is especially useful to manipulate relative pathnames portably, where it is crucial to possess a portable pathname syntax independent of the underlying OS. This is what PARSE-UNIX-NAMESTRING provides, and why we use it in ASDF. When given a PATHNAME object, just return it untouched. When given NIL, just return NIL. When given a non-null SYMBOL, first downcase its name and treat it as a string. When given a STRING, portably decompose it into a pathname as below. #\\/ separates directory components. The last #\\/-separated substring is interpreted as follows: 1- If TYPE is :DIRECTORY or ENSURE-DIRECTORY is true, the string is made the last directory component, and NAME and TYPE are NIL. if the string is empty, it's the empty pathname with all slots NIL. 2- If TYPE is NIL, the substring is a file-namestring, and its NAME and TYPE are separated by SPLIT-NAME-TYPE. 3- If TYPE is a string, it is the given TYPE, and the whole string is the NAME. Directory components with an empty name or the name \".\" are removed. Any directory named \"..\" is read as DOT-DOT, which must be one of :BACK or :UP and defaults to :BACK. HOST, DEVICE and VERSION components are taken from DEFAULTS, which itself defaults to *NIL-PATHNAME*, also used if DEFAULTS is NIL. No host or device can be specified in the string itself, which makes it unsuitable for absolute pathnames outside Unix. For relative pathnames, these components (and hence the defaults) won't matter if you use MERGE-PATHNAMES* but will matter if you use MERGE-PATHNAMES, which is an important reason to always use MERGE-PATHNAMES*. Arbitrary keys are accepted, and the parse result is passed to ENSURE-PATHNAME with those keys, removing TYPE DEFAULTS and DOT-DOT. When you're manipulating pathnames that are supposed to make sense portably even though the OS may not be Unixish, we recommend you use :WANT-RELATIVE T to throw an error if the pathname is absolute" (block nil (check-type type (or null string (eql :directory))) (when ensure-directory (setf type :directory)) (etypecase name ((or null pathname) (return name)) (symbol (setf name (string-downcase name))) (string)) (multiple-value-bind (relative path filename file-only) (split-unix-namestring-directory-components name :dot-dot dot-dot :ensure-directory (eq type :directory)) (multiple-value-bind (name type) (cond ((or (eq type :directory) (null filename)) (values nil nil)) (type (values filename type)) (t (split-name-type filename))) (let* ((directory (unless file-only (cons relative path))) (pathname #-abcl (make-pathname :directory directory :name name :type type :defaults (or #-mcl defaults *nil-pathname*)) #+abcl (if (and defaults (ext:pathname-jar-p defaults) (null directory)) ;; When DEFAULTS is a jar, it will have the directory we want (make-pathname :name name :type type :defaults (or defaults *nil-pathname*)) (make-pathname :name name :type type :defaults (or defaults *nil-pathname*) :directory directory)))) (apply 'ensure-pathname pathname (remove-plist-keys '(:type :dot-dot :defaults) keys))))))) (defun unix-namestring (pathname) "Given a non-wild PATHNAME, return a Unix-style namestring for it. If the PATHNAME is NIL or a STRING, return it unchanged. This only considers the DIRECTORY, NAME and TYPE components of the pathname. This is a portable solution for representing relative pathnames, But unless you are running on a Unix system, it is not a general solution to representing native pathnames. An error is signaled if the argument is not NULL, a STRING or a PATHNAME, or if it is a PATHNAME but some of its components are not recognized." (etypecase pathname ((or null string) pathname) (pathname (with-output-to-string (s) (flet ((err () (parameter-error "~S: invalid unix-namestring ~S" 'unix-namestring pathname))) (let* ((dir (normalize-pathname-directory-component (pathname-directory pathname))) (name (pathname-name pathname)) (name (and (not (eq name :unspecific)) name)) (type (pathname-type pathname)) (type (and (not (eq type :unspecific)) type))) (cond ((member dir '(nil :unspecific))) ((eq dir '(:relative)) (princ "./" s)) ((consp dir) (destructuring-bind (relabs &rest dirs) dir (or (member relabs '(:relative :absolute)) (err)) (when (eq relabs :absolute) (princ #\/ s)) (loop :for x :in dirs :do (cond ((member x '(:back :up)) (princ "../" s)) ((equal x "") (err)) ;;((member x '("." "..") :test 'equal) (err)) ((stringp x) (format s "~A/" x)) (t (err)))))) (t (err))) (cond (name (unless (and (stringp name) (or (null type) (stringp type))) (err)) (format s "~A~@[.~A~]" name type)) (t (or (null type) (err))))))))))) ;;; Absolute and relative pathnames (with-upgradability () (defun subpathname (pathname subpath &key type) "This function takes a PATHNAME and a SUBPATH and a TYPE. If SUBPATH is already a PATHNAME object (not namestring), and is an absolute pathname at that, it is returned unchanged; otherwise, SUBPATH is turned into a relative pathname with given TYPE as per PARSE-UNIX-NAMESTRING with :WANT-RELATIVE T :TYPE TYPE, then it is merged with the PATHNAME-DIRECTORY-PATHNAME of PATHNAME." (or (and (pathnamep subpath) (absolute-pathname-p subpath)) (merge-pathnames* (parse-unix-namestring subpath :type type :want-relative t) (pathname-directory-pathname pathname)))) (defun subpathname* (pathname subpath &key type) "returns NIL if the base pathname is NIL, otherwise like SUBPATHNAME." (and pathname (subpathname (ensure-directory-pathname pathname) subpath :type type))) (defun pathname-root (pathname) "return the root directory for the host and device of given PATHNAME" (make-pathname :directory '(:absolute) :name nil :type nil :version nil :defaults pathname ;; host device, and on scl, *some* ;; scheme-specific parts: port username password, not others: . #.(or #+scl '(:parameters nil :query nil :fragment nil)))) (defun pathname-host-pathname (pathname) "return a pathname with the same host as given PATHNAME, and all other fields NIL" (make-pathname :directory nil :name nil :type nil :version nil :device nil :defaults pathname ;; host device, and on scl, *some* ;; scheme-specific parts: port username password, not others: . #.(or #+scl '(:parameters nil :query nil :fragment nil)))) (defun ensure-absolute-pathname (path &optional defaults (on-error 'error)) "Given a pathname designator PATH, return an absolute pathname as specified by PATH considering the DEFAULTS, or, if not possible, use CALL-FUNCTION on the specified ON-ERROR behavior, with a format control-string and other arguments as arguments" (cond ((absolute-pathname-p path)) ((stringp path) (ensure-absolute-pathname (pathname path) defaults on-error)) ((not (pathnamep path)) (call-function on-error "not a valid pathname designator ~S" path)) ((let ((default-pathname (if (pathnamep defaults) defaults (call-function defaults)))) (or (if (absolute-pathname-p default-pathname) (absolute-pathname-p (merge-pathnames* path default-pathname)) (call-function on-error "Default pathname ~S is not an absolute pathname" default-pathname)) (call-function on-error "Failed to merge ~S with ~S into an absolute pathname" path default-pathname)))) (t (call-function on-error "Cannot ensure ~S is evaluated as an absolute pathname with defaults ~S" path defaults)))) (defun subpathp (maybe-subpath base-pathname) "if MAYBE-SUBPATH is a pathname that is under BASE-PATHNAME, return a pathname object that when used with MERGE-PATHNAMES* with defaults BASE-PATHNAME, returns MAYBE-SUBPATH." (and (pathnamep maybe-subpath) (pathnamep base-pathname) (absolute-pathname-p maybe-subpath) (absolute-pathname-p base-pathname) (directory-pathname-p base-pathname) (not (wild-pathname-p base-pathname)) (pathname-equal (pathname-root maybe-subpath) (pathname-root base-pathname)) (with-pathname-defaults (*nil-pathname*) (let ((enough (enough-namestring maybe-subpath base-pathname))) (and (relative-pathname-p enough) (pathname enough)))))) (defun enough-pathname (maybe-subpath base-pathname) "if MAYBE-SUBPATH is a pathname that is under BASE-PATHNAME, return a pathname object that when used with MERGE-PATHNAMES* with defaults BASE-PATHNAME, returns MAYBE-SUBPATH." (let ((sub (when maybe-subpath (pathname maybe-subpath))) (base (when base-pathname (ensure-absolute-pathname (pathname base-pathname))))) (or (and base (subpathp sub base)) sub))) (defun call-with-enough-pathname (maybe-subpath defaults-pathname thunk) "In a context where *DEFAULT-PATHNAME-DEFAULTS* is bound to DEFAULTS-PATHNAME (if not null, or else to its current value), call THUNK with ENOUGH-PATHNAME for MAYBE-SUBPATH given DEFAULTS-PATHNAME as a base pathname." (let ((enough (enough-pathname maybe-subpath defaults-pathname)) (*default-pathname-defaults* (or defaults-pathname *default-pathname-defaults*))) (funcall thunk enough))) (defmacro with-enough-pathname ((pathname-var &key (pathname pathname-var) (defaults *default-pathname-defaults*)) &body body) "Shorthand syntax for CALL-WITH-ENOUGH-PATHNAME" `(call-with-enough-pathname ,pathname ,defaults #'(lambda (,pathname-var) ,@body)))) ;;; Wildcard pathnames (with-upgradability () (defparameter *wild* (or #+cormanlisp "*" :wild) "Wild component for use with MAKE-PATHNAME") (defparameter *wild-directory-component* (or :wild) "Wild directory component for use with MAKE-PATHNAME") (defparameter *wild-inferiors-component* (or :wild-inferiors) "Wild-inferiors directory component for use with MAKE-PATHNAME") (defparameter *wild-file* (make-pathname :directory nil :name *wild* :type *wild* :version (or #-(or allegro abcl xcl) *wild*)) "A pathname object with wildcards for matching any file with TRANSLATE-PATHNAME") (defparameter *wild-file-for-directory* (make-pathname :directory nil :name *wild* :type (or #-(or clisp gcl) *wild*) :version (or #-(or allegro abcl clisp gcl xcl) *wild*)) "A pathname object with wildcards for matching any file with DIRECTORY") (defparameter *wild-directory* (make-pathname :directory `(:relative ,*wild-directory-component*) :name nil :type nil :version nil) "A pathname object with wildcards for matching any subdirectory") (defparameter *wild-inferiors* (make-pathname :directory `(:relative ,*wild-inferiors-component*) :name nil :type nil :version nil) "A pathname object with wildcards for matching any recursive subdirectory") (defparameter *wild-path* (merge-pathnames* *wild-file* *wild-inferiors*) "A pathname object with wildcards for matching any file in any recursive subdirectory") (defun wilden (path) "From a pathname, return a wildcard pathname matching any file in any subdirectory of given pathname's directory" (merge-pathnames* *wild-path* path))) ;;; Translate a pathname (with-upgradability () (defun relativize-directory-component (directory-component) "Given the DIRECTORY-COMPONENT of a pathname, return an otherwise similar relative directory component" (let ((directory (normalize-pathname-directory-component directory-component))) (cond ((stringp directory) (list :relative directory)) ((eq (car directory) :absolute) (cons :relative (cdr directory))) (t directory)))) (defun relativize-pathname-directory (pathspec) "Given a PATHNAME, return a relative pathname with otherwise the same components" (let ((p (pathname pathspec))) (make-pathname :directory (relativize-directory-component (pathname-directory p)) :defaults p))) (defun directory-separator-for-host (&optional (pathname *default-pathname-defaults*)) "Given a PATHNAME, return the character used to delimit directory names on this host and device." (let ((foo (make-pathname :directory '(:absolute "FOO") :defaults pathname))) (last-char (namestring foo)))) #-scl (defun directorize-pathname-host-device (pathname) "Given a PATHNAME, return a pathname that has representations of its HOST and DEVICE components added to its DIRECTORY component. This is useful for output translations." (os-cond ((os-unix-p) (when (physical-pathname-p pathname) (return-from directorize-pathname-host-device pathname)))) (let* ((root (pathname-root pathname)) (wild-root (wilden root)) (absolute-pathname (merge-pathnames* pathname root)) (separator (directory-separator-for-host root)) (root-namestring (namestring root)) (root-string (substitute-if #\/ #'(lambda (x) (or (eql x #\:) (eql x separator))) root-namestring))) (multiple-value-bind (relative path filename) (split-unix-namestring-directory-components root-string :ensure-directory t) (declare (ignore relative filename)) (let ((new-base (make-pathname :defaults root :directory `(:absolute ,@path)))) (translate-pathname absolute-pathname wild-root (wilden new-base)))))) #+scl (defun directorize-pathname-host-device (pathname) (let ((scheme (ext:pathname-scheme pathname)) (host (pathname-host pathname)) (port (ext:pathname-port pathname)) (directory (pathname-directory pathname))) (flet ((specificp (x) (and x (not (eq x :unspecific))))) (if (or (specificp port) (and (specificp host) (plusp (length host))) (specificp scheme)) (let ((prefix "")) (when (specificp port) (setf prefix (format nil ":~D" port))) (when (and (specificp host) (plusp (length host))) (setf prefix (strcat host prefix))) (setf prefix (strcat ":" prefix)) (when (specificp scheme) (setf prefix (strcat scheme prefix))) (assert (and directory (eq (first directory) :absolute))) (make-pathname :directory `(:absolute ,prefix ,@(rest directory)) :defaults pathname))) pathname))) (defun translate-pathname* (path absolute-source destination &optional root source) "A wrapper around TRANSLATE-PATHNAME to be used by the ASDF output-translations facility. PATH is the pathname to be translated. ABSOLUTE-SOURCE is an absolute pathname to use as source for translate-pathname, DESTINATION is either a function, to be called with PATH and ABSOLUTE-SOURCE, or a relative pathname, to be merged with ROOT and used as destination for translate-pathname or an absolute pathname, to be used as destination for translate-pathname. In that last case, if ROOT is non-NIL, PATH is first transformated by DIRECTORIZE-PATHNAME-HOST-DEVICE." (declare (ignore source)) (cond ((functionp destination) (funcall destination path absolute-source)) ((eq destination t) path) ((not (pathnamep destination)) (parameter-error "~S: Invalid destination" 'translate-pathname*)) ((not (absolute-pathname-p destination)) (translate-pathname path absolute-source (merge-pathnames* destination root))) (root (translate-pathname (directorize-pathname-host-device path) absolute-source destination)) (t (translate-pathname path absolute-source destination)))) (defvar *output-translation-function* 'identity "Hook for output translations. This function needs to be idempotent, so that actions can work whether their inputs were translated or not, which they will be if we are composing operations. e.g. if some create-lisp-op creates a lisp file from some higher-level input, you need to still be able to use compile-op on that lisp file.")) ;;;; ------------------------------------------------------------------------- ;;;; Portability layer around Common Lisp filesystem access (uiop/package:define-package :uiop/filesystem (:use :uiop/common-lisp :uiop/package :uiop/utility :uiop/os :uiop/pathname) (:export ;; Native namestrings #:native-namestring #:parse-native-namestring ;; Probing the filesystem #:truename* #:safe-file-write-date #:probe-file* #:directory-exists-p #:file-exists-p #:directory* #:filter-logical-directory-results #:directory-files #:subdirectories #:collect-sub*directories ;; Resolving symlinks somewhat #:truenamize #:resolve-symlinks #:*resolve-symlinks* #:resolve-symlinks* ;; merging with cwd #:get-pathname-defaults #:call-with-current-directory #:with-current-directory ;; Environment pathnames #:inter-directory-separator #:split-native-pathnames-string #:getenv-pathname #:getenv-pathnames #:getenv-absolute-directory #:getenv-absolute-directories #:lisp-implementation-directory #:lisp-implementation-pathname-p ;; Simple filesystem operations #:ensure-all-directories-exist #:rename-file-overwriting-target #:delete-file-if-exists #:delete-empty-directory #:delete-directory-tree)) (in-package :uiop/filesystem) ;;; Native namestrings, as seen by the operating system calls rather than Lisp (with-upgradability () (defun native-namestring (x) "From a non-wildcard CL pathname, a return namestring suitable for passing to the operating system" (when x (let ((p (pathname x))) #+clozure (with-pathname-defaults () (ccl:native-translated-namestring p)) ; see ccl bug 978 #+(or cmucl scl) (ext:unix-namestring p nil) #+sbcl (sb-ext:native-namestring p) #-(or clozure cmucl sbcl scl) (os-cond ((os-unix-p) (unix-namestring p)) (t (namestring p)))))) (defun parse-native-namestring (string &rest constraints &key ensure-directory &allow-other-keys) "From a native namestring suitable for use by the operating system, return a CL pathname satisfying all the specified constraints as per ENSURE-PATHNAME" (check-type string (or string null)) (let* ((pathname (when string (with-pathname-defaults () #+clozure (ccl:native-to-pathname string) #+cmucl (uiop/os::parse-unix-namestring* string) #+sbcl (sb-ext:parse-native-namestring string) #+scl (lisp::parse-unix-namestring string) #-(or clozure cmucl sbcl scl) (os-cond ((os-unix-p) (parse-unix-namestring string :ensure-directory ensure-directory)) (t (parse-namestring string)))))) (pathname (if ensure-directory (and pathname (ensure-directory-pathname pathname)) pathname))) (apply 'ensure-pathname pathname constraints)))) ;;; Probing the filesystem (with-upgradability () (defun truename* (p) "Nicer variant of TRUENAME that plays well with NIL, avoids logical pathname contexts, and tries both files and directories" (when p (when (stringp p) (setf p (with-pathname-defaults () (parse-namestring p)))) (values (or (ignore-errors (truename p)) ;; this is here because trying to find the truename of a directory pathname WITHOUT supplying ;; a trailing directory separator, causes an error on some lisps. #+(or clisp gcl) (if-let (d (ensure-directory-pathname p nil)) (ignore-errors (truename d))) ;; On Genera, truename of a directory pathname will probably fail as Genera ;; will merge in a filename/type/version from *default-pathname-defaults* and ;; will try to get the truename of a file that probably doesn't exist. #+genera (when (directory-pathname-p p) (let ((d (scl:send p :directory-pathname-as-file))) (ensure-directory-pathname (ignore-errors (truename d)) nil))))))) (defun safe-file-write-date (pathname) "Safe variant of FILE-WRITE-DATE that may return NIL rather than raise an error." ;; If FILE-WRITE-DATE returns NIL, it's possible that ;; the user or some other agent has deleted an input file. ;; Also, generated files will not exist at the time planning is done ;; and calls compute-action-stamp which calls safe-file-write-date. ;; So it is very possible that we can't get a valid file-write-date, ;; and we can survive and we will continue the planning ;; as if the file were very old. ;; (or should we treat the case in a different, special way?) (and pathname (handler-case (file-write-date (physicalize-pathname pathname)) (file-error () nil)))) (defun probe-file* (p &key truename) "when given a pathname P (designated by a string as per PARSE-NAMESTRING), probes the filesystem for a file or directory with given pathname. If it exists, return its truename if TRUENAME is true, or the original (parsed) pathname if it is false (the default)." (values (ignore-errors (setf p (funcall 'ensure-pathname p :namestring :lisp :ensure-physical t :ensure-absolute t :defaults 'get-pathname-defaults :want-non-wild t :on-error nil)) (when p #+allegro (probe-file p :follow-symlinks truename) #+gcl (if truename (truename* p) (let ((kind (car (si::stat p)))) (when (eq kind :link) (setf kind (ignore-errors (car (si::stat (truename* p)))))) (ecase kind ((nil) nil) ((:file :link) (cond ((file-pathname-p p) p) ((directory-pathname-p p) (subpathname p (car (last (pathname-directory p))))))) (:directory (ensure-directory-pathname p))))) #+clisp #.(let* ((fs (or #-os-windows (find-symbol* '#:file-stat :posix nil))) (pp (find-symbol* '#:probe-pathname :ext nil))) `(if truename ,(if pp `(values (,pp p)) '(or (truename* p) (truename* (ignore-errors (ensure-directory-pathname p))))) ,(cond (fs `(and (,fs p) p)) (pp `(nth-value 1 (,pp p))) (t '(or (and (truename* p) p) (if-let (d (ensure-directory-pathname p)) (and (truename* d) d))))))) #-(or allegro clisp gcl) (if truename (probe-file p) (and #+(or cmucl scl) (unix:unix-stat (ext:unix-namestring p)) #+(and lispworks os-unix) (system:get-file-stat p) #+sbcl (sb-unix:unix-stat (sb-ext:native-namestring p)) #-(or cmucl (and lispworks os-unix) sbcl scl) (file-write-date p) p)))))) (defun directory-exists-p (x) "Is X the name of a directory that exists on the filesystem?" #+allegro (excl:probe-directory x) #+clisp (handler-case (ext:probe-directory x) (sys::simple-file-error () nil)) #-(or allegro clisp) (let ((p (probe-file* x :truename t))) (and (directory-pathname-p p) p))) (defun file-exists-p (x) "Is X the name of a file that exists on the filesystem?" (let ((p (probe-file* x :truename t))) (and (file-pathname-p p) p))) (defun directory* (pathname-spec &rest keys &key &allow-other-keys) "Return a list of the entries in a directory by calling DIRECTORY. Try to override the defaults to not resolving symlinks, if implementation allows." (apply 'directory pathname-spec (append keys '#.(or #+allegro '(:directories-are-files nil :follow-symbolic-links nil) #+(or clozure digitool) '(:follow-links nil) #+clisp '(:circle t :if-does-not-exist :ignore) #+(or cmucl scl) '(:follow-links nil :truenamep nil) #+lispworks '(:link-transparency nil) #+sbcl (when (find-symbol* :resolve-symlinks '#:sb-impl nil) '(:resolve-symlinks nil)))))) (defun filter-logical-directory-results (directory entries merger) "If DIRECTORY isn't a logical pathname, return ENTRIES. If it is, given ENTRIES in the DIRECTORY, remove the entries which are physical yet when transformed by MERGER have a different TRUENAME. Also remove duplicates as may appear with some translation rules. This function is used as a helper to DIRECTORY-FILES to avoid invalid entries when using logical-pathnames." (if (logical-pathname-p directory) (remove-duplicates ;; on CLISP, querying ~/ will return duplicates ;; Try hard to not resolve logical-pathname into physical pathnames; ;; otherwise logical-pathname users/lovers will be disappointed. ;; If directory* could use some implementation-dependent magic, ;; we will have logical pathnames already; otherwise, ;; we only keep pathnames for which specifying the name and ;; translating the LPN commute. (loop :for f :in entries :for p = (or (and (logical-pathname-p f) f) (let* ((u (ignore-errors (call-function merger f)))) ;; The first u avoids a cumbersome (truename u) error. ;; At this point f should already be a truename, ;; but isn't quite in CLISP, for it doesn't have :version :newest (and u (equal (truename* u) (truename* f)) u))) :when p :collect p) :test 'pathname-equal) entries)) (defun directory-files (directory &optional (pattern *wild-file-for-directory*)) "Return a list of the files in a directory according to the PATTERN. Subdirectories should NOT be returned. PATTERN defaults to a pattern carefully chosen based on the implementation; override the default at your own risk. DIRECTORY-FILES tries NOT to resolve symlinks if the implementation permits this, but the behavior in presence of symlinks is not portable. Use IOlib to handle such situations." (let ((dir (ensure-directory-pathname directory))) (when (logical-pathname-p dir) ;; Because of the filtering we do below, ;; logical pathnames have restrictions on wild patterns. ;; Not that the results are very portable when you use these patterns on physical pathnames. (when (wild-pathname-p dir) (parameter-error "~S: Invalid wild pattern in logical directory ~S" 'directory-files directory)) (unless (member (pathname-directory pattern) '(() (:relative)) :test 'equal) (parameter-error "~S: Invalid file pattern ~S for logical directory ~S" 'directory-files pattern directory)) (setf pattern (make-pathname-logical pattern (pathname-host dir)))) (let* ((pat (merge-pathnames* pattern dir)) (entries (ignore-errors (directory* pat)))) (remove-if 'directory-pathname-p (filter-logical-directory-results directory entries #'(lambda (f) (make-pathname :defaults dir :name (make-pathname-component-logical (pathname-name f)) :type (make-pathname-component-logical (pathname-type f)) :version (make-pathname-component-logical (pathname-version f))))))))) (defun subdirectories (directory) "Given a DIRECTORY pathname designator, return a list of the subdirectories under it. The behavior in presence of symlinks is not portable. Use IOlib to handle such situations." (let* ((directory (ensure-directory-pathname directory)) #-(or abcl cormanlisp genera xcl) (wild (merge-pathnames* #-(or abcl allegro cmucl lispworks sbcl scl xcl) *wild-directory* #+(or abcl allegro cmucl lispworks sbcl scl xcl) "*.*" directory)) (dirs #-(or abcl cormanlisp genera xcl) (ignore-errors (directory* wild . #.(or #+clozure '(:directories t :files nil) #+mcl '(:directories t)))) #+(or abcl xcl) (system:list-directory directory) #+cormanlisp (cl::directory-subdirs directory) #+genera (handler-case (fs:directory-list directory) (fs:directory-not-found () nil))) #+(or abcl allegro cmucl genera lispworks sbcl scl xcl) (dirs (loop :for x :in dirs :for d = #+(or abcl xcl) (extensions:probe-directory x) #+allegro (excl:probe-directory x) #+(or cmucl sbcl scl) (directory-pathname-p x) #+genera (getf (cdr x) :directory) #+lispworks (lw:file-directory-p x) :when d :collect #+(or abcl allegro xcl) (ensure-directory-pathname d) #+genera (ensure-directory-pathname (first x)) #+(or cmucl lispworks sbcl scl) x))) (filter-logical-directory-results directory dirs (let ((prefix (or (normalize-pathname-directory-component (pathname-directory directory)) '(:absolute)))) ; because allegro returns NIL for #p"FOO:" #'(lambda (d) (let ((dir (normalize-pathname-directory-component (pathname-directory d)))) (and (consp dir) (consp (cdr dir)) (make-pathname :defaults directory :name nil :type nil :version nil :directory (append prefix (make-pathname-component-logical (last dir))))))))))) (defun collect-sub*directories (directory collectp recursep collector) "Given a DIRECTORY, when COLLECTP returns true when CALL-FUNCTION'ed with the directory, call-function the COLLECTOR function designator on the directory, and recurse each of its subdirectories on which the RECURSEP returns true when CALL-FUNCTION'ed with them. This function will thus let you traverse a filesystem hierarchy, superseding the functionality of CL-FAD:WALK-DIRECTORY. The behavior in presence of symlinks is not portable. Use IOlib to handle such situations." (when (call-function collectp directory) (call-function collector directory) (dolist (subdir (subdirectories directory)) (when (call-function recursep subdir) (collect-sub*directories subdir collectp recursep collector)))))) ;;; Resolving symlinks somewhat (with-upgradability () (defun truenamize (pathname) "Resolve as much of a pathname as possible" (block nil (when (typep pathname '(or null logical-pathname)) (return pathname)) (let ((p pathname)) (unless (absolute-pathname-p p) (setf p (or (absolute-pathname-p (ensure-absolute-pathname p 'get-pathname-defaults nil)) (return p)))) (when (logical-pathname-p p) (return p)) (let ((found (probe-file* p :truename t))) (when found (return found))) (let* ((directory (normalize-pathname-directory-component (pathname-directory p))) (up-components (reverse (rest directory))) (down-components ())) (assert (eq :absolute (first directory))) (loop :while up-components :do (if-let (parent (ignore-errors (probe-file* (make-pathname :directory `(:absolute ,@(reverse up-components)) :name nil :type nil :version nil :defaults p)))) (if-let (simplified (ignore-errors (merge-pathnames* (make-pathname :directory `(:relative ,@down-components) :defaults p) (ensure-directory-pathname parent)))) (return simplified))) (push (pop up-components) down-components) :finally (return p)))))) (defun resolve-symlinks (path) "Do a best effort at resolving symlinks in PATH, returning a partially or totally resolved PATH." #-allegro (truenamize path) #+allegro (if (physical-pathname-p path) (or (ignore-errors (excl:pathname-resolve-symbolic-links path)) path) path)) (defvar *resolve-symlinks* t "Determine whether or not ASDF resolves symlinks when defining systems. Defaults to T.") (defun resolve-symlinks* (path) "RESOLVE-SYMLINKS in PATH iff *RESOLVE-SYMLINKS* is T (the default)." (if *resolve-symlinks* (and path (resolve-symlinks path)) path))) ;;; Check pathname constraints (with-upgradability () (defun ensure-pathname (pathname &key on-error defaults type dot-dot namestring empty-is-nil want-pathname want-logical want-physical ensure-physical want-relative want-absolute ensure-absolute ensure-subpath want-non-wild want-wild wilden want-file want-directory ensure-directory want-existing ensure-directories-exist truename resolve-symlinks truenamize &aux (p pathname)) ;; mutable working copy, preserve original "Coerces its argument into a PATHNAME, optionally doing some transformations and checking specified constraints. If the argument is NIL, then NIL is returned unless the WANT-PATHNAME constraint is specified. If the argument is a STRING, it is first converted to a pathname via PARSE-UNIX-NAMESTRING, PARSE-NAMESTRING or PARSE-NATIVE-NAMESTRING respectively depending on the NAMESTRING argument being :UNIX, :LISP or :NATIVE respectively, or else by using CALL-FUNCTION on the NAMESTRING argument; if :UNIX is specified (or NIL, the default, which specifies the same thing), then PARSE-UNIX-NAMESTRING it is called with the keywords DEFAULTS TYPE DOT-DOT ENSURE-DIRECTORY WANT-RELATIVE, and the result is optionally merged into the DEFAULTS if ENSURE-ABSOLUTE is true. The pathname passed or resulting from parsing the string is then subjected to all the checks and transformations below are run. Each non-nil constraint argument can be one of the symbols T, ERROR, CERROR or IGNORE. The boolean T is an alias for ERROR. ERROR means that an error will be raised if the constraint is not satisfied. CERROR means that an continuable error will be raised if the constraint is not satisfied. IGNORE means just return NIL instead of the pathname. The ON-ERROR argument, if not NIL, is a function designator (as per CALL-FUNCTION) that will be called with the the following arguments: a generic format string for ensure pathname, the pathname, the keyword argument corresponding to the failed check or transformation, a format string for the reason ENSURE-PATHNAME failed, and a list with arguments to that format string. If ON-ERROR is NIL, ERROR is used instead, which does the right thing. You could also pass (CERROR \"CONTINUE DESPITE FAILED CHECK\"). The transformations and constraint checks are done in this order, which is also the order in the lambda-list: EMPTY-IS-NIL returns NIL if the argument is an empty string. WANT-PATHNAME checks that pathname (after parsing if needed) is not null. Otherwise, if the pathname is NIL, ensure-pathname returns NIL. WANT-LOGICAL checks that pathname is a LOGICAL-PATHNAME WANT-PHYSICAL checks that pathname is not a LOGICAL-PATHNAME ENSURE-PHYSICAL ensures that pathname is physical via TRANSLATE-LOGICAL-PATHNAME WANT-RELATIVE checks that pathname has a relative directory component WANT-ABSOLUTE checks that pathname does have an absolute directory component ENSURE-ABSOLUTE merges with the DEFAULTS, then checks again that the result absolute is an absolute pathname indeed. ENSURE-SUBPATH checks that the pathname is a subpath of the DEFAULTS. WANT-FILE checks that pathname has a non-nil FILE component WANT-DIRECTORY checks that pathname has nil FILE and TYPE components ENSURE-DIRECTORY uses ENSURE-DIRECTORY-PATHNAME to interpret any file and type components as being actually a last directory component. WANT-NON-WILD checks that pathname is not a wild pathname WANT-WILD checks that pathname is a wild pathname WILDEN merges the pathname with **/*.*.* if it is not wild WANT-EXISTING checks that a file (or directory) exists with that pathname. ENSURE-DIRECTORIES-EXIST creates any parent directory with ENSURE-DIRECTORIES-EXIST. TRUENAME replaces the pathname by its truename, or errors if not possible. RESOLVE-SYMLINKS replaces the pathname by a variant with symlinks resolved by RESOLVE-SYMLINKS. TRUENAMIZE uses TRUENAMIZE to resolve as many symlinks as possible." (block nil (flet ((report-error (keyword description &rest arguments) (call-function (or on-error 'error) "Invalid pathname ~S: ~*~?" pathname keyword description arguments))) (macrolet ((err (constraint &rest arguments) `(report-error ',(intern* constraint :keyword) ,@arguments)) (check (constraint condition &rest arguments) `(when ,constraint (unless ,condition (err ,constraint ,@arguments)))) (transform (transform condition expr) `(when ,transform (,@(if condition `(when ,condition) '(progn)) (setf p ,expr))))) (etypecase p ((or null pathname)) (string (when (and (emptyp p) empty-is-nil) (return-from ensure-pathname nil)) (setf p (case namestring ((:unix nil) (parse-unix-namestring p :defaults defaults :type type :dot-dot dot-dot :ensure-directory ensure-directory :want-relative want-relative)) ((:native) (parse-native-namestring p)) ((:lisp) (parse-namestring p)) (t (call-function namestring p)))))) (etypecase p (pathname) (null (check want-pathname (pathnamep p) "Expected a pathname, not NIL") (return nil))) (check want-logical (logical-pathname-p p) "Expected a logical pathname") (check want-physical (physical-pathname-p p) "Expected a physical pathname") (transform ensure-physical () (physicalize-pathname p)) (check ensure-physical (physical-pathname-p p) "Could not translate to a physical pathname") (check want-relative (relative-pathname-p p) "Expected a relative pathname") (check want-absolute (absolute-pathname-p p) "Expected an absolute pathname") (transform ensure-absolute (not (absolute-pathname-p p)) (ensure-absolute-pathname p defaults (list #'report-error :ensure-absolute "~@?"))) (check ensure-absolute (absolute-pathname-p p) "Could not make into an absolute pathname even after merging with ~S" defaults) (check ensure-subpath (absolute-pathname-p defaults) "cannot be checked to be a subpath of non-absolute pathname ~S" defaults) (check ensure-subpath (subpathp p defaults) "is not a sub pathname of ~S" defaults) (check want-file (file-pathname-p p) "Expected a file pathname") (check want-directory (directory-pathname-p p) "Expected a directory pathname") (transform ensure-directory (not (directory-pathname-p p)) (ensure-directory-pathname p)) (check want-non-wild (not (wild-pathname-p p)) "Expected a non-wildcard pathname") (check want-wild (wild-pathname-p p) "Expected a wildcard pathname") (transform wilden (not (wild-pathname-p p)) (wilden p)) (when want-existing (let ((existing (probe-file* p :truename truename))) (if existing (when truename (return existing)) (err want-existing "Expected an existing pathname")))) (when ensure-directories-exist (ensure-directories-exist p)) (when truename (let ((truename (truename* p))) (if truename (return truename) (err truename "Can't get a truename for pathname")))) (transform resolve-symlinks () (resolve-symlinks p)) (transform truenamize () (truenamize p)) p))))) ;;; Pathname defaults (with-upgradability () (defun get-pathname-defaults (&optional (defaults *default-pathname-defaults*)) "Find the actual DEFAULTS to use for pathnames, including resolving them with respect to GETCWD if the DEFAULTS were relative" (or (absolute-pathname-p defaults) (merge-pathnames* defaults (getcwd)))) (defun call-with-current-directory (dir thunk) "call the THUNK in a context where the current directory was changed to DIR, if not NIL. Note that this operation is usually NOT thread-safe." (if dir (let* ((dir (resolve-symlinks* (get-pathname-defaults (ensure-directory-pathname dir)))) (cwd (getcwd)) (*default-pathname-defaults* dir)) (chdir dir) (unwind-protect (funcall thunk) (chdir cwd))) (funcall thunk))) (defmacro with-current-directory ((&optional dir) &body body) "Call BODY while the POSIX current working directory is set to DIR" `(call-with-current-directory ,dir #'(lambda () ,@body)))) ;;; Environment pathnames (with-upgradability () (defun inter-directory-separator () "What character does the current OS conventionally uses to separate directories?" (os-cond ((os-unix-p) #\:) (t #\;))) (defun split-native-pathnames-string (string &rest constraints &key &allow-other-keys) "Given a string of pathnames specified in native OS syntax, separate them in a list, check constraints and normalize each one as per ENSURE-PATHNAME, where an empty string denotes NIL." (loop :for namestring :in (split-string string :separator (string (inter-directory-separator))) :collect (unless (emptyp namestring) (apply 'parse-native-namestring namestring constraints)))) (defun getenv-pathname (x &rest constraints &key ensure-directory want-directory on-error &allow-other-keys) "Extract a pathname from a user-configured environment variable, as per native OS, check constraints and normalize as per ENSURE-PATHNAME." ;; For backward compatibility with ASDF 2, want-directory implies ensure-directory (apply 'parse-native-namestring (getenvp x) :ensure-directory (or ensure-directory want-directory) :on-error (or on-error `(error "In (~S ~S), invalid pathname ~*~S: ~*~?" getenv-pathname ,x)) constraints)) (defun getenv-pathnames (x &rest constraints &key on-error &allow-other-keys) "Extract a list of pathname from a user-configured environment variable, as per native OS, check constraints and normalize each one as per ENSURE-PATHNAME. Any empty entries in the environment variable X will be returned as NILs." (unless (getf constraints :empty-is-nil t) (parameter-error "Cannot have EMPTY-IS-NIL false for ~S" 'getenv-pathnames)) (apply 'split-native-pathnames-string (getenvp x) :on-error (or on-error `(error "In (~S ~S), invalid pathname ~*~S: ~*~?" getenv-pathnames ,x)) :empty-is-nil t constraints)) (defun getenv-absolute-directory (x) "Extract an absolute directory pathname from a user-configured environment variable, as per native OS" (getenv-pathname x :want-absolute t :ensure-directory t)) (defun getenv-absolute-directories (x) "Extract a list of absolute directories from a user-configured environment variable, as per native OS. Any empty entries in the environment variable X will be returned as NILs." (getenv-pathnames x :want-absolute t :ensure-directory t)) (defun lisp-implementation-directory (&key truename) "Where are the system files of the current installation of the CL implementation?" (declare (ignorable truename)) (let ((dir #+abcl extensions:*lisp-home* #+(or allegro clasp ecl mkcl) #p"SYS:" #+clisp custom:*lib-directory* #+clozure #p"ccl:" #+cmucl (ignore-errors (pathname-parent-directory-pathname (truename #p"modules:"))) #+gcl system::*system-directory* #+lispworks lispworks:*lispworks-directory* #+sbcl (if-let (it (find-symbol* :sbcl-homedir-pathname :sb-int nil)) (funcall it) (getenv-pathname "SBCL_HOME" :ensure-directory t)) #+scl (ignore-errors (pathname-parent-directory-pathname (truename #p"file://modules/"))) #+xcl ext:*xcl-home*)) (if (and dir truename) (truename* dir) dir))) (defun lisp-implementation-pathname-p (pathname) "Is the PATHNAME under the current installation of the CL implementation?" ;; Other builtin systems are those under the implementation directory (and (when pathname (if-let (impdir (lisp-implementation-directory)) (or (subpathp pathname impdir) (when *resolve-symlinks* (if-let (truename (truename* pathname)) (if-let (trueimpdir (truename* impdir)) (subpathp truename trueimpdir))))))) t))) ;;; Simple filesystem operations (with-upgradability () (defun ensure-all-directories-exist (pathnames) "Ensure that for every pathname in PATHNAMES, we ensure its directories exist" (dolist (pathname pathnames) (when pathname (ensure-directories-exist (physicalize-pathname pathname))))) (defun delete-file-if-exists (x) "Delete a file X if it already exists" (when x (handler-case (delete-file x) (file-error () nil)))) (defun rename-file-overwriting-target (source target) "Rename a file, overwriting any previous file with the TARGET name, in an atomic way if the implementation allows." (let ((source (ensure-pathname source :namestring :lisp :ensure-physical t :want-file t)) (target (ensure-pathname target :namestring :lisp :ensure-physical t :want-file t))) #+clisp ;; in recent enough versions of CLISP, :if-exists :overwrite would make it atomic (progn (funcall 'require "syscalls") (symbol-call :posix :copy-file source target :method :rename)) #+(and sbcl os-windows) (delete-file-if-exists target) ;; not atomic #-clisp (rename-file source target #+(or clasp clozure ecl) :if-exists #+clozure :rename-and-delete #+(or clasp ecl) t))) (defun delete-empty-directory (directory-pathname) "Delete an empty directory" #+(or abcl digitool gcl) (delete-file directory-pathname) #+allegro (excl:delete-directory directory-pathname) #+clisp (ext:delete-directory directory-pathname) #+clozure (ccl::delete-empty-directory directory-pathname) #+(or cmucl scl) (multiple-value-bind (ok errno) (unix:unix-rmdir (native-namestring directory-pathname)) (unless ok #+cmucl (error "Error number ~A when trying to delete directory ~A" errno directory-pathname) #+scl (error "~@" directory-pathname (unix:get-unix-error-msg errno)))) #+cormanlisp (win32:delete-directory directory-pathname) #+(or clasp ecl) (si:rmdir directory-pathname) #+genera (fs:delete-directory directory-pathname) #+lispworks (lw:delete-directory directory-pathname) #+mkcl (mkcl:rmdir directory-pathname) #+sbcl #.(if-let (dd (find-symbol* :delete-directory :sb-ext nil)) `(,dd directory-pathname) ;; requires SBCL 1.0.44 or later `(progn (require :sb-posix) (symbol-call :sb-posix :rmdir directory-pathname))) #+xcl (symbol-call :uiop :run-program `("rmdir" ,(native-namestring directory-pathname))) #-(or abcl allegro clasp clisp clozure cmucl cormanlisp digitool ecl gcl genera lispworks mkcl sbcl scl xcl) (not-implemented-error 'delete-empty-directory "(on your platform)")) ; genera (defun delete-directory-tree (directory-pathname &key (validate nil validatep) (if-does-not-exist :error)) "Delete a directory including all its recursive contents, aka rm -rf. To reduce the risk of infortunate mistakes, DIRECTORY-PATHNAME must be a physical non-wildcard directory pathname (not namestring). If the directory does not exist, the IF-DOES-NOT-EXIST argument specifies what happens: if it is :ERROR (the default), an error is signaled, whereas if it is :IGNORE, nothing is done. Furthermore, before any deletion is attempted, the DIRECTORY-PATHNAME must pass the validation function designated (as per ENSURE-FUNCTION) by the VALIDATE keyword argument which in practice is thus compulsory, and validates by returning a non-NIL result. If you're suicidal or extremely confident, just use :VALIDATE T." (check-type if-does-not-exist (member :error :ignore)) (setf directory-pathname (ensure-pathname directory-pathname :want-pathname t :want-non-wild t :want-physical t :want-directory t)) (cond ((not validatep) (parameter-error "~S was asked to delete ~S but was not provided a validation predicate" 'delete-directory-tree directory-pathname)) ((not (call-function validate directory-pathname)) (parameter-error "~S was asked to delete ~S but it is not valid ~@[according to ~S~]" 'delete-directory-tree directory-pathname validate)) ((not (directory-exists-p directory-pathname)) (ecase if-does-not-exist (:error (error "~S was asked to delete ~S but the directory does not exist" 'delete-directory-tree directory-pathname)) (:ignore nil))) #-(or allegro cmucl clozure genera sbcl scl) ((os-unix-p) ;; On Unix, don't recursively walk the directory and delete everything in Lisp, ;; except on implementations where we can prevent DIRECTORY from following symlinks; ;; instead spawn a standard external program to do the dirty work. (symbol-call :uiop :run-program `("rm" "-rf" ,(native-namestring directory-pathname)))) (t ;; On supported implementation, call supported system functions #+allegro (symbol-call :excl.osi :delete-directory-and-files directory-pathname :if-does-not-exist if-does-not-exist) #+clozure (ccl:delete-directory directory-pathname) #+genera (fs:delete-directory directory-pathname :confirm nil) #+sbcl #.(if-let (dd (find-symbol* :delete-directory :sb-ext nil)) `(,dd directory-pathname :recursive t) ;; requires SBCL 1.0.44 or later '(error "~S requires SBCL 1.0.44 or later" 'delete-directory-tree)) ;; Outside Unix or on CMUCL and SCL that can avoid following symlinks, ;; do things the hard way. #-(or allegro clozure genera sbcl) (let ((sub*directories (while-collecting (c) (collect-sub*directories directory-pathname t t #'c)))) (dolist (d (nreverse sub*directories)) (map () 'delete-file (directory-files d)) (delete-empty-directory d))))))) ;;;; --------------------------------------------------------------------------- ;;;; Utilities related to streams (uiop/package:define-package :uiop/stream (:use :uiop/common-lisp :uiop/package :uiop/utility :uiop/os :uiop/pathname :uiop/filesystem) (:export #:*default-stream-element-type* #:*stdin* #:setup-stdin #:*stdout* #:setup-stdout #:*stderr* #:setup-stderr #:detect-encoding #:*encoding-detection-hook* #:always-default-encoding #:encoding-external-format #:*encoding-external-format-hook* #:default-encoding-external-format #:*default-encoding* #:*utf-8-external-format* #:with-safe-io-syntax #:call-with-safe-io-syntax #:safe-read-from-string #:with-output #:output-string #:with-input #:input-string #:with-input-file #:call-with-input-file #:with-output-file #:call-with-output-file #:null-device-pathname #:call-with-null-input #:with-null-input #:call-with-null-output #:with-null-output #:finish-outputs #:format! #:safe-format! #:copy-stream-to-stream #:concatenate-files #:copy-file #:slurp-stream-string #:slurp-stream-lines #:slurp-stream-line #:slurp-stream-forms #:slurp-stream-form #:read-file-string #:read-file-line #:read-file-lines #:safe-read-file-line #:read-file-forms #:read-file-form #:safe-read-file-form #:eval-input #:eval-thunk #:standard-eval-thunk #:println #:writeln #:file-stream-p #:file-or-synonym-stream-p ;; Temporary files #:*temporary-directory* #:temporary-directory #:default-temporary-directory #:setup-temporary-directory #:call-with-temporary-file #:with-temporary-file #:add-pathname-suffix #:tmpize-pathname #:call-with-staging-pathname #:with-staging-pathname)) (in-package :uiop/stream) (with-upgradability () (defvar *default-stream-element-type* (or #+(or abcl cmucl cormanlisp scl xcl) 'character #+lispworks 'lw:simple-char :default) "default element-type for open (depends on the current CL implementation)") (defvar *stdin* *standard-input* "the original standard input stream at startup") (defun setup-stdin () (setf *stdin* #.(or #+clozure 'ccl::*stdin* #+(or cmucl scl) 'system:*stdin* #+(or clasp ecl) 'ext::+process-standard-input+ #+sbcl 'sb-sys:*stdin* '*standard-input*))) (defvar *stdout* *standard-output* "the original standard output stream at startup") (defun setup-stdout () (setf *stdout* #.(or #+clozure 'ccl::*stdout* #+(or cmucl scl) 'system:*stdout* #+(or clasp ecl) 'ext::+process-standard-output+ #+sbcl 'sb-sys:*stdout* '*standard-output*))) (defvar *stderr* *error-output* "the original error output stream at startup") (defun setup-stderr () (setf *stderr* #.(or #+allegro 'excl::*stderr* #+clozure 'ccl::*stderr* #+(or cmucl scl) 'system:*stderr* #+(or clasp ecl) 'ext::+process-error-output+ #+sbcl 'sb-sys:*stderr* '*error-output*))) ;; Run them now. In image.lisp, we'll register them to be run at image restart. (setup-stdin) (setup-stdout) (setup-stderr)) ;;; Encodings (mostly hooks only; full support requires asdf-encodings) (with-upgradability () (defparameter *default-encoding* ;; preserve explicit user changes to something other than the legacy default :default (or (if-let (previous (and (boundp '*default-encoding*) (symbol-value '*default-encoding*))) (unless (eq previous :default) previous)) :utf-8) "Default encoding for source files. The default value :utf-8 is the portable thing. The legacy behavior was :default. If you (asdf:load-system :asdf-encodings) then you will have autodetection via *encoding-detection-hook* below, reading emacs-style -*- coding: utf-8 -*- specifications, and falling back to utf-8 or latin1 if nothing is specified.") (defparameter *utf-8-external-format* (if (featurep :asdf-unicode) (or #+clisp charset:utf-8 :utf-8) :default) "Default :external-format argument to pass to CL:OPEN and also CL:LOAD or CL:COMPILE-FILE to best process a UTF-8 encoded file. On modern implementations, this will decode UTF-8 code points as CL characters. On legacy implementations, it may fall back on some 8-bit encoding, with non-ASCII code points being read as several CL characters; hopefully, if done consistently, that won't affect program behavior too much.") (defun always-default-encoding (pathname) "Trivial function to use as *encoding-detection-hook*, always 'detects' the *default-encoding*" (declare (ignore pathname)) *default-encoding*) (defvar *encoding-detection-hook* #'always-default-encoding "Hook for an extension to define a function to automatically detect a file's encoding") (defun detect-encoding (pathname) "Detects the encoding of a specified file, going through user-configurable hooks" (if (and pathname (not (directory-pathname-p pathname)) (probe-file* pathname)) (funcall *encoding-detection-hook* pathname) *default-encoding*)) (defun default-encoding-external-format (encoding) "Default, ignorant, function to transform a character ENCODING as a portable keyword to an implementation-dependent EXTERNAL-FORMAT specification. Load system ASDF-ENCODINGS to hook in a better one." (case encoding (:default :default) ;; for backward-compatibility only. Explicit usage discouraged. (:utf-8 *utf-8-external-format*) (otherwise (cerror "Continue using :external-format :default" (compatfmt "~@") encoding) :default))) (defvar *encoding-external-format-hook* #'default-encoding-external-format "Hook for an extension (e.g. ASDF-ENCODINGS) to define a better mapping from non-default encodings to and implementation-defined external-format's") (defun encoding-external-format (encoding) "Transform a portable ENCODING keyword to an implementation-dependent EXTERNAL-FORMAT, going through all the proper hooks." (funcall *encoding-external-format-hook* (or encoding *default-encoding*)))) ;;; Safe syntax (with-upgradability () (defvar *standard-readtable* (with-standard-io-syntax *readtable*) "The standard readtable, implementing the syntax specified by the CLHS. It must never be modified, though only good implementations will even enforce that.") (defmacro with-safe-io-syntax ((&key (package :cl)) &body body) "Establish safe CL reader options around the evaluation of BODY" `(call-with-safe-io-syntax #'(lambda () (let ((*package* (find-package ,package))) ,@body)))) (defun call-with-safe-io-syntax (thunk &key (package :cl)) (with-standard-io-syntax (let ((*package* (find-package package)) (*read-default-float-format* 'double-float) (*print-readably* nil) (*read-eval* nil)) (funcall thunk)))) (defun safe-read-from-string (string &key (package :cl) (eof-error-p t) eof-value (start 0) end preserve-whitespace) "Read from STRING using a safe syntax, as per WITH-SAFE-IO-SYNTAX" (with-safe-io-syntax (:package package) (read-from-string string eof-error-p eof-value :start start :end end :preserve-whitespace preserve-whitespace)))) ;;; Output helpers (with-upgradability () (defun call-with-output-file (pathname thunk &key (element-type *default-stream-element-type*) (external-format *utf-8-external-format*) (if-exists :error) (if-does-not-exist :create)) "Open FILE for input with given recognizes options, call THUNK with the resulting stream. Other keys are accepted but discarded." (with-open-file (s pathname :direction :output :element-type element-type :external-format external-format :if-exists if-exists :if-does-not-exist if-does-not-exist) (funcall thunk s))) (defmacro with-output-file ((var pathname &rest keys &key element-type external-format if-exists if-does-not-exist) &body body) (declare (ignore element-type external-format if-exists if-does-not-exist)) `(call-with-output-file ,pathname #'(lambda (,var) ,@body) ,@keys)) (defun call-with-output (output function &key (element-type 'character)) "Calls FUNCTION with an actual stream argument, behaving like FORMAT with respect to how stream designators are interpreted: If OUTPUT is a STREAM, use it as the stream. If OUTPUT is NIL, use a STRING-OUTPUT-STREAM of given ELEMENT-TYPE as the stream, and return the resulting string. If OUTPUT is T, use *STANDARD-OUTPUT* as the stream. If OUTPUT is a STRING with a fill-pointer, use it as a STRING-OUTPUT-STREAM of given ELEMENT-TYPE. If OUTPUT is a PATHNAME, open the file and write to it, passing ELEMENT-TYPE to WITH-OUTPUT-FILE -- this latter as an extension since ASDF 3.1. \(Proper ELEMENT-TYPE treatment since ASDF 3.3.4 only.\) Otherwise, signal an error." (etypecase output (null (with-output-to-string (stream nil :element-type element-type) (funcall function stream))) ((eql t) (funcall function *standard-output*)) (stream (funcall function output)) (string (assert (fill-pointer output)) (with-output-to-string (stream output :element-type element-type) (funcall function stream))) (pathname (call-with-output-file output function :element-type element-type))))) (with-upgradability () (locally (declare #+sbcl (sb-ext:muffle-conditions style-warning)) (handler-bind (#+sbcl (style-warning #'muffle-warning)) (defmacro with-output ((output-var &optional (value output-var) &key element-type) &body body) "Bind OUTPUT-VAR to an output stream obtained from VALUE (default: previous binding of OUTPUT-VAR) treated as a stream designator per CALL-WITH-OUTPUT. Evaluate BODY in the scope of this binding." `(call-with-output ,value #'(lambda (,output-var) ,@body) ,@(when element-type `(:element-type ,element-type))))))) (defun output-string (string &optional output) "If the desired OUTPUT is not NIL, print the string to the output; otherwise return the string" (if output (with-output (output) (princ string output)) string)) ;;; Input helpers (with-upgradability () (defun call-with-input-file (pathname thunk &key (element-type *default-stream-element-type*) (external-format *utf-8-external-format*) (if-does-not-exist :error)) "Open FILE for input with given recognizes options, call THUNK with the resulting stream. Other keys are accepted but discarded." (with-open-file (s pathname :direction :input :element-type element-type :external-format external-format :if-does-not-exist if-does-not-exist) (funcall thunk s))) (defmacro with-input-file ((var pathname &rest keys &key element-type external-format if-does-not-exist) &body body) (declare (ignore element-type external-format if-does-not-exist)) `(call-with-input-file ,pathname #'(lambda (,var) ,@body) ,@keys)) (defun call-with-input (input function &key keys) "Calls FUNCTION with an actual stream argument, interpreting stream designators like READ, but also coercing strings to STRING-INPUT-STREAM, and PATHNAME to FILE-STREAM. If INPUT is a STREAM, use it as the stream. If INPUT is NIL, use a *STANDARD-INPUT* as the stream. If INPUT is T, use *TERMINAL-IO* as the stream. If INPUT is a STRING, use it as a string-input-stream. If INPUT is a PATHNAME, open it, passing KEYS to WITH-INPUT-FILE -- the latter is an extension since ASDF 3.1. Otherwise, signal an error." (etypecase input (null (funcall function *standard-input*)) ((eql t) (funcall function *terminal-io*)) (stream (funcall function input)) (string (with-input-from-string (stream input) (funcall function stream))) (pathname (apply 'call-with-input-file input function keys)))) (defmacro with-input ((input-var &optional (value input-var)) &body body) "Bind INPUT-VAR to an input stream, coercing VALUE (default: previous binding of INPUT-VAR) as per CALL-WITH-INPUT, and evaluate BODY within the scope of this binding." `(call-with-input ,value #'(lambda (,input-var) ,@body))) (defun input-string (&optional input) "If the desired INPUT is a string, return that string; otherwise slurp the INPUT into a string and return that" (if (stringp input) input (with-input (input) (funcall 'slurp-stream-string input))))) ;;; Null device (with-upgradability () (defun null-device-pathname () "Pathname to a bit bucket device that discards any information written to it and always returns EOF when read from" (os-cond ((os-unix-p) #p"/dev/null") ((os-windows-p) #p"NUL") ;; Q: how many Lisps accept the #p"NUL:" syntax? (t (error "No /dev/null on your OS")))) (defun call-with-null-input (fun &key element-type external-format if-does-not-exist) "Call FUN with an input stream that always returns end of file. The keyword arguments are allowed for backward compatibility, but are ignored." (declare (ignore element-type external-format if-does-not-exist)) (with-open-stream (input (make-concatenated-stream)) (funcall fun input))) (defmacro with-null-input ((var &rest keys &key element-type external-format if-does-not-exist) &body body) (declare (ignore element-type external-format if-does-not-exist)) "Evaluate BODY in a context when VAR is bound to an input stream that always returns end of file. The keyword arguments are allowed for backward compatibility, but are ignored." `(call-with-null-input #'(lambda (,var) ,@body) ,@keys)) (defun call-with-null-output (fun &key (element-type *default-stream-element-type*) (external-format *utf-8-external-format*) (if-exists :overwrite) (if-does-not-exist :error)) (declare (ignore element-type external-format if-exists if-does-not-exist)) "Call FUN with an output stream that discards all output. The keyword arguments are allowed for backward compatibility, but are ignored." (with-open-stream (output (make-broadcast-stream)) (funcall fun output))) (defmacro with-null-output ((var &rest keys &key element-type external-format if-does-not-exist if-exists) &body body) "Evaluate BODY in a context when VAR is bound to an output stream that discards all output. The keyword arguments are allowed for backward compatibility, but are ignored." (declare (ignore element-type external-format if-exists if-does-not-exist)) `(call-with-null-output #'(lambda (,var) ,@body) ,@keys))) ;;; Ensure output buffers are flushed (with-upgradability () (defun finish-outputs (&rest streams) "Finish output on the main output streams as well as any specified one. Useful for portably flushing I/O before user input or program exit." ;; CCL notably buffers its stream output by default. (dolist (s (append streams (list *stdout* *stderr* *error-output* *standard-output* *trace-output* *debug-io* *terminal-io* *query-io*))) (ignore-errors (finish-output s))) (values)) (defun format! (stream format &rest args) "Just like format, but call finish-outputs before and after the output." (finish-outputs stream) (apply 'format stream format args) (finish-outputs stream)) (defun safe-format! (stream format &rest args) "Variant of FORMAT that is safe against both dangerous syntax configuration and errors while printing." (with-safe-io-syntax () (ignore-errors (apply 'format! stream format args)) (finish-outputs stream)))) ; just in case format failed ;;; Simple Whole-Stream processing (with-upgradability () (defun copy-stream-to-stream (input output &key element-type buffer-size linewise prefix) "Copy the contents of the INPUT stream into the OUTPUT stream. If LINEWISE is true, then read and copy the stream line by line, with an optional PREFIX. Otherwise, using WRITE-SEQUENCE using a buffer of size BUFFER-SIZE." (with-open-stream (input input) (if linewise (loop :for (line eof) = (multiple-value-list (read-line input nil nil)) :while line :do (when prefix (princ prefix output)) (princ line output) (unless eof (terpri output)) (finish-output output) (when eof (return))) (loop :with buffer-size = (or buffer-size 8192) :with buffer = (make-array (list buffer-size) :element-type (or element-type 'character)) :for end = (read-sequence buffer input) :until (zerop end) :do (write-sequence buffer output :end end) (when (< end buffer-size) (return)))))) (defun concatenate-files (inputs output) "create a new OUTPUT file the contents of which a the concatenate of the INPUTS files." (with-open-file (o output :element-type '(unsigned-byte 8) :direction :output :if-exists :rename-and-delete) (dolist (input inputs) (with-open-file (i input :element-type '(unsigned-byte 8) :direction :input :if-does-not-exist :error) (copy-stream-to-stream i o :element-type '(unsigned-byte 8)))))) (defun copy-file (input output) "Copy contents of the INPUT file to the OUTPUT file" ;; Not available on LW personal edition or LW 6.0 on Mac: (lispworks:copy-file i f) #+allegro (excl.osi:copy-file input output) #+ecl (ext:copy-file input output) #-(or allegro ecl) (concatenate-files (list input) output)) (defun slurp-stream-string (input &key (element-type 'character) stripped) "Read the contents of the INPUT stream as a string" (let ((string (with-open-stream (input input) (with-output-to-string (output nil :element-type element-type) (copy-stream-to-stream input output :element-type element-type))))) (if stripped (stripln string) string))) (defun slurp-stream-lines (input &key count) "Read the contents of the INPUT stream as a list of lines, return those lines. Note: relies on the Lisp's READ-LINE, but additionally removes any remaining CR from the line-ending if the file or stream had CR+LF but Lisp only removed LF. Read no more than COUNT lines." (check-type count (or null integer)) (with-open-stream (input input) (loop :for n :from 0 :for l = (and (or (not count) (< n count)) (read-line input nil nil)) ;; stripln: to remove CR when the OS sends CRLF and Lisp only remove LF :while l :collect (stripln l)))) (defun slurp-stream-line (input &key (at 0)) "Read the contents of the INPUT stream as a list of lines, then return the ACCESS-AT of that list of lines using the AT specifier. PATH defaults to 0, i.e. return the first line. PATH is typically an integer, or a list of an integer and a function. If PATH is NIL, it will return all the lines in the file. The stream will not be read beyond the Nth lines, where N is the index specified by path if path is either an integer or a list that starts with an integer." (access-at (slurp-stream-lines input :count (access-at-count at)) at)) (defun slurp-stream-forms (input &key count) "Read the contents of the INPUT stream as a list of forms, and return those forms. If COUNT is null, read to the end of the stream; if COUNT is an integer, stop after COUNT forms were read. BEWARE: be sure to use WITH-SAFE-IO-SYNTAX, or some variant thereof" (check-type count (or null integer)) (loop :with eof = '#:eof :for n :from 0 :for form = (if (and count (>= n count)) eof (read-preserving-whitespace input nil eof)) :until (eq form eof) :collect form)) (defun slurp-stream-form (input &key (at 0)) "Read the contents of the INPUT stream as a list of forms, then return the ACCESS-AT of these forms following the AT. AT defaults to 0, i.e. return the first form. AT is typically a list of integers. If AT is NIL, it will return all the forms in the file. The stream will not be read beyond the Nth form, where N is the index specified by path, if path is either an integer or a list that starts with an integer. BEWARE: be sure to use WITH-SAFE-IO-SYNTAX, or some variant thereof" (access-at (slurp-stream-forms input :count (access-at-count at)) at)) (defun read-file-string (file &rest keys) "Open FILE with option KEYS, read its contents as a string" (apply 'call-with-input-file file 'slurp-stream-string keys)) (defun read-file-lines (file &rest keys) "Open FILE with option KEYS, read its contents as a list of lines BEWARE: be sure to use WITH-SAFE-IO-SYNTAX, or some variant thereof" (apply 'call-with-input-file file 'slurp-stream-lines keys)) (defun read-file-line (file &rest keys &key (at 0) &allow-other-keys) "Open input FILE with option KEYS (except AT), and read its contents as per SLURP-STREAM-LINE with given AT specifier. BEWARE: be sure to use WITH-SAFE-IO-SYNTAX, or some variant thereof" (apply 'call-with-input-file file #'(lambda (input) (slurp-stream-line input :at at)) (remove-plist-key :at keys))) (defun read-file-forms (file &rest keys &key count &allow-other-keys) "Open input FILE with option KEYS (except COUNT), and read its contents as per SLURP-STREAM-FORMS with given COUNT. If COUNT is null, read to the end of the stream; if COUNT is an integer, stop after COUNT forms were read. BEWARE: be sure to use WITH-SAFE-IO-SYNTAX, or some variant thereof" (apply 'call-with-input-file file #'(lambda (input) (slurp-stream-forms input :count count)) (remove-plist-key :count keys))) (defun read-file-form (file &rest keys &key (at 0) &allow-other-keys) "Open input FILE with option KEYS (except AT), and read its contents as per SLURP-STREAM-FORM with given AT specifier. BEWARE: be sure to use WITH-SAFE-IO-SYNTAX, or some variant thereof" (apply 'call-with-input-file file #'(lambda (input) (slurp-stream-form input :at at)) (remove-plist-key :at keys))) (defun safe-read-file-line (pathname &rest keys &key (package :cl) &allow-other-keys) "Reads the specified line from the top of a file using a safe standardized syntax. Extracts the line using READ-FILE-LINE, within an WITH-SAFE-IO-SYNTAX using the specified PACKAGE." (with-safe-io-syntax (:package package) (apply 'read-file-line pathname (remove-plist-key :package keys)))) (defun safe-read-file-form (pathname &rest keys &key (package :cl) &allow-other-keys) "Reads the specified form from the top of a file using a safe standardized syntax. Extracts the form using READ-FILE-FORM, within an WITH-SAFE-IO-SYNTAX using the specified PACKAGE." (with-safe-io-syntax (:package package) (apply 'read-file-form pathname (remove-plist-key :package keys)))) (defun eval-input (input) "Portably read and evaluate forms from INPUT, return the last values." (with-input (input) (loop :with results :with eof ='#:eof :for form = (read input nil eof) :until (eq form eof) :do (setf results (multiple-value-list (eval form))) :finally (return (values-list results))))) (defun eval-thunk (thunk) "Evaluate a THUNK of code: If a function, FUNCALL it without arguments. If a constant literal and not a sequence, return it. If a cons or a symbol, EVAL it. If a string, repeatedly read and evaluate from it, returning the last values." (etypecase thunk ((or boolean keyword number character pathname) thunk) ((or cons symbol) (eval thunk)) (function (funcall thunk)) (string (eval-input thunk)))) (defun standard-eval-thunk (thunk &key (package :cl)) "Like EVAL-THUNK, but in a more standardized evaluation context." ;; Note: it's "standard-" not "safe-", because evaluation is never safe. (when thunk (with-safe-io-syntax (:package package) (let ((*read-eval* t)) (eval-thunk thunk)))))) (with-upgradability () (defun println (x &optional (stream *standard-output*)) "Variant of PRINC that also calls TERPRI afterwards" (princ x stream) (terpri stream) (finish-output stream) (values)) (defun writeln (x &rest keys &key (stream *standard-output*) &allow-other-keys) "Variant of WRITE that also calls TERPRI afterwards" (apply 'write x keys) (terpri stream) (finish-output stream) (values))) ;;; Using temporary files (with-upgradability () (defun default-temporary-directory () "Return a default directory to use for temporary files" (os-cond ((os-unix-p) (or (getenv-pathname "TMPDIR" :ensure-directory t) (parse-native-namestring "/tmp/"))) ((os-windows-p) (getenv-pathname "TEMP" :ensure-directory t)) (t (subpathname (user-homedir-pathname) "tmp/")))) (defvar *temporary-directory* nil "User-configurable location for temporary files") (defun temporary-directory () "Return a directory to use for temporary files" (or *temporary-directory* (default-temporary-directory))) (defun setup-temporary-directory () "Configure a default temporary directory to use." (setf *temporary-directory* (default-temporary-directory)) #+gcl (setf system::*tmp-dir* *temporary-directory*)) (defun call-with-temporary-file (thunk &key (want-stream-p t) (want-pathname-p t) (direction :io) keep after directory (type "tmp" typep) prefix (suffix (when typep "-tmp")) (element-type *default-stream-element-type*) (external-format *utf-8-external-format*)) "Call a THUNK with stream and/or pathname arguments identifying a temporary file. The temporary file's pathname will be based on concatenating PREFIX (or \"tmp\" if it's NIL), a random alphanumeric string, and optional SUFFIX (defaults to \"-tmp\" if a type was provided) and TYPE (defaults to \"tmp\", using a dot as separator if not NIL), within DIRECTORY (defaulting to the TEMPORARY-DIRECTORY) if the PREFIX isn't absolute. The file will be open with specified DIRECTION (defaults to :IO), ELEMENT-TYPE (defaults to *DEFAULT-STREAM-ELEMENT-TYPE*) and EXTERNAL-FORMAT (defaults to *UTF-8-EXTERNAL-FORMAT*). If WANT-STREAM-P is true (the defaults to T), then THUNK will then be CALL-FUNCTION'ed with the stream and the pathname (if WANT-PATHNAME-P is true, defaults to T), and stream will be closed after the THUNK exits (either normally or abnormally). If WANT-STREAM-P is false, then WANT-PATHAME-P must be true, and then THUNK is only CALL-FUNCTION'ed after the stream is closed, with the pathname as argument. Upon exit of THUNK, the AFTER thunk if defined is CALL-FUNCTION'ed with the pathname as argument. If AFTER is defined, its results are returned, otherwise, the results of THUNK are returned. Finally, the file will be deleted, unless the KEEP argument when CALL-FUNCTION'ed returns true." #+xcl (declare (ignorable typep)) (check-type direction (member :output :io)) (assert (or want-stream-p want-pathname-p)) (loop :with prefix-pn = (ensure-absolute-pathname (or prefix "tmp") (or (ensure-pathname directory :namestring :native :ensure-directory t :ensure-physical t) #'temporary-directory)) :with prefix-nns = (native-namestring prefix-pn) :with results = (progn (ensure-directories-exist prefix-pn) ()) :for counter :from (random (expt 36 #-gcl 8 #+gcl 5)) :for pathname = (parse-native-namestring (format nil "~A~36R~@[~A~]~@[.~A~]" prefix-nns counter suffix (unless (eq type :unspecific) type))) :for okp = nil :do ;; TODO: on Unix, do something about umask ;; TODO: on Unix, audit the code so we make sure it uses O_CREAT|O_EXCL ;; TODO: on Unix, use CFFI and mkstemp -- ;; except UIOP is precisely meant to not depend on CFFI or on anything! Grrrr. ;; Can we at least design some hook? (unwind-protect (progn (ensure-directories-exist pathname) (with-open-file (stream pathname :direction direction :element-type element-type :external-format external-format :if-exists nil :if-does-not-exist :create) (when stream (setf okp pathname) (when want-stream-p ;; Note: can't return directly from within with-open-file ;; or the non-local return causes the file creation to be undone. (setf results (multiple-value-list (if want-pathname-p (call-function thunk stream pathname) (call-function thunk stream))))))) ;; if we don't want a stream, then we must call the thunk *after* ;; the stream is closed, but only if it was successfully opened. (when okp (when (and want-pathname-p (not want-stream-p)) (setf results (multiple-value-list (call-function thunk okp)))) ;; if the stream was successfully opened, then return a value, ;; either one computed already, or one from AFTER, if that exists. (if after (return (call-function after pathname)) (return (values-list results))))) (when (and okp (not (call-function keep))) (ignore-errors (delete-file-if-exists okp)))))) (defmacro with-temporary-file ((&key (stream (gensym "STREAM") streamp) (pathname (gensym "PATHNAME") pathnamep) directory prefix suffix type keep direction element-type external-format) &body body) "Evaluate BODY where the symbols specified by keyword arguments STREAM and PATHNAME (if respectively specified) are bound corresponding to a newly created temporary file ready for I/O, as per CALL-WITH-TEMPORARY-FILE. At least one of STREAM or PATHNAME must be specified. If the STREAM is not specified, it will be closed before the BODY is evaluated. If STREAM is specified, then the :CLOSE-STREAM label if it appears in the BODY, separates forms run before and after the stream is closed. The values of the last form of the BODY (not counting the separating :CLOSE-STREAM) are returned. Upon success, the KEEP form is evaluated and the file is is deleted unless it evaluates to TRUE." (check-type stream symbol) (check-type pathname symbol) (assert (or streamp pathnamep)) (let* ((afterp (position :close-stream body)) (before (if afterp (subseq body 0 afterp) body)) (after (when afterp (subseq body (1+ afterp)))) (beforef (gensym "BEFORE")) (afterf (gensym "AFTER"))) (when (eql afterp 0) (style-warn ":CLOSE-STREAM should not be the first form of BODY in WITH-TEMPORARY-FILE. Instead, do not provide a STREAM.")) `(flet (,@(when before `((,beforef (,@(when streamp `(,stream)) ,@(when pathnamep `(,pathname))) ,@(when after `((declare (ignorable ,pathname)))) ,@before))) ,@(when after (assert pathnamep) `((,afterf (,pathname) ,@after)))) #-gcl (declare (dynamic-extent ,@(when before `(#',beforef)) ,@(when after `(#',afterf)))) (call-with-temporary-file ,(when before `#',beforef) :want-stream-p ,streamp :want-pathname-p ,pathnamep ,@(when direction `(:direction ,direction)) ,@(when directory `(:directory ,directory)) ,@(when prefix `(:prefix ,prefix)) ,@(when suffix `(:suffix ,suffix)) ,@(when type `(:type ,type)) ,@(when keep `(:keep ,keep)) ,@(when after `(:after #',afterf)) ,@(when element-type `(:element-type ,element-type)) ,@(when external-format `(:external-format ,external-format)))))) (defun get-temporary-file (&key directory prefix suffix type (keep t)) (with-temporary-file (:pathname pn :keep keep :directory directory :prefix prefix :suffix suffix :type type) pn)) ;; Temporary pathnames in simple cases where no contention is assumed (defun add-pathname-suffix (pathname suffix &rest keys) "Add a SUFFIX to the name of a PATHNAME, return a new pathname. Further KEYS can be passed to MAKE-PATHNAME." (apply 'make-pathname :name (strcat (pathname-name pathname) suffix) :defaults pathname keys)) (defun tmpize-pathname (x) "Return a new pathname modified from X by adding a trivial random suffix. A new empty file with said temporary pathname is created, to ensure there is no clash with any concurrent process attempting the same thing." (let* ((px (ensure-pathname x :ensure-physical t)) (prefix (if-let (n (pathname-name px)) (strcat n "-tmp") "tmp")) (directory (pathname-directory-pathname px))) ;; Genera uses versioned pathnames -- If we leave the empty file in place, ;; the system will create a new version of the file when the caller opens ;; it for output. That empty file will remain after the operation is completed. ;; As Genera is a single core processor, the possibility of a name conflict is ;; minimal if not nil. (And, in the event of a collision, the two processes ;; would be writing to different versions of the file.) (get-temporary-file :directory directory :prefix prefix :type (pathname-type px) #+genera :keep #+genera nil))) (defun call-with-staging-pathname (pathname fun) "Calls FUN with a staging pathname, and atomically renames the staging pathname to the PATHNAME in the end. NB: this protects only against failure of the program, not against concurrent attempts. For the latter case, we ought pick a random suffix and atomically open it." (let* ((pathname (pathname pathname)) (staging (tmpize-pathname pathname))) (unwind-protect (multiple-value-prog1 (funcall fun staging) (rename-file-overwriting-target staging pathname)) (delete-file-if-exists staging)))) (defmacro with-staging-pathname ((pathname-var &optional (pathname-value pathname-var)) &body body) "Trivial syntax wrapper for CALL-WITH-STAGING-PATHNAME" `(call-with-staging-pathname ,pathname-value #'(lambda (,pathname-var) ,@body)))) (with-upgradability () (defun file-stream-p (stream) (typep stream 'file-stream)) (defun file-or-synonym-stream-p (stream) (or (file-stream-p stream) (and (typep stream 'synonym-stream) (file-or-synonym-stream-p (symbol-value (synonym-stream-symbol stream))))))) ;;;; ------------------------------------------------------------------------- ;;;; Starting, Stopping, Dumping a Lisp image (uiop/package:define-package :uiop/image (:use :uiop/common-lisp :uiop/package :uiop/utility :uiop/pathname :uiop/stream :uiop/os) (:export #:*image-dumped-p* #:raw-command-line-arguments #:*command-line-arguments* #:command-line-arguments #:raw-command-line-arguments #:setup-command-line-arguments #:argv0 #:*lisp-interaction* #:fatal-condition #:fatal-condition-p #:handle-fatal-condition #:call-with-fatal-condition-handler #:with-fatal-condition-handler #:*image-restore-hook* #:*image-prelude* #:*image-entry-point* #:*image-postlude* #:*image-dump-hook* #:quit #:die #:raw-print-backtrace #:print-backtrace #:print-condition-backtrace #:shell-boolean-exit #:register-image-restore-hook #:register-image-dump-hook #:call-image-restore-hook #:call-image-dump-hook #:restore-image #:dump-image #:create-image )) (in-package :uiop/image) (with-upgradability () (defvar *lisp-interaction* t "Is this an interactive Lisp environment, or is it batch processing?") (defvar *command-line-arguments* nil "Command-line arguments") (defvar *image-dumped-p* nil ; may matter as to how to get to command-line-arguments "Is this a dumped image? As a standalone executable?") (defvar *image-restore-hook* nil "Functions to call (in reverse order) when the image is restored") (defvar *image-restored-p* nil "Has the image been restored? A boolean, or :in-progress while restoring, :in-regress while dumping") (defvar *image-prelude* nil "a form to evaluate, or string containing forms to read and evaluate when the image is restarted, but before the entry point is called.") (defvar *image-entry-point* nil "a function with which to restart the dumped image when execution is restored from it.") (defvar *image-postlude* nil "a form to evaluate, or string containing forms to read and evaluate before the image dump hooks are called and before the image is dumped.") (defvar *image-dump-hook* nil "Functions to call (in order) when before an image is dumped")) (eval-when (#-lispworks :compile-toplevel :load-toplevel :execute) (deftype fatal-condition () `(and serious-condition #+clozure (not ccl:process-reset)))) ;;; Exiting properly or im- (with-upgradability () (defun quit (&optional (code 0) (finish-output t)) "Quits from the Lisp world, with the given exit status if provided. This is designed to abstract away the implementation specific quit forms." (when finish-output ;; essential, for ClozureCL, and for standard compliance. (finish-outputs)) #+(or abcl xcl) (ext:quit :status code) #+allegro (excl:exit code :quiet t) #+(or clasp ecl) (si:quit code) #+clisp (ext:quit code) #+clozure (ccl:quit code) #+cormanlisp (win32:exitprocess code) #+(or cmucl scl) (unix:unix-exit code) #+gcl (system:quit code) #+genera (error "~S: You probably don't want to Halt Genera. (code: ~S)" 'quit code) #+lispworks (lispworks:quit :status code :confirm nil :return nil :ignore-errors-p t) #+mcl (progn code (ccl:quit)) ;; or should we use FFI to call libc's exit(3) ? #+mkcl (mk-ext:quit :exit-code code) #+sbcl #.(let ((exit (find-symbol* :exit :sb-ext nil)) (quit (find-symbol* :quit :sb-ext nil))) (cond (exit `(,exit :code code :abort (not finish-output))) (quit `(,quit :unix-status code :recklessly-p (not finish-output))))) #-(or abcl allegro clasp clisp clozure cmucl ecl gcl genera lispworks mcl mkcl sbcl scl xcl) (not-implemented-error 'quit "(called with exit code ~S)" code)) (defun die (code format &rest arguments) "Die in error with some error message" (with-safe-io-syntax () (ignore-errors (format! *stderr* "~&~?~&" format arguments))) (quit code)) (defun raw-print-backtrace (&key (stream *debug-io*) count condition) "Print a backtrace, directly accessing the implementation" (declare (ignorable stream count condition)) #+abcl (loop :for i :from 0 :for frame :in (sys:backtrace (or count most-positive-fixnum)) :do (safe-format! stream "~&~D: ~A~%" i frame)) #+allegro (let ((*terminal-io* stream) (*standard-output* stream) (tpl:*zoom-print-circle* *print-circle*) (tpl:*zoom-print-level* *print-level*) (tpl:*zoom-print-length* *print-length*)) (tpl:do-command "zoom" :from-read-eval-print-loop nil :count (or count t) :all t)) #+clasp (clasp-debug:print-backtrace :stream stream :count count) #+(or ecl mkcl) (let* ((top (si:ihs-top)) (repeats (if count (min top count) top)) (backtrace (loop :for ihs :from 0 :below top :collect (list (si::ihs-fun ihs) (si::ihs-env ihs))))) (loop :for i :from 0 :below repeats :for frame :in (nreverse backtrace) :do (safe-format! stream "~&~D: ~S~%" i frame))) #+clisp (system::print-backtrace :out stream :limit count) #+(or clozure mcl) (let ((*debug-io* stream)) #+clozure (ccl:print-call-history :count count :start-frame-number 1) #+mcl (ccl:print-call-history :detailed-p nil) (finish-output stream)) #+(or cmucl scl) (let ((debug:*debug-print-level* *print-level*) (debug:*debug-print-length* *print-length*)) (debug:backtrace (or count most-positive-fixnum) stream)) #+gcl (let ((*debug-io* stream)) (ignore-errors (with-safe-io-syntax () (if condition (conditions::condition-backtrace condition) (system::simple-backtrace))))) #+lispworks (let ((dbg::*debugger-stack* (dbg::grab-stack nil :how-many (or count most-positive-fixnum))) (*debug-io* stream) (dbg:*debug-print-level* *print-level*) (dbg:*debug-print-length* *print-length*)) (dbg:bug-backtrace nil)) #+mezzano (let ((*standard-output* stream)) (sys.int::backtrace count)) #+sbcl (sb-debug:print-backtrace :stream stream :count (or count most-positive-fixnum)) #+xcl (loop :for i :from 0 :below (or count most-positive-fixnum) :for frame :in (extensions:backtrace-as-list) :do (safe-format! stream "~&~D: ~S~%" i frame))) (defun print-backtrace (&rest keys &key stream count condition) "Print a backtrace" (declare (ignore stream count condition)) (with-safe-io-syntax (:package :cl) (let ((*print-readably* nil) (*print-circle* t) (*print-miser-width* 75) (*print-length* nil) (*print-level* nil) (*print-pretty* t)) (ignore-errors (apply 'raw-print-backtrace keys))))) (defun print-condition-backtrace (condition &key (stream *stderr*) count) "Print a condition after a backtrace triggered by that condition" ;; We print the condition *after* the backtrace, ;; for the sake of who sees the backtrace at a terminal. ;; It is up to the caller to print the condition *before*, with some context. (print-backtrace :stream stream :count count :condition condition) (when condition (safe-format! stream "~&Above backtrace due to this condition:~%~A~&" condition))) (defun fatal-condition-p (condition) "Is the CONDITION fatal?" (typep condition 'fatal-condition)) (defun handle-fatal-condition (condition) "Handle a fatal CONDITION: depending on whether *LISP-INTERACTION* is set, enter debugger or die" (cond (*lisp-interaction* (invoke-debugger condition)) (t (safe-format! *stderr* "~&Fatal condition:~%~A~%" condition) (print-condition-backtrace condition :stream *stderr*) (die 99 "~A" condition)))) (defun call-with-fatal-condition-handler (thunk) "Call THUNK in a context where fatal conditions are appropriately handled" (handler-bind ((fatal-condition #'handle-fatal-condition)) (funcall thunk))) (defmacro with-fatal-condition-handler ((&optional) &body body) "Execute BODY in a context where fatal conditions are appropriately handled" `(call-with-fatal-condition-handler #'(lambda () ,@body))) (defun shell-boolean-exit (x) "Quit with a return code that is 0 iff argument X is true" (quit (if x 0 1)))) ;;; Using image hooks (with-upgradability () (defun register-image-restore-hook (hook &optional (call-now-p t)) "Regiter a hook function to be run when restoring a dumped image" (register-hook-function '*image-restore-hook* hook call-now-p)) (defun register-image-dump-hook (hook &optional (call-now-p nil)) "Register a the hook function to be run before to dump an image" (register-hook-function '*image-dump-hook* hook call-now-p)) (defun call-image-restore-hook () "Call the hook functions registered to be run when restoring a dumped image" (call-functions (reverse *image-restore-hook*))) (defun call-image-dump-hook () "Call the hook functions registered to be run before to dump an image" (call-functions *image-dump-hook*))) ;;; Proper command-line arguments (with-upgradability () (defun raw-command-line-arguments () "Find what the actual command line for this process was." #+abcl ext:*command-line-argument-list* ; Use 1.0.0 or later! #+allegro (sys:command-line-arguments) ; default: :application t #+(or clasp ecl) (loop :for i :from 0 :below (si:argc) :collect (si:argv i)) #+clisp (coerce (ext:argv) 'list) #+clozure ccl:*command-line-argument-list* #+(or cmucl scl) extensions:*command-line-strings* #+gcl si:*command-args* #+(or genera mcl mezzano) nil #+lispworks sys:*line-arguments-list* #+mkcl (loop :for i :from 0 :below (mkcl:argc) :collect (mkcl:argv i)) #+sbcl sb-ext:*posix-argv* #+xcl system:*argv* #-(or abcl allegro clasp clisp clozure cmucl ecl gcl genera lispworks mcl mezzano mkcl sbcl scl xcl) (not-implemented-error 'raw-command-line-arguments)) (defun command-line-arguments (&optional (arguments (raw-command-line-arguments))) "Extract user arguments from command-line invocation of current process. Assume the calling conventions of a generated script that uses -- if we are not called from a directly executable image." (block nil #+abcl (return arguments) ;; SBCL and Allegro already separate user arguments from implementation arguments. #-(or sbcl allegro) (unless (eq *image-dumped-p* :executable) ;; LispWorks command-line processing isn't transparent to the user ;; unless you create a standalone executable; in that case, ;; we rely on cl-launch or some other script to set the arguments for us. #+lispworks (return *command-line-arguments*) ;; On other implementations, on non-standalone executables, ;; we trust cl-launch or whichever script starts the program ;; to use -- as a delimiter between implementation arguments and user arguments. #-lispworks (setf arguments (member "--" arguments :test 'string-equal))) (rest arguments))) (defun argv0 () "On supported implementations (most that matter), or when invoked by a proper wrapper script, return a string that for the name with which the program was invoked, i.e. argv[0] in C. Otherwise, return NIL." (cond ((eq *image-dumped-p* :executable) ; yes, this ARGV0 is our argv0 ! ;; NB: not currently available on ABCL, Corman, Genera, MCL (or #+(or allegro clisp clozure cmucl gcl lispworks sbcl scl xcl) (first (raw-command-line-arguments)) #+(or clasp ecl) (si:argv 0) #+mkcl (mkcl:argv 0))) (t ;; argv[0] is the name of the interpreter. ;; The wrapper script can export __CL_ARGV0. cl-launch does as of 4.0.1.8. (getenvp "__CL_ARGV0")))) (defun setup-command-line-arguments () (setf *command-line-arguments* (command-line-arguments))) (defun restore-image (&key (lisp-interaction *lisp-interaction*) (restore-hook *image-restore-hook*) (prelude *image-prelude*) (entry-point *image-entry-point*) (if-already-restored '(cerror "RUN RESTORE-IMAGE ANYWAY"))) "From a freshly restarted Lisp image, restore the saved Lisp environment by setting appropriate variables, running various hooks, and calling any specified entry point. If the image has already been restored or is already being restored, as per *IMAGE-RESTORED-P*, call the IF-ALREADY-RESTORED error handler (by default, a continuable error), and do return immediately to the surrounding restore process if allowed to continue. Then, comes the restore process itself: First, call each function in the RESTORE-HOOK, in the order they were registered with REGISTER-IMAGE-RESTORE-HOOK. Second, evaluate the prelude, which is often Lisp text that is read, as per EVAL-INPUT. Third, call the ENTRY-POINT function, if any is specified, with no argument. The restore process happens in a WITH-FATAL-CONDITION-HANDLER, so that if LISP-INTERACTION is NIL, any unhandled error leads to a backtrace and an exit with an error status. If LISP-INTERACTION is NIL, the process also exits when no error occurs: if neither restart nor entry function is provided, the program will exit with status 0 (success); if a function was provided, the program will exit after the function returns (if it returns), with status 0 if and only if the primary return value of result is generalized boolean true, and with status 1 if this value is NIL. If LISP-INTERACTION is true, unhandled errors will take you to the debugger, and the result of the function will be returned rather than interpreted as a boolean designating an exit code." (when *image-restored-p* (if if-already-restored (call-function if-already-restored "Image already ~:[being ~;~]restored" (eq *image-restored-p* t)) (return-from restore-image))) (with-fatal-condition-handler () (setf *lisp-interaction* lisp-interaction) (setf *image-restore-hook* restore-hook) (setf *image-prelude* prelude) (setf *image-restored-p* :in-progress) (call-image-restore-hook) (standard-eval-thunk prelude) (setf *image-restored-p* t) (let ((results (multiple-value-list (if entry-point (call-function entry-point) t)))) (if lisp-interaction (values-list results) (shell-boolean-exit (first results))))))) ;;; Dumping an image (with-upgradability () (defun dump-image (filename &key output-name executable (postlude *image-postlude*) (dump-hook *image-dump-hook*) #+clozure prepend-symbols #+clozure (purify t) #+sbcl compression #+(and sbcl os-windows) application-type) "Dump an image of the current Lisp environment at pathname FILENAME, with various options. First, finalize the image, by evaluating the POSTLUDE as per EVAL-INPUT, then calling each of the functions in DUMP-HOOK, in reverse order of registration by REGISTER-IMAGE-DUMP-HOOK. If EXECUTABLE is true, create an standalone executable program that calls RESTORE-IMAGE on startup. Pass various implementation-defined options, such as PREPEND-SYMBOLS and PURITY on CCL, or COMPRESSION on SBCL, and APPLICATION-TYPE on SBCL/Windows." ;; Note: at least SBCL saves only global values of variables in the heap image, ;; so make sure things you want to dump are NOT just local bindings shadowing the global values. (declare (ignorable filename output-name executable)) (setf *image-dumped-p* (if executable :executable t)) (setf *image-restored-p* :in-regress) (setf *image-postlude* postlude) (standard-eval-thunk *image-postlude*) (setf *image-dump-hook* dump-hook) (call-image-dump-hook) (setf *image-restored-p* nil) #-(or clisp clozure (and cmucl executable) lispworks sbcl scl) (when executable (not-implemented-error 'dump-image "dumping an executable")) #+allegro (progn (sys:resize-areas :global-gc t :pack-heap t :sift-old-areas t :tenure t) ; :new 5000000 (excl:dumplisp :name filename :suppress-allegro-cl-banner t)) #+clisp (apply #'ext:saveinitmem filename :quiet t :start-package *package* :keep-global-handlers nil ;; Faré explains the odd executable value (slightly paraphrased): ;; 0 is very different from t in clisp and there for a good reason: ;; 0 turns the executable into one that has its own command-line handling, so hackers can't ;; use the underlying -i or -x to turn your would-be restricted binary into an unrestricted evaluator. :executable (if executable 0 t) ;--- requires clisp 2.48 or later, still catches --clisp-x (when executable (list ;; :parse-options nil ;--- requires a non-standard patch to clisp. :norc t :script nil :init-function #'restore-image))) #+clozure (flet ((dump (prepend-kernel) (ccl:save-application filename :prepend-kernel prepend-kernel :purify purify :toplevel-function (when executable #'restore-image)))) ;;(setf ccl::*application* (make-instance 'ccl::lisp-development-system)) (if prepend-symbols (with-temporary-file (:prefix "ccl-symbols-" :direction :output :pathname path) (require 'elf) (funcall (fdefinition 'ccl::write-elf-symbols-to-file) path) (dump path)) (dump t))) #+(or cmucl scl) (progn (ext:gc :full t) (setf ext:*batch-mode* nil) (setf ext::*gc-run-time* 0) (apply 'ext:save-lisp filename :allow-other-keys t ;; hush SCL and old versions of CMUCL #+(and cmucl executable) :executable #+(and cmucl executable) t (when executable '(:init-function restore-image :process-command-line nil :quiet t :load-init-file nil :site-init nil)))) #+gcl (progn (si::set-hole-size 500) (si::gbc nil) (si::sgc-on t) (si::save-system filename)) #+lispworks (if executable (lispworks:deliver 'restore-image filename 0 :interface nil) (hcl:save-image filename :environment nil)) #+sbcl (progn ;;(sb-pcl::precompile-random-code-segments) ;--- it is ugly slow at compile-time (!) when the initial core is a big CLOS program. If you want it, do it yourself (setf sb-ext::*gc-run-time* 0) (apply 'sb-ext:save-lisp-and-die filename :executable t ;--- always include the runtime that goes with the core (append (when compression (list :compression compression)) ;;--- only save runtime-options for standalone executables (when executable (list :toplevel #'restore-image :save-runtime-options t)) #+(and sbcl os-windows) ;; passing :application-type :gui will disable the console window. ;; the default is :console - only works with SBCL 1.1.15 or later. (when application-type (list :application-type application-type))))) #-(or allegro clisp clozure cmucl gcl lispworks sbcl scl) (not-implemented-error 'dump-image)) (defun create-image (destination lisp-object-files &key kind output-name prologue-code epilogue-code extra-object-files (prelude () preludep) (postlude () postludep) (entry-point () entry-point-p) build-args no-uiop) (declare (ignorable destination lisp-object-files extra-object-files kind output-name prologue-code epilogue-code prelude preludep postlude postludep entry-point entry-point-p build-args no-uiop)) "On ECL, create an executable at pathname DESTINATION from the specified OBJECT-FILES and options" ;; Is it meaningful to run these in the current environment? ;; only if we also track the object files that constitute the "current" image, ;; and otherwise simulate dump-image, including quitting at the end. #-(or clasp ecl mkcl) (not-implemented-error 'create-image) #+(or clasp ecl mkcl) (let ((epilogue-code (if no-uiop epilogue-code (let ((forms (append (when epilogue-code `(,epilogue-code)) (when postludep `((setf *image-postlude* ',postlude))) (when preludep `((setf *image-prelude* ',prelude))) (when entry-point-p `((setf *image-entry-point* ',entry-point))) (case kind ((:image) (setf kind :program) ;; to ECL, it's just another program. `((setf *image-dumped-p* t) (si::top-level #+(or clasp ecl) t) (quit))) ((:program) `((setf *image-dumped-p* :executable) (shell-boolean-exit (restore-image)))))))) (when forms `(progn ,@forms)))))) (check-type kind (member :dll :shared-library :lib :static-library :fasl :fasb :program)) (apply #+clasp 'cmp:builder #+clasp kind #+(or ecl mkcl) (ecase kind ((:dll :shared-library) #+ecl 'c::build-shared-library #+mkcl 'compiler:build-shared-library) ((:lib :static-library) #+ecl 'c::build-static-library #+mkcl 'compiler:build-static-library) ((:fasl #+ecl :fasb) #+ecl 'c::build-fasl #+mkcl 'compiler:build-fasl) #+mkcl ((:fasb) 'compiler:build-bundle) ((:program) #+ecl 'c::build-program #+mkcl 'compiler:build-program)) (pathname destination) #+(or clasp ecl) :lisp-files #+mkcl :lisp-object-files (append lisp-object-files #+(or clasp ecl) extra-object-files) #+ecl :init-name #+ecl (getf build-args :init-name) (append (when prologue-code `(:prologue-code ,prologue-code)) (when epilogue-code `(:epilogue-code ,epilogue-code)) #+mkcl (when extra-object-files `(:object-files ,extra-object-files)) build-args))))) ;;; Some universal image restore hooks (with-upgradability () (map () 'register-image-restore-hook '(setup-stdin setup-stdout setup-stderr setup-command-line-arguments setup-temporary-directory #+abcl detect-os))) ;;;; ------------------------------------------------------------------------- ;;;; Support to build (compile and load) Lisp files (uiop/package:define-package :uiop/lisp-build (:nicknames :asdf/lisp-build) ;; OBSOLETE, used by slime/contrib/swank-asdf.lisp (:use :uiop/common-lisp :uiop/package :uiop/utility :uiop/os :uiop/pathname :uiop/filesystem :uiop/stream :uiop/image) (:export ;; Variables #:*compile-file-warnings-behaviour* #:*compile-file-failure-behaviour* #:*output-translation-function* #:*optimization-settings* #:*previous-optimization-settings* #:*base-build-directory* #:compile-condition #:compile-file-error #:compile-warned-error #:compile-failed-error #:compile-warned-warning #:compile-failed-warning #:check-lisp-compile-results #:check-lisp-compile-warnings #:*uninteresting-conditions* #:*usual-uninteresting-conditions* #:*uninteresting-compiler-conditions* #:*uninteresting-loader-conditions* ;; Types #+sbcl #:sb-grovel-unknown-constant-condition ;; Functions & Macros #:get-optimization-settings #:proclaim-optimization-settings #:with-optimization-settings #:call-with-muffled-compiler-conditions #:with-muffled-compiler-conditions #:call-with-muffled-loader-conditions #:with-muffled-loader-conditions #:reify-simple-sexp #:unreify-simple-sexp #:reify-deferred-warnings #:unreify-deferred-warnings #:reset-deferred-warnings #:save-deferred-warnings #:check-deferred-warnings #:with-saved-deferred-warnings #:warnings-file-p #:warnings-file-type #:*warnings-file-type* #:enable-deferred-warnings-check #:disable-deferred-warnings-check #:current-lisp-file-pathname #:load-pathname #:lispize-pathname #:compile-file-type #:call-around-hook #:compile-file* #:compile-file-pathname* #:*compile-check* #:load* #:load-from-string #:combine-fasls) (:intern #:defaults #:failure-p #:warnings-p #:s #:y #:body)) (in-package :uiop/lisp-build) (with-upgradability () (defvar *compile-file-warnings-behaviour* (or #+clisp :ignore :warn) "How should ASDF react if it encounters a warning when compiling a file? Valid values are :error, :warn, and :ignore.") (defvar *compile-file-failure-behaviour* (or #+(or mkcl sbcl) :error #+clisp :ignore :warn) "How should ASDF react if it encounters a failure (per the ANSI spec of COMPILE-FILE) when compiling a file, which includes any non-style-warning warning. Valid values are :error, :warn, and :ignore. Note that ASDF ALWAYS raises an error if it fails to create an output file when compiling.") (defvar *base-build-directory* nil "When set to a non-null value, it should be an absolute directory pathname, which will serve as the *DEFAULT-PATHNAME-DEFAULTS* around a COMPILE-FILE, what more while the input-file is shortened if possible to ENOUGH-PATHNAME relative to it. This can help you produce more deterministic output for FASLs.")) ;;; Optimization settings (with-upgradability () (defvar *optimization-settings* nil "Optimization settings to be used by PROCLAIM-OPTIMIZATION-SETTINGS") (defvar *previous-optimization-settings* nil "Optimization settings saved by PROCLAIM-OPTIMIZATION-SETTINGS") (defparameter +optimization-variables+ ;; TODO: allegro genera corman mcl (or #+(or abcl xcl) '(system::*speed* system::*space* system::*safety* system::*debug*) #+clisp '() ;; system::*optimize* is a constant hash-table! (with non-constant contents) #+clozure '(ccl::*nx-speed* ccl::*nx-space* ccl::*nx-safety* ccl::*nx-debug* ccl::*nx-cspeed*) #+(or cmucl scl) '(c::*default-cookie*) #+clasp nil #+ecl (unless (use-ecl-byte-compiler-p) '(c::*speed* c::*space* c::*safety* c::*debug*)) #+gcl '(compiler::*speed* compiler::*space* compiler::*compiler-new-safety* compiler::*debug*) #+lispworks '(compiler::*optimization-level*) #+mkcl '(si::*speed* si::*space* si::*safety* si::*debug*) #+sbcl '(sb-c::*policy*))) (defun get-optimization-settings () "Get current compiler optimization settings, ready to PROCLAIM again" #-(or abcl allegro clasp clisp clozure cmucl ecl lispworks mkcl sbcl scl xcl) (warn "~S does not support ~S. Please help me fix that." 'get-optimization-settings (implementation-type)) #+clasp (cleavir-env:optimize (cleavir-env:optimize-info CLASP-CLEAVIR:*CLASP-ENV*)) #+(or abcl allegro clisp clozure cmucl ecl lispworks mkcl sbcl scl xcl) (let ((settings '(speed space safety debug compilation-speed #+(or cmucl scl) c::brevity))) #.`(loop #+(or allegro clozure) ,@'(:with info = #+allegro (sys:declaration-information 'optimize) #+clozure (ccl:declaration-information 'optimize nil)) :for x :in settings ,@(or #+(or abcl clasp ecl gcl mkcl xcl) '(:for v :in +optimization-variables+)) :for y = (or #+(or allegro clozure) (second (assoc x info)) ; normalize order #+clisp (gethash x system::*optimize* 1) #+(or abcl ecl mkcl xcl) (symbol-value v) #+(or cmucl scl) (slot-value c::*default-cookie* (case x (compilation-speed 'c::cspeed) (otherwise x))) #+lispworks (slot-value compiler::*optimization-level* x) #+sbcl (sb-c::policy-quality sb-c::*policy* x)) :when y :collect (list x y)))) (defun proclaim-optimization-settings () "Proclaim the optimization settings in *OPTIMIZATION-SETTINGS*" (proclaim `(optimize ,@*optimization-settings*)) (let ((settings (get-optimization-settings))) (unless (equal *previous-optimization-settings* settings) (setf *previous-optimization-settings* settings)))) (defmacro with-optimization-settings ((&optional (settings *optimization-settings*)) &body body) #+(or allegro clasp clisp) (let ((previous-settings (gensym "PREVIOUS-SETTINGS")) (reset-settings (gensym "RESET-SETTINGS"))) `(let* ((,previous-settings (get-optimization-settings)) (,reset-settings #+clasp (reverse ,previous-settings) #-clasp ,previous-settings)) ,@(when settings `((proclaim `(optimize ,@,settings)))) (unwind-protect (progn ,@body) (proclaim `(optimize ,@,reset-settings))))) #-(or allegro clasp clisp) `(let ,(loop :for v :in +optimization-variables+ :collect `(,v ,v)) ,@(when settings `((proclaim `(optimize ,@,settings)))) ,@body))) ;;; Condition control (with-upgradability () #+sbcl (progn (defun sb-grovel-unknown-constant-condition-p (c) "Detect SB-GROVEL unknown-constant conditions on older versions of SBCL" (ignore-errors (and (typep c 'sb-int:simple-style-warning) (string-enclosed-p "Couldn't grovel for " (simple-condition-format-control c) " (unknown to the C compiler).")))) (deftype sb-grovel-unknown-constant-condition () '(and style-warning (satisfies sb-grovel-unknown-constant-condition-p)))) (defvar *usual-uninteresting-conditions* (append ;;#+clozure '(ccl:compiler-warning) #+cmucl '("Deleting unreachable code.") #+lispworks '("~S being redefined in ~A (previously in ~A)." "~S defined more than once in ~A.") ;; lispworks gets confused by eval-when. #+sbcl '(sb-c::simple-compiler-note "&OPTIONAL and &KEY found in the same lambda list: ~S" sb-kernel:undefined-alien-style-warning sb-grovel-unknown-constant-condition ; defined above. sb-ext:implicit-generic-function-warning ;; Controversial. sb-int:package-at-variance sb-kernel:uninteresting-redefinition ;; BEWARE: the below four are controversial to include here. sb-kernel:redefinition-with-defun sb-kernel:redefinition-with-defgeneric sb-kernel:redefinition-with-defmethod sb-kernel::redefinition-with-defmacro) ; not exported by old SBCLs #+sbcl (let ((condition (find-symbol* '#:lexical-environment-too-complex :sb-kernel nil))) (when condition (list condition))) '("No generic function ~S present when encountering macroexpansion of defmethod. Assuming it will be an instance of standard-generic-function.")) ;; from closer2mop "A suggested value to which to set or bind *uninteresting-conditions*.") (defvar *uninteresting-conditions* '() "Conditions that may be skipped while compiling or loading Lisp code.") (defvar *uninteresting-compiler-conditions* '() "Additional conditions that may be skipped while compiling Lisp code.") (defvar *uninteresting-loader-conditions* (append '("Overwriting already existing readtable ~S." ;; from named-readtables #(#:finalizers-off-warning :asdf-finalizers)) ;; from asdf-finalizers #+clisp '(clos::simple-gf-replacing-method-warning)) "Additional conditions that may be skipped while loading Lisp code.")) ;;;; ----- Filtering conditions while building ----- (with-upgradability () (defun call-with-muffled-compiler-conditions (thunk) "Call given THUNK in a context where uninteresting conditions and compiler conditions are muffled" (call-with-muffled-conditions thunk (append *uninteresting-conditions* *uninteresting-compiler-conditions*))) (defmacro with-muffled-compiler-conditions ((&optional) &body body) "Trivial syntax for CALL-WITH-MUFFLED-COMPILER-CONDITIONS" `(call-with-muffled-compiler-conditions #'(lambda () ,@body))) (defun call-with-muffled-loader-conditions (thunk) "Call given THUNK in a context where uninteresting conditions and loader conditions are muffled" (call-with-muffled-conditions thunk (append *uninteresting-conditions* *uninteresting-loader-conditions*))) (defmacro with-muffled-loader-conditions ((&optional) &body body) "Trivial syntax for CALL-WITH-MUFFLED-LOADER-CONDITIONS" `(call-with-muffled-loader-conditions #'(lambda () ,@body)))) ;;;; Handle warnings and failures (with-upgradability () (define-condition compile-condition (condition) ((context-format :initform nil :reader compile-condition-context-format :initarg :context-format) (context-arguments :initform nil :reader compile-condition-context-arguments :initarg :context-arguments) (description :initform nil :reader compile-condition-description :initarg :description)) (:report (lambda (c s) (format s (compatfmt "~@<~A~@[ while ~?~]~@:>") (or (compile-condition-description c) (type-of c)) (compile-condition-context-format c) (compile-condition-context-arguments c))))) (define-condition compile-file-error (compile-condition error) ()) (define-condition compile-warned-warning (compile-condition warning) ()) (define-condition compile-warned-error (compile-condition error) ()) (define-condition compile-failed-warning (compile-condition warning) ()) (define-condition compile-failed-error (compile-condition error) ()) (defun check-lisp-compile-warnings (warnings-p failure-p &optional context-format context-arguments) "Given the warnings or failures as resulted from COMPILE-FILE or checking deferred warnings, raise an error or warning as appropriate" (when failure-p (case *compile-file-failure-behaviour* (:warn (warn 'compile-failed-warning :description "Lisp compilation failed" :context-format context-format :context-arguments context-arguments)) (:error (error 'compile-failed-error :description "Lisp compilation failed" :context-format context-format :context-arguments context-arguments)) (:ignore nil))) (when warnings-p (case *compile-file-warnings-behaviour* (:warn (warn 'compile-warned-warning :description "Lisp compilation had style-warnings" :context-format context-format :context-arguments context-arguments)) (:error (error 'compile-warned-error :description "Lisp compilation had style-warnings" :context-format context-format :context-arguments context-arguments)) (:ignore nil)))) (defun check-lisp-compile-results (output warnings-p failure-p &optional context-format context-arguments) "Given the results of COMPILE-FILE, raise an error or warning as appropriate" (unless output (error 'compile-file-error :context-format context-format :context-arguments context-arguments)) (check-lisp-compile-warnings warnings-p failure-p context-format context-arguments))) ;;;; Deferred-warnings treatment, originally implemented by Douglas Katzman. ;;; ;;; To support an implementation, three functions must be implemented: ;;; reify-deferred-warnings unreify-deferred-warnings reset-deferred-warnings ;;; See their respective docstrings. (with-upgradability () (defun reify-simple-sexp (sexp) "Given a simple SEXP, return a representation of it as a portable SEXP. Simple means made of symbols, numbers, characters, simple-strings, pathnames, cons cells." (etypecase sexp (symbol (reify-symbol sexp)) ((or number character simple-string pathname) sexp) (cons (cons (reify-simple-sexp (car sexp)) (reify-simple-sexp (cdr sexp)))) (simple-vector (vector (mapcar 'reify-simple-sexp (coerce sexp 'list)))))) (defun unreify-simple-sexp (sexp) "Given the portable output of REIFY-SIMPLE-SEXP, return the simple SEXP it represents" (etypecase sexp ((or symbol number character simple-string pathname) sexp) (cons (cons (unreify-simple-sexp (car sexp)) (unreify-simple-sexp (cdr sexp)))) ((simple-vector 2) (unreify-symbol sexp)) ((simple-vector 1) (coerce (mapcar 'unreify-simple-sexp (aref sexp 0)) 'vector)))) #+clozure (progn (defun reify-source-note (source-note) (when source-note (with-accessors ((source ccl::source-note-source) (filename ccl:source-note-filename) (start-pos ccl:source-note-start-pos) (end-pos ccl:source-note-end-pos)) source-note (declare (ignorable source)) (list :filename filename :start-pos start-pos :end-pos end-pos #|:source (reify-source-note source)|#)))) (defun unreify-source-note (source-note) (when source-note (destructuring-bind (&key filename start-pos end-pos source) source-note (ccl::make-source-note :filename filename :start-pos start-pos :end-pos end-pos :source (unreify-source-note source))))) (defun unsymbolify-function-name (name) (if-let (setfed (gethash name ccl::%setf-function-name-inverses%)) `(setf ,setfed) name)) (defun symbolify-function-name (name) (if (and (consp name) (eq (first name) 'setf)) (let ((setfed (second name))) (gethash setfed ccl::%setf-function-names%)) name)) (defun reify-function-name (function-name) (let ((name (or (first function-name) ;; defun: extract the name (let ((sec (second function-name))) (or (and (atom sec) sec) ; scoped method: drop scope (first sec)))))) ; method: keep gf name, drop method specializers (list name))) (defun unreify-function-name (function-name) function-name) (defun nullify-non-literals (sexp) (typecase sexp ((or number character simple-string symbol pathname) sexp) (cons (cons (nullify-non-literals (car sexp)) (nullify-non-literals (cdr sexp)))) (t nil))) (defun reify-deferred-warning (deferred-warning) (with-accessors ((warning-type ccl::compiler-warning-warning-type) (args ccl::compiler-warning-args) (source-note ccl:compiler-warning-source-note) (function-name ccl:compiler-warning-function-name)) deferred-warning (list :warning-type warning-type :function-name (reify-function-name function-name) :source-note (reify-source-note source-note) :args (destructuring-bind (fun &rest more) args (cons (unsymbolify-function-name fun) (nullify-non-literals more)))))) (defun unreify-deferred-warning (reified-deferred-warning) (destructuring-bind (&key warning-type function-name source-note args) reified-deferred-warning (make-condition (or (cdr (ccl::assq warning-type ccl::*compiler-whining-conditions*)) 'ccl::compiler-warning) :function-name (unreify-function-name function-name) :source-note (unreify-source-note source-note) :warning-type warning-type :args (destructuring-bind (fun . more) args (cons (symbolify-function-name fun) more)))))) #+(or cmucl scl) (defun reify-undefined-warning (warning) ;; Extracting undefined-warnings from the compilation-unit ;; To be passed through the above reify/unreify link, it must be a "simple-sexp" (list* (c::undefined-warning-kind warning) (c::undefined-warning-name warning) (c::undefined-warning-count warning) (mapcar #'(lambda (frob) ;; the lexenv slot can be ignored for reporting purposes `(:enclosing-source ,(c::compiler-error-context-enclosing-source frob) :source ,(c::compiler-error-context-source frob) :original-source ,(c::compiler-error-context-original-source frob) :context ,(c::compiler-error-context-context frob) :file-name ,(c::compiler-error-context-file-name frob) ; a pathname :file-position ,(c::compiler-error-context-file-position frob) ; an integer :original-source-path ,(c::compiler-error-context-original-source-path frob))) (c::undefined-warning-warnings warning)))) #+sbcl (defun reify-undefined-warning (warning) ;; Extracting undefined-warnings from the compilation-unit ;; To be passed through the above reify/unreify link, it must be a "simple-sexp" (list* (sb-c::undefined-warning-kind warning) (sb-c::undefined-warning-name warning) (sb-c::undefined-warning-count warning) ;; the COMPILER-ERROR-CONTEXT struct has changed in SBCL, which means how we ;; handle deferred warnings must change... TODO: when enough time has ;; gone by, just assume all versions of SBCL are adequately ;; up-to-date, and cut this material.[2018/05/30:rpg] (mapcar #'(lambda (frob) ;; the lexenv slot can be ignored for reporting purposes `( #- #.(uiop/utility:symbol-test-to-feature-expression '#:compiler-error-context-%source '#:sb-c) ,@`(:enclosing-source ,(sb-c::compiler-error-context-enclosing-source frob) :source ,(sb-c::compiler-error-context-source frob) :original-source ,(sb-c::compiler-error-context-original-source frob)) #+ #.(uiop/utility:symbol-test-to-feature-expression '#:compiler-error-context-%source '#:sb-c) ,@ `(:%enclosing-source ,(sb-c::compiler-error-context-enclosing-source frob) :%source ,(sb-c::compiler-error-context-source frob) :original-form ,(sb-c::compiler-error-context-original-form frob)) :context ,(sb-c::compiler-error-context-context frob) :file-name ,(sb-c::compiler-error-context-file-name frob) ; a pathname :file-position ,(sb-c::compiler-error-context-file-position frob) ; an integer :original-source-path ,(sb-c::compiler-error-context-original-source-path frob))) (sb-c::undefined-warning-warnings warning)))) (defun reify-deferred-warnings () "return a portable S-expression, portably readable and writeable in any Common Lisp implementation using READ within a WITH-SAFE-IO-SYNTAX, that represents the warnings currently deferred by WITH-COMPILATION-UNIT. One of three functions required for deferred-warnings support in ASDF." #+allegro (list :functions-defined excl::.functions-defined. :functions-called excl::.functions-called.) #+clozure (mapcar 'reify-deferred-warning (if-let (dw ccl::*outstanding-deferred-warnings*) (let ((mdw (ccl::ensure-merged-deferred-warnings dw))) (ccl::deferred-warnings.warnings mdw)))) #+(or cmucl scl) (when lisp::*in-compilation-unit* ;; Try to send nothing through the pipe if nothing needs to be accumulated `(,@(when c::*undefined-warnings* `((c::*undefined-warnings* ,@(mapcar #'reify-undefined-warning c::*undefined-warnings*)))) ,@(loop :for what :in '(c::*compiler-error-count* c::*compiler-warning-count* c::*compiler-note-count*) :for value = (symbol-value what) :when (plusp value) :collect `(,what . ,value)))) #+sbcl (when sb-c::*in-compilation-unit* ;; Try to send nothing through the pipe if nothing needs to be accumulated `(,@(when sb-c::*undefined-warnings* `((sb-c::*undefined-warnings* ,@(mapcar #'reify-undefined-warning sb-c::*undefined-warnings*)))) ,@(loop :for what :in '(sb-c::*aborted-compilation-unit-count* sb-c::*compiler-error-count* sb-c::*compiler-warning-count* sb-c::*compiler-style-warning-count* sb-c::*compiler-note-count*) :for value = (symbol-value what) :when (plusp value) :collect `(,what . ,value))))) (defun unreify-deferred-warnings (reified-deferred-warnings) "given a S-expression created by REIFY-DEFERRED-WARNINGS, reinstantiate the corresponding deferred warnings as to be handled at the end of the current WITH-COMPILATION-UNIT. Handle any warning that has been resolved already, such as an undefined function that has been defined since. One of three functions required for deferred-warnings support in ASDF." (declare (ignorable reified-deferred-warnings)) #+allegro (destructuring-bind (&key functions-defined functions-called) reified-deferred-warnings (setf excl::.functions-defined. (append functions-defined excl::.functions-defined.) excl::.functions-called. (append functions-called excl::.functions-called.))) #+clozure (let ((dw (or ccl::*outstanding-deferred-warnings* (setf ccl::*outstanding-deferred-warnings* (ccl::%defer-warnings t))))) (appendf (ccl::deferred-warnings.warnings dw) (mapcar 'unreify-deferred-warning reified-deferred-warnings))) #+(or cmucl scl) (dolist (item reified-deferred-warnings) ;; Each item is (symbol . adjustment) where the adjustment depends on the symbol. ;; For *undefined-warnings*, the adjustment is a list of initargs. ;; For everything else, it's an integer. (destructuring-bind (symbol . adjustment) item (case symbol ((c::*undefined-warnings*) (setf c::*undefined-warnings* (nconc (mapcan #'(lambda (stuff) (destructuring-bind (kind name count . rest) stuff (unless (case kind (:function (fboundp name))) (list (c::make-undefined-warning :name name :kind kind :count count :warnings (mapcar #'(lambda (x) (apply #'c::make-compiler-error-context x)) rest)))))) adjustment) c::*undefined-warnings*))) (otherwise (set symbol (+ (symbol-value symbol) adjustment)))))) #+sbcl (dolist (item reified-deferred-warnings) ;; Each item is (symbol . adjustment) where the adjustment depends on the symbol. ;; For *undefined-warnings*, the adjustment is a list of initargs. ;; For everything else, it's an integer. (destructuring-bind (symbol . adjustment) item (case symbol ((sb-c::*undefined-warnings*) (setf sb-c::*undefined-warnings* (nconc (mapcan #'(lambda (stuff) (destructuring-bind (kind name count . rest) stuff (unless (case kind (:function (fboundp name))) (list (sb-c::make-undefined-warning :name name :kind kind :count count :warnings (mapcar #'(lambda (x) (apply #'sb-c::make-compiler-error-context x)) rest)))))) adjustment) sb-c::*undefined-warnings*))) (otherwise (set symbol (+ (symbol-value symbol) adjustment))))))) (defun reset-deferred-warnings () "Reset the set of deferred warnings to be handled at the end of the current WITH-COMPILATION-UNIT. One of three functions required for deferred-warnings support in ASDF." #+allegro (setf excl::.functions-defined. nil excl::.functions-called. nil) #+clozure (if-let (dw ccl::*outstanding-deferred-warnings*) (let ((mdw (ccl::ensure-merged-deferred-warnings dw))) (setf (ccl::deferred-warnings.warnings mdw) nil))) #+(or cmucl scl) (when lisp::*in-compilation-unit* (setf c::*undefined-warnings* nil c::*compiler-error-count* 0 c::*compiler-warning-count* 0 c::*compiler-note-count* 0)) #+sbcl (when sb-c::*in-compilation-unit* (setf sb-c::*undefined-warnings* nil sb-c::*aborted-compilation-unit-count* 0 sb-c::*compiler-error-count* 0 sb-c::*compiler-warning-count* 0 sb-c::*compiler-style-warning-count* 0 sb-c::*compiler-note-count* 0))) (defun save-deferred-warnings (warnings-file) "Save forward reference conditions so they may be issued at a latter time, possibly in a different process." (with-open-file (s warnings-file :direction :output :if-exists :supersede :element-type *default-stream-element-type* :external-format *utf-8-external-format*) (with-safe-io-syntax () (let ((*read-eval* t)) (write (reify-deferred-warnings) :stream s :pretty t :readably t)) (terpri s)))) (defun warnings-file-type (&optional implementation-type) "The pathname type for warnings files on given IMPLEMENTATION-TYPE, where NIL designates the current one" (case (or implementation-type *implementation-type*) ((:acl :allegro) "allegro-warnings") ;;((:clisp) "clisp-warnings") ((:cmu :cmucl) "cmucl-warnings") ((:sbcl) "sbcl-warnings") ((:clozure :ccl) "ccl-warnings") ((:scl) "scl-warnings"))) (defvar *warnings-file-type* nil "Pathname type for warnings files, or NIL if disabled") (defun enable-deferred-warnings-check () "Enable the saving of deferred warnings" (setf *warnings-file-type* (warnings-file-type))) (defun disable-deferred-warnings-check () "Disable the saving of deferred warnings" (setf *warnings-file-type* nil)) (defun warnings-file-p (file &optional implementation-type) "Is FILE a saved warnings file for the given IMPLEMENTATION-TYPE? If that given type is NIL, use the currently configured *WARNINGS-FILE-TYPE* instead." (if-let (type (if implementation-type (warnings-file-type implementation-type) *warnings-file-type*)) (equal (pathname-type file) type))) (defun check-deferred-warnings (files &optional context-format context-arguments) "Given a list of FILES containing deferred warnings saved by CALL-WITH-SAVED-DEFERRED-WARNINGS, re-intern and raise any warnings that are still meaningful." (let ((file-errors nil) (failure-p nil) (warnings-p nil)) (handler-bind ((warning #'(lambda (c) (setf warnings-p t) (unless (typep c 'style-warning) (setf failure-p t))))) (with-compilation-unit (:override t) (reset-deferred-warnings) (dolist (file files) (unreify-deferred-warnings (handler-case (with-safe-io-syntax () (let ((*read-eval* t)) (read-file-form file))) (error (c) ;;(delete-file-if-exists file) ;; deleting forces rebuild but prevents debugging (push c file-errors) nil)))))) (dolist (error file-errors) (error error)) (check-lisp-compile-warnings (or failure-p warnings-p) failure-p context-format context-arguments))) #| Mini-guide to adding support for deferred warnings on an implementation. First, look at what such a warning looks like: (describe (handler-case (and (eval '(lambda () (some-undefined-function))) nil) (t (c) c))) Then you can grep for the condition type in your compiler sources and see how to catch those that have been deferred, and/or read, clear and restore the deferred list. Also look at (macroexpand-1 '(with-compilation-unit () foo)) |# (defun call-with-saved-deferred-warnings (thunk warnings-file &key source-namestring) "If WARNINGS-FILE is not nil, record the deferred-warnings around a call to THUNK and save those warnings to the given file for latter use, possibly in a different process. Otherwise just call THUNK." (declare (ignorable source-namestring)) (if warnings-file (with-compilation-unit (:override t #+sbcl :source-namestring #+sbcl source-namestring) (unwind-protect (let (#+sbcl (sb-c::*undefined-warnings* nil)) (multiple-value-prog1 (funcall thunk) (save-deferred-warnings warnings-file))) (reset-deferred-warnings))) (funcall thunk))) (defmacro with-saved-deferred-warnings ((warnings-file &key source-namestring) &body body) "Trivial syntax for CALL-WITH-SAVED-DEFERRED-WARNINGS" `(call-with-saved-deferred-warnings #'(lambda () ,@body) ,warnings-file :source-namestring ,source-namestring))) ;;; from ASDF (with-upgradability () (defun current-lisp-file-pathname () "Portably return the PATHNAME of the current Lisp source file being compiled or loaded" (or *compile-file-pathname* *load-pathname*)) (defun load-pathname () "Portably return the LOAD-PATHNAME of the current source file or fasl. May return a relative pathname." *load-pathname*) ;; magic no longer needed for GCL. (defun lispize-pathname (input-file) "From a INPUT-FILE pathname, return a corresponding .lisp source pathname" (make-pathname :type "lisp" :defaults input-file)) (defun compile-file-type (&rest keys) "pathname TYPE for lisp FASt Loading files" (declare (ignorable keys)) #-(or clasp ecl mkcl) (load-time-value (pathname-type (compile-file-pathname "foo.lisp"))) #+(or clasp ecl mkcl) (pathname-type (apply 'compile-file-pathname "foo" keys))) (defun call-around-hook (hook function) "Call a HOOK around the execution of FUNCTION" (call-function (or hook 'funcall) function)) (defun compile-file-pathname* (input-file &rest keys &key output-file &allow-other-keys) "Variant of COMPILE-FILE-PATHNAME that works well with COMPILE-FILE*" (let* ((keys (remove-plist-keys `(#+(or (and allegro (not (version>= 8 2)))) :external-format ,@(unless output-file '(:output-file))) keys))) (if (absolute-pathname-p output-file) ;; what cfp should be doing, w/ mp* instead of mp (let* ((type (pathname-type (apply 'compile-file-type keys))) (defaults (make-pathname :type type :defaults (merge-pathnames* input-file)))) (merge-pathnames* output-file defaults)) (funcall *output-translation-function* (apply 'compile-file-pathname input-file keys))))) (defvar *compile-check* nil "A hook for user-defined compile-time invariants") (defun compile-file* (input-file &rest keys &key (compile-check *compile-check*) output-file warnings-file #+clisp lib-file #+(or clasp ecl mkcl) object-file #+sbcl emit-cfasl &allow-other-keys) "This function provides a portable wrapper around COMPILE-FILE. It ensures that the OUTPUT-FILE value is only returned and the file only actually created if the compilation was successful, even though your implementation may not do that. It also checks an optional user-provided consistency function COMPILE-CHECK to determine success; it will call this function if not NIL at the end of the compilation with the arguments sent to COMPILE-FILE*, except with :OUTPUT-FILE TMP-FILE where TMP-FILE is the name of a temporary output-file. It also checks two flags (with legacy british spelling from ASDF1), *COMPILE-FILE-FAILURE-BEHAVIOUR* and *COMPILE-FILE-WARNINGS-BEHAVIOUR* with appropriate implementation-dependent defaults, and if a failure (respectively warnings) are reported by COMPILE-FILE, it will consider that an error unless the respective behaviour flag is one of :SUCCESS :WARN :IGNORE. If WARNINGS-FILE is defined, deferred warnings are saved to that file. On ECL or MKCL, it creates both the linkable object and loadable fasl files. On implementations that erroneously do not recognize standard keyword arguments, it will filter them appropriately." #+(or clasp ecl) (when (and object-file (equal (compile-file-type) (pathname object-file))) (format t "Whoa, some funky ASDF upgrade switched ~S calling convention for ~S and ~S~%" 'compile-file* output-file object-file) (rotatef output-file object-file)) (let* ((keywords (remove-plist-keys `(:output-file :compile-check :warnings-file #+clisp :lib-file #+(or clasp ecl mkcl) :object-file) keys)) (output-file (or output-file (apply 'compile-file-pathname* input-file :output-file output-file keywords))) (physical-output-file (physicalize-pathname output-file)) #+(or clasp ecl) (object-file (unless (use-ecl-byte-compiler-p) (or object-file #+ecl (compile-file-pathname output-file :type :object) #+clasp (compile-file-pathname output-file :output-type :object)))) #+mkcl (object-file (or object-file (compile-file-pathname output-file :fasl-p nil))) (tmp-file (tmpize-pathname physical-output-file)) #+clasp (tmp-object-file (compile-file-pathname tmp-file :output-type :object)) #+sbcl (cfasl-file (etypecase emit-cfasl (null nil) ((eql t) (make-pathname :type "cfasl" :defaults physical-output-file)) (string (parse-namestring emit-cfasl)) (pathname emit-cfasl))) #+sbcl (tmp-cfasl (when cfasl-file (make-pathname :type "cfasl" :defaults tmp-file))) #+clisp (tmp-lib (make-pathname :type "lib" :defaults tmp-file))) (multiple-value-bind (output-truename warnings-p failure-p) (with-enough-pathname (input-file :defaults *base-build-directory*) (with-saved-deferred-warnings (warnings-file :source-namestring (namestring input-file)) (with-muffled-compiler-conditions () (or #-(or clasp ecl mkcl) (let (#+genera (si:*common-lisp-syntax-is-ansi-common-lisp* t)) (apply 'compile-file input-file :output-file tmp-file #+sbcl (if emit-cfasl (list* :emit-cfasl tmp-cfasl keywords) keywords) #-sbcl keywords)) #+ecl (apply 'compile-file input-file :output-file (if object-file (list* object-file :system-p t keywords) (list* tmp-file keywords))) #+clasp (apply 'compile-file input-file :output-file (if object-file (list* tmp-object-file :output-type :object #|:system-p t|# keywords) (list* tmp-file keywords))) #+mkcl (apply 'compile-file input-file :output-file object-file :fasl-p nil keywords))))) (cond ((and output-truename (flet ((check-flag (flag behaviour) (or (not flag) (member behaviour '(:success :warn :ignore))))) (and (check-flag failure-p *compile-file-failure-behaviour*) (check-flag warnings-p *compile-file-warnings-behaviour*))) (progn #+(or clasp ecl mkcl) (when (and #+(or clasp ecl) object-file) (setf output-truename (compiler::build-fasl tmp-file #+(or clasp ecl) :lisp-files #+mkcl :lisp-object-files (list #+clasp tmp-object-file #-clasp object-file)))) (or (not compile-check) (apply compile-check input-file :output-file output-truename keywords)))) (delete-file-if-exists physical-output-file) (when output-truename ;; see CLISP bug 677 #+clisp (progn (setf tmp-lib (make-pathname :type "lib" :defaults output-truename)) (unless lib-file (setf lib-file (make-pathname :type "lib" :defaults physical-output-file))) (rename-file-overwriting-target tmp-lib lib-file)) #+sbcl (when cfasl-file (rename-file-overwriting-target tmp-cfasl cfasl-file)) #+clasp (progn ;;; the following 4 rename-file-overwriting-target better be atomic, but we can't implement this right now #+:target-os-darwin (let ((temp-dwarf (pathname (strcat (namestring output-truename) ".dwarf"))) (target-dwarf (pathname (strcat (namestring physical-output-file) ".dwarf")))) (when (probe-file temp-dwarf) (rename-file-overwriting-target temp-dwarf target-dwarf))) ;;; need to rename the bc or ll file as well or test-bundle.script fails ;;; They might not exist with parallel compilation (let ((bitcode-src (compile-file-pathname tmp-file :output-type :bitcode)) (bitcode-target (compile-file-pathname physical-output-file :output-type :bitcode))) (when (probe-file bitcode-src) (rename-file-overwriting-target bitcode-src bitcode-target))) (rename-file-overwriting-target tmp-object-file object-file)) (rename-file-overwriting-target output-truename physical-output-file) (setf output-truename (truename physical-output-file))) #+clasp (delete-file-if-exists tmp-file) #+clisp (progn (delete-file-if-exists tmp-file) ;; this one works around clisp BUG 677 (delete-file-if-exists tmp-lib))) ;; this one is "normal" defensive cleanup (t ;; error or failed check (delete-file-if-exists output-truename) #+clisp (delete-file-if-exists tmp-lib) #+sbcl (delete-file-if-exists tmp-cfasl) (setf output-truename nil))) (values output-truename warnings-p failure-p)))) (defun load* (x &rest keys &key &allow-other-keys) "Portable wrapper around LOAD that properly handles loading from a stream." (with-muffled-loader-conditions () (let (#+genera (si:*common-lisp-syntax-is-ansi-common-lisp* t)) (etypecase x ((or pathname string #-(or allegro clozure genera) stream #+clozure file-stream) (apply 'load x keys)) ;; Genera can't load from a string-input-stream ;; ClozureCL 1.6 can only load from file input stream ;; Allegro 5, I don't remember but it must have been broken when I tested. #+(or allegro clozure genera) (stream ;; make do this way (let ((*package* *package*) (*readtable* *readtable*) (*load-pathname* nil) (*load-truename* nil)) (eval-input x))))))) (defun load-from-string (string) "Portably read and evaluate forms from a STRING." (with-input-from-string (s string) (load* s)))) ;;; Links FASLs together (with-upgradability () (defun combine-fasls (inputs output) "Combine a list of FASLs INPUTS into a single FASL OUTPUT" #-(or abcl allegro clisp clozure cmucl lispworks sbcl scl xcl) (not-implemented-error 'combine-fasls "~%inputs: ~S~%output: ~S" inputs output) #+abcl (funcall 'sys::concatenate-fasls inputs output) ; requires ABCL 1.2.0 #+(or allegro clisp cmucl sbcl scl xcl) (concatenate-files inputs output) #+clozure (ccl:fasl-concatenate output inputs :if-exists :supersede) #+lispworks (let (fasls) (unwind-protect (progn (loop :for i :in inputs :for n :from 1 :for f = (add-pathname-suffix output (format nil "-FASL~D" n)) :do (copy-file i f) (push f fasls)) (ignore-errors (lispworks:delete-system :fasls-to-concatenate)) (eval `(scm:defsystem :fasls-to-concatenate (:default-pathname ,(pathname-directory-pathname output)) :members ,(loop :for f :in (reverse fasls) :collect `(,(namestring f) :load-only t)))) (scm:concatenate-system output :fasls-to-concatenate :force t)) (loop :for f :in fasls :do (ignore-errors (delete-file f))) (ignore-errors (lispworks:delete-system :fasls-to-concatenate)))))) ;;;; ------------------------------------------------------------------------- ;;;; launch-program - semi-portably spawn asynchronous subprocesses (uiop/package:define-package :uiop/launch-program (:use :uiop/common-lisp :uiop/package :uiop/utility :uiop/pathname :uiop/os :uiop/filesystem :uiop/stream :uiop/version) (:export ;;; Escaping the command invocation madness #:easy-sh-character-p #:escape-sh-token #:escape-sh-command #:escape-windows-token #:escape-windows-command #:escape-shell-token #:escape-shell-command #:escape-token #:escape-command ;;; launch-program #:launch-program #:close-streams #:process-alive-p #:terminate-process #:wait-process #:process-info #:process-info-error-output #:process-info-input #:process-info-output #:process-info-pid)) (in-package :uiop/launch-program) ;;;; ----- Escaping strings for the shell ----- (with-upgradability () (defun requires-escaping-p (token &key good-chars bad-chars) "Does this token require escaping, given the specification of either good chars that don't need escaping or bad chars that do need escaping, as either a recognizing function or a sequence of characters." (some (cond ((and good-chars bad-chars) (parameter-error "~S: only one of good-chars and bad-chars can be provided" 'requires-escaping-p)) ((typep good-chars 'function) (complement good-chars)) ((typep bad-chars 'function) bad-chars) ((and good-chars (typep good-chars 'sequence)) #'(lambda (c) (not (find c good-chars)))) ((and bad-chars (typep bad-chars 'sequence)) #'(lambda (c) (find c bad-chars))) (t (parameter-error "~S: no good-char criterion" 'requires-escaping-p))) token)) (defun escape-token (token &key stream quote good-chars bad-chars escaper) "Call the ESCAPER function on TOKEN string if it needs escaping as per REQUIRES-ESCAPING-P using GOOD-CHARS and BAD-CHARS, otherwise output TOKEN, using STREAM as output (or returning result as a string if NIL)" (if (requires-escaping-p token :good-chars good-chars :bad-chars bad-chars) (with-output (stream) (apply escaper token stream (when quote `(:quote ,quote)))) (output-string token stream))) (defun escape-windows-token-within-double-quotes (x &optional s) "Escape a string token X within double-quotes for use within a MS Windows command-line, outputing to S." (labels ((issue (c) (princ c s)) (issue-backslash (n) (loop :repeat n :do (issue #\\)))) (loop :initially (issue #\") :finally (issue #\") :with l = (length x) :with i = 0 :for i+1 = (1+ i) :while (< i l) :do (case (char x i) ((#\") (issue-backslash 1) (issue #\") (setf i i+1)) ((#\\) (let* ((j (and (< i+1 l) (position-if-not #'(lambda (c) (eql c #\\)) x :start i+1))) (n (- (or j l) i))) (cond ((null j) (issue-backslash (* 2 n)) (setf i l)) ((and (< j l) (eql (char x j) #\")) (issue-backslash (1+ (* 2 n))) (issue #\") (setf i (1+ j))) (t (issue-backslash n) (setf i j))))) (otherwise (issue (char x i)) (setf i i+1)))))) (defun easy-windows-character-p (x) "Is X an \"easy\" character that does not require quoting by the shell?" (or (alphanumericp x) (find x "+-_.,@:/="))) (defun escape-windows-token (token &optional s) "Escape a string TOKEN within double-quotes if needed for use within a MS Windows command-line, outputing to S." (escape-token token :stream s :good-chars #'easy-windows-character-p :quote nil :escaper 'escape-windows-token-within-double-quotes)) (defun escape-sh-token-within-double-quotes (x s &key (quote t)) "Escape a string TOKEN within double-quotes for use within a POSIX Bourne shell, outputing to S; omit the outer double-quotes if key argument :QUOTE is NIL" (when quote (princ #\" s)) (loop :for c :across x :do (when (find c "$`\\\"") (princ #\\ s)) (princ c s)) (when quote (princ #\" s))) (defun easy-sh-character-p (x) "Is X an \"easy\" character that does not require quoting by the shell?" (or (alphanumericp x) (find x "+-_.,%@:/="))) (defun escape-sh-token (token &optional s) "Escape a string TOKEN within double-quotes if needed for use within a POSIX Bourne shell, outputing to S." (escape-token token :stream s :quote #\" :good-chars #'easy-sh-character-p :escaper 'escape-sh-token-within-double-quotes)) (defun escape-shell-token (token &optional s) "Escape a token for the current operating system shell" (os-cond ((os-unix-p) (escape-sh-token token s)) ((os-windows-p) (escape-windows-token token s)))) (defun escape-command (command &optional s (escaper 'escape-shell-token)) "Given a COMMAND as a list of tokens, return a string of the spaced, escaped tokens, using ESCAPER to escape." (etypecase command (string (output-string command s)) (list (with-output (s) (loop :for first = t :then nil :for token :in command :do (unless first (princ #\space s)) (funcall escaper token s)))))) (defun escape-windows-command (command &optional s) "Escape a list of command-line arguments into a string suitable for parsing by CommandLineToArgv in MS Windows" ;; http://msdn.microsoft.com/en-us/library/bb776391(v=vs.85).aspx ;; http://msdn.microsoft.com/en-us/library/17w5ykft(v=vs.85).aspx (escape-command command s 'escape-windows-token)) (defun escape-sh-command (command &optional s) "Escape a list of command-line arguments into a string suitable for parsing by /bin/sh in POSIX" (escape-command command s 'escape-sh-token)) (defun escape-shell-command (command &optional stream) "Escape a command for the current operating system's shell" (escape-command command stream 'escape-shell-token))) (with-upgradability () ;;; Internal helpers for run-program (defun %normalize-io-specifier (specifier &optional role) "Normalizes a portable I/O specifier for LAUNCH-PROGRAM into an implementation-dependent argument to pass to the internal RUN-PROGRAM" (declare (ignorable role)) (typecase specifier (null (or #+(or allegro lispworks) (null-device-pathname))) (string (parse-native-namestring specifier)) (pathname specifier) (stream specifier) ((eql :stream) :stream) ((eql :interactive) #+(or allegro lispworks) nil #+clisp :terminal #+(or abcl clozure cmucl ecl mkcl sbcl scl) t #-(or abcl clozure cmucl ecl mkcl sbcl scl allegro lispworks clisp) (not-implemented-error :interactive-output "On this lisp implementation, cannot interpret ~a value of ~a" specifier role)) ((eql :output) (cond ((eq role :error-output) #+(or abcl allegro clozure cmucl ecl lispworks mkcl sbcl scl) :output #-(or abcl allegro clozure cmucl ecl lispworks mkcl sbcl scl) (not-implemented-error :error-output-redirect "Can't send ~a to ~a on this lisp implementation." role specifier)) (t (parameter-error "~S IO specifier invalid for ~S" specifier role)))) ((eql t) #+ (or lispworks abcl) (not-implemented-error :interactive-output "On this lisp implementation, cannot interpret ~a value of ~a" specifier role) #- (or lispworks abcl) (cond ((eq role :error-output) *error-output*) ((eq role :output) #+lispworks *terminal-io* #-lispworks *standard-output*) ((eq role :input) *standard-input*))) (otherwise (parameter-error "Incorrect I/O specifier ~S for ~S" specifier role)))) (defun %interactivep (input output error-output) (member :interactive (list input output error-output))) (defun %signal-to-exit-code (signum) (+ 128 signum)) (defun %code-to-status (exit-code signal-code) (cond ((null exit-code) :running) ((null signal-code) (values :exited exit-code)) (t (values :signaled signal-code)))) #+mkcl (defun %mkcl-signal-to-number (signal) (require :mk-unix) (symbol-value (find-symbol signal :mk-unix))) (defclass process-info () (;; The process field is highly platform-, implementation-, and ;; even version-dependent. ;; Prior to LispWorks 7, the only information that ;; `sys:run-shell-command` with `:wait nil` was certain to return ;; is a PID (e.g. when all streams are nil), hence we stored it ;; and used `sys:pid-exit-status` to obtain an exit status ;; later. That is still what we do. ;; From LispWorks 7 on, if `sys:run-shell-command` does not ;; return a proper stream, we are instead given a dummy stream. ;; We can thus always store a stream and use ;; `sys:pipe-exit-status` to obtain an exit status later. ;; The advantage of dealing with streams instead of PID is the ;; availability of functions like `sys:pipe-kill-process`. (process :initform nil) (input-stream :initform nil) (output-stream :initform nil) (bidir-stream :initform nil) (error-output-stream :initform nil) ;; For backward-compatibility, to maintain the property (zerop ;; exit-code) <-> success, an exit in response to a signal is ;; encoded as 128+signum. (exit-code :initform nil) ;; If the platform allows it, distinguish exiting with a code ;; >128 from exiting in response to a signal by setting this code (signal-code :initform nil)) (:documentation "This class should be treated as opaque by programmers, except for the exported PROCESS-INFO-* functions. It should never be directly instantiated by MAKE-INSTANCE. Primarily, it is being made available to enable type-checking.")) ;;;--------------------------------------------------------------------------- ;;; The following two helper functions take care of handling the IF-EXISTS and ;;; IF-DOES-NOT-EXIST arguments for RUN-PROGRAM. In particular, they process the ;;; :ERROR, :APPEND, and :SUPERSEDE arguments *here*, allowing the master ;;; function to treat input and output files unconditionally for reading and ;;; writing. ;;;--------------------------------------------------------------------------- (defun %handle-if-exists (file if-exists) (when (or (stringp file) (pathnamep file)) (ecase if-exists ((:append :supersede :error) (with-open-file (dummy file :direction :output :if-exists if-exists) (declare (ignorable dummy))))))) (defun %handle-if-does-not-exist (file if-does-not-exist) (when (or (stringp file) (pathnamep file)) (ecase if-does-not-exist ((:create :error) (with-open-file (dummy file :direction :probe :if-does-not-exist if-does-not-exist) (declare (ignorable dummy))))))) (defun process-info-error-output (process-info) (slot-value process-info 'error-output-stream)) (defun process-info-input (process-info) (or (slot-value process-info 'bidir-stream) (slot-value process-info 'input-stream))) (defun process-info-output (process-info) (or (slot-value process-info 'bidir-stream) (slot-value process-info 'output-stream))) (defun process-info-pid (process-info) (let ((process (slot-value process-info 'process))) (declare (ignorable process)) #+abcl (symbol-call :sys :process-pid process) #+allegro process #+clozure (ccl:external-process-id process) #+ecl (ext:external-process-pid process) #+(or cmucl scl) (ext:process-pid process) #+lispworks7+ (sys:pipe-pid process) #+(and lispworks (not lispworks7+)) process #+mkcl (mkcl:process-id process) #+sbcl (sb-ext:process-pid process) #-(or abcl allegro clozure cmucl ecl mkcl lispworks sbcl scl) (not-implemented-error 'process-info-pid))) (defun %process-status (process-info) (if-let (exit-code (slot-value process-info 'exit-code)) (return-from %process-status (if-let (signal-code (slot-value process-info 'signal-code)) (values :signaled signal-code) (values :exited exit-code)))) #-(or allegro clozure cmucl ecl lispworks mkcl sbcl scl) (not-implemented-error '%process-status) (if-let (process (slot-value process-info 'process)) (multiple-value-bind (status code) (progn #+allegro (multiple-value-bind (exit-code pid signal-code) (sys:reap-os-subprocess :pid process :wait nil) (assert pid) (%code-to-status exit-code signal-code)) #+clozure (ccl:external-process-status process) #+(or cmucl scl) (let ((status (ext:process-status process))) (if (member status '(:exited :signaled)) ;; Calling ext:process-exit-code on ;; processes that are still alive ;; yields an undefined result (values status (ext:process-exit-code process)) status)) #+ecl (ext:external-process-status process) #+lispworks ;; a signal is only returned on LispWorks 7+ (multiple-value-bind (exit-code signal-code) (symbol-call :sys #+lispworks7+ :pipe-exit-status #-lispworks7+ :pid-exit-status process :wait nil) (%code-to-status exit-code signal-code)) #+mkcl (let ((status (mk-ext:process-status process))) (if (eq status :exited) ;; Only call mk-ext:process-exit-code when ;; necessary since it leads to another waitpid() (let ((code (mk-ext:process-exit-code process))) (if (stringp code) (values :signaled (%mkcl-signal-to-number code)) (values :exited code))) status)) #+sbcl (let ((status (sb-ext:process-status process))) (if (eq status :running) :running ;; sb-ext:process-exit-code can also be ;; called for stopped processes to determine ;; the signal that stopped them (values status (sb-ext:process-exit-code process))))) (case status (:exited (setf (slot-value process-info 'exit-code) code)) (:signaled (let ((%code (%signal-to-exit-code code))) (setf (slot-value process-info 'exit-code) %code (slot-value process-info 'signal-code) code)))) (if code (values status code) status)))) (defun process-alive-p (process-info) "Check if a process has yet to exit." (unless (slot-value process-info 'exit-code) #+abcl (sys:process-alive-p (slot-value process-info 'process)) #+(or cmucl scl) (ext:process-alive-p (slot-value process-info 'process)) #+sbcl (sb-ext:process-alive-p (slot-value process-info 'process)) #-(or abcl cmucl sbcl scl) (find (%process-status process-info) '(:running :stopped :continued :resumed)))) (defun wait-process (process-info) "Wait for the process to terminate, if it is still running. Otherwise, return immediately. An exit code (a number) will be returned, with 0 indicating success, and anything else indicating failure. If the process exits after receiving a signal, the exit code will be the sum of 128 and the (positive) numeric signal code. A second value may be returned in this case: the numeric signal code itself. Any asynchronously spawned process requires this function to be run before it is garbage-collected in order to free up resources that might otherwise be irrevocably lost." (if-let (exit-code (slot-value process-info 'exit-code)) (if-let (signal-code (slot-value process-info 'signal-code)) (values exit-code signal-code) exit-code) (let ((process (slot-value process-info 'process))) #-(or abcl allegro clozure cmucl ecl lispworks mkcl sbcl scl) (not-implemented-error 'wait-process) (when process ;; 1- wait #+clozure (ccl::external-process-wait process) #+(or cmucl scl) (ext:process-wait process) #+sbcl (sb-ext:process-wait process) ;; 2- extract result (multiple-value-bind (exit-code signal-code) (progn #+abcl (sys:process-wait process) #+allegro (multiple-value-bind (exit-code pid signal) (sys:reap-os-subprocess :pid process :wait t) (assert pid) (values exit-code signal)) #+clozure (multiple-value-bind (status code) (ccl:external-process-status process) (if (eq status :signaled) (values nil code) code)) #+(or cmucl scl) (let ((status (ext:process-status process)) (code (ext:process-exit-code process))) (if (eq status :signaled) (values nil code) code)) #+ecl (multiple-value-bind (status code) (ext:external-process-wait process t) (if (eq status :signaled) (values nil code) code)) #+lispworks (symbol-call :sys #+lispworks7+ :pipe-exit-status #-lispworks7+ :pid-exit-status process :wait t) #+mkcl (let ((code (mkcl:join-process process))) (if (stringp code) (values nil (%mkcl-signal-to-number code)) code)) #+sbcl (let ((status (sb-ext:process-status process)) (code (sb-ext:process-exit-code process))) (if (eq status :signaled) (values nil code) code))) (if signal-code (let ((%exit-code (%signal-to-exit-code signal-code))) (setf (slot-value process-info 'exit-code) %exit-code (slot-value process-info 'signal-code) signal-code) (values %exit-code signal-code)) (progn (setf (slot-value process-info 'exit-code) exit-code) exit-code))))))) ;; WARNING: For signals other than SIGTERM and SIGKILL this may not ;; do what you expect it to. Sending SIGSTOP to a process spawned ;; via LAUNCH-PROGRAM, e.g., will stop the shell /bin/sh that is used ;; to run the command (via `sh -c command`) but not the actual ;; command. #+os-unix (defun %posix-send-signal (process-info signal) #+allegro (excl.osi:kill (slot-value process-info 'process) signal) #+clozure (ccl:signal-external-process (slot-value process-info 'process) signal :error-if-exited nil) #+(or cmucl scl) (ext:process-kill (slot-value process-info 'process) signal) #+sbcl (sb-ext:process-kill (slot-value process-info 'process) signal) #-(or allegro clozure cmucl sbcl scl) (if-let (pid (process-info-pid process-info)) (symbol-call :uiop :run-program (format nil "kill -~a ~a" signal pid) :ignore-error-status t))) ;;; this function never gets called on Windows, but the compiler cannot tell ;;; that. [2016/09/25:rpg] #+os-windows (defun %posix-send-signal (process-info signal) (declare (ignore process-info signal)) (values)) (defun terminate-process (process-info &key urgent) "Cause the process to exit. To that end, the process may or may not be sent a signal, which it will find harder (or even impossible) to ignore if URGENT is T. On some platforms, it may also be subject to race conditions." (declare (ignorable urgent)) #+abcl (sys:process-kill (slot-value process-info 'process)) ;; On ECL, this will only work on versions later than 2016-09-06, ;; but we still want to compile on earlier versions, so we use symbol-call #+ecl (symbol-call :ext :terminate-process (slot-value process-info 'process) urgent) #+lispworks7+ (sys:pipe-kill-process (slot-value process-info 'process)) #+mkcl (mk-ext:terminate-process (slot-value process-info 'process) :force urgent) #-(or abcl ecl lispworks7+ mkcl) (os-cond ((os-unix-p) (%posix-send-signal process-info (if urgent 9 15))) ((os-windows-p) (if-let (pid (process-info-pid process-info)) (symbol-call :uiop :run-program (format nil "taskkill ~:[~;/f ~]/pid ~a" urgent pid) :ignore-error-status t))) (t (not-implemented-error 'terminate-process)))) (defun close-streams (process-info) "Close any stream that the process might own. Needs to be run whenever streams were requested by passing :stream to :input, :output, or :error-output." (dolist (stream (cons (slot-value process-info 'error-output-stream) (if-let (bidir-stream (slot-value process-info 'bidir-stream)) (list bidir-stream) (list (slot-value process-info 'input-stream) (slot-value process-info 'output-stream))))) (when stream (close stream)))) (defun launch-program (command &rest keys &key input (if-input-does-not-exist :error) output (if-output-exists :supersede) error-output (if-error-output-exists :supersede) (element-type #-clozure *default-stream-element-type* #+clozure 'character) (external-format *utf-8-external-format*) directory #+allegro separate-streams &allow-other-keys) "Launch program specified by COMMAND, either a list of strings specifying a program and list of arguments, or a string specifying a shell command (/bin/sh on Unix, CMD.EXE on Windows) _asynchronously_. If OUTPUT is a pathname, a string designating a pathname, or NIL (the default) designating the null device, the file at that path is used as output. If it's :INTERACTIVE, output is inherited from the current process; beware that this may be different from your *STANDARD-OUTPUT*, and under SLIME will be on your *inferior-lisp* buffer. If it's T, output goes to your current *STANDARD-OUTPUT* stream. If it's :STREAM, a new stream will be made available that can be accessed via PROCESS-INFO-OUTPUT and read from. Otherwise, OUTPUT should be a value that the underlying lisp implementation knows how to handle. IF-OUTPUT-EXISTS, which is only meaningful if OUTPUT is a string or a pathname, can take the values :ERROR, :APPEND, and :SUPERSEDE (the default). The meaning of these values and their effect on the case where OUTPUT does not exist, is analogous to the IF-EXISTS parameter to OPEN with :DIRECTION :OUTPUT. ERROR-OUTPUT is similar to OUTPUT. T designates the *ERROR-OUTPUT*, :OUTPUT means redirecting the error output to the output stream, and :STREAM causes a stream to be made available via PROCESS-INFO-ERROR-OUTPUT. IF-ERROR-OUTPUT-EXISTS is similar to IF-OUTPUT-EXIST, except that it affects ERROR-OUTPUT rather than OUTPUT. INPUT is similar to OUTPUT, except that T designates the *STANDARD-INPUT* and a stream requested through the :STREAM keyword would be available through PROCESS-INFO-INPUT. IF-INPUT-DOES-NOT-EXIST, which is only meaningful if INPUT is a string or a pathname, can take the values :CREATE and :ERROR (the default). The meaning of these values is analogous to the IF-DOES-NOT-EXIST parameter to OPEN with :DIRECTION :INPUT. ELEMENT-TYPE and EXTERNAL-FORMAT are passed on to your Lisp implementation, when applicable, for creation of the output stream. LAUNCH-PROGRAM returns a PROCESS-INFO object. LAUNCH-PROGRAM currently does not smooth over all the differences between implementations. Of particular note is when streams are provided for OUTPUT or ERROR-OUTPUT. Some implementations don't support this at all, some support only certain subclasses of streams, and some support any arbitrary stream. Additionally, the implementations that support streams may have differing behavior on how those streams are filled with data. If data is not periodically read from the child process and sent to the stream, the child could block because its output buffers are full." #-(or abcl allegro clozure cmucl ecl (and lispworks os-unix) mkcl sbcl scl) (progn command keys input output error-output directory element-type external-format if-input-does-not-exist if-output-exists if-error-output-exists ;; ignore (not-implemented-error 'launch-program)) #+allegro (when (some #'(lambda (stream) (and (streamp stream) (not (file-stream-p stream)))) (list input output error-output)) (parameter-error "~S: Streams passed as I/O parameters need to be file streams on this lisp" 'launch-program)) #+(or abcl clisp lispworks) (when (some #'streamp (list input output error-output)) (parameter-error "~S: I/O parameters cannot be foreign streams on this lisp" 'launch-program)) #+clisp (unless (eq error-output :interactive) (parameter-error "~S: The only admissible value for ~S is ~S on this lisp" 'launch-program :error-output :interactive)) #+ecl (when (and (version< (lisp-implementation-version) "20.4.24") (some #'(lambda (stream) (and (streamp stream) (not (file-or-synonym-stream-p stream)))) (list input output error-output))) (parameter-error "~S: Streams passed as I/O parameters need to be (synonymous with) file streams on this lisp" 'launch-program)) #+(or abcl allegro clozure cmucl ecl (and lispworks os-unix) mkcl sbcl scl) (nest (progn ;; see comments for these functions (%handle-if-does-not-exist input if-input-does-not-exist) (%handle-if-exists output if-output-exists) (%handle-if-exists error-output if-error-output-exists)) #+ecl (let ((*standard-input* *stdin*) (*standard-output* *stdout*) (*error-output* *stderr*))) (let ((process-info (make-instance 'process-info)) (input (%normalize-io-specifier input :input)) (output (%normalize-io-specifier output :output)) (error-output (%normalize-io-specifier error-output :error-output)) #+(and allegro os-windows) (interactive (%interactivep input output error-output)) (command (etypecase command #+os-unix (string `("/bin/sh" "-c" ,command)) #+os-unix (list command) #+os-windows (string ;; NB: On other Windows implementations, this is utterly bogus ;; except in the most trivial cases where no quoting is needed. ;; Use at your own risk. #-(or allegro clisp clozure ecl) (nest #+(or ecl sbcl) (unless (find-symbol* :escape-arguments #+ecl :ext #+sbcl :sb-impl nil)) (parameter-error "~S doesn't support string commands on Windows on this Lisp" 'launch-program command)) ;; NB: We add cmd /c here. Behavior without going through cmd is not well specified ;; when the command contains spaces or special characters: ;; IIUC, the system will use space as a separator, ;; but the C++ argv-decoding libraries won't, and ;; you're supposed to use an extra argument to CreateProcess to bridge the gap, ;; yet neither allegro nor clisp provide access to that argument. #+(or allegro clisp) (strcat "cmd /c " command) ;; On ClozureCL for Windows, we assume you are using ;; r15398 or later in 1.9 or later, ;; so that bug 858 is fixed http://trac.clozure.com/ccl/ticket/858 ;; On ECL, commit 2040629 https://gitlab.com/embeddable-common-lisp/ecl/issues/304 ;; On SBCL, we assume the patch from fcae0fd (to be part of SBCL 1.3.13) #+(or clozure ecl sbcl) (cons "cmd" (strcat "/c " command))) #+os-windows (list #+allegro (escape-windows-command command) #-allegro command))))) #+(or abcl (and allegro os-unix) clozure cmucl ecl mkcl sbcl) (let ((program (car command)) #-allegro (arguments (cdr command)))) #+(and (or ecl sbcl) os-windows) (multiple-value-bind (arguments escape-arguments) (if (listp arguments) (values arguments t) (values (list arguments) nil))) #-(or allegro mkcl sbcl) (with-current-directory (directory)) (multiple-value-bind #+(or abcl clozure cmucl sbcl scl) (process) #+allegro (in-or-io out-or-err err-or-pid pid-or-nil) #+ecl (stream code process) #+lispworks (io-or-pid err-or-nil #-lispworks7+ pid-or-nil) #+mkcl (stream process code) #.`(apply #+abcl 'sys:run-program #+allegro ,@'('excl:run-shell-command #+os-unix (coerce (cons program command) 'vector) #+os-windows command) #+clozure 'ccl:run-program #+(or cmucl ecl scl) 'ext:run-program #+lispworks ,@'('system:run-shell-command `("/usr/bin/env" ,@command)) ; full path needed #+mkcl 'mk-ext:run-program #+sbcl 'sb-ext:run-program #+(or abcl clozure cmucl ecl mkcl sbcl) ,@'(program arguments) #+(and (or ecl sbcl) os-windows) ,@'(:escape-arguments escape-arguments) :input input :if-input-does-not-exist :error :output output :if-output-exists :append ,(or #+(or allegro lispworks) :error-output :error) error-output ,(or #+(or allegro lispworks) :if-error-output-exists :if-error-exists) :append :wait nil :element-type element-type :external-format external-format :allow-other-keys t #+allegro ,@`(:directory directory #+os-windows ,@'(:show-window (if interactive nil :hide))) #+lispworks ,@'(:save-exit-status t) #+mkcl ,@'(:directory (native-namestring directory)) #-sbcl keys ;; on SBCL, don't pass :directory nil but remove it from the keys #+sbcl ,@'(:search t (if directory keys (remove-plist-key :directory keys))))) (labels ((prop (key value) (setf (slot-value process-info key) value))) #+allegro (cond (separate-streams (prop 'process pid-or-nil) (when (eq input :stream) (prop 'input-stream in-or-io)) (when (eq output :stream) (prop 'output-stream out-or-err)) (when (eq error-output :stream) (prop 'error-output-stream err-or-pid))) (t (prop 'process err-or-pid) (ecase (+ (if (eq input :stream) 1 0) (if (eq output :stream) 2 0)) (0) (1 (prop 'input-stream in-or-io)) (2 (prop 'output-stream in-or-io)) (3 (prop 'bidir-stream in-or-io))) (when (eq error-output :stream) (prop 'error-output-stream out-or-err)))) #+(or abcl clozure cmucl sbcl scl) (progn (prop 'process process) (when (eq input :stream) (nest (prop 'input-stream) #+abcl (symbol-call :sys :process-input) #+clozure (ccl:external-process-input-stream) #+(or cmucl scl) (ext:process-input) #+sbcl (sb-ext:process-input) process)) (when (eq output :stream) (nest (prop 'output-stream) #+abcl (symbol-call :sys :process-output) #+clozure (ccl:external-process-output-stream) #+(or cmucl scl) (ext:process-output) #+sbcl (sb-ext:process-output) process)) (when (eq error-output :stream) (nest (prop 'error-output-stream) #+abcl (symbol-call :sys :process-error) #+clozure (ccl:external-process-error-stream) #+(or cmucl scl) (ext:process-error) #+sbcl (sb-ext:process-error) process))) #+(or ecl mkcl) (let ((mode (+ (if (eq input :stream) 1 0) (if (eq output :stream) 2 0)))) code ;; ignore (unless (zerop mode) (prop (case mode (1 'input-stream) (2 'output-stream) (3 'bidir-stream)) stream)) (when (eq error-output :stream) (prop 'error-output-stream (if (version< (lisp-implementation-version) "16.0.0") (symbol-call :ext :external-process-error process) (symbol-call :ext :external-process-error-stream process)))) (prop 'process process)) #+lispworks ;; See also the comments on the process-info class (let ((mode (+ (if (eq input :stream) 1 0) (if (eq output :stream) 2 0)))) (cond ((or (plusp mode) (eq error-output :stream)) (prop 'process #+lispworks7+ io-or-pid #-lispworks7+ pid-or-nil) (when (plusp mode) (prop (ecase mode (1 'input-stream) (2 'output-stream) (3 'bidir-stream)) io-or-pid)) (when (eq error-output :stream) (prop 'error-output-stream err-or-nil))) ;; Prior to Lispworks 7, this returned (pid); now it ;; returns (io err pid) of which we keep io. (t (prop 'process io-or-pid))))) process-info))) ;;;; ------------------------------------------------------------------------- ;;;; run-program initially from xcvb-driver. (uiop/package:define-package :uiop/run-program (:nicknames :asdf/run-program) ; OBSOLETE. Used by cl-sane, printv. (:use :uiop/common-lisp :uiop/package :uiop/utility :uiop/version :uiop/pathname :uiop/os :uiop/filesystem :uiop/stream :uiop/launch-program) (:export #:run-program #:slurp-input-stream #:vomit-output-stream #:subprocess-error #:subprocess-error-code #:subprocess-error-command #:subprocess-error-process) (:import-from :uiop/launch-program #:%handle-if-does-not-exist #:%handle-if-exists #:%interactivep #:input-stream #:output-stream #:error-output-stream)) (in-package :uiop/run-program) ;;;; Slurping a stream, typically the output of another program (with-upgradability () (defun call-stream-processor (fun processor stream) "Given FUN (typically SLURP-INPUT-STREAM or VOMIT-OUTPUT-STREAM, a PROCESSOR specification which is either an atom or a list specifying a processor an keyword arguments, call the specified processor with the given STREAM as input" (if (consp processor) (apply fun (first processor) stream (rest processor)) (funcall fun processor stream))) (defgeneric slurp-input-stream (processor input-stream &key) (:documentation "SLURP-INPUT-STREAM is a generic function with two positional arguments PROCESSOR and INPUT-STREAM and additional keyword arguments, that consumes (slurps) the contents of the INPUT-STREAM and processes them according to a method specified by PROCESSOR. Built-in methods include the following: * if PROCESSOR is a function, it is called with the INPUT-STREAM as its argument * if PROCESSOR is a list, its first element should be a function. It will be applied to a cons of the INPUT-STREAM and the rest of the list. That is (x . y) will be treated as \(APPLY x y\) * if PROCESSOR is an output-stream, the contents of INPUT-STREAM is copied to the output-stream, per copy-stream-to-stream, with appropriate keyword arguments. * if PROCESSOR is the symbol CL:STRING or the keyword :STRING, then the contents of INPUT-STREAM are returned as a string, as per SLURP-STREAM-STRING. * if PROCESSOR is the keyword :LINES then the INPUT-STREAM will be handled by SLURP-STREAM-LINES. * if PROCESSOR is the keyword :LINE then the INPUT-STREAM will be handled by SLURP-STREAM-LINE. * if PROCESSOR is the keyword :FORMS then the INPUT-STREAM will be handled by SLURP-STREAM-FORMS. * if PROCESSOR is the keyword :FORM then the INPUT-STREAM will be handled by SLURP-STREAM-FORM. * if PROCESSOR is T, it is treated the same as *standard-output*. If it is NIL, NIL is returned. Programmers are encouraged to define their own methods for this generic function.")) #-genera (defmethod slurp-input-stream ((function function) input-stream &key) (funcall function input-stream)) (defmethod slurp-input-stream ((list cons) input-stream &key) (apply (first list) input-stream (rest list))) #-genera (defmethod slurp-input-stream ((output-stream stream) input-stream &key linewise prefix (element-type 'character) buffer-size) (copy-stream-to-stream input-stream output-stream :linewise linewise :prefix prefix :element-type element-type :buffer-size buffer-size)) (defmethod slurp-input-stream ((x (eql 'string)) stream &key stripped) (slurp-stream-string stream :stripped stripped)) (defmethod slurp-input-stream ((x (eql :string)) stream &key stripped) (slurp-stream-string stream :stripped stripped)) (defmethod slurp-input-stream ((x (eql :lines)) stream &key count) (slurp-stream-lines stream :count count)) (defmethod slurp-input-stream ((x (eql :line)) stream &key (at 0)) (slurp-stream-line stream :at at)) (defmethod slurp-input-stream ((x (eql :forms)) stream &key count) (slurp-stream-forms stream :count count)) (defmethod slurp-input-stream ((x (eql :form)) stream &key (at 0)) (slurp-stream-form stream :at at)) (defmethod slurp-input-stream ((x (eql t)) stream &rest keys &key &allow-other-keys) (apply 'slurp-input-stream *standard-output* stream keys)) (defmethod slurp-input-stream ((x null) (stream t) &key) nil) (defmethod slurp-input-stream ((pathname pathname) input &key (element-type *default-stream-element-type*) (external-format *utf-8-external-format*) (if-exists :rename-and-delete) (if-does-not-exist :create) buffer-size linewise) (with-output-file (output pathname :element-type element-type :external-format external-format :if-exists if-exists :if-does-not-exist if-does-not-exist) (copy-stream-to-stream input output :element-type element-type :buffer-size buffer-size :linewise linewise))) (defmethod slurp-input-stream (x stream &key linewise prefix (element-type 'character) buffer-size) (declare (ignorable stream linewise prefix element-type buffer-size)) (cond #+genera ((functionp x) (funcall x stream)) #+genera ((output-stream-p x) (copy-stream-to-stream stream x :linewise linewise :prefix prefix :element-type element-type :buffer-size buffer-size)) (t (parameter-error "Invalid ~S destination ~S" 'slurp-input-stream x))))) ;;;; Vomiting a stream, typically into the input of another program. (with-upgradability () (defgeneric vomit-output-stream (processor output-stream &key) (:documentation "VOMIT-OUTPUT-STREAM is a generic function with two positional arguments PROCESSOR and OUTPUT-STREAM and additional keyword arguments, that produces (vomits) some content onto the OUTPUT-STREAM, according to a method specified by PROCESSOR. Built-in methods include the following: * if PROCESSOR is a function, it is called with the OUTPUT-STREAM as its argument * if PROCESSOR is a list, its first element should be a function. It will be applied to a cons of the OUTPUT-STREAM and the rest of the list. That is (x . y) will be treated as \(APPLY x y\) * if PROCESSOR is an input-stream, its contents will be copied the OUTPUT-STREAM, per copy-stream-to-stream, with appropriate keyword arguments. * if PROCESSOR is a string, its contents will be printed to the OUTPUT-STREAM. * if PROCESSOR is T, it is treated the same as *standard-input*. If it is NIL, nothing is done. Programmers are encouraged to define their own methods for this generic function.")) #-genera (defmethod vomit-output-stream ((function function) output-stream &key) (funcall function output-stream)) (defmethod vomit-output-stream ((list cons) output-stream &key) (apply (first list) output-stream (rest list))) #-genera (defmethod vomit-output-stream ((input-stream stream) output-stream &key linewise prefix (element-type 'character) buffer-size) (copy-stream-to-stream input-stream output-stream :linewise linewise :prefix prefix :element-type element-type :buffer-size buffer-size)) (defmethod vomit-output-stream ((x string) stream &key fresh-line terpri) (princ x stream) (when fresh-line (fresh-line stream)) (when terpri (terpri stream)) (values)) (defmethod vomit-output-stream ((x (eql t)) stream &rest keys &key &allow-other-keys) (apply 'vomit-output-stream *standard-input* stream keys)) (defmethod vomit-output-stream ((x null) (stream t) &key) (values)) (defmethod vomit-output-stream ((pathname pathname) input &key (element-type *default-stream-element-type*) (external-format *utf-8-external-format*) (if-exists :rename-and-delete) (if-does-not-exist :create) buffer-size linewise) (with-output-file (output pathname :element-type element-type :external-format external-format :if-exists if-exists :if-does-not-exist if-does-not-exist) (copy-stream-to-stream input output :element-type element-type :buffer-size buffer-size :linewise linewise))) (defmethod vomit-output-stream (x stream &key linewise prefix (element-type 'character) buffer-size) (declare (ignorable stream linewise prefix element-type buffer-size)) (cond #+genera ((functionp x) (funcall x stream)) #+genera ((input-stream-p x) (copy-stream-to-stream x stream :linewise linewise :prefix prefix :element-type element-type :buffer-size buffer-size)) (t (parameter-error "Invalid ~S source ~S" 'vomit-output-stream x))))) ;;;; Run-program: synchronously run a program in a subprocess, handling input, output and error-output. (with-upgradability () (define-condition subprocess-error (error) ((code :initform nil :initarg :code :reader subprocess-error-code) (command :initform nil :initarg :command :reader subprocess-error-command) (process :initform nil :initarg :process :reader subprocess-error-process)) (:report (lambda (condition stream) (format stream "Subprocess ~@[~S~% ~]~@[with command ~S~% ~]exited with error~@[ code ~D~]" (subprocess-error-process condition) (subprocess-error-command condition) (subprocess-error-code condition))))) (defun %check-result (exit-code &key command process ignore-error-status) (unless ignore-error-status (unless (eql exit-code 0) (cerror "IGNORE-ERROR-STATUS" 'subprocess-error :command command :code exit-code :process process))) exit-code) (defun %active-io-specifier-p (specifier) "Determines whether a run-program I/O specifier requires Lisp-side processing via SLURP-INPUT-STREAM or VOMIT-OUTPUT-STREAM (return T), or whether it's already taken care of by the implementation's underlying run-program." (not (typep specifier '(or null string pathname (member :interactive :output) #+(or cmucl (and sbcl os-unix) scl) (or stream (eql t)) #+lispworks file-stream)))) (defun %run-program (command &rest keys &key &allow-other-keys) "DEPRECATED. Use LAUNCH-PROGRAM instead." (apply 'launch-program command keys)) (defun %call-with-program-io (gf tval stream-easy-p fun direction spec activep returner &key (element-type #-clozure *default-stream-element-type* #+clozure 'character) (external-format *utf-8-external-format*) &allow-other-keys) ;; handle redirection for run-program and system ;; SPEC is the specification for the subprocess's input or output or error-output ;; TVAL is the value used if the spec is T ;; GF is the generic function to call to handle arbitrary values of SPEC ;; STREAM-EASY-P is T if we're going to use a RUN-PROGRAM that copies streams in the background ;; (it's only meaningful on CMUCL, SBCL, SCL that actually do it) ;; DIRECTION is :INPUT, :OUTPUT or :ERROR-OUTPUT for the direction of this io argument ;; FUN is a function of the new reduced spec and an activity function to call with a stream ;; when the subprocess is active and communicating through that stream. ;; ACTIVEP is a boolean true if we will get to run code while the process is running ;; ELEMENT-TYPE and EXTERNAL-FORMAT control what kind of temporary file we may open. ;; RETURNER is a function called with the value of the activity. ;; --- TODO (fare@tunes.org): handle if-output-exists and such when doing it the hard way. (declare (ignorable stream-easy-p)) (let* ((actual-spec (if (eq spec t) tval spec)) (activity-spec (if (eq actual-spec :output) (ecase direction ((:input :output) (parameter-error "~S does not allow ~S as a ~S spec" 'run-program :output direction)) ((:error-output) nil)) actual-spec))) (labels ((activity (stream) (call-function returner (call-stream-processor gf activity-spec stream))) (easy-case () (funcall fun actual-spec nil)) (hard-case () (if activep (funcall fun :stream #'activity) (with-temporary-file (:pathname tmp) (ecase direction (:input (with-output-file (s tmp :if-exists :overwrite :external-format external-format :element-type element-type) (activity s)) (funcall fun tmp nil)) ((:output :error-output) (multiple-value-prog1 (funcall fun tmp nil) (with-input-file (s tmp :external-format external-format :element-type element-type) (activity s))))))))) (typecase activity-spec ((or null string pathname (eql :interactive)) (easy-case)) #+(or cmucl (and sbcl os-unix) scl) ;; streams are only easy on implementations that try very hard (stream (if stream-easy-p (easy-case) (hard-case))) (t (hard-case)))))) (defmacro place-setter (place) (when place (let ((value (gensym))) `#'(lambda (,value) (setf ,place ,value))))) (defmacro with-program-input (((reduced-input-var &optional (input-activity-var (gensym) iavp)) input-form &key setf stream-easy-p active keys) &body body) `(apply '%call-with-program-io 'vomit-output-stream *standard-input* ,stream-easy-p #'(lambda (,reduced-input-var ,input-activity-var) ,@(unless iavp `((declare (ignore ,input-activity-var)))) ,@body) :input ,input-form ,active (place-setter ,setf) ,keys)) (defmacro with-program-output (((reduced-output-var &optional (output-activity-var (gensym) oavp)) output-form &key setf stream-easy-p active keys) &body body) `(apply '%call-with-program-io 'slurp-input-stream *standard-output* ,stream-easy-p #'(lambda (,reduced-output-var ,output-activity-var) ,@(unless oavp `((declare (ignore ,output-activity-var)))) ,@body) :output ,output-form ,active (place-setter ,setf) ,keys)) (defmacro with-program-error-output (((reduced-error-output-var &optional (error-output-activity-var (gensym) eoavp)) error-output-form &key setf stream-easy-p active keys) &body body) `(apply '%call-with-program-io 'slurp-input-stream *error-output* ,stream-easy-p #'(lambda (,reduced-error-output-var ,error-output-activity-var) ,@(unless eoavp `((declare (ignore ,error-output-activity-var)))) ,@body) :error-output ,error-output-form ,active (place-setter ,setf) ,keys)) (defun %use-launch-program (command &rest keys &key input output error-output ignore-error-status &allow-other-keys) ;; helper for RUN-PROGRAM when using LAUNCH-PROGRAM #+(or cormanlisp gcl (and lispworks os-windows) mcl xcl) (progn command keys input output error-output ignore-error-status ;; ignore (not-implemented-error '%use-launch-program)) (when (member :stream (list input output error-output)) (parameter-error "~S: ~S is not allowed as synchronous I/O redirection argument" 'run-program :stream)) (let* ((active-input-p (%active-io-specifier-p input)) (active-output-p (%active-io-specifier-p output)) (active-error-output-p (%active-io-specifier-p error-output)) (activity (cond (active-output-p :output) (active-input-p :input) (active-error-output-p :error-output) (t nil))) output-result error-output-result exit-code process-info) (with-program-output ((reduced-output output-activity) output :keys keys :setf output-result :stream-easy-p t :active (eq activity :output)) (with-program-error-output ((reduced-error-output error-output-activity) error-output :keys keys :setf error-output-result :stream-easy-p t :active (eq activity :error-output)) (with-program-input ((reduced-input input-activity) input :keys keys :stream-easy-p t :active (eq activity :input)) (setf process-info (apply 'launch-program command :input reduced-input :output reduced-output :error-output (if (eq error-output :output) :output reduced-error-output) keys)) (labels ((get-stream (stream-name &optional fallbackp) (or (slot-value process-info stream-name) (when fallbackp (slot-value process-info 'bidir-stream)))) (run-activity (activity stream-name &optional fallbackp) (if-let (stream (get-stream stream-name fallbackp)) (funcall activity stream) (error 'subprocess-error :code `(:missing ,stream-name) :command command :process process-info)))) (unwind-protect (ecase activity ((nil)) (:input (run-activity input-activity 'input-stream t)) (:output (run-activity output-activity 'output-stream t)) (:error-output (run-activity error-output-activity 'error-output-stream))) (close-streams process-info) (setf exit-code (wait-process process-info))))))) (%check-result exit-code :command command :process process-info :ignore-error-status ignore-error-status) (values output-result error-output-result exit-code))) (defun %normalize-system-command (command) ;; helper for %USE-SYSTEM (etypecase command (string command) (list (escape-shell-command (os-cond ((os-unix-p) (cons "exec" command)) (t command)))))) (defun %redirected-system-command (command in out err directory) ;; helper for %USE-SYSTEM (flet ((redirect (spec operator) (let ((pathname (typecase spec (null (null-device-pathname)) (string (parse-native-namestring spec)) (pathname spec) ((eql :output) (unless (equal operator " 2>>") (parameter-error "~S: only the ~S argument can be ~S" 'run-program :error-output :output)) (return-from redirect '(" 2>&1")))))) (when pathname (list operator " " (escape-shell-token (native-namestring pathname))))))) (let* ((redirections (append (redirect in " <") (redirect out " >>") (redirect err " 2>>"))) (normalized (%normalize-system-command command)) (directory (or directory #+(or abcl xcl) (getcwd))) (chdir (when directory (let ((dir-arg (escape-shell-token (native-namestring directory)))) (os-cond ((os-unix-p) `("cd " ,dir-arg " ; ")) ((os-windows-p) `("cd /d " ,dir-arg " & "))))))) (reduce/strcat (os-cond ((os-unix-p) `(,@(when redirections `("exec " ,@redirections " ; ")) ,@chdir ,normalized)) ((os-windows-p) `(,@redirections " (" ,@chdir ,normalized ")"))))))) (defun %system (command &rest keys &key directory input (if-input-does-not-exist :error) output (if-output-exists :supersede) error-output (if-error-output-exists :supersede) &allow-other-keys) "A portable abstraction of a low-level call to libc's system()." (declare (ignorable keys directory input if-input-does-not-exist output if-output-exists error-output if-error-output-exists)) (when (member :stream (list input output error-output)) (parameter-error "~S: ~S is not allowed as synchronous I/O redirection argument" 'run-program :stream)) #+(or abcl allegro clozure cmucl ecl (and lispworks os-unix) mkcl sbcl scl) (let (#+(or abcl ecl mkcl) (version (parse-version #-abcl (lisp-implementation-version) #+abcl (second (split-string (implementation-identifier) :separator '(#\-)))))) (nest #+abcl (unless (lexicographic< '< version '(1 4 0))) #+ecl (unless (lexicographic<= '< version '(16 0 0))) #+mkcl (unless (lexicographic<= '< version '(1 1 9))) (return-from %system (wait-process (apply 'launch-program (%normalize-system-command command) keys))))) #+(or abcl clasp clisp cormanlisp ecl gcl genera (and lispworks os-windows) mkcl xcl) (let ((%command (%redirected-system-command command input output error-output directory))) ;; see comments for these functions (%handle-if-does-not-exist input if-input-does-not-exist) (%handle-if-exists output if-output-exists) (%handle-if-exists error-output if-error-output-exists) #+abcl (ext:run-shell-command %command) #+(or clasp ecl) (let ((*standard-input* *stdin*) (*standard-output* *stdout*) (*error-output* *stderr*)) (ext:system %command)) #+clisp (let ((raw-exit-code (or #.`(#+os-windows ,@'(ext:run-shell-command %command) #+os-unix ,@'(ext:run-program "/bin/sh" :arguments `("-c" ,%command)) :wait t :input :terminal :output :terminal) 0))) (if (minusp raw-exit-code) (- 128 raw-exit-code) raw-exit-code)) #+cormanlisp (win32:system %command) #+gcl (system:system %command) #+genera (not-implemented-error '%system) #+(and lispworks os-windows) (system:call-system %command :current-directory directory :wait t) #+mcl (ccl::with-cstrs ((%%command %command)) (_system %%command)) #+mkcl (mkcl:system %command) #+xcl (system:%run-shell-command %command))) (defun %use-system (command &rest keys &key input output error-output ignore-error-status &allow-other-keys) ;; helper for RUN-PROGRAM when using %system (let (output-result error-output-result exit-code) (with-program-output ((reduced-output) output :keys keys :setf output-result) (with-program-error-output ((reduced-error-output) error-output :keys keys :setf error-output-result) (with-program-input ((reduced-input) input :keys keys) (setf exit-code (apply '%system command :input reduced-input :output reduced-output :error-output reduced-error-output keys))))) (%check-result exit-code :command command :ignore-error-status ignore-error-status) (values output-result error-output-result exit-code))) (defun run-program (command &rest keys &key ignore-error-status (force-shell nil force-shell-suppliedp) input (if-input-does-not-exist :error) output (if-output-exists :supersede) error-output (if-error-output-exists :supersede) (element-type #-clozure *default-stream-element-type* #+clozure 'character) (external-format *utf-8-external-format*) &allow-other-keys) "Run program specified by COMMAND, either a list of strings specifying a program and list of arguments, or a string specifying a shell command (/bin/sh on Unix, CMD.EXE on Windows); _synchronously_ process its output as specified and return the processing results when the program and its output processing are complete. Always call a shell (rather than directly execute the command when possible) if FORCE-SHELL is specified. Similarly, never call a shell if FORCE-SHELL is specified to be NIL. Signal a continuable SUBPROCESS-ERROR if the process wasn't successful (exit-code 0), unless IGNORE-ERROR-STATUS is specified. If OUTPUT is a pathname, a string designating a pathname, or NIL (the default) designating the null device, the file at that path is used as output. If it's :INTERACTIVE, output is inherited from the current process; beware that this may be different from your *STANDARD-OUTPUT*, and under SLIME will be on your *inferior-lisp* buffer. If it's T, output goes to your current *STANDARD-OUTPUT* stream. Otherwise, OUTPUT should be a value that is a suitable first argument to SLURP-INPUT-STREAM (qv.), or a list of such a value and keyword arguments. In this case, RUN-PROGRAM will create a temporary stream for the program output; the program output, in that stream, will be processed by a call to SLURP-INPUT-STREAM, using OUTPUT as the first argument (or the first element of OUTPUT, and the rest as keywords). The primary value resulting from that call (or NIL if no call was needed) will be the first value returned by RUN-PROGRAM. E.g., using :OUTPUT :STRING will have it return the entire output stream as a string. And using :OUTPUT '(:STRING :STRIPPED T) will have it return the same string stripped of any ending newline. IF-OUTPUT-EXISTS, which is only meaningful if OUTPUT is a string or a pathname, can take the values :ERROR, :APPEND, and :SUPERSEDE (the default). The meaning of these values and their effect on the case where OUTPUT does not exist, is analogous to the IF-EXISTS parameter to OPEN with :DIRECTION :OUTPUT. ERROR-OUTPUT is similar to OUTPUT, except that the resulting value is returned as the second value of RUN-PROGRAM. T designates the *ERROR-OUTPUT*. Also :OUTPUT means redirecting the error output to the output stream, in which case NIL is returned. IF-ERROR-OUTPUT-EXISTS is similar to IF-OUTPUT-EXIST, except that it affects ERROR-OUTPUT rather than OUTPUT. INPUT is similar to OUTPUT, except that VOMIT-OUTPUT-STREAM is used, no value is returned, and T designates the *STANDARD-INPUT*. IF-INPUT-DOES-NOT-EXIST, which is only meaningful if INPUT is a string or a pathname, can take the values :CREATE and :ERROR (the default). The meaning of these values is analogous to the IF-DOES-NOT-EXIST parameter to OPEN with :DIRECTION :INPUT. ELEMENT-TYPE and EXTERNAL-FORMAT are passed on to your Lisp implementation, when applicable, for creation of the output stream. One and only one of the stream slurping or vomiting may or may not happen in parallel in parallel with the subprocess, depending on options and implementation, and with priority being given to output processing. Other streams are completely produced or consumed before or after the subprocess is spawned, using temporary files. RUN-PROGRAM returns 3 values: 0- the result of the OUTPUT slurping if any, or NIL 1- the result of the ERROR-OUTPUT slurping if any, or NIL 2- either 0 if the subprocess exited with success status, or an indication of failure via the EXIT-CODE of the process" (declare (ignorable input output error-output if-input-does-not-exist if-output-exists if-error-output-exists element-type external-format ignore-error-status)) #-(or abcl allegro clasp clisp clozure cmucl cormanlisp ecl gcl lispworks mcl mkcl sbcl scl xcl) (not-implemented-error 'run-program) (apply (if (or force-shell ;; Per doc string, set FORCE-SHELL to T if we get command as a string. ;; But don't override user's specified preference. [2015/06/29:rpg] (and (stringp command) (or (not force-shell-suppliedp) #-(or allegro clisp clozure sbcl) (os-cond ((os-windows-p) t)))) #+(or clasp clisp cormanlisp gcl (and lispworks os-windows) mcl xcl) t ;; A race condition in ECL <= 16.0.0 prevents using ext:run-program #+ecl #.(if-let (ver (parse-version (lisp-implementation-version))) (lexicographic<= '< ver '(16 0 0))) #+(and lispworks os-unix) (%interactivep input output error-output)) '%use-system '%use-launch-program) command keys))) ;;;; --------------------------------------------------------------------------- ;;;; Generic support for configuration files (uiop/package:define-package :uiop/configuration (:recycle :uiop/configuration :asdf/configuration) ;; necessary to upgrade from 2.27. (:use :uiop/package :uiop/common-lisp :uiop/utility :uiop/os :uiop/pathname :uiop/filesystem :uiop/stream :uiop/image :uiop/lisp-build) (:export #:user-configuration-directories #:system-configuration-directories ;; implemented in backward-driver #:in-first-directory #:in-user-configuration-directory #:in-system-configuration-directory ;; idem #:get-folder-path #:xdg-data-home #:xdg-config-home #:xdg-data-dirs #:xdg-config-dirs #:xdg-cache-home #:xdg-runtime-dir #:system-config-pathnames #:filter-pathname-set #:xdg-data-pathnames #:xdg-config-pathnames #:find-preferred-file #:xdg-data-pathname #:xdg-config-pathname #:validate-configuration-form #:validate-configuration-file #:validate-configuration-directory #:configuration-inheritance-directive-p #:report-invalid-form #:invalid-configuration #:*ignored-configuration-form* #:*user-cache* #:*clear-configuration-hook* #:clear-configuration #:register-clear-configuration-hook #:resolve-location #:location-designator-p #:location-function-p #:*here-directory* #:resolve-relative-location #:resolve-absolute-location #:upgrade-configuration #:uiop-directory)) (in-package :uiop/configuration) (with-upgradability () (define-condition invalid-configuration () ((form :reader condition-form :initarg :form) (location :reader condition-location :initarg :location) (format :reader condition-format :initarg :format) (arguments :reader condition-arguments :initarg :arguments :initform nil)) (:report (lambda (c s) (format s (compatfmt "~@<~? (will be skipped)~@:>") (condition-format c) (list* (condition-form c) (condition-location c) (condition-arguments c)))))) (defun configuration-inheritance-directive-p (x) "Is X a configuration inheritance directive?" (let ((kw '(:inherit-configuration :ignore-inherited-configuration))) (or (member x kw) (and (length=n-p x 1) (member (car x) kw))))) (defun report-invalid-form (reporter &rest args) "Report an invalid form according to REPORTER and various ARGS" (etypecase reporter (null (apply 'error 'invalid-configuration args)) (function (apply reporter args)) ((or symbol string) (apply 'error reporter args)) (cons (apply 'apply (append reporter args))))) (defvar *ignored-configuration-form* nil "Have configuration forms been ignored while parsing the configuration?") (defun validate-configuration-form (form tag directive-validator &key location invalid-form-reporter) "Validate a configuration FORM. By default it will raise an error if the FORM is not valid. Otherwise it will return the validated form. Arguments control the behavior: The configuration FORM should be of the form (TAG . ) Each element of will be checked by first seeing if it's a configuration inheritance directive (see CONFIGURATION-INHERITANCE-DIRECTIVE-P) then invoking DIRECTIVE-VALIDATOR on it. In the event of an invalid form, INVALID-FORM-REPORTER will be used to control reporting (see REPORT-INVALID-FORM) with LOCATION providing information about where the configuration form appeared." (unless (and (consp form) (eq (car form) tag)) (setf *ignored-configuration-form* t) (report-invalid-form invalid-form-reporter :form form :location location) (return-from validate-configuration-form nil)) (loop :with inherit = 0 :with ignore-invalid-p = nil :with x = (list tag) :for directive :in (cdr form) :when (cond ((configuration-inheritance-directive-p directive) (incf inherit) t) ((eq directive :ignore-invalid-entries) (setf ignore-invalid-p t) t) ((funcall directive-validator directive) t) (ignore-invalid-p nil) (t (setf *ignored-configuration-form* t) (report-invalid-form invalid-form-reporter :form directive :location location) nil)) :do (push directive x) :finally (unless (= inherit 1) (report-invalid-form invalid-form-reporter :form form :location location ;; we throw away the form and location arguments, hence the ~2* ;; this is necessary because of the report in INVALID-CONFIGURATION :format (compatfmt "~@") :arguments '(:inherit-configuration :ignore-inherited-configuration))) (return (nreverse x)))) (defun validate-configuration-file (file validator &key description) "Validate a configuration FILE. The configuration file should have only one s-expression in it, which will be checked with the VALIDATOR FORM. DESCRIPTION argument used for error reporting." (let ((forms (read-file-forms file))) (unless (length=n-p forms 1) (error (compatfmt "~@~%") description forms)) (funcall validator (car forms) :location file))) (defun validate-configuration-directory (directory tag validator &key invalid-form-reporter) "Map the VALIDATOR across the .conf files in DIRECTORY, the TAG will be applied to the results to yield a configuration form. Current values of TAG include :source-registry and :output-translations." (let ((files (sort (ignore-errors ;; SORT w/o COPY-LIST is OK: DIRECTORY returns a fresh list (remove-if 'hidden-pathname-p (directory* (make-pathname :name *wild* :type "conf" :defaults directory)))) #'string< :key #'namestring))) `(,tag ,@(loop :for file :in files :append (loop :with ignore-invalid-p = nil :for form :in (read-file-forms file) :when (eq form :ignore-invalid-entries) :do (setf ignore-invalid-p t) :else :when (funcall validator form) :collect form :else :when ignore-invalid-p :do (setf *ignored-configuration-form* t) :else :do (report-invalid-form invalid-form-reporter :form form :location file))) :inherit-configuration))) (defun resolve-relative-location (x &key ensure-directory wilden) "Given a designator X for an relative location, resolve it to a pathname." (ensure-pathname (etypecase x (null nil) (pathname x) (string (parse-unix-namestring x :ensure-directory ensure-directory)) (cons (if (null (cdr x)) (resolve-relative-location (car x) :ensure-directory ensure-directory :wilden wilden) (let* ((car (resolve-relative-location (car x) :ensure-directory t :wilden nil))) (merge-pathnames* (resolve-relative-location (cdr x) :ensure-directory ensure-directory :wilden wilden) car)))) ((eql :*/) *wild-directory*) ((eql :**/) *wild-inferiors*) ((eql :*.*.*) *wild-file*) ((eql :implementation) (parse-unix-namestring (implementation-identifier) :ensure-directory t)) ((eql :implementation-type) (parse-unix-namestring (string-downcase (implementation-type)) :ensure-directory t)) ((eql :hostname) (parse-unix-namestring (hostname) :ensure-directory t))) :wilden (and wilden (not (pathnamep x)) (not (member x '(:*/ :**/ :*.*.*)))) :want-relative t)) (defvar *here-directory* nil "This special variable is bound to the currect directory during calls to PROCESS-SOURCE-REGISTRY in order that we be able to interpret the :here directive.") (defvar *user-cache* nil "A specification as per RESOLVE-LOCATION of where the user keeps his FASL cache") (defun resolve-absolute-location (x &key ensure-directory wilden) "Given a designator X for an absolute location, resolve it to a pathname" (ensure-pathname (etypecase x (null nil) (pathname x) (string (let ((p #-mcl (parse-namestring x) #+mcl (probe-posix x))) #+mcl (unless p (error "POSIX pathname ~S does not exist" x)) (if ensure-directory (ensure-directory-pathname p) p))) (cons (return-from resolve-absolute-location (if (null (cdr x)) (resolve-absolute-location (car x) :ensure-directory ensure-directory :wilden wilden) (merge-pathnames* (resolve-relative-location (cdr x) :ensure-directory ensure-directory :wilden wilden) (resolve-absolute-location (car x) :ensure-directory t :wilden nil))))) ((eql :root) ;; special magic! we return a relative pathname, ;; but what it means to the output-translations is ;; "relative to the root of the source pathname's host and device". (return-from resolve-absolute-location (let ((p (make-pathname :directory '(:relative)))) (if wilden (wilden p) p)))) ((eql :home) (user-homedir-pathname)) ((eql :here) (resolve-absolute-location (or *here-directory* (pathname-directory-pathname (truename (load-pathname)))) :ensure-directory t :wilden nil)) ((eql :user-cache) (resolve-absolute-location *user-cache* :ensure-directory t :wilden nil))) :wilden (and wilden (not (pathnamep x))) :resolve-symlinks *resolve-symlinks* :want-absolute t)) ;; Try to override declaration in previous versions of ASDF. (declaim (ftype (function (t &key (:directory boolean) (:wilden boolean) (:ensure-directory boolean)) t) resolve-location)) (defun resolve-location (x &key ensure-directory wilden directory) "Resolve location designator X into a PATHNAME" ;; :directory backward compatibility, until 2014-01-16: accept directory as well as ensure-directory (loop :with dirp = (or directory ensure-directory) :with (first . rest) = (if (atom x) (list x) x) :with path = (or (resolve-absolute-location first :ensure-directory (and (or dirp rest) t) :wilden (and wilden (null rest))) (return nil)) :for (element . morep) :on rest :for dir = (and (or morep dirp) t) :for wild = (and wilden (not morep)) :for sub = (merge-pathnames* (resolve-relative-location element :ensure-directory dir :wilden wild) path) :do (setf path (if (absolute-pathname-p sub) (resolve-symlinks* sub) sub)) :finally (return path))) (defun location-designator-p (x) "Is X a designator for a location?" ;; NIL means "skip this entry", or as an output translation, same as translation input. ;; T means "any input" for a translation, or as output, same as translation input. (flet ((absolute-component-p (c) (typep c '(or string pathname (member :root :home :here :user-cache)))) (relative-component-p (c) (typep c '(or string pathname (member :*/ :**/ :*.*.* :implementation :implementation-type))))) (or (typep x 'boolean) (absolute-component-p x) (and (consp x) (absolute-component-p (first x)) (every #'relative-component-p (rest x)))))) (defun location-function-p (x) "Is X the specification of a location function?" ;; Location functions are allowed in output translations, and notably used by ABCL for JAR file support. (and (length=n-p x 2) (eq (car x) :function))) (defvar *clear-configuration-hook* '()) (defun register-clear-configuration-hook (hook-function &optional call-now-p) "Register a function to be called when clearing configuration" (register-hook-function '*clear-configuration-hook* hook-function call-now-p)) (defun clear-configuration () "Call the functions in *CLEAR-CONFIGURATION-HOOK*" (call-functions *clear-configuration-hook*)) (register-image-dump-hook 'clear-configuration) (defun upgrade-configuration () "If a previous version of ASDF failed to read some configuration, try again now." (when *ignored-configuration-form* (clear-configuration) (setf *ignored-configuration-form* nil))) (defun get-folder-path (folder) "Semi-portable implementation of a subset of LispWorks' sys:get-folder-path, this function tries to locate the Windows FOLDER for one of :LOCAL-APPDATA, :APPDATA or :COMMON-APPDATA. Returns NIL when the folder is not defined (e.g., not on Windows)." (or #+(and lispworks os-windows) (sys:get-folder-path folder) ;; read-windows-registry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\AppData (ecase folder (:local-appdata (or (getenv-absolute-directory "LOCALAPPDATA") (subpathname* (get-folder-path :appdata) "Local"))) (:appdata (getenv-absolute-directory "APPDATA")) (:common-appdata (or (getenv-absolute-directory "ALLUSERSAPPDATA") (subpathname* (getenv-absolute-directory "ALLUSERSPROFILE") "Application Data/")))))) ;; Support for the XDG Base Directory Specification (defun xdg-data-home (&rest more) "Returns an absolute pathname for the directory containing user-specific data files. MORE may contain specifications for a subpath relative to this directory: a subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." (resolve-absolute-location `(,(or (getenv-absolute-directory "XDG_DATA_HOME") (os-cond ((os-windows-p) (get-folder-path :local-appdata)) (t (subpathname (user-homedir-pathname) ".local/share/")))) ,more))) (defun xdg-config-home (&rest more) "Returns a pathname for the directory containing user-specific configuration files. MORE may contain specifications for a subpath relative to this directory: a subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." (resolve-absolute-location `(,(or (getenv-absolute-directory "XDG_CONFIG_HOME") (os-cond ((os-windows-p) (xdg-data-home "config/")) (t (subpathname (user-homedir-pathname) ".config/")))) ,more))) (defun xdg-data-dirs (&rest more) "The preference-ordered set of additional paths to search for data files. Returns a list of absolute directory pathnames. MORE may contain specifications for a subpath relative to these directories: a subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." (mapcar #'(lambda (d) (resolve-location `(,d ,more))) (or (remove nil (getenv-absolute-directories "XDG_DATA_DIRS")) (os-cond ((os-windows-p) (mapcar 'get-folder-path '(:appdata :common-appdata))) ;; macOS' separate read-only system volume means that the contents ;; of /usr/share are frozen by Apple. Unlike when running natively ;; on macOS, Genera must access the filesystem through NFS. Attempting ;; to export either the root (/) or /usr/share simply doesn't work. ;; (Genera will go into an infinite loop trying to access those mounts.) ;; So, when running Genera on macOS, only search /usr/local/share. ((os-genera-p) #+Genera (sys:system-case (darwin-vlm (mapcar 'parse-unix-namestring '("/usr/local/share/"))) (otherwise (mapcar 'parse-unix-namestring '("/usr/local/share/" "/usr/share/"))))) (t (mapcar 'parse-unix-namestring '("/usr/local/share/" "/usr/share/"))))))) (defun xdg-config-dirs (&rest more) "The preference-ordered set of additional base paths to search for configuration files. Returns a list of absolute directory pathnames. MORE may contain specifications for a subpath relative to these directories: subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." (mapcar #'(lambda (d) (resolve-location `(,d ,more))) (or (remove nil (getenv-absolute-directories "XDG_CONFIG_DIRS")) (os-cond ((os-windows-p) (xdg-data-dirs "config/")) (t (mapcar 'parse-unix-namestring '("/etc/xdg/"))))))) (defun xdg-cache-home (&rest more) "The base directory relative to which user specific non-essential data files should be stored. Returns an absolute directory pathname. MORE may contain specifications for a subpath relative to this directory: a subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." (resolve-absolute-location `(,(or (getenv-absolute-directory "XDG_CACHE_HOME") (os-cond ((os-windows-p) (xdg-data-home "cache/")) (t (subpathname* (user-homedir-pathname) ".cache/")))) ,more))) (defun xdg-runtime-dir (&rest more) "Pathname for user-specific non-essential runtime files and other file objects, such as sockets, named pipes, etc. Returns an absolute directory pathname. MORE may contain specifications for a subpath relative to this directory: a subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." ;; The XDG spec says that if not provided by the login system, the application should ;; issue a warning and provide a replacement. UIOP is not equipped to do that and returns NIL. (resolve-absolute-location `(,(getenv-absolute-directory "XDG_RUNTIME_DIR") ,more))) ;;; NOTE: modified the docstring because "system user configuration ;;; directories" seems self-contradictory. I'm not sure my wording is right. (defun system-config-pathnames (&rest more) "Return a list of directories where are stored the system's default user configuration information. MORE may contain specifications for a subpath relative to these directories: a subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." (declare (ignorable more)) (os-cond ((os-unix-p) (list (resolve-absolute-location `(,(parse-unix-namestring "/etc/") ,more)))))) (defun filter-pathname-set (dirs) "Parse strings as unix namestrings and remove duplicates and non absolute-pathnames in a list." (remove-duplicates (remove-if-not #'absolute-pathname-p dirs) :from-end t :test 'equal)) (defun xdg-data-pathnames (&rest more) "Return a list of absolute pathnames for application data directories. With APP, returns directory for data for that application, without APP, returns the set of directories for storing all application configurations. MORE may contain specifications for a subpath relative to these directories: a subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." (filter-pathname-set `(,(xdg-data-home more) ,@(xdg-data-dirs more)))) (defun xdg-config-pathnames (&rest more) "Return a list of pathnames for application configuration. MORE may contain specifications for a subpath relative to these directories: a subpathname specification and keyword arguments as per RESOLVE-LOCATION \(see also \"Configuration DSL\"\) in the ASDF manual." (filter-pathname-set `(,(xdg-config-home more) ,@(xdg-config-dirs more)))) (defun find-preferred-file (files &key (direction :input)) "Find first file in the list of FILES that exists (for direction :input or :probe) or just the first one (for direction :output or :io). Note that when we say \"file\" here, the files in question may be directories." (find-if (ecase direction ((:probe :input) 'probe-file*) ((:output :io) 'identity)) files)) (defun xdg-data-pathname (&optional more (direction :input)) (find-preferred-file (xdg-data-pathnames more) :direction direction)) (defun xdg-config-pathname (&optional more (direction :input)) (find-preferred-file (xdg-config-pathnames more) :direction direction)) (defun compute-user-cache () "Compute (and return) the location of the default user-cache for translate-output objects. Side-effects for cached file location computation." (setf *user-cache* (xdg-cache-home "common-lisp" :implementation))) (register-image-restore-hook 'compute-user-cache) (defun uiop-directory () "Try to locate the UIOP source directory at runtime" (labels ((pf (x) (ignore-errors (probe-file* x))) (sub (x y) (pf (subpathname x y))) (ssd (x) (ignore-errors (symbol-call :asdf :system-source-directory x)))) ;; NB: conspicuously *not* including searches based on #.(current-lisp-pathname) (or ;; Look under uiop if available as source override, under asdf if avaiable as source (ssd "uiop") (sub (ssd "asdf") "uiop/") ;; Look in recommended path for user-visible source installation (sub (user-homedir-pathname) "common-lisp/asdf/uiop/") ;; Look in XDG paths under known package names for user-invisible source installation (xdg-data-pathname "common-lisp/source/asdf/uiop/") (xdg-data-pathname "common-lisp/source/cl-asdf/uiop/") ; traditional Debian location ;; The last one below is useful for Fare, primary (sole?) known user (sub (user-homedir-pathname) "cl/asdf/uiop/") (cerror "Configure source registry to include UIOP source directory and retry." "Unable to find UIOP directory") (uiop-directory))))) ;;; ------------------------------------------------------------------------- ;;; Hacks for backward-compatibility with older versions of UIOP (uiop/package:define-package :uiop/backward-driver (:recycle :uiop/backward-driver :asdf/backward-driver :uiop) (:use :uiop/common-lisp :uiop/package :uiop/utility :uiop/version :uiop/pathname :uiop/stream :uiop/os :uiop/image :uiop/run-program :uiop/lisp-build :uiop/configuration) (:export #:coerce-pathname #:user-configuration-directories #:system-configuration-directories #:in-first-directory #:in-user-configuration-directory #:in-system-configuration-directory #:version-compatible-p)) (in-package :uiop/backward-driver) (eval-when (:compile-toplevel :load-toplevel :execute) (with-deprecation ((version-deprecation *uiop-version* :style-warning "3.2" :warning "3.4")) ;; Backward compatibility with ASDF 2.000 to 2.26 ;; For backward-compatibility only, for people using internals ;; Reported users in quicklisp 2015-11: hu.dwim.asdf (removed in next release) ;; Will be removed after 2015-12. (defun coerce-pathname (name &key type defaults) "DEPRECATED. Please use UIOP:PARSE-UNIX-NAMESTRING instead." (parse-unix-namestring name :type type :defaults defaults)) ;; Backward compatibility for ASDF 2.27 to 3.1.4 (defun user-configuration-directories () "Return the current user's list of user configuration directories for configuring common-lisp. DEPRECATED. Use UIOP:XDG-CONFIG-PATHNAMES instead." (xdg-config-pathnames "common-lisp")) (defun system-configuration-directories () "Return the list of system configuration directories for common-lisp. DEPRECATED. Use UIOP:SYSTEM-CONFIG-PATHNAMES (with argument \"common-lisp\"), instead." (system-config-pathnames "common-lisp")) (defun in-first-directory (dirs x &key (direction :input)) "Finds the first appropriate file named X in the list of DIRS for I/O in DIRECTION \(which may be :INPUT, :OUTPUT, :IO, or :PROBE). If direction is :INPUT or :PROBE, will return the first extant file named X in one of the DIRS. If direction is :OUTPUT or :IO, will simply return the file named X in the first element of DIRS that exists. DEPRECATED." (find-preferred-file (mapcar #'(lambda (dir) (subpathname (ensure-directory-pathname dir) x)) dirs) :direction direction)) (defun in-user-configuration-directory (x &key (direction :input)) "Return the file named X in the user configuration directory for common-lisp. DEPRECATED." (xdg-config-pathname `("common-lisp" ,x) direction)) (defun in-system-configuration-directory (x &key (direction :input)) "Return the pathname for the file named X under the system configuration directory for common-lisp. DEPRECATED." (find-preferred-file (system-config-pathnames "common-lisp" x) :direction direction)) ;; Backward compatibility with ASDF 1 to ASDF 2.32 (defun version-compatible-p (provided-version required-version) "Is the provided version a compatible substitution for the required-version? If major versions differ, it's not compatible. If they are equal, then any later version is compatible, with later being determined by a lexicographical comparison of minor numbers. DEPRECATED." (let ((x (parse-version provided-version nil)) (y (parse-version required-version nil))) (and x y (= (car x) (car y)) (lexicographic<= '< (cdr y) (cdr x))))))) ;;;; --------------------------------------------------------------------------- ;;;; Re-export all the functionality in UIOP (uiop/package:define-package :uiop/driver (:nicknames :uiop ;; Official name we recommend should be used for all references to uiop symbols. :asdf/driver) ;; DO NOT USE, a deprecated name, not supported anymore. ;; We should remove the name :asdf/driver at some point, ;; but not until it has been eradicated from Quicklisp for a year or two. ;; The last known user was cffi (PR merged in May 2020). (:use :uiop/common-lisp) ;; NB: We are not reexporting uiop/common-lisp ;; which include all of CL with compatibility modifications on select platforms, ;; because that would cause potential conflicts for packages that ;; might want to :use (:cl :uiop) or :use (:closer-common-lisp :uiop), etc. (:use-reexport :uiop/package* :uiop/utility :uiop/version :uiop/os :uiop/pathname :uiop/filesystem :uiop/stream :uiop/image :uiop/launch-program :uiop/run-program :uiop/lisp-build :uiop/configuration :uiop/backward-driver)) ;; Provide both lowercase and uppercase, to satisfy more implementations. (provide "uiop") (provide "UIOP") ;;;; ------------------------------------------------------------------------- ;;;; Handle upgrade as forward- and backward-compatibly as possible ;; See https://bugs.launchpad.net/asdf/+bug/485687 (uiop/package:define-package :asdf/upgrade (:recycle :asdf/upgrade :asdf) (:use :uiop/common-lisp :uiop) (:export #:asdf-version #:*previous-asdf-versions* #:*asdf-version* #:asdf-message #:*verbose-out* #:upgrading-p #:when-upgrading #:upgrade-asdf #:defparameter* #:*post-upgrade-cleanup-hook* #:cleanup-upgraded-asdf ;; There will be no symbol left behind! #:with-asdf-deprecation #:intern*) (:import-from :uiop/package #:intern* #:find-symbol*)) (in-package :asdf/upgrade) ;;; Special magic to detect if this is an upgrade (with-upgradability () (defun asdf-version () "Exported interface to the version of ASDF currently installed. A string. You can compare this string with e.g.: (ASDF:VERSION-SATISFIES (ASDF:ASDF-VERSION) \"3.4.5.67\")." (when (find-package :asdf) (or (symbol-value (find-symbol (string :*asdf-version*) :asdf)) (let* ((revsym (find-symbol (string :*asdf-revision*) :asdf)) (rev (and revsym (boundp revsym) (symbol-value revsym)))) (etypecase rev (string rev) (cons (format nil "~{~D~^.~}" rev)) (null "1.0")))))) ;; This (private) variable contains a list of versions of previously loaded variants of ASDF, ;; from which ASDF was upgraded. ;; Important: define *p-a-v* /before/ *a-v* so that they initialize correctly. (defvar *previous-asdf-versions* (let ((previous (asdf-version))) (when previous ;; Punt on upgrade from ASDF1 or ASDF2, by renaming (or deleting) the package. (when (version< previous "2.27") ;; 2.27 is the first to have the :asdf3 feature. (let ((away (format nil "~A-~A" :asdf previous))) (rename-package :asdf away) (when *load-verbose* (format t "~&; Renamed old ~A package away to ~A~%" :asdf away)))) (list previous)))) ;; This public variable will be bound shortly to the currently loaded version of ASDF. (defvar *asdf-version* nil) ;; We need to clear systems from versions older than the one in this (private) parameter. ;; The latest incompatible defclass is 2.32.13 renaming a slot in component, ;; or 3.2.0.2 for CCL (incompatibly changing some superclasses). ;; the latest incompatible gf change is in 3.1.7.20 (see redefined-functions below). (defparameter *oldest-forward-compatible-asdf-version* "3.2.0.2") ;; Semi-private variable: a designator for a stream on which to output ASDF progress messages (defvar *verbose-out* nil) ;; Private function by which ASDF outputs progress messages and warning messages: (defun asdf-message (format-string &rest format-args) (when *verbose-out* (apply 'format *verbose-out* format-string format-args))) ;; Private hook for functions to run after ASDF has upgraded itself from an older variant: (defvar *post-upgrade-cleanup-hook* ()) ;; Private variable for post upgrade cleanup to communicate if an upgrade has ;; actually occured. (defvar *asdf-upgraded-p*) ;; Private function to detect whether the current upgrade counts as an incompatible ;; data schema upgrade implying the need to drop data. (defun upgrading-p (&optional (oldest-compatible-version *oldest-forward-compatible-asdf-version*)) (and *previous-asdf-versions* (version< (first *previous-asdf-versions*) oldest-compatible-version))) ;; Private variant of defparameter that works in presence of incompatible upgrades: ;; behaves like defvar in a compatible upgrade (e.g. reloading system after simple code change), ;; but behaves like defparameter if in presence of an incompatible upgrade. (defmacro defparameter* (var value &optional docstring (version *oldest-forward-compatible-asdf-version*)) (let* ((name (string-trim "*" var)) (valfun (intern (format nil "%~A-~A-~A" :compute name :value)))) `(progn (defun ,valfun () ,value) (defvar ,var (,valfun) ,@(ensure-list docstring)) (when (upgrading-p ,version) (setf ,var (,valfun)))))) ;; Private macro to declare sections of code that are only compiled and run when upgrading. ;; The use of eval portably ensures that the code will not have adverse compile-time side-effects, ;; whereas the use of handler-bind portably ensures that it will not issue warnings when it runs. (defmacro when-upgrading ((&key (version *oldest-forward-compatible-asdf-version*) (upgrading-p `(upgrading-p ,version)) when) &body body) "A wrapper macro for code that should only be run when upgrading a previously-loaded version of ASDF." `(with-upgradability () (when (and ,upgrading-p ,@(when when `(,when))) (handler-bind ((style-warning #'muffle-warning)) (eval '(progn ,@body)))))) ;; Only now can we safely update the version. (let* (;; For bug reporting sanity, please always bump this version when you modify this file. ;; Please also modify asdf.asd to reflect this change. make bump-version v=3.4.5.67.8 ;; can help you do these changes in synch (look at the source for documentation). ;; Relying on its automation, the version is now redundantly present on top of asdf.lisp. ;; "3.4" would be the general branch for major version 3, minor version 4. ;; "3.4.5" would be an official release in the 3.4 branch. ;; "3.4.5.67" would be a development version in the official branch, on top of 3.4.5. ;; "3.4.5.0.8" would be your eighth local modification of official release 3.4.5 ;; "3.4.5.67.8" would be your eighth local modification of development version 3.4.5.67 (asdf-version "3.3.5.7") (existing-version (asdf-version))) (setf *asdf-version* asdf-version) (when (and existing-version (not (equal asdf-version existing-version))) (push existing-version *previous-asdf-versions*) (when (or *verbose-out* *load-verbose*) (format (or *verbose-out* *trace-output*) (compatfmt "~&~@<; ~@;Upgrading ASDF ~@[from version ~A ~]to version ~A~@:>~%") existing-version asdf-version))))) ;;; Upon upgrade, specially frob some functions and classes that are being incompatibly redefined (when-upgrading () (let* ((previous-version (first *previous-asdf-versions*)) (redefined-functions ;; List of functions that changed incompatibly since 2.27: ;; gf signature changed, defun that became a generic function (but not way around), ;; method removed that will mess up with new ones ;; (especially :around :before :after, more specific or call-next-method'ed method) ;; and/or semantics otherwise modified. Oops. ;; NB: it's too late to do anything about functions in UIOP! ;; If you introduce some critical incompatibility there, you MUST change the function name. ;; Note that we don't need do anything about functions that changed incompatibly ;; from ASDF 2.26 or earlier: we wholly punt on the entire ASDF package in such an upgrade. ;; Also, the strong constraints apply most importantly for functions called from ;; the continuation of compiling or loading some of the code in ASDF or UIOP. ;; See discussion at https://gitlab.common-lisp.net/asdf/asdf/merge_requests/36 ;; and at https://gitlab.common-lisp.net/asdf/asdf/-/merge_requests/141 `(,@(when (version< previous-version "2.31") '(#:normalize-version)) ;; pathname became &key ,@(when (version< previous-version "3.1.2") '(#:component-depends-on #:input-files)) ;; crucial methods *removed* before 3.1.2 ,@(when (version< previous-version "3.1.7.20") '(#:find-component)))) ;; added &key registered (redefined-classes ;; with the old ASDF during upgrade, and many implementations bork (when (or #+(or clozure mkcl) t) '((#:compile-concatenated-source-op (#:operation) ()) (#:compile-bundle-op (#:operation) ()) (#:concatenate-source-op (#:operation) ()) (#:dll-op (#:operation) ()) (#:lib-op (#:operation) ()) (#:monolithic-compile-bundle-op (#:operation) ()) (#:monolithic-concatenate-source-op (#:operation) ()))))) (loop :for name :in redefined-functions :for sym = (find-symbol* name :asdf nil) :do (when sym (fmakunbound sym))) (labels ((asym (x) (multiple-value-bind (s p) (if (consp x) (values (car x) (cadr x)) (values x :asdf)) (find-symbol* s p nil))) (asyms (l) (mapcar #'asym l))) (loop :for (name superclasses slots) :in redefined-classes :for sym = (find-symbol* name :asdf nil) :when (and sym (find-class sym)) :do #+ccl (eval `(defclass ,sym ,(asyms superclasses) ,(asyms slots))) #-ccl (setf (find-class sym) nil))))) ;; mkcl ;;; Self-upgrade functions (with-upgradability () ;; This private function is called at the end of asdf/footer and ensures that, ;; *if* this loading of ASDF was an upgrade, then all registered cleanup functions will be called. (defun cleanup-upgraded-asdf (&optional (old-version (first *previous-asdf-versions*))) (let ((new-version (asdf-version))) (unless (equal old-version new-version) (push new-version *previous-asdf-versions*) (when (boundp '*asdf-upgraded-p*) (setf *asdf-upgraded-p* t)) (when old-version (if (version<= new-version old-version) (error (compatfmt "~&~@<; ~@;Downgraded ASDF from version ~A to version ~A~@:>~%") old-version new-version) (asdf-message (compatfmt "~&~@<; ~@;Upgraded ASDF from version ~A to version ~A~@:>~%") old-version new-version)) ;; In case the previous version was too old to be forward-compatible, clear systems. ;; TODO: if needed, we may have to define a separate hook to run ;; in case of forward-compatible upgrade. ;; Or to move the tests forward-compatibility test inside each hook function? (unless (version<= *oldest-forward-compatible-asdf-version* old-version) (call-functions (reverse *post-upgrade-cleanup-hook*))) t)))) (defun upgrade-asdf () "Try to upgrade of ASDF. If a different version was used, return T. We need do that before we operate on anything that may possibly depend on ASDF." (let ((*load-print* nil) (*compile-print* nil) (*asdf-upgraded-p* nil)) (handler-bind (((or style-warning) #'muffle-warning)) (symbol-call :asdf :load-system :asdf :verbose nil)) *asdf-upgraded-p*)) (defmacro with-asdf-deprecation ((&rest keys &key &allow-other-keys) &body body) `(with-upgradability () (with-deprecation ((version-deprecation *asdf-version* ,@keys)) ,@body)))) ;;;; ------------------------------------------------------------------------- ;;;; Session (uiop/package:define-package :asdf/session (:recycle :asdf/session :asdf/cache :asdf/component :asdf/action :asdf/find-system :asdf/plan :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade) (:export #:get-file-stamp #:compute-file-stamp #:register-file-stamp #:asdf-cache #:set-asdf-cache-entry #:unset-asdf-cache-entry #:consult-asdf-cache #:do-asdf-cache #:normalize-namestring #:call-with-asdf-session #:with-asdf-session #:*asdf-session* #:*asdf-session-class* #:session #:toplevel-asdf-session #:session-cache #:forcing #:asdf-upgraded-p #:visited-actions #:visiting-action-set #:visiting-action-list #:total-action-count #:planned-action-count #:planned-output-action-count #:clear-configuration-and-retry #:retry #:operate-level ;; conditions #:system-definition-error ;; top level, moved here because this is the earliest place for it. #:formatted-system-definition-error #:format-control #:format-arguments #:sysdef-error)) (in-package :asdf/session) (with-upgradability () ;; The session variable. ;; NIL when outside a session. (defvar *asdf-session* nil) (defparameter* *asdf-session-class* 'session "The default class for sessions") (defclass session () (;; The ASDF session cache is used to memoize some computations. ;; It is instrumental in achieving: ;; * Consistency in the view of the world relied on by ASDF within a given session. ;; Inconsistencies in file stamps, system definitions, etc., could cause infinite loops ;; (a.k.a. stack overflows) and other erratic behavior. ;; * Speed and reliability of ASDF, with fewer side-effects from access to the filesystem, and ;; no expensive recomputations of transitive dependencies for input-files or output-files. ;; * Testability of ASDF with the ability to fake timestamps without actually touching files. (ancestor :initform nil :initarg :ancestor :reader session-ancestor :documentation "Top level session that this is part of") (session-cache :initform (make-hash-table :test 'equal) :initarg :session-cache :reader session-cache :documentation "Memoize expensive computations") (operate-level :initform 0 :initarg :operate-level :accessor session-operate-level :documentation "Number of nested calls to operate we're under (for toplevel session only)") ;; shouldn't the below be superseded by the session-wide caching of action-status ;; for (load-op "asdf") ? (asdf-upgraded-p :initform nil :initarg :asdf-upgraded-p :accessor asdf-upgraded-p :documentation "Was ASDF already upgraded in this session - only valid for toplevel-asdf-session.") (forcing :initform nil :initarg :forcing :accessor forcing :documentation "Forcing parameters for the session") ;; Table that to actions already visited while walking the dependencies associates status (visited-actions :initform (make-hash-table :test 'equal) :accessor visited-actions) ;; Actions that depend on those being currently walked through, to detect circularities (visiting-action-set ;; as a set :initform (make-hash-table :test 'equal) :accessor visiting-action-set) (visiting-action-list :initform () :accessor visiting-action-list) ;; as a list ;; Counts of total actions in plan (total-action-count :initform 0 :accessor total-action-count) ;; Count of actions that need to be performed (planned-action-count :initform 0 :accessor planned-action-count) ;; Count of actions that need to be performed that have a non-empty list of output-files. (planned-output-action-count :initform 0 :accessor planned-output-action-count)) (:documentation "An ASDF session with a cache to memoize some computations")) (defun toplevel-asdf-session () (when *asdf-session* (or (session-ancestor *asdf-session*) *asdf-session*))) (defun operate-level () (session-operate-level (toplevel-asdf-session))) (defun (setf operate-level) (new-level) (setf (session-operate-level (toplevel-asdf-session)) new-level)) (defun asdf-cache () (session-cache *asdf-session*)) ;; Set a session cache entry for KEY to a list of values VALUE-LIST, when inside a session. ;; Return those values. (defun set-asdf-cache-entry (key value-list) (values-list (if *asdf-session* (setf (gethash key (asdf-cache)) value-list) value-list))) ;; Unset the session cache entry for KEY, when inside a session. (defun unset-asdf-cache-entry (key) (when *asdf-session* (remhash key (session-cache *asdf-session*)))) ;; Consult the session cache entry for KEY if present and in a session; ;; if not present, compute it by calling the THUNK, ;; and set the session cache entry accordingly, if in a session. ;; Return the values from the cache and/or the thunk computation. (defun consult-asdf-cache (key &optional thunk) (if *asdf-session* (multiple-value-bind (results foundp) (gethash key (session-cache *asdf-session*)) (if foundp (values-list results) (set-asdf-cache-entry key (multiple-value-list (call-function thunk))))) (call-function thunk))) ;; Syntactic sugar for consult-asdf-cache (defmacro do-asdf-cache (key &body body) `(consult-asdf-cache ,key #'(lambda () ,@body))) ;; Compute inside a ASDF session with a cache. ;; First, make sure an ASDF session is underway, by binding the session cache variable ;; to a new hash-table if it's currently null (or even if it isn't, if OVERRIDE is true). ;; Second, if a new session was started, establish restarts for retrying the overall computation. ;; Finally, consult the cache if a KEY was specified with the THUNK as a fallback when the cache ;; entry isn't found, or just call the THUNK if no KEY was specified. (defun call-with-asdf-session (thunk &key override key override-cache override-forcing) (let ((fun (if key #'(lambda () (consult-asdf-cache key thunk)) thunk))) (if (and (not override) *asdf-session*) (funcall fun) (loop (restart-case (let ((*asdf-session* (apply 'make-instance *asdf-session-class* (when *asdf-session* `(:ancestor ,(toplevel-asdf-session) ,@(unless override-forcing `(:forcing ,(forcing *asdf-session*))) ,@(unless override-cache `(:session-cache ,(session-cache *asdf-session*)))))))) (return (funcall fun))) (retry () :report (lambda (s) (format s (compatfmt "~@")))) (clear-configuration-and-retry () :report (lambda (s) (format s (compatfmt "~@"))) (unless (null *asdf-session*) (clrhash (session-cache *asdf-session*))) (clear-configuration))))))) ;; Syntactic sugar for call-with-asdf-session (defmacro with-asdf-session ((&key key override override-cache override-forcing) &body body) `(call-with-asdf-session #'(lambda () ,@body) :override ,override :key ,key :override-cache ,override-cache :override-forcing ,override-forcing)) ;;; Define specific accessor for file (date) stamp. ;; Normalize a namestring for use as a key in the session cache. (defun normalize-namestring (pathname) (let ((resolved (resolve-symlinks* (ensure-absolute-pathname (physicalize-pathname pathname) 'get-pathname-defaults)))) (with-pathname-defaults () (namestring resolved)))) ;; Compute the file stamp for a normalized namestring (defun compute-file-stamp (normalized-namestring) (with-pathname-defaults () (or (safe-file-write-date normalized-namestring) t))) ;; Override the time STAMP associated to a given FILE in the session cache. ;; If no STAMP is specified, recompute a new one from the filesystem. (defun register-file-stamp (file &optional (stamp nil stampp)) (let* ((namestring (normalize-namestring file)) (stamp (if stampp stamp (compute-file-stamp namestring)))) (set-asdf-cache-entry `(get-file-stamp ,namestring) (list stamp)))) ;; Get or compute a memoized stamp for given FILE from the session cache. (defun get-file-stamp (file) (when file (let ((namestring (normalize-namestring file))) (do-asdf-cache `(get-file-stamp ,namestring) (compute-file-stamp namestring))))) ;;; Conditions (define-condition system-definition-error (error) () ;; [this use of :report should be redundant, but unfortunately it's not. ;; cmucl's lisp::output-instance prefers the kernel:slot-class-print-function ;; over print-object; this is always conditions::%print-condition for ;; condition objects, which in turn does inheritance of :report options at ;; run-time. fortunately, inheritance means we only need this kludge here in ;; order to fix all conditions that build on it. -- rgr, 28-Jul-02.] #+cmucl (:report print-object)) (define-condition formatted-system-definition-error (system-definition-error) ((format-control :initarg :format-control :reader format-control) (format-arguments :initarg :format-arguments :reader format-arguments)) (:report (lambda (c s) (apply 'format s (format-control c) (format-arguments c))))) (defun sysdef-error (format &rest arguments) (error 'formatted-system-definition-error :format-control format :format-arguments arguments))) ;;;; ------------------------------------------------------------------------- ;;;; Components (uiop/package:define-package :asdf/component (:recycle :asdf/component :asdf/find-component :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session) (:export #:component #:component-find-path #:find-component ;; methods defined in find-component #:component-name #:component-pathname #:component-relative-pathname #:component-parent #:component-system #:component-parent-pathname #:child-component #:parent-component #:module #:file-component #:source-file #:c-source-file #:java-source-file #:static-file #:doc-file #:html-file #:file-type #:source-file-type #:source-file-explicit-type ;; backward-compatibility #:component-in-order-to #:component-sideway-dependencies #:component-if-feature #:around-compile-hook #:component-description #:component-long-description #:component-version #:version-satisfies #:component-inline-methods ;; backward-compatibility only. DO NOT USE! #:component-operation-times ;; For internal use only. ;; portable ASDF encoding and implementation-specific external-format #:component-external-format #:component-encoding #:component-children-by-name #:component-children #:compute-children-by-name #:component-build-operation #:module-default-component-class #:module-components ;; backward-compatibility. DO NOT USE. #:sub-components ;; conditions #:duplicate-names ;; Internals we'd like to share with the ASDF package, especially for upgrade purposes #:name #:version #:description #:long-description #:author #:maintainer #:licence #:components-by-name #:components #:children #:children-by-name #:default-component-class #:source-file #:defsystem-depends-on ; This symbol retained for backward compatibility. #:sideway-dependencies #:if-feature #:in-order-to #:inline-methods #:relative-pathname #:absolute-pathname #:operation-times #:around-compile #:%encoding #:properties #:component-properties #:parent)) (in-package :asdf/component) (with-upgradability () (defgeneric component-name (component) (:documentation "Name of the COMPONENT, unique relative to its parent")) (defgeneric component-system (component) (:documentation "Top-level system containing the COMPONENT")) (defgeneric component-pathname (component) (:documentation "Pathname of the COMPONENT if any, or NIL.")) (defgeneric component-relative-pathname (component) ;; in ASDF4, rename that to component-specified-pathname ? (:documentation "Specified pathname of the COMPONENT, intended to be merged with the pathname of that component's parent if any, using merged-pathnames*. Despite the function's name, the return value can be an absolute pathname, in which case the merge will leave it unmodified.")) (defgeneric component-external-format (component) (:documentation "The external-format of the COMPONENT. By default, deduced from the COMPONENT-ENCODING.")) (defgeneric component-encoding (component) (:documentation "The encoding of the COMPONENT. By default, only :utf-8 is supported. Use asdf-encodings to support more encodings.")) (defgeneric version-satisfies (component version) (:documentation "Check whether a COMPONENT satisfies the constraint of being at least as recent as the specified VERSION, which must be a string of dot-separated natural numbers, or NIL.")) (defgeneric component-version (component) (:documentation "Return the version of a COMPONENT, which must be a string of dot-separated natural numbers, or NIL.")) (defgeneric (setf component-version) (new-version component) (:documentation "Updates the version of a COMPONENT, which must be a string of dot-separated natural numbers, or NIL.")) (defgeneric component-parent (component) (:documentation "The parent of a child COMPONENT, or NIL for top-level components (a.k.a. systems)")) ;; NIL is a designator for the absence of a component, in which case the parent is also absent. (defmethod component-parent ((component null)) nil) ;; Deprecated: Backward compatible way of computing the FILE-TYPE of a component. (with-asdf-deprecation (:style-warning "3.4") (defgeneric source-file-type (component system) (:documentation "DEPRECATED. Use the FILE-TYPE of a COMPONENT instead."))) (define-condition duplicate-names (system-definition-error) ((name :initarg :name :reader duplicate-names-name)) (:report (lambda (c s) (format s (compatfmt "~@") (duplicate-names-name c)))))) (with-upgradability () (defclass component () ((name :accessor component-name :initarg :name :type string :documentation "Component name: designator for a string composed of portable pathname characters") ;; We might want to constrain version with ;; :type (and string (satisfies parse-version)) ;; but we cannot until we fix all systems that don't use it correctly! (version :accessor component-version :initarg :version :initform nil) (description :accessor component-description :initarg :description :initform nil) (long-description :accessor component-long-description :initarg :long-description :initform nil) (sideway-dependencies :accessor component-sideway-dependencies :initform nil) (if-feature :accessor component-if-feature :initform nil :initarg :if-feature) ;; In the ASDF object model, dependencies exist between *actions*, ;; where an action is a pair of an operation and a component. ;; Dependencies are represented as alists of operations ;; to a list where each entry is a pair of an operation and a list of component specifiers. ;; Up until ASDF 2.26.9, there used to be two kinds of dependencies: ;; in-order-to and do-first, each stored in its own slot. Now there is only in-order-to. ;; in-order-to used to represent things that modify the filesystem (such as compiling a fasl) ;; and do-first things that modify the current image (such as loading a fasl). ;; These are now unified because we now correctly propagate timestamps between dependencies. ;; Happily, no one seems to have used do-first too much (especially since until ASDF 2.017, ;; anything you specified was overridden by ASDF itself anyway), but the name in-order-to remains. ;; The names are bad, but they have been the official API since Dan Barlow's ASDF 1.52! ;; LispWorks's defsystem has caused-by and requires for in-order-to and do-first respectively. ;; Maybe rename the slots in ASDF? But that's not very backward-compatible. ;; See our ASDF 2 paper for more complete explanations. (in-order-to :initform nil :initarg :in-order-to :accessor component-in-order-to) ;; Methods defined using the "inline" style inside a defsystem form: ;; we store them here so we can delete them when the system is re-evaluated. (inline-methods :accessor component-inline-methods :initform nil) ;; ASDF4: rename it from relative-pathname to specified-pathname. It need not be relative. ;; There is no initform and no direct accessor for this specified pathname, ;; so we only access the information through appropriate methods, after it has been processed. ;; Unhappily, some braindead systems directly access the slot. Make them stop before ASDF4. (relative-pathname :initarg :pathname) ;; The absolute-pathname is computed based on relative-pathname and parent pathname. ;; The slot is but a cache used by component-pathname. (absolute-pathname) (operation-times :initform (make-hash-table) :accessor component-operation-times) (around-compile :initarg :around-compile) ;; Properties are for backward-compatibility with ASDF2 only. DO NOT USE! (properties :accessor component-properties :initarg :properties :initform nil) (%encoding :accessor %component-encoding :initform nil :initarg :encoding) ;; For backward-compatibility, this slot is part of component rather than of child-component. ASDF4: stop it. (parent :initarg :parent :initform nil :reader component-parent) (build-operation :initarg :build-operation :initform nil :reader component-build-operation) ;; Cache for ADDITIONAL-INPUT-FILES function. (additional-input-files :accessor %additional-input-files :initform nil)) (:documentation "Base class for all components of a build")) (defgeneric find-component (base path &key registered) (:documentation "Find a component by resolving the PATH starting from BASE parent. If REGISTERED is true, only search currently registered systems.")) (defun component-find-path (component) "Return a path from a root system to the COMPONENT. The return value is a list of component NAMES; a list of strings." (check-type component (or null component)) (reverse (loop :for c = component :then (component-parent c) :while c :collect (component-name c)))) (defmethod print-object ((c component) stream) (print-unreadable-object (c stream :type t :identity nil) (format stream "~{~S~^ ~}" (component-find-path c)))) (defmethod component-system ((component component)) (if-let (system (component-parent component)) (component-system system) component))) ;;;; Component hierarchy within a system ;; The tree typically but not necessarily follows the filesystem hierarchy. (with-upgradability () (defclass child-component (component) () (:documentation "A CHILD-COMPONENT is a COMPONENT that may be part of a PARENT-COMPONENT.")) (defclass file-component (child-component) ((type :accessor file-type :initarg :type)) ; no default (:documentation "a COMPONENT that represents a file")) (defclass source-file (file-component) ((type :accessor source-file-explicit-type ;; backward-compatibility :initform nil))) ;; NB: many systems have come to rely on this default. (defclass c-source-file (source-file) ((type :initform "c"))) (defclass java-source-file (source-file) ((type :initform "java"))) (defclass static-file (source-file) ((type :initform nil)) (:documentation "Component for a file to be included as is in the build output")) (defclass doc-file (static-file) ()) (defclass html-file (doc-file) ((type :initform "html"))) (defclass parent-component (component) ((children :initform nil :initarg :components :reader module-components ; backward-compatibility :accessor component-children) (children-by-name :reader module-components-by-name ; backward-compatibility :accessor component-children-by-name) (default-component-class :initform nil :initarg :default-component-class :accessor module-default-component-class)) (:documentation "A PARENT-COMPONENT is a component that may have children."))) (with-upgradability () ;; (Private) Function that given a PARENT component, ;; the list of children of which has been initialized, ;; compute the hash-table in slot children-by-name that allows to retrieve its children by name. ;; If ONLY-IF-NEEDED-P is defined, skip any (re)computation if the slot is already populated. (defun compute-children-by-name (parent &key only-if-needed-p) (unless (and only-if-needed-p (slot-boundp parent 'children-by-name)) (let ((hash (make-hash-table :test 'equal))) (setf (component-children-by-name parent) hash) (loop :for c :in (component-children parent) :for name = (component-name c) :for previous = (gethash name hash) :do (when previous (error 'duplicate-names :name name)) (setf (gethash name hash) c)) hash)))) (with-upgradability () (defclass module (child-component parent-component) (#+clisp (components)) ;; backward compatibility during upgrade only (:documentation "A module is a intermediate component with both a parent and children, typically but not necessarily representing the files in a subdirectory of the build source."))) ;;;; component pathnames (with-upgradability () (defgeneric component-parent-pathname (component) (:documentation "The pathname of the COMPONENT's parent, if any, or NIL")) (defmethod component-parent-pathname (component) (component-pathname (component-parent component))) ;; The default method for component-pathname tries to extract a cached precomputed ;; absolute-pathname from the relevant slot, and if not, computes it by merging the ;; component-relative-pathname (which should be component-specified-pathname, it can be absolute) ;; with the directory of the component-parent-pathname. (defmethod component-pathname ((component component)) (if (slot-boundp component 'absolute-pathname) (slot-value component 'absolute-pathname) (let ((pathname (merge-pathnames* (component-relative-pathname component) (pathname-directory-pathname (component-parent-pathname component))))) (unless (or (null pathname) (absolute-pathname-p pathname)) (error (compatfmt "~@") pathname (component-find-path component))) (setf (slot-value component 'absolute-pathname) pathname) pathname))) ;; Default method for component-relative-pathname: ;; combine the contents of slot relative-pathname (from specified initarg :pathname) ;; with the appropriate source-file-type, which defaults to the file-type of the component. (defmethod component-relative-pathname ((component component)) ;; SOURCE-FILE-TYPE below is strictly for backward-compatibility with ASDF1. ;; We ought to be able to extract this from the component alone with FILE-TYPE. ;; TODO: track who uses it in Quicklisp, and have them not use it anymore; ;; maybe issue a WARNING (then eventually CERROR) if the two methods diverge? (let (#+abcl (parent (component-parent-pathname component))) (parse-unix-namestring (or (and (slot-boundp component 'relative-pathname) (slot-value component 'relative-pathname)) (component-name component)) :want-relative #-abcl t ;; JAR-PATHNAMES always have absolute directories #+abcl (not (ext:pathname-jar-p parent)) :type (source-file-type component (component-system component)) :defaults (component-parent-pathname component)))) (defmethod source-file-type ((component parent-component) (system parent-component)) :directory) (defmethod source-file-type ((component file-component) (system parent-component)) (file-type component))) ;;;; Encodings (with-upgradability () (defmethod component-encoding ((c component)) (or (loop :for x = c :then (component-parent x) :while x :thereis (%component-encoding x)) (detect-encoding (component-pathname c)))) (defmethod component-external-format ((c component)) (encoding-external-format (component-encoding c)))) ;;;; around-compile-hook (with-upgradability () (defgeneric around-compile-hook (component) (:documentation "An optional hook function that will be called with one argument, a thunk. The hook function must call the thunk, that will compile code from the component, and may or may not also evaluate the compiled results. The hook function may establish dynamic variable bindings around this compilation, or check its results, etc.")) (defmethod around-compile-hook ((c component)) (cond ((slot-boundp c 'around-compile) (slot-value c 'around-compile)) ((component-parent c) (around-compile-hook (component-parent c)))))) ;;;; version-satisfies (with-upgradability () ;; short-circuit testing of null version specifications. ;; this is an all-pass, without warning (defmethod version-satisfies :around ((c t) (version null)) t) (defmethod version-satisfies ((c component) version) (unless (and version (slot-boundp c 'version) (component-version c)) (when version (warn "Requested version ~S but ~S has no version" version c)) (return-from version-satisfies nil)) (version-satisfies (component-version c) version)) (defmethod version-satisfies ((cver string) version) (version<= version cver))) ;;; all sub-components (of a given type) (with-upgradability () (defun sub-components (component &key (type t)) "Compute the transitive sub-components of given COMPONENT that are of given TYPE" (while-collecting (c) (labels ((recurse (x) (when (if-let (it (component-if-feature x)) (featurep it) t) (when (typep x type) (c x)) (when (typep x 'parent-component) (map () #'recurse (component-children x)))))) (recurse component))))) ;;;; ------------------------------------------------------------------------- ;;;; Operations (uiop/package:define-package :asdf/operation (:recycle :asdf/operation :asdf/action :asdf) ;; asdf/action for FEATURE pre 2.31.5. (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session) (:export #:operation #:*operations* #:make-operation #:find-operation #:feature)) ;; TODO: stop exporting the deprecated FEATURE feature. (in-package :asdf/operation) ;;; Operation Classes (when-upgrading (:version "2.27" :when (find-class 'operation nil)) ;; override any obsolete shared-initialize method when upgrading from ASDF2. (defmethod shared-initialize :after ((o operation) (slot-names t) &key) (values))) (with-upgradability () (defclass operation () () (:documentation "The base class for all ASDF operations. ASDF does NOT and never did distinguish between multiple operations of the same class. Therefore, all slots of all operations MUST have :allocation :class and no initargs. No exceptions. ")) (defvar *in-make-operation* nil) (defun check-operation-constructor () "Enforce that OPERATION instances must be created with MAKE-OPERATION." (unless *in-make-operation* (sysdef-error "OPERATION instances must only be created through MAKE-OPERATION."))) (defmethod print-object ((o operation) stream) (print-unreadable-object (o stream :type t :identity nil))) ;;; Override previous methods (from 3.1.7 and earlier) and add proper error checking. #-genera ;; Genera adds its own system initargs, e.g. clos-internals:storage-area 8 (defmethod initialize-instance :after ((o operation) &rest initargs &key &allow-other-keys) (unless (null initargs) (parameter-error "~S does not accept initargs" 'operation)))) ;;; make-operation, find-operation (with-upgradability () ;; A table to memoize instances of a given operation. There shall be only one. (defparameter* *operations* (make-hash-table :test 'equal)) ;; A memoizing way of creating instances of operation. (defun make-operation (operation-class) "This function creates and memoizes an instance of OPERATION-CLASS. All operation instances MUST be created through this function. Use of INITARGS is not supported at this time." (let ((class (coerce-class operation-class :package :asdf/interface :super 'operation :error 'sysdef-error)) (*in-make-operation* t)) (ensure-gethash class *operations* `(make-instance ,class)))) ;; This function is mostly for backward and forward compatibility: ;; operations used to preserve the operation-original-initargs of the context, ;; and may in the future preserve some operation-canonical-initargs. ;; Still, the treatment of NIL as a disabling context is useful in some cases. (defgeneric find-operation (context spec) (:documentation "Find an operation by resolving the SPEC in the CONTEXT")) (defmethod find-operation ((context t) (spec operation)) spec) (defmethod find-operation ((context t) (spec symbol)) (when spec ;; NIL designates itself, i.e. absence of operation (make-operation spec))) ;; TODO: preserve the (operation-canonical-initargs context) (defmethod find-operation ((context t) (spec string)) (make-operation spec))) ;; TODO: preserve the (operation-canonical-initargs context) ;;;; ------------------------------------------------------------------------- ;;;; Systems (uiop/package:define-package :asdf/system (:recycle :asdf :asdf/system :asdf/find-system) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component) (:export #:system #:proto-system #:undefined-system #:reset-system-class #:system-source-file #:system-source-directory #:system-relative-pathname #:system-description #:system-long-description #:system-author #:system-maintainer #:system-licence #:system-license #:system-version #:definition-dependency-list #:definition-dependency-set #:system-defsystem-depends-on #:system-depends-on #:system-weakly-depends-on #:component-build-pathname #:build-pathname #:component-entry-point #:entry-point #:homepage #:system-homepage #:bug-tracker #:system-bug-tracker #:mailto #:system-mailto #:long-name #:system-long-name #:source-control #:system-source-control #:coerce-name #:primary-system-name #:primary-system-p #:coerce-filename #:find-system #:builtin-system-p)) ;; forward-reference, defined in find-system (in-package :asdf/system) (with-upgradability () ;; The method is actually defined in asdf/find-system, ;; but we declare the function here to avoid a forward reference. (defgeneric find-system (system &optional error-p) (:documentation "Given a system designator, find the actual corresponding system object. If no system is found, then signal an error if ERROR-P is true (the default), or else return NIL. A system designator is usually a string (conventionally all lowercase) or a symbol, designating the same system as its downcased name; it can also be a system object (designating itself).")) (defgeneric system-source-file (system) (:documentation "Return the source file in which system is defined.")) ;; This is bad design, but was the easiest kluge I found to let the user specify that ;; some special actions create outputs at locations controled by the user that are not affected ;; by the usual output-translations. ;; TODO: Fix operate to stop passing flags to operation (which in the current design shouldn't ;; have any flags, since the stamp cache, etc., can't distinguish them), and instead insert ;; *there* the ability of specifying special output paths, not in the system definition. (defgeneric component-build-pathname (component) (:documentation "The COMPONENT-BUILD-PATHNAME, when defined and not null, specifies the output pathname for the action using the COMPONENT-BUILD-OPERATION. NB: This interface is subject to change. Please contact ASDF maintainers if you use it.")) ;; TODO: Should this have been made a SYSTEM-ENTRY-POINT instead? (defgeneric component-entry-point (component) (:documentation "The COMPONENT-ENTRY-POINT, when defined, specifies what function to call (with no argument) when running an image dumped from the COMPONENT. NB: This interface is subject to change. Please contact ASDF maintainers if you use it.")) (defmethod component-entry-point ((c component)) nil)) ;;;; The system class (with-upgradability () (defclass proto-system () ; slots to keep when resetting a system ;; To preserve identity for all objects, we'd need keep the components slots ;; but also to modify parse-component-form to reset the recycled objects. ((name) (source-file) ;; These two slots contains the *inferred* dependencies of define-op, ;; from loading the .asd file, as list and as set. (definition-dependency-list :initform nil :accessor definition-dependency-list) (definition-dependency-set :initform (list-to-hash-set nil) :accessor definition-dependency-set)) (:documentation "PROTO-SYSTEM defines the elements of identity that are preserved when a SYSTEM is redefined and its class is modified.")) (defclass system (module proto-system) ;; Backward-compatibility: inherit from module. ASDF4: only inherit from parent-component. (;; {,long-}description is now inherited from component, but we add the legacy accessors (description :writer (setf system-description)) (long-description :writer (setf system-long-description)) (author :writer (setf system-author) :initarg :author :initform nil) (maintainer :writer (setf system-maintainer) :initarg :maintainer :initform nil) (licence :writer (setf system-licence) :initarg :licence :writer (setf system-license) :initarg :license :initform nil) (homepage :writer (setf system-homepage) :initarg :homepage :initform nil) (bug-tracker :writer (setf system-bug-tracker) :initarg :bug-tracker :initform nil) (mailto :writer (setf system-mailto) :initarg :mailto :initform nil) (long-name :writer (setf system-long-name) :initarg :long-name :initform nil) ;; Conventions for this slot aren't clear yet as of ASDF 2.27, but whenever they are, they will be enforced. ;; I'm introducing the slot before the conventions are set for maximum compatibility. (source-control :writer (setf system-source-control) :initarg :source-control :initform nil) (builtin-system-p :accessor builtin-system-p :initform nil :initarg :builtin-system-p) (build-pathname :initform nil :initarg :build-pathname :accessor component-build-pathname) (entry-point :initform nil :initarg :entry-point :accessor component-entry-point) (source-file :initform nil :initarg :source-file :accessor system-source-file) ;; This slot contains the *declared* defsystem-depends-on dependencies (defsystem-depends-on :reader system-defsystem-depends-on :initarg :defsystem-depends-on :initform nil) ;; these two are specially set in parse-component-form, so have no :INITARGs. (depends-on :reader system-depends-on :initform nil) (weakly-depends-on :reader system-weakly-depends-on :initform nil)) (:documentation "SYSTEM is the base class for top-level components that users may request ASDF to build.")) (defclass undefined-system (system) () (:documentation "System that was not defined yet.")) (defun reset-system-class (system new-class &rest keys &key &allow-other-keys) "Erase any data from a SYSTEM except its basic identity, then reinitialize it based on supplied KEYS." (change-class (change-class system 'proto-system) new-class) (apply 'reinitialize-instance system keys))) ;;; Canonicalizing system names (with-upgradability () (defun coerce-name (name) "Given a designator for a component NAME, return the name as a string. The designator can be a COMPONENT (designing its name; note that a SYSTEM is a component), a SYMBOL (designing its name, downcased), or a STRING (designing itself)." (typecase name (component (component-name name)) (symbol (string-downcase name)) (string name) (t (sysdef-error (compatfmt "~@") name)))) (defun primary-system-name (system-designator) "Given a system designator NAME, return the name of the corresponding primary system, after which the .asd file in which it is defined is named. If given a string or symbol (to downcase), do it syntactically by stripping anything from the first slash on. If given a component, do it semantically by extracting the system-primary-system-name of its system from its source-file if any, falling back to the syntactic criterion if none." (etypecase system-designator (string (if-let (p (position #\/ system-designator)) (subseq system-designator 0 p) system-designator)) (symbol (primary-system-name (coerce-name system-designator))) (component (let* ((system (component-system system-designator)) (source-file (physicalize-pathname (system-source-file system)))) (if source-file (and (equal (pathname-type source-file) "asd") (pathname-name source-file)) (primary-system-name (component-name system))))))) (defun primary-system-p (system) "Given a system designator SYSTEM, return T if it designates a primary system, or else NIL. If given a string, do it syntactically and return true if the name does not contain a slash. If given a symbol, downcase to a string then fallback to previous case (NB: for NIL return T). If given a component, do it semantically and return T if it's a SYSTEM and its primary-system-name is the same as its component-name." (etypecase system (string (not (find #\/ system))) (symbol (primary-system-p (coerce-name system))) (component (and (typep system 'system) (equal (component-name system) (primary-system-name system)))))) (defun coerce-filename (name) "Coerce a system designator NAME into a string suitable as a filename component. The (current) transformation is to replace characters /:\\ each by --, the former being forbidden in a filename component. NB: The onus is unhappily on the user to avoid clashes." (frob-substrings (coerce-name name) '("/" ":" "\\") "--"))) ;;; System virtual slot readers, recursing to the primary system if needed. (with-upgradability () (defvar *system-virtual-slots* '(long-name description long-description author maintainer mailto homepage source-control licence version bug-tracker) "The list of system virtual slot names.") (defun system-virtual-slot-value (system slot-name) "Return SYSTEM's virtual SLOT-NAME value. If SYSTEM's SLOT-NAME value is NIL and SYSTEM is a secondary system, look in the primary one." (or (slot-value system slot-name) (unless (primary-system-p system) (slot-value (find-system (primary-system-name system)) slot-name)))) (defmacro define-system-virtual-slot-reader (slot-name) (let ((name (intern (strcat (string :system-) (string slot-name))))) `(progn (fmakunbound ',name) ;; These were gf from defgeneric before 3.3.2.11 (declaim (notinline ,name)) (defun ,name (system) (system-virtual-slot-value system ',slot-name))))) (defmacro define-system-virtual-slot-readers () `(progn ,@(mapcar (lambda (slot-name) `(define-system-virtual-slot-reader ,slot-name)) *system-virtual-slots*))) (define-system-virtual-slot-readers) (defun system-license (system) (system-virtual-slot-value system 'licence))) ;;;; Pathnames (with-upgradability () ;; Resolve a system designator to a system before extracting its system-source-file (defmethod system-source-file ((system-name string)) (system-source-file (find-system system-name))) (defmethod system-source-file ((system-name symbol)) (when system-name (system-source-file (find-system system-name)))) (defun system-source-directory (system-designator) "Return a pathname object corresponding to the directory in which the system specification (.asd file) is located." (pathname-directory-pathname (system-source-file system-designator))) (defun system-relative-pathname (system name &key type) "Given a SYSTEM, and a (Unix-style relative path) NAME of a file (or directory) of given TYPE, return the absolute pathname of a corresponding file under that system's source code pathname." (subpathname (system-source-directory system) name :type type)) (defmethod component-pathname ((system system)) "Given a SYSTEM, and a (Unix-style relative path) NAME of a file (or directory) of given TYPE, return the absolute pathname of a corresponding file under that system's source code pathname." (let ((pathname (or (call-next-method) (system-source-directory system)))) (unless (and (slot-boundp system 'relative-pathname) ;; backward-compatibility with ASDF1-age (slot-value system 'relative-pathname)) ;; systems that directly access this slot. (setf (slot-value system 'relative-pathname) pathname)) pathname)) ;; The default method of component-relative-pathname for a system: ;; if a pathname was specified in the .asd file, it must be relative to the .asd file ;; (actually, to its truename* if *resolve-symlinks* it true, the default). ;; The method will return an *absolute* pathname, once again showing that the historical name ;; component-relative-pathname is misleading and should have been component-specified-pathname. (defmethod component-relative-pathname ((system system)) (parse-unix-namestring (and (slot-boundp system 'relative-pathname) (slot-value system 'relative-pathname)) :want-relative t :type :directory :ensure-absolute t :defaults (system-source-directory system))) ;; A system has no parent; if some method wants to make a path "relative to its parent", ;; it will instead be relative to the system itself. (defmethod component-parent-pathname ((system system)) (system-source-directory system)) ;; Most components don't have a specified component-build-pathname, and therefore ;; no magic redirection of their output that disregards the output-translations. (defmethod component-build-pathname ((c component)) nil)) ;;;; ------------------------------------------------------------------------- ;;;; Finding systems (uiop/package:define-package :asdf/system-registry (:recycle :asdf/system-registry :asdf/find-system :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/system) (:export #:remove-entry-from-registry #:coerce-entry-to-directory #:registered-system #:register-system #:registered-systems* #:registered-systems #:clear-system #:map-systems #:*system-definition-search-functions* #:search-for-system-definition #:*central-registry* #:probe-asd #:sysdef-central-registry-search #:contrib-sysdef-search #:sysdef-find-asdf ;; backward compatibility symbols, functions removed #:sysdef-preloaded-system-search #:register-preloaded-system #:*preloaded-systems* #:find-system-if-being-defined #:mark-component-preloaded ;; forward references to asdf/find-system #:sysdef-immutable-system-search #:register-immutable-system #:*immutable-systems* #:*registered-systems* #:clear-registered-systems ;; defined in source-registry, but specially mentioned here: #:sysdef-source-registry-search)) (in-package :asdf/system-registry) (with-upgradability () ;;; Registry of Defined Systems (defvar *registered-systems* (make-hash-table :test 'equal) "This is a hash table whose keys are strings -- the names of systems -- and whose values are systems. A system is referred to as \"registered\" if it is present in this table.") (defun registered-system (name) "Return a system of given NAME that was registered already, if such a system exists. NAME is a system designator, to be normalized by COERCE-NAME. The value returned is a system object, or NIL if not found." (gethash (coerce-name name) *registered-systems*)) (defun registered-systems* () "Return a list containing every registered system (as a system object)." (loop :for registered :being :the :hash-values :of *registered-systems* :collect registered)) (defun registered-systems () "Return a list of the names of every registered system." (mapcar 'coerce-name (registered-systems*))) (defun register-system (system) "Given a SYSTEM object, register it." (check-type system system) (let ((name (component-name system))) (check-type name string) (asdf-message (compatfmt "~&~@<; ~@;Registering system ~3i~_~A~@:>~%") name) (setf (gethash name *registered-systems*) system))) (defun map-systems (fn) "Apply FN to each defined system. FN should be a function of one argument. It will be called with an object of type asdf:system." (loop :for registered :being :the :hash-values :of *registered-systems* :do (funcall fn registered))) ;;; Preloaded systems: in the image even if you can't find source files backing them. (defvar *preloaded-systems* (make-hash-table :test 'equal) "Registration table for preloaded systems.") (declaim (ftype (function (t) t) mark-component-preloaded)) ; defined in asdf/find-system (defun make-preloaded-system (name keys) "Make a preloaded system of given NAME with build information from KEYS" (let ((system (apply 'make-instance (getf keys :class 'system) :name name :source-file (getf keys :source-file) (remove-plist-keys '(:class :name :source-file) keys)))) (mark-component-preloaded system) system)) (defun sysdef-preloaded-system-search (requested) "If REQUESTED names a system registered as preloaded, return a new system with its registration information." (let ((name (coerce-name requested))) (multiple-value-bind (keys foundp) (gethash name *preloaded-systems*) (when foundp (make-preloaded-system name keys))))) (defun ensure-preloaded-system-registered (name) "If there isn't a registered _defined_ system of given NAME, and a there is a registered _preloaded_ system of given NAME, then define and register said preloaded system." (if-let (system (and (not (registered-system name)) (sysdef-preloaded-system-search name))) (register-system system))) (defun register-preloaded-system (system-name &rest keys &key (version t) &allow-other-keys) "Register a system as being preloaded. If the system has not been loaded from the filesystem yet, or if its build information is later cleared with CLEAR-SYSTEM, a dummy system will be registered without backing filesystem information, based on KEYS (e.g. to provide a VERSION). If VERSION is the default T, and a system was already loaded, then its version will be preserved." (let ((name (coerce-name system-name))) (when (eql version t) (if-let (system (registered-system name)) (setf (getf keys :version) (component-version system)))) (setf (gethash name *preloaded-systems*) keys) (ensure-preloaded-system-registered system-name))) ;;; Immutable systems: in the image and can't be reloaded from source. (defvar *immutable-systems* nil "A hash-set (equal hash-table mapping keys to T) of systems that are immutable, i.e. already loaded in memory and not to be refreshed from the filesystem. They will be treated specially by find-system, and passed as :force-not argument to make-plan. For instance, to can deliver an image with many systems precompiled, that *will not* check the filesystem for them every time a user loads an extension, what more risk a problematic upgrade or catastrophic downgrade, before you dump an image, you may use: (map () 'asdf:register-immutable-system (asdf:already-loaded-systems)) Note that direct access to this variable from outside ASDF is not supported. Please call REGISTER-IMMUTABLE-SYSTEM to add new immutable systems, and contact maintainers if you need a stable API to do more than that.") (defun sysdef-immutable-system-search (requested) (let ((name (coerce-name requested))) (when (and *immutable-systems* (gethash name *immutable-systems*)) (or (registered-system requested) (error 'formatted-system-definition-error :format-control "Requested system ~A registered as an immutable-system, ~ but not even registered as defined" :format-arguments (list name)))))) (defun register-immutable-system (system-name &rest keys) "Register SYSTEM-NAME as preloaded and immutable. It will automatically be considered as passed to FORCE-NOT in a plan." (let ((system-name (coerce-name system-name))) (apply 'register-preloaded-system system-name keys) (unless *immutable-systems* (setf *immutable-systems* (list-to-hash-set nil))) (setf (gethash system-name *immutable-systems*) t))) ;;; Making systems undefined. (defun clear-system (system) "Clear the entry for a SYSTEM in the database of systems previously defined. However if the system was registered as PRELOADED (which it is if it is IMMUTABLE), then a new system with the same name will be defined and registered in its place from which build details will have been cleared. Note that this does NOT in any way cause any of the code of the system to be unloaded. Returns T if system was or is now undefined, NIL if a new preloaded system was redefined." ;; There is no "unload" operation in Common Lisp, and ;; a general such operation cannot be portably written, ;; considering how much CL relies on side-effects to global data structures. (let ((name (coerce-name system))) (remhash name *registered-systems*) (unset-asdf-cache-entry `(find-system ,name)) (not (ensure-preloaded-system-registered name)))) (defun clear-registered-systems () "Clear all currently registered defined systems. Preloaded systems (including immutable ones) will be reset, other systems will be de-registered." (map () 'clear-system (registered-systems))) ;;; Searching for system definitions ;; For the sake of keeping things reasonably neat, we adopt a convention that ;; only symbols are to be pushed to this list (rather than e.g. function objects), ;; which makes upgrade easier. Also, the name of these symbols shall start with SYSDEF- (defvar *system-definition-search-functions* '() "A list that controls the ways that ASDF looks for system definitions. It contains symbols to be funcalled in order, with a requested system name as argument, until one returns a non-NIL result (if any), which must then be a fully initialized system object with that name.") ;; Initialize and/or upgrade the *system-definition-search-functions* ;; so it doesn't contain obsolete symbols, and does contain the current ones. (defun cleanup-system-definition-search-functions () (setf *system-definition-search-functions* (append ;; Remove known-incompatible sysdef functions from old versions of asdf. ;; Order matters, so we can't just use set-difference. (let ((obsolete '(contrib-sysdef-search sysdef-find-asdf sysdef-preloaded-system-search))) (remove-if #'(lambda (x) (member x obsolete)) *system-definition-search-functions*)) ;; Tuck our defaults at the end of the list if they were absent. ;; This is imperfect, in case they were removed on purpose, ;; but then it will be the responsibility of whoever removes these symmbols ;; to upgrade asdf before he does such a thing rather than after. (remove-if #'(lambda (x) (member x *system-definition-search-functions*)) '(sysdef-central-registry-search sysdef-source-registry-search))))) (cleanup-system-definition-search-functions) ;; This (private) function does the search for a system definition using *s-d-s-f*; ;; it is to be called by locate-system. (defun search-for-system-definition (system) ;; Search for valid definitions of the system available in the current session. ;; Previous definitions as registered in *registered-systems* MUST NOT be considered; ;; they will be reconciled by locate-system then find-system. ;; There are two special treatments: first, specially search for objects being defined ;; in the current session, to avoid definition races between several files; ;; second, specially search for immutable systems, so they cannot be redefined. ;; Finally, use the search functions specified in *system-definition-search-functions*. (let ((name (coerce-name system))) (flet ((try (f) (if-let ((x (funcall f name))) (return-from search-for-system-definition x)))) (try 'find-system-if-being-defined) (try 'sysdef-immutable-system-search) (map () #'try *system-definition-search-functions*)))) ;;; The legacy way of finding a system: the *central-registry* ;; This variable contains a list of directories to be lazily searched for the requested asd ;; by sysdef-central-registry-search. (defvar *central-registry* nil "A list of 'system directory designators' ASDF uses to find systems. A 'system directory designator' is a pathname or an expression which evaluates to a pathname. For example: (setf asdf:*central-registry* (list '*default-pathname-defaults* #p\"/home/me/cl/systems/\" #p\"/usr/share/common-lisp/systems/\")) This variable is for backward compatibility. Going forward, we recommend new users should be using the source-registry.") ;; Function to look for an asd file of given NAME under a directory provided by DEFAULTS. ;; Return the truename of that file if it is found and TRUENAME is true. ;; Return NIL if the file is not found. ;; On Windows, follow shortcuts to .asd files. (defun probe-asd (name defaults &key truename) (block nil (when (directory-pathname-p defaults) (if-let (file (probe-file* (ensure-absolute-pathname (parse-unix-namestring name :type "asd") #'(lambda () (ensure-absolute-pathname defaults 'get-pathname-defaults nil)) nil) :truename truename)) (return file)) #-(or clisp genera) ; clisp doesn't need it, plain genera doesn't have read-sequence(!) (os-cond ((os-windows-p) (when (physical-pathname-p defaults) (let ((shortcut (make-pathname :defaults defaults :case :local :name (strcat name ".asd") :type "lnk"))) (when (probe-file* shortcut) (ensure-pathname (parse-windows-shortcut shortcut) :namestring :native))))))))) ;; Function to push onto *s-d-s-f* to use the *central-registry* (defun sysdef-central-registry-search (system) (let ((name (primary-system-name system)) (to-remove nil) (to-replace nil)) (block nil (unwind-protect (dolist (dir *central-registry*) (let ((defaults (eval dir)) directorized) (when defaults (cond ((directory-pathname-p defaults) (let* ((file (probe-asd name defaults :truename *resolve-symlinks*))) (when file (return file)))) (t (restart-case (let* ((*print-circle* nil) (message (format nil (compatfmt "~@") system dir defaults))) (error message)) (remove-entry-from-registry () :report "Remove entry from *central-registry* and continue" (push dir to-remove)) (coerce-entry-to-directory () :test (lambda (c) (declare (ignore c)) (and (not (directory-pathname-p defaults)) (directory-pathname-p (setf directorized (ensure-directory-pathname defaults))))) :report (lambda (s) (format s (compatfmt "~@") directorized dir)) (push (cons dir directorized) to-replace)))))))) ;; cleanup (dolist (dir to-remove) (setf *central-registry* (remove dir *central-registry*))) (dolist (pair to-replace) (let* ((current (car pair)) (new (cdr pair)) (position (position current *central-registry*))) (setf *central-registry* (append (subseq *central-registry* 0 position) (list new) (subseq *central-registry* (1+ position))))))))))) ;;;; ------------------------------------------------------------------------- ;;;; Actions (uiop/package:define-package :asdf/action (:nicknames :asdf-action) (:recycle :asdf/action :asdf/plan :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/operation) (:import-from :asdf/operation #:check-operation-constructor) (:import-from :asdf/component #:%additional-input-files) (:export #:action #:define-convenience-action-methods #:action-description #:format-action #:downward-operation #:upward-operation #:sideway-operation #:selfward-operation #:non-propagating-operation #:component-depends-on #:input-files #:output-files #:output-file #:operation-done-p #:action-operation #:action-component #:make-action #:component-operation-time #:mark-operation-done #:compute-action-stamp #:perform #:perform-with-restarts #:retry #:accept #:action-path #:find-action #:operation-definition-warning #:operation-definition-error ;; condition #:action-valid-p #:circular-dependency #:circular-dependency-actions #:call-while-visiting-action #:while-visiting-action #:additional-input-files)) (in-package :asdf/action) (eval-when (#-lispworks :compile-toplevel :load-toplevel :execute) ;; LispWorks issues spurious warning (deftype action () "A pair of operation and component uniquely identifies a node in the dependency graph of steps to be performed while building a system." '(cons operation component)) (deftype operation-designator () "An operation designates itself. NIL designates a context-dependent current operation, and a class-name or class designates the canonical instance of the designated class." '(or operation null symbol class))) ;;; these are pseudo accessors -- let us abstract away the CONS cell representation of plan ;;; actions. (with-upgradability () (defun make-action (operation component) (cons operation component)) (defun action-operation (action) (car action)) (defun action-component (action) (cdr action))) ;;;; Reified representation for storage or debugging. Note: an action is identified by its class. (with-upgradability () (defun action-path (action) "A readable data structure that identifies the action." (when action (let ((o (action-operation action)) (c (action-component action))) (cons (type-of o) (component-find-path c))))) (defun find-action (path) "Reconstitute an action from its action-path" (destructuring-bind (o . c) path (make-action (make-operation o) (find-component () c))))) ;;;; Convenience methods (with-upgradability () ;; A macro that defines convenience methods for a generic function (gf) that ;; dispatches on operation and component. The convenience methods allow users ;; to call the gf with operation and/or component designators, that the ;; methods will resolve into actual operation and component objects, so that ;; the users can interact using readable designators, but developers only have ;; to write methods that handle operation and component objects. ;; FUNCTION is the generic function name ;; FORMALS is its list of arguments, which must include OPERATION and COMPONENT. ;; IF-NO-OPERATION is a form (defaults to NIL) describing what to do if no operation is found. ;; IF-NO-COMPONENT is a form (defaults to NIL) describing what to do if no component is found. (defmacro define-convenience-action-methods (function formals &key if-no-operation if-no-component) (let* ((rest (gensym "REST")) (found (gensym "FOUND")) (keyp (equal (last formals) '(&key))) (formals-no-key (if keyp (butlast formals) formals)) (len (length formals-no-key)) (operation 'operation) (component 'component) (opix (position operation formals)) (coix (position component formals)) (prefix (subseq formals 0 opix)) (suffix (subseq formals (1+ coix) len)) (more-args (when keyp `(&rest ,rest &key &allow-other-keys)))) (assert (and (integerp opix) (integerp coix) (= coix (1+ opix)))) (flet ((next-method (o c) (if keyp `(apply ',function ,@prefix ,o ,c ,@suffix ,rest) `(,function ,@prefix ,o ,c ,@suffix)))) `(progn (defmethod ,function (,@prefix (,operation string) ,component ,@suffix ,@more-args) (declare (notinline ,function)) (let ((,component (find-component () ,component))) ;; do it first, for defsystem-depends-on ,(next-method `(safe-read-from-string ,operation :package :asdf/interface) component))) (defmethod ,function (,@prefix (,operation symbol) ,component ,@suffix ,@more-args) (declare (notinline ,function)) (if ,operation ,(next-method `(make-operation ,operation) `(or (find-component () ,component) ,if-no-component)) ,if-no-operation)) (defmethod ,function (,@prefix (,operation operation) ,component ,@suffix ,@more-args) (declare (notinline ,function)) (if (typep ,component 'component) (error "No defined method for ~S on ~/asdf-action:format-action/" ',function (make-action ,operation ,component)) (if-let (,found (find-component () ,component)) ,(next-method operation found) ,if-no-component)))))))) ;;;; Self-description (with-upgradability () (defgeneric action-description (operation component) (:documentation "returns a phrase that describes performing this operation on this component, e.g. \"loading /a/b/c\". You can put together sentences using this phrase.")) (defmethod action-description (operation component) (format nil (compatfmt "~@<~A on ~A~@:>") operation component)) (defun format-action (stream action &optional colon-p at-sign-p) "FORMAT helper to display an action's action-description. Use it in FORMAT control strings as ~/asdf-action:format-action/" (assert (null colon-p)) (assert (null at-sign-p)) (destructuring-bind (operation . component) action (princ (action-description operation component) stream)))) ;;;; Detection of circular dependencies (with-upgradability () (defun action-valid-p (operation component) "Is this action valid to include amongst dependencies?" ;; If either the operation or component was resolved to nil, the action is invalid. ;; :if-feature will invalidate actions on components for which the features don't apply. (and operation component (if-let (it (component-if-feature component)) (featurep it) t))) (define-condition circular-dependency (system-definition-error) ((actions :initarg :actions :reader circular-dependency-actions)) (:report (lambda (c s) (format s (compatfmt "~@") (first (circular-dependency-actions c)) (circular-dependency-actions c))))) (defun call-while-visiting-action (operation component fun) "Detect circular dependencies" (with-asdf-session () (with-accessors ((action-set visiting-action-set) (action-list visiting-action-list)) *asdf-session* (let ((action (cons operation component))) (when (gethash action action-set) (error 'circular-dependency :actions (member action (reverse action-list) :test 'equal))) (setf (gethash action action-set) t) (push action action-list) (unwind-protect (funcall fun) (pop action-list) (setf (gethash action action-set) nil)))))) ;; Syntactic sugar for call-while-visiting-action (defmacro while-visiting-action ((o c) &body body) `(call-while-visiting-action ,o ,c #'(lambda () ,@body)))) ;;;; Dependencies (with-upgradability () (defgeneric component-depends-on (operation component) ;; ASDF4: rename to component-dependencies (:documentation "Returns a list of dependencies needed by the component to perform the operation. A dependency has one of the following forms: ( *), where is an operation designator with respect to FIND-OPERATION in the context of the OPERATION argument, and each is a component designator with respect to FIND-COMPONENT in the context of the COMPONENT argument, and means that the component depends on having been performed on each ; [Note: an is an operation designator -- it can be either an operation name or an operation object. Similarly, a may be a component name or a component object. Also note that, the degenerate case of () is a no-op.] Methods specialized on subclasses of existing component types should usually append the results of CALL-NEXT-METHOD to the list.")) (define-convenience-action-methods component-depends-on (operation component)) (defmethod component-depends-on :around ((o operation) (c component)) (do-asdf-cache `(component-depends-on ,o ,c) (call-next-method)))) ;;;; upward-operation, downward-operation, sideway-operation, selfward-operation ;; These together handle actions that propagate along the component hierarchy or operation universe. (with-upgradability () (defclass downward-operation (operation) ((downward-operation :initform nil :reader downward-operation :type operation-designator :allocation :class)) (:documentation "A DOWNWARD-OPERATION's dependencies propagate down the component hierarchy. I.e., if O is a DOWNWARD-OPERATION and its DOWNWARD-OPERATION slot designates operation D, then the action (O . M) of O on module M will depends on each of (D . C) for each child C of module M. The default value for slot DOWNWARD-OPERATION is NIL, which designates the operation O itself. E.g. in order for a MODULE to be loaded with LOAD-OP (resp. compiled with COMPILE-OP), all the children of the MODULE must have been loaded with LOAD-OP (resp. compiled with COMPILE-OP.")) (defun downward-operation-depends-on (o c) `((,(or (downward-operation o) o) ,@(component-children c)))) (defmethod component-depends-on ((o downward-operation) (c parent-component)) `(,@(downward-operation-depends-on o c) ,@(call-next-method))) (defclass upward-operation (operation) ((upward-operation :initform nil :reader upward-operation :type operation-designator :allocation :class)) (:documentation "An UPWARD-OPERATION has dependencies that propagate up the component hierarchy. I.e., if O is an instance of UPWARD-OPERATION, and its UPWARD-OPERATION slot designates operation U, then the action (O . C) of O on a component C that has the parent P will depends on (U . P). The default value for slot UPWARD-OPERATION is NIL, which designates the operation O itself. E.g. in order for a COMPONENT to be prepared for loading or compiling with PREPARE-OP, its PARENT must first be prepared for loading or compiling with PREPARE-OP.")) ;; For backward-compatibility reasons, a system inherits from module and is a child-component ;; so we must guard against this case. ASDF4: remove that. (defun upward-operation-depends-on (o c) (if-let (p (component-parent c)) `((,(or (upward-operation o) o) ,p)))) (defmethod component-depends-on ((o upward-operation) (c child-component)) `(,@(upward-operation-depends-on o c) ,@(call-next-method))) (defclass sideway-operation (operation) ((sideway-operation :initform nil :reader sideway-operation :type operation-designator :allocation :class)) (:documentation "A SIDEWAY-OPERATION has dependencies that propagate \"sideway\" to siblings that a component depends on. I.e. if O is a SIDEWAY-OPERATION, and its SIDEWAY-OPERATION slot designates operation S (where NIL designates O itself), then the action (O . C) of O on component C depends on each of (S . D) where D is a declared dependency of C. E.g. in order for a COMPONENT to be prepared for loading or compiling with PREPARE-OP, each of its declared dependencies must first be loaded as by LOAD-OP.")) (defun sideway-operation-depends-on (o c) `((,(or (sideway-operation o) o) ,@(component-sideway-dependencies c)))) (defmethod component-depends-on ((o sideway-operation) (c component)) `(,@(sideway-operation-depends-on o c) ,@(call-next-method))) (defclass selfward-operation (operation) ((selfward-operation ;; NB: no :initform -- if an operation depends on others, it must explicitly specify which :type (or operation-designator list) :reader selfward-operation :allocation :class)) (:documentation "A SELFWARD-OPERATION depends on another operation on the same component. I.e., if O is a SELFWARD-OPERATION, and its SELFWARD-OPERATION designates a list of operations L, then the action (O . C) of O on component C depends on each (S . C) for S in L. E.g. before a component may be loaded by LOAD-OP, it must have been compiled by COMPILE-OP. A operation-designator designates a singleton list of the designated operation; a list of operation-designators designates the list of designated operations; NIL is not a valid operation designator in that context. Note that any dependency ordering between the operations in a list of SELFWARD-OPERATION should be specified separately in the respective operation's COMPONENT-DEPENDS-ON methods so that they be scheduled properly.")) (defun selfward-operation-depends-on (o c) (loop :for op :in (ensure-list (selfward-operation o)) :collect `(,op ,c))) (defmethod component-depends-on ((o selfward-operation) (c component)) `(,@(selfward-operation-depends-on o c) ,@(call-next-method))) (defclass non-propagating-operation (operation) () (:documentation "A NON-PROPAGATING-OPERATION is an operation that propagates no dependencies whatsoever. It is supplied in order that the programmer be able to specify that s/he is intentionally specifying an operation which invokes no dependencies."))) ;;;--------------------------------------------------------------------------- ;;; Help programmers catch obsolete OPERATION subclasses ;;;--------------------------------------------------------------------------- (with-upgradability () (define-condition operation-definition-warning (simple-warning) () (:documentation "Warning condition related to definition of obsolete OPERATION objects.")) (define-condition operation-definition-error (simple-error) () (:documentation "Error condition related to definition of incorrect OPERATION objects.")) (defmethod initialize-instance :before ((o operation) &key) (check-operation-constructor) (unless (typep o '(or downward-operation upward-operation sideway-operation selfward-operation non-propagating-operation)) (warn 'operation-definition-warning :format-control "No dependency propagating scheme specified for operation class ~S. The class needs to be updated for ASDF 3.1 and specify appropriate propagation mixins." :format-arguments (list (type-of o))))) (defmethod initialize-instance :before ((o non-propagating-operation) &key) (when (typep o '(or downward-operation upward-operation sideway-operation selfward-operation)) (error 'operation-definition-error :format-control "Inconsistent class: ~S NON-PROPAGATING-OPERATION is incompatible with propagating operation classes as superclasses." :format-arguments (list (type-of o))))) (defun backward-compatible-depends-on (o c) "DEPRECATED: all subclasses of OPERATION used in ASDF should inherit from one of DOWNWARD-OPERATION UPWARD-OPERATION SIDEWAY-OPERATION SELFWARD-OPERATION NON-PROPAGATING-OPERATION. The function BACKWARD-COMPATIBLE-DEPENDS-ON temporarily provides ASDF2 behaviour for those that don't. In the future this functionality will be removed, and the default will be no propagation." (uiop/version::notify-deprecated-function (version-deprecation *asdf-version* :style-warning "3.2") `(backward-compatible-depends-on :for-operation ,o)) `(,@(sideway-operation-depends-on o c) ,@(when (typep c 'parent-component) (downward-operation-depends-on o c)))) (defmethod component-depends-on ((o operation) (c component)) `(;; Normal behavior, to allow user-specified in-order-to dependencies ,@(cdr (assoc (type-of o) (component-in-order-to c))) ;; For backward-compatibility with ASDF2, any operation that doesn't specify propagation ;; or non-propagation through an appropriate mixin will be downward and sideway. ,@(unless (typep o '(or downward-operation upward-operation sideway-operation selfward-operation non-propagating-operation)) (backward-compatible-depends-on o c)))) (defmethod downward-operation ((o operation)) nil) (defmethod sideway-operation ((o operation)) nil)) ;;;--------------------------------------------------------------------------- ;;; End of OPERATION class checking ;;;--------------------------------------------------------------------------- ;;;; Inputs, Outputs, and invisible dependencies (with-upgradability () (defgeneric output-files (operation component) (:documentation "Methods for this function return two values: a list of output files corresponding to this action, and a boolean indicating if they have already been subjected to relevant output translations and should not be further translated. Methods on PERFORM *must* call this function to determine where their outputs are to be located. They may rely on the order of the files to discriminate between outputs. ")) (defgeneric input-files (operation component) (:documentation "A list of input files corresponding to this action. Methods on PERFORM *must* call this function to determine where their inputs are located. They may rely on the order of the files to discriminate between inputs. ")) (defgeneric operation-done-p (operation component) (:documentation "Returns a boolean which is NIL if the action must be performed (again).")) (define-convenience-action-methods output-files (operation component)) (define-convenience-action-methods input-files (operation component)) (define-convenience-action-methods operation-done-p (operation component)) (defmethod operation-done-p ((o operation) (c component)) t) ;; Translate output files, unless asked not to. Memoize the result. (defmethod output-files :around ((operation t) (component t)) (do-asdf-cache `(output-files ,operation ,component) (values (multiple-value-bind (pathnames fixedp) (call-next-method) ;; 1- Make sure we have absolute pathnames (let* ((directory (pathname-directory-pathname (component-pathname (find-component () component)))) (absolute-pathnames (loop :for pathname :in pathnames :collect (ensure-absolute-pathname pathname directory)))) ;; 2- Translate those pathnames as required (if fixedp absolute-pathnames (mapcar *output-translation-function* absolute-pathnames)))) t))) (defmethod output-files ((o operation) (c component)) nil) (defun output-file (operation component) "The unique output file of performing OPERATION on COMPONENT" (let ((files (output-files operation component))) (assert (length=n-p files 1)) (first files))) (defgeneric additional-input-files (operation component) (:documentation "Additional input files for the operation on this component. These are files that are inferred, rather than explicitly specified, and these are typically NOT files that undergo operations directly. Instead, they are files that it is important for ASDF to know about in order to compute operation times,etc.")) (define-convenience-action-methods additional-input-files (operation component)) (defmethod additional-input-files ((op operation) (comp component)) (cdr (assoc op (%additional-input-files comp)))) ;; Memoize input files. (defmethod input-files :around (operation component) (do-asdf-cache `(input-files ,operation ,component) ;; get the additional input files, if any (append (call-next-method) ;; must come after the first, for other code that ;; assumes the first will be the "key" file (additional-input-files operation component)))) ;; By default an action has no input-files. (defmethod input-files ((o operation) (c component)) nil) ;; An action with a selfward-operation by default gets its input-files from the output-files of ;; the actions using selfward-operations it depends on (and the same component), ;; or if there are none, on the component-pathname of the component if it's a file ;; -- and then on the results of the next-method. (defmethod input-files ((o selfward-operation) (c component)) `(,@(or (loop :for dep-o :in (ensure-list (selfward-operation o)) :append (or (output-files dep-o c) (input-files dep-o c))) (if-let ((pathname (component-pathname c))) (and (file-pathname-p pathname) (list pathname)))) ,@(call-next-method)))) ;;;; Done performing (with-upgradability () ;; ASDF4: hide it behind plan-action-stamp (defgeneric component-operation-time (operation component) (:documentation "Return the timestamp for when an action was last performed")) (defgeneric (setf component-operation-time) (time operation component) (:documentation "Update the timestamp for when an action was last performed")) (define-convenience-action-methods component-operation-time (operation component)) ;; ASDF4: hide it behind (setf plan-action-stamp) (defgeneric mark-operation-done (operation component) (:documentation "Mark a action as having been just done. Updates the action's COMPONENT-OPERATION-TIME to match the COMPUTE-ACTION-STAMP using the JUST-DONE flag.")) (defgeneric compute-action-stamp (plan- operation component &key just-done) ;; NB: using plan- rather than plan above allows clisp to upgrade from 2.26(!) (:documentation "Has this action been successfully done already, and at what known timestamp has it been done at or will it be done at? * PLAN is a plan object modelling future effects of actions, or NIL to denote what actually happened. * OPERATION and COMPONENT denote the action. Takes keyword JUST-DONE: * JUST-DONE is a boolean that is true if the action was just successfully performed, at which point we want compute the actual stamp and warn if files are missing; otherwise we are making plans, anticipating the effects of the action. Returns two values: * a STAMP saying when it was done or will be done, or T if the action involves files that need to be recomputed. * a boolean DONE-P that indicates whether the action has actually been done, and both its output-files and its in-image side-effects are up to date.")) (defmethod component-operation-time ((o operation) (c component)) (gethash o (component-operation-times c))) (defmethod (setf component-operation-time) (stamp (o operation) (c component)) (assert stamp () "invalid null stamp for ~A" (action-description o c)) (setf (gethash o (component-operation-times c)) stamp)) (defmethod mark-operation-done ((o operation) (c component)) (let ((stamp (compute-action-stamp nil o c :just-done t))) (assert stamp () "Failed to compute a stamp for completed action ~A" (action-description o c))1 (setf (component-operation-time o c) stamp)))) ;;;; Perform (with-upgradability () (defgeneric perform (operation component) (:documentation "PERFORM an action, consuming its input-files and building its output-files")) (define-convenience-action-methods perform (operation component)) (defmethod perform :around ((o operation) (c component)) (while-visiting-action (o c) (call-next-method))) (defmethod perform :before ((o operation) (c component)) (ensure-all-directories-exist (output-files o c))) (defmethod perform :after ((o operation) (c component)) (mark-operation-done o c)) (defmethod perform ((o operation) (c parent-component)) nil) (defmethod perform ((o operation) (c source-file)) ;; For backward compatibility, don't error on operations that don't specify propagation. (when (typep o '(or downward-operation upward-operation sideway-operation selfward-operation non-propagating-operation)) (sysdef-error (compatfmt "~@") 'perform (make-action o c)))) ;; The restarts of the perform-with-restarts variant matter in an interactive context. ;; The retry strategies of p-w-r itself, and/or the background workers of a multiprocess build ;; may call perform directly rather than call p-w-r. (defgeneric perform-with-restarts (operation component) (:documentation "PERFORM an action in a context where suitable restarts are in place.")) (defmethod perform-with-restarts (operation component) (perform operation component)) (defmethod perform-with-restarts :around (operation component) (loop (restart-case (return (call-next-method)) (retry () :report (lambda (s) (format s (compatfmt "~@") (action-description operation component)))) (accept () :report (lambda (s) (format s (compatfmt "~@") (action-description operation component))) (mark-operation-done operation component) (return)))))) ;;;; ------------------------------------------------------------------------- ;;;; Actions to build Common Lisp software (uiop/package:define-package :asdf/lisp-action (:recycle :asdf/lisp-action :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/system :asdf/operation :asdf/action) (:export #:try-recompiling #:cl-source-file #:cl-source-file.cl #:cl-source-file.lsp #:basic-load-op #:basic-compile-op #:load-op #:prepare-op #:compile-op #:test-op #:load-source-op #:prepare-source-op #:call-with-around-compile-hook #:perform-lisp-compilation #:perform-lisp-load-fasl #:perform-lisp-load-source #:lisp-compilation-output-files)) (in-package :asdf/lisp-action) ;;;; Component classes (with-upgradability () (defclass cl-source-file (source-file) ((type :initform "lisp")) (:documentation "Component class for a Common Lisp source file (using type \"lisp\")")) (defclass cl-source-file.cl (cl-source-file) ((type :initform "cl")) (:documentation "Component class for a Common Lisp source file using type \"cl\"")) (defclass cl-source-file.lsp (cl-source-file) ((type :initform "lsp")) (:documentation "Component class for a Common Lisp source file using type \"lsp\""))) ;;;; Operation classes (with-upgradability () (defclass basic-load-op (operation) () (:documentation "Base class for operations that apply the load-time effects of a file")) (defclass basic-compile-op (operation) () (:documentation "Base class for operations that apply the compile-time effects of a file"))) ;;; Our default operations: loading into the current lisp image (with-upgradability () (defclass prepare-op (upward-operation sideway-operation) ((sideway-operation :initform 'load-op :allocation :class)) (:documentation "Load the dependencies for the COMPILE-OP or LOAD-OP of a given COMPONENT.")) (defclass load-op (basic-load-op downward-operation selfward-operation) ;; NB: even though compile-op depends on prepare-op it is not needed-in-image-p, ;; so we need to directly depend on prepare-op for its side-effects in the current image. ((selfward-operation :initform '(prepare-op compile-op) :allocation :class)) (:documentation "Operation for loading the compiled FASL for a Lisp file")) (defclass compile-op (basic-compile-op downward-operation selfward-operation) ((selfward-operation :initform 'prepare-op :allocation :class)) (:documentation "Operation for compiling a Lisp file to a FASL")) (defclass prepare-source-op (upward-operation sideway-operation) ((sideway-operation :initform 'load-source-op :allocation :class)) (:documentation "Operation for loading the dependencies of a Lisp file as source.")) (defclass load-source-op (basic-load-op downward-operation selfward-operation) ((selfward-operation :initform 'prepare-source-op :allocation :class)) (:documentation "Operation for loading a Lisp file as source.")) (defclass test-op (selfward-operation) ((selfward-operation :initform 'load-op :allocation :class)) (:documentation "Operation for running the tests for system. If the tests fail, an error will be signaled."))) ;;;; Methods for prepare-op, compile-op and load-op ;;; prepare-op (with-upgradability () (defmethod action-description ((o prepare-op) (c component)) (format nil (compatfmt "~@") c)) (defmethod perform ((o prepare-op) (c component)) nil) (defmethod input-files ((o prepare-op) (s system)) (if-let (it (system-source-file s)) (list it)))) ;;; compile-op (with-upgradability () (defmethod action-description ((o compile-op) (c component)) (format nil (compatfmt "~@") c)) (defmethod action-description ((o compile-op) (c parent-component)) (format nil (compatfmt "~@") c)) (defgeneric call-with-around-compile-hook (component thunk) (:documentation "A method to be called around the PERFORM'ing of actions that apply the compile-time side-effects of file (i.e., COMPILE-OP or LOAD-SOURCE-OP). This method can be used to setup readtables and other variables that control reading, macroexpanding, and compiling, etc. Note that it will NOT be called around the performing of LOAD-OP.")) (defmethod call-with-around-compile-hook ((c component) function) (call-around-hook (around-compile-hook c) function)) (defun perform-lisp-compilation (o c) "Perform the compilation of the Lisp file associated to the specified action (O . C)." (let (;; Before 2.26.53, that was unfortunately component-pathname. Now, ;; we consult input-files, the first of which should be the one to compile-file (input-file (first (input-files o c))) ;; On some implementations, there are more than one output-file, ;; but the first one should always be the primary fasl that gets loaded. (outputs (output-files o c))) (multiple-value-bind (output warnings-p failure-p) (destructuring-bind (output-file &optional #+(or clasp ecl mkcl) object-file #+clisp lib-file warnings-file &rest rest) outputs ;; Allow for extra outputs that are not of type warnings-file ;; The way we do it is kludgy. In ASDF4, output-files shall not be positional. (declare (ignore rest)) (when warnings-file (unless (equal (pathname-type warnings-file) (warnings-file-type)) (setf warnings-file nil))) (call-with-around-compile-hook c #'(lambda (&rest flags) (apply 'compile-file* input-file :output-file output-file :external-format (component-external-format c) :warnings-file warnings-file (append #+clisp (list :lib-file lib-file) #+(or clasp ecl mkcl) (list :object-file object-file) flags))))) (check-lisp-compile-results output warnings-p failure-p "~/asdf-action::format-action/" (list (cons o c)))))) (defun report-file-p (f) "Is F a build report file containing, e.g., warnings to check?" (equalp (pathname-type f) "build-report")) (defun perform-lisp-warnings-check (o c) "Check the warnings associated with the dependencies of an action." (let* ((expected-warnings-files (remove-if-not #'warnings-file-p (input-files o c))) (actual-warnings-files (loop :for w :in expected-warnings-files :when (get-file-stamp w) :collect w :else :do (warn "Missing warnings file ~S while ~A" w (action-description o c))))) (check-deferred-warnings actual-warnings-files) (let* ((output (output-files o c)) (report (find-if #'report-file-p output))) (when report (with-open-file (s report :direction :output :if-exists :supersede) (format s ":success~%")))))) (defmethod perform ((o compile-op) (c cl-source-file)) (perform-lisp-compilation o c)) (defun lisp-compilation-output-files (o c) "Compute the output-files for compiling the Lisp file for the specified action (O . C), an OPERATION and a COMPONENT." (let* ((i (first (input-files o c))) (f (compile-file-pathname i #+clasp :output-type #+ecl :type #+(or clasp ecl) :fasl #+mkcl :fasl-p #+mkcl t))) `(,f ;; the fasl is the primary output, in first position #+clasp ,@(unless nil ;; was (use-ecl-byte-compiler-p) `(,(compile-file-pathname i :output-type :object))) #+clisp ,@`(,(make-pathname :type "lib" :defaults f)) #+ecl ,@(unless (use-ecl-byte-compiler-p) `(,(compile-file-pathname i :type :object))) #+mkcl ,(compile-file-pathname i :fasl-p nil) ;; object file ,@(when (and *warnings-file-type* (not (builtin-system-p (component-system c)))) `(,(make-pathname :type *warnings-file-type* :defaults f)))))) (defmethod output-files ((o compile-op) (c cl-source-file)) (lisp-compilation-output-files o c)) (defmethod perform ((o compile-op) (c static-file)) nil) ;; Performing compile-op on a system will check the deferred warnings for the system (defmethod perform ((o compile-op) (c system)) (when (and *warnings-file-type* (not (builtin-system-p c))) (perform-lisp-warnings-check o c))) (defmethod input-files ((o compile-op) (c system)) (when (and *warnings-file-type* (not (builtin-system-p c))) ;; The most correct way to do it would be to use: ;; (collect-dependencies o c :other-systems nil :keep-operation 'compile-op :keep-component 'cl-source-file) ;; but it's expensive and we don't care too much about file order or ASDF extensions. (loop :for sub :in (sub-components c :type 'cl-source-file) :nconc (remove-if-not 'warnings-file-p (output-files o sub))))) (defmethod output-files ((o compile-op) (c system)) (when (and *warnings-file-type* (not (builtin-system-p c))) (if-let ((pathname (component-pathname c))) (list (subpathname pathname (coerce-filename c) :type "build-report")))))) ;;; load-op (with-upgradability () (defmethod action-description ((o load-op) (c cl-source-file)) (format nil (compatfmt "~@") c)) (defmethod action-description ((o load-op) (c parent-component)) (format nil (compatfmt "~@") c)) (defmethod action-description ((o load-op) (c component)) (format nil (compatfmt "~@") c)) (defmethod perform-with-restarts ((o load-op) (c cl-source-file)) (loop (restart-case (return (call-next-method)) (try-recompiling () :report (lambda (s) (format s "Recompile ~a and try loading it again" (component-name c))) (perform (find-operation o 'compile-op) c))))) (defun perform-lisp-load-fasl (o c) "Perform the loading of a FASL associated to specified action (O . C), an OPERATION and a COMPONENT." (if-let (fasl (first (input-files o c))) (load* fasl))) (defmethod perform ((o load-op) (c cl-source-file)) (perform-lisp-load-fasl o c)) (defmethod perform ((o load-op) (c static-file)) nil)) ;;;; prepare-source-op, load-source-op ;;; prepare-source-op (with-upgradability () (defmethod action-description ((o prepare-source-op) (c component)) (format nil (compatfmt "~@") c)) (defmethod input-files ((o prepare-source-op) (s system)) (if-let (it (system-source-file s)) (list it))) (defmethod perform ((o prepare-source-op) (c component)) nil)) ;;; load-source-op (with-upgradability () (defmethod action-description ((o load-source-op) (c component)) (format nil (compatfmt "~@") c)) (defmethod action-description ((o load-source-op) (c parent-component)) (format nil (compatfmt "~@") c)) (defun perform-lisp-load-source (o c) "Perform the loading of a Lisp file as associated to specified action (O . C)" (call-with-around-compile-hook c #'(lambda () (load* (first (input-files o c)) :external-format (component-external-format c))))) (defmethod perform ((o load-source-op) (c cl-source-file)) (perform-lisp-load-source o c)) (defmethod perform ((o load-source-op) (c static-file)) nil)) ;;;; test-op (with-upgradability () (defmethod perform ((o test-op) (c component)) nil) (defmethod operation-done-p ((o test-op) (c system)) "Testing a system is _never_ done." nil)) ;;;; ------------------------------------------------------------------------- ;;;; Finding components (uiop/package:define-package :asdf/find-component (:recycle :asdf/find-component :asdf/find-system :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/system :asdf/system-registry) (:export #:find-component #:resolve-dependency-name #:resolve-dependency-spec #:resolve-dependency-combination ;; Conditions #:missing-component #:missing-requires #:missing-parent #:missing-component-of-version #:retry #:missing-dependency #:missing-dependency-of-version #:missing-requires #:missing-parent #:missing-required-by #:missing-version)) (in-package :asdf/find-component) ;;;; Missing component conditions (with-upgradability () (define-condition missing-component (system-definition-error) ((requires :initform "(unnamed)" :reader missing-requires :initarg :requires) (parent :initform nil :reader missing-parent :initarg :parent))) (define-condition missing-component-of-version (missing-component) ((version :initform nil :reader missing-version :initarg :version))) (define-condition missing-dependency (missing-component) ((required-by :initarg :required-by :reader missing-required-by))) (defmethod print-object ((c missing-dependency) s) (format s (compatfmt "~@<~A, required by ~A~@:>") (call-next-method c nil) (missing-required-by c))) (define-condition missing-dependency-of-version (missing-dependency missing-component-of-version) ()) (defmethod print-object ((c missing-component) s) (format s (compatfmt "~@") (missing-requires c) (when (missing-parent c) (coerce-name (missing-parent c))))) (defmethod print-object ((c missing-component-of-version) s) (format s (compatfmt "~@") (missing-requires c) (missing-version c) (when (missing-parent c) (coerce-name (missing-parent c)))))) ;;;; Finding components (with-upgradability () (defgeneric resolve-dependency-combination (component combinator arguments) (:documentation "Return a component satisfying the dependency specification (COMBINATOR . ARGUMENTS) in the context of COMPONENT")) ;; Methods for find-component ;; If the base component is a string, resolve it as a system, then if not nil follow the path. (defmethod find-component ((base string) path &key registered) (if-let ((s (if registered (registered-system base) (find-system base nil)))) (find-component s path :registered registered))) ;; If the base component is a symbol, coerce it to a name if not nil, and resolve that. ;; If nil, use the path as base if not nil, or else return nil. (defmethod find-component ((base symbol) path &key registered) (cond (base (find-component (coerce-name base) path :registered registered)) (path (find-component path nil :registered registered)) (t nil))) ;; If the base component is a cons cell, resolve its car, and add its cdr to the path. (defmethod find-component ((base cons) path &key registered) (find-component (car base) (cons (cdr base) path) :registered registered)) ;; If the base component is a parent-component and the path a string, find the named child. (defmethod find-component ((parent parent-component) (name string) &key registered) (declare (ignorable registered)) (compute-children-by-name parent :only-if-needed-p t) (values (gethash name (component-children-by-name parent)))) ;; If the path is a symbol, coerce it to a name if non-nil, or else just return the base. (defmethod find-component (base (name symbol) &key registered) (if name (find-component base (coerce-name name) :registered registered) base)) ;; If the path is a cons, first resolve its car as path, then its cdr. (defmethod find-component ((c component) (name cons) &key registered) (find-component (find-component c (car name) :registered registered) (cdr name) :registered registered)) ;; If the path is a component, return it, disregarding the base. (defmethod find-component ((base t) (actual component) &key registered) (declare (ignorable registered)) actual) ;; Resolve dependency NAME in the context of a COMPONENT, with given optional VERSION constraint. ;; This (private) function is used below by RESOLVE-DEPENDENCY-SPEC and by the :VERSION spec. (defun resolve-dependency-name (component name &optional version) (loop (restart-case (return (let ((comp (find-component (component-parent component) name))) (unless comp (error 'missing-dependency :required-by component :requires name)) (when version (unless (version-satisfies comp version) (error 'missing-dependency-of-version :required-by component :version version :requires name))) comp)) (retry () :report (lambda (s) (format s (compatfmt "~@") name)) :test (lambda (c) (or (null c) (and (typep c 'missing-dependency) (eq (missing-required-by c) component) (equal (missing-requires c) name)))) (unless (component-parent component) (let ((name (coerce-name name))) (unset-asdf-cache-entry `(find-system ,name)))))))) ;; Resolve dependency specification DEP-SPEC in the context of COMPONENT. ;; This is notably used by MAP-DIRECT-DEPENDENCIES to process the results of COMPONENT-DEPENDS-ON ;; and by PARSE-DEFSYSTEM to process DEFSYSTEM-DEPENDS-ON. (defun resolve-dependency-spec (component dep-spec) (let ((component (find-component () component))) (if (atom dep-spec) (resolve-dependency-name component dep-spec) (resolve-dependency-combination component (car dep-spec) (cdr dep-spec))))) ;; Methods for RESOLVE-DEPENDENCY-COMBINATION to parse lists as dependency specifications. (defmethod resolve-dependency-combination (component combinator arguments) (parameter-error (compatfmt "~@") 'resolve-dependency-combination (cons combinator arguments) component)) (defmethod resolve-dependency-combination (component (combinator (eql :feature)) arguments) (when (featurep (first arguments)) (resolve-dependency-spec component (second arguments)))) (defmethod resolve-dependency-combination (component (combinator (eql :version)) arguments) (resolve-dependency-name component (first arguments) (second arguments)))) ;; See lp#527788 ;;;; ------------------------------------------------------------------------- ;;;; Forcing (uiop/package:define-package :asdf/forcing (:recycle :asdf/forcing :asdf/plan :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/operation :asdf/system :asdf/system-registry) (:export #:forcing #:make-forcing #:forced #:forced-not #:performable-p #:normalize-forced-systems #:normalize-forced-not-systems #:action-forced-p #:action-forced-not-p)) (in-package :asdf/forcing) ;;;; Forcing (with-upgradability () (defclass forcing () (;; Can plans using this forcing be PERFORMed? A plan that has different force and force-not ;; settings than the session can only be used for read-only queries that do not cause the ;; status of any action to be raised. (performable-p :initform nil :initarg :performable-p :reader performable-p) ;; Parameters (parameters :initform nil :initarg :parameters :reader parameters) ;; Table of systems specified via :force arguments (forced :initarg :forced :reader forced) ;; Table of systems specified via :force-not argument (and/or immutable) (forced-not :initarg :forced-not :reader forced-not))) (defgeneric action-forced-p (forcing operation component) (:documentation "Is this action forced to happen in this plan?")) (defgeneric action-forced-not-p (forcing operation component) (:documentation "Is this action forced to not happen in this plan? Takes precedence over action-forced-p.")) (defun normalize-forced-systems (force system) "Given a SYSTEM on which operate is called and the specified FORCE argument, extract a hash-set of systems that are forced, or a predicate on system names, or NIL if none are forced, or :ALL if all are." (etypecase force ((or (member nil :all) hash-table function) force) (cons (list-to-hash-set (mapcar #'coerce-name force))) ((eql t) (when system (list-to-hash-set (list (coerce-name system))))))) (defun normalize-forced-not-systems (force-not system) "Given a SYSTEM on which operate is called, the specified FORCE-NOT argument, and the set of IMMUTABLE systems, extract a hash-set of systems that are effectively forced-not, or predicate on system names, or NIL if none are forced, or :ALL if all are." (let ((requested (etypecase force-not ((or (member nil :all) hash-table function) force-not) (cons (list-to-hash-set (mapcar #'coerce-name force-not))) ((eql t) (if system (let ((name (coerce-name system))) #'(lambda (x) (not (equal x name)))) :all))))) (if (and *immutable-systems* requested) #'(lambda (x) (or (call-function requested x) (call-function *immutable-systems* x))) (or *immutable-systems* requested)))) ;; TODO: shouldn't we be looking up the primary system name, rather than the system name? (defun action-override-p (forcing operation component override-accessor) "Given a plan, an action, and a function that given the plan accesses a set of overrides, i.e. force or force-not, see if the override applies to the current action." (declare (ignore operation)) (call-function (funcall override-accessor forcing) (coerce-name (component-system (find-component () component))))) (defmethod action-forced-p (forcing operation component) (and ;; Did the user ask us to re-perform the action? (action-override-p forcing operation component 'forced) ;; You really can't force a builtin system and :all doesn't apply to it. (not (builtin-system-p (component-system component))))) (defmethod action-forced-not-p (forcing operation component) ;; Did the user ask us to not re-perform the action? ;; NB: force-not takes precedence over force, as it should (action-override-p forcing operation component 'forced-not)) ;; Null forcing means no forcing either way (defmethod action-forced-p ((forcing null) (operation operation) (component component)) nil) (defmethod action-forced-not-p ((forcing null) (operation operation) (component component)) nil) (defun or-function (fun1 fun2) (cond ((or (null fun2) (eq fun1 :all)) fun1) ((or (null fun1) (eq fun2 :all)) fun2) (t #'(lambda (x) (or (call-function fun1 x) (call-function fun2 x)))))) (defun make-forcing (&key performable-p system (force nil force-p) (force-not nil force-not-p) &allow-other-keys) (let* ((session-forcing (when *asdf-session* (forcing *asdf-session*))) (system (and system (coerce-name system))) (forced (normalize-forced-systems force system)) (forced-not (normalize-forced-not-systems force-not system)) (parameters `(,@(when force `(:force ,force)) ,@(when force-not `(:force-not ,force-not)) ,@(when (or (eq force t) (eq force-not t)) `(:system ,system)) ,@(when performable-p `(:performable-p t)))) forcing) (cond ((not session-forcing) (setf forcing (make-instance 'forcing :performable-p performable-p :parameters parameters :forced forced :forced-not forced-not)) (when (and performable-p *asdf-session*) (setf (forcing *asdf-session*) forcing))) (performable-p (when (and (not (equal parameters (parameters session-forcing))) (or force-p force-not-p)) (parameter-error "~*~S and ~S arguments not allowed in a nested call to ~3:*~S ~ unless identically to toplevel" (find-symbol* :operate :asdf) :force :force-not)) (setf forcing session-forcing)) (t (setf forcing (make-instance 'forcing ;; Combine force and force-not with values from the toplevel-plan :parameters `(,@parameters :on-top-of ,(parameters session-forcing)) :forced (or-function (forced session-forcing) forced) :forced-not (or-function (forced-not session-forcing) forced-not))))) forcing)) (defmethod print-object ((forcing forcing) stream) (print-unreadable-object (forcing stream :type t) (format stream "~{~S~^ ~}" (parameters forcing)))) ;; During upgrade, the *asdf-session* may legitimately be NIL, so we must handle that case. (defmethod forcing ((x null)) (if-let (session (toplevel-asdf-session)) (forcing session) (make-forcing :performable-p t))) ;; When performing a plan that is a list of actions, use the toplevel asdf sesssion forcing. (defmethod forcing ((x cons)) (forcing (toplevel-asdf-session)))) ;;;; ------------------------------------------------------------------------- ;;;; Plan (uiop/package:define-package :asdf/plan ;; asdf/action below is needed for required-components, traverse-action and traverse-sub-actions ;; that used to live there before 3.2.0. (:recycle :asdf/plan :asdf/action :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/operation :asdf/action :asdf/lisp-action :asdf/system :asdf/system-registry :asdf/find-component :asdf/forcing) (:export #:plan #:plan-traversal #:sequential-plan #:*plan-class* #:action-status #:status-stamp #:status-index #:status-done-p #:status-keep-p #:status-need-p #:action-already-done-p #:+status-good+ #:+status-todo+ #:+status-void+ #:system-out-of-date #:action-up-to-date-p #:circular-dependency #:circular-dependency-actions #:needed-in-image-p #:map-direct-dependencies #:reduce-direct-dependencies #:direct-dependencies #:compute-action-stamp #:traverse-action #:record-dependency #:make-plan #:plan-actions #:plan-actions-r #:perform-plan #:mark-as-done #:required-components #:filtered-sequential-plan #:plan-component-type #:plan-keep-operation #:plan-keep-component)) (in-package :asdf/plan) ;;;; Generic plan traversal class (with-upgradability () (defclass plan () () (:documentation "Base class for a plan based on which ASDF can build a system")) (defclass plan-traversal (plan) (;; The forcing parameters for this plan. Also indicates whether the plan is performable, ;; in which case the forcing is the same as for the entire session. (forcing :initform (forcing (toplevel-asdf-session)) :initarg :forcing :reader forcing)) (:documentation "Base class for plans that simply traverse dependencies")) ;; Sequential plans (the default) (defclass sequential-plan (plan-traversal) ((actions-r :initform nil :accessor plan-actions-r)) (:documentation "Simplest, default plan class, accumulating a sequence of actions")) (defgeneric plan-actions (plan) (:documentation "Extract from a plan a list of actions to perform in sequence")) (defmethod plan-actions ((plan list)) plan) (defmethod plan-actions ((plan sequential-plan)) (reverse (plan-actions-r plan))) (defgeneric record-dependency (plan operation component) (:documentation "Record that, within PLAN, performing OPERATION on COMPONENT depends on all of the (OPERATION . COMPONENT) actions in the current ASDF session's VISITING-ACTION-LIST. You can get a single action which dominates the set of dependencies corresponding to this call with (first (visiting-action-list *asdf-session*)) since VISITING-ACTION-LIST is a stack whose top action depends directly on its second action, and whose second action depends directly on its third action, and so forth.")) ;; No need to record a dependency to build a full graph, just accumulate nodes in order. (defmethod record-dependency ((plan sequential-plan) (o operation) (c component)) (values))) (when-upgrading (:version "3.3.0") (defmethod initialize-instance :after ((plan plan-traversal) &key &allow-other-keys))) ;;;; Planned action status (with-upgradability () (defclass action-status () ((bits :type fixnum :initarg :bits :reader status-bits :documentation "bitmap describing the status of the action.") (stamp :type (or integer boolean) :initarg :stamp :reader status-stamp :documentation "STAMP associated with the ACTION if it has been completed already in some previous session or image, T if it was done and builtin the image, or NIL if it needs to be done.") (level :type fixnum :initarg :level :initform 0 :reader status-level :documentation "the highest (operate-level) at which the action was needed") (index :type (or integer null) :initarg :index :initform nil :reader status-index :documentation "INDEX associated with the ACTION in the current session, or NIL if no the status is considered outside of a specific plan.")) (:documentation "Status of an action in a plan")) ;; STAMP KEEP-P DONE-P NEED-P symbol bitmap previously currently ;; not-nil T T T => GOOD 7 up-to-date done (e.g. file previously loaded) ;; not-nil T T NIL => HERE 6 up-to-date unplanned yet done ;; not-nil T NIL T => REDO 5 up-to-date planned (e.g. file to load) ;; not-nil T NIL NIL => SKIP 4 up-to-date unplanned (e.g. file compiled) ;; not-nil NIL T T => DONE 3 out-of-date done ;; not-nil NIL T NIL => WHAT 2 out-of-date unplanned yet done(?) ;; NIL NIL NIL T => TODO 1 out-of-date planned ;; NIL NIL NIL NIL => VOID 0 out-of-date unplanned ;; ;; Note that a VOID status cannot happen as part of a transitive dependency of a wanted node ;; while traversing a node with TRAVERSE-ACTION; it can only happen while checking whether an ;; action is up-to-date with ACTION-UP-TO-DATE-P. ;; ;; When calling TRAVERSE-ACTION, the +need-bit+ is set, ;; unless the action is up-to-date and not needed-in-image (HERE, SKIP). ;; When PERFORMing an action, the +done-bit+ is set. ;; When the +need-bit+ is set but not the +done-bit+, the level slot indicates which level of ;; OPERATE it was last marked needed for; if it happens to be needed at a higher-level, then ;; its urgency (and that of its transitive dependencies) must be escalated so that it will be ;; done before the end of this level of operate. ;; ;; Also, when no ACTION-STATUS is associated to an action yet, NIL serves as a bottom value. ;; (defparameter +keep-bit+ 4) (defparameter +done-bit+ 2) (defparameter +need-bit+ 1) (defparameter +good-bits+ 7) (defparameter +todo-bits+ 1) (defparameter +void-bits+ 0) (defparameter +status-good+ (make-instance 'action-status :bits +good-bits+ :stamp t)) (defparameter +status-todo+ (make-instance 'action-status :bits +todo-bits+ :stamp nil)) (defparameter +status-void+ (make-instance 'action-status :bits +void-bits+ :stamp nil))) (with-upgradability () (defun make-action-status (&key bits stamp (level 0) index) (check-type bits (integer 0 7)) (check-type stamp (or integer boolean)) (check-type level (integer 0 #.most-positive-fixnum)) (check-type index (or integer null)) (assert (eq (null stamp) (zerop (logand bits #.(logior +keep-bit+ +done-bit+)))) () "Bad action-status :bits ~S :stamp ~S" bits stamp) (block nil (when (and (null index) (zerop level)) (case bits (#.+void-bits+ (return +status-void+)) (#.+todo-bits+ (return +status-todo+)) (#.+good-bits+ (when (eq stamp t) (return +status-good+))))) (make-instance 'action-status :bits bits :stamp stamp :level level :index index))) (defun status-keep-p (status) (plusp (logand (status-bits status) #.+keep-bit+))) (defun status-done-p (status) (plusp (logand (status-bits status) #.+done-bit+))) (defun status-need-p (status) (plusp (logand (status-bits status) #.+need-bit+))) (defun merge-action-status (status1 status2) ;; status-and "Return the earliest status later than both status1 and status2" (make-action-status :bits (logand (status-bits status1) (status-bits status2)) :stamp (latest-timestamp (status-stamp status1) (status-stamp status2)) :level (min (status-level status1) (status-level status2)) :index (or (status-index status1) (status-index status2)))) (defun mark-status-needed (status &optional (level (operate-level))) ;; limited status-or "Return the same status but with the need bit set, for the given level" (if (and (status-need-p status) (>= (status-level status) level)) status (make-action-status :bits (logior (status-bits status) +need-bit+) :level (max level (status-level status)) :stamp (status-stamp status) :index (status-index status)))) (defmethod print-object ((status action-status) stream) (print-unreadable-object (status stream :type t) (with-slots (bits stamp level index) status (format stream "~{~S~^ ~}" `(:bits ,bits :stamp ,stamp :level ,level :index ,index))))) (defgeneric action-status (plan operation component) (:documentation "Returns the ACTION-STATUS associated to the action of OPERATION on COMPONENT in the PLAN, or NIL if the action wasn't visited yet as part of the PLAN.")) (defgeneric (setf action-status) (new-status plan operation component) (:documentation "Sets the ACTION-STATUS associated to the action of OPERATION on COMPONENT in the PLAN")) (defmethod action-status ((plan null) (o operation) (c component)) (multiple-value-bind (stamp done-p) (component-operation-time o c) (if done-p (make-action-status :bits #.+keep-bit+ :stamp stamp) +status-void+))) (defmethod (setf action-status) (new-status (plan null) (o operation) (c component)) (let ((times (component-operation-times c))) (if (status-done-p new-status) (setf (gethash o times) (status-stamp new-status)) (remhash o times))) new-status) ;; Handle FORCED-NOT: it makes an action return its current timestamp as status (defmethod action-status ((p plan) (o operation) (c component)) ;; TODO: should we instead test something like: ;; (action-forced-not-p plan operation (primary-system component)) (or (gethash (make-action o c) (visited-actions *asdf-session*)) (when (action-forced-not-p (forcing p) o c) (let ((status (action-status nil o c))) (setf (gethash (make-action o c) (visited-actions *asdf-session*)) (make-action-status :bits +good-bits+ :stamp (or (and status (status-stamp status)) t) :index (incf (total-action-count *asdf-session*)))))))) (defmethod (setf action-status) (new-status (p plan) (o operation) (c component)) (setf (gethash (make-action o c) (visited-actions *asdf-session*)) new-status)) (defmethod (setf action-status) :after (new-status (p sequential-plan) (o operation) (c component)) (unless (status-done-p new-status) (push (make-action o c) (plan-actions-r p))))) ;;;; Is the action needed in this image? (with-upgradability () (defgeneric needed-in-image-p (operation component) (:documentation "Is the action of OPERATION on COMPONENT needed in the current image to be meaningful, or could it just as well have been done in another Lisp image?")) (defmethod needed-in-image-p ((o operation) (c component)) ;; We presume that actions that modify the filesystem don't need be run ;; in the current image if they have already been done in another, ;; and can be run in another process (e.g. a fork), ;; whereas those that don't are meant to side-effect the current image and can't. (not (output-files o c)))) ;;;; Visiting dependencies of an action and computing action stamps (with-upgradability () (defun map-direct-dependencies (operation component fun) "Call FUN on all the valid dependencies of the given action in the given plan" (loop :for (dep-o-spec . dep-c-specs) :in (component-depends-on operation component) :for dep-o = (find-operation operation dep-o-spec) :when dep-o :do (loop :for dep-c-spec :in dep-c-specs :for dep-c = (and dep-c-spec (resolve-dependency-spec component dep-c-spec)) :when (action-valid-p dep-o dep-c) :do (funcall fun dep-o dep-c)))) (defun reduce-direct-dependencies (operation component combinator seed) "Reduce the direct dependencies to a value computed by iteratively calling COMBINATOR for each dependency action on the dependency's operation and component and an accumulator initialized with SEED." (map-direct-dependencies operation component #'(lambda (dep-o dep-c) (setf seed (funcall combinator dep-o dep-c seed)))) seed) (defun direct-dependencies (operation component) "Compute a list of the direct dependencies of the action within the plan" (reverse (reduce-direct-dependencies operation component #'acons nil))) ;; In a distant future, get-file-stamp, component-operation-time and latest-stamp ;; shall also be parametrized by the plan, or by a second model object, ;; so they need not refer to the state of the filesystem, ;; and the stamps could be cryptographic checksums rather than timestamps. ;; Such a change remarkably would only affect COMPUTE-ACTION-STAMP. (define-condition dependency-not-done (warning) ((op :initarg :op) (component :initarg :component) (dep-op :initarg :dep-op) (dep-component :initarg :dep-component) (plan :initarg :plan :initform nil)) (:report (lambda (condition stream) (with-slots (op component dep-op dep-component plan) condition (format stream "Computing just-done stamp ~@[in plan ~S~] for action ~S, but dependency ~S wasn't done yet!" plan (action-path (make-action op component)) (action-path (make-action dep-op dep-component))))))) (defmethod compute-action-stamp (plan (o operation) (c component) &key just-done) ;; Given an action, figure out at what time in the past it has been done, ;; or if it has just been done, return the time that it has. ;; Returns two values: ;; 1- the TIMESTAMP of the action if it has already been done and is up to date, ;; or NIL is either hasn't been done or is out of date. ;; (An ASDF extension could use a cryptographic digest instead.) ;; 2- the DONE-IN-IMAGE-P boolean flag that is T if the action has already been done ;; in the current image, or NIL if it hasn't. ;; Note that if e.g. LOAD-OP only depends on up-to-date files, but ;; hasn't been done in the current image yet, then it can have a non-NIL timestamp, ;; yet a NIL done-in-image-p flag: we can predict what timestamp it will have once loaded, ;; i.e. that of the input-files. ;; If just-done is NIL, these values return are the notional fields of ;; a KEEP, REDO or TODO status (VOID is possible, but probably an error). ;; If just-done is T, they are the notional fields of DONE status ;; (or, if something went wrong, TODO). (nest (block ()) (let* ((dep-status ; collect timestamp from dependencies (or T if forced or out-of-date) (reduce-direct-dependencies o c #'(lambda (do dc status) ;; out-of-date dependency: don't bother looking further (let ((action-status (action-status plan do dc))) (cond ((and action-status (or (status-keep-p action-status) (and just-done (status-stamp action-status)))) (merge-action-status action-status status)) (just-done ;; It's OK to lose some ASDF action stamps during self-upgrade (unless (equal "asdf" (primary-system-name dc)) (warn 'dependency-not-done :plan plan :op o :component c :dep-op do :dep-component dc)) status) (t (return (values nil nil)))))) +status-good+)) (dep-stamp (status-stamp dep-status)))) (let* (;; collect timestamps from inputs, and exit early if any is missing (in-files (input-files o c)) (in-stamps (mapcar #'get-file-stamp in-files)) (missing-in (loop :for f :in in-files :for s :in in-stamps :unless s :collect f)) (latest-in (timestamps-latest (cons dep-stamp in-stamps)))) (when (and missing-in (not just-done)) (return (values nil nil)))) (let* (;; collect timestamps from outputs, and exit early if any is missing (out-files (remove-if 'null (output-files o c))) (out-stamps (mapcar (if just-done 'register-file-stamp 'get-file-stamp) out-files)) (missing-out (loop :for f :in out-files :for s :in out-stamps :unless s :collect f)) (earliest-out (timestamps-earliest out-stamps))) (when (and missing-out (not just-done)) (return (values nil nil)))) (let (;; Time stamps from the files at hand, and whether any is missing (all-present (not (or missing-in missing-out))) ;; Has any input changed since we last generated the files? ;; Note that we use timestamp<= instead of timestamp< to play nice with generated files. ;; Any race condition is intrinsic to the limited timestamp resolution. (up-to-date-p (timestamp<= latest-in earliest-out)) ;; If everything is up to date, the latest of inputs and outputs is our stamp (done-stamp (timestamps-latest (cons latest-in out-stamps)))) ;; Warn if some files are missing: ;; either our model is wrong or some other process is messing with our files. (when (and just-done (not all-present)) ;; Shouldn't that be an error instead? (warn "~A completed without ~:[~*~;~*its input file~:p~2:*~{ ~S~}~*~]~ ~:[~; or ~]~:[~*~;~*its output file~:p~2:*~{ ~S~}~*~]" (action-description o c) missing-in (length missing-in) (and missing-in missing-out) missing-out (length missing-out)))) (let (;; There are three kinds of actions: (out-op (and out-files t)) ; those that create files on the filesystem ;;(image-op (and in-files (null out-files))) ; those that load stuff into the image ;;(null-op (and (null out-files) (null in-files))) ; placeholders that do nothing )) (if (or just-done ;; The done-stamp is valid: if we're just done, or (and all-present ;; if all filesystem effects are up-to-date up-to-date-p (operation-done-p o c) ;; and there's no invalidating reason. (not (action-forced-p (forcing (or plan *asdf-session*)) o c)))) (values done-stamp ;; return the hard-earned timestamp (or just-done out-op ;; A file-creating op is done when all files are up to date. ;; An image-effecting operation is done when (and (status-done-p dep-status) ;; all the dependencies were done, and (multiple-value-bind (perform-stamp perform-done-p) (component-operation-time o c) (and perform-done-p ;; the op was actually run, (equal perform-stamp done-stamp)))))) ;; with a matching stamp. ;; done-stamp invalid: return a timestamp in an indefinite future, action not done yet (values nil nil))))) ;;;; The four different actual traversals: ;; * TRAVERSE-ACTION o c T: Ensure all dependencies are either up-to-date in-image, or planned ;; * TRAVERSE-ACTION o c NIL: Ensure all dependencies are up-to-date or planned, in-image or not ;; * ACTION-UP-TO-DATE-P: Check whether some (defsystem-depends-on ?) dependencies are up to date ;; * COLLECT-ACTION-DEPENDENCIES: Get the dependencies (filtered), don't change any status (with-upgradability () ;; Compute the action status for a newly visited action. (defun compute-action-status (plan operation component need-p) (multiple-value-bind (stamp done-p) (compute-action-stamp plan operation component) (assert (or stamp (not done-p))) (make-action-status :bits (logior (if stamp #.+keep-bit+ 0) (if done-p #.+done-bit+ 0) (if need-p #.+need-bit+ 0)) :stamp stamp :level (operate-level) :index (incf (total-action-count *asdf-session*))))) ;; TRAVERSE-ACTION, in the context of a given PLAN object that accumulates dependency data, ;; visits the action defined by its OPERATION and COMPONENT arguments, ;; and all its transitive dependencies (unless already visited), ;; in the context of the action being (or not) NEEDED-IN-IMAGE-P, ;; i.e. needs to be done in the current image vs merely have been done in a previous image. ;; ;; TRAVERSE-ACTION updates the VISITED-ACTIONS entries for the action and for all its ;; transitive dependencies (that haven't been sufficiently visited so far). ;; It does not return any usable value. ;; ;; Note that for an XCVB-like plan with one-image-per-file-outputting-action, ;; the below method would be insufficient, since it assumes a single image ;; to traverse each node at most twice; non-niip actions would be traversed only once, ;; but niip nodes could be traversed once per image, i.e. once plus once per non-niip action. (defun traverse-action (plan operation component needed-in-image-p) (block nil (unless (action-valid-p operation component) (return)) ;; Record the dependency. This hook is needed by POIU, which tracks a full dependency graph, ;; instead of just a dependency order as in vanilla ASDF. ;; TODO: It is also needed to detect OPERATE-in-PERFORM. (record-dependency plan operation component) (while-visiting-action (operation component) ; maintain context, handle circularity. ;; needed-in-image distinguishes b/w things that must happen in the ;; current image and those things that simply need to have been done in a previous one. (let* ((aniip (needed-in-image-p operation component)) ; action-specific needed-in-image ;; effective niip: meaningful for the action and required by the plan as traversed (eniip (and aniip needed-in-image-p)) ;; status: have we traversed that action previously, and if so what was its status? (status (action-status plan operation component)) (level (operate-level))) (when (and status (or (status-done-p status) ;; all done (and (status-need-p status) (<= level (status-level status))) ;; already visited (and (status-keep-p status) (not eniip)))) ;; up-to-date and not eniip (return)) ; Already visited with sufficient need-in-image level! (labels ((visit-action (niip) ; We may visit the action twice, once with niip NIL, then T (map-direct-dependencies ; recursively traverse dependencies operation component #'(lambda (o c) (traverse-action plan o c niip))) ;; AFTER dependencies have been traversed, compute action stamp (let* ((status (if status (mark-status-needed status level) (compute-action-status plan operation component t))) (out-of-date-p (not (status-keep-p status))) (to-perform-p (or out-of-date-p (and niip (not (status-done-p status)))))) (cond ; it needs be done if it's out of date or needed in image but absent ((and out-of-date-p (not niip)) ; if we need to do it, (visit-action t)) ; then we need to do it *in the (current) image*! (t (setf (action-status plan operation component) status) (when (status-done-p status) (setf (component-operation-time operation component) (status-stamp status))) (when to-perform-p ; if it needs to be added to the plan, count it (incf (planned-action-count *asdf-session*)) (unless aniip ; if it's output-producing, count it (incf (planned-output-action-count *asdf-session*))))))))) (visit-action eniip)))))) ; visit the action ;; NB: This is not an error, not a warning, but a normal expected condition, ;; to be to signaled by FIND-SYSTEM when it detects an out-of-date system, ;; *before* it tries to replace it with a new definition. (define-condition system-out-of-date (condition) ((name :initarg :name :reader component-name)) (:documentation "condition signaled when a system is detected as being out of date") (:report (lambda (c s) (format s "system ~A is out of date" (component-name c))))) (defun action-up-to-date-p (plan operation component) "Check whether an action was up-to-date at the beginning of the session. Update the VISITED-ACTIONS table with the known status, but don't add anything to the PLAN." (block nil (unless (action-valid-p operation component) (return t)) (while-visiting-action (operation component) ; maintain context, handle circularity. ;; Do NOT record the dependency: it might be out of date. (let ((status (or (action-status plan operation component) (setf (action-status plan operation component) (let ((dependencies-up-to-date-p (handler-case (block nil (map-direct-dependencies operation component #'(lambda (o c) (unless (action-up-to-date-p plan o c) (return nil)))) t) (system-out-of-date () nil)))) (if dependencies-up-to-date-p (compute-action-status plan operation component nil) +status-void+)))))) (and (status-keep-p status) (status-stamp status))))))) ;;;; Incidental traversals ;;; Making a FILTERED-SEQUENTIAL-PLAN can be used to, e.g., all of the source ;;; files required by a bundling operation. (with-upgradability () (defclass filtered-sequential-plan (sequential-plan) ((component-type :initform t :initarg :component-type :reader plan-component-type) (keep-operation :initform t :initarg :keep-operation :reader plan-keep-operation) (keep-component :initform t :initarg :keep-component :reader plan-keep-component)) (:documentation "A variant of SEQUENTIAL-PLAN that only records a subset of actions.")) (defmethod initialize-instance :after ((plan filtered-sequential-plan) &key system other-systems) ;; Ignore force and force-not, rely on other-systems: ;; force traversal of what we're interested in, i.e. current system or also others; ;; force-not traversal of what we're not interested in, i.e. other systems unless other-systems. (setf (slot-value plan 'forcing) (make-forcing :system system :force :all :force-not (if other-systems nil t)))) (defmethod plan-actions ((plan filtered-sequential-plan)) (with-slots (keep-operation keep-component) plan (loop :for action :in (call-next-method) :as o = (action-operation action) :as c = (action-component action) :when (and (typep o keep-operation) (typep c keep-component)) :collect (make-action o c)))) (defun collect-action-dependencies (plan operation component) (when (action-valid-p operation component) (while-visiting-action (operation component) ; maintain context, handle circularity. (let ((action (make-action operation component))) (unless (nth-value 1 (gethash action (visited-actions *asdf-session*))) (setf (gethash action (visited-actions *asdf-session*)) nil) (when (and (typep component (plan-component-type plan)) (not (action-forced-not-p (forcing plan) operation component))) (map-direct-dependencies operation component #'(lambda (o c) (collect-action-dependencies plan o c))) (push action (plan-actions-r plan)))))))) (defgeneric collect-dependencies (operation component &key &allow-other-keys) (:documentation "Given an action, build a plan for all of its dependencies.")) (define-convenience-action-methods collect-dependencies (operation component &key)) (defmethod collect-dependencies ((operation operation) (component component) &rest keys &key &allow-other-keys) (let ((plan (apply 'make-instance 'filtered-sequential-plan :system (component-system component) keys))) (loop :for action :in (direct-dependencies operation component) :do (collect-action-dependencies plan (action-operation action) (action-component action))) (plan-actions plan))) (defun required-components (system &rest keys &key (goal-operation 'load-op) &allow-other-keys) "Given a SYSTEM and a GOAL-OPERATION (default LOAD-OP), traverse the dependencies and return a list of the components involved in building the desired action." (with-asdf-session (:override t) (remove-duplicates (mapcar 'action-component (apply 'collect-dependencies goal-operation system (remove-plist-key :goal-operation keys))) :from-end t)))) ;;;; High-level interface: make-plan, perform-plan (with-upgradability () (defgeneric make-plan (plan-class operation component &key &allow-other-keys) (:documentation "Generate and return a plan for performing OPERATION on COMPONENT.")) (define-convenience-action-methods make-plan (plan-class operation component &key)) (defgeneric mark-as-done (plan-class operation component) (:documentation "Mark an action as done in a plan, after performing it.")) (define-convenience-action-methods mark-as-done (plan-class operation component)) (defgeneric perform-plan (plan &key) (:documentation "Actually perform a plan and build the requested actions")) (defparameter* *plan-class* 'sequential-plan "The default plan class to use when building with ASDF") (defmethod make-plan (plan-class (o operation) (c component) &rest keys &key &allow-other-keys) (with-asdf-session () (let ((plan (apply 'make-instance (or plan-class *plan-class*) keys))) (traverse-action plan o c t) plan))) (defmethod perform-plan :around ((plan t) &key) (assert (performable-p (forcing plan)) () "plan not performable") (let ((*package* *package*) (*readtable* *readtable*)) (with-compilation-unit () ;; backward-compatibility. (call-next-method)))) ;; Going forward, see deferred-warning support in lisp-build. (defun action-already-done-p (plan operation component) (if-let (status (action-status plan operation component)) (status-done-p status))) (defmethod perform-plan ((plan t) &key) (loop :for action :in (plan-actions plan) :as o = (action-operation action) :as c = (action-component action) :do (unless (action-already-done-p plan o c) (perform-with-restarts o c) (mark-as-done plan o c)))) (defmethod mark-as-done ((plan plan) (o operation) (c component)) (let ((plan-status (action-status plan o c)) (perform-status (action-status nil o c))) (assert (and (status-stamp perform-status) (status-keep-p perform-status)) () "Just performed ~A but failed to mark it done" (action-description o c)) (setf (action-status plan o c) (make-action-status :bits (logior (status-bits plan-status) +done-bit+) :stamp (status-stamp perform-status) :level (status-level plan-status) :index (status-index plan-status)))))) ;;;; ------------------------------------------------------------------------- ;;;; Invoking Operations (uiop/package:define-package :asdf/operate (:recycle :asdf/operate :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/system :asdf/system-registry :asdf/find-component :asdf/operation :asdf/action :asdf/lisp-action :asdf/forcing :asdf/plan) (:export #:operate #:oos #:build-op #:make #:load-system #:load-systems #:load-systems* #:compile-system #:test-system #:require-system #:module-provide-asdf #:component-loaded-p #:already-loaded-systems #:recursive-operate)) (in-package :asdf/operate) (with-upgradability () (defgeneric operate (operation component &key) (:documentation "Operate does mainly four things for the user: 1. Resolves the OPERATION designator into an operation object. OPERATION is typically a symbol denoting an operation class, instantiated with MAKE-OPERATION. 2. Resolves the COMPONENT designator into a component object. COMPONENT is typically a string or symbol naming a system, loaded from disk using FIND-SYSTEM. 3. It then calls MAKE-PLAN with the operation and system as arguments. 4. Finally calls PERFORM-PLAN on the resulting plan to actually build the system. The entire computation is wrapped in WITH-COMPILATION-UNIT and error handling code. If a VERSION argument is supplied, then operate also ensures that the system found satisfies it using the VERSION-SATISFIES method. If a PLAN-CLASS argument is supplied, that class is used for the plan. If a PLAN-OPTIONS argument is supplied, the options are passed to the plan. The :FORCE or :FORCE-NOT argument to OPERATE can be: T to force the inside of the specified system to be rebuilt (resp. not), without recursively forcing the other systems we depend on. :ALL to force all systems including other systems we depend on to be rebuilt (resp. not). (SYSTEM1 SYSTEM2 ... SYSTEMN) to force systems named in a given list :FORCE-NOT has precedence over :FORCE; builtin systems cannot be forced. For backward compatibility, all keyword arguments are passed to MAKE-OPERATION when instantiating a new operation, that will in turn be inherited by new operations. But do NOT depend on it, for this is deprecated behavior.")) (define-convenience-action-methods operate (operation component &key) :if-no-component (error 'missing-component :requires component)) ;; This method ensures that an ASDF upgrade is attempted as the very first thing, ;; with suitable state preservation in case in case it actually happens, ;; and that a few suitable dynamic bindings are established. (defmethod operate :around (operation component &rest keys &key verbose (on-warnings *compile-file-warnings-behaviour*) (on-failure *compile-file-failure-behaviour*)) (nest (with-asdf-session ()) (let* ((operation-remaker ;; how to remake the operation after ASDF was upgraded (if it was) (etypecase operation (operation (let ((name (type-of operation))) #'(lambda () (make-operation name)))) ((or symbol string) (constantly operation)))) (component-path (typecase component ;; to remake the component after ASDF upgrade (component (component-find-path component)) (t component))) (system-name (labels ((first-name (x) (etypecase x ((or string symbol) x) ; NB: includes the NIL case. (cons (or (first-name (car x)) (first-name (cdr x))))))) (coerce-name (first-name component-path))))) (apply 'make-forcing :performable-p t :system system-name keys) ;; Before we operate on any system, make sure ASDF is up-to-date, ;; for if an upgrade is ever attempted at any later time, there may be BIG trouble. (unless (asdf-upgraded-p (toplevel-asdf-session)) (setf (asdf-upgraded-p (toplevel-asdf-session)) t) (when (upgrade-asdf) ;; If we were upgraded, restart OPERATE the hardest of ways, for ;; its function may have been redefined. (return-from operate (with-asdf-session (:override t :override-cache t) (apply 'operate (funcall operation-remaker) component-path keys)))))) ;; Setup proper bindings around any operate call. (let* ((*verbose-out* (and verbose *standard-output*)) (*compile-file-warnings-behaviour* on-warnings) (*compile-file-failure-behaviour* on-failure))) (unwind-protect (progn (incf (operate-level)) (call-next-method)) (decf (operate-level))))) (defmethod operate :before ((operation operation) (component component) &key version) (unless (version-satisfies component version) (error 'missing-component-of-version :requires component :version version)) (record-dependency nil operation component)) (defmethod operate ((operation operation) (component component) &key plan-class plan-options) (let ((plan (apply 'make-plan plan-class operation component :forcing (forcing *asdf-session*) plan-options))) (perform-plan plan) (values operation plan))) (defun oos (operation component &rest args &key &allow-other-keys) (apply 'operate operation component args)) (setf (documentation 'oos 'function) (format nil "Short for _operate on system_ and an alias for the OPERATE function.~%~%~a" (documentation 'operate 'function))) (define-condition recursive-operate (warning) ((operation :initarg :operation :reader condition-operation) (component :initarg :component :reader condition-component) (action :initarg :action :reader condition-action)) (:report (lambda (c s) (format s (compatfmt "~@") 'operate (type-of (condition-operation c)) (component-find-path (condition-component c)) (action-path (condition-action c))))))) ;;;; Common operations (when-upgrading () (defmethod component-depends-on ((o prepare-op) (s system)) (call-next-method))) (with-upgradability () (defclass build-op (non-propagating-operation) () (:documentation "Since ASDF3, BUILD-OP is the recommended 'master' operation, to operate by default on a system or component, via the function BUILD. Its meaning is configurable via the :BUILD-OPERATION option of a component. which typically specifies the name of a specific operation to which to delegate the build, as a symbol or as a string later read as a symbol (after loading the defsystem-depends-on); if NIL is specified (the default), BUILD-OP falls back to LOAD-OP, that will load the system in the current image.")) (defmethod component-depends-on ((o build-op) (c component)) `((,(or (component-build-operation c) 'load-op) ,c) ,@(call-next-method))) (defun make (system &rest keys) "The recommended way to interact with ASDF3.1 is via (ASDF:MAKE :FOO). It will build system FOO using the operation BUILD-OP, the meaning of which is configurable by the system, and defaults to LOAD-OP, to load it in current image." (apply 'operate 'build-op system keys) t) (defun load-system (system &rest keys &key force force-not verbose version &allow-other-keys) "Shorthand for `(operate 'asdf:load-op system)`. See OPERATE for details." (declare (ignore force force-not verbose version)) (apply 'operate 'load-op system keys) t) (defun load-systems* (systems &rest keys) "Loading multiple systems at once." (dolist (s systems) (apply 'load-system s keys))) (defun load-systems (&rest systems) "Loading multiple systems at once." (load-systems* systems)) (defun compile-system (system &rest args &key force force-not verbose version &allow-other-keys) "Shorthand for `(asdf:operate 'asdf:compile-op system)`. See OPERATE for details." (declare (ignore force force-not verbose version)) (apply 'operate 'compile-op system args) t) (defun test-system (system &rest args &key force force-not verbose version &allow-other-keys) "Shorthand for `(asdf:operate 'asdf:test-op system)`. See OPERATE for details." (declare (ignore force force-not verbose version)) (apply 'operate 'test-op system args) t)) ;;;;; Define the function REQUIRE-SYSTEM, that, similarly to REQUIRE, ;; only tries to load its specified target if it's not loaded yet. (with-upgradability () (defun component-loaded-p (component) "Has the given COMPONENT been successfully loaded in the current image (yet)? Note that this returns true even if the component is not up to date." (if-let ((component (find-component component () :registered t))) (nth-value 1 (component-operation-time (make-operation 'load-op) component)))) (defun already-loaded-systems () "return a list of the names of the systems that have been successfully loaded so far" (mapcar 'coerce-name (remove-if-not 'component-loaded-p (registered-systems*))))) ;;;; Define the class REQUIRE-SYSTEM, to be hooked into CL:REQUIRE when possible, ;; i.e. for ABCL, CLISP, ClozureCL, CMUCL, ECL, MKCL and SBCL ;; Note that despite the two being homonyms, the _function_ require-system ;; and the _class_ require-system are quite distinct entities, fulfilling independent purposes. (with-upgradability () (defvar *modules-being-required* nil) (defclass require-system (system) ((module :initarg :module :initform nil :accessor required-module)) (:documentation "A SYSTEM subclass whose processing is handled by the implementation's REQUIRE rather than by internal ASDF mechanisms.")) (defmethod perform ((o compile-op) (c require-system)) nil) (defmethod perform ((o load-op) (s require-system)) (let* ((module (or (required-module s) (coerce-name s))) (*modules-being-required* (cons module *modules-being-required*))) (assert (null (component-children s))) (require module))) (defmethod resolve-dependency-combination (component (combinator (eql :require)) arguments) (unless (and (length=n-p arguments 1) (typep (car arguments) '(or string (and symbol (not null))))) (parameter-error (compatfmt "~@") 'resolve-dependency-combination (cons combinator arguments) component combinator)) ;; :require must be prepared for some implementations providing modules using ASDF, ;; as SBCL used to do, and others may might do. Thus, the system provided in the end ;; would be a downcased name as per module-provide-asdf above. For the same reason, ;; we cannot assume that the system in the end will be of type require-system, ;; but must check whether we can use find-system and short-circuit cl:require. ;; Otherwise, calling cl:require could result in nasty reentrant calls between ;; cl:require and asdf:operate that could potentially blow up the stack, ;; all the while defeating the consistency of the dependency graph. (let* ((module (car arguments)) ;; NB: we already checked that it was not null ;; CMUCL, MKCL, SBCL like their module names to be all upcase. (module-name (string module)) (system-name (string-downcase module)) (system (find-system system-name nil))) (or system (let ((system (make-instance 'require-system :name system-name :module module-name))) (register-system system) system)))) (defun module-provide-asdf (name) ;; We must use string-downcase, because modules are traditionally specified as symbols, ;; that implementations traditionally normalize as uppercase, for which we seek a system ;; with a name that is traditionally in lowercase. Case is lost along the way. That's fine. ;; We could make complex, non-portable rules to try to preserve case, and just documenting ;; them would be a hell that it would be a disservice to inflict on users. (let ((module-name (string name)) (system-name (string-downcase name))) (unless (member module-name *modules-being-required* :test 'equal) (let ((*modules-being-required* (cons module-name *modules-being-required*)) #+sbcl (sb-impl::*requiring* (remove module-name sb-impl::*requiring* :test 'equal))) (handler-bind (((or style-warning recursive-operate) #'muffle-warning) (missing-component (constantly nil)) (fatal-condition #'(lambda (e) (format *error-output* (compatfmt "~@~%") name e)))) (let ((*verbose-out* (make-broadcast-stream))) (let ((system (find-system system-name nil))) (when system ;; Do not use require-system after all, use load-system: ;; on the one hand, REQUIRE already uses *MODULES* not to load something twice, ;; on the other hand, REQUIRE-SYSTEM uses FORCE-NOT which may conflict with ;; the toplevel session forcing settings. (load-system system :verbose nil) t))))))))) ;;;; Some upgrade magic (with-upgradability () (defun restart-upgraded-asdf () ;; If we're in the middle of something, restart it. (let ((systems-being-defined (when *asdf-session* (prog1 (loop :for k :being :the hash-keys :of (asdf-cache) :when (eq (first k) 'find-system) :collect (second k)) (clrhash (asdf-cache)))))) ;; Regardless, clear defined systems, since they might be invalid ;; after an incompatible ASDF upgrade. (clear-registered-systems) ;; The configuration also may have to be upgraded. (upgrade-configuration) ;; If we were in the middle of an operation, be sure to restore the system being defined. (dolist (s systems-being-defined) (find-system s nil)))) (register-hook-function '*post-upgrade-cleanup-hook* 'restart-upgraded-asdf)) ;;;; ------------------------------------------------------------------------- ;;;; Finding systems (uiop/package:define-package :asdf/find-system (:recycle :asdf/find-system :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/system :asdf/operation :asdf/action :asdf/lisp-action :asdf/find-component :asdf/system-registry :asdf/plan :asdf/operate) (:import-from #:asdf/component #:%additional-input-files) (:export #:find-system #:locate-system #:load-asd #:define-op #:load-system-definition-error #:error-name #:error-pathname #:error-condition)) (in-package :asdf/find-system) (with-upgradability () (define-condition load-system-definition-error (system-definition-error) ((name :initarg :name :reader error-name) (pathname :initarg :pathname :reader error-pathname) (condition :initarg :condition :reader error-condition)) (:report (lambda (c s) (format s (compatfmt "~@") (error-name c) (error-pathname c) (error-condition c))))) ;;; Methods for find-system ;; Reject NIL as a system designator. (defmethod find-system ((name null) &optional (error-p t)) (when error-p (sysdef-error (compatfmt "~@")))) ;; Default method for find-system: resolve the argument using COERCE-NAME. (defmethod find-system (name &optional (error-p t)) (find-system (coerce-name name) error-p)) (defun find-system-if-being-defined (name) ;; This function finds systems being defined *in the current ASDF session*, as embodied by ;; its session cache, even before they are fully defined and registered in *registered-systems*. ;; The purpose of this function is to prevent races between two files that might otherwise ;; try overwrite each other's system objects, resulting in infinite loops and stack overflow. ;; This function explicitly MUST NOT find definitions merely registered in previous sessions. ;; NB: this function depends on a corresponding side-effect in parse-defsystem; ;; the precise protocol between the two functions may change in the future (or not). (first (gethash `(find-system ,(coerce-name name)) (asdf-cache)))) (defclass define-op (non-propagating-operation) () (:documentation "An operation to record dependencies on loading a .asd file.")) (defmethod record-dependency ((plan null) (operation t) (component t)) (unless (or (typep operation 'define-op) (and (typep operation 'load-op) (typep component 'system) (equal "asdf" (coerce-name component)))) (if-let ((action (first (visiting-action-list *asdf-session*)))) (let ((parent-operation (action-operation action)) (parent-component (action-component action))) (cond ((and (typep parent-operation 'define-op) (typep parent-component 'system)) (let ((action (cons operation component))) (unless (gethash action (definition-dependency-set parent-component)) (push (cons operation component) (definition-dependency-list parent-component)) (setf (gethash action (definition-dependency-set parent-component)) t)))) (t (warn 'recursive-operate :operation operation :component component :action action))))))) (defmethod component-depends-on ((o define-op) (s system)) `(;;NB: 1- ,@(system-defsystem-depends-on s)) ; Should be already included in the below. ;; 2- We don't call-next-method to avoid other methods ,@(loop :for (o . c) :in (definition-dependency-list s) :collect (list o c)))) (defmethod component-depends-on ((o operation) (s system)) `(,@(when (and (not (typep o 'define-op)) (or (system-source-file s) (definition-dependency-list s))) `((define-op ,(primary-system-name s)))) ,@(call-next-method))) (defmethod perform ((o operation) (c undefined-system)) (sysdef-error "Trying to use undefined or incompletely defined system ~A" (coerce-name c))) ;; TODO: could this file be refactored so that locate-system is merely ;; the cache-priming call to input-files here? (defmethod input-files ((o define-op) (s system)) (if-let ((asd (system-source-file s))) (list asd))) (defmethod perform ((o define-op) (s system)) (nest (if-let ((pathname (first (input-files o s))))) (let ((readtable *readtable*) ;; save outer syntax tables. TODO: proper syntax-control (print-pprint-dispatch *print-pprint-dispatch*))) (with-standard-io-syntax) (let ((*print-readably* nil) ;; Note that our backward-compatible *readtable* is ;; a global readtable that gets globally side-effected. Ouch. ;; Same for the *print-pprint-dispatch* table. ;; We should do something about that for ASDF3 if possible, or else ASDF4. (*readtable* readtable) ;; restore inside syntax table (*print-pprint-dispatch* print-pprint-dispatch) (*package* (find-package :asdf-user)) (*default-pathname-defaults* ;; resolve logical-pathnames so they won't wreak havoc in parsing namestrings. (pathname-directory-pathname (physicalize-pathname pathname))))) (handler-bind (((and error (not missing-component)) #'(lambda (condition) (error 'load-system-definition-error :name (coerce-name s) :pathname pathname :condition condition)))) (asdf-message (compatfmt "~&~@<; ~@;Loading system definition~@[ for ~A~] from ~A~@:>~%") (coerce-name s) pathname) ;; dependencies will depend on what's loaded via definition-dependency-list (unset-asdf-cache-entry `(component-depends-on ,o ,s)) (unset-asdf-cache-entry `(input-files ,o ,s))) (load* pathname :external-format (encoding-external-format (detect-encoding pathname))))) (defun load-asd (pathname &key name) "Load system definitions from PATHNAME. NAME if supplied is the name of a system expected to be defined in that file. Do NOT try to load a .asd file directly with CL:LOAD. Always use ASDF:LOAD-ASD." (with-asdf-session () ;; TODO: use OPERATE, so we consult the cache and only load once per session. (flet ((do-it (o c) (operate o c))) (let ((primary-name (primary-system-name (or name (pathname-name pathname)))) (operation (make-operation 'define-op))) (if-let (system (registered-system primary-name)) (progn ;; We already determine this to be obsolete --- ;; or should we move some tests from find-system to check for up-to-date-ness here? (setf (component-operation-time operation system) t (definition-dependency-list system) nil (definition-dependency-set system) (list-to-hash-set nil)) (do-it operation system)) (let ((system (make-instance 'undefined-system :name primary-name :source-file pathname))) (register-system system) (unwind-protect (do-it operation system) (when (typep system 'undefined-system) (clear-system system))))))))) (defvar *old-asdf-systems* (make-hash-table :test 'equal)) ;; (Private) function to check that a system that was found isn't an asdf downgrade. ;; Returns T if everything went right, NIL if the system was an ASDF at an older version, ;; or UIOP of the same or older version, that shall not be loaded. ;; Also issue a warning if it was a strictly older version of ASDF. (defun check-not-old-asdf-system (name pathname) (or (not (member name '("asdf" "uiop") :test 'equal)) (null pathname) (let* ((asdfp (equal name "asdf")) ;; otherwise, it's uiop (version-pathname (subpathname pathname "version" :type (if asdfp "lisp-expr" "lisp"))) (version (and (probe-file* version-pathname :truename nil) (read-file-form version-pathname :at (if asdfp '(0) '(2 2 2))))) (old-version (asdf-version))) (cond ;; Same version is OK for ASDF, to allow loading from modified source. ;; However, do *not* load UIOP of the exact same version: ;; it was already loaded it as part of ASDF and would only be double-loading. ;; Be quiet about it, though, since it's a normal situation. ((equal old-version version) asdfp) ((version< old-version version) t) ;; newer version: Good! (t ;; old version: bad (ensure-gethash (list (namestring pathname) version) *old-asdf-systems* #'(lambda () (let ((old-pathname (system-source-file (registered-system "asdf")))) (if asdfp (warn "~@<~ You are using ASDF version ~A ~:[(probably from (require \"asdf\") ~ or loaded by quicklisp)~;from ~:*~S~] and have an older version of ASDF ~ ~:[(and older than 2.27 at that)~;~:*~A~] registered at ~S. ~ Having an ASDF installed and registered is the normal way of configuring ASDF to upgrade itself, ~ and having an old version registered is a configuration error. ~ ASDF will ignore this configured system rather than downgrade itself. ~ In the future, you may want to either: ~ (a) upgrade this configured ASDF to a newer version, ~ (b) install a newer ASDF and register it in front of the former in your configuration, or ~ (c) uninstall or unregister this and any other old version of ASDF from your configuration. ~ Note that the older ASDF might be registered implicitly through configuration inherited ~ from your system installation, in which case you might have to specify ~ :ignore-inherited-configuration in your in your ~~/.config/common-lisp/source-registry.conf ~ or other source-registry configuration file, environment variable or lisp parameter. ~ Indeed, a likely offender is an obsolete version of the cl-asdf debian or ubuntu package, ~ that you might want to upgrade (if a recent enough version is available) ~ or else remove altogether (since most implementations ship with a recent asdf); ~ if you lack the system administration rights to upgrade or remove this package, ~ then you might indeed want to either install and register a more recent version, ~ or use :ignore-inherited-configuration to avoid registering the old one. ~ Please consult ASDF documentation and/or experts.~@:>~%" old-version old-pathname version pathname) ;; NB: for UIOP, don't warn, just ignore. (warn "ASDF ~A (from ~A), UIOP ~A (from ~A)" old-version old-pathname version pathname) )))) nil))))) ;; only issue the warning the first time, but always return nil (defun locate-system (name) "Given a system NAME designator, try to locate where to load the system from. Returns six values: FOUNDP FOUND-SYSTEM PATHNAME PREVIOUS PREVIOUS-TIME PREVIOUS-PRIMARY FOUNDP is true when a system was found, either a new unregistered one or a previously registered one. FOUND-SYSTEM when not null is a SYSTEM object that may be REGISTER-SYSTEM'ed. PATHNAME when not null is a path from which to load the system, either associated with FOUND-SYSTEM, or with the PREVIOUS system. PREVIOUS when not null is a previously loaded SYSTEM object of same name. PREVIOUS-TIME when not null is the time at which the PREVIOUS system was loaded. PREVIOUS-PRIMARY when not null is the primary system for the PREVIOUS system." (with-asdf-session () ;; NB: We don't cache the results. We once used to, but it wasn't useful, ;; and keeping a negative cache was a bug (see lp#1335323), which required ;; explicit invalidation in clear-system and find-system (when unsucccessful). (let* ((name (coerce-name name)) (previous (registered-system name)) ; load from disk if absent or newer on disk (previous-primary-name (and previous (primary-system-name previous))) (previous-primary-system (and previous-primary-name (registered-system previous-primary-name))) (previous-time (and previous-primary-system (component-operation-time 'define-op previous-primary-system))) (found (search-for-system-definition name)) (found-system (and (typep found 'system) found)) (pathname (ensure-pathname (or (and (typep found '(or pathname string)) (pathname found)) (system-source-file found-system) (system-source-file previous)) :want-absolute t :resolve-symlinks *resolve-symlinks*)) (foundp (and (or found-system pathname previous) t))) (check-type found (or null pathname system)) (unless (check-not-old-asdf-system name pathname) (check-type previous system) ;; asdf is preloaded, so there should be a previous one. (setf found-system nil pathname nil)) (values foundp found-system pathname previous previous-time previous-primary-system)))) ;; TODO: make a prepare-define-op node for this ;; so we can properly cache the answer rather than recompute it. (defun definition-dependencies-up-to-date-p (system) (check-type system system) (or (not (primary-system-p system)) (handler-case (loop :with plan = (make-instance *plan-class*) :for action :in (definition-dependency-list system) :always (action-up-to-date-p plan (action-operation action) (action-component action)) :finally (let ((o (make-operation 'define-op))) (multiple-value-bind (stamp done-p) (compute-action-stamp plan o system) (return (and (timestamp<= stamp (component-operation-time o system)) done-p))))) (system-out-of-date () nil)))) ;; Main method for find-system: first, make sure the computation is memoized in a session cache. ;; Unless the system is immutable, use locate-system to find the primary system; ;; reconcile the finding (if any) with any previous definition (in a previous session, ;; preloaded, with a previous configuration, or before filesystem changes), and ;; load a found .asd if appropriate. Finally, update registration table and return results. (defmethod find-system ((name string) &optional (error-p t)) (nest (with-asdf-session (:key `(find-system ,name))) (let ((name-primary-p (primary-system-p name))) (unless name-primary-p (find-system (primary-system-name name) nil))) (or (and *immutable-systems* (gethash name *immutable-systems*) (registered-system name))) (multiple-value-bind (foundp found-system pathname previous previous-time previous-primary) (locate-system name) (assert (eq foundp (and (or found-system pathname previous) t)))) (let ((previous-pathname (system-source-file previous)) (system (or previous found-system))) (when (and found-system (not previous)) (register-system found-system)) (when (and system pathname) (setf (system-source-file system) pathname)) (if-let ((stamp (get-file-stamp pathname))) (let ((up-to-date-p (and previous previous-primary (or (pathname-equal pathname previous-pathname) (and pathname previous-pathname (pathname-equal (physicalize-pathname pathname) (physicalize-pathname previous-pathname)))) (timestamp<= stamp previous-time) ;; Check that all previous definition-dependencies are up-to-date, ;; traversing them without triggering the adding of nodes to the plan. ;; TODO: actually have a prepare-define-op, extract its timestamp, ;; and check that it is less than the stamp of the previous define-op ? (definition-dependencies-up-to-date-p previous-primary)))) (unless up-to-date-p (restart-case (signal 'system-out-of-date :name name) (continue () :report "continue")) (load-asd pathname :name name))))) ;; Try again after having loaded from disk if needed (or (registered-system name) (when error-p (error 'missing-component :requires name))))) ;; Resolved forward reference for asdf/system-registry. (defun mark-component-preloaded (component) "Mark a component as preloaded." (let ((component (find-component component nil :registered t))) ;; Recurse to children, so asdf/plan will hopefully be happy. (map () 'mark-component-preloaded (component-children component)) ;; Mark the timestamps of the common lisp-action operations as 0. (let ((cot (component-operation-times component))) (dolist (o `(,@(when (primary-system-p component) '(define-op)) prepare-op compile-op load-op)) (setf (gethash (make-operation o) cot) 0)))))) ;;;; ------------------------------------------------------------------------- ;;;; Defsystem (uiop/package:define-package :asdf/parse-defsystem (:recycle :asdf/parse-defsystem :asdf/defsystem :asdf) (:nicknames :asdf/defsystem) ;; previous name, to be compatible with, in case anyone cares (:use :uiop/common-lisp :asdf/driver :asdf/upgrade :asdf/session :asdf/component :asdf/system :asdf/system-registry :asdf/find-component :asdf/action :asdf/lisp-action :asdf/operate) (:import-from :asdf/system #:depends-on #:weakly-depends-on) ;; these needed for record-additional-system-input-file (:import-from :asdf/operation #:make-operation) (:import-from :asdf/component #:%additional-input-files) (:import-from :asdf/find-system #:define-op) (:export #:defsystem #:register-system-definition #:*default-component-class* #:determine-system-directory #:parse-component-form #:non-toplevel-system #:non-system-system #:bad-system-name #:*known-systems-with-bad-secondary-system-names* #:known-system-with-bad-secondary-system-names-p #:sysdef-error-component #:check-component-input #:explain ;; for extending the component types #:compute-component-children #:class-for-type)) (in-package :asdf/parse-defsystem) ;;; Pathname (with-upgradability () (defun determine-system-directory (pathname) ;; The defsystem macro calls this function to determine the pathname of a system as follows: ;; 1. If the pathname argument is an pathname object (NOT a namestring), ;; that is already an absolute pathname, return it. ;; 2. Otherwise, the directory containing the LOAD-PATHNAME ;; is considered (as deduced from e.g. *LOAD-PATHNAME*), and ;; if it is indeed available and an absolute pathname, then ;; the PATHNAME argument is normalized to a relative pathname ;; as per PARSE-UNIX-NAMESTRING (with ENSURE-DIRECTORY T) ;; and merged into that DIRECTORY as per SUBPATHNAME. ;; Note: avoid *COMPILE-FILE-PATHNAME* because the .asd is loaded as source, ;; but may be from within the EVAL-WHEN of a file compilation. ;; If no absolute pathname was found, we return NIL. (check-type pathname (or null string pathname)) (pathname-directory-pathname (resolve-symlinks* (ensure-absolute-pathname (parse-unix-namestring pathname :type :directory) #'(lambda () (ensure-absolute-pathname (load-pathname) 'get-pathname-defaults nil)) nil))))) (when-upgrading (:version "3.3.4.17") ;; This turned into a generic function in 3.3.4.17 (fmakunbound 'class-for-type)) ;;; Component class (with-upgradability () ;; What :file gets interpreted as, unless overridden by a :default-component-class (defvar *default-component-class* 'cl-source-file) (defgeneric class-for-type (parent type-designator) (:documentation "Return a CLASS object to be used to instantiate components specified by TYPE-DESIGNATOR in the context of PARENT.")) (defmethod class-for-type ((parent null) type) "If the PARENT is NIL, then TYPE must designate a subclass of SYSTEM." (or (coerce-class type :package :asdf/interface :super 'system :error nil) (sysdef-error "don't recognize component type ~S in the context of no parent" type))) (defmethod class-for-type ((parent parent-component) type) (or (coerce-class type :package :asdf/interface :super 'component :error nil) (and (eq type :file) (coerce-class (or (loop :for p = parent :then (component-parent p) :while p :thereis (module-default-component-class p)) *default-component-class*) :package :asdf/interface :super 'component :error nil)) (sysdef-error "don't recognize component type ~S" type)))) ;;; Check inputs (with-upgradability () (define-condition non-system-system (system-definition-error) ((name :initarg :name :reader non-system-system-name) (class-name :initarg :class-name :reader non-system-system-class-name)) (:report (lambda (c s) (format s (compatfmt "~@") (non-system-system-name c) (non-system-system-class-name c) 'system)))) (define-condition non-toplevel-system (system-definition-error) ((parent :initarg :parent :reader non-toplevel-system-parent) (name :initarg :name :reader non-toplevel-system-name)) (:report (lambda (c s) (format s (compatfmt "~@") (non-toplevel-system-parent c) (non-toplevel-system-name c))))) (define-condition bad-system-name (warning) ((name :initarg :name :reader component-name) (source-file :initarg :source-file :reader system-source-file)) (:report (lambda (c s) (let* ((file (system-source-file c)) (name (component-name c)) (asd (pathname-name file))) (format s (compatfmt "~@") file name asd (strcat asd "/") (strcat asd "/test")))))) (defun sysdef-error-component (msg type name value) (sysdef-error (strcat msg (compatfmt "~&~@")) type name value)) (defun check-component-input (type name weakly-depends-on depends-on components) "A partial test of the values of a component." (unless (listp depends-on) (sysdef-error-component ":depends-on must be a list." type name depends-on)) (unless (listp weakly-depends-on) (sysdef-error-component ":weakly-depends-on must be a list." type name weakly-depends-on)) (unless (listp components) (sysdef-error-component ":components must be NIL or a list of components." type name components))) (defun record-additional-system-input-file (pathname component parent) (let* ((record-on (if parent (loop :with retval :for par = parent :then (component-parent par) :while par :do (setf retval par) :finally (return retval)) component)) (comp (if (typep record-on 'component) record-on ;; at this point there will be no parent for RECORD-ON (find-component record-on nil))) (op (make-operation 'define-op)) (cell (or (assoc op (%additional-input-files comp)) (let ((new-cell (list op))) (push new-cell (%additional-input-files comp)) new-cell)))) (pushnew pathname (cdr cell) :test 'pathname-equal) (values))) ;; Given a form used as :version specification, in the context of a system definition ;; in a file at PATHNAME, for given COMPONENT with given PARENT, normalize the form ;; to an acceptable ASDF-format version. (fmakunbound 'normalize-version) ;; signature changed between 2.27 and 2.31 (defun normalize-version (form &key pathname component parent) (labels ((invalid (&optional (continuation "using NIL instead")) (warn (compatfmt "~@") form component parent pathname continuation)) (invalid-parse (control &rest args) (unless (if-let (target (find-component parent component)) (builtin-system-p target)) (apply 'warn control args) (invalid)))) (if-let (v (typecase form ((or string null) form) (real (invalid "Substituting a string") (format nil "~D" form)) ;; 1.0 becomes "1.0" (cons (case (first form) ((:read-file-form) (destructuring-bind (subpath &key (at 0)) (rest form) (let ((path (subpathname pathname subpath))) (record-additional-system-input-file path component parent) (safe-read-file-form path :at at :package :asdf-user)))) ((:read-file-line) (destructuring-bind (subpath &key (at 0)) (rest form) (let ((path (subpathname pathname subpath))) (record-additional-system-input-file path component parent) (safe-read-file-line (subpathname pathname subpath) :at at)))) (otherwise (invalid)))) (t (invalid)))) (if-let (pv (parse-version v #'invalid-parse)) (unparse-version pv) (invalid)))))) ;;; "inline methods" (with-upgradability () (defparameter* +asdf-methods+ '(perform-with-restarts perform explain output-files operation-done-p)) (defun %remove-component-inline-methods (component) (dolist (name +asdf-methods+) (map () ;; this is inefficient as most of the stored ;; methods will not be for this particular gf ;; But this is hardly performance-critical #'(lambda (m) (remove-method (symbol-function name) m)) (component-inline-methods component))) (component-inline-methods component) nil) (defparameter *standard-method-combination-qualifiers* '(:around :before :after)) ;;; Find inline method definitions of the form ;;; ;;; :perform (test-op :before (operation component) ...) ;;; ;;; in REST (which is the plist of all DEFSYSTEM initargs) and define the specified methods. (defun %define-component-inline-methods (ret rest) ;; find key-value pairs that look like inline method definitions in REST. For each identified ;; definition, parse it and, if it is well-formed, define the method. (loop :for (key value) :on rest :by #'cddr :for name = (and (keywordp key) (find key +asdf-methods+ :test 'string=)) :when name :do ;; parse VALUE as an inline method definition of the form ;; ;; (OPERATION-NAME [QUALIFIER] (OPERATION-PARAMETER COMPONENT-PARAMETER) &rest BODY) (destructuring-bind (operation-name &rest rest) value (let ((qualifiers '())) ;; ensure that OPERATION-NAME is a symbol. (unless (and (symbolp operation-name) (not (null operation-name))) (sysdef-error "Ill-formed inline method: ~S. The first element is not a symbol ~ designating an operation but ~S." value operation-name)) ;; ensure that REST starts with either a cons (potential lambda list, further checked ;; below) or a qualifier accepted by the standard method combination. Everything else ;; is ill-formed. In case of a valid qualifier, pop it from REST so REST now definitely ;; has to start with the lambda list. (cond ((consp (car rest))) ((not (member (car rest) *standard-method-combination-qualifiers*)) (sysdef-error "Ill-formed inline method: ~S. Only a single of the standard ~ qualifiers ~{~S~^ ~} is allowed, not ~S." value *standard-method-combination-qualifiers* (car rest))) (t (setf qualifiers (list (pop rest))))) ;; REST must start with a two-element lambda list. (unless (and (listp (car rest)) (length=n-p (car rest) 2) (null (cddar rest))) (sysdef-error "Ill-formed inline method: ~S. The operation name ~S is not followed by ~ a lambda-list of the form (OPERATION COMPONENT) and a method body." value operation-name)) ;; define the method. (destructuring-bind ((o c) &rest body) rest (pushnew (eval `(defmethod ,name ,@qualifiers ((,o ,operation-name) (,c (eql ,ret))) ,@body)) (component-inline-methods ret))))))) (defun %refresh-component-inline-methods (component rest) ;; clear methods, then add the new ones (%remove-component-inline-methods component) (%define-component-inline-methods component rest))) ;;; Main parsing function (with-upgradability () (defun parse-dependency-def (dd) (if (listp dd) (case (first dd) (:feature (unless (= (length dd) 3) (sysdef-error "Ill-formed feature dependency: ~s" dd)) (let ((embedded (parse-dependency-def (third dd)))) `(:feature ,(second dd) ,embedded))) (feature (sysdef-error "`feature' has been removed from the dependency spec language of ASDF. Use :feature instead in ~s." dd)) (:require (unless (= (length dd) 2) (sysdef-error "Ill-formed require dependency: ~s" dd)) dd) (:version (unless (= (length dd) 3) (sysdef-error "Ill-formed version dependency: ~s" dd)) `(:version ,(coerce-name (second dd)) ,(third dd))) (otherwise (sysdef-error "Ill-formed dependency: ~s" dd))) (coerce-name dd))) (defun parse-dependency-defs (dd-list) "Parse the dependency defs in DD-LIST into canonical form by translating all system names contained using COERCE-NAME. Return the result." (mapcar 'parse-dependency-def dd-list)) (defgeneric compute-component-children (component components serial-p) (:documentation "Return a list of children for COMPONENT. COMPONENTS is a list of the explicitly defined children descriptions. SERIAL-P is non-NIL if each child in COMPONENTS should depend on the previous children.")) (defun stable-union (s1 s2 &key (test #'eql) (key 'identity)) (append s1 (remove-if #'(lambda (e2) (member (funcall key e2) (funcall key s1) :test test)) s2))) (defun parse-component-form (parent options &key previous-serial-components) (destructuring-bind (type name &rest rest &key (builtin-system-p () bspp) ;; the following list of keywords is reproduced below in the ;; remove-plist-keys form. important to keep them in sync components pathname perform explain output-files operation-done-p weakly-depends-on depends-on serial do-first if-component-dep-fails version ;; list ends &allow-other-keys) options (declare (ignore perform explain output-files operation-done-p builtin-system-p)) (check-component-input type name weakly-depends-on depends-on components) (when (and parent (find-component parent name) (not ;; ignore the same object when rereading the defsystem (typep (find-component parent name) (class-for-type parent type)))) (error 'duplicate-names :name name)) (when do-first (error "DO-FIRST is not supported anymore as of ASDF 3")) (let* ((name (coerce-name name)) (args `(:name ,name :pathname ,pathname ,@(when parent `(:parent ,parent)) ,@(remove-plist-keys '(:components :pathname :if-component-dep-fails :version :perform :explain :output-files :operation-done-p :weakly-depends-on :depends-on :serial) rest))) (component (find-component parent name)) (class (class-for-type parent type))) (when (and parent (subtypep class 'system)) (error 'non-toplevel-system :parent parent :name name)) (if component ; preserve identity (apply 'reinitialize-instance component args) (setf component (apply 'make-instance class args))) (component-pathname component) ; eagerly compute the absolute pathname (when (typep component 'system) ;; cache information for introspection (setf (slot-value component 'depends-on) (parse-dependency-defs depends-on) (slot-value component 'weakly-depends-on) ;; these must be a list of systems, cannot be features or versioned systems (mapcar 'coerce-name weakly-depends-on))) (let ((sysfile (system-source-file (component-system component)))) ;; requires the previous (when (and (typep component 'system) (not bspp)) (setf (builtin-system-p component) (lisp-implementation-pathname-p sysfile))) (setf version (normalize-version version :component name :parent parent :pathname sysfile))) ;; Don't use the accessor: kluge to avoid upgrade issue on CCL 1.8. ;; A better fix is required. (setf (slot-value component 'version) version) (when (typep component 'parent-component) (setf (component-children component) (compute-component-children component components serial)) (compute-children-by-name component)) (when previous-serial-components (setf depends-on (stable-union depends-on previous-serial-components :test #'equal))) (when weakly-depends-on ;; ASDF4: deprecate this feature and remove it. (appendf depends-on (remove-if (complement #'(lambda (x) (find-system x nil))) weakly-depends-on))) ;; Used by POIU. ASDF4: rename to component-depends-on? (setf (component-sideway-dependencies component) depends-on) (%refresh-component-inline-methods component rest) (when if-component-dep-fails (error "The system definition for ~S uses deprecated ~ ASDF option :IF-COMPONENT-DEP-FAILS. ~ Starting with ASDF 3, please use :IF-FEATURE instead" (coerce-name (component-system component)))) component))) (defmethod compute-component-children ((component parent-component) components serial-p) (loop :with previous-components = nil ; list of strings :for c-form :in components :for c = (parse-component-form component c-form :previous-serial-components previous-components) :for name :of-type string = (component-name c) :when serial-p ;; if this is an if-feature component, we need to make a serial link ;; from previous components to following components -- otherwise should ;; the IF-FEATURE component drop out, the chain of serial dependencies will be ;; broken. :unless (component-if-feature c) :do (setf previous-components nil) :end :and :do (push name previous-components) :end :collect c)) ;; the following are all systems that Stas Boukarev maintains and refuses to fix, ;; hoping instead to make my life miserable. Instead, I just make ASDF ignore them. (defparameter* *known-systems-with-bad-secondary-system-names* (list-to-hash-set '("cl-ppcre" "cl-interpol"))) (defun known-system-with-bad-secondary-system-names-p (asd-name) ;; Does .asd file with name ASD-NAME contain known exceptions ;; that should be screened out of checking for BAD-SYSTEM-NAME? (gethash asd-name *known-systems-with-bad-secondary-system-names*)) (defun register-system-definition (name &rest options &key pathname (class 'system) (source-file () sfp) defsystem-depends-on &allow-other-keys) ;; The system must be registered before we parse the body, ;; otherwise we recur when trying to find an existing system ;; of the same name to reuse options (e.g. pathname) from. ;; To avoid infinite recursion in cases where you defsystem a system ;; that is registered to a different location to find-system, ;; we also need to remember it in the asdf-cache. (nest (with-asdf-session ()) (let* ((name (coerce-name name)) (source-file (if sfp source-file (resolve-symlinks* (load-pathname)))))) (flet ((fix-case (x) (if (logical-pathname-p source-file) (string-downcase x) x)))) (let* ((asd-name (and source-file (equal "asd" (fix-case (pathname-type source-file))) (fix-case (pathname-name source-file)))) ;; note that PRIMARY-NAME is a *syntactically* primary name (primary-name (primary-system-name name))) (when (and asd-name (not (equal asd-name primary-name)) (not (known-system-with-bad-secondary-system-names-p asd-name))) (warn (make-condition 'bad-system-name :source-file source-file :name name)))) (let* (;; NB: handle defsystem-depends-on BEFORE to create the system object, ;; so that in case it fails, there is no incomplete object polluting the build. (checked-defsystem-depends-on (let* ((dep-forms (parse-dependency-defs defsystem-depends-on)) (deps (loop :for spec :in dep-forms :when (resolve-dependency-spec nil spec) :collect :it))) (load-systems* deps) dep-forms)) (system (or (find-system-if-being-defined name) (if-let (registered (registered-system name)) (reset-system-class registered 'undefined-system :name name :source-file source-file) (register-system (make-instance 'undefined-system :name name :source-file source-file))))) (component-options (append (remove-plist-keys '(:defsystem-depends-on :class) options) ;; cache defsystem-depends-on in canonical form (when checked-defsystem-depends-on `(:defsystem-depends-on ,checked-defsystem-depends-on)))) (directory (determine-system-directory pathname))) ;; This works hand in hand with asdf/find-system:find-system-if-being-defined: (set-asdf-cache-entry `(find-system ,name) (list system))) ;; We change-class AFTER we loaded the defsystem-depends-on ;; since the class might be defined as part of those. (let ((class (class-for-type nil class))) (unless (subtypep class 'system) (error 'non-system-system :name name :class-name (class-name class))) (unless (eq (type-of system) class) (reset-system-class system class))) (parse-component-form nil (list* :system name :pathname directory component-options)))) (defmacro defsystem (name &body options) `(apply 'register-system-definition ',name ',options))) ;;;; ------------------------------------------------------------------------- ;;;; ASDF-Bundle (uiop/package:define-package :asdf/bundle (:recycle :asdf/bundle :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/component :asdf/system :asdf/operation :asdf/find-component ;; used by ECL :asdf/action :asdf/lisp-action :asdf/plan :asdf/operate :asdf/parse-defsystem) (:export #:bundle-op #:bundle-type #:program-system #:bundle-system #:bundle-pathname-type #:direct-dependency-files #:monolithic-op #:monolithic-bundle-op #:operation-monolithic-p #:basic-compile-bundle-op #:prepare-bundle-op #:compile-bundle-op #:load-bundle-op #:monolithic-compile-bundle-op #:monolithic-load-bundle-op #:lib-op #:monolithic-lib-op #:dll-op #:monolithic-dll-op #:deliver-asd-op #:monolithic-deliver-asd-op #:program-op #:image-op #:compiled-file #:precompiled-system #:prebuilt-system #:user-system-p #:user-system #:trivial-system-p #:prologue-code #:epilogue-code #:static-library)) (in-package :asdf/bundle) (with-upgradability () (defclass bundle-op (operation) () (:documentation "base class for operations that bundle outputs from multiple components")) (defgeneric bundle-type (bundle-op)) (defclass monolithic-op (operation) () (:documentation "A MONOLITHIC operation operates on a system *and all of its dependencies*. So, for example, a monolithic concatenate operation will concatenate together a system's components and all of its dependencies, but a simple concatenate operation will concatenate only the components of the system itself.")) (defclass monolithic-bundle-op (bundle-op monolithic-op) ;; Old style way of specifying prologue and epilogue on ECL: in the monolithic operation. ;; DEPRECATED. Supported replacement: Define slots on program-system instead. ((prologue-code :initform nil :accessor prologue-code) (epilogue-code :initform nil :accessor epilogue-code)) (:documentation "operations that are both monolithic-op and bundle-op")) (defclass program-system (system) ;; New style (ASDF3.1) way of specifying prologue and epilogue on ECL: in the system ((prologue-code :initform nil :initarg :prologue-code :reader prologue-code) (epilogue-code :initform nil :initarg :epilogue-code :reader epilogue-code) (no-uiop :initform nil :initarg :no-uiop :reader no-uiop) (prefix-lisp-object-files :initarg :prefix-lisp-object-files :initform nil :accessor prefix-lisp-object-files) (postfix-lisp-object-files :initarg :postfix-lisp-object-files :initform nil :accessor postfix-lisp-object-files) (extra-object-files :initarg :extra-object-files :initform nil :accessor extra-object-files) (extra-build-args :initarg :extra-build-args :initform nil :accessor extra-build-args))) (defmethod prologue-code ((x system)) nil) (defmethod epilogue-code ((x system)) nil) (defmethod no-uiop ((x system)) nil) (defmethod prefix-lisp-object-files ((x system)) nil) (defmethod postfix-lisp-object-files ((x system)) nil) (defmethod extra-object-files ((x system)) nil) (defmethod extra-build-args ((x system)) nil) (defclass link-op (bundle-op) () (:documentation "Abstract operation for linking files together")) (defclass gather-operation (bundle-op) () (:documentation "Abstract operation for gathering many input files from a system")) (defgeneric gather-operation (gather-operation)) (defmethod gather-operation ((o gather-operation)) nil) (defgeneric gather-type (gather-operation)) (defun operation-monolithic-p (op) (typep op 'monolithic-op)) ;; Dependencies of a gather-op are the actions of the dependent operation ;; for all the (sorted) required components for loading the system. ;; Monolithic operations typically use lib-op as the dependent operation, ;; and all system-level dependencies as required components. ;; Non-monolithic operations typically use compile-op as the dependent operation, ;; and all transitive sub-components as required components (excluding other systems). (defmethod component-depends-on ((o gather-operation) (s system)) (let* ((mono (operation-monolithic-p o)) (go (make-operation (or (gather-operation o) 'compile-op))) (bundle-p (typep go 'bundle-op)) ;; In a non-mono operation, don't recurse to other systems. ;; In a mono operation gathering bundles, don't recurse inside systems. (component-type (if mono (if bundle-p 'system t) '(not system))) ;; In the end, only keep system bundles or non-system bundles, depending. (keep-component (if bundle-p 'system '(not system))) (deps ;; Required-components only looks at the dependencies of an action, excluding the action ;; itself, so it may be safely used by an action recursing on its dependencies (which ;; may or may not be an overdesigned API, since in practice we never use it that way). ;; Therefore, if we use :goal-operation 'load-op :keep-operation 'load-op, which looks ;; cleaner, we will miss the load-op on the requested system itself, which doesn't ;; matter for a regular system, but matters, a lot, for a package-inferred-system. ;; Using load-op as the goal operation and basic-compile-op as the keep-operation works ;; for our needs of gathering all the files we want to include in a bundle. ;; Note that we use basic-compile-op rather than compile-op so it will still work on ;; systems that would somehow load dependencies with load-bundle-op. (required-components s :other-systems mono :component-type component-type :keep-component keep-component :goal-operation 'load-op :keep-operation 'basic-compile-op))) `((,go ,@deps) ,@(call-next-method)))) ;; Create a single fasl for the entire library (defclass basic-compile-bundle-op (bundle-op basic-compile-op) () (:documentation "Base class for compiling into a bundle")) (defmethod bundle-type ((o basic-compile-bundle-op)) :fasb) (defmethod gather-type ((o basic-compile-bundle-op)) #-(or clasp ecl mkcl) :fasl #+(or clasp ecl mkcl) :object) ;; Analog to prepare-op, for load-bundle-op and compile-bundle-op (defclass prepare-bundle-op (sideway-operation) ((sideway-operation :initform #+(or clasp ecl mkcl) 'load-bundle-op #-(or clasp ecl mkcl) 'load-op :allocation :class)) (:documentation "Operation class for loading the bundles of a system's dependencies")) (defclass lib-op (link-op gather-operation non-propagating-operation) () (:documentation "Compile the system and produce a linkable static library (.a/.lib) for all the linkable object files associated with the system. Compare with DLL-OP. On most implementations, these object files only include extensions to the runtime written in C or another language with a compiler producing linkable object files. On CLASP, ECL, MKCL, these object files _also_ include the contents of Lisp files themselves. In any case, this operation will produce what you need to further build a static runtime for your system, or a dynamic library to load in an existing runtime.")) (defmethod bundle-type ((o lib-op)) :lib) (defmethod gather-type ((o lib-op)) :object) ;; What works: on ECL, CLASP(?), MKCL, we link the many .o files from the system into the .so; ;; on other implementations, we combine (usually concatenate) the .fasl files into one. (defclass compile-bundle-op (basic-compile-bundle-op selfward-operation gather-operation #+(or clasp ecl mkcl) link-op) ((selfward-operation :initform '(prepare-bundle-op) :allocation :class)) (:documentation "This operator is an alternative to COMPILE-OP. Build a system and all of its dependencies, but build only a single (\"monolithic\") FASL, instead of one per source file, which may be more resource efficient. That monolithic FASL should be loaded with LOAD-BUNDLE-OP, rather than LOAD-OP.")) (defclass load-bundle-op (basic-load-op selfward-operation) ((selfward-operation :initform '(prepare-bundle-op compile-bundle-op) :allocation :class)) (:documentation "This operator is an alternative to LOAD-OP. Build a system and all of its dependencies, using COMPILE-BUNDLE-OP. The difference with respect to LOAD-OP is that it builds only a single FASL, which may be faster and more resource efficient.")) ;; NB: since the monolithic-op's can't be sideway-operation's, ;; if we wanted lib-op, dll-op, deliver-asd-op to be sideway-operation's, ;; we'd have to have the monolithic-op not inherit from the main op, ;; but instead inherit from a basic-FOO-op as with basic-compile-bundle-op above. (defclass dll-op (link-op gather-operation non-propagating-operation) () (:documentation "Compile the system and produce a dynamic loadable library (.so/.dll) for all the linkable object files associated with the system. Compare with LIB-OP.")) (defmethod bundle-type ((o dll-op)) :dll) (defmethod gather-type ((o dll-op)) :object) (defclass deliver-asd-op (basic-compile-op selfward-operation) ((selfward-operation ;; TODO: implement link-op on all implementations, and make that ;; '(compile-bundle-op lib-op #-(or clasp ecl mkcl) dll-op) :initform '(compile-bundle-op #+(or clasp ecl mkcl) lib-op) :allocation :class)) (:documentation "produce an asd file for delivering the system as a single fasl")) (defclass monolithic-deliver-asd-op (deliver-asd-op monolithic-bundle-op) ((selfward-operation ;; TODO: implement link-op on all implementations, and make that ;; '(monolithic-compile-bundle-op monolithic-lib-op #-(or clasp ecl mkcl) monolithic-dll-op) :initform '(monolithic-compile-bundle-op #+(or clasp ecl mkcl) monolithic-lib-op) :allocation :class)) (:documentation "produce fasl and asd files for combined system and dependencies.")) (defclass monolithic-compile-bundle-op (basic-compile-bundle-op monolithic-bundle-op #+(or clasp ecl mkcl) link-op gather-operation non-propagating-operation) () (:documentation "Create a single fasl for the system and its dependencies.")) (defclass monolithic-load-bundle-op (load-bundle-op monolithic-bundle-op) ((selfward-operation :initform 'monolithic-compile-bundle-op :allocation :class)) (:documentation "Load a single fasl for the system and its dependencies.")) (defclass monolithic-lib-op (lib-op monolithic-bundle-op non-propagating-operation) () (:documentation "Compile the system and produce a linkable static library (.a/.lib) for all the linkable object files associated with the system or its dependencies. See LIB-OP.")) (defclass monolithic-dll-op (dll-op monolithic-bundle-op non-propagating-operation) () (:documentation "Compile the system and produce a dynamic loadable library (.so/.dll) for all the linkable object files associated with the system or its dependencies. See LIB-OP")) (defclass image-op (monolithic-bundle-op selfward-operation #+(or clasp ecl mkcl) link-op #+(or clasp ecl mkcl) gather-operation) ((selfward-operation :initform '(#-(or clasp ecl mkcl) load-op) :allocation :class)) (:documentation "create an image file from the system and its dependencies")) (defmethod bundle-type ((o image-op)) :image) #+(or clasp ecl mkcl) (defmethod gather-operation ((o image-op)) 'lib-op) #+(or clasp ecl mkcl) (defmethod gather-type ((o image-op)) :static-library) (defclass program-op (image-op) () (:documentation "create an executable file from the system and its dependencies")) (defmethod bundle-type ((o program-op)) :program) ;; From the ASDF-internal bundle-type identifier, get a filesystem-usable pathname type. (defun bundle-pathname-type (bundle-type) (etypecase bundle-type ((or null string) ;; pass through nil or string literal bundle-type) ((eql :no-output-file) ;; marker for a bundle-type that has NO output file (error "No output file, therefore no pathname type")) ((eql :fasl) ;; the type of a fasl (compile-file-type)) ; on image-based platforms, used as input and output ((eql :fasb) ;; the type of a fasl #-(or clasp ecl mkcl) (compile-file-type) ; on image-based platforms, used as input and output #+(or ecl mkcl) "fasb" #+clasp "fasp") ; on C-linking platforms, only used as output for system bundles ((member :image) #+allegro "dxl" #+(and clisp os-windows) "exe" #-(or allegro (and clisp os-windows)) "image") ;; NB: on CLASP and ECL these implementations, we better agree with ;; (compile-file-type :type bundle-type)) ((eql :object) ;; the type of a linkable object file (os-cond ((os-unix-p) #+clasp "fasp" ;(core:build-extension cmp:*default-object-type*) #-clasp "o") ((os-windows-p) (if (featurep '(:or :mingw32 :mingw64)) "o" "obj")))) ((member :lib :static-library) ;; the type of a linkable library (os-cond ((os-unix-p) "a") ((os-windows-p) (if (featurep '(:or :mingw32 :mingw64)) "a" "lib")))) ((member :dll :shared-library) ;; the type of a shared library (os-cond ((os-macosx-p) "dylib") ((os-unix-p) "so") ((os-windows-p) "dll"))) ((eql :program) ;; the type of an executable program (os-cond ((os-unix-p) nil) ((os-windows-p) "exe"))))) ;; Compute the output-files for a given bundle action (defun bundle-output-files (o c) (let ((bundle-type (bundle-type o))) (unless (or (eq bundle-type :no-output-file) ;; NIL already means something regarding type. (and (null (input-files o c)) (not (member bundle-type '(:image :program))))) (let ((name (or (component-build-pathname c) (let ((suffix (unless (typep o 'program-op) ;; "." is no good separator for Logical Pathnames, so we use "--" (if (operation-monolithic-p o) "--all-systems" ;; These use a different type .fasb or .a instead of .fasl #-(or clasp ecl mkcl) "--system")))) (format nil "~A~@[~A~]" (coerce-filename (component-name c)) suffix)))) (type (bundle-pathname-type bundle-type))) (values (list (subpathname (component-pathname c) name :type type)) (eq (class-of o) (coerce-class (component-build-operation c) :package :asdf/interface :super 'operation :error nil))))))) (defmethod output-files ((o bundle-op) (c system)) (bundle-output-files o c)) #-(or clasp ecl mkcl) (progn (defmethod perform ((o image-op) (c system)) (dump-image (output-file o c) :executable (typep o 'program-op))) (defmethod perform :before ((o program-op) (c system)) (setf *image-entry-point* (ensure-function (component-entry-point c))))) (defclass compiled-file (file-component) ((type :initform #-(or clasp ecl mkcl) (compile-file-type) #+(or clasp ecl mkcl) "fasb")) (:documentation "Class for a file that is already compiled, e.g. as part of the implementation, of an outer build system that calls into ASDF, or of opaque libraries shipped along the source code.")) (defclass precompiled-system (system) ((build-pathname :initarg :fasb :initarg :fasl)) (:documentation "Class For a system that is delivered as a precompiled fasl")) (defclass prebuilt-system (system) ((build-pathname :initarg :static-library :initarg :lib :accessor prebuilt-system-static-library)) (:documentation "Class for a system delivered with a linkable static library (.a/.lib)"))) ;;; ;;; BUNDLE-OP ;;; ;;; This operation takes all components from one or more systems and ;;; creates a single output file, which may be ;;; a FASL, a statically linked library, a shared library, etc. ;;; The different targets are defined by specialization. ;;; (when-upgrading (:version "3.2.0") ;; Cancel any previously defined method (defmethod initialize-instance :after ((instance bundle-op) &rest initargs &key &allow-other-keys) (declare (ignore initargs)))) (with-upgradability () (defgeneric trivial-system-p (component)) (defun user-system-p (s) (and (typep s 'system) (not (builtin-system-p s)) (not (trivial-system-p s))))) (eval-when (#-lispworks :compile-toplevel :load-toplevel :execute) (deftype user-system () '(and system (satisfies user-system-p)))) ;;; ;;; First we handle monolithic bundles. ;;; These are standalone systems which contain everything, ;;; including other ASDF systems required by the current one. ;;; A PROGRAM is always monolithic. ;;; ;;; MONOLITHIC SHARED LIBRARIES, PROGRAMS, FASL ;;; (with-upgradability () (defun direct-dependency-files (o c &key (test 'identity) (key 'output-files) &allow-other-keys) ;; This function selects output files from direct dependencies; ;; your component-depends-on method must gather the correct dependencies in the correct order. (while-collecting (collect) (map-direct-dependencies o c #'(lambda (sub-o sub-c) (loop :for f :in (funcall key sub-o sub-c) :when (funcall test f) :do (collect f)))))) (defun pathname-type-equal-function (type) #'(lambda (p) (equalp (pathname-type p) type))) (defmethod input-files ((o gather-operation) (c system)) (unless (eq (bundle-type o) :no-output-file) (direct-dependency-files o c :key 'output-files :test (pathname-type-equal-function (bundle-pathname-type (gather-type o)))))) ;; Find the operation that produces a given bundle-type (defun select-bundle-operation (type &optional monolithic) (ecase type ((:dll :shared-library) (if monolithic 'monolithic-dll-op 'dll-op)) ((:lib :static-library) (if monolithic 'monolithic-lib-op 'lib-op)) ((:fasb) (if monolithic 'monolithic-compile-bundle-op 'compile-bundle-op)) ((:image) 'image-op) ((:program) 'program-op)))) ;;; ;;; LOAD-BUNDLE-OP ;;; ;;; This is like ASDF's LOAD-OP, but using bundle fasl files. ;;; (with-upgradability () (defmethod component-depends-on ((o load-bundle-op) (c system)) `((,o ,@(component-sideway-dependencies c)) (,(if (user-system-p c) 'compile-bundle-op 'load-op) ,c) ,@(call-next-method))) (defmethod input-files ((o load-bundle-op) (c system)) (when (user-system-p c) (output-files (find-operation o 'compile-bundle-op) c))) (defmethod perform ((o load-bundle-op) (c system)) (when (input-files o c) (perform-lisp-load-fasl o c))) (defmethod mark-operation-done :after ((o load-bundle-op) (c system)) (mark-operation-done (find-operation o 'load-op) c))) ;;; ;;; PRECOMPILED FILES ;;; ;;; This component can be used to distribute ASDF systems in precompiled form. ;;; Only useful when the dependencies have also been precompiled. ;;; (with-upgradability () (defmethod trivial-system-p ((s system)) (every #'(lambda (c) (typep c 'compiled-file)) (component-children s))) (defmethod input-files ((o operation) (c compiled-file)) (list (component-pathname c))) (defmethod perform ((o load-op) (c compiled-file)) (perform-lisp-load-fasl o c)) (defmethod perform ((o load-source-op) (c compiled-file)) (perform (find-operation o 'load-op) c)) (defmethod perform ((o operation) (c compiled-file)) nil)) ;;; ;;; Pre-built systems ;;; (with-upgradability () (defmethod trivial-system-p ((s prebuilt-system)) t) (defmethod perform ((o link-op) (c prebuilt-system)) nil) (defmethod perform ((o basic-compile-bundle-op) (c prebuilt-system)) nil) (defmethod perform ((o lib-op) (c prebuilt-system)) nil) (defmethod perform ((o dll-op) (c prebuilt-system)) nil) (defmethod component-depends-on ((o gather-operation) (c prebuilt-system)) nil) (defmethod output-files ((o lib-op) (c prebuilt-system)) (values (list (prebuilt-system-static-library c)) t))) ;;; ;;; PREBUILT SYSTEM CREATOR ;;; (with-upgradability () (defmethod output-files ((o deliver-asd-op) (s system)) (list (make-pathname :name (coerce-filename (component-name s)) :type "asd" :defaults (component-pathname s)))) ;; because of name collisions between the output files of different ;; subclasses of DELIVER-ASD-OP, we cannot trust the file system to ;; tell us if the output file is up-to-date, so just treat the ;; operation as never being done. (defmethod operation-done-p ((o deliver-asd-op) (s system)) (declare (ignorable o s)) nil) (defun space-for-crlf (s) (substitute-if #\space #'(lambda (x) (find x +crlf+)) s)) (defmethod perform ((o deliver-asd-op) (s system)) "Write an ASDF system definition for loading S as a delivered system." (let* ((inputs (input-files o s)) (fasl (first inputs)) (library (second inputs)) (asd (output-file o s)) (name (if (and fasl asd) (pathname-name asd) (return-from perform))) (version (component-version s)) (dependencies (if (operation-monolithic-p o) ;; We want only dependencies, and we use basic-load-op rather than load-op so that ;; this will keep working on systems that load dependencies with load-bundle-op (remove-if-not 'builtin-system-p (required-components s :component-type 'system :keep-operation 'basic-load-op)) (while-collecting (x) ;; resolve the sideway-dependencies of s (map-direct-dependencies 'prepare-op s #'(lambda (o c) (when (and (typep o 'load-op) (typep c 'system)) (x c))))))) (depends-on (mapcar 'coerce-name dependencies))) (when (pathname-equal asd (system-source-file s)) (cerror "overwrite the asd file" "~/asdf-action:format-action/ is going to overwrite the system definition file ~S ~ which is probably not what you want; you probably need to tweak your output translations." (cons o s) asd)) (with-open-file (s asd :direction :output :if-exists :supersede :if-does-not-exist :create) (format s ";;; Prebuilt~:[~; monolithic~] ASDF definition for system ~A~%" (operation-monolithic-p o) name) ;; this can cause bugs in cases where one of the functions returns a multi-line ;; string (let ((description-string (format nil ";;; Built for ~A ~A on a ~A/~A ~A" (lisp-implementation-type) (lisp-implementation-version) (software-type) (machine-type) (software-version)))) ;; ensure the whole thing is on one line (println (space-for-crlf description-string) s)) (let ((*package* (find-package :asdf-user))) (pprint `(defsystem ,name :class prebuilt-system :version ,version :depends-on ,depends-on :components ((:compiled-file ,(pathname-name fasl))) ,@(when library `(:lib ,(file-namestring library)))) s) (terpri s))))) #-(or clasp ecl mkcl) (defmethod perform ((o basic-compile-bundle-op) (c system)) (let* ((input-files (input-files o c)) (fasl-files (remove (compile-file-type) input-files :key #'pathname-type :test-not #'equalp)) (non-fasl-files (remove (compile-file-type) input-files :key #'pathname-type :test #'equalp)) (output-files (output-files o c)) ; can't use OUTPUT-FILE fn because possibility it's NIL (output-file (first output-files))) (assert (eq (not input-files) (not output-files))) (when input-files (when non-fasl-files (error "On ~A, asdf/bundle can only bundle FASL files, but these were also produced: ~S" (implementation-type) non-fasl-files)) (when (or (prologue-code c) (epilogue-code c)) (error "prologue-code and epilogue-code are not supported on ~A" (implementation-type))) (with-staging-pathname (output-file) (combine-fasls fasl-files output-file))))) (defmethod input-files ((o load-op) (s precompiled-system)) (bundle-output-files (find-operation o 'compile-bundle-op) s)) (defmethod perform ((o load-op) (s precompiled-system)) (perform-lisp-load-fasl o s)) (defmethod component-depends-on ((o load-bundle-op) (s precompiled-system)) `((load-op ,s) ,@(call-next-method)))) #| ;; Example use: (asdf:defsystem :precompiled-asdf-utils :class asdf::precompiled-system :fasl (asdf:apply-output-translations (asdf:system-relative-pathname :asdf-utils "asdf-utils.system.fasl"))) (asdf:load-system :precompiled-asdf-utils) |# #+(or clasp ecl mkcl) (with-upgradability () (defun system-module-pathname (module) (let ((name (coerce-name module))) (some 'file-exists-p (list #+clasp (compile-file-pathname (make-pathname :name name :defaults "sys:") :output-type :object) #+ecl (compile-file-pathname (make-pathname :name name :defaults "sys:") :type :lib) #+ecl (compile-file-pathname (make-pathname :name (strcat "lib" name) :defaults "sys:") :type :lib) #+ecl (compile-file-pathname (make-pathname :name name :defaults "sys:") :type :object) #+mkcl (make-pathname :name name :type (bundle-pathname-type :lib) :defaults #p"sys:") #+mkcl (make-pathname :name name :type (bundle-pathname-type :lib) :defaults #p"sys:contrib;"))))) (defun make-prebuilt-system (name &optional (pathname (system-module-pathname name))) "Creates a prebuilt-system if PATHNAME isn't NIL." (when pathname (make-instance 'prebuilt-system :name (coerce-name name) :static-library (resolve-symlinks* pathname)))) (defun linkable-system (x) (or ;; If the system is available as source, use it. (if-let (s (find-system x)) (and (output-files 'lib-op s) s)) ;; If an ASDF upgrade is available from source, but not a UIOP upgrade to that, ;; then use the asdf/driver system instead of ;; the UIOP that was disabled by check-not-old-asdf-system. (if-let (s (and (equal (coerce-name x) "uiop") (output-files 'lib-op "asdf") (find-system "asdf/driver"))) (and (output-files 'lib-op s) s)) ;; If there was no source upgrade, look for modules provided by the implementation. (if-let (p (system-module-pathname (coerce-name x))) (make-prebuilt-system x p)))) (defmethod component-depends-on :around ((o image-op) (c system)) (let* ((next (call-next-method)) (deps (make-hash-table :test 'equal)) (linkable (loop :for (do . dcs) :in next :collect (cons do (loop :for dc :in dcs :for dep = (and dc (resolve-dependency-spec c dc)) :when dep :do (setf (gethash (coerce-name (component-system dep)) deps) t) :collect (or (and (typep dep 'system) (linkable-system dep)) dep)))))) `((lib-op ,@(unless (no-uiop c) (list (linkable-system "cmp") (unless (or (and (gethash "uiop" deps) (linkable-system "uiop")) (and (gethash "asdf" deps) (linkable-system "asdf"))) (or (linkable-system "uiop") (linkable-system "asdf") "asdf"))))) ,@linkable))) (defmethod perform ((o link-op) (c system)) (let* ((object-files (input-files o c)) (output (output-files o c)) (bundle (first output)) (programp (typep o 'program-op)) (kind (bundle-type o))) (when output (apply 'create-image bundle (append (when programp (prefix-lisp-object-files c)) object-files (when programp (postfix-lisp-object-files c))) :kind kind :prologue-code (when programp (prologue-code c)) :epilogue-code (when programp (epilogue-code c)) :build-args (when programp (extra-build-args c)) :extra-object-files (when programp (extra-object-files c)) :no-uiop (no-uiop c) (when programp `(:entry-point ,(component-entry-point c)))))))) ;;;; ------------------------------------------------------------------------- ;;;; Concatenate-source (uiop/package:define-package :asdf/concatenate-source (:recycle :asdf/concatenate-source :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/component :asdf/operation :asdf/system :asdf/action :asdf/lisp-action :asdf/plan :asdf/bundle) (:export #:concatenate-source-op #:load-concatenated-source-op #:compile-concatenated-source-op #:load-compiled-concatenated-source-op #:monolithic-concatenate-source-op #:monolithic-load-concatenated-source-op #:monolithic-compile-concatenated-source-op #:monolithic-load-compiled-concatenated-source-op)) (in-package :asdf/concatenate-source) ;;; ;;; Concatenate sources ;;; (with-upgradability () ;; Base classes for both regular and monolithic concatenate-source operations (defclass basic-concatenate-source-op (bundle-op) ()) (defmethod bundle-type ((o basic-concatenate-source-op)) "lisp") (defclass basic-load-concatenated-source-op (basic-load-op selfward-operation) ()) (defclass basic-compile-concatenated-source-op (basic-compile-op selfward-operation) ()) (defclass basic-load-compiled-concatenated-source-op (basic-load-op selfward-operation) ()) ;; Regular concatenate-source operations (defclass concatenate-source-op (basic-concatenate-source-op non-propagating-operation) () (:documentation "Operation to concatenate all sources in a system into a single file")) (defclass load-concatenated-source-op (basic-load-concatenated-source-op) ((selfward-operation :initform '(prepare-op concatenate-source-op) :allocation :class)) (:documentation "Operation to load the result of concatenate-source-op as source")) (defclass compile-concatenated-source-op (basic-compile-concatenated-source-op) ((selfward-operation :initform '(prepare-op concatenate-source-op) :allocation :class)) (:documentation "Operation to compile the result of concatenate-source-op")) (defclass load-compiled-concatenated-source-op (basic-load-compiled-concatenated-source-op) ((selfward-operation :initform '(prepare-op compile-concatenated-source-op) :allocation :class)) (:documentation "Operation to load the result of compile-concatenated-source-op")) (defclass monolithic-concatenate-source-op (basic-concatenate-source-op monolithic-bundle-op non-propagating-operation) () (:documentation "Operation to concatenate all sources in a system and its dependencies into a single file")) (defclass monolithic-load-concatenated-source-op (basic-load-concatenated-source-op) ((selfward-operation :initform 'monolithic-concatenate-source-op :allocation :class)) (:documentation "Operation to load the result of monolithic-concatenate-source-op as source")) (defclass monolithic-compile-concatenated-source-op (basic-compile-concatenated-source-op) ((selfward-operation :initform 'monolithic-concatenate-source-op :allocation :class)) (:documentation "Operation to compile the result of monolithic-concatenate-source-op")) (defclass monolithic-load-compiled-concatenated-source-op (basic-load-compiled-concatenated-source-op) ((selfward-operation :initform 'monolithic-compile-concatenated-source-op :allocation :class)) (:documentation "Operation to load the result of monolithic-compile-concatenated-source-op")) (defmethod input-files ((operation basic-concatenate-source-op) (s system)) (loop :with encoding = (or (component-encoding s) *default-encoding*) :with other-encodings = '() :with around-compile = (around-compile-hook s) :with other-around-compile = '() :for c :in (required-components ;; see note about similar call to required-components s :goal-operation 'load-op ;; in bundle.lisp :keep-operation 'basic-compile-op :other-systems (operation-monolithic-p operation)) :append (when (typep c 'cl-source-file) (let ((e (component-encoding c))) (unless (or (equal e encoding) (and (equal e :ASCII) (equal encoding :UTF-8))) (let ((a (assoc e other-encodings))) (if a (push (component-find-path c) (cdr a)) (push (list e (component-find-path c)) other-encodings))))) (unless (equal around-compile (around-compile-hook c)) (push (component-find-path c) other-around-compile)) (input-files (make-operation 'compile-op) c)) :into inputs :finally (when other-encodings (warn "~S uses encoding ~A but has sources that use these encodings:~{ ~A~}" operation encoding (mapcar #'(lambda (x) (cons (car x) (list (reverse (cdr x))))) other-encodings))) (when other-around-compile (warn "~S uses around-compile hook ~A but has sources that use these hooks: ~A" operation around-compile other-around-compile)) (return inputs))) (defmethod output-files ((o basic-compile-concatenated-source-op) (s system)) (lisp-compilation-output-files o s)) (defmethod perform ((o basic-concatenate-source-op) (s system)) (let* ((ins (input-files o s)) (out (output-file o s)) (tmp (tmpize-pathname out))) (concatenate-files ins tmp) (rename-file-overwriting-target tmp out))) (defmethod perform ((o basic-load-concatenated-source-op) (s system)) (perform-lisp-load-source o s)) (defmethod perform ((o basic-compile-concatenated-source-op) (s system)) (perform-lisp-compilation o s)) (defmethod perform ((o basic-load-compiled-concatenated-source-op) (s system)) (perform-lisp-load-fasl o s))) ;;;; ------------------------------------------------------------------------- ;;;; Package systems in the style of quick-build or faslpath (uiop:define-package :asdf/package-inferred-system (:recycle :asdf/package-inferred-system :asdf/package-system :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/system :asdf/system-registry :asdf/lisp-action :asdf/parse-defsystem) (:export #:package-inferred-system #:sysdef-package-inferred-system-search #:package-system ;; backward compatibility only. To be removed. #:register-system-packages #:*defpackage-forms* #:*package-inferred-systems* #:package-inferred-system-missing-package-error)) (in-package :asdf/package-inferred-system) (with-upgradability () ;; The names of the recognized defpackage forms. (defparameter *defpackage-forms* '(defpackage define-package)) (defun initial-package-inferred-systems-table () ;; Mark all existing packages are preloaded. (let ((h (make-hash-table :test 'equal))) (dolist (p (list-all-packages)) (dolist (n (package-names p)) (setf (gethash n h) t))) h)) ;; Mapping from package names to systems that provide them. (defvar *package-inferred-systems* (initial-package-inferred-systems-table)) (defclass package-inferred-system (system) () (:documentation "Class for primary systems for which secondary systems are automatically in the one-file, one-file, one-system style: system names are mapped to files under the primary system's system-source-directory, dependencies are inferred from the first defpackage form in every such file")) ;; DEPRECATED. For backward compatibility only. To be removed in an upcoming release: (defclass package-system (package-inferred-system) ()) ;; Is a given form recognizable as a defpackage form? (defun defpackage-form-p (form) (and (consp form) (member (car form) *defpackage-forms*))) ;; Find the first defpackage form in a stream, if any (defun stream-defpackage-form (stream) (loop :for form = (read stream nil nil) :while form :when (defpackage-form-p form) :return form)) (defun file-defpackage-form (file) "Return the first DEFPACKAGE form in FILE." (with-input-file (f file) (stream-defpackage-form f))) (define-condition package-inferred-system-missing-package-error (system-definition-error) ((system :initarg :system :reader error-system) (pathname :initarg :pathname :reader error-pathname)) (:report (lambda (c s) (format s (compatfmt "~@") (error-system c) (error-pathname c))))) (defun package-dependencies (defpackage-form) "Return a list of packages depended on by the package defined in DEFPACKAGE-FORM. A package is depended upon if the DEFPACKAGE-FORM uses it or imports a symbol from it." (assert (defpackage-form-p defpackage-form)) (remove-duplicates (while-collecting (dep) (loop :for (option . arguments) :in (cddr defpackage-form) :do (ecase option ((:use :mix :reexport :use-reexport :mix-reexport) (dolist (p arguments) (dep (string p)))) ((:import-from :shadowing-import-from) (dep (string (first arguments)))) #+package-local-nicknames ((:local-nicknames) (loop :for (nil actual-package-name) :in arguments :do (dep (string actual-package-name)))) ((:nicknames :documentation :shadow :export :intern :unintern :recycle))))) :from-end t :test 'equal)) (defun package-designator-name (package) "Normalize a package designator to a string" (etypecase package (package (package-name package)) (string package) (symbol (string package)))) (defun register-system-packages (system packages) "Register SYSTEM as providing PACKAGES." (let ((name (or (eq system t) (coerce-name system)))) (dolist (p (ensure-list packages)) (setf (gethash (package-designator-name p) *package-inferred-systems*) name)))) (defun package-name-system (package-name) "Return the name of the SYSTEM providing PACKAGE-NAME, if such exists, otherwise return a default system name computed from PACKAGE-NAME." (check-type package-name string) (or (gethash package-name *package-inferred-systems*) (string-downcase package-name))) ;; Given a file in package-inferred-system style, find its dependencies (defun package-inferred-system-file-dependencies (file &optional system) (if-let (defpackage-form (file-defpackage-form file)) (remove t (mapcar 'package-name-system (package-dependencies defpackage-form))) (error 'package-inferred-system-missing-package-error :system system :pathname file))) ;; Given package-inferred-system object, check whether its specification matches ;; the provided parameters (defun same-package-inferred-system-p (system name directory subpath around-compile dependencies) (and (eq (type-of system) 'package-inferred-system) (equal (component-name system) name) (pathname-equal directory (component-pathname system)) (equal dependencies (component-sideway-dependencies system)) (equal around-compile (around-compile-hook system)) (let ((children (component-children system))) (and (length=n-p children 1) (let ((child (first children))) (and (eq (type-of child) 'cl-source-file) (equal (component-name child) "lisp") (and (slot-boundp child 'relative-pathname) (equal (slot-value child 'relative-pathname) subpath)))))))) ;; sysdef search function to push into *system-definition-search-functions* (defun sysdef-package-inferred-system-search (system-name) "Takes SYSTEM-NAME and returns an initialized SYSTEM object, or NIL. Made to be added to *SYSTEM-DEFINITION-SEARCH-FUNCTIONS*." (let ((primary (primary-system-name system-name))) ;; this function ONLY does something if the primary system name is NOT the same as ;; SYSTEM-NAME. It is used to find the systems with names that are relative to ;; the primary system's name, and that are not explicitly specified in the system ;; definition (unless (equal primary system-name) (let ((top (find-system primary nil))) (when (typep top 'package-inferred-system) (if-let (dir (component-pathname top)) (let* ((sub (subseq system-name (1+ (length primary)))) (component-type (class-for-type top :file)) (file-type (file-type (make-instance component-type))) (f (probe-file* (subpathname dir sub :type file-type) :truename *resolve-symlinks*))) (when (file-pathname-p f) (let ((dependencies (package-inferred-system-file-dependencies f system-name)) (previous (registered-system system-name)) (around-compile (around-compile-hook top))) (if (same-package-inferred-system-p previous system-name dir sub around-compile dependencies) previous (eval `(defsystem ,system-name :class package-inferred-system :default-component-class ,component-type :source-file ,(system-source-file top) :pathname ,dir :depends-on ,dependencies :around-compile ,around-compile :components ((,component-type file-type :pathname ,sub))))))))))))))) (with-upgradability () (pushnew 'sysdef-package-inferred-system-search *system-definition-search-functions*) (setf *system-definition-search-functions* (remove (find-symbol* :sysdef-package-system-search :asdf/package-system nil) *system-definition-search-functions*))) ;;;; --------------------------------------------------------------------------- ;;;; asdf-output-translations (uiop/package:define-package :asdf/output-translations (:recycle :asdf/output-translations :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade) (:export #:*output-translations* #:*output-translations-parameter* #:invalid-output-translation #:output-translations #:output-translations-initialized-p #:initialize-output-translations #:clear-output-translations #:disable-output-translations #:ensure-output-translations #:apply-output-translations #:validate-output-translations-directive #:validate-output-translations-form #:validate-output-translations-file #:validate-output-translations-directory #:parse-output-translations-string #:wrapping-output-translations #:user-output-translations-pathname #:system-output-translations-pathname #:user-output-translations-directory-pathname #:system-output-translations-directory-pathname #:environment-output-translations #:process-output-translations #:compute-output-translations #+abcl #:translate-jar-pathname )) (in-package :asdf/output-translations) ;; (setf output-translations) between 2.27 and 3.0.3 was using a defsetf macro ;; for the sake of obsolete versions of GCL 2.6. Make sure it doesn't come to haunt us. (when-upgrading (:version "3.1.2") (fmakunbound '(setf output-translations))) (with-upgradability () (define-condition invalid-output-translation (invalid-configuration warning) ((format :initform (compatfmt "~@")))) (defvar *output-translations* () "Either NIL (for uninitialized), or a list of one element, said element itself being a sorted list of mappings. Each mapping is a pair of a source pathname and destination pathname, and the order is by decreasing length of namestring of the source pathname.") (defun output-translations () "Return the configured output-translations, if any" (car *output-translations*)) ;; Set the output-translations, by sorting the provided new-value. (defun set-output-translations (new-value) (setf *output-translations* (list (stable-sort (copy-list new-value) #'> :key #'(lambda (x) (etypecase (car x) ((eql t) -1) (pathname (let ((directory (normalize-pathname-directory-component (pathname-directory (car x))))) (if (listp directory) (length directory) 0)))))))) new-value) (defun (setf output-translations) (new-value) (set-output-translations new-value)) (defun output-translations-initialized-p () "Have the output-translations been initialized yet?" (and *output-translations* t)) (defun clear-output-translations () "Undoes any initialization of the output translations." (setf *output-translations* '()) (values)) (register-clear-configuration-hook 'clear-output-translations) ;;; Validation of the configuration directives... (defun validate-output-translations-directive (directive) (or (member directive '(:enable-user-cache :disable-cache nil)) (and (consp directive) (or (and (length=n-p directive 2) (or (and (eq (first directive) :include) (typep (second directive) '(or string pathname null))) (and (location-designator-p (first directive)) (or (location-designator-p (second directive)) (location-function-p (second directive)))))) (and (length=n-p directive 1) (location-designator-p (first directive))))))) (defun validate-output-translations-form (form &key location) (validate-configuration-form form :output-translations 'validate-output-translations-directive :location location :invalid-form-reporter 'invalid-output-translation)) (defun validate-output-translations-file (file) (validate-configuration-file file 'validate-output-translations-form :description "output translations")) (defun validate-output-translations-directory (directory) (validate-configuration-directory directory :output-translations 'validate-output-translations-directive :invalid-form-reporter 'invalid-output-translation)) ;;; Parse the ASDF_OUTPUT_TRANSLATIONS environment variable and/or some file contents (defun parse-output-translations-string (string &key location) (cond ((or (null string) (equal string "")) '(:output-translations :inherit-configuration)) ((not (stringp string)) (error (compatfmt "~@") string)) ((eql (char string 0) #\") (parse-output-translations-string (read-from-string string) :location location)) ((eql (char string 0) #\() (validate-output-translations-form (read-from-string string) :location location)) (t (loop :with inherit = nil :with directives = () :with start = 0 :with end = (length string) :with source = nil :with separator = (inter-directory-separator) :for i = (or (position separator string :start start) end) :do (let ((s (subseq string start i))) (cond (source (push (list source (if (equal "" s) nil s)) directives) (setf source nil)) ((equal "" s) (when inherit (error (compatfmt "~@") string)) (setf inherit t) (push :inherit-configuration directives)) (t (setf source s))) (setf start (1+ i)) (when (> start end) (when source (error (compatfmt "~@") string)) (unless inherit (push :ignore-inherited-configuration directives)) (return `(:output-translations ,@(nreverse directives))))))))) ;; The default sources of configuration for output-translations (defparameter* *default-output-translations* '(environment-output-translations user-output-translations-pathname user-output-translations-directory-pathname system-output-translations-pathname system-output-translations-directory-pathname)) ;; Compulsory implementation-dependent wrapping for the translations: ;; handle implementation-provided systems. (defun wrapping-output-translations () `(:output-translations ;; Some implementations have precompiled ASDF systems, ;; so we must disable translations for implementation paths. #+(or clasp #|clozure|# ecl mkcl sbcl) ,@(let ((h (resolve-symlinks* (lisp-implementation-directory)))) (when h `(((,h ,*wild-path*) ())))) #+mkcl (,(translate-logical-pathname "CONTRIB:") ()) ;; All-import, here is where we want user stuff to be: :inherit-configuration ;; These are for convenience, and can be overridden by the user: #+abcl (#p"/___jar___file___root___/**/*.*" (:user-cache #p"**/*.*")) #+abcl (#p"jar:file:/**/*.jar!/**/*.*" (:function translate-jar-pathname)) ;; We enable the user cache by default, and here is the place we do: :enable-user-cache)) ;; Relative pathnames of output-translations configuration to XDG configuration directory (defparameter *output-translations-file* (parse-unix-namestring "common-lisp/asdf-output-translations.conf")) (defparameter *output-translations-directory* (parse-unix-namestring "common-lisp/asdf-output-translations.conf.d/")) ;; Locating various configuration pathnames, depending on input or output intent. (defun user-output-translations-pathname (&key (direction :input)) (xdg-config-pathname *output-translations-file* direction)) (defun system-output-translations-pathname (&key (direction :input)) (find-preferred-file (system-config-pathnames *output-translations-file*) :direction direction)) (defun user-output-translations-directory-pathname (&key (direction :input)) (xdg-config-pathname *output-translations-directory* direction)) (defun system-output-translations-directory-pathname (&key (direction :input)) (find-preferred-file (system-config-pathnames *output-translations-directory*) :direction direction)) (defun environment-output-translations () (getenv "ASDF_OUTPUT_TRANSLATIONS")) ;;; Processing the configuration. (defgeneric process-output-translations (spec &key inherit collect)) (defun inherit-output-translations (inherit &key collect) (when inherit (process-output-translations (first inherit) :collect collect :inherit (rest inherit)))) (defun process-output-translations-directive (directive &key inherit collect) (if (atom directive) (ecase directive ((:enable-user-cache) (process-output-translations-directive '(t :user-cache) :collect collect)) ((:disable-cache) (process-output-translations-directive '(t t) :collect collect)) ((:inherit-configuration) (inherit-output-translations inherit :collect collect)) ((:ignore-inherited-configuration :ignore-invalid-entries nil) nil)) (let ((src (first directive)) (dst (second directive))) (if (eq src :include) (when dst (process-output-translations (pathname dst) :inherit nil :collect collect)) (when src (let ((trusrc (or (eql src t) (let ((loc (resolve-location src :ensure-directory t :wilden t))) (if (absolute-pathname-p loc) (resolve-symlinks* loc) loc))))) (cond ((location-function-p dst) (funcall collect (list trusrc (ensure-function (second dst))))) ((typep dst 'boolean) (funcall collect (list trusrc t))) (t (let* ((trudst (resolve-location dst :ensure-directory t :wilden t))) (funcall collect (list trudst t)) (funcall collect (list trusrc trudst))))))))))) (defmethod process-output-translations ((x symbol) &key (inherit *default-output-translations*) collect) (process-output-translations (funcall x) :inherit inherit :collect collect)) (defmethod process-output-translations ((pathname pathname) &key inherit collect) (cond ((directory-pathname-p pathname) (process-output-translations (validate-output-translations-directory pathname) :inherit inherit :collect collect)) ((probe-file* pathname :truename *resolve-symlinks*) (process-output-translations (validate-output-translations-file pathname) :inherit inherit :collect collect)) (t (inherit-output-translations inherit :collect collect)))) (defmethod process-output-translations ((string string) &key inherit collect) (process-output-translations (parse-output-translations-string string) :inherit inherit :collect collect)) (defmethod process-output-translations ((x null) &key inherit collect) (inherit-output-translations inherit :collect collect)) (defmethod process-output-translations ((form cons) &key inherit collect) (dolist (directive (cdr (validate-output-translations-form form))) (process-output-translations-directive directive :inherit inherit :collect collect))) ;;; Top-level entry-points to configure output-translations (defun compute-output-translations (&optional parameter) "read the configuration, return it" (remove-duplicates (while-collecting (c) (inherit-output-translations `(wrapping-output-translations ,parameter ,@*default-output-translations*) :collect #'c)) :test 'equal :from-end t)) ;; Saving the user-provided parameter to output-translations, if any, ;; so we can recompute the translations after code upgrade. (defvar *output-translations-parameter* nil) ;; Main entry-point for users. (defun initialize-output-translations (&optional (parameter *output-translations-parameter*)) "read the configuration, initialize the internal configuration variable, return the configuration" (setf *output-translations-parameter* parameter (output-translations) (compute-output-translations parameter))) (defun disable-output-translations () "Initialize output translations in a way that maps every file to itself, effectively disabling the output translation facility." (initialize-output-translations '(:output-translations :disable-cache :ignore-inherited-configuration))) ;; checks an initial variable to see whether the state is initialized ;; or cleared. In the former case, return current configuration; in ;; the latter, initialize. ASDF will call this function at the start ;; of (asdf:find-system). (defun ensure-output-translations () (if (output-translations-initialized-p) (output-translations) (initialize-output-translations))) ;; Top-level entry-point to _use_ output-translations (defun apply-output-translations (path) (etypecase path (logical-pathname path) ((or pathname string) (ensure-output-translations) (loop :with p = (resolve-symlinks* path) :for (source destination) :in (car *output-translations*) :for root = (when (or (eq source t) (and (pathnamep source) (not (absolute-pathname-p source)))) (pathname-root p)) :for absolute-source = (cond ((eq source t) (wilden root)) (root (merge-pathnames* source root)) (t source)) :when (or (eq source t) (pathname-match-p p absolute-source)) :return (translate-pathname* p absolute-source destination root source) :finally (return p))))) ;; Hook into uiop's output-translation mechanism #-cormanlisp (setf *output-translation-function* 'apply-output-translations) ;;; Implementation-dependent hacks #+abcl ;; ABCL: make it possible to use systems provided in the ABCL jar. (defun translate-jar-pathname (source wildcard) (declare (ignore wildcard)) (flet ((normalize-device (pathname) (if (find :windows *features*) pathname (make-pathname :defaults pathname :device :unspecific)))) (let* ((jar (pathname (first (pathname-device source)))) (target-root-directory-namestring (format nil "/___jar___file___root___/~@[~A/~]" (and (find :windows *features*) (pathname-device jar)))) (relative-source (relativize-pathname-directory source)) (relative-jar (relativize-pathname-directory (ensure-directory-pathname jar))) (target-root-directory (normalize-device (pathname-directory-pathname (parse-namestring target-root-directory-namestring)))) (target-root (merge-pathnames* relative-jar target-root-directory)) (target (merge-pathnames* relative-source target-root))) (normalize-device (apply-output-translations target)))))) ;;;; ----------------------------------------------------------------- ;;;; Source Registry Configuration, by Francois-Rene Rideau ;;;; See the Manual and https://bugs.launchpad.net/asdf/+bug/485918 (uiop/package:define-package :asdf/source-registry ;; NB: asdf/find-system allows upgrade from <=3.2.1 that have initialize-source-registry there (:recycle :asdf/source-registry :asdf/find-system :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/system :asdf/system-registry) (:export #:*source-registry-parameter* #:*default-source-registries* #:invalid-source-registry #:source-registry-initialized-p #:initialize-source-registry #:clear-source-registry #:*source-registry* #:ensure-source-registry #:*source-registry-parameter* #:*default-source-registry-exclusions* #:*source-registry-exclusions* #:*wild-asd* #:directory-asd-files #:register-asd-directory #:*recurse-beyond-asds* #:collect-asds-in-directory #:collect-sub*directories-asd-files #:validate-source-registry-directive #:validate-source-registry-form #:validate-source-registry-file #:validate-source-registry-directory #:parse-source-registry-string #:wrapping-source-registry #:default-user-source-registry #:default-system-source-registry #:user-source-registry #:system-source-registry #:user-source-registry-directory #:system-source-registry-directory #:environment-source-registry #:process-source-registry #:inherit-source-registry #:compute-source-registry #:flatten-source-registry #:sysdef-source-registry-search)) (in-package :asdf/source-registry) (with-upgradability () (define-condition invalid-source-registry (invalid-configuration warning) ((format :initform (compatfmt "~@")))) ;; Default list of directories under which the source-registry tree search won't recurse (defvar *default-source-registry-exclusions* '(;;-- Using ack 1.2 exclusions ".bzr" ".cdv" ;; "~.dep" "~.dot" "~.nib" "~.plst" ; we don't support ack wildcards ".git" ".hg" ".pc" ".svn" "CVS" "RCS" "SCCS" "_darcs" "_sgbak" "autom4te.cache" "cover_db" "_build" ;;-- debian often builds stuff under the debian directory... BAD. "debian")) ;; Actual list of directories under which the source-registry tree search won't recurse (defvar *source-registry-exclusions* *default-source-registry-exclusions*) ;; The state of the source-registry after search in configured locations (defvar *source-registry* nil "Either NIL (for uninitialized), or an equal hash-table, mapping system names to pathnames of .asd files") ;; Saving the user-provided parameter to the source-registry, if any, ;; so we can recompute the source-registry after code upgrade. (defvar *source-registry-parameter* nil) (defun source-registry-initialized-p () (typep *source-registry* 'hash-table)) (defun clear-source-registry () "Undoes any initialization of the source registry." (setf *source-registry* nil) (values)) (register-clear-configuration-hook 'clear-source-registry) (defparameter *wild-asd* (make-pathname :directory nil :name *wild* :type "asd" :version :newest)) (defun directory-asd-files (directory) (directory-files directory *wild-asd*)) (defun collect-asds-in-directory (directory collect) (let ((asds (directory-asd-files directory))) (map () collect asds) asds)) (defvar *recurse-beyond-asds* t "Should :tree entries of the source-registry recurse in subdirectories after having found a .asd file? True by default.") ;; When walking down a filesystem tree, if in a directory there is a .cl-source-registry.cache, ;; read its contents instead of further recursively querying the filesystem. (defun process-source-registry-cache (directory collect) (let ((cache (ignore-errors (safe-read-file-form (subpathname directory ".cl-source-registry.cache"))))) (when (and (listp cache) (eq :source-registry-cache (first cache))) (loop :for s :in (rest cache) :do (funcall collect (subpathname directory s))) t))) (defun collect-sub*directories-asd-files (directory &key (exclude *default-source-registry-exclusions*) collect (recurse-beyond-asds *recurse-beyond-asds*) ignore-cache) (let ((visited (make-hash-table :test 'equalp))) (flet ((collectp (dir) (unless (and (not ignore-cache) (process-source-registry-cache dir collect)) (let ((asds (collect-asds-in-directory dir collect))) (or recurse-beyond-asds (not asds))))) (recursep (x) ; x will be a directory pathname (and (not (member (car (last (pathname-directory x))) exclude :test #'equal)) (flet ((pathname-key (x) (namestring (truename* x)))) (let ((visitedp (gethash (pathname-key x) visited))) (if visitedp nil (setf (gethash (pathname-key x) visited) t))))))) (collect-sub*directories directory #'collectp #'recursep (constantly nil))))) ;;; Validate the configuration forms (defun validate-source-registry-directive (directive) (or (member directive '(:default-registry)) (and (consp directive) (let ((rest (rest directive))) (case (first directive) ((:include :directory :tree) (and (length=n-p rest 1) (location-designator-p (first rest)))) ((:exclude :also-exclude) (every #'stringp rest)) ((:default-registry) (null rest))))))) (defun validate-source-registry-form (form &key location) (validate-configuration-form form :source-registry 'validate-source-registry-directive :location location :invalid-form-reporter 'invalid-source-registry)) (defun validate-source-registry-file (file) (validate-configuration-file file 'validate-source-registry-form :description "a source registry")) (defun validate-source-registry-directory (directory) (validate-configuration-directory directory :source-registry 'validate-source-registry-directive :invalid-form-reporter 'invalid-source-registry)) ;;; Parse the configuration string (defun parse-source-registry-string (string &key location) (cond ((or (null string) (equal string "")) '(:source-registry :inherit-configuration)) ((not (stringp string)) (error (compatfmt "~@") string)) ((find (char string 0) "\"(") (validate-source-registry-form (read-from-string string) :location location)) (t (loop :with inherit = nil :with directives = () :with start = 0 :with end = (length string) :with separator = (inter-directory-separator) :for pos = (position separator string :start start) :do (let ((s (subseq string start (or pos end)))) (flet ((check (dir) (unless (absolute-pathname-p dir) (error (compatfmt "~@") string)) dir)) (cond ((equal "" s) ; empty element: inherit (when inherit (error (compatfmt "~@") string)) (setf inherit t) (push ':inherit-configuration directives)) ((string-suffix-p s "//") ;; TODO: allow for doubling of separator even outside Unix? (push `(:tree ,(check (subseq s 0 (- (length s) 2)))) directives)) (t (push `(:directory ,(check s)) directives)))) (cond (pos (setf start (1+ pos))) (t (unless inherit (push '(:ignore-inherited-configuration) directives)) (return `(:source-registry ,@(nreverse directives)))))))))) (defun register-asd-directory (directory &key recurse exclude collect) (if (not recurse) (collect-asds-in-directory directory collect) (collect-sub*directories-asd-files directory :exclude exclude :collect collect))) (defparameter* *default-source-registries* '(environment-source-registry user-source-registry user-source-registry-directory default-user-source-registry system-source-registry system-source-registry-directory default-system-source-registry) "List of default source registries" "3.1.0.102") (defparameter *source-registry-file* (parse-unix-namestring "common-lisp/source-registry.conf")) (defparameter *source-registry-directory* (parse-unix-namestring "common-lisp/source-registry.conf.d/")) (defun wrapping-source-registry () `(:source-registry #+(or clasp ecl sbcl) (:tree ,(resolve-symlinks* (lisp-implementation-directory))) :inherit-configuration #+mkcl (:tree ,(translate-logical-pathname "SYS:")) #+cmucl (:tree #p"modules:") #+scl (:tree #p"file://modules/"))) (defun default-user-source-registry () `(:source-registry (:tree (:home "common-lisp/")) #+sbcl (:directory (:home ".sbcl/systems/")) (:directory ,(xdg-data-home "common-lisp/systems/")) (:tree ,(xdg-data-home "common-lisp/source/")) :inherit-configuration)) (defun default-system-source-registry () `(:source-registry ,@(loop :for dir :in (xdg-data-dirs "common-lisp/") :collect `(:directory (,dir "systems/")) :collect `(:tree (,dir "source/"))) :inherit-configuration)) (defun user-source-registry (&key (direction :input)) (xdg-config-pathname *source-registry-file* direction)) (defun system-source-registry (&key (direction :input)) (find-preferred-file (system-config-pathnames *source-registry-file*) :direction direction)) (defun user-source-registry-directory (&key (direction :input)) (xdg-config-pathname *source-registry-directory* direction)) (defun system-source-registry-directory (&key (direction :input)) (find-preferred-file (system-config-pathnames *source-registry-directory*) :direction direction)) (defun environment-source-registry () (getenv "CL_SOURCE_REGISTRY")) ;;; Process the source-registry configuration (defgeneric process-source-registry (spec &key inherit register)) (defun inherit-source-registry (inherit &key register) (when inherit (process-source-registry (first inherit) :register register :inherit (rest inherit)))) (defun process-source-registry-directive (directive &key inherit register) (destructuring-bind (kw &rest rest) (if (consp directive) directive (list directive)) (ecase kw ((:include) (destructuring-bind (pathname) rest (process-source-registry (resolve-location pathname) :inherit nil :register register))) ((:directory) (destructuring-bind (pathname) rest (when pathname (funcall register (resolve-location pathname :ensure-directory t))))) ((:tree) (destructuring-bind (pathname) rest (when pathname (funcall register (resolve-location pathname :ensure-directory t) :recurse t :exclude *source-registry-exclusions*)))) ((:exclude) (setf *source-registry-exclusions* rest)) ((:also-exclude) (appendf *source-registry-exclusions* rest)) ((:default-registry) (inherit-source-registry '(default-user-source-registry default-system-source-registry) :register register)) ((:inherit-configuration) (inherit-source-registry inherit :register register)) ((:ignore-inherited-configuration) nil))) nil) (defmethod process-source-registry ((x symbol) &key inherit register) (process-source-registry (funcall x) :inherit inherit :register register)) (defmethod process-source-registry ((pathname pathname) &key inherit register) (cond ((directory-pathname-p pathname) (let ((*here-directory* (resolve-symlinks* pathname))) (process-source-registry (validate-source-registry-directory pathname) :inherit inherit :register register))) ((probe-file* pathname :truename *resolve-symlinks*) (let ((*here-directory* (pathname-directory-pathname pathname))) (process-source-registry (validate-source-registry-file pathname) :inherit inherit :register register))) (t (inherit-source-registry inherit :register register)))) (defmethod process-source-registry ((string string) &key inherit register) (process-source-registry (parse-source-registry-string string) :inherit inherit :register register)) (defmethod process-source-registry ((x null) &key inherit register) (inherit-source-registry inherit :register register)) (defmethod process-source-registry ((form cons) &key inherit register) (let ((*source-registry-exclusions* *default-source-registry-exclusions*)) (dolist (directive (cdr (validate-source-registry-form form))) (process-source-registry-directive directive :inherit inherit :register register)))) ;; Flatten the user-provided configuration into an ordered list of directories and trees (defun flatten-source-registry (&optional (parameter *source-registry-parameter*)) (remove-duplicates (while-collecting (collect) (with-pathname-defaults () ;; be location-independent (inherit-source-registry `(wrapping-source-registry ,parameter ,@*default-source-registries*) :register #'(lambda (directory &key recurse exclude) (collect (list directory :recurse recurse :exclude exclude)))))) :test 'equal :from-end t)) ;; MAYBE: move this utility function to uiop/pathname and export it? (defun pathname-directory-depth (p) (length (normalize-pathname-directory-component (pathname-directory p)))) (defun preferred-source-path-p (x y) "Return T iff X is to be preferred over Y as a source path" (let ((lx (pathname-directory-depth x)) (ly (pathname-directory-depth y))) (or (< lx ly) (and (= lx ly) (string< (namestring x) (namestring y)))))) ;; Will read the configuration and initialize all internal variables. (defun compute-source-registry (&optional (parameter *source-registry-parameter*) (registry *source-registry*)) (dolist (entry (flatten-source-registry parameter)) (destructuring-bind (directory &key recurse exclude) entry (let* ((h (make-hash-table :test 'equal))) ; table to detect duplicates (register-asd-directory directory :recurse recurse :exclude exclude :collect #'(lambda (asd) (let* ((name (pathname-name asd)) (name (if (typep asd 'logical-pathname) ;; logical pathnames are upper-case, ;; at least in the CLHS and on SBCL, ;; yet (coerce-name :foo) is lower-case. ;; won't work well with (load-system "Foo") ;; instead of (load-system 'foo) (string-downcase name) name))) (unless (gethash name registry) ; already shadowed by something else (if-let (old (gethash name h)) ;; If the name appears multiple times, ;; prefer the one with the shallowest directory, ;; or if they have same depth, compare unix-namestring with string< (multiple-value-bind (better worse) (if (preferred-source-path-p asd old) (progn (setf (gethash name h) asd) (values asd old)) (values old asd)) (when *verbose-out* (warn (compatfmt "~@") directory recurse name better worse))) (setf (gethash name h) asd)))))) (maphash #'(lambda (k v) (setf (gethash k registry) v)) h)))) (values)) (defun initialize-source-registry (&optional (parameter *source-registry-parameter*)) ;; Record the parameter used to configure the registry (setf *source-registry-parameter* parameter) ;; Clear the previous registry database: (setf *source-registry* (make-hash-table :test 'equal)) ;; Do it! (compute-source-registry parameter)) ;; Checks an initial variable to see whether the state is initialized ;; or cleared. In the former case, return current configuration; in ;; the latter, initialize. ASDF will call this function at the start ;; of (asdf:find-system) to make sure the source registry is initialized. ;; However, it will do so *without* a parameter, at which point it ;; will be too late to provide a parameter to this function, though ;; you may override the configuration explicitly by calling ;; initialize-source-registry directly with your parameter. (defun ensure-source-registry (&optional parameter) (unless (source-registry-initialized-p) (initialize-source-registry parameter)) (values)) (defun sysdef-source-registry-search (system) (ensure-source-registry) (values (gethash (primary-system-name system) *source-registry*)))) ;;;; ------------------------------------------------------------------------- ;;; Internal hacks for backward-compatibility (uiop/package:define-package :asdf/backward-internals (:recycle :asdf/backward-internals :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/find-system) (:export #:load-sysdef)) (in-package :asdf/backward-internals) (with-asdf-deprecation (:style-warning "3.2" :warning "3.4") (defun load-sysdef (name pathname) (declare (ignore name pathname)) ;; Needed for backward compatibility with swank-asdf from SLIME 2015-12-01 or older. (error "Use asdf:load-asd instead of asdf::load-sysdef"))) ;;;; ------------------------------------------------------------------------- ;;; Backward-compatible interfaces (uiop/package:define-package :asdf/backward-interface (:recycle :asdf/backward-interface :asdf) (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/system :asdf/system-registry :asdf/operation :asdf/action :asdf/lisp-action :asdf/plan :asdf/operate :asdf/find-system :asdf/parse-defsystem :asdf/output-translations :asdf/bundle) (:export #:*asdf-verbose* #:operation-error #:compile-error #:compile-failed #:compile-warned #:error-component #:error-operation #:traverse #:component-load-dependencies #:enable-asdf-binary-locations-compatibility #:operation-on-failure #:operation-on-warnings #:on-failure #:on-warnings #:component-property #:run-shell-command #:system-definition-pathname #:system-registered-p #:require-system #:explain #+ecl #:make-build)) (in-package :asdf/backward-interface) ;; NB: the warning status of these functions may have to be distinguished later, ;; as some get removed faster than the others in client code. (with-asdf-deprecation (:style-warning "3.2" :warning "3.4") ;; These conditions from ASDF 1 and 2 are used by many packages in Quicklisp; ;; but ASDF3 replaced them with somewhat different variants of uiop:compile-condition ;; that do not involve ASDF actions. ;; TODO: find the offenders and stop them. (progn (define-condition operation-error (error) ;; Bad, backward-compatible name ;; Used by SBCL, cffi-tests, clsql-mysql, clsql-uffi, qt, elephant, uffi-tests, sb-grovel ((component :reader error-component :initarg :component) (operation :reader error-operation :initarg :operation)) (:report (lambda (c s) (format s (compatfmt "~@<~A while invoking ~A on ~A~@:>") (type-of c) (error-operation c) (error-component c))))) (define-condition compile-error (operation-error) ()) (define-condition compile-failed (compile-error) ()) (define-condition compile-warned (compile-error) ())) ;; In Quicklisp 2015-05, still used by lisp-executable, staple, repl-utilities, cffi (defun component-load-dependencies (component) ;; from ASDF 2.000 to 2.26 "DEPRECATED. Please use COMPONENT-SIDEWAY-DEPENDENCIES instead; or better, define your operations with proper use of SIDEWAY-OPERATION, SELFWARD-OPERATION, or define methods on PREPARE-OP, etc." ;; Old deprecated name for the same thing. Please update your software. (component-sideway-dependencies component)) ;; These old interfaces from ASDF1 have never been very meaningful ;; but are still used in obscure places. ;; In Quicklisp 2015-05, still used by cl-protobufs and clx. (defgeneric operation-on-warnings (operation) (:documentation "DEPRECATED. Please use UIOP:*COMPILE-FILE-WARNINGS-BEHAVIOUR* instead.")) (defgeneric operation-on-failure (operation) (:documentation "DEPRECATED. Please use UIOP:*COMPILE-FILE-FAILURE-BEHAVIOUR* instead.")) (defgeneric (setf operation-on-warnings) (x operation) (:documentation "DEPRECATED. Please SETF UIOP:*COMPILE-FILE-WARNINGS-BEHAVIOUR* instead.")) (defgeneric (setf operation-on-failure) (x operation) (:documentation "DEPRECATED. Please SETF UIOP:*COMPILE-FILE-FAILURE-BEHAVIOUR* instead.")) (progn (defmethod operation-on-warnings ((o operation)) *compile-file-warnings-behaviour*) (defmethod operation-on-failure ((o operation)) *compile-file-failure-behaviour*) (defmethod (setf operation-on-warnings) (x (o operation)) (setf *compile-file-warnings-behaviour* x)) (defmethod (setf operation-on-failure) (x (o operation)) (setf *compile-file-failure-behaviour* x))) ;; Quicklisp 2015-05: Still used by SLIME's swank-asdf (!), common-lisp-stat, ;; js-parser, osicat, babel, staple, weblocks, cl-png, plain-odbc, autoproject, ;; cl-blapack, com.informatimago, cells-gtk3, asdf-dependency-grovel, ;; cl-glfw, cffi, jwacs, montezuma (defun system-definition-pathname (x) ;; As of 2.014.8, we mean to make this function obsolete, ;; but that won't happen until all clients have been updated. "DEPRECATED. This function used to expose ASDF internals with subtle differences with respect to user expectations, that have been refactored away since. We recommend you use ASDF:SYSTEM-SOURCE-FILE instead for a mostly compatible replacement that we're supporting, or even ASDF:SYSTEM-SOURCE-DIRECTORY or ASDF:SYSTEM-RELATIVE-PATHNAME if that's whay you mean." ;;) (system-source-file x)) ;; TRAVERSE is the function used to compute a plan in ASDF 1 and 2. ;; It was never officially exposed but some people still used it. (defgeneric traverse (operation component &key &allow-other-keys) (:documentation "DEPRECATED. Use MAKE-PLAN and PLAN-ACTIONS, or REQUIRED-COMPONENTS, or some other supported interface instead. Generate and return a plan for performing OPERATION on COMPONENT. The plan returned is a list of dotted-pairs. Each pair is the CONS of ASDF operation object and a COMPONENT object. The pairs will be processed in order by OPERATE.")) (progn (define-convenience-action-methods traverse (operation component &key))) (defmethod traverse ((o operation) (c component) &rest keys &key plan-class &allow-other-keys) (plan-actions (apply 'make-plan plan-class o c keys))) ;; ASDF-Binary-Locations compatibility ;; This remains supported for legacy user, but not recommended for new users. ;; We suspect there are no more legacy users in 2016. (defun enable-asdf-binary-locations-compatibility (&key (centralize-lisp-binaries nil) (default-toplevel-directory ;; Use ".cache/common-lisp/" instead ??? (subpathname (user-homedir-pathname) ".fasls/")) (include-per-user-information nil) (map-all-source-files (or #+(or clasp clisp ecl mkcl) t nil)) (source-to-target-mappings nil) (file-types `(,(compile-file-type) "build-report" #+clasp (compile-file-type :output-type :object) #+ecl (compile-file-type :type :object) #+mkcl (compile-file-type :fasl-p nil) #+clisp "lib" #+sbcl "cfasl" #+sbcl "sbcl-warnings" #+clozure "ccl-warnings"))) "DEPRECATED. Use asdf-output-translations instead." #+(or clasp clisp ecl mkcl) (when (null map-all-source-files) (error "asdf:enable-asdf-binary-locations-compatibility doesn't support :map-all-source-files nil on CLISP, ECL and MKCL")) (let* ((patterns (if map-all-source-files (list *wild-file*) (loop :for type :in file-types :collect (make-pathname :type type :defaults *wild-file*)))) (destination-directory (if centralize-lisp-binaries `(,default-toplevel-directory ,@(when include-per-user-information (cdr (pathname-directory (user-homedir-pathname)))) :implementation ,*wild-inferiors*) `(:root ,*wild-inferiors* :implementation)))) (initialize-output-translations `(:output-translations ,@source-to-target-mappings #+abcl (#p"jar:file:/**/*.jar!/**/*.*" (:function translate-jar-pathname)) #+abcl (#p"/___jar___file___root___/**/*.*" (,@destination-directory)) ,@(loop :for pattern :in patterns :collect `((:root ,*wild-inferiors* ,pattern) (,@destination-directory ,pattern))) (t t) :ignore-inherited-configuration)))) (progn (defmethod operate :before (operation-class system &rest args &key &allow-other-keys) (declare (ignore operation-class system args)) (when (find-symbol* '#:output-files-for-system-and-operation :asdf nil) (error "ASDF 2 is not compatible with ASDF-BINARY-LOCATIONS, which you are using. ASDF 2 now achieves the same purpose with its builtin ASDF-OUTPUT-TRANSLATIONS, which should be easier to configure. Please stop using ASDF-BINARY-LOCATIONS, and instead use ASDF-OUTPUT-TRANSLATIONS. See the ASDF manual for details. In case you insist on preserving your previous A-B-L configuration, but do not know how to achieve the same effect with A-O-T, you may use function ASDF:ENABLE-ASDF-BINARY-LOCATIONS-COMPATIBILITY as documented in the manual; call that function where you would otherwise have loaded and configured A-B-L.")))) ;; run-shell-command from ASDF 2, lightly fixed from ASDF 1, copied from MK-DEFSYSTEM. Die! (defun run-shell-command (control-string &rest args) "PLEASE DO NOT USE. This function is not just DEPRECATED, but also dysfunctional. Please use UIOP:RUN-PROGRAM instead." #-(and ecl os-windows) (let ((command (apply 'format nil control-string args))) (asdf-message "; $ ~A~%" command) (let ((exit-code (ignore-errors (nth-value 2 (run-program command :force-shell t :ignore-error-status t :output *verbose-out*))))) (typecase exit-code ((integer 0 255) exit-code) (t 255)))) #+(and ecl os-windows) (not-implemented-error "run-shell-command" "for ECL on Windows.")) ;; HOW do we get rid of variables??? With a symbol-macro that issues a warning? ;; In Quicklisp 2015-05, cl-protobufs still uses it, but that should be fixed in next version. (progn (defvar *asdf-verbose* nil)) ;; backward-compatibility with ASDF2 only. Unused. ;; Do NOT use in new code. NOT SUPPORTED. ;; NB: When this goes away, remove the slot PROPERTY in COMPONENT. ;; In Quicklisp 2014-05, it's still used by yaclml, amazon-ecs, blackthorn-engine, cl-tidy. ;; See TODO for further cleanups required before to get rid of it. (defgeneric component-property (component property)) (defgeneric (setf component-property) (new-value component property)) (defmethod component-property ((c component) property) (cdr (assoc property (slot-value c 'properties) :test #'equal))) (defmethod (setf component-property) (new-value (c component) property) (let ((a (assoc property (slot-value c 'properties) :test #'equal))) (if a (setf (cdr a) new-value) (setf (slot-value c 'properties) (acons property new-value (slot-value c 'properties))))) new-value) ;; This method survives from ASDF 1, but really it is superseded by action-description. (defgeneric explain (operation component) (:documentation "Display a message describing an action. DEPRECATED. Use ASDF:ACTION-DESCRIPTION and/or ASDF::FORMAT-ACTION instead.")) (progn (define-convenience-action-methods explain (operation component))) (defmethod explain ((o operation) (c component)) (asdf-message (compatfmt "~&~@<; ~@;~A~:>~%") (action-description o c)))) (with-asdf-deprecation (:style-warning "3.3") (defun system-registered-p (name) "DEPRECATED. Return a generalized boolean that is true if a system of given NAME was registered already. NAME is a system designator, to be normalized by COERCE-NAME. The value returned if true is a pair of a timestamp and a system object." (if-let (system (registered-system name)) (cons (if-let (primary-system (registered-system (primary-system-name name))) (component-operation-time 'define-op primary-system)) system))) (defun require-system (system &rest keys &key &allow-other-keys) "Ensure the specified SYSTEM is loaded, passing the KEYS to OPERATE, but do not update the system or its dependencies if it has already been loaded." (declare (ignore keys)) (unless (component-loaded-p system) (load-system system)))) ;;; This function is for backward compatibility with ECL only. #+ecl (with-asdf-deprecation (:style-warning "3.2" :warning "9999") (defun make-build (system &rest args &key (monolithic nil) (type :fasl) (move-here nil move-here-p) prologue-code epilogue-code no-uiop prefix-lisp-object-files postfix-lisp-object-files extra-object-files &allow-other-keys) (let* ((operation (asdf/bundle::select-bundle-operation type monolithic)) (move-here-path (if (and move-here (typep move-here '(or pathname string))) (ensure-pathname move-here :namestring :lisp :ensure-directory t) (system-relative-pathname system "asdf-output/"))) (extra-build-args (remove-plist-keys '(:monolithic :type :move-here :prologue-code :epilogue-code :no-uiop :prefix-lisp-object-files :postfix-lisp-object-files :extra-object-files) args)) (build-system (if (subtypep operation 'image-op) (eval `(defsystem "asdf.make-build" :class program-system :source-file nil :pathname ,(system-source-directory system) :build-operation ,operation :build-pathname ,(subpathname move-here-path (file-namestring (first (output-files operation system)))) :depends-on (,(coerce-name system)) :prologue-code ,prologue-code :epilogue-code ,epilogue-code :no-uiop ,no-uiop :prefix-lisp-object-files ,prefix-lisp-object-files :postfix-lisp-object-files ,postfix-lisp-object-files :extra-object-files ,extra-object-files :extra-build-args ,extra-build-args)) system)) (files (output-files operation build-system))) (operate operation build-system) (if (or move-here (and (null move-here-p) (member operation '(program-op image-op)))) (loop :with dest-path = (resolve-symlinks* (ensure-directories-exist move-here-path)) :for f :in files :for new-f = (make-pathname :name (pathname-name f) :type (pathname-type f) :defaults dest-path) :do (rename-file-overwriting-target f new-f) :collect new-f) files)))) ;;;; --------------------------------------------------------------------------- ;;;; Handle ASDF package upgrade, including implementation-dependent magic. (uiop/package:define-package :asdf/interface (:nicknames :asdf :asdf-utilities) (:recycle :asdf/interface :asdf) (:unintern #:loaded-systems ; makes for annoying SLIME completion #:output-files-for-system-and-operation) ; ASDF-BINARY-LOCATION function we use to detect ABL (:use :uiop/common-lisp :uiop :asdf/upgrade :asdf/session :asdf/component :asdf/system :asdf/system-registry :asdf/find-component :asdf/operation :asdf/action :asdf/lisp-action :asdf/output-translations :asdf/source-registry :asdf/forcing :asdf/plan :asdf/operate :asdf/find-system :asdf/parse-defsystem :asdf/bundle :asdf/concatenate-source :asdf/backward-internals :asdf/backward-interface :asdf/package-inferred-system) ;; Note: (1) we are NOT automatically reexporting everything from previous packages. ;; (2) we only reexport UIOP functionality when backward-compatibility requires it. (:export #:defsystem #:find-system #:load-asd #:locate-system #:coerce-name #:primary-system-name #:primary-system-p #:oos #:operate #:make-plan #:perform-plan #:sequential-plan #:system-definition-pathname #:search-for-system-definition #:find-component #:component-find-path #:compile-system #:load-system #:load-systems #:load-systems* #:require-system #:test-system #:clear-system #:operation #:make-operation #:find-operation #:upward-operation #:downward-operation #:sideway-operation #:selfward-operation #:non-propagating-operation #:build-op #:make #:load-op #:prepare-op #:compile-op #:prepare-source-op #:load-source-op #:test-op #:define-op #:feature #:version #:version-satisfies #:upgrade-asdf #:implementation-identifier #:implementation-type #:hostname #:component-depends-on ; backward-compatible name rather than action-depends-on #:input-files #:additional-input-files #:output-files #:output-file #:perform #:perform-with-restarts #:operation-done-p #:explain #:action-description #:component-sideway-dependencies #:needed-in-image-p #:bundle-op #:monolithic-bundle-op #:precompiled-system #:compiled-file #:bundle-system #:program-system #:basic-compile-bundle-op #:prepare-bundle-op #:compile-bundle-op #:load-bundle-op #:monolithic-compile-bundle-op #:monolithic-load-bundle-op #:lib-op #:dll-op #:deliver-asd-op #:program-op #:image-op #:monolithic-lib-op #:monolithic-dll-op #:monolithic-deliver-asd-op #:concatenate-source-op #:load-concatenated-source-op #:compile-concatenated-source-op #:load-compiled-concatenated-source-op #:monolithic-concatenate-source-op #:monolithic-load-concatenated-source-op #:monolithic-compile-concatenated-source-op #:monolithic-load-compiled-concatenated-source-op #:operation-monolithic-p #:required-components #:component-loaded-p #:component #:parent-component #:child-component #:system #:module #:file-component #:source-file #:c-source-file #:java-source-file #:cl-source-file #:cl-source-file.cl #:cl-source-file.lsp #:static-file #:doc-file #:html-file #:file-type #:source-file-type #:register-preloaded-system #:sysdef-preloaded-system-search #:register-immutable-system #:sysdef-immutable-system-search #:package-inferred-system #:register-system-packages #:component-children #:component-children-by-name #:component-pathname #:component-relative-pathname #:component-name #:component-version #:component-parent #:component-system #:component-encoding #:component-external-format #:system-description #:system-long-description #:system-author #:system-maintainer #:system-license #:system-licence #:system-version #:system-source-file #:system-source-directory #:system-relative-pathname #:system-homepage #:system-mailto #:system-bug-tracker #:system-long-name #:system-source-control #:map-systems #:system-defsystem-depends-on #:system-depends-on #:system-weakly-depends-on #:*system-definition-search-functions* ; variables #:*central-registry* #:*compile-file-warnings-behaviour* #:*compile-file-failure-behaviour* #:*resolve-symlinks* #:*verbose-out* #:asdf-version #:compile-condition #:compile-file-error #:compile-warned-error #:compile-failed-error #:compile-warned-warning #:compile-failed-warning #:error-name #:error-pathname #:load-system-definition-error #:error-component #:error-operation #:system-definition-error #:missing-component #:missing-component-of-version #:missing-dependency #:missing-dependency-of-version #:circular-dependency ; errors #:duplicate-names #:non-toplevel-system #:non-system-system #:bad-system-name #:system-out-of-date #:package-inferred-system-missing-package-error #:operation-definition-warning #:operation-definition-error #:try-recompiling ; restarts #:retry #:accept #:coerce-entry-to-directory #:remove-entry-from-registry #:clear-configuration-and-retry #:*encoding-detection-hook* #:*encoding-external-format-hook* #:*default-encoding* #:*utf-8-external-format* #:clear-configuration #:*output-translations-parameter* #:initialize-output-translations #:disable-output-translations #:clear-output-translations #:ensure-output-translations #:apply-output-translations #:compile-file* #:compile-file-pathname* #:*warnings-file-type* #:enable-deferred-warnings-check #:disable-deferred-warnings-check #:enable-asdf-binary-locations-compatibility #:*default-source-registries* #:*source-registry-parameter* #:initialize-source-registry #:compute-source-registry #:clear-source-registry #:ensure-source-registry #:process-source-registry #:registered-system #:registered-systems #:already-loaded-systems #:resolve-location #:asdf-message #:*user-cache* #:user-output-translations-pathname #:system-output-translations-pathname #:user-output-translations-directory-pathname #:system-output-translations-directory-pathname #:user-source-registry #:system-source-registry #:user-source-registry-directory #:system-source-registry-directory ;; The symbols below are all DEPRECATED, do not use. To be removed in a further release. #:*asdf-verbose* #:run-shell-command #:component-load-dependencies #:system-registered-p #:package-system #+ecl #:make-build #:operation-on-warnings #:operation-on-failure #:operation-error #:compile-failed #:compile-warned #:compile-error #:module-components #:component-property #:traverse)) ;;;; --------------------------------------------------------------------------- ;;;; ASDF-USER, where the action happens. (uiop/package:define-package :asdf/user (:nicknames :asdf-user) ;; NB: releases before 3.1.2 this :use'd only uiop/package instead of uiop below. ;; They also :use'd uiop/common-lisp, that reexports common-lisp and is not included in uiop. ;; ASDF3 releases from 2.27 to 2.31 called uiop asdf-driver and asdf/foo uiop/foo. ;; ASDF1 and ASDF2 releases (2.26 and earlier) create a temporary package ;; that only :use's :cl and :asdf (:use :uiop/common-lisp :uiop :asdf/interface)) ;;;; ----------------------------------------------------------------------- ;;;; ASDF Footer: last words and cleanup (uiop/package:define-package :asdf/footer (:recycle :asdf/footer :asdf) (:use :uiop/common-lisp :uiop :asdf/system ;; used by ECL :asdf/upgrade :asdf/system-registry :asdf/operate :asdf/bundle) ;; Happily, all those implementations all have the same module-provider hook interface. #+(or abcl clasp cmucl clozure ecl mezzano mkcl sbcl) (:import-from #+abcl :sys #+(or clasp cmucl ecl) :ext #+clozure :ccl #+mkcl :mk-ext #+sbcl sb-ext #+mezzano :sys.int #:*module-provider-functions* #+ecl #:*load-hooks*) #+(or clasp mkcl) (:import-from :si #:*load-hooks*)) (in-package :asdf/footer) ;;;; Register ASDF itself and all its subsystems as preloaded. (with-upgradability () (dolist (s '("asdf" "asdf-package-system")) ;; Don't bother with these system names, no one relies on them anymore: ;; "asdf-utils" "asdf-bundle" "asdf-driver" "asdf-defsystem" (register-preloaded-system s :version *asdf-version*)) (register-preloaded-system "uiop" :version *uiop-version*)) ;;;; Ensure that the version slot on the registered preloaded systems are ;;;; correct, by CLEARing the system. However, we do not CLEAR-SYSTEM ;;;; unconditionally. This is because it's possible the user has upgraded the ;;;; systems using ASDF itself, meaning that the registered systems have real ;;;; data from the file system that we want to preserve instead of blasting ;;;; away and replacing with a blank preloaded system. (with-upgradability () (unless (equal (system-version (registered-system "asdf")) (asdf-version)) (clear-system "asdf")) ;; 3.1.2 is the last version where asdf-package-system was a separate system. (when (version< "3.1.2" (system-version (registered-system "asdf-package-system"))) (clear-system "asdf-package-system")) (unless (equal (system-version (registered-system "uiop")) *uiop-version*) (clear-system "uiop"))) ;;;; Hook ASDF into the implementation's REQUIRE and other entry points. #+(or abcl clasp clisp clozure cmucl ecl mezzano mkcl sbcl) (with-upgradability () ;; Hook into CL:REQUIRE. #-clisp (pushnew 'module-provide-asdf *module-provider-functions*) #+clisp (if-let (x (find-symbol* '#:*module-provider-functions* :custom nil)) (eval `(pushnew 'module-provide-asdf ,x))) #+(or clasp ecl mkcl) (progn (pushnew '("fasb" . si::load-binary) *load-hooks* :test 'equal :key 'car) #+os-windows (unless (assoc "asd" *load-hooks* :test 'equal) (appendf *load-hooks* '(("asd" . si::load-source)))) ;; Wrap module provider functions in an idempotent, upgrade friendly way (defvar *wrapped-module-provider* (make-hash-table)) (setf (gethash 'module-provide-asdf *wrapped-module-provider*) 'module-provide-asdf) (defun wrap-module-provider (provider name) (let ((results (multiple-value-list (funcall provider name)))) (when (first results) (register-preloaded-system (coerce-name name))) (values-list results))) (defun wrap-module-provider-function (provider) (ensure-gethash provider *wrapped-module-provider* (constantly #'(lambda (module-name) (wrap-module-provider provider module-name))))) (setf *module-provider-functions* (mapcar #'wrap-module-provider-function *module-provider-functions*)))) #+cmucl ;; Hook into the CMUCL herald. (with-upgradability () (defun herald-asdf (stream) (format stream " ASDF ~A" (asdf-version))) (setf (getf ext:*herald-items* :asdf) '(herald-asdf))) ;;;; Done! (with-upgradability () #+allegro ;; restore *w-o-n-r-c* setting as saved in uiop/common-lisp (when (boundp 'excl:*warn-on-nested-reader-conditionals*) (setf excl:*warn-on-nested-reader-conditionals* uiop/common-lisp::*acl-warn-save*)) ;; Advertise the features we provide. (dolist (f '(:asdf :asdf2 :asdf3 :asdf3.1 :asdf3.2 :asdf3.3)) (pushnew f *features*)) ;; Provide both lowercase and uppercase, to satisfy more people, especially LispWorks users. (provide "asdf") (provide "ASDF") ;; Finally, call a function that will cleanup in case this is an upgrade of an older ASDF. (cleanup-upgraded-asdf)) (when *load-verbose* (asdf-message ";; ASDF, version ~a~%" (asdf-version))) abcl-src-1.9.0/src/org/armedbear/lisp/ash.java0100644 0000000 0000000 00000003571 14202767264 017643 0ustar000000000 0000000 /* * ash.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### ash // ash integer count => shifted-integer public final class ash extends Primitive { private ash() { super("ash", "integer count"); } @Override public LispObject execute(LispObject first, LispObject second) { return first.ash(second); } private static final Primitive ASH = new ash(); } abcl-src-1.9.0/src/org/armedbear/lisp/assert.lisp0100644 0000000 0000000 00000006202 14223403213 020371 0ustar000000000 0000000 ;;; assert.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package #:system) (defmacro assert (test-form &optional places datum &rest arguments) "Signals an error if the value of test-form is nil. Continuing from this error using the CONTINUE restart will allow the user to alter the value of some locations known to SETF and start over with test-form. Returns nil." `(loop (when ,test-form (return nil)) (assert-error ',test-form ',places ,datum ,@arguments) ,@(mapcar #'(lambda (place) `(setf ,place (assert-prompt ',place ,place))) places))) (defun assert-error (assertion places datum &rest arguments) (declare (ignore places)) (let ((c (if datum (coerce-to-condition datum arguments 'simple-error 'error) (make-condition 'simple-error :format-control "The assertion ~S failed." :format-arguments (list assertion))))) (restart-case (error c) (continue () :report (lambda (stream) (format stream "Retry assertion.")) nil)))) (defun assert-prompt (name value) (cond ((y-or-n-p "The old value of ~S is ~S.~%Do you want to supply a new value? " name value) (fresh-line *query-io*) (format *query-io* "Type a form to be evaluated:~%") (flet ((read-it () (eval (read *query-io*)))) (if (symbolp name) ;help user debug lexical variables (progv (list name) (list value) (read-it)) (read-it)))) (t value))) abcl-src-1.9.0/src/org/armedbear/lisp/assoc.lisp0100644 0000000 0000000 00000011164 14223403213 020203 0ustar000000000 0000000 ;;; assoc.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From CMUCL. (in-package "SYSTEM") (defmacro assoc-guts (test-guy) `(do ((alist alist (cdr alist))) ((endp alist)) (if (car alist) (if ,test-guy (return (car alist)))))) (defun assoc (item alist &key key test test-not) (cond (test (if key (assoc-guts (funcall test item (funcall key (caar alist)))) (assoc-guts (funcall test item (caar alist))))) (test-not (if key (assoc-guts (not (funcall test-not item (funcall key (caar alist))))) (assoc-guts (not (funcall test-not item (caar alist)))))) (t (if key (assoc-guts (eql item (funcall key (caar alist)))) (assoc-guts (eql item (caar alist))))))) (defun assoc-if (predicate alist &key key) (if key (assoc-guts (funcall predicate (funcall key (caar alist)))) (assoc-guts (funcall predicate (caar alist))))) (defun assoc-if-not (predicate alist &key key) (if key (assoc-guts (not (funcall predicate (funcall key (caar alist))))) (assoc-guts (not (funcall predicate (caar alist)))))) (defun rassoc (item alist &key key test test-not) (cond (test (if key (assoc-guts (funcall test item (funcall key (cdar alist)))) (assoc-guts (funcall test item (cdar alist))))) (test-not (if key (assoc-guts (not (funcall test-not item (funcall key (cdar alist))))) (assoc-guts (not (funcall test-not item (cdar alist)))))) (t (if key (assoc-guts (eql item (funcall key (cdar alist)))) (assoc-guts (eql item (cdar alist))))))) (defun rassoc-if (predicate alist &key key) (if key (assoc-guts (funcall predicate (funcall key (cdar alist)))) (assoc-guts (funcall predicate (cdar alist))))) (defun rassoc-if-not (predicate alist &key key) (if key (assoc-guts (not (funcall predicate (funcall key (cdar alist))))) (assoc-guts (not (funcall predicate (cdar alist)))))) (defun acons (key datum alist) (cons (cons key datum) alist)) (defun pairlis (keys data &optional (alist '())) (do ((x keys (cdr x)) (y data (cdr y))) ((and (endp x) (endp y)) alist) (if (or (endp x) (endp y)) (error "the lists of keys and data are of unequal length")) (setq alist (acons (car x) (car y) alist)))) ;;; From SBCL. (defun copy-alist (alist) "Return a new association list which is EQUAL to ALIST." (if (endp alist) alist (let ((result (cons (if (atom (car alist)) (car alist) (cons (caar alist) (cdar alist))) nil))) (do ((x (cdr alist) (cdr x)) (splice result (cdr (rplacd splice (cons (if (atom (car x)) (car x) (cons (caar x) (cdar x))) nil))))) ((endp x))) result))) abcl-src-1.9.0/src/org/armedbear/lisp/assq.java0100644 0000000 0000000 00000003633 14202767264 020036 0ustar000000000 0000000 /* * assq.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### assq item alist => entry public final class assq extends Primitive { private assq() { super("assq", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject item, LispObject alist) { return Lisp.assq(item, alist); } private static final Primitive ASSQ = new assq(); } abcl-src-1.9.0/src/org/armedbear/lisp/assql.java0100644 0000000 0000000 00000004313 14202767264 020206 0ustar000000000 0000000 /* * assql.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### assql item alist => entry public final class assql extends Primitive { private assql() { super("assql", PACKAGE_EXT); } @Override public LispObject execute(LispObject item, LispObject alist) { while (alist != NIL) { LispObject cons = alist.car(); if (cons instanceof Cons) { if (cons.car().eql(item)) return cons; } else if (cons != NIL) return type_error(cons, Symbol.LIST); alist = alist.cdr(); } return NIL; } private static final Primitive ASSQL = new assql(); } abcl-src-1.9.0/src/org/armedbear/lisp/autoloads-gen.lisp0100644 0000000 0000000 00000146010 14202767264 021654 0ustar000000000 0000000 ;; This is a bootstrapping file ;; We need a file in place before starting compilation, because ;; 'autoloads.lisp' only contains the manual additions. ;; The content has been generated using the same code as the code which ;; is used at build-time. ;; Generation of an file up-to-date file is part of the build process ;; and that file is included in abcl.jar. ;; ---- GENERATED CONTENT BELOW ;; FUNCTIONS (IN-PACKAGE :FORMAT) (DOLIST (SYSTEM::FS (QUOTE ((("format") %PRINT-FORMAT-ERROR MISSING-ARG MAKE-FORMAT-DIRECTIVE FORMAT-DIRECTIVE-P TOKENIZE-CONTROL-STRING PARSE-DIRECTIVE %FORMATTER EXPAND-CONTROL-STRING EXPAND-DIRECTIVE-LIST EXPAND-DIRECTIVE EXPAND-NEXT-ARG %SET-FORMAT-DIRECTIVE-EXPANDER %SET-FORMAT-DIRECTIVE-INTERPRETER FIND-DIRECTIVE A-FORMAT-DIRECTIVE-EXPANDER S-FORMAT-DIRECTIVE-EXPANDER C-FORMAT-DIRECTIVE-EXPANDER W-FORMAT-DIRECTIVE-EXPANDER EXPAND-FORMAT-INTEGER D-FORMAT-DIRECTIVE-EXPANDER B-FORMAT-DIRECTIVE-EXPANDER O-FORMAT-DIRECTIVE-EXPANDER X-FORMAT-DIRECTIVE-EXPANDER R-FORMAT-DIRECTIVE-EXPANDER P-FORMAT-DIRECTIVE-EXPANDER F-FORMAT-DIRECTIVE-EXPANDER E-FORMAT-DIRECTIVE-EXPANDER G-FORMAT-DIRECTIVE-EXPANDER $-FORMAT-DIRECTIVE-EXPANDER %-FORMAT-DIRECTIVE-EXPANDER &-FORMAT-DIRECTIVE-EXPANDER |\|-FORMAT-DIRECTIVE-EXPANDER| ~-FORMAT-DIRECTIVE-EXPANDER |Newline-FORMAT-DIRECTIVE-EXPANDER| T-FORMAT-DIRECTIVE-EXPANDER _-FORMAT-DIRECTIVE-EXPANDER I-FORMAT-DIRECTIVE-EXPANDER *-FORMAT-DIRECTIVE-EXPANDER ?-FORMAT-DIRECTIVE-EXPANDER |(-FORMAT-DIRECTIVE-EXPANDER| |)-FORMAT-DIRECTIVE-EXPANDER| [-FORMAT-DIRECTIVE-EXPANDER PARSE-CONDITIONAL-DIRECTIVE EXPAND-MAYBE-CONDITIONAL EXPAND-TRUE-FALSE-CONDITIONAL |;-FORMAT-DIRECTIVE-EXPANDER| ]-FORMAT-DIRECTIVE-EXPANDER ^-FORMAT-DIRECTIVE-EXPANDER {-FORMAT-DIRECTIVE-EXPANDER }-FORMAT-DIRECTIVE-EXPANDER ILLEGAL-INSIDE-JUSTIFICATION-P <-FORMAT-DIRECTIVE-EXPANDER >-FORMAT-DIRECTIVE-EXPANDER PARSE-FORMAT-LOGICAL-BLOCK ADD-FILL-STYLE-NEWLINES ADD-FILL-STYLE-NEWLINES-AUX PARSE-FORMAT-JUSTIFICATION EXPAND-FORMAT-LOGICAL-BLOCK EXPAND-FORMAT-JUSTIFICATION /-FORMAT-DIRECTIVE-EXPANDER EXTRACT-USER-FUN-NAME %COMPILER-WALK-FORMAT-STRING %FORMAT INTERPRET-DIRECTIVE-LIST FORMAT-WRITE-FIELD FORMAT-PRINC A-FORMAT-DIRECTIVE-INTERPRETER FORMAT-PRIN1 S-FORMAT-DIRECTIVE-INTERPRETER C-FORMAT-DIRECTIVE-INTERPRETER FORMAT-PRINT-NAMED-CHARACTER W-FORMAT-DIRECTIVE-INTERPRETER FORMAT-PRINT-INTEGER FORMAT-ADD-COMMAS D-FORMAT-DIRECTIVE-INTERPRETER B-FORMAT-DIRECTIVE-INTERPRETER O-FORMAT-DIRECTIVE-INTERPRETER X-FORMAT-DIRECTIVE-INTERPRETER R-FORMAT-DIRECTIVE-INTERPRETER FORMAT-PRINT-SMALL-CARDINAL FORMAT-PRINT-CARDINAL FORMAT-PRINT-CARDINAL-AUX FORMAT-PRINT-ORDINAL FORMAT-PRINT-OLD-ROMAN FORMAT-PRINT-ROMAN P-FORMAT-DIRECTIVE-INTERPRETER DECIMAL-STRING F-FORMAT-DIRECTIVE-INTERPRETER FORMAT-FIXED FORMAT-FIXED-AUX E-FORMAT-DIRECTIVE-INTERPRETER FORMAT-EXPONENTIAL FORMAT-EXPONENT-MARKER FORMAT-EXP-AUX G-FORMAT-DIRECTIVE-INTERPRETER FORMAT-GENERAL FORMAT-GENERAL-AUX $-FORMAT-DIRECTIVE-INTERPRETER FORMAT-DOLLARS %-FORMAT-DIRECTIVE-INTERPRETER &-FORMAT-DIRECTIVE-INTERPRETER |\|-FORMAT-DIRECTIVE-INTERPRETER| ~-FORMAT-DIRECTIVE-INTERPRETER |Newline-FORMAT-DIRECTIVE-INTERPRETER| T-FORMAT-DIRECTIVE-INTERPRETER OUTPUT-SPACES FORMAT-RELATIVE-TAB FORMAT-ABSOLUTE-TAB _-FORMAT-DIRECTIVE-INTERPRETER I-FORMAT-DIRECTIVE-INTERPRETER *-FORMAT-DIRECTIVE-INTERPRETER ?-FORMAT-DIRECTIVE-INTERPRETER |(-FORMAT-DIRECTIVE-INTERPRETER| |)-FORMAT-DIRECTIVE-INTERPRETER| [-FORMAT-DIRECTIVE-INTERPRETER |;-FORMAT-DIRECTIVE-INTERPRETER| ]-FORMAT-DIRECTIVE-INTERPRETER ^-FORMAT-DIRECTIVE-INTERPRETER {-FORMAT-DIRECTIVE-INTERPRETER }-FORMAT-DIRECTIVE-INTERPRETER <-FORMAT-DIRECTIVE-INTERPRETER INTERPRET-FORMAT-JUSTIFICATION FORMAT-JUSTIFICATION INTERPRET-FORMAT-LOGICAL-BLOCK /-FORMAT-DIRECTIVE-INTERPRETER)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :FORMAT) (DOLIST (SYSTEM::FS (QUOTE ((("format") EXPANDER-NEXT-ARG EXPAND-BIND-DEFAULTS DEF-COMPLEX-FORMAT-DIRECTIVE DEF-FORMAT-DIRECTIVE EXPANDER-PPRINT-NEXT-ARG INTERPRET-FORMAT-INTEGER)))) (FUNCALL (FUNCTION AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; FUNCTIONS ;; MACROS ;; FUNCTIONS (IN-PACKAGE :LOOP) (DOLIST (SYSTEM::FS (QUOTE ((("loop") MAKE-LOOP-MINIMAX-INTERNAL MAKE-LOOP-MINIMAX LOOP-NOTE-MINIMAX-OPERATION LOOP-TEQUAL LOOP-TASSOC LOOP-TMEMBER LOOP-LOOKUP-KEYWORD MAKE-LOOP-UNIVERSE MAKE-STANDARD-LOOP-UNIVERSE LOOP-MAKE-PSETQ LOOP-MAKE-DESETQ LOOP-CONSTANT-FOLD-IF-POSSIBLE LOOP-CONSTANTP LOOP-CODE-DUPLICATION-THRESHOLD DUPLICATABLE-CODE-P DESTRUCTURING-SIZE ESTIMATE-CODE-SIZE ESTIMATE-CODE-SIZE-1 LOOP-CONTEXT LOOP-ERROR LOOP-WARN LOOP-CHECK-DATA-TYPE SUBST-GENSYMS-FOR-NIL LOOP-BUILD-DESTRUCTURING-BINDINGS LOOP-TRANSLATE LOOP-ITERATION-DRIVER LOOP-POP-SOURCE LOOP-GET-FORM LOOP-GET-COMPOUND-FORM LOOP-GET-PROGN LOOP-CONSTRUCT-RETURN LOOP-PSEUDO-BODY LOOP-EMIT-BODY LOOP-EMIT-FINAL-VALUE LOOP-DISALLOW-CONDITIONAL LOOP-DISALLOW-ANONYMOUS-COLLECTORS LOOP-DISALLOW-AGGREGATE-BOOLEANS LOOP-TYPED-INIT LOOP-OPTIONAL-TYPE LOOP-BIND-BLOCK LOOP-VAR-P LOOP-MAKE-VAR LOOP-MAKE-ITERATION-VAR LOOP-DECLARE-VAR LOOP-MAYBE-BIND-FORM LOOP-DO-IF LOOP-DO-INITIALLY LOOP-DO-FINALLY LOOP-DO-DO LOOP-DO-NAMED LOOP-DO-RETURN MAKE-LOOP-COLLECTOR LOOP-GET-COLLECTION-INFO LOOP-LIST-COLLECTION LOOP-SUM-COLLECTION LOOP-MAXMIN-COLLECTION LOOP-DO-ALWAYS LOOP-DO-THEREIS LOOP-DO-WHILE LOOP-DO-REPEAT LOOP-DO-WITH LOOP-HACK-ITERATION LOOP-DO-FOR LOOP-WHEN-IT-VAR LOOP-ANSI-FOR-EQUALS LOOP-FOR-ACROSS LOOP-LIST-STEP LOOP-FOR-ON LOOP-FOR-IN MAKE-LOOP-PATH ADD-LOOP-PATH LOOP-FOR-BEING LOOP-NAMED-VAR LOOP-COLLECT-PREPOSITIONAL-PHRASES LOOP-SEQUENCER LOOP-FOR-ARITHMETIC LOOP-SEQUENCE-ELEMENTS-PATH LOOP-HASH-TABLE-ITERATION-PATH LOOP-PACKAGE-SYMBOLS-ITERATION-PATH MAKE-ANSI-LOOP-UNIVERSE LOOP-STANDARD-EXPANSION)))) (FUNCALL (FUNCTION EXTENSIONS:AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :LOOP) (DOLIST (SYSTEM::FS (QUOTE ((("loop") WITH-LOOP-LIST-COLLECTION-HEAD LOOP-COLLECT-RPLACD LOOP-COLLECT-ANSWER WITH-MINIMAX-VALUE LOOP-ACCUMULATE-MINIMAX-VALUE LOOP-STORE-TABLE-DATA LOOP-REALLY-DESETQ LOOP-BODY LOOP-DESTRUCTURING-BIND)))) (FUNCALL (FUNCTION EXTENSIONS:AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; EXPORTS (IN-PACKAGE :MOP) (EXPORT (QUOTE (CANONICALIZE-DIRECT-SUPERCLASSES %DEFGENERIC UPDATE-DEPENDENT MAP-DEPENDENTS REMOVE-DEPENDENT ADD-DEPENDENT EXTRACT-SPECIALIZER-NAMES EXTRACT-LAMBDA-LIST FIND-METHOD-COMBINATION REMOVE-DIRECT-METHOD ADD-DIRECT-METHOD SPECIALIZER-DIRECT-GENERIC-FUNCTIONS SPECIALIZER-DIRECT-METHODS EQL-SPECIALIZER-OBJECT INTERN-EQL-SPECIALIZER FUNCALLABLE-STANDARD-INSTANCE-ACCESS SLOT-DEFINITION-WRITERS SLOT-DEFINITION-TYPE SLOT-DEFINITION-READERS SLOT-DEFINITION-NAME SLOT-DEFINITION-LOCATION SLOT-DEFINITION-INITFUNCTION SLOT-DEFINITION-INITFORM SLOT-DEFINITION-INITARGS SLOT-DEFINITION-ALLOCATION EFFECTIVE-SLOT-DEFINITION-CLASS DIRECT-SLOT-DEFINITION-CLASS WRITER-METHOD-CLASS READER-METHOD-CLASS ACCESSOR-METHOD-SLOT-DEFINITION METHOD-SPECIALIZERS METHOD-LAMBDA-LIST METHOD-GENERIC-FUNCTION METHOD-FUNCTION GENERIC-FUNCTION-NAME GENERIC-FUNCTION-METHOD-COMBINATION GENERIC-FUNCTION-METHOD-CLASS GENERIC-FUNCTION-LAMBDA-LIST GENERIC-FUNCTION-DECLARATIONS GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER REMOVE-DIRECT-SUBCLASS ADD-DIRECT-SUBCLASS CLASS-SLOTS CLASS-PROTOTYPE CLASS-PRECEDENCE-LIST CLASS-FINALIZED-P CLASS-DIRECT-SUPERCLASSES CLASS-DIRECT-SUBCLASSES CLASS-DIRECT-SLOTS CLASS-DIRECT-DEFAULT-INITARGS CLASS-DEFAULT-INITARGS ENSURE-GENERIC-FUNCTION-USING-CLASS ENSURE-CLASS-USING-CLASS ENSURE-CLASS SLOT-MAKUNBOUND-USING-CLASS SLOT-BOUNDP-USING-CLASS SLOT-VALUE-USING-CLASS VALIDATE-SUPERCLASS FINALIZE-INHERITANCE COMPUTE-SLOTS MAKE-METHOD-LAMBDA COMPUTE-EFFECTIVE-METHOD COMPUTE-APPLICABLE-METHODS-USING-CLASSES COMPUTE-DISCRIMINATING-FUNCTION COMPUTE-EFFECTIVE-SLOT-DEFINITION COMPUTE-DEFAULT-INITARGS COMPUTE-CLASS-PRECEDENCE-LIST STANDARD-WRITER-METHOD STANDARD-READER-METHOD STANDARD-ACCESSOR-METHOD FUNCALLABLE-STANDARD-CLASS FUNCALLABLE-STANDARD-OBJECT))) ;; FUNCTIONS (IN-PACKAGE :MOP) (DOLIST (SYSTEM::FS (QUOTE ((("clos") CLASS-SLOTS CLASS-DIRECT-SLOTS CLASS-LAYOUT CLASS-DIRECT-SUPERCLASSES CLASS-DIRECT-SUBCLASSES CLASS-DIRECT-METHODS CLASS-PRECEDENCE-LIST CLASS-FINALIZED-P CLASS-DEFAULT-INITARGS CLASS-DIRECT-DEFAULT-INITARGS ADD-DIRECT-SUBCLASS REMOVE-DIRECT-SUBCLASS FIXUP-STANDARD-CLASS-HIERARCHY MAP-DEPENDENTS MAPAPPEND MAPPLIST FUNCALLABLE-STANDARD-INSTANCE-ACCESS CANONICALIZE-DIRECT-SLOTS CANONICALIZE-DIRECT-SLOT MAYBE-NOTE-NAME-DEFINED CANONICALIZE-DEFCLASS-OPTIONS CANONICALIZE-DEFCLASS-OPTION MAKE-INITFUNCTION SLOT-DEFINITION-ALLOCATION SLOT-DEFINITION-INITARGS SLOT-DEFINITION-INITFORM SLOT-DEFINITION-INITFUNCTION SLOT-DEFINITION-NAME SLOT-DEFINITION-READERS SLOT-DEFINITION-WRITERS SLOT-DEFINITION-ALLOCATION-CLASS SLOT-DEFINITION-LOCATION SLOT-DEFINITION-TYPE SLOT-DEFINITION-DOCUMENTATION INIT-SLOT-DEFINITION DIRECT-SLOT-DEFINITION-CLASS MAKE-DIRECT-SLOT-DEFINITION EFFECTIVE-SLOT-DEFINITION-CLASS MAKE-EFFECTIVE-SLOT-DEFINITION COMPUTE-DEFAULT-INITARGS STD-COMPUTE-DEFAULT-INITARGS STD-FINALIZE-INHERITANCE FINALIZE-INHERITANCE STD-COMPUTE-CLASS-PRECEDENCE-LIST TOPOLOGICAL-SORT STD-TIE-BREAKER-RULE COLLECT-SUPERCLASSES* LOCAL-PRECEDENCE-ORDERING STD-COMPUTE-SLOTS STD-COMPUTE-EFFECTIVE-SLOT-DEFINITION FIND-SLOT-DEFINITION SLOT-LOCATION INSTANCE-SLOT-LOCATION %SET-SLOT-VALUE STD-SLOT-MAKUNBOUND STD-SLOT-EXISTS-P INSTANCE-SLOT-P STD-ALLOCATE-INSTANCE ALLOCATE-FUNCALLABLE-INSTANCE CLASS-PROTOTYPE MAYBE-FINALIZE-CLASS-SUBTREE MAKE-INSTANCE-STANDARD-CLASS STD-AFTER-INITIALIZATION-FOR-CLASSES EXPAND-LONG-DEFCOMBIN %MAKE-LONG-METHOD-COMBINATION METHOD-COMBINATION-NAME METHOD-COMBINATION-DOCUMENTATION SHORT-METHOD-COMBINATION-OPERATOR SHORT-METHOD-COMBINATION-IDENTITY-WITH-ONE-ARGUMENT LONG-METHOD-COMBINATION-LAMBDA-LIST LONG-METHOD-COMBINATION-METHOD-GROUP-SPECS LONG-METHOD-COMBINATION-ARGS-LAMBDA-LIST LONG-METHOD-COMBINATION-GENERIC-FUNCTION-SYMBOL LONG-METHOD-COMBINATION-FUNCTION LONG-METHOD-COMBINATION-ARGUMENTS LONG-METHOD-COMBINATION-DECLARATIONS LONG-METHOD-COMBINATION-FORMS EXPAND-SHORT-DEFCOMBIN METHOD-GROUP-P CHECK-VARIABLE-NAME CANONICALIZE-METHOD-GROUP-SPEC EXTRACT-REQUIRED-PART EXTRACT-SPECIFIED-PART EXTRACT-OPTIONAL-PART PARSE-DEFINE-METHOD-COMBINATION-ARGS-LAMBDA-LIST WRAP-WITH-CALL-METHOD-MACRO ASSERT-UNAMBIGUOUS-METHOD-SORTING METHOD-COMBINATION-TYPE-LAMBDA-WITH-ARGS-EMF METHOD-COMBINATION-TYPE-LAMBDA DECLARATIONP LONG-FORM-METHOD-COMBINATION-ARGS DEFINE-LONG-FORM-METHOD-COMBINATION STD-FIND-METHOD-COMBINATION FIND-METHOD-COMBINATION INTERN-EQL-SPECIALIZER EQL-SPECIALIZER-OBJECT STD-METHOD-FUNCTION STD-METHOD-GENERIC-FUNCTION STD-METHOD-SPECIALIZERS STD-METHOD-QUALIFIERS STD-ACCESSOR-METHOD-SLOT-DEFINITION STD-METHOD-FAST-FUNCTION STD-FUNCTION-KEYWORDS METHOD-GENERIC-FUNCTION METHOD-FUNCTION METHOD-SPECIALIZERS GENERIC-FUNCTION-NAME GENERIC-FUNCTION-LAMBDA-LIST GENERIC-FUNCTION-METHODS GENERIC-FUNCTION-METHOD-CLASS GENERIC-FUNCTION-METHOD-COMBINATION GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER METHOD-DOCUMENTATION CANONICALIZE-DEFGENERIC-OPTIONS CANONICALIZE-DEFGENERIC-OPTION ARGUMENT-PRECEDENCE-ORDER-INDICES FIND-GENERIC-FUNCTION LAMBDA-LISTS-CONGRUENT-P %DEFGENERIC COLLECT-EQL-SPECIALIZER-OBJECTS FINALIZE-STANDARD-GENERIC-FUNCTION MAKE-INSTANCE-STANDARD-GENERIC-FUNCTION CANONICALIZE-SPECIALIZERS CANONICALIZE-SPECIALIZER PARSE-DEFMETHOD REQUIRED-PORTION EXTRACT-LAMBDA-LIST EXTRACT-SPECIALIZER-NAMES GET-KEYWORD-FROM-ARG ANALYZE-LAMBDA-LIST CHECK-METHOD-LAMBDA-LIST CHECK-ARGUMENT-PRECEDENCE-ORDER ENSURE-METHOD MAKE-INSTANCE-STANDARD-METHOD ADD-DIRECT-METHOD REMOVE-DIRECT-METHOD STD-ADD-METHOD STD-REMOVE-METHOD %FIND-METHOD FAST-CALLABLE-P SLOW-READER-LOOKUP STD-COMPUTE-DISCRIMINATING-FUNCTION SORT-METHODS METHOD-APPLICABLE-P STD-COMPUTE-APPLICABLE-METHODS METHOD-APPLICABLE-USING-CLASSES-P CHECK-APPLICABLE-METHOD-KEYWORD-ARGS COMPUTE-APPLICABLE-KEYWORDS WRAP-EMFUN-FOR-KEYWORD-ARGS-CHECK SLOW-METHOD-LOOKUP SLOW-METHOD-LOOKUP-1 SUB-SPECIALIZER-P STD-METHOD-MORE-SPECIFIC-P PRIMARY-METHOD-P BEFORE-METHOD-P AFTER-METHOD-P AROUND-METHOD-P PROCESS-NEXT-METHOD-LIST STD-COMPUTE-EFFECTIVE-METHOD GENERATE-EMF-LAMBDA COMPUTE-PRIMARY-EMFUN WALK-FORM COMPUTE-METHOD-FUNCTION COMPUTE-METHOD-FAST-FUNCTION MAKE-METHOD-LAMBDA ALLOW-OTHER-KEYS MAKE-INSTANCE-STANDARD-ACCESSOR-METHOD ADD-READER-METHOD ADD-WRITER-METHOD CHECK-DUPLICATE-SLOTS CHECK-DUPLICATE-DEFAULT-INITARGS CANONICALIZE-DIRECT-SUPERCLASSES ENSURE-CLASS ENSURE-CLASS-USING-CLASS READER-METHOD-CLASS WRITER-METHOD-CLASS COMPUTE-APPLICABLE-METHODS-USING-CLASSES SLOT-VALUE-USING-CLASS SLOT-EXISTS-P-USING-CLASS SLOT-BOUNDP-USING-CLASS SLOT-MAKUNBOUND-USING-CLASS CALCULATE-ALLOWABLE-INITARGS CHECK-INITARGS MERGE-INITARGS-SETS EXTRACT-LAMBDA-LIST-KEYWORDS AUGMENT-INITARGS-WITH-DEFAULTS STD-SHARED-INITIALIZE COMPUTE-SLOTS COMPUTE-EFFECTIVE-SLOT-DEFINITION COMPUTE-DISCRIMINATING-FUNCTION METHOD-MORE-SPECIFIC-P COMPUTE-EFFECTIVE-METHOD SPECIALIZER-DIRECT-GENERIC-FUNCTIONS SPECIALIZER-DIRECT-METHODS ADD-DEPENDENT REMOVE-DEPENDENT UPDATE-DEPENDENT ENSURE-GENERIC-FUNCTION-USING-CLASS %METHOD-GENERIC-FUNCTION %METHOD-FUNCTION)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :MOP) (DOLIST (SYSTEM::FS (QUOTE ((("clos") DEFINE-CLASS->%CLASS-FORWARDER PUSH-ON-END DEFINE-PRIMORDIAL-CLASS WITH-METHOD-GROUPS ATOMIC-DEFGENERIC REDEFINE-CLASS-FORWARDER SLOT-DEFINITION-DISPATCH)))) (FUNCALL (FUNCTION AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; EXPORTS (IN-PACKAGE :XP) (EXPORT (QUOTE (*PRINT-SHARED*))) ;; FUNCTIONS (IN-PACKAGE :XP) (DOLIST (SYSTEM::FS (QUOTE ((("pprint-dispatch") MAKE-PPRINT-DISPATCH-TABLE PPRINT-DISPATCH-TABLE-P MAKE-ENTRY ENTRY-P SET-PPRINT-DISPATCH+ PRIORITY-> ADJUST-COUNTS GET-PRINTER FITS SPECIFIER-CATEGORY ALWAYS-TRUE SPECIFIER-FN CONVERT-BODY FUNCTION-CALL-P PPRINT-DISPATCH-PRINT) (("pprint") STRUCTURE-TYPE-P OUTPUT-WIDTH MAKE-XP-STRUCTURE XP-STRUCTURE-P PUSH-BLOCK-STACK POP-BLOCK-STACK PUSH-PREFIX-STACK POP-PREFIX-STACK ENQUEUE INITIALIZE-XP WRITE-CHAR+ WRITE-STRING+ WRITE-CHAR++ FORCE-SOME-OUTPUT WRITE-STRING++ WRITE-STRING+++ PPRINT-TAB+ PPRINT-NEWLINE+ START-BLOCK END-BLOCK PPRINT-INDENT+ ATTEMPT-TO-OUTPUT FLUSH OUTPUT-LINE SETUP-FOR-NEXT-LINE SET-INDENTATION-PREFIX SET-PREFIX SET-SUFFIX REVERSE-STRING-IN-PLACE MAYBE-INITIATE-XP-PRINTING XP-PRINT DO-XP-PRINTING WRITE+ NON-PRETTY-PRINT MAYBE-PRINT-FAST PRINT-FIXNUM PPRINT-POP-CHECK+ CHECK-BLOCK-ABBREVIATION PRETTY-ARRAY PRETTY-VECTOR PRETTY-NON-VECTOR ARRAY-READABLY-PRINTABLE-P FN-CALL ALTERNATIVE-FN-CALL BIND-LIST BLOCK-LIKE DEFUN-LIKE PRINT-FANCY-FN-CALL LET-PRINT COND-PRINT DMM-PRINT DEFSETF-PRINT DO-PRINT FLET-PRINT FUNCTION-PRINT MVB-PRINT MAYBELAB PROG-PRINT TAGBODY-PRINT SETQ-PRINT QUOTE-PRINT UP-PRINT TOKEN-TYPE PRETTY-LOOP OUTPUT-PRETTY-OBJECT)))) (FUNCALL (FUNCTION EXTENSIONS:AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :XP) (DOLIST (SYSTEM::FS (QUOTE ((("pprint") LP<-BP TP<-BP BP<-LP BP<-TP LP<-TP CHECK-SIZE SECTION-START PREFIX-PTR SUFFIX-PTR NON-BLANK-PREFIX-PTR INITIAL-PREFIX-PTR SECTION-START-LINE QTYPE QKIND QPOS QDEPTH QEND QOFFSET QARG QNEXT MAYBE-TOO-LARGE MISERING? PPRINT-LOGICAL-BLOCK+ PPRINT-POP+)))) (FUNCALL (FUNCTION EXTENSIONS:AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; FUNCTIONS ;; MACROS ;; EXPORTS (IN-PACKAGE :PROFILER) (EXPORT (QUOTE (WITH-PROFILING SHOW-HOT-COUNTS SHOW-CALL-COUNTS *GRANULARITY* *HIDDEN-FUNCTIONS*))) ;; FUNCTIONS (IN-PACKAGE :PROFILER) (DOLIST (SYSTEM::FS (QUOTE ((("profiler") MAKE-PROFILE-INFO PROFILE-INFO-P LIST-CALLED-OBJECTS OBJECT-NAME OBJECT-COMPILED-FUNCTION-P SHOW-CALL-COUNT SHOW-HOT-COUNT SHOW-CALL-COUNTS SHOW-HOT-COUNTS START-PROFILER)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :PROFILER) (DOLIST (SYSTEM::FS (QUOTE ((("profiler") WITH-PROFILING)))) (FUNCALL (FUNCTION AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; EXPORTS (IN-PACKAGE :JAVA) (EXPORT (QUOTE (JEQUAL JMETHOD-LET CHAIN ENSURE-JAVA-CLASS DEFINE-JAVA-CLASS JNEW-RUNTIME-CLASS JMEMBER-PROTECTED-P JMEMBER-PUBLIC-P JMEMBER-STATIC-P JINSTANCE-OF-P JMETHOD-NAME JMETHOD-PARAMS JCLASS-METHODS JFIELD-NAME JFIELD-TYPE JCLASS-FIELDS JCLASS-FIELD JCONSTRUCTOR-PARAMS JCLASS-CONSTRUCTORS JARRAY-FROM-LIST JNEW-ARRAY-FROM-LIST JNEW-ARRAY-FROM-ARRAY JARRAY-LENGTH JARRAY-COMPONENT-TYPE JCLASS-ARRAY-P JCLASS-SUPERCLASS-P JCLASS-INTERFACE-P JCLASS-INTERFACES JCLASS-SUPERCLASS JOBJECT-CLASS JPROPERTY-VALUE JMAKE-PROXY JMAKE-INVOCATION-HANDLER JINTERFACE-IMPLEMENTATION JREGISTER-HANDLER))) ;; FUNCTIONS (IN-PACKAGE :JAVA) (DOLIST (SYSTEM::FS (QUOTE ((("java") ADD-URL-TO-CLASSPATH ADD-URLS-TO-CLASSPATH ADD-TO-CLASSPATH JREGISTER-HANDLER JINTERFACE-IMPLEMENTATION JMAKE-INVOCATION-HANDLER JMAKE-PROXY CANONICALIZE-JPROXY-INTERFACES JEQUAL JOBJECT-CLASS JCLASS-SUPERCLASS JCLASS-INTERFACES JCLASS-INTERFACE-P JCLASS-SUPERCLASS-P JCLASS-ARRAY-P JARRAY-COMPONENT-TYPE JARRAY-LENGTH JNEW-ARRAY-FROM-ARRAY JNEW-ARRAY-FROM-LIST JARRAY-FROM-LIST LIST-FROM-JARRAY VECTOR-FROM-JARRAY LIST-FROM-JENUMERATION JCLASS-CONSTRUCTORS JCONSTRUCTOR-PARAMS JCLASS-FIELDS JCLASS-FIELD JFIELD-TYPE JFIELD-NAME JCLASS-METHODS JMETHOD-PARAMS JMETHOD-RETURN-TYPE JMETHOD-DECLARING-CLASS JMETHOD-NAME JINSTANCE-OF-P JMEMBER-STATIC-P JMEMBER-PUBLIC-P JMEMBER-PROTECTED-P JPROPERTY-VALUE JCLASS-ADDITIONAL-SUPERCLASSES ENSURE-JAVA-CLASS JINPUT-STREAM) (("runtime-class") JNEW-RUNTIME-CLASS %JNEW-RUNTIME-CLASS MAKE-ACCESSOR-NAME CANONICALIZE-JAVA-TYPE EMIT-UNBOX-AND-RETURN RUNTIME-CLASS-ADD-METHODS RUNTIME-CLASS-ADD-FIELDS)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :JAVA) (DOLIST (SYSTEM::FS (QUOTE ((("java") CHAIN JMETHOD-LET) (("runtime-class") DEFINE-JAVA-CLASS)))) (FUNCALL (FUNCTION AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; EXPORTS (IN-PACKAGE :JVM) (EXPORT (QUOTE (DERIVE-COMPILER-TYPE *CATCH-ERRORS* COMPILE-DEFUN))) ;; FUNCTIONS (IN-PACKAGE :JVM) (DOLIST (SYSTEM::FS (QUOTE ((("compiler-pass1") GENERATE-INLINE-EXPANSION PARSE-LAMBDA-LIST MATCH-LAMBDA-LIST MATCH-KEYWORD-AND-REST-ARGS EXPAND-FUNCTION-CALL-INLINE PROCESS-DECLARATIONS-FOR-VARS CHECK-NAME P1-BODY P1-DEFAULT P1-LET-VARS P1-LET*-VARS P1-LET/LET* P1-LOCALLY P1-M-V-B P1-BLOCK P1-CATCH P1-THREADS-SYNCHRONIZED-ON P1-UNWIND-PROTECT P1-RETURN-FROM P1-TAGBODY P1-GO SPLIT-DECLS REWRITE-AUX-VARS REWRITE-LAMBDA VALIDATE-FUNCTION-NAME CONSTRUCT-FLET/LABELS-FUNCTION P1-FLET P1-LABELS P1-FUNCALL P1-FUNCTION P1-LAMBDA P1-EVAL-WHEN P1-PROGV P1-QUOTE P1-SETQ P1-THE P1-TRULY-THE P1-THROW REWRITE-FUNCTION-CALL P1-FUNCTION-CALL %FUNCALL P1-VARIABLE-REFERENCE P1 INSTALL-P1-HANDLER INITIALIZE-P1-HANDLERS P1-COMPILAND) (("compiler-pass2") POOL-NAME POOL-NAME-AND-TYPE POOL-CLASS POOL-STRING POOL-FIELD POOL-METHOD POOL-INT POOL-FLOAT POOL-LONG POOL-DOUBLE ADD-EXCEPTION-HANDLER EMIT-PUSH-NIL EMIT-PUSH-NIL-SYMBOL EMIT-PUSH-T EMIT-PUSH-FALSE EMIT-PUSH-TRUE EMIT-PUSH-CONSTANT-INT EMIT-PUSH-CONSTANT-LONG EMIT-PUSH-CONSTANT-FLOAT EMIT-PUSH-CONSTANT-DOUBLE EMIT-DUP EMIT-SWAP EMIT-INVOKESTATIC PRETTY-JAVA-CLASS EMIT-INVOKEVIRTUAL EMIT-INVOKESPECIAL-INIT PRETTY-JAVA-TYPE EMIT-GETSTATIC EMIT-PUTSTATIC EMIT-GETFIELD EMIT-PUTFIELD EMIT-NEW EMIT-ANEWARRAY EMIT-CHECKCAST EMIT-INSTANCEOF TYPE-REPRESENTATION EMIT-UNBOX-BOOLEAN EMIT-UNBOX-CHARACTER CONVERT-REPRESENTATION COMMON-REPRESENTATION MAYBE-INITIALIZE-THREAD-VAR ENSURE-THREAD-VAR-INITIALIZED EMIT-PUSH-CURRENT-THREAD VARIABLE-LOCAL-P EMIT-LOAD-LOCAL-VARIABLE EMIT-PUSH-VARIABLE-NAME GENERATE-INSTANCEOF-TYPE-CHECK-FOR-VARIABLE FIND-TYPE-FOR-TYPE-CHECK GENERATE-TYPE-CHECK-FOR-VARIABLE MAYBE-GENERATE-TYPE-CHECK GENERATE-TYPE-CHECKS-FOR-VARIABLES GENERATE-ARG-COUNT-CHECK MAYBE-GENERATE-INTERRUPT-CHECK SINGLE-VALUED-P EMIT-CLEAR-VALUES MAYBE-EMIT-CLEAR-VALUES COMPILE-FORMS-AND-MAYBE-EMIT-CLEAR-VALUES LOAD-SAVED-OPERANDS SAVE-EXISTING-OPERANDS SAVE-OPERAND COMPILE-OPERAND EMIT-VARIABLE-OPERAND EMIT-REGISTER-OPERAND EMIT-THREAD-OPERAND EMIT-LOAD-EXTERNALIZED-OBJECT-OPERAND EMIT-UNBOX-FIXNUM EMIT-UNBOX-LONG EMIT-UNBOX-FLOAT EMIT-UNBOX-DOUBLE FIX-BOXING EMIT-MOVE-FROM-STACK EMIT-PUSH-REGISTER EMIT-INVOKE-METHOD CHECK-NUMBER-OF-ARGS CHECK-ARG-COUNT CHECK-MIN-ARGS EMIT-CONSTRUCTOR-LAMBDA-NAME EMIT-CONSTRUCTOR-LAMBDA-LIST EMIT-READ-FROM-STRING MAKE-CONSTRUCTOR MAKE-STATIC-INITIALIZER FINISH-CLASS DECLARE-FIELD SANITIZE SERIALIZE-INTEGER SERIALIZE-CHARACTER SERIALIZE-FLOAT SERIALIZE-DOUBLE SERIALIZE-STRING SERIALIZE-PACKAGE COMPILAND-EXTERNAL-CONSTANT-RESOURCE-NAME SERIALIZE-OBJECT SERIALIZE-SYMBOL EMIT-LOAD-EXTERNALIZED-OBJECT DECLARE-FUNCTION DECLARE-SETF-FUNCTION LOCAL-FUNCTION-CLASS-AND-FIELD DECLARE-LOCAL-FUNCTION DECLARE-OBJECT-AS-STRING DECLARE-LOAD-TIME-VALUE DECLARE-OBJECT COMPILE-CONSTANT INITIALIZE-UNARY-OPERATORS INSTALL-P2-HANDLER DEFINE-PREDICATE P2-PREDICATE COMPILE-FUNCTION-CALL-1 INITIALIZE-BINARY-OPERATORS COMPILE-BINARY-OPERATION COMPILE-FUNCTION-CALL-2 FIXNUM-OR-UNBOXED-VARIABLE-P EMIT-PUSH-INT EMIT-PUSH-LONG P2-EQ/NEQ EMIT-IFNE-FOR-EQL P2-EQL P2-MEMQ P2-MEMQL P2-GENSYM P2-GET P2-GETF P2-GETHASH P2-PUTHASH INLINE-OK PROCESS-ARGS EMIT-CALL-EXECUTE EMIT-CALL-THREAD-EXECUTE COMPILE-FUNCTION-CALL COMPILE-CALL P2-FUNCALL DUPLICATE-CLOSURE-ARRAY EMIT-LOAD-LOCAL-FUNCTION COMPILE-LOCAL-FUNCTION-CALL EMIT-NUMERIC-COMPARISON P2-NUMERIC-COMPARISON P2-TEST-HANDLER INITIALIZE-P2-TEST-HANDLERS NEGATE-JUMP-CONDITION EMIT-TEST-JUMP P2-TEST-PREDICATE P2-TEST-INSTANCEOF-PREDICATE P2-TEST-BIT-VECTOR-P P2-TEST-CHARACTERP P2-TEST-CONSTANTP P2-TEST-ENDP P2-TEST-EVENP P2-TEST-ODDP P2-TEST-FLOATP P2-TEST-INTEGERP P2-TEST-LISTP P2-TEST-MINUSP P2-TEST-PLUSP P2-TEST-ZEROP P2-TEST-NUMBERP P2-TEST-PACKAGEP P2-TEST-RATIONALP P2-TEST-REALP P2-TEST-SPECIAL-OPERATOR-P P2-TEST-SPECIAL-VARIABLE-P P2-TEST-SYMBOLP P2-TEST-CONSP P2-TEST-ATOM P2-TEST-FIXNUMP P2-TEST-STRINGP P2-TEST-VECTORP P2-TEST-SIMPLE-VECTOR-P COMPILE-TEST-FORM P2-TEST-NOT/NULL P2-TEST-CHAR= P2-TEST-EQ P2-TEST-OR P2-TEST-AND P2-TEST-NEQ P2-TEST-EQL P2-TEST-EQUALITY P2-TEST-SIMPLE-TYPEP P2-TEST-MEMQ P2-TEST-MEMQL P2-TEST-/= P2-TEST-NUMERIC-COMPARISON P2-IF COMPILE-MULTIPLE-VALUE-LIST COMPILE-MULTIPLE-VALUE-PROG1 COMPILE-MULTIPLE-VALUE-CALL UNUSED-VARIABLE CHECK-FOR-UNUSED-VARIABLES EMIT-NEW-CLOSURE-BINDING COMPILE-BINDING COMPILE-PROGN-BODY RESTORE-DYNAMIC-ENVIRONMENT SAVE-DYNAMIC-ENVIRONMENT P2-M-V-B-NODE PROPAGATE-VARS DERIVE-VARIABLE-REPRESENTATION ALLOCATE-VARIABLE-REGISTER EMIT-MOVE-TO-VARIABLE EMIT-PUSH-VARIABLE P2-LET-BINDINGS P2-LET*-BINDINGS P2-LET/LET*-NODE P2-LOCALLY-NODE P2-TAGBODY-NODE P2-GO P2-ATOM P2-INSTANCEOF-PREDICATE P2-BIT-VECTOR-P P2-CHARACTERP P2-CONSP P2-FIXNUMP P2-PACKAGEP P2-READTABLEP P2-SIMPLE-VECTOR-P P2-STRINGP P2-SYMBOLP P2-VECTORP P2-COERCE-TO-FUNCTION P2-BLOCK-NODE P2-RETURN-FROM EMIT-CAR/CDR P2-CAR P2-CDR P2-CONS COMPILE-PROGN P2-EVAL-WHEN P2-LOAD-TIME-VALUE P2-PROGV-NODE P2-QUOTE P2-RPLACD P2-SET-CAR/CDR COMPILE-DECLARE COMPILE-LOCAL-FUNCTION P2-FLET-NODE P2-LABELS-NODE P2-LAMBDA P2-FUNCTION P2-ASH P2-LOGAND P2-LOGIOR P2-LOGXOR P2-LOGNOT P2-%LDB P2-MOD P2-ZEROP P2-FIND-CLASS P2-VECTOR-PUSH-EXTEND P2-STD-SLOT-VALUE P2-SET-STD-SLOT-VALUE P2-STREAM-ELEMENT-TYPE P2-WRITE-8-BITS P2-READ-LINE DERIVE-TYPE-AREF DERIVE-TYPE-FIXNUMP DERIVE-TYPE-SETQ DERIVE-TYPE-LOGIOR/LOGXOR DERIVE-TYPE-LOGAND DERIVE-TYPE-LOGNOT DERIVE-TYPE-MOD DERIVE-TYPE-COERCE DERIVE-TYPE-COPY-SEQ DERIVE-TYPE-INTEGER-LENGTH DERIVE-TYPE-%LDB DERIVE-INTEGER-TYPE DERIVE-TYPE-NUMERIC-OP DERIVE-COMPILER-TYPES DERIVE-TYPE-MINUS DERIVE-TYPE-PLUS DERIVE-TYPE-TIMES DERIVE-TYPE-MAX DERIVE-TYPE-MIN DERIVE-TYPE-READ-CHAR DERIVE-TYPE-ASH DERIVE-TYPE DERIVE-COMPILER-TYPE P2-DELETE P2-LENGTH CONS-FOR-LIST/LIST* P2-LIST P2-LIST* COMPILE-NTH P2-TIMES P2-MIN/MAX P2-PLUS P2-MINUS P2-CHAR/SCHAR P2-SET-CHAR/SCHAR P2-SVREF P2-SVSET P2-TRUNCATE P2-ELT P2-AREF P2-ASET P2-STRUCTURE-REF P2-STRUCTURE-SET P2-NOT/NULL P2-NTHCDR P2-AND P2-OR P2-VALUES COMPILE-SPECIAL-REFERENCE COMPILE-VAR-REF P2-SET P2-SETQ P2-SXHASH P2-SYMBOL-NAME P2-SYMBOL-PACKAGE P2-SYMBOL-VALUE GENERATE-INSTANCEOF-TYPE-CHECK-FOR-VALUE GENERATE-TYPE-CHECK-FOR-VALUE P2-THE P2-TRULY-THE P2-CHAR-CODE P2-JAVA-JCLASS P2-JAVA-JCONSTRUCTOR P2-JAVA-JMETHOD P2-CHAR= P2-THREADS-SYNCHRONIZED-ON P2-CATCH-NODE P2-THROW P2-UNWIND-PROTECT-NODE COMPILE-FORM P2-COMPILAND-PROCESS-TYPE-DECLARATIONS P2-COMPILAND-UNBOX-VARIABLE ASSIGN-FIELD-NAME P2-COMPILAND COMPILE-TO-JVM-CLASS P2-WITH-INLINE-CODE COMPILE-1 MAKE-COMPILER-ERROR-FORM COMPILE-DEFUN NOTE-ERROR-CONTEXT HANDLE-WARNING HANDLE-COMPILER-ERROR %WITH-COMPILATION-UNIT %JVM-COMPILE JVM-COMPILE INITIALIZE-P2-HANDLERS) (("dump-class") READ-U1 READ-U2 READ-U4 LOOKUP-UTF8 READ-CONSTANT-POOL-ENTRY DUMP-CODE DUMP-CODE-ATTRIBUTE DUMP-EXCEPTIONS READ-ATTRIBUTE READ-INFO DUMP-CLASS) (("jvm-class-file") MAP-PRIMITIVE-TYPE PRETTY-CLASS PRETTY-TYPE %MAKE-JVM-CLASS-NAME JVM-CLASS-NAME-P MAKE-JVM-CLASS-NAME CLASS-ARRAY INTERNAL-FIELD-TYPE INTERNAL-FIELD-REF DESCRIPTOR DESCRIPTOR-STACK-EFFECT MAKE-POOL POOL-P MATCHING-INDEX-P FIND-POOL-ENTRY MAKE-CONSTANT CONSTANT-P PRINT-POOL-CONSTANT MAKE-CONSTANT-CLASS CONSTANT-CLASS-P %MAKE-CONSTANT-MEMBER-REF CONSTANT-MEMBER-REF-P MAKE-CONSTANT-FIELD-REF MAKE-CONSTANT-METHOD-REF MAKE-CONSTANT-INTERFACE-METHOD-REF MAKE-CONSTANT-STRING CONSTANT-STRING-P %MAKE-CONSTANT-FLOAT/INT CONSTANT-FLOAT/INT-P MAKE-CONSTANT-FLOAT MAKE-CONSTANT-INT %MAKE-CONSTANT-DOUBLE/LONG CONSTANT-DOUBLE/LONG-P MAKE-CONSTANT-DOUBLE MAKE-CONSTANT-LONG MAKE-CONSTANT-NAME/TYPE CONSTANT-NAME/TYPE-P PARSE-DESCRIPTOR MAKE-CONSTANT-UTF8 CONSTANT-UTF8-P POOL-ADD-CLASS POOL-ADD-FIELD-REF POOL-ADD-METHOD-REF POOL-ADD-INTERFACE-METHOD-REF POOL-ADD-STRING POOL-ADD-INT POOL-ADD-FLOAT POOL-ADD-LONG POOL-ADD-DOUBLE POOL-ADD-NAME/TYPE POOL-ADD-UTF8 MAKE-CLASS-FILE CLASS-FILE-P MAKE-CLASS-INTERFACE-FILE CLASS-ADD-FIELD CLASS-FIELD CLASS-ADD-METHOD CLASS-METHODS-BY-NAME CLASS-METHOD CLASS-REMOVE-METHOD CLASS-ADD-ATTRIBUTE CLASS-ADD-SUPERINTERFACE CLASS-ATTRIBUTE FINALIZE-INTERFACES FINALIZE-CLASS-FILE WRITE-U1 WRITE-U2 WRITE-U4 WRITE-S4 WRITE-ASCII WRITE-UTF8 WRITE-CLASS-FILE WRITE-CONSTANTS PRINT-ENTRY MAP-FLAGS %MAKE-FIELD FIELD-P MAKE-FIELD FIELD-ADD-ATTRIBUTE FIELD-ATTRIBUTE FINALIZE-FIELD WRITE-FIELD %MAKE-JVM-METHOD JVM-METHOD-P MAP-METHOD-NAME MAKE-JVM-METHOD METHOD-ADD-ATTRIBUTE METHOD-ADD-CODE METHOD-ENSURE-CODE METHOD-ATTRIBUTE FINALIZE-METHOD WRITE-METHOD MAKE-ATTRIBUTE ATTRIBUTE-P FINALIZE-ATTRIBUTES WRITE-ATTRIBUTES %MAKE-CODE-ATTRIBUTE CODE-ATTRIBUTE-P CODE-LABEL-OFFSET FINALIZE-CODE-ATTRIBUTE WRITE-CODE-ATTRIBUTE MAKE-CODE-ATTRIBUTE CODE-ADD-ATTRIBUTE CODE-ATTRIBUTE CODE-ADD-EXCEPTION-HANDLER MAKE-EXCEPTION EXCEPTION-P MAKE-CONSTANT-VALUE-ATTRIBUTE CONSTANT-VALUE-ATTRIBUTE-P MAKE-CHECKED-EXCEPTIONS-ATTRIBUTE CHECKED-EXCEPTIONS-ATTRIBUTE-P FINALIZE-CHECKED-EXCEPTIONS WRITE-CHECKED-EXCEPTIONS MAKE-DEPRECATED-ATTRIBUTE DEPRECATED-ATTRIBUTE-P SAVE-CODE-SPECIALS RESTORE-CODE-SPECIALS MAKE-SOURCE-FILE-ATTRIBUTE SOURCE-FILE-ATTRIBUTE-P FINALIZE-SOURCE-FILE WRITE-SOURCE-FILE MAKE-SYNTHETIC-ATTRIBUTE SYNTHETIC-ATTRIBUTE-P MAKE-LINE-NUMBERS-ATTRIBUTE LINE-NUMBERS-ATTRIBUTE-P MAKE-LINE-NUMBER LINE-NUMBER-P FINALIZE-LINE-NUMBERS WRITE-LINE-NUMBERS LINE-NUMBERS-ADD-LINE MAKE-LOCAL-VARIABLES-ATTRIBUTE LOCAL-VARIABLES-ATTRIBUTE-P MAKE-LOCAL-VARIABLE LOCAL-VARIABLE-P FINALIZE-LOCAL-VARIABLES WRITE-LOCAL-VARIABLES MAKE-ANNOTATIONS-ATTRIBUTE ANNOTATIONS-ATTRIBUTE-P MAKE-ANNOTATION ANNOTATION-P MAKE-ANNOTATION-ELEMENT ANNOTATION-ELEMENT-P MAKE-PRIMITIVE-OR-STRING-ANNOTATION-ELEMENT PRIMITIVE-OR-STRING-ANNOTATION-ELEMENT-P MAKE-ENUM-VALUE-ANNOTATION-ELEMENT ENUM-VALUE-ANNOTATION-ELEMENT-P MAKE-ANNOTATION-VALUE-ANNOTATION-ELEMENT ANNOTATION-VALUE-ANNOTATION-ELEMENT-P MAKE-ARRAY-ANNOTATION-ELEMENT ARRAY-ANNOTATION-ELEMENT-P MAKE-RUNTIME-VISIBLE-ANNOTATIONS-ATTRIBUTE RUNTIME-VISIBLE-ANNOTATIONS-ATTRIBUTE-P FINALIZE-ANNOTATIONS FINALIZE-ANNOTATION FINALIZE-ANNOTATION-ELEMENT WRITE-ANNOTATIONS WRITE-ANNOTATION WRITE-ANNOTATION-ELEMENT) (("jvm-instructions") U2 S1 S2 MAKE-JVM-OPCODE JVM-OPCODE-P %DEFINE-OPCODE OPCODE-NAME OPCODE-NUMBER OPCODE-SIZE OPCODE-STACK-EFFECT OPCODE-ARGS-SPEC %MAKE-INSTRUCTION INSTRUCTION-P MAKE-INSTRUCTION PRINT-INSTRUCTION INSTRUCTION-LABEL INST %%EMIT %EMIT LABEL ALOAD ASTORE BRANCH-P UNCONDITIONAL-CONTROL-TRANSFER-P LABEL-P FORMAT-INSTRUCTION-ARGS PRINT-CODE PRINT-CODE2 EXPAND-VIRTUAL-INSTRUCTIONS UNSUPPORTED-OPCODE INITIALIZE-RESOLVERS LOAD/STORE-RESOLVER RESOLVE-INSTRUCTION RESOLVE-INSTRUCTIONS ANALYZE-STACK-PATH ANALYZE-STACK ANALYZE-LOCALS DELETE-UNUSED-LABELS DELETE-UNREACHABLE-CODE LABEL-TARGET-INSTRUCTIONS OPTIMIZE-JUMPS OPTIMIZE-INSTRUCTION-SEQUENCES OPTIMIZE-CODE CODE-BYTES FINALIZE-CODE) (("jvm") INVOKE-CALLBACKS %MAKE-ABCL-CLASS-FILE ABCL-CLASS-FILE-P CLASS-NAME-FROM-FILESPEC MAKE-UNIQUE-CLASS-NAME MAKE-ABCL-CLASS-FILE MAKE-COMPILAND COMPILAND-P COMPILAND-SINGLE-VALUED-P DUMP-1-VARIABLE DUMP-VARIABLES MAKE-VARIABLE VARIABLE-P MAKE-VAR-REF VAR-REF-P UNBOXED-FIXNUM-VARIABLE FIND-VARIABLE FIND-VISIBLE-VARIABLE REPRESENTATION-SIZE ALLOCATE-REGISTER MAKE-LOCAL-FUNCTION LOCAL-FUNCTION-P FIND-LOCAL-FUNCTION MAKE-NODE NODE-P ADD-NODE-CHILD MAKE-CONTROL-TRANSFERRING-NODE CONTROL-TRANSFERRING-NODE-P %MAKE-TAGBODY-NODE TAGBODY-NODE-P MAKE-TAGBODY-NODE %MAKE-CATCH-NODE CATCH-NODE-P MAKE-CATCH-NODE %MAKE-BLOCK-NODE BLOCK-NODE-P MAKE-BLOCK-NODE %MAKE-JUMP-NODE JUMP-NODE-P MAKE-JUMP-NODE MAKE-BINDING-NODE BINDING-NODE-P %MAKE-LET/LET*-NODE LET/LET*-NODE-P MAKE-LET/LET*-NODE %MAKE-FLET-NODE FLET-NODE-P MAKE-FLET-NODE %MAKE-LABELS-NODE LABELS-NODE-P MAKE-LABELS-NODE %MAKE-M-V-B-NODE M-V-B-NODE-P MAKE-M-V-B-NODE %MAKE-PROGV-NODE PROGV-NODE-P MAKE-PROGV-NODE %MAKE-LOCALLY-NODE LOCALLY-NODE-P MAKE-LOCALLY-NODE %MAKE-PROTECTED-NODE PROTECTED-NODE-P MAKE-PROTECTED-NODE %MAKE-UNWIND-PROTECT-NODE UNWIND-PROTECT-NODE-P MAKE-UNWIND-PROTECT-NODE %MAKE-SYNCHRONIZED-NODE SYNCHRONIZED-NODE-P MAKE-SYNCHRONIZED-NODE FIND-BLOCK %FIND-ENCLOSED-BLOCKS FIND-ENCLOSED-BLOCKS SOME-NESTED-BLOCK NODE-CONSTANT-P BLOCK-REQUIRES-NON-LOCAL-EXIT-P NODE-OPSTACK-UNSAFE-P BLOCK-CREATES-RUNTIME-BINDINGS-P ENCLOSED-BY-RUNTIME-BINDINGS-CREATING-BLOCK-P ENCLOSED-BY-PROTECTED-BLOCK-P ENCLOSED-BY-ENVIRONMENT-SETTING-BLOCK-P ENVIRONMENT-REGISTER-TO-RESTORE MAKE-TAG TAG-P FIND-TAG PROCESS-IGNORE/IGNORABLE FINALIZE-GENERIC-FUNCTIONS) (("runtime-class") EMIT-INVOKESPECIAL PARSE-ANNOTATION PARSE-ANNOTATION-ELEMENT)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :JVM) (DOLIST (SYSTEM::FS (QUOTE ((("compiler-pass1") PUSH-ARGUMENT-BINDING P1-LET/LET*-VARS) (("compiler-pass2") WITH-OPERAND-ACCUMULATION ACCUMULATE-OPERAND DECLARE-WITH-HASHTABLE DEFINE-INLINED-FUNCTION P2-TEST-INTEGER-PREDICATE DEFINE-DERIVE-TYPE-HANDLER DEFINE-INT-BOUNDS-DERIVATION WITH-OPEN-CLASS-FILE WITH-FILE-COMPILATION) (("dump-class") OUT) (("jvm-class-file") DEFINE-CLASS-NAME WITH-CODE-TO-METHOD) (("jvm-instructions") DEFINE-OPCODE EMIT DEFINE-RESOLVER) (("jvm") DFORMAT WITH-SAVED-COMPILER-POLICY WITH-CLASS-FILE)))) (FUNCALL (FUNCTION AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; EXPORTS (IN-PACKAGE :EXTENSIONS) (EXPORT (QUOTE (COLLECT COMPILE-SYSTEM SHOW-RESTARTS *DEBUG-LEVEL* *DEBUG-CONDITION* FEATUREP MAKE-DIALOG-PROMPT-STREAM INIT-GUI *GUI-BACKEND* URL-PATHNAME-FRAGMENT URL-PATHNAME-QUERY URL-PATHNAME-AUTHORITY URL-PATHNAME-SCHEME RUN-SHELL-COMMAND SOCKET-PEER-ADDRESS SOCKET-LOCAL-ADDRESS SOCKET-LOCAL-PORT SOCKET-PEER-PORT GET-SOCKET-STREAM SOCKET-CLOSE SOCKET-ACCEPT SERVER-SOCKET-CLOSE MAKE-SERVER-SOCKET MAKE-SOCKET))) ;; FUNCTIONS (IN-PACKAGE :EXTENSIONS) (DOLIST (SYSTEM::FS (QUOTE ((("collect") COLLECT-NORMAL-EXPANDER COLLECT-LIST-EXPANDER) (("compile-system") COMPILE-SYSTEM) (("debug") SHOW-RESTARTS) (("featurep") FEATUREP) (("gui") INIT-GUI MAKE-DIALOG-PROMPT-STREAM %MAKE-DIALOG-PROMPT-STREAM) (("pathnames") URL-PATHNAME-SCHEME SET-URL-PATHNAME-SCHEME URL-PATHNAME-AUTHORITY SET-URL-PATHNAME-AUTHORITY URL-PATHNAME-QUERY SET-URL-PATHNAME-QUERY URL-PATHNAME-FRAGMENT SET-URL-PATHNAME-FRAGMENT) (("pprint") CHARPOS) (("run-shell-command") RUN-SHELL-COMMAND) (("socket") GET-SOCKET-STREAM MAKE-SOCKET MAKE-SERVER-SOCKET SOCKET-ACCEPT SOCKET-CLOSE SERVER-SOCKET-CLOSE %SOCKET-ADDRESS %SOCKET-PORT SOCKET-LOCAL-ADDRESS SOCKET-PEER-ADDRESS SOCKET-LOCAL-PORT SOCKET-PEER-PORT)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :EXTENSIONS) (DOLIST (SYSTEM::FS (QUOTE ((("collect") COLLECT)))) (FUNCALL (FUNCTION AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; EXPORTS (IN-PACKAGE :THREADS) (EXPORT (QUOTE (RELEASE-MUTEX GET-MUTEX MAKE-MUTEX MAILBOX-PEEK MAILBOX-READ MAILBOX-EMPTY-P MAILBOX-SEND MAKE-MAILBOX WITH-MUTEX WITH-THREAD-LOCK MAKE-THREAD-LOCK))) ;; FUNCTIONS (IN-PACKAGE :THREADS) (DOLIST (SYSTEM::FS (QUOTE ((("threads") THREAD-FUNCTION-WRAPPER MAKE-MAILBOX MAILBOX-P MAILBOX-SEND MAILBOX-EMPTY-P MAILBOX-READ MAILBOX-PEEK MAKE-MUTEX MUTEX-P GET-MUTEX RELEASE-MUTEX MAKE-THREAD-LOCK)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :THREADS) (DOLIST (SYSTEM::FS (QUOTE ((("threads") WITH-MUTEX WITH-THREAD-LOCK)))) (FUNCALL (FUNCTION AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; FUNCTIONS (IN-PACKAGE :TOP-LEVEL) (DOLIST (SYSTEM::FS (QUOTE ((("top-level") PROMPT-PACKAGE-NAME REPL-PROMPT-FUN PEEK-CHAR-NON-WHITESPACE APROPOS-COMMAND CONTINUE-COMMAND DESCRIBE-COMMAND ERROR-COMMAND PRINT-FRAME BACKTRACE-COMMAND FRAME-COMMAND INSPECT-COMMAND ISTEP-COMMAND MACROEXPAND-COMMAND PACKAGE-COMMAND RESET-COMMAND EXIT-COMMAND CD-COMMAND LS-COMMAND TOKENIZE LD-COMMAND CF-COMMAND CLOAD-COMMAND RQ-COMMAND PWD-COMMAND TRACE-COMMAND UNTRACE-COMMAND PAD %HELP-COMMAND HELP-COMMAND ENTRY-NAME ENTRY-ABBREVIATION ENTRY-COMMAND ENTRY-HELP FIND-COMMAND PROCESS-CMD READ-CMD REPL-READ-FORM-FUN REPL TOP-LEVEL-LOOP)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS ;; EXPORTS (IN-PACKAGE :SYSTEM) (EXPORT (QUOTE (CONCATENATE-FASLS AVER *COMPILER-DIAGNOSTIC* COMPILE-FILE-IF-NEEDED GROVEL-JAVA-DEFINITIONS-IN-FILE COMPILER-UNSUPPORTED INTERNAL-COMPILER-ERROR COMPILER-ERROR COMPILER-WARN COMPILER-STYLE-WARN *COMPILER-ERROR-CONTEXT* COMPILER-MACROEXPAND DEFKNOWN FUNCTION-RESULT-TYPE COMPILER-SUBTYPEP MAKE-COMPILER-TYPE JAVA-LONG-TYPE-P INTEGER-CONSTANT-VALUE FIXNUM-CONSTANT-VALUE FIXNUM-TYPE-P +INTEGER-TYPE+ +FIXNUM-TYPE+ MAKE-INTEGER-TYPE %MAKE-INTEGER-TYPE INTEGER-TYPE-P INTEGER-TYPE-HIGH INTEGER-TYPE-LOW +FALSE-TYPE+ +TRUE-TYPE+ COMPILER-DEFSTRUCT DESCRIBE-COMPILER-POLICY PARSE-BODY DUMP-UNINTERNED-SYMBOL-INDEX DUMP-FORM LOOKUP-KNOWN-SYMBOL STANDARD-INSTANCE-ACCESS SLOT-DEFINITION FORWARD-REFERENCED-CLASS LOGICAL-HOST-P *INLINE-DECLARATIONS* FTYPE-RESULT-TYPE PROCLAIMED-FTYPE PROCLAIMED-TYPE CHECK-DECLARATION-TYPE PROCESS-KILL PROCESS-EXIT-CODE PROCESS-WAIT PROCESS-ALIVE-P PROCESS-ERROR PROCESS-OUTPUT PROCESS-INPUT PROCESS-P PROCESS RUN-PROGRAM SIMPLE-SEARCH EXPAND-SOURCE-TRANSFORM DEFINE-SOURCE-TRANSFORM SOURCE-TRANSFORM UNTRACED-FUNCTION))) ;; FUNCTIONS (IN-PACKAGE :SYSTEM) (DOLIST (FS (QUOTE ((("fasl-concat") CONCATENATE-FALSL) (("abcl-contrib") FIND-SYSTEM-JAR FIND-CONTRIB) (("assert") ASSERT-ERROR ASSERT-PROMPT) (("aver") %FAILED-AVER) (("backquote") BACKQUOTE-MACRO COMMA-MACRO EXPANDABLE-BACKQ-EXPRESSION-P BACKQUOTIFY COMMA BACKQUOTIFY-1 BACKQ-LIST BACKQ-LIST* BACKQ-APPEND BACKQ-NCONC BACKQ-CONS BACKQ-VECTOR %READER-ERROR) (("bit-array-ops") BIT-ARRAY-SAME-DIMENSIONS-P REQUIRE-SAME-DIMENSIONS PICK-RESULT-ARRAY) (("case") LIST-OF-LENGTH-AT-LEAST-P CASE-BODY-ERROR CASE-BODY-AUX CASE-BODY) (("check-type") CHECK-TYPE-ERROR) (("clos") COERCE-TO-CONDITION) (("coerce") COERCE-LIST-TO-VECTOR COPY-STRING COERCE-ERROR COERCE-OBJECT-TO-AND-TYPE) (("compile-file-pathname") CFP-OUTPUT-FILE-DEFAULT) (("compile-file") BASE-CLASSNAME FASL-LOADER-CLASSNAME COMPUTE-CLASSFILE-NAME SANITIZE-CLASS-NAME NEXT-CLASSFILE-NAME DUMMY VERIFY-LOAD NOTE-TOPLEVEL-FORM OUTPUT-FORM FINALIZE-FASL-OUTPUT SIMPLE-TOPLEVEL-FORM-P CONVERT-TOPLEVEL-FORM PROCESS-PROGN PRECOMPILE-TOPLEVEL-FORM PROCESS-TOPLEVEL-MACROLET PROCESS-TOPLEVEL-DEFCONSTANT PROCESS-TOPLEVEL-QUOTE PROCESS-TOPLEVEL-IMPORT PROCESS-TOPLEVEL-EXPORT PROCESS-TOPLEVEL-MOP.ENSURE-METHOD PROCESS-TOPLEVEL-DEFVAR/DEFPARAMETER PROCESS-TOPLEVEL-DEFPACKAGE/IN-PACKAGE PROCESS-TOPLEVEL-DECLARE PROCESS-TOPLEVEL-PROGN PROCESS-TOPLEVEL-DEFTYPE PROCESS-TOPLEVEL-EVAL-WHEN PROCESS-TOPLEVEL-DEFMETHOD/DEFGENERIC PROCESS-TOPLEVEL-LOCALLY PROCESS-TOPLEVEL-DEFMACRO PROCESS-TOPLEVEL-DEFUN INSTALL-TOPLEVEL-HANDLER PROCESS-TOPLEVEL-FORM POPULATE-ZIP-FASL WRITE-FASL-PROLOGUE COMPILE-FROM-STREAM COMPILE-FILE-IF-NEEDED) (("compile-system") CHECK-LISP-HOME GROVEL-JAVA-DEFINITIONS-IN-FILE GROVEL-JAVA-DEFINITIONS PACKAGES-FROM-COMBOS REMOVE-MULTI-COMBO-SYMBOLS SET-EQUAL COMBOS-TO-SYMBOL-FILESETS COMBOS-TO-FILESET-SYMBOLS WRITE-AUTOLOADER WRITE-PACKAGE-FILESETS LOAD-COMBOS GENERATE-AUTOLOADS %COMPILE-SYSTEM CREATE-SYSTEM-LOGICAL-TRANSLATIONS) (("compiler-error") COMPILER-STYLE-WARN COMPILER-WARN COMPILER-ERROR INTERNAL-COMPILER-ERROR COMPILER-UNSUPPORTED) (("compiler-macro") COMPILER-MACROEXPAND-1 COMPILER-MACROEXPAND) (("compiler-pass2") AUTOCOMPILE) (("compiler-types") MAKE-CONSTANT-TYPE CONSTANT-TYPE-P %MAKE-INTEGER-TYPE INTEGER-TYPE-P MAKE-INTEGER-TYPE FIXNUM-TYPE-P FIXNUM-CONSTANT-VALUE INTEGER-CONSTANT-VALUE JAVA-LONG-TYPE-P MAKE-UNION-TYPE MAKE-COMPILER-TYPE INTEGER-TYPE-SUBTYPEP COMPILER-SUBTYPEP FUNCTION-RESULT-TYPE SET-FUNCTION-RESULT-TYPE %DEFKNOWN) (("concatenate") CONCATENATE-TO-STRING) (("debug") INTERNAL-DEBUG DEBUG-LOOP INVOKE-DEBUGGER-REPORT-CONDITION RUN-HOOK BACKTRACE-AS-LIST) (("define-symbol-macro") %DEFINE-SYMBOL-MACRO) (("defpackage") DESIGNATED-PACKAGE-NAME STRINGIFY-NAMES CHECK-DISJOINT) (("defsetf") %DEFSETF) (("defstruct") MAKE-DEFSTRUCT-DESCRIPTION MAKE-DEFSTRUCT-SLOT-DESCRIPTION KEYWORDIFY DEFINE-KEYWORD-CONSTRUCTOR FIND-DSD GET-SLOT DEFINE-BOA-CONSTRUCTOR DEFAULT-CONSTRUCTOR-NAME DEFINE-CONSTRUCTORS NAME-INDEX DEFINE-PREDICATE MAKE-LIST-READER MAKE-VECTOR-READER MAKE-STRUCTURE-READER DEFINE-READER MAKE-LIST-WRITER MAKE-VECTOR-WRITER MAKE-STRUCTURE-WRITER DEFINE-WRITER DEFINE-ACCESS-FUNCTIONS DEFINE-COPIER DEFINE-PRINT-FUNCTION PARSE-1-OPTION PARSE-NAME-AND-OPTIONS COMPILER-DEFSTRUCT DEFSTRUCT-DEFAULT-CONSTRUCTOR) (("deftype") EXPAND-DEFTYPE) (("delete-duplicates") LIST-DELETE-DUPLICATES* VECTOR-DELETE-DUPLICATES*) (("describe-compiler-policy") DESCRIBE-COMPILER-POLICY) (("describe") DESCRIBE-ARGLIST %DESCRIBE-OBJECT) (("destructuring-bind") PARSE-BODY ARG-COUNT-ERROR PARSE-DEFMACRO DEFMACRO-ERROR VERIFY-KEYWORDS LOOKUP-KEYWORD KEYWORD-SUPPLIED-P PARSE-DEFMACRO-LAMBDA-LIST PUSH-SUB-LIST-BINDING PUSH-LET-BINDING PUSH-OPTIONAL-BINDING MAKE-MACRO-EXPANDER) (("directory") PATHNAME-AS-FILE WILD-INFERIORS-P LIST-DIRECTORIES-WITH-WILDCARDS) (("do") DO-DO-BODY) (("dump-form") GET-INSTANCE-FORM DF-REGISTER-CIRCULARITY DF-CHECK-CONS DF-CHECK-VECTOR DF-CHECK-INSTANCE DF-CHECK-OBJECT DF-HANDLE-CIRCULARITY DUMP-CONS DUMP-VECTOR DUMP-INSTANCE DUMP-UNINTERNED-SYMBOL-INDEX DUMP-OBJECT DUMP-FORM) (("ed") DEFAULT-ED-FUNCTION) (("enough-namestring") EQUAL-COMPONENTS-P) (("fill") LIST-FILL VECTOR-FILL) (("find") LIST-POSITION* VECTOR-POSITION* LIST-FIND* VECTOR-FIND*) (("format") SYMBOLICATE PROPER-LIST-OF-LENGTH-P FLONUM-TO-STRING ROUND-UP SCALE-EXPONENT FLOAT-DENORMALIZED-P) (("inline") INLINE-EXPANSION SET-INLINE-EXPANSION) (("inspect") LEADER SAFE-LENGTH DISPLAY-OBJECT DISPLAY-CURRENT ISTEP) (("late-setf") MAKE-GENSYM-LIST) (("lcm") TWO-ARG-LCM) (("ldb") %LDB) (("load") LOAD-RETURNING-LAST-RESULT) (("make-sequence") SIZE-MISMATCH-ERROR) (("map1") MAP1) (("nsubstitute") NLIST-SUBSTITUTE* NVECTOR-SUBSTITUTE* NLIST-SUBSTITUTE-IF* NVECTOR-SUBSTITUTE-IF* NLIST-SUBSTITUTE-IF-NOT* NVECTOR-SUBSTITUTE-IF-NOT*) (("open") UPGRADED-ELEMENT-TYPE-BITS UPGRADED-ELEMENT-TYPE) (("parse-integer") PARSE-INTEGER-ERROR) (("parse-lambda-list") PARSE-LAMBDA-LIST-LIKE-THING PARSE-LAMBDA-LIST) (("pathnames") COMPONENT-MATCH-WILD-P COMPONENT-MATCH-P DIRECTORY-MATCH-COMPONENTS DIRECTORY-MATCH-P WILD-P CASIFY TRANSLATE-COMPONENT TRANSLATE-JAR-DEVICE TRANSLATE-DIRECTORY-COMPONENTS-AUX TRANSLATE-DIRECTORY-COMPONENTS TRANSLATE-DIRECTORY LOGICAL-HOST-P CANONICALIZE-LOGICAL-PATHNAME-TRANSLATIONS %SET-LOGICAL-PATHNAME-TRANSLATIONS) (("print-unreadable-object") %PRINT-UNREADABLE-OBJECT) (("print") COMPOUND-OBJECT-P OUTPUT-INTEGER OUTPUT-LIST OUTPUT-TERSE-ARRAY ARRAY-READABLY-PRINTABLE-P OUTPUT-VECTOR OUTPUT-UGLY-OBJECT CHECK-FOR-CIRCULARITY HANDLE-CIRCULARITY PRINT-LABEL PRINT-REFERENCE UNIQUELY-IDENTIFIED-BY-PRINT-P %PRINT-OBJECT %CHECK-OBJECT OUTPUT-OBJECT) (("proclaim") DECLARATION-ERROR CHECK-DECLARATION-TYPE PROCLAIM-TYPE PROCLAIMED-TYPE PROCLAIM-FTYPE-1 PROCLAIM-FTYPE PROCLAIMED-FTYPE FTYPE-RESULT-TYPE) (("query") QUERY-READLINE) (("read-circle") CIRCLE-SUBST SHARP-EQUAL SHARP-SHARP) (("read-conditional") READ-FEATURE READ-CONDITIONAL) (("remove-duplicates") LIST-REMOVE-DUPLICATES VECTOR-REMOVE-DUPLICATES) (("replace") LIST-REPLACE-FROM-LIST* LIST-REPLACE-FROM-VECTOR* VECTOR-REPLACE-FROM-LIST* VECTOR-REPLACE-FROM-VECTOR*) (("run-program") RUN-PROGRAM %MAKE-PROCESS PROCESS-P MAKE-PROCESS PROCESS-ALIVE-P PROCESS-WAIT PROCESS-EXIT-CODE PROCESS-KILL %MAKE-PROCESS-BUILDER %PROCESS-BUILDER-ENVIRONMENT %PROCESS-BUILDER-ENV-PUT %PROCESS-BUILDER-ENV-CLEAR %PROCESS-BUILDER-START %MAKE-PROCESS-INPUT-STREAM %MAKE-PROCESS-OUTPUT-STREAM %MAKE-PROCESS-ERROR-STREAM %PROCESS-ALIVE-P %PROCESS-WAIT %PROCESS-EXIT-CODE %PROCESS-KILL) (("search") SIMPLE-SEARCH) (("sequences") MAKE-SEQUENCE-OF-TYPE) (("setf") GET-SETF-METHOD-INVERSE EXPAND-OR-GET-SETF-INVERSE %SET-SUBSEQ %DEFINE-SETF-MACRO %SET-CAAR %SET-CADR %SET-CDAR %SET-CDDR %SET-CAAAR %SET-CADAR %SET-CDAAR %SET-CDDAR %SET-CAADR %SET-CADDR %SET-CDADR %SET-CDDDR %SET-CAAAAR %SET-CADAAR %SET-CDAAAR %SET-CDDAAR %SET-CAADAR %SET-CADDAR %SET-CDADAR %SET-CDDDAR %SET-CAAADR %SET-CADADR %SET-CDAADR %SET-CDDADR %SET-CAADDR %SET-CADDDR %SET-CDADDR %SET-CDDDDR %SET-FIFTH %SET-SIXTH %SET-SEVENTH %SET-EIGHTH %SET-NINTH %SET-TENTH) (("sort") MERGE-SORT-VECTORS LAST-CONS-OF MERGE-LISTS MERGE-LISTS-NO-KEY SORT-LIST QUICKSORT QUICK-SORT) (("source-transform") SOURCE-TRANSFORM SET-SOURCE-TRANSFORM EXPAND-SOURCE-TRANSFORM-1 EXPAND-SOURCE-TRANSFORM) (("subst") %SUBST %SUBST-IF %SUBST-IF-NOT) (("subtypep") INITIALIZE-KNOWN-TYPES KNOWN-TYPE-P SUB-INTERVAL-P DIMENSION-SUBTYPEP SIMPLE-SUBTYPEP MAKE-CTYPE CTYPE-SUPER CTYPE-TYPE CTYPE CSUBTYPEP-ARRAY CSUBTYPEP-FUNCTION CSUBTYPEP-COMPLEX CSUBTYPEP %SUBTYPEP) (("time") PICK-OBVIOUS-YEAR LEAP-YEARS-BEFORE) (("trace") MAKE-TRACE-INFO TRACE-INFO-P LIST-TRACED-FUNCTIONS EXPAND-TRACE TRACE-1 TRACED-FUNCTION UNTRACED-FUNCTION TRACE-REDEFINED-UPDATE INDENT UNTRACE-ALL UNTRACE-1) (("tree-equal") TREE-EQUAL-TEST-NOT TREE-EQUAL-TEST) (("typep") SIMPLE-ARRAY-P IN-INTERVAL-P MATCH-DIMENSIONS %TYPEP) (("with-hash-table-iterator") HASH-TABLE-ITERATOR-FUNCTION) (("with-package-iterator") PACKAGE-ITERATOR-FUNCTION) (("with-standard-io-syntax") %WITH-STANDARD-IO-SYNTAX)))) (FUNCALL (FUNCTION AUTOLOAD) (CDR FS) (CAR (CAR FS)))) ;; MACROS (IN-PACKAGE :SYSTEM) (DOLIST (FS (QUOTE ((("assoc") ASSOC-GUTS) (("aver") AVER) (("chars") EQUAL-CHAR-CODE) (("compile-file") REPORT-ERROR DIAG) (("compiler-types") DEFKNOWN) (("copy-seq") VECTOR-COPY-SEQ LIST-COPY-SEQ) (("define-modify-macro") INCF-COMPLEX DECF-COMPLEX) (("defstruct") DD-NAME DD-CONC-NAME DD-DEFAULT-CONSTRUCTOR DD-CONSTRUCTORS DD-COPIER DD-INCLUDE DD-TYPE DD-NAMED DD-INITIAL-OFFSET DD-PREDICATE DD-PRINT-FUNCTION DD-PRINT-OBJECT DD-DIRECT-SLOTS DD-SLOTS DD-INHERITED-ACCESSORS DSD-NAME DSD-INDEX DSD-READER DSD-INITFORM DSD-TYPE DSD-READ-ONLY) (("delete") MUMBLE-DELETE MUMBLE-DELETE-FROM-END NORMAL-MUMBLE-DELETE NORMAL-MUMBLE-DELETE-FROM-END LIST-DELETE LIST-DELETE-FROM-END NORMAL-LIST-DELETE NORMAL-LIST-DELETE-FROM-END IF-MUMBLE-DELETE IF-MUMBLE-DELETE-FROM-END IF-LIST-DELETE IF-LIST-DELETE-FROM-END IF-NOT-MUMBLE-DELETE IF-NOT-MUMBLE-DELETE-FROM-END IF-NOT-LIST-DELETE IF-NOT-LIST-DELETE-FROM-END) (("find") VECTOR-LOCATER-MACRO LOCATER-TEST-NOT VECTOR-LOCATER LOCATER-IF-TEST VECTOR-LOCATER-IF-MACRO VECTOR-LOCATER-IF VECTOR-LOCATER-IF-NOT LIST-LOCATER-MACRO LIST-LOCATER LIST-LOCATER-IF-MACRO LIST-LOCATER-IF LIST-LOCATER-IF-NOT VECTOR-POSITION LIST-POSITION VECTOR-POSITION-IF LIST-POSITION-IF VECTOR-POSITION-IF-NOT LIST-POSITION-IF-NOT VECTOR-FIND LIST-FIND VECTOR-FIND-IF LIST-FIND-IF VECTOR-FIND-IF-NOT LIST-FIND-IF-NOT) (("format") NAMED-LET ONCE-ONLY) (("list") APPLY-KEY) (("print") PUNT-PRINT-IF-TOO-LONG) (("reduce") LIST-REDUCE LIST-REDUCE-FROM-END) (("remove") MUMBLE-REMOVE-MACRO MUMBLE-REMOVE MUMBLE-REMOVE-FROM-END NORMAL-MUMBLE-REMOVE NORMAL-MUMBLE-REMOVE-FROM-END IF-MUMBLE-REMOVE IF-MUMBLE-REMOVE-FROM-END IF-NOT-MUMBLE-REMOVE IF-NOT-MUMBLE-REMOVE-FROM-END LIST-REMOVE-MACRO LIST-REMOVE LIST-REMOVE-FROM-END NORMAL-LIST-REMOVE NORMAL-LIST-REMOVE-FROM-END IF-LIST-REMOVE IF-LIST-REMOVE-FROM-END IF-NOT-LIST-REMOVE IF-NOT-LIST-REMOVE-FROM-END) (("sequences") TYPE-SPECIFIER-ATOM MAKE-SEQUENCE-LIKE) (("sets") WITH-SET-KEYS STEVE-SPLICE) (("sort") MERGE-VECTORS-BODY MERGE-SORT-BODY QUICKSORT-BODY) (("source-transform") DEFINE-SOURCE-TRANSFORM) (("subst") SATISFIES-THE-TEST)))) (FUNCALL (FUNCTION AUTOLOAD-MACRO) (CDR FS) (CAR (CAR FS)))) ;; EXPORTS (IN-PACKAGE :CL) (EXPORT (QUOTE (NBUTLAST BUTLAST IGNORE-ERRORS MAP-INTO MISMATCH METHOD-QUALIFIERS COMPUTE-APPLICABLE-METHODS STANDARD-METHOD SUBSTITUTE-IF-NOT SUBSTITUTE-IF SUBSTITUTE))) ;; FUNCTIONS (IN-PACKAGE :CL) (DOLIST (SYSTEM::FS (QUOTE ((("adjoin") ADJOIN) (("apropos") APROPOS-LIST APROPOS) (("arrays") MAKE-ARRAY ADJUST-ARRAY ARRAY-ROW-MAJOR-INDEX BIT SBIT) (("assoc") ASSOC ASSOC-IF ASSOC-IF-NOT RASSOC RASSOC-IF RASSOC-IF-NOT ACONS PAIRLIS COPY-ALIST) (("bit-array-ops") BIT-AND BIT-IOR BIT-XOR BIT-EQV BIT-NAND BIT-NOR BIT-ANDC1 BIT-ANDC2 BIT-ORC1 BIT-ORC2 BIT-NOT) (("boole") BOOLE) (("butlast") BUTLAST NBUTLAST) (("byte-io") WRITE-BYTE READ-BYTE) (("chars") CHAR/= CHAR> CHAR>= CHAR-NOT-EQUAL) (("clos") CLASS-NAME NO-APPLICABLE-METHOD FUNCTION-KEYWORDS SLOT-VALUE SLOT-BOUNDP SLOT-MAKUNBOUND SLOT-EXISTS-P METHOD-QUALIFIERS ENSURE-GENERIC-FUNCTION COMPUTE-APPLICABLE-METHODS SLOT-MISSING SLOT-UNBOUND ALLOCATE-INSTANCE INITIALIZE-INSTANCE REINITIALIZE-INSTANCE CHANGE-CLASS UPDATE-INSTANCE-FOR-DIFFERENT-CLASS MAKE-INSTANCES-OBSOLETE UPDATE-INSTANCE-FOR-REDEFINED-CLASS MAKE-CONDITION INVALID-METHOD-ERROR METHOD-COMBINATION-ERROR FIND-METHOD ADD-METHOD REMOVE-METHOD NO-NEXT-METHOD) (("coerce") COERCE) (("compile-file-pathname") COMPILE-FILE-PATHNAME) (("compile-file") COMPILE-FILE) (("compiler-macro") COMPILER-MACRO-FUNCTION) (("compiler-pass2") COMPILE) (("concatenate") CONCATENATE) (("copy-seq") COPY-SEQ) (("copy-symbol") COPY-SYMBOL) (("count") COUNT COUNT-IF COUNT-IF-NOT) (("debug") INVOKE-DEBUGGER BREAK) (("delete-duplicates") DELETE-DUPLICATES) (("delete") DELETE DELETE-IF DELETE-IF-NOT) (("deposit-field") DEPOSIT-FIELD) (("describe") DESCRIBE) (("directory") DIRECTORY) (("disassemble") DISASSEMBLE) (("documentation") DOCUMENTATION) (("dribble") DRIBBLE) (("ed") ED) (("enough-namestring") ENOUGH-NAMESTRING) (("ensure-directories-exist") ENSURE-DIRECTORIES-EXIST) (("fill") FILL) (("find-all-symbols") FIND-ALL-SYMBOLS) (("find") POSITION POSITION-IF POSITION-IF-NOT FIND FIND-IF FIND-IF-NOT) (("format") FORMAT) (("gentemp") GENTEMP) (("inspect") INSPECT) (("lcm") LCM) (("ldb") BYTE BYTE-SIZE BYTE-POSITION LDB LDB-TEST DPB) (("ldiff") LDIFF) (("list-length") LIST-LENGTH) (("list") FIFTH SIXTH SEVENTH EIGHTH NINTH TENTH MAKE-LIST COMPLEMENT CONSTANTLY MEMBER) (("load") LOAD) (("make-hash-table") MAKE-HASH-TABLE) (("make-load-form-saving-slots") MAKE-LOAD-FORM-SAVING-SLOTS) (("make-sequence") MAKE-SEQUENCE) (("make-string-output-stream") MAKE-STRING-OUTPUT-STREAM) (("make-string") MAKE-STRING) (("map-into") MAP-INTO) (("map") MAP) (("map1") MAPCAN MAPL MAPLIST MAPCON) (("mask-field") MASK-FIELD) (("member-if") MEMBER-IF MEMBER-IF-NOT) (("mismatch") BAD-SEQ-LIMIT THE-END THE-START CALL-TEST TEST-ERROR MISMATCH) (("nsubstitute") NSUBSTITUTE NSUBSTITUTE-IF NSUBSTITUTE-IF-NOT) (("numbers") SIGNUM ROUND FFLOOR FCEILING FROUND RATIONALIZE GCD ISQRT FLOAT-PRECISION DECODE-FLOAT CONJUGATE PHASE) (("open") OPEN) (("package") MAKE-PACKAGE IMPORT DELETE-PACKAGE) (("parse-integer") PARSE-INTEGER) (("pathnames") PATHNAME-HOST PATHNAME-DEVICE PATHNAME-DIRECTORY PATHNAME-NAME PATHNAME-TYPE WILD-PATHNAME-P PATHNAME-MATCH-P TRANSLATE-PATHNAME LOGICAL-PATHNAME-TRANSLATIONS TRANSLATE-LOGICAL-PATHNAME LOAD-LOGICAL-PATHNAME-TRANSLATIONS LOGICAL-PATHNAME PARSE-NAMESTRING) (("pprint-dispatch") COPY-PPRINT-DISPATCH SET-PPRINT-DISPATCH PPRINT-DISPATCH) (("pprint") WRITE PRINT PRIN1 PRINC PPRINT WRITE-TO-STRING PRIN1-TO-STRING PRINC-TO-STRING WRITE-CHAR WRITE-STRING WRITE-LINE TERPRI FRESH-LINE FINISH-OUTPUT FORCE-OUTPUT CLEAR-OUTPUT PPRINT-NEWLINE PPRINT-INDENT PPRINT-TAB PPRINT-LINEAR PPRINT-FILL PPRINT-TABULAR) (("proclaim") PROCLAIM) (("query") Y-OR-N-P YES-OR-NO-P) (("read-from-string") READ-FROM-STRING) (("read-sequence") READ-SEQUENCE) (("reduce") REDUCE) (("remove-duplicates") REMOVE-DUPLICATES) (("remove") REMOVE REMOVE-IF REMOVE-IF-NOT) (("replace") REPLACE) (("revappend") REVAPPEND) (("search") SEARCH) (("setf") GET-SETF-EXPANSION) (("sets") UNION NUNION INTERSECTION NINTERSECTION SET-DIFFERENCE NSET-DIFFERENCE SET-EXCLUSIVE-OR NSET-EXCLUSIVE-OR SUBSETP) (("sort") MERGE SORT STABLE-SORT) (("strings") STRING-UPCASE STRING-DOWNCASE STRING-CAPITALIZE NSTRING-UPCASE NSTRING-DOWNCASE NSTRING-CAPITALIZE STRING= STRING/= STRING-EQUAL STRING-NOT-EQUAL STRING< STRING> STRING<= STRING>= STRING-LESSP STRING-GREATERP STRING-NOT-LESSP STRING-NOT-GREATERP STRING-LEFT-TRIM STRING-RIGHT-TRIM STRING-TRIM) (("sublis") SUBLIS NSUBLIS) (("subst") SUBST SUBST-IF SUBST-IF-NOT NSUBST NSUBST-IF NSUBST-IF-NOT) (("substitute") LIST-SUBSTITUTE* VECTOR-SUBSTITUTE* SUBSTITUTE SUBSTITUTE-IF SUBSTITUTE-IF-NOT) (("subtypep") SUBTYPEP) (("tailp") TAILP) (("time") DECODE-UNIVERSAL-TIME GET-DECODED-TIME ENCODE-UNIVERSAL-TIME) (("tree-equal") TREE-EQUAL) (("typep") TYPEP) (("upgraded-complex-part-type") UPGRADED-COMPLEX-PART-TYPE) (("write-sequence") WRITE-SEQUENCE)))) (FUNCALL (FUNCTION EXTENSIONS:AUTOLOAD) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) ;; MACROS (IN-PACKAGE :CL) (DOLIST (SYSTEM::FS (QUOTE ((("and") AND) (("assert") ASSERT) (("case") CASE CCASE ECASE TYPECASE CTYPECASE ETYPECASE) (("check-type") CHECK-TYPE) (("clos") DEFINE-METHOD-COMBINATION DEFGENERIC DEFMETHOD DEFCLASS DEFINE-CONDITION) (("compiler-macro") DEFINE-COMPILER-MACRO) (("compiler-pass2") WITH-COMPILATION-UNIT) (("cond") COND) (("count") VECTOR-COUNT-IF LIST-COUNT-IF) (("define-modify-macro") DEFINE-MODIFY-MACRO) (("define-symbol-macro") DEFINE-SYMBOL-MACRO) (("defmacro") DEFMACRO) (("defpackage") DEFPACKAGE) (("defstruct") DEFSTRUCT) (("deftype") DEFTYPE) (("destructuring-bind") DESTRUCTURING-BIND) (("do-all-symbols") DO-ALL-SYMBOLS) (("do-external-symbols") DO-EXTERNAL-SYMBOLS) (("do-symbols") DO-SYMBOLS) (("do") DO DO*) (("dolist") DOLIST) (("dotimes") DOTIMES) (("error") IGNORE-ERRORS) (("format") FORMATTER) (("late-setf") DEFINE-SETF-EXPANDER) (("loop") LOOP LOOP-FINISH) (("mismatch") WITH-START-END) (("multiple-value-bind") MULTIPLE-VALUE-BIND) (("multiple-value-list") MULTIPLE-VALUE-LIST) (("multiple-value-setq") MULTIPLE-VALUE-SETQ) (("nth-value") NTH-VALUE) (("or") OR) (("pprint") PPRINT-LOGICAL-BLOCK) (("print-unreadable-object") PRINT-UNREADABLE-OBJECT) (("proclaim") DECLAIM) (("prog") PROG PROG*) (("psetf") PSETF) (("remf") REMF) (("rotatef") ROTATEF) (("setf") SETF) (("shiftf") SHIFTF) (("step") STEP) (("sublis") NSUBLIS-MACRO) (("substitute") REAL-COUNT SUBST-DISPATCH) (("trace") TRACE UNTRACE) (("with-accessors") WITH-ACCESSORS) (("with-hash-table-iterator") WITH-HASH-TABLE-ITERATOR) (("with-input-from-string") WITH-INPUT-FROM-STRING) (("with-open-file") WITH-OPEN-FILE) (("with-output-to-string") WITH-OUTPUT-TO-STRING) (("with-package-iterator") WITH-PACKAGE-ITERATOR) (("with-slots") WITH-SLOTS) (("with-standard-io-syntax") WITH-STANDARD-IO-SYNTAX)))) (FUNCALL (FUNCTION EXTENSIONS:AUTOLOAD-MACRO) (CDR SYSTEM::FS) (CAR (CAR SYSTEM::FS)))) abcl-src-1.9.0/src/org/armedbear/lisp/autoloads.lisp0100644 0000000 0000000 00000004545 14202767264 021113 0ustar000000000 0000000 ;;; autoloads.lisp ;;; ;;; Copyright (C) 2003-2008 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;; ABOUT THIS FILE ;; In order to avoid loading the full CL system (of which not all functions ;; may be required by the current program), this file makes sure symbols ;; of public functions have their function slots bound to a proxy function ;; which loads the actual functions or macros on invocation. ;; There are two autoloader files: autoload-gen.lisp, which is automatically ;; generated based on the source files, and this file, which is manually ;; maintained for any symbols that can't be automatically detected. (in-package "SYSTEM") ;; This one must be last, or at least past print-object and clos: ;; we don't want FORMATs executed before we can load those to end us ;; in a debugger. This command replaces the earlier function binding ;; where simple-format calls sys::%format (autoload 'simple-format "format") abcl-src-1.9.0/src/org/armedbear/lisp/aver.lisp0100644 0000000 0000000 00000003561 14202767264 020052 0ustar000000000 0000000 ;;; aver.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package "SYSTEM") (export 'aver) (defun %failed-aver (expr-as-string) (error 'simple-error :format-control "Failed AVER: ~S" :format-arguments (list expr-as-string))) (defmacro aver (expr) "Signal simple-error when EXPR is non-NIL." `(unless ,expr (%failed-aver ,(format nil "~A" expr)))) abcl-src-1.9.0/src/org/armedbear/lisp/backquote.lisp0100644 0000000 0000000 00000024056 14223403213 021055 0ustar000000000 0000000 ;;; backquote.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. ;;;; the backquote reader macro ;;;; This software is part of the SBCL system. See the README file for ;;;; more information. ;;;; ;;;; This software is derived from the CMU CL system, which was ;;;; written at Carnegie Mellon University and released into the ;;;; public domain. The software is in the public domain and is ;;;; provided with absolutely no warranty. See the COPYING and CREDITS ;;;; files for more information. (in-package #:system) ;;; The flags passed back by BACKQUOTIFY can be interpreted as follows: ;;; ;;; |`,|: [a] => a ;;; NIL: [a] => a ;the NIL flag is used only when a is NIL ;;; T: [a] => a ;the T flag is used when a is self-evaluating ;;; QUOTE: [a] => (QUOTE a) ;;; APPEND: [a] => (APPEND . a) ;;; NCONC: [a] => (NCONC . a) ;;; LIST: [a] => (LIST . a) ;;; LIST*: [a] => (LIST* . a) ;;; ;;; The flags are combined according to the following set of rules: ;;; ([a] means that a should be converted according to the previous table) ;;; ;;; \ car || otherwise | QUOTE or | |`,@| | |`,.| ;;;cdr \ || | T or NIL | | ;;;================================================================================ ;;; |`,| || LIST* ([a] [d]) | LIST* ([a] [d]) | APPEND (a [d]) | NCONC (a [d]) ;;; NIL || LIST ([a]) | QUOTE (a) | a | a ;;;QUOTE or T|| LIST* ([a] [d]) | QUOTE (a . d) | APPEND (a [d]) | NCONC (a [d]) ;;; APPEND || LIST* ([a] [d]) | LIST* ([a] [d]) | APPEND (a . d) | NCONC (a [d]) ;;; NCONC || LIST* ([a] [d]) | LIST* ([a] [d]) | APPEND (a [d]) | NCONC (a . d) ;;; LIST || LIST ([a] . d) | LIST ([a] . d) | APPEND (a [d]) | NCONC (a [d]) ;;; LIST* || LIST* ([a] . d) | LIST* ([a] . d) | APPEND (a [d]) | NCONC (a [d]) ;;; ;;; involves starting over again pretending you had read ".,a)" instead ;;; of ",@a)" ;; (%defvar '*backquote-count* 0) ; defined in Java, q.v. Lisp.java:2754 (%defvar '*bq-comma-flag* '(|,|)) (%defvar '*bq-at-flag* '(|,@|)) (%defvar '*bq-dot-flag* '(|,.|)) ;; (%defvar '*bq-vector-flag* '(|bqv|)) ; defined in Java, q.v. Lisp.java:2757 ;;; the actual character macro (defun backquote-macro (stream ignore) (declare (ignore ignore)) (let ((*backquote-count* (1+ *backquote-count*))) (multiple-value-bind (flag thing) (backquotify stream (read stream t nil t)) (when (eq flag *bq-at-flag*) (%reader-error stream ",@ after backquote in ~S" thing)) (when (eq flag *bq-dot-flag*) (%reader-error stream ",. after backquote in ~S" thing)) (backquotify-1 flag thing)))) (defun comma-macro (stream ignore) (declare (ignore ignore)) (unless (> *backquote-count* 0) (when *read-suppress* (return-from comma-macro nil)) (%reader-error stream "Comma not inside a backquote.")) (let ((c (read-char stream)) (*backquote-count* (1- *backquote-count*))) (cond ((char= c #\@) (cons *bq-at-flag* (read stream t nil t))) ((char= c #\.) (cons *bq-dot-flag* (read stream t nil t))) (t (unread-char c stream) (cons *bq-comma-flag* (read stream t nil t)))))) ;;; (defun expandable-backq-expression-p (object) (and (consp object) (let ((flag (%car object))) (or (eq flag *bq-at-flag*) (eq flag *bq-dot-flag*))))) ;;; This does the expansion from table 2. (defun backquotify (stream code) (cond ((atom code) (cond ((null code) (values nil nil)) ((or (consp code) (symbolp code)) ;; Keywords are self-evaluating. Install after packages. (values 'quote code)) (t (values t code)))) ((or (eq (car code) *bq-at-flag*) (eq (car code) *bq-dot-flag*)) (values (car code) (cdr code))) ((eq (car code) *bq-comma-flag*) (comma (cdr code))) ((eq (car code) *bq-vector-flag*) (multiple-value-bind (dflag d) (backquotify stream (cdr code)) (values 'vector (backquotify-1 dflag d)))) (t (multiple-value-bind (aflag a) (backquotify stream (car code)) (multiple-value-bind (dflag d) (backquotify stream (cdr code)) (when (eq dflag *bq-at-flag*) ;; Get the errors later. (%reader-error stream ",@ after dot in ~S" code)) (when (eq dflag *bq-dot-flag*) (%reader-error stream ",. after dot in ~S" code)) (cond ((eq aflag *bq-at-flag*) (if (null dflag) (if (expandable-backq-expression-p a) (values 'append (list a)) (comma a)) (values 'append (cond ((eq dflag 'append) (cons a d )) (t (list a (backquotify-1 dflag d))))))) ((eq aflag *bq-dot-flag*) (if (null dflag) (if (expandable-backq-expression-p a) (values 'nconc (list a)) (comma a)) (values 'nconc (cond ((eq dflag 'nconc) (cons a d)) (t (list a (backquotify-1 dflag d))))))) ((null dflag) (if (memq aflag '(quote t nil)) (values 'quote (list a)) (values 'list (list (backquotify-1 aflag a))))) ((memq dflag '(quote t)) (if (memq aflag '(quote t nil)) (values 'quote (cons a d )) (values 'list* (list (backquotify-1 aflag a) (backquotify-1 dflag d))))) (t (setq a (backquotify-1 aflag a)) (if (memq dflag '(list list*)) (values dflag (cons a d)) (values 'list* (list a (backquotify-1 dflag d))))))))))) ;;; This handles the cases. (defun comma (code) (cond ((atom code) (cond ((null code) (values nil nil)) ((or (numberp code) (eq code t)) (values t code)) (t (values *bq-comma-flag* code)))) ((and (eq (car code) 'quote) (not (expandable-backq-expression-p (cadr code)))) (values (car code) (cadr code))) ((memq (car code) '(append list list* nconc)) (values (car code) (cdr code))) ((eq (car code) 'cons) (values 'list* (cdr code))) (t (values *bq-comma-flag* code)))) ;;; This handles table 1. (defun backquotify-1 (flag thing) (cond ((or (eq flag *bq-comma-flag*) (memq flag '(t nil))) thing) ((eq flag 'quote) (list 'quote thing)) ((eq flag 'list*) (cond ((and (null (cddr thing)) (not (expandable-backq-expression-p (cadr thing)))) (cons 'backq-cons thing)) ((expandable-backq-expression-p (car (last thing))) (list 'backq-append (cons 'backq-list (butlast thing)) ;; Can it be optimized further? -- APD, 2001-12-21 (car (last thing)))) (t (cons 'backq-list* thing)))) ((eq flag 'vector) (list 'backq-vector thing)) (t (cons (ecase flag ((list) 'backq-list) ((append) 'backq-append) ((nconc) 'backq-nconc)) thing)))) ;;;; magic BACKQ- versions of builtin functions ;;; Define synonyms for the lisp functions we use, so that by using ;;; them, the backquoted material will be recognizable to the ;;; pretty-printer. (defun backq-list (&rest args) (apply #'list args)) (defun backq-list* (&rest args) (apply #'list* args)) (defun backq-append (&rest args) (apply #'append args)) (defun backq-nconc (&rest args) (apply #'nconc args)) (defun backq-cons (&rest args) (apply #'cons args)) (defun backq-vector (list) (declare (list list)) (coerce list 'simple-vector)) ;;; The pretty-printer needs to know about our special tokens (%defvar '*backq-tokens* '(backq-comma backq-comma-at backq-comma-dot backq-list backq-list* backq-append backq-nconc backq-cons backq-vector)) (defun %reader-error (stream control &rest args) (error 'reader-error :stream stream :format-control control :format-arguments args)) abcl-src-1.9.0/src/org/armedbear/lisp/bit-array-ops.lisp0100644 0000000 0000000 00000023330 14223403213 021562 0ustar000000000 0000000 ;;; bit-array-ops.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package #:system) (defun bit-array-same-dimensions-p (array1 array2) (declare (type (array bit) array1 array2)) (and (= (array-rank array1) (array-rank array2)) (dotimes (index (array-rank array1) t) (when (/= (array-dimension array1 index) (array-dimension array2 index)) (return nil))))) (defun require-same-dimensions (array1 array2) (unless (bit-array-same-dimensions-p array1 array2) (error 'program-error "~S and ~S do not have the same dimensions." array1 array2))) (defun pick-result-array (result-bit-array bit-array-1) (case result-bit-array ((t) bit-array-1) ((nil) (make-array (array-dimensions bit-array-1) :element-type 'bit :initial-element 0)) (t (require-same-dimensions bit-array-1 result-bit-array) result-bit-array))) (defun bit-and (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-and bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logand (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i))))))) (defun bit-ior (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-ior bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logior (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i))))))) (defun bit-xor (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-xor bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logxor (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i))))))) (defun bit-eqv (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-eqv bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logand (logeqv (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i)) 1)))))) (defun bit-nand (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-nand bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logand (lognand (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i)) 1)))))) (defun bit-nor (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-nor bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logand (lognor (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i)) 1)))))) (defun bit-andc1 (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-andc1 bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logand (logandc1 (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i)) 1)))))) (defun bit-andc2 (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-andc2 bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logand (logandc2 (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i)) 1)))))) (defun bit-orc1 (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-orc1 bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logand (logorc1 (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i)) 1)))))) (defun bit-orc2 (bit-array-1 bit-array-2 &optional result-bit-array) (require-same-dimensions bit-array-1 bit-array-2) (let ((result-bit-array (pick-result-array result-bit-array bit-array-1))) (if (and (simple-bit-vector-p bit-array-1) (simple-bit-vector-p bit-array-2) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-orc2 bit-array-1 bit-array-2 result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logand (logorc2 (row-major-aref bit-array-1 i) (row-major-aref bit-array-2 i)) 1)))))) (defun bit-not (bit-array &optional result-bit-array) (let ((result-bit-array (pick-result-array result-bit-array bit-array))) (if (and (simple-bit-vector-p bit-array) (simple-bit-vector-p result-bit-array)) (%simple-bit-vector-bit-not bit-array result-bit-array) (dotimes (i (array-total-size result-bit-array) result-bit-array) (setf (row-major-aref result-bit-array i) (logxor (row-major-aref bit-array i) 1)))))) abcl-src-1.9.0/src/org/armedbear/lisp/boole.lisp0100644 0000000 0000000 00000004456 14202767264 020221 0ustar000000000 0000000 ;;; boole.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (defun boole (op n1 n2) (unless (and (integerp n1) (integerp n2)) (error 'type-error :datum (if (integerp n1) n2 n1) :expected-type 'integer)) (case op (#.boole-clr 0) (#.boole-set -1) (#.boole-1 n1) (#.boole-2 n2) (#.boole-c1 (lognot n1)) (#.boole-c2 (lognot n2)) (#.boole-and (logand n1 n2)) (#.boole-ior (logior n1 n2)) (#.boole-xor (logxor n1 n2)) (#.boole-eqv (logeqv n1 n2)) (#.boole-nand (lognand n1 n2)) (#.boole-nor (lognor n1 n2)) (#.boole-andc1 (logandc1 n1 n2)) (#.boole-andc2 (logandc2 n1 n2)) (#.boole-orc1 (logorc1 n1 n2)) (#.boole-orc2 (logorc2 n1 n2)) (t (error 'type-error :datum op :expected-type (list 'integer #.boole-clr #.boole-orc2))))) abcl-src-1.9.0/src/org/armedbear/lisp/boot.lisp0100644 0000000 0000000 00000015007 14202767264 020056 0ustar000000000 0000000 ;;; boot.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (sys:%in-package "SYSTEM") (setq *load-verbose* nil) (setq *autoload-verbose* nil) ;; Redefined in macros.lisp. (defmacro in-package (name) (list '%in-package (string name))) (defmacro lambda (lambda-list &rest body) (list 'function (list* 'lambda lambda-list body))) (defmacro named-lambda (name lambda-list &rest body) (list 'function (list* 'named-lambda name lambda-list body))) ;; Redefined in macros.lisp. (defmacro return (&optional result) (list 'return-from nil result)) ;; Redefined in precompiler.lisp. (defmacro defun (name lambda-list &rest body) (let ((block-name (fdefinition-block-name name))) (list '%defun (list 'quote name) (list 'lambda lambda-list (list* 'block block-name body))))) ;; Redefined in macros.lisp. (defmacro defconstant (name initial-value &optional docstring) (list '%defconstant (list 'quote name) initial-value docstring)) ;; Redefined in macros.lisp. (defmacro defparameter (name initial-value &optional docstring) (list '%defparameter (list 'quote name) initial-value docstring)) (defmacro declare (&rest ignored) nil) (in-package #:extensions) (export '(%car %cdr %cadr %caddr)) (defmacro %car (x) (list 'car (list 'truly-the 'cons x))) (defmacro %cdr (x) (list 'cdr (list 'truly-the 'cons x))) (defmacro %cadr (x) (list '%car (list '%cdr x))) (defmacro %caddr (x) (list '%car (list '%cdr (list '%cdr x)))) (in-package #:system) ;; Redefined in precompiler.lisp. (defun eval (form) (%eval form)) ;; Redefined in pprint.lisp. (defun terpri (&optional output-stream) (%terpri output-stream)) ;; Redefined in pprint.lisp. (defun fresh-line (&optional output-stream) (%fresh-line output-stream)) ;; Redefined in pprint.lisp. (defun write-char (character &optional output-stream) (%write-char character output-stream)) (in-package #:extensions) ;; Redefined in pprint.lisp. (defun charpos (stream) (sys::stream-charpos stream)) ;; Redefined in pprint.lisp. (defun (setf charpos) (new-value stream) (sys::stream-%set-charpos stream new-value)) (export 'charpos '#:extensions) ;; Redefined in precompiler.lisp. (defun precompile (name &optional definition) (declare (ignore name definition)) nil) (export 'precompile '#:extensions) (in-package #:system) (defun simple-format (destination control-string &rest args) (apply #'format destination control-string args)) (export 'simple-format '#:system) ;; INVOKE-DEBUGGER is redefined in debug.lisp. (defun invoke-debugger (condition) (sys::%format t "~A~%" condition) (ext:quit)) ;;Redefined in extensible-sequences.lisp (defun length (sequence) (%length sequence)) (defun elt (sequence index) (%elt sequence index)) (defun subseq (sequence start &optional end) (sys::%subseq sequence start end)) (defun reverse (sequence) (sys::%reverse sequence)) (defun nreverse (sequence) (sys::%nreverse sequence)) (load-system-file "autoloads-gen") (load-system-file "autoloads") (load-system-file "early-defuns") (load-system-file "backquote") (load-system-file "destructuring-bind") (load-system-file "defmacro") (load-system-file "setf") (load-system-file "fdefinition") (load-system-file "featurep") (load-system-file "read-conditional") (load-system-file "macros") ;; Redefined in package.lisp (defun make-package (package-name &key nicknames use) (%make-package package-name nicknames use)) (load-system-file "read-circle") (copy-readtable +standard-readtable+ *readtable*) ;; SYS::%COMPILE is redefined in precompiler.lisp. (defun sys::%compile (name definition) (values (if name name definition) nil nil)) (load-system-file "inline") (load-system-file "proclaim") (load-system-file "arrays") (load-system-file "compiler-macro") (load-system-file "subtypep") (load-system-file "typep") (load-system-file "signal") (load-system-file "list") (load-system-file "require") ;; precompiler has a large performance benefit on interpreted code ;; load as early as possible (load-system-file "precompiler") (load-system-file "extensible-sequences-base") (load-system-file "sequences") (load-system-file "error") (load-system-file "defpackage") (load-system-file "define-modify-macro") (load-system-file "defstruct") ;; The actual stream and system-stream classes ;; are created in BuiltInClass.java, however, that code does not ;; set up the structure internals correctly: we wouldn't be able ;; to :include the structure classes. Fix that here. (defstruct (stream (:constructor nil) (:copier nil) (:predicate nil))) ;; Predicate STREAMP defined elsewhere (defstruct (system-stream (:include stream) (:constructor nil) (:copier nil))) (load-system-file "restart") (load-system-file "late-setf") (load-system-file "debug") (load-system-file "print") (load-system-file "pprint-dispatch") (load-system-file "defsetf") (load-system-file "package") (unless (featurep :j) (unless *noinform* (%format t "Startup completed in ~A seconds.~%" (float (/ (ext:uptime) 1000))))) abcl-src-1.9.0/src/org/armedbear/lisp/butlast.lisp0100644 0000000 0000000 00000005126 14223403213 020552 0ustar000000000 0000000 ;;; butlast.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "COMMON-LISP") (export '(butlast nbutlast)) (defun butlast (list &optional (n 1)) (unless (and (listp list) (typep n '(integer 0))) (error 'type-error)) (unless (null list) (let ((length (do ((list list (cdr list)) (i 0 (1+ i))) ((atom list) (1- i))))) (unless (< length n) (do* ((top (cdr list) (cdr top)) (result (list (car list))) (splice result) (count length (1- count))) ((= count n) result) (setq splice (cdr (rplacd splice (list (car top)))))))))) (defun nbutlast (list &optional (n 1)) (unless (and (listp list) (typep n '(integer 0))) (error 'type-error)) (unless (null list) (let ((length (do ((list list (cdr list)) (i 0 (1+ i))) ((atom list) (1- i))))) (unless (< length n) (do ((1st (cdr list) (cdr 1st)) (2nd list 1st) (count length (1- count))) ((= count n) (rplacd 2nd ()) list)))))) abcl-src-1.9.0/src/org/armedbear/lisp/byte-io.lisp0100644 0000000 0000000 00000006312 14202767264 020462 0ustar000000000 0000000 ;;; byte-io.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun write-byte (byte stream) (declare (type stream stream)) (let ((element-type (expand-deftype (stream-element-type stream)))) (require-type byte element-type) (let ((width (cadr element-type))) (if (= width 8) (write-8-bits (the (unsigned-byte 8) byte) stream) (let ((bytes ())) (dotimes (i (/ width 8)) (push (logand byte #xff) bytes) (setf byte (ash byte -8))) (dolist (b bytes) (write-8-bits (the (unsigned-byte 8) b) stream))))) byte)) (defun read-byte (stream &optional (eof-error-p t) eof-value) (declare (type stream stream)) (let* ((element-type (expand-deftype (stream-element-type stream)))) (unless element-type (if eof-error-p (error 'end-of-file :stream stream) (return-from read-byte eof-value))) (unless (consp element-type) (error 'simple-type-error :format-control "READ-BYTE: unsupported element type ~S." :format-arguments (list element-type))) (let ((width (cadr element-type))) (if (= width 8) (read-8-bits stream eof-error-p eof-value) (let ((result 0)) (dotimes (i (/ width 8)) (let ((byte (read-8-bits stream eof-error-p eof-value))) (when (eq byte eof-value) (return-from read-byte eof-value)) (setf result (ash result 8)) (setf result (+ result byte)))) (if (and (eq (car element-type) 'signed-byte) (not (zerop (logand result (expt 2 (1- width)))))) (- result (expt 2 width)) result)))))) abcl-src-1.9.0/src/org/armedbear/lisp/case.lisp0100644 0000000 0000000 00000020017 14223403213 020003 0ustar000000000 0000000 ;;; case.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) ;;; Is X a (possibly-improper) list of at least N elements? (defun list-of-length-at-least-p (x n) (or (zerop n) ; since anything can be considered an improper list of length 0 (and (consp x) (list-of-length-at-least-p (cdr x) (1- n))))) (defun case-body-error (name keyform keyform-value expected-type keys) (declare (ignore name keys)) (restart-case (error 'type-error :datum keyform-value :expected-type expected-type) (store-value (value) :report (lambda (stream) (format stream "Supply a new value for ~S." keyform)) :interactive read-evaluated-form value))) ;;; CASE-BODY-AUX provides the expansion once CASE-BODY has groveled ;;; all the cases. Note: it is not necessary that the resulting code ;;; signal case-failure conditions, but that's what KMP's prototype ;;; code did. We call CASE-BODY-ERROR, because of how closures are ;;; compiled. RESTART-CASE has forms with closures that the compiler ;;; causes to be generated at the top of any function using the case ;;; macros, regardless of whether they are needed. ;;; ;;; The CASE-BODY-ERROR function is defined later, when the ;;; RESTART-CASE macro has been defined. (defun case-body-aux (name keyform keyform-value clauses keys errorp proceedp expected-type) (if proceedp (let ((block (gensym)) (again (gensym))) `(let ((,keyform-value ,keyform)) (block ,block (tagbody ,again (return-from ,block (cond ,@(nreverse clauses) (t (setf ,keyform-value (setf ,keyform (case-body-error ',name ',keyform ,keyform-value ',expected-type ',keys))) (go ,again)))))))) `(let ((,keyform-value ,keyform)) (cond ,@(nreverse clauses) ,@(if errorp ;; `((t (error 'case-failure ;; :name ',name ;; :datum ,keyform-value ;; :expected-type ',expected-type ;; :possibilities ',keys)))))))) `((t (error 'type-error :datum ,keyform-value :expected-type ',expected-type)))))))) ;;; CASE-BODY returns code for all the standard "case" macros. NAME is ;;; the macro name, and KEYFORM is the thing to case on. MULTI-P ;;; indicates whether a branch may fire off a list of keys; otherwise, ;;; a key that is a list is interpreted in some way as a single key. ;;; When MULTI-P, TEST is applied to the value of KEYFORM and each key ;;; for a given branch; otherwise, TEST is applied to the value of ;;; KEYFORM and the entire first element, instead of each part, of the ;;; case branch. When ERRORP, no T or OTHERWISE branch is permitted, ;;; and an ERROR form is generated. When PROCEEDP, it is an error to ;;; omit ERRORP, and the ERROR form generated is executed within a ;;; RESTART-CASE allowing KEYFORM to be set and retested. (defun case-body (name keyform cases multi-p test errorp proceedp needcasesp) (unless (or cases (not needcasesp)) (warn "no clauses in ~S" name)) (let ((keyform-value (gensym)) (clauses ()) (keys ())) (do* ((cases cases (cdr cases)) (case (car cases) (car cases))) ((null cases) nil) (unless (list-of-length-at-least-p case 1) (error "~S -- bad clause in ~S" case name)) (destructuring-bind (keyoid &rest forms) case (cond ((and (memq keyoid '(t otherwise)) (null (cdr cases))) (if errorp (progn (style-warn "~@" keyoid name) (push keyoid keys) (push `((,test ,keyform-value ',keyoid) nil ,@forms) clauses)) (push `(t nil ,@forms) clauses))) ((and multi-p (listp keyoid)) (setf keys (append keyoid keys)) (push `((or ,@(mapcar (lambda (key) `(,test ,keyform-value ',key)) keyoid)) nil ,@forms) clauses)) (t (push keyoid keys) (push `((,test ,keyform-value ',keyoid) nil ,@forms) clauses))))) (case-body-aux name keyform keyform-value clauses keys errorp proceedp `(,(if multi-p 'member 'or) ,@keys)))) (defmacro case (keyform &body cases) "CASE Keyform {({(Key*) | Key} Form*)}* Evaluates the Forms in the first clause with a Key EQL to the value of Keyform. If a singleton key is T then the clause is a default clause." (case-body 'case keyform cases t 'eql nil nil nil)) (defmacro ccase (keyform &body cases) "CCASE Keyform {({(Key*) | Key} Form*)}* Evaluates the Forms in the first clause with a Key EQL to the value of Keyform. If none of the keys matches then a correctable error is signalled." (case-body 'ccase keyform cases t 'eql t t t)) (defmacro ecase (keyform &body cases) "ECASE Keyform {({(Key*) | Key} Form*)}* Evaluates the Forms in the first clause with a Key EQL to the value of Keyform. If none of the keys matches then an error is signalled." (case-body 'ecase keyform cases t 'eql t nil t)) (defmacro typecase (keyform &body cases) "TYPECASE Keyform {(Type Form*)}* Evaluates the Forms in the first clause for which TYPEP of Keyform and Type is true." (case-body 'typecase keyform cases nil 'typep nil nil nil)) (defmacro ctypecase (keyform &body cases) "CTYPECASE Keyform {(Type Form*)}* Evaluates the Forms in the first clause for which TYPEP of Keyform and Type is true. If no form is satisfied then a correctable error is signalled." (case-body 'ctypecase keyform cases nil 'typep t t t)) (defmacro etypecase (keyform &body cases) "ETYPECASE Keyform {(Type Form*)}* Evaluates the Forms in the first clause for which TYPEP of Keyform and Type is true. If no form is satisfied then an error is signalled." (case-body 'etypecase keyform cases nil 'typep t nil t)) abcl-src-1.9.0/src/org/armedbear/lisp/ceiling.java0100644 0000000 0000000 00000005024 14202767264 020475 0ustar000000000 0000000 /* * ceiling.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### ceiling number &optional divisor public final class ceiling extends Primitive { private ceiling() { super("ceiling", "number &optional divisor"); } @Override public LispObject execute(LispObject arg) { return execute(arg, Fixnum.ONE); } @Override public LispObject execute(LispObject first, LispObject second) { LispObject quotient = first.truncate(second); final LispThread thread = LispThread.currentThread(); LispObject remainder = thread._values[1]; if (remainder.zerop()) return quotient; if (second.minusp()) { if (first.plusp()) return quotient; } else { if (first.minusp()) return quotient; } quotient = quotient.incr(); thread._values[0] = quotient; thread._values[1] = remainder.subtract(second); return quotient; } private static final Primitive CEILING = new ceiling(); } abcl-src-1.9.0/src/org/armedbear/lisp/cell_error_name.java0100644 0000000 0000000 00000004244 14202767264 022216 0ustar000000000 0000000 /* * cell_error_name.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### cell-error-name public final class cell_error_name extends Primitive { private cell_error_name() { super(Symbol.CELL_ERROR_NAME, "condition"); } @Override public LispObject execute(LispObject arg) { final StandardObject obj; if (arg instanceof StandardObject) { obj = (StandardObject) arg; } else { return type_error(arg, Symbol.STANDARD_OBJECT); } return obj.getInstanceSlotValue(Symbol.NAME); } private static final Primitive CELL_ERROR_NAME = new cell_error_name(); } abcl-src-1.9.0/src/org/armedbear/lisp/chars.lisp0100644 0000000 0000000 00000005567 14223403213 020205 0ustar000000000 0000000 ;;; chars.lisp ;;; ;;; Copyright (C) 2003-2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) ;;; From CMUCL. (defun char/= (character &rest more-characters) (do* ((head character (car list)) (list more-characters (cdr list))) ((atom list) T) (unless (do* ((l list (cdr l))) ;inner loop returns T ((atom l) T) ; iff head /= rest. (if (eql head (car l)) (return nil))) (return nil)))) (defun char> (character &rest more-characters) (do* ((c character (car list)) (list more-characters (cdr list))) ((atom list) T) (unless (> (char-int c) (char-int (car list))) (return nil)))) (defun char>= (character &rest more-characters) (do* ((c character (car list)) (list more-characters (cdr list))) ((atom list) T) (unless (>= (char-int c) (char-int (car list))) (return nil)))) (defmacro equal-char-code (character) `(let ((ch (char-code ,character))) (if (< 96 ch 123) (- ch 32) ch))) (defun char-not-equal (character &rest more-characters) (do* ((head character (car list)) (list more-characters (cdr list))) ((atom list) T) (unless (do* ((l list (cdr l))) ((atom l) T) (if (= (equal-char-code head) (equal-char-code (car l))) (return nil))) (return nil)))) abcl-src-1.9.0/src/org/armedbear/lisp/check-type.lisp0100644 0000000 0000000 00000005706 14223403213 021134 0ustar000000000 0000000 ;;; check-type.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package #:system) (defmacro check-type (place type &optional type-string) (let ((place-value (gensym))) `(loop (let ((,place-value ,place)) (when (typep ,place-value ',type) (return nil)) (setf ,place (check-type-error ',place ,place-value ',type ,type-string)))))) (defun check-type-error (place place-value type type-string) (let ((cond (if type-string (make-condition 'simple-type-error :datum place-value :expected-type type :format-control "The value of ~S is ~S, which is not ~A." :format-arguments (list place place-value type-string)) (make-condition 'simple-type-error :datum place-value :expected-type type :format-control "The value of ~S is ~S, which is not of type ~S." :format-arguments (list place place-value type))))) (restart-case (error cond) (store-value (value) :report (lambda (stream) (format stream "Supply a new value for ~S." place)) :interactive read-evaluated-form value)))) abcl-src-1.9.0/src/org/armedbear/lisp/clos.lisp0100644 0000000 0000000 00000632233 14242624277 020061 0ustar000000000 0000000 ;;; clos.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; Copyright (C) 2010-2013 Mark Evenson ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Originally based on Closette. ;;; Closette Version 1.0 (February 10, 1991) ;;; ;;; Copyright (c) 1990, 1991 Xerox Corporation. ;;; All rights reserved. ;;; ;;; Use and copying of this software and preparation of derivative works ;;; based upon this software are permitted. Any distribution of this ;;; software or derivative works must comply with all applicable United ;;; States export control laws. ;;; ;;; This software is made available AS IS, and Xerox Corporation makes no ;;; warranty about the software, its performance or its conformity to any ;;; specification. ;;; ;;; Closette is an implementation of a subset of CLOS with a metaobject ;;; protocol as described in "The Art of The Metaobject Protocol", ;;; MIT Press, 1991. (in-package #:mop) (export '(%defgeneric canonicalize-direct-superclasses)) ;; ;; ;; ;; In order to bootstrap CLOS, first implement the required API as ;; normal functions which only apply to the "root" metaclass ;; STANDARD-CLASS. ;; ;; After putting the normal functions in place, the building blocks ;; are in place to gradually swap the normal functions with ;; generic functions and methods. ;; ;; Some functionality implemented in the temporary regular functions ;; needs to be available later as a method definition to be dispatched ;; to for the standard case, e.g. with arguments of type STANDARD-CLASS ;; or STANDARD-GENERIC-FUNCTION. To prevent repeated code, the ;; functions are implemented in functions by the same name as the API ;; functions, but with the STD- prefix. These functions are sometimes ;; used in regular code as well, either in a "fast path" or to break a ;; circularity (e.g., within compute-discriminating-function when the ;; user adds a method to compute-discriminating-function). ;; ;; When hacking this file, note that some important parts are implemented ;; in the Java world. These Java bits can be found in the files ;; ;; * LispClass.java ;; * SlotClass.java ;; * StandardClass.java ;; * BuiltInClass.java ;; * StandardObject.java ;; * StandardObjectFunctions.java ;; * FuncallableStandardObject.java ;; * Layout.java ;; ;; In case of function names, those defined on the Java side can be ;; recognized by their prefixed percent (%) sign. ;; ;; The API functions need to be declaimed NOTINLINE explicitly, because ;; that prevents inlining in the current FASL (which is allowed by the ;; CLHS without the declaration); this is a hard requirement to in order ;; to be able to swap the symbol's function slot with a generic function ;; later on - with it actually being used. ;; ;; ;; ;; ### Note that the "declares all API functions as regular functions" ;; isn't true when I write the above, but it's definitely the target. ;; ;; A note about AMOP: the first chapters (and the sample Closette ;; implementation) of the book sometimes deviate from the specification. ;; For example, in the examples slot-value-using-class has the slot name ;; as third argument where in the specification it is the effective slot ;; definition. When in doubt, we aim to follow the specification, the ;; MOP test suite at http://common-lisp.net/project/closer/features.html ;; and the behavior of other CL implementations in preference to ;; chapters 1-4 and appendix D. (defconstant +the-standard-class+ (find-class 'standard-class)) (defconstant +the-funcallable-standard-class+ (find-class 'funcallable-standard-class)) (defconstant +the-standard-object-class+ (find-class 'standard-object)) (defconstant +the-funcallable-standard-object-class+ (find-class 'funcallable-standard-object)) (defconstant +the-standard-method-class+ (find-class 'standard-method)) (defconstant +the-T-class+ (find-class 'T)) (defconstant +the-standard-slot-definition-class+ (find-class 'standard-slot-definition)) (defconstant +the-standard-direct-slot-definition-class+ (find-class 'standard-direct-slot-definition)) (defconstant +the-standard-effective-slot-definition-class+ (find-class 'standard-effective-slot-definition)) ;; Don't use DEFVAR, because that disallows loading clos.lisp ;; after compiling it: the binding won't get assigned to T anymore (defparameter *clos-booting* t) (defmacro define-class->%class-forwarder (name) (let* (($name (if (consp name) (cadr name) name)) (%name (intern (concatenate 'string "%" (if (consp name) (symbol-name 'set-) "") (symbol-name $name)) (symbol-package $name)))) `(progn (declaim (notinline ,name)) (defun ,name (&rest args) (apply #',%name args))))) ;; ;; DEFINE PLACE HOLDER FUNCTIONS ;; (define-class->%class-forwarder class-name) (define-class->%class-forwarder (setf class-name)) (define-class->%class-forwarder class-slots) (define-class->%class-forwarder (setf class-slots)) (define-class->%class-forwarder class-direct-slots) (define-class->%class-forwarder (setf class-direct-slots)) (define-class->%class-forwarder class-layout) (define-class->%class-forwarder (setf class-layout)) (define-class->%class-forwarder class-direct-superclasses) (define-class->%class-forwarder (setf class-direct-superclasses)) (define-class->%class-forwarder class-direct-subclasses) (define-class->%class-forwarder (setf class-direct-subclasses)) (define-class->%class-forwarder class-direct-methods) (define-class->%class-forwarder (setf class-direct-methods)) (define-class->%class-forwarder class-precedence-list) (define-class->%class-forwarder (setf class-precedence-list)) (define-class->%class-forwarder class-finalized-p) (define-class->%class-forwarder (setf class-finalized-p)) (define-class->%class-forwarder class-default-initargs) (define-class->%class-forwarder (setf class-default-initargs)) (define-class->%class-forwarder class-direct-default-initargs) (define-class->%class-forwarder (setf class-direct-default-initargs)) (declaim (notinline add-direct-subclass remove-direct-subclass)) (defun add-direct-subclass (superclass subclass) (setf (class-direct-subclasses superclass) (adjoin subclass (class-direct-subclasses superclass)))) (defun remove-direct-subclass (superclass subclass) (setf (class-direct-subclasses superclass) (remove subclass (class-direct-subclasses superclass)))) (defun fixup-standard-class-hierarchy () ;; Make the result of class-direct-subclasses for the pre-built ;; classes agree with AMOP Table 5.1 (pg. 141). This could be done in ;; StandardClass.java where these classes are defined, but it's less ;; painful to do it Lisp-side. (flet ((add-subclasses (class subclasses) (when (atom subclasses) (setf subclasses (list subclasses))) (setf (class-direct-subclasses (find-class class)) (union (class-direct-subclasses (find-class class)) (mapcar #'find-class subclasses))))) (add-subclasses t 'standard-object) (add-subclasses 'function 'funcallable-standard-object) (add-subclasses 'standard-object '(funcallable-standard-object metaobject)) (add-subclasses 'metaobject '(method slot-definition specializer)) (add-subclasses 'specializer '(class)) (add-subclasses 'method 'standard-method) (add-subclasses 'slot-definition '(direct-slot-definition effective-slot-definition standard-slot-definition)) (add-subclasses 'standard-slot-definition '(standard-direct-slot-definition standard-effective-slot-definition)) (add-subclasses 'direct-slot-definition 'standard-direct-slot-definition) (add-subclasses 'effective-slot-definition 'standard-effective-slot-definition) (add-subclasses 'class '(built-in-class standard-class funcallable-standard-class)))) (fixup-standard-class-hierarchy) (defun std-class-p (class) (let ((metaclass (class-of class))) (or (eq metaclass +the-standard-class+) (eq metaclass +the-funcallable-standard-class+)))) (defun no-applicable-method (generic-function &rest args) (error "There is no applicable method for the generic function ~S when called with arguments ~S." generic-function args)) (defun function-keywords (method) (std-function-keywords method)) (declaim (notinline map-dependents)) (defun map-dependents (metaobject function) ;; stub, will be redefined later (declare (ignore metaobject function)) nil) (defmacro push-on-end (value location) `(setf ,location (nconc ,location (list ,value)))) ;;; (SETF GETF*) is like (SETF GETF) except that it always changes the list, ;;; which must be non-nil. (defun (setf getf*) (new-value plist key) (block body (do ((x plist (cddr x))) ((null x)) (when (eq (car x) key) (setf (car (cdr x)) new-value) (return-from body new-value))) (push-on-end key plist) (push-on-end new-value plist) new-value)) (defun mapappend (fun &rest args) (if (some #'null args) () (append (apply fun (mapcar #'car args)) (apply #'mapappend fun (mapcar #'cdr args))))) (defun mapplist (fun x) (if (null x) () (cons (funcall fun (car x) (cadr x)) (mapplist fun (cddr x))))) (defsetf std-slot-value set-std-slot-value) (defsetf std-instance-layout %set-std-instance-layout) (defsetf standard-instance-access %set-standard-instance-access) (defun funcallable-standard-instance-access (instance location) (standard-instance-access instance location)) (defsetf funcallable-standard-instance-access %set-standard-instance-access) (defun (setf find-class) (new-value symbol &optional errorp environment) (declare (ignore errorp environment)) (%set-find-class symbol new-value)) (defun canonicalize-direct-slots (direct-slots) `(list ,@(mapcar #'canonicalize-direct-slot direct-slots))) (defun canonicalize-direct-slot (spec) (if (symbolp spec) `(list :name ',spec) (let ((name (car spec)) (initfunction nil) (initform nil) (initargs ()) (type nil) (allocation nil) (documentation nil) (readers ()) (writers ()) (other-options ()) (non-std-options ())) (do ((olist (cdr spec) (cddr olist))) ((null olist)) (case (car olist) (:initform (when initform (error 'program-error "duplicate slot option :INITFORM for slot named ~S" name)) (setq initfunction t) (setq initform (cadr olist))) (:initarg (push-on-end (cadr olist) initargs)) (:allocation (when allocation (error 'program-error "duplicate slot option :ALLOCATION for slot named ~S" name)) (setf allocation (cadr olist)) (push-on-end (car olist) other-options) (push-on-end (cadr olist) other-options)) (:type (when type (error 'program-error "duplicate slot option :TYPE for slot named ~S" name)) (setf type (cadr olist))) (:documentation (when documentation (error 'program-error "duplicate slot option :DOCUMENTATION for slot named ~S" name)) (setf documentation (cadr olist))) (:reader (maybe-note-name-defined (cadr olist)) (push-on-end (cadr olist) readers)) (:writer (maybe-note-name-defined (cadr olist)) (push-on-end (cadr olist) writers)) (:accessor (maybe-note-name-defined (cadr olist)) (push-on-end (cadr olist) readers) (push-on-end `(setf ,(cadr olist)) writers)) (t (push-on-end (cadr olist) (getf non-std-options (car olist)))))) `(list :name ',name ,@(when initfunction `(:initform ',initform :initfunction ,(if (eq allocation :class) ;; CLHS specifies the initform for a ;; class allocation level slot needs ;; to be evaluated in the dynamic ;; extent of the DEFCLASS form (let ((var (gensym))) `(let ((,var ,initform)) (lambda () ,var))) `(lambda () ,initform)))) ,@(when initargs `(:initargs ',initargs)) ,@(when readers `(:readers ',readers)) ,@(when writers `(:writers ',writers)) ,@(when type `(:type ',type)) ,@(when documentation `(:documentation ',documentation)) ,@other-options ,@(mapcar #'(lambda (opt) (if (or (atom opt) (/= 1 (length opt))) `',opt `',(car opt))) non-std-options))))) (defun maybe-note-name-defined (name) (when (fboundp 'note-name-defined) (note-name-defined name))) (defun canonicalize-defclass-options (options) (mapappend #'canonicalize-defclass-option options)) (defun canonicalize-defclass-option (option) (case (car option) (:metaclass (list ':metaclass `(find-class ',(cadr option)))) (:default-initargs (list ':direct-default-initargs `(list ,@(mapplist #'(lambda (key value) `(list ',key ',value ,(make-initfunction value))) (cdr option))))) ((:documentation :report) (list (car option) `',(cadr option))) (t (list `(quote ,(car option)) `(quote ,(cdr option)))))) (defun make-initfunction (initform) `(function (lambda () ,initform))) (defun slot-definition-allocation (slot-definition) (std-slot-value slot-definition 'sys::allocation)) (declaim (notinline (setf slot-definition-allocation))) (defun (setf slot-definition-allocation) (value slot-definition) (setf (std-slot-value slot-definition 'sys::allocation) value)) (defun slot-definition-initargs (slot-definition) (std-slot-value slot-definition 'sys::initargs)) (declaim (notinline (setf slot-definition-initargs))) (defun (setf slot-definition-initargs) (value slot-definition) (setf (std-slot-value slot-definition 'sys::initargs) value)) (defun slot-definition-initform (slot-definition) (std-slot-value slot-definition 'sys::initform)) (declaim (notinline (setf slot-definition-initform))) (defun (setf slot-definition-initform) (value slot-definition) (setf (std-slot-value slot-definition 'sys::initform) value)) (defun slot-definition-initfunction (slot-definition) (std-slot-value slot-definition 'sys::initfunction)) (declaim (notinline (setf slot-definition-initfunction))) (defun (setf slot-definition-initfunction) (value slot-definition) (setf (std-slot-value slot-definition 'sys::initfunction) value)) (defun slot-definition-name (slot-definition) (std-slot-value slot-definition 'sys:name)) (declaim (notinline (setf slot-definition-name))) (defun (setf slot-definition-name) (value slot-definition) (setf (std-slot-value slot-definition 'sys:name) value)) (defun slot-definition-readers (slot-definition) (std-slot-value slot-definition 'sys::readers)) (declaim (notinline (setf slot-definition-readers))) (defun (setf slot-definition-readers) (value slot-definition) (setf (std-slot-value slot-definition 'sys::readers) value)) (defun slot-definition-writers (slot-definition) (std-slot-value slot-definition 'sys::writers)) (declaim (notinline (setf slot-definition-writers))) (defun (setf slot-definition-writers) (value slot-definition) (setf (std-slot-value slot-definition 'sys::writers) value)) (defun slot-definition-allocation-class (slot-definition) (std-slot-value slot-definition 'sys::allocation-class)) (declaim (notinline (setf slot-definition-allocation-class))) (defun (setf slot-definition-allocation-class) (value slot-definition) (setf (std-slot-value slot-definition 'sys::allocation-class) value)) (defun slot-definition-location (slot-definition) (std-slot-value slot-definition 'sys::location)) (declaim (notinline (setf slot-definition-location-class))) (defun (setf slot-definition-location) (value slot-definition) (setf (std-slot-value slot-definition 'sys::location) value)) (defun slot-definition-type (slot-definition) (std-slot-value slot-definition 'sys::%type)) (declaim (notinline (setf slot-definition-type))) (defun (setf slot-definition-type) (value slot-definition) (setf (std-slot-value slot-definition 'sys::%type) value)) (defun slot-definition-documentation (slot-definition) (std-slot-value slot-definition 'sys:%documentation)) (declaim (notinline (setf slot-definition-documentation))) (defun (setf slot-definition-documentation) (value slot-definition) (setf (std-slot-value slot-definition 'sys:%documentation) value)) (defun init-slot-definition (slot &key name (initargs ()) (initform nil) (initfunction nil) (readers ()) (writers ()) (allocation :instance) (allocation-class nil) (type t) (documentation nil)) (setf (slot-definition-name slot) name) (setf (slot-definition-initargs slot) initargs) (setf (slot-definition-initform slot) initform) (setf (slot-definition-initfunction slot) initfunction) (setf (slot-definition-readers slot) readers) (setf (slot-definition-writers slot) writers) (setf (slot-definition-allocation slot) allocation) (setf (slot-definition-allocation-class slot) allocation-class) (setf (slot-definition-type slot) type) (setf (slot-definition-documentation slot) documentation) slot) (declaim (notinline direct-slot-definition-class)) (defun direct-slot-definition-class (class &rest args) (declare (ignore class args)) +the-standard-direct-slot-definition-class+) (defun make-direct-slot-definition (class &rest args) (let ((slot-class (apply #'direct-slot-definition-class class args))) (if (eq slot-class +the-standard-direct-slot-definition-class+) (let ((slot (%make-slot-definition +the-standard-direct-slot-definition-class+))) (apply #'init-slot-definition slot :allocation-class class args) slot) (progn (let ((slot (apply #'make-instance slot-class :allocation-class class args))) slot))))) (declaim (notinline effective-slot-definition-class)) (defun effective-slot-definition-class (class &rest args) (declare (ignore class args)) +the-standard-effective-slot-definition-class+) (defun make-effective-slot-definition (class &rest args) (let ((slot-class (apply #'effective-slot-definition-class class args))) (if (eq slot-class +the-standard-effective-slot-definition-class+) (let ((slot (%make-slot-definition +the-standard-effective-slot-definition-class+))) (apply #'init-slot-definition slot args) slot) (progn (let ((slot (apply #'make-instance slot-class args))) slot))))) ;;; finalize-inheritance (declaim (notinline compute-default-initargs)) (defun compute-default-initargs (class) (std-compute-default-initargs class)) (defun std-compute-default-initargs (class) (delete-duplicates (mapcan #'(lambda (c) (copy-list (class-direct-default-initargs c))) (class-precedence-list class)) :key #'car :from-end t)) (defun std-finalize-inheritance (class) ;; In case the class is already finalized, return ;; immediately, as per AMOP. ; (when (class-finalized-p class) ; (return-from std-finalize-inheritance)) (setf (class-precedence-list class) (funcall (if (std-class-p class) #'std-compute-class-precedence-list #'compute-class-precedence-list) class)) (setf (class-slots class) (funcall (if (std-class-p class) #'std-compute-slots #'compute-slots) class)) (let ((old-layout (class-layout class)) (length 0) (instance-slots '()) (shared-slots '())) (dolist (slot (class-slots class)) (case (slot-definition-allocation slot) (:instance (setf (slot-definition-location slot) length) (incf length) (push (slot-definition-name slot) instance-slots)) (:class (unless (slot-definition-location slot) (let ((allocation-class (slot-definition-allocation-class slot))) (if (eq allocation-class class) ;; We initialize class slots here so they can be ;; accessed without creating a dummy instance. (let ((initfunction (slot-definition-initfunction slot))) (setf (slot-definition-location slot) (cons (slot-definition-name slot) (if initfunction (funcall initfunction) +slot-unbound+)))) (setf (slot-definition-location slot) (slot-location allocation-class (slot-definition-name slot)))))) (push (slot-definition-location slot) shared-slots)))) (when old-layout ;; Redefined class: initialize added shared slots. (dolist (location shared-slots) (let* ((slot-name (car location)) (old-location (layout-slot-location old-layout slot-name))) (unless old-location (let* ((slot-definition (find slot-name (class-slots class) :key 'slot-definition-name)) (initfunction (slot-definition-initfunction slot-definition))) (when initfunction (setf (cdr location) (funcall initfunction)))))))) (setf (class-layout class) (make-layout class (nreverse instance-slots) (nreverse shared-slots)))) (setf (class-default-initargs class) (compute-default-initargs class)) (setf (class-finalized-p class) t)) (declaim (notinline finalize-inheritance)) (defun finalize-inheritance (class) (std-finalize-inheritance class)) ;;; Class precedence lists (defun std-compute-class-precedence-list (class) (let ((classes-to-order (collect-superclasses* class))) (dolist (super classes-to-order) (when (typep super 'forward-referenced-class) (error "Can't compute class precedence list for class ~A ~ which depends on forward referenced class ~A." class super))) (topological-sort classes-to-order (remove-duplicates (mapappend #'local-precedence-ordering classes-to-order)) #'std-tie-breaker-rule))) ;;; topological-sort implements the standard algorithm for topologically ;;; sorting an arbitrary set of elements while honoring the precedence ;;; constraints given by a set of (X,Y) pairs that indicate that element ;;; X must precede element Y. The tie-breaker procedure is called when it ;;; is necessary to choose from multiple minimal elements; both a list of ;;; candidates and the ordering so far are provided as arguments. (defun topological-sort (elements constraints tie-breaker) (let ((remaining-constraints constraints) (remaining-elements elements) (result ())) (loop (let ((minimal-elements (remove-if #'(lambda (class) (member class remaining-constraints :key #'cadr)) remaining-elements))) (when (null minimal-elements) (if (null remaining-elements) (return-from topological-sort result) (error "Inconsistent precedence graph."))) (let ((choice (if (null (cdr minimal-elements)) (car minimal-elements) (funcall tie-breaker minimal-elements result)))) (setq result (append result (list choice))) (setq remaining-elements (remove choice remaining-elements)) (setq remaining-constraints (remove choice remaining-constraints :test #'member))))))) ;;; In the event of a tie while topologically sorting class precedence lists, ;;; the CLOS Specification says to "select the one that has a direct subclass ;;; rightmost in the class precedence list computed so far." The same result ;;; is obtained by inspecting the partially constructed class precedence list ;;; from right to left, looking for the first minimal element to show up among ;;; the direct superclasses of the class precedence list constituent. ;;; (There's a lemma that shows that this rule yields a unique result.) (defun std-tie-breaker-rule (minimal-elements cpl-so-far) (dolist (cpl-constituent (reverse cpl-so-far)) (let* ((supers (class-direct-superclasses cpl-constituent)) (common (intersection minimal-elements supers))) (when (not (null common)) (return-from std-tie-breaker-rule (car common)))))) ;;; This version of collect-superclasses* isn't bothered by cycles in the class ;;; hierarchy, which sometimes happen by accident. (defun collect-superclasses* (class) (labels ((all-superclasses-loop (seen superclasses) (let ((to-be-processed (set-difference superclasses seen))) (if (null to-be-processed) superclasses (let ((class-to-process (car to-be-processed))) (all-superclasses-loop (cons class-to-process seen) (union (class-direct-superclasses class-to-process) superclasses))))))) (all-superclasses-loop () (list class)))) ;;; The local precedence ordering of a class C with direct superclasses C_1, ;;; C_2, ..., C_n is the set ((C C_1) (C_1 C_2) ...(C_n-1 C_n)). (defun local-precedence-ordering (class) (mapcar #'list (cons class (butlast (class-direct-superclasses class))) (class-direct-superclasses class))) ;;; Slot inheritance (defun std-compute-slots (class) (let* ((all-slots (mapappend #'(lambda (c) (class-direct-slots c)) ;; Slots of base class must come first (reverse (class-precedence-list class)))) (all-names (delete-duplicates (mapcar 'slot-definition-name all-slots) :from-end t))) (mapcar #'(lambda (name) (funcall (if (std-class-p class) #'std-compute-effective-slot-definition #'compute-effective-slot-definition) class name ;; Slot of inherited class must override initfunction, ;; documentation of base class (nreverse (remove name all-slots :key 'slot-definition-name :test-not #'eq)))) all-names))) (defun std-compute-effective-slot-definition (class name direct-slots) (let ((initer (find-if-not #'null direct-slots :key 'slot-definition-initfunction)) (documentation-slot (find-if-not #'null direct-slots :key 'slot-definition-documentation)) (types (delete-duplicates (delete t (mapcar #'slot-definition-type direct-slots)) :test #'equal))) (make-effective-slot-definition class :name name :initform (if initer (slot-definition-initform initer) nil) :initfunction (if initer (slot-definition-initfunction initer) nil) :initargs (remove-duplicates (mapappend 'slot-definition-initargs direct-slots)) :allocation (slot-definition-allocation (car direct-slots)) :allocation-class (when (slot-boundp (car direct-slots) 'sys::allocation-class) ;;for some classes created in Java ;;(e.g. SimpleCondition) this slot is unbound (slot-definition-allocation-class (car direct-slots))) :type (cond ((null types) t) ((= 1 (length types)) types) (t (list* 'and types))) :documentation (if documentation-slot (documentation documentation-slot t) nil)))) ;;; Standard instance slot access ;;; N.B. The location of the effective-slots slots in the class metaobject for ;;; standard-class must be determined without making any further slot ;;; references. (defun find-slot-definition (class slot-name) (dolist (slot (class-slots class) nil) (when (eq slot-name (slot-definition-name slot)) (return slot)))) (defun slot-location (class slot-name) (let ((slot (find-slot-definition class slot-name))) (if slot (slot-definition-location slot) nil))) (defun instance-slot-location (instance slot-name) (let ((layout (std-instance-layout instance))) (and layout (layout-slot-location layout slot-name)))) (defun slot-value (object slot-name) (let* ((class (class-of object)) (metaclass (class-of class))) (if (or (eq metaclass +the-standard-class+) (eq metaclass +the-structure-class+) (eq metaclass +the-funcallable-standard-class+)) (std-slot-value object slot-name) (slot-value-using-class class object (find-slot-definition class slot-name))))) (defun %set-slot-value (object slot-name new-value) (let* ((class (class-of object)) (metaclass (class-of class))) (if (or (eq metaclass +the-standard-class+) (eq metaclass +the-structure-class+) (eq metaclass +the-funcallable-standard-class+)) (setf (std-slot-value object slot-name) new-value) (setf (slot-value-using-class class object (find-slot-definition class slot-name)) new-value)))) (defsetf slot-value %set-slot-value) (defun slot-boundp (object slot-name) (let ((class (class-of object))) (if (std-class-p class) (std-slot-boundp object slot-name) (slot-boundp-using-class class object (find-slot-definition class slot-name))))) (defun std-slot-makunbound (instance slot-name) (let ((location (instance-slot-location instance slot-name))) (cond ((fixnump location) (setf (standard-instance-access instance location) +slot-unbound+)) ((consp location) (setf (cdr location) +slot-unbound+)) (t (slot-missing (class-of instance) instance slot-name 'slot-makunbound)))) instance) (defun slot-makunbound (object slot-name) (let ((class (class-of object))) (if (std-class-p class) (std-slot-makunbound object slot-name) (slot-makunbound-using-class class object (find-slot-definition class slot-name))))) (defun std-slot-exists-p (instance slot-name) (not (null (find slot-name (class-slots (class-of instance)) :key 'slot-definition-name)))) (defun slot-exists-p (object slot-name) (let ((class (class-of object))) (if (std-class-p class) (std-slot-exists-p object slot-name) (slot-exists-p-using-class class object slot-name)))) (defun instance-slot-p (slot) (eq (slot-definition-allocation slot) :instance)) (defun std-allocate-instance (class) (sys::%std-allocate-instance class)) (defun allocate-funcallable-instance (class) (let ((instance (sys::%allocate-funcallable-instance class))) ;; KLUDGE: without this, the build fails with unbound-slot (when (or (eq class +the-standard-generic-function-class+) (subtypep class +the-standard-generic-function-class+)) (setf (std-slot-value instance 'sys::method-class) +the-standard-method-class+)) (set-funcallable-instance-function instance #'(lambda (&rest args) (declare (ignore args)) (error 'program-error "Called a funcallable-instance with unset function."))) instance)) (declaim (notinline class-prototype)) (defun class-prototype (class) (unless (class-finalized-p class) (error "Class ~A not finalized" (class-name class))) (std-allocate-instance class)) (defun maybe-finalize-class-subtree (class) (when (every #'class-finalized-p (class-direct-superclasses class)) (finalize-inheritance class) (dolist (subclass (class-direct-subclasses class)) (maybe-finalize-class-subtree subclass)))) (defun make-instance-standard-class (metaclass &rest initargs &key name direct-superclasses direct-slots direct-default-initargs documentation) (declare (ignore metaclass)) (let ((class (std-allocate-instance +the-standard-class+))) (unless *clos-booting* (check-initargs (list #'allocate-instance #'initialize-instance) (list* class initargs) class t initargs *make-instance-initargs-cache* 'make-instance)) (%set-class-name name class) ;; KLUDGE: necessary in define-primordial-class, otherwise ;; StandardClass.getClassLayout() throws an error (unless *clos-booting* (%set-class-layout nil class)) (%set-class-direct-subclasses () class) (%set-class-direct-methods () class) (%set-class-documentation class documentation) (std-after-initialization-for-classes class :direct-superclasses direct-superclasses :direct-slots direct-slots :direct-default-initargs direct-default-initargs) class)) (defun make-or-find-instance-funcallable-standard-class (metaclass &rest initargs &key name direct-superclasses direct-slots direct-default-initargs documentation) (declare (ignore metaclass initargs)) (or (find-class name nil) (let ((class (std-allocate-instance +the-funcallable-standard-class+))) (%set-class-name name class) (unless *clos-booting* (%set-class-layout nil class)) (%set-class-direct-subclasses () class) (%set-class-direct-methods () class) (%set-class-documentation class documentation) (std-after-initialization-for-classes class :direct-superclasses direct-superclasses :direct-slots direct-slots :direct-default-initargs direct-default-initargs) class))) ;(defun convert-to-direct-slot-definition (class canonicalized-slot) ; (apply #'make-instance ; (apply #'direct-slot-definition-class ; class canonicalized-slot) ; canonicalized-slot)) (defun canonicalize-direct-superclass-list (class direct-superclasses) (cond (direct-superclasses) ((subtypep (class-of class) +the-funcallable-standard-class+) (list +the-funcallable-standard-object-class+)) ((subtypep (class-of class) +the-standard-class+) (list +the-standard-object-class+)))) (defun std-after-initialization-for-classes (class &key direct-superclasses direct-slots direct-default-initargs &allow-other-keys) (let ((supers (canonicalize-direct-superclass-list class direct-superclasses))) (setf (class-direct-superclasses class) supers) (dolist (superclass supers) (add-direct-subclass superclass class))) (let ((slots (mapcar #'(lambda (slot-properties) (apply #'make-direct-slot-definition class slot-properties)) direct-slots))) (setf (class-direct-slots class) slots) (dolist (direct-slot slots) (dolist (reader (slot-definition-readers direct-slot)) (add-reader-method class reader direct-slot)) (dolist (writer (slot-definition-writers direct-slot)) (add-writer-method class writer direct-slot)))) (setf (class-direct-default-initargs class) direct-default-initargs) (maybe-finalize-class-subtree class) (values)) (defmacro define-primordial-class (name superclasses direct-slots) "Primitive class definition tool. No non-standard metaclasses, accessor methods, duplicate slots, non-existent superclasses, default initargs, or other complicated stuff. Handle with care." (let ((class (gensym))) `(let ((,class (make-instance-standard-class nil :name ',name :direct-superclasses ',(mapcar #'find-class superclasses) :direct-slots ,(canonicalize-direct-slots direct-slots)))) (%set-find-class ',name ,class) ,class))) (defmacro define-funcallable-primordial-class (name superclasses direct-slots) "Primitive funcallable class definition tool. No non-standard metaclasses, accessor methods, duplicate slots, non-existent superclasses, default initargs, or other complicated stuff. Handle with care. Will not modify existing classes to avoid breaking std-generic-function-p." (let ((class (gensym))) `(let ((,class (make-or-find-instance-funcallable-standard-class nil :name ',name :direct-superclasses ',(mapcar #'find-class superclasses) :direct-slots ,(canonicalize-direct-slots direct-slots)))) (%set-find-class ',name ,class) ,class))) (define-primordial-class eql-specializer (specializer) ((object :initform nil) (direct-methods :initform nil))) (define-primordial-class method-combination (metaobject) ((sys::name :initarg :name :initform nil) (sys::%documentation :initarg :documentation :initform nil) (options :initarg :options :initform nil))) (define-primordial-class short-method-combination (method-combination) ((operator :initarg :operator) (identity-with-one-argument :initarg :identity-with-one-argument))) (define-primordial-class long-method-combination (method-combination) ((sys::lambda-list :initarg :lambda-list) (method-group-specs :initarg :method-group-specs) (args-lambda-list :initarg :args-lambda-list) (generic-function-symbol :initarg :generic-function-symbol) (function :initarg :function) (arguments :initarg :arguments) (declarations :initarg :declarations) (forms :initarg :forms))) (define-primordial-class standard-accessor-method (standard-method) ((sys::%slot-definition :initarg :slot-definition :initform nil))) (define-primordial-class standard-reader-method (standard-accessor-method) ()) (defconstant +the-standard-reader-method-class+ (find-class 'standard-reader-method)) (define-primordial-class standard-writer-method (standard-accessor-method) ()) (defconstant +the-standard-writer-method-class+ (find-class 'standard-writer-method)) (define-primordial-class structure-class (class) ()) (defconstant +the-structure-class+ (find-class 'structure-class)) (define-primordial-class forward-referenced-class (class) ;; The standard-class layout. Not all of these slots are necessary, ;; but at least NAME and DIRECT-SUBCLASSES are. ((sys::name :initarg :name :initform nil) (sys::layout :initform nil) (sys::direct-superclasses :initform nil) (sys::direct-subclasses :initform nil) (sys::precedence-list :initform nil) (sys::direct-methods :initform nil) (sys::direct-slots :initform nil) (sys::slots :initform nil) (sys::direct-default-initargs :initform nil) (sys::default-initargs :initform nil) (sys::finalized-p :initform nil) (sys::%documentation :initform nil))) (defconstant +the-forward-referenced-class+ (find-class 'forward-referenced-class)) (define-funcallable-primordial-class generic-function (metaobject funcallable-standard-object) ()) (defvar *extensible-built-in-classes* (list (find-class 'sequence) (find-class 'java:java-object))) (defvar *make-instance-initargs-cache* (make-hash-table :test #'eq) "Cached sets of allowable initargs, keyed on the class they belong to.") (defvar *reinitialize-instance-initargs-cache* (make-hash-table :test #'eq) "Cached sets of allowable initargs, keyed on the class they belong to.") (defun expand-long-defcombin (name args) (destructuring-bind (lambda-list method-groups &rest body) args `(apply #'define-long-form-method-combination ',name ',lambda-list (list ,@(mapcar #'canonicalize-method-group-spec method-groups)) ',body))) ;;; The class method-combination and its subclasses are defined in ;;; StandardClass.java, but we cannot use make-instance and slot-value ;;; yet. (defun %make-long-method-combination (&key name documentation lambda-list method-group-specs args-lambda-list generic-function-symbol function arguments declarations forms) (let ((instance (std-allocate-instance (find-class 'long-method-combination)))) (setf (std-slot-value instance 'sys::name) name) (setf (std-slot-value instance 'sys:%documentation) documentation) (setf (std-slot-value instance 'sys::lambda-list) lambda-list) (setf (std-slot-value instance 'method-group-specs) method-group-specs) (setf (std-slot-value instance 'args-lambda-list) args-lambda-list) (setf (std-slot-value instance 'generic-function-symbol) generic-function-symbol) (setf (std-slot-value instance 'function) function) (setf (std-slot-value instance 'arguments) arguments) (setf (std-slot-value instance 'declarations) declarations) (setf (std-slot-value instance 'forms) forms) (setf (std-slot-value instance 'options) nil) instance)) (defun method-combination-name (method-combination) (check-type method-combination method-combination) (std-slot-value method-combination 'sys::name)) (defun method-combination-documentation (method-combination) (check-type method-combination method-combination) (std-slot-value method-combination 'sys:%documentation)) (defun short-method-combination-operator (method-combination) (check-type method-combination short-method-combination) (std-slot-value method-combination 'operator)) (defun short-method-combination-identity-with-one-argument (method-combination) (check-type method-combination short-method-combination) (std-slot-value method-combination 'identity-with-one-argument)) (defun long-method-combination-lambda-list (method-combination) (check-type method-combination long-method-combination) (std-slot-value method-combination 'sys::lambda-list)) (defun long-method-combination-method-group-specs (method-combination) (check-type method-combination long-method-combination) (std-slot-value method-combination 'method-group-specs)) (defun long-method-combination-args-lambda-list (method-combination) (check-type method-combination long-method-combination) (std-slot-value method-combination 'args-lambda-list)) (defun long-method-combination-generic-function-symbol (method-combination) (check-type method-combination long-method-combination) (std-slot-value method-combination 'generic-function-symbol)) (defun long-method-combination-function (method-combination) (check-type method-combination long-method-combination) (std-slot-value method-combination 'function)) (defun long-method-combination-arguments (method-combination) (check-type method-combination long-method-combination) (std-slot-value method-combination 'arguments)) (defun long-method-combination-declarations (method-combination) (check-type method-combination long-method-combination) (std-slot-value method-combination 'declarations)) (defun long-method-combination-forms (method-combination) (check-type method-combination long-method-combination) (std-slot-value method-combination 'forms)) (defun expand-short-defcombin (whole) (let* ((name (cadr whole)) (documentation (getf (cddr whole) :documentation "")) (identity-with-one-arg (getf (cddr whole) :identity-with-one-argument nil)) (operator (getf (cddr whole) :operator name))) `(progn (let ((instance (std-allocate-instance (find-class 'short-method-combination)))) (setf (std-slot-value instance 'sys::name) ',name) (setf (std-slot-value instance 'sys:%documentation) ',documentation) (setf (std-slot-value instance 'operator) ',operator) (setf (std-slot-value instance 'identity-with-one-argument) ',identity-with-one-arg) (setf (std-slot-value instance 'options) nil) (setf (get ',name 'method-combination-object) instance) ',name)))) (defmacro define-method-combination (&whole form name &rest args) (if (and (cddr form) (listp (caddr form))) (expand-long-defcombin name args) (expand-short-defcombin form))) (define-method-combination + :identity-with-one-argument t) (define-method-combination and :identity-with-one-argument t) (define-method-combination append :identity-with-one-argument nil) (define-method-combination list :identity-with-one-argument nil) (define-method-combination max :identity-with-one-argument t) (define-method-combination min :identity-with-one-argument t) (define-method-combination nconc :identity-with-one-argument t) (define-method-combination or :identity-with-one-argument t) (define-method-combination progn :identity-with-one-argument t) ;;; ;;; long form of define-method-combination (from Sacla and XCL) ;;; (defun method-group-p (selecter qualifiers) ;; selecter::= qualifier-pattern | predicate (etypecase selecter (list (or (equal selecter qualifiers) (let ((last (last selecter))) (when (eq '* (cdr last)) (let* ((prefix `(,@(butlast selecter) ,(car last))) (pos (mismatch prefix qualifiers))) (or (null pos) (= pos (length prefix)))))))) ((eql *) t) (symbol (funcall (symbol-function selecter) qualifiers)))) (defun check-variable-name (name) (flet ((valid-variable-name-p (name) (and (symbolp name) (not (constantp name))))) (assert (valid-variable-name-p name)))) (defun canonicalize-method-group-spec (spec) ;; spec ::= (name {qualifier-pattern+ | predicate} [[long-form-option]]) ;; long-form-option::= :description description | :order order | ;; :required required-p ;; a canonicalized-spec is a simple plist. (let* ((rest spec) (name (prog2 (check-variable-name (car rest)) (car rest) (setq rest (cdr rest)))) (option-names '(:description :order :required)) (selecters (let ((end (or (position-if #'(lambda (it) (member it option-names)) rest) (length rest)))) (prog1 (subseq rest 0 end) (setq rest (subseq rest end))))) (description (getf rest :description "")) (order (getf rest :order :most-specific-first)) (required-p (getf rest :required))) `(list :name ',name :predicate (lambda (qualifiers) (loop for item in ',selecters thereis (method-group-p item qualifiers))) :description ',description :order ',order :required ',required-p :*-selecter ,(equal selecters '(*))))) (defun extract-required-part (lambda-list) (flet ((skip (key lambda-list) (if (eq (first lambda-list) key) (cddr lambda-list) lambda-list))) (let* ((trimmed-lambda-list (skip '&environment (skip '&whole lambda-list))) (after-required-lambda-list (member-if #'(lambda (it) (member it lambda-list-keywords)) trimmed-lambda-list))) (if after-required-lambda-list (ldiff trimmed-lambda-list after-required-lambda-list) trimmed-lambda-list)))) (defun extract-specified-part (key lambda-list) (case key ((&eval &whole) (list (second (member key lambda-list)))) (t (let ((here (cdr (member key lambda-list)))) (ldiff here (member-if #'(lambda (it) (member it lambda-list-keywords)) here)))))) (defun extract-optional-part (lambda-list) (extract-specified-part '&optional lambda-list)) (defun parse-define-method-combination-args-lambda-list (lambda-list) ;; Define-method-combination Arguments Lambda Lists ;; http://www.lispworks.com/reference/HyperSpec/Body/03_dj.htm (let ((required (extract-required-part lambda-list)) (whole (extract-specified-part '&whole lambda-list)) (optional (extract-specified-part '&optional lambda-list)) (rest (extract-specified-part '&rest lambda-list)) (keys (extract-specified-part '&key lambda-list)) (aux (extract-specified-part '&aux lambda-list))) (values (first whole) required (mapcar #'(lambda (spec) (if (consp spec) `(,(first spec) ,(second spec) ,@(cddr spec)) `(,spec nil))) optional) (first rest) (mapcar #'(lambda (spec) (let ((key (if (consp spec) (car spec) spec)) (rest (when (consp spec) (rest spec)))) `(,(if (consp key) key `(,(make-keyword key) ,key)) ,(car rest) ,@(cdr rest)))) keys) (mapcar #'(lambda (spec) (if (consp spec) `(,(first spec) ,(second spec)) `(,spec nil))) aux)))) (defun wrap-with-call-method-macro (gf args-var emf-form) `(macrolet ((call-method (method &optional next-method-list) `(funcall ,(cond ((listp method) (assert (eq (first method) 'make-method)) ;; by generating an inline expansion we prevent allocation ;; of a method instance which will be discarded immediately ;; after reading the METHOD-FUNCTION slot (compute-method-function `(lambda (&rest ,(gensym)) ;; the MAKE-METHOD body form gets evaluated in ;; the null lexical environment augmented ;; with a binding for CALL-METHOD ,(wrap-with-call-method-macro ,gf ',args-var (second method))))) (t (method-function method))) ,',args-var ,(unless (null next-method-list) ;; by not generating an emf when there are no next methods, ;; we ensure next-method-p returns NIL (compute-effective-method ,gf (generic-function-method-combination ,gf) (process-next-method-list next-method-list)))))) ,emf-form)) (defun assert-unambiguous-method-sorting (group-name methods) (let ((specializers (make-hash-table :test 'equal))) (dolist (method methods) (push method (gethash (method-specializers method) specializers))) (loop for specializer-methods being each hash-value of specializers using (hash-key method-specializers) unless (= 1 (length specializer-methods)) do (error "Ambiguous method sorting in method group ~A due to multiple ~ methods with specializers ~S: ~S" group-name method-specializers specializer-methods)))) (defmacro with-method-groups (method-group-specs methods-form &body forms) (flet ((grouping-form (spec methods-var) (let ((predicate (coerce-to-function (getf spec :predicate))) (group (gensym)) (leftovers (gensym)) (method (gensym))) `(let ((,group '()) (,leftovers '())) (dolist (,method ,methods-var) (if (funcall ,predicate (method-qualifiers ,method)) (push ,method ,group) (push ,method ,leftovers))) (ecase ,(getf spec :order) (:most-specific-last ) (:most-specific-first (setq ,group (nreverse ,group)))) ,@(when (getf spec :required) `((when (null ,group) (error "Method group ~S must not be empty." ',(getf spec :name))))) (setq ,methods-var (nreverse ,leftovers)) ,group)))) (let ((rest (gensym)) (method (gensym))) `(let* ((,rest ,methods-form) ,@(mapcar #'(lambda (spec) `(,(getf spec :name) ,(grouping-form spec rest))) method-group-specs)) (dolist (,method ,rest) (invalid-method-error ,method "Method ~S with qualifiers ~S does not belong to any method group." ,method (method-qualifiers ,method))) ,@(unless (and (= 1 (length method-group-specs)) (getf (car method-group-specs) :*-selecter)) (mapcar #'(lambda (spec) `(assert-unambiguous-method-sorting ',(getf spec :name) ,(getf spec :name))) method-group-specs)) ,@forms)))) (defun method-combination-type-lambda-with-args-emf (&key args-lambda-list generic-function-symbol forms &allow-other-keys) (multiple-value-bind (whole required optional rest keys aux) (parse-define-method-combination-args-lambda-list args-lambda-list) (unless rest (when keys (setf rest (gensym)))) (let* ((gf-lambda-list (gensym)) (args-var (gensym)) (args-len-var (gensym)) (binding-forms (gensym)) (needs-args-len-var (gensym)) (emf-form (gensym))) `(let* ((,gf-lambda-list (slot-value ,generic-function-symbol 'sys::lambda-list)) (nreq (length (extract-required-part ,gf-lambda-list))) (nopt (length (extract-optional-part ,gf-lambda-list))) (,binding-forms) (,needs-args-len-var) (,emf-form (let* (,@(when whole `((,whole (progn (push `(,',whole ,',args-var) ,binding-forms) ',args-var)))) ,@(when rest ;; ### TODO: use a fresh symbol for the rest ;; binding being generated and pushed into binding-forms `((,rest (progn (push `(,',rest (subseq ,',args-var ,(+ nreq nopt))) ,binding-forms) ',rest)))) ,@(loop for var in required and i upfrom 0 for var-binding = (gensym) collect `(,var (when (< ,i nreq) (push `(,',var-binding (nth ,,i ,',args-var)) ,binding-forms) ',var-binding))) ,@(loop for (var initform supplied-var) in optional and i upfrom 0 for supplied-binding = (or supplied-var (gensym)) for var-binding = (gensym) ;; check for excess parameters ;; only assign initform if the parameter ;; isn't in excess: the spec says explicitly ;; to bind parameters in excess to forms evaluating ;; to nil. ;; This leaves initforms to be used with ;; parameters not supplied in excess, but ;; not available in the arguments list ;; ;; Also, if specified, bind "supplied-p" collect `(,supplied-binding (when (< ,i nopt) (setq ,needs-args-len-var t) ;; ### TODO: use a fresh symbol for the supplied binding ;; binding being generated and pushed into binding-forms (push `(,',supplied-binding (< ,(+ ,i nreq) ,',args-len-var)) ,binding-forms) ',supplied-binding)) collect `(,var (when (< ,i nopt) (push `(,',var-binding (if ,',supplied-binding (nth ,(+ ,i nreq) ,',args-var) ,',initform)) ,binding-forms) ',var-binding))) ,@(loop for ((key var) initform supplied-var) in keys for supplied-binding = (or supplied-var (gensym)) for var-binding = (gensym) ;; Same as optional parameters: ;; even though keywords can't be supplied in ;; excess, we should bind "supplied-p" in case ;; the key isn't supplied in the arguments list collect `(,supplied-binding (progn ;; ### TODO: use a fresh symbol for the rest ;; binding being generated and pushed into binding-forms (push `(,',supplied-binding (member ,',key ,',rest)) ,binding-forms) ',supplied-binding)) collect `(,var (progn (push `(,',var-binding (if ,',supplied-binding (cadr ,',supplied-binding) ,',initform)) ,binding-forms) ',var-binding))) ,@(loop for (var initform) in aux for var-binding = (gensym) collect `(,var (progn (push '(,var-binding ,initform) ,binding-forms) ',var-binding)))) ,@forms))) `(lambda (,',args-var) ;; set up bindings to ensure the expressions to which the ;; variables of the arguments option have been bound are ;; evaluated exactly once. (let* (,@(when ,needs-args-len-var `((,',args-len-var (length ,',args-var)))) ,@(reverse ,binding-forms)) ;; This is the lambda which *is* the effective method ;; hence gets called on every method invocation ;; be as efficient in this method as we can be ,(wrap-with-call-method-macro ,generic-function-symbol ',args-var ,emf-form))))))) (defun method-combination-type-lambda (&rest all-args &key name lambda-list args-lambda-list generic-function-symbol method-group-specs declarations forms &allow-other-keys) (declare (ignore name)) (let ((methods (gensym)) (args-var (gensym)) (emf-form (gensym))) `(lambda (,generic-function-symbol ,methods ,@lambda-list) ;; This is the lambda which computes the effective method ,@declarations (with-method-groups ,method-group-specs ,methods ,(if (null args-lambda-list) `(let ((,emf-form (progn ,@forms))) `(lambda (,',args-var) ;; This is the lambda which *is* the effective method ;; hence gets called on every method invocation ;; be as efficient in this method as we can be ,(wrap-with-call-method-macro ,generic-function-symbol ',args-var ,emf-form))) (apply #'method-combination-type-lambda-with-args-emf all-args)))))) (defun declarationp (expr) (and (consp expr) (eq (car expr) 'DECLARE))) (defun long-form-method-combination-args (args) ;; define-method-combination name lambda-list (method-group-specifier*) args ;; args ::= [(:arguments . args-lambda-list)] ;; [(:generic-function generic-function-symbol)] ;; [[declaration* | documentation]] form* (let ((rest args)) (labels ((nextp (key) (and (consp (car rest)) (eq key (caar rest)))) (args-lambda-list () (when (nextp :arguments) (prog1 (cdr (car rest)) (setq rest (cdr rest))))) (generic-function-symbol () (if (nextp :generic-function) (prog1 (second (car rest)) (setq rest (cdr rest))) (gensym))) (declaration* () (let ((end (position-if-not #'declarationp rest))) (when end (prog1 (subseq rest 0 end) (setq rest (nthcdr end rest)))))) (documentation? () (when (stringp (car rest)) (prog1 (car rest) (setq rest (cdr rest))))) (form* () rest)) (let ((declarations '())) `(:args-lambda-list ,(args-lambda-list) :generic-function-symbol ,(generic-function-symbol) :documentation ,(prog2 (setq declarations (declaration*)) (documentation?)) :declarations (,@declarations ,@(declaration*)) :forms ,(form*)))))) (defun define-long-form-method-combination (name lambda-list method-group-specs &rest args) (let* ((initargs `(:name ,name :lambda-list ,lambda-list :method-group-specs ,method-group-specs ,@(long-form-method-combination-args args))) (lambda-expression (apply #'method-combination-type-lambda initargs))) (setf (get name 'method-combination-object) (apply '%make-long-method-combination :function (coerce-to-function lambda-expression) initargs)) name)) (defun std-find-method-combination (gf name options) (declare (ignore gf)) (when (and (eql name 'standard) options) ;; CLHS DEFGENERIC (error "The standard method combination does not accept any arguments.")) (let ((mc (get name 'method-combination-object))) (cond ((null mc) (error "Method combination ~S not found" name)) ((null options) mc) ((typep mc 'short-method-combination) (make-instance 'short-method-combination :name name :documentation (method-combination-documentation mc) :operator (short-method-combination-operator mc) :identity-with-one-argument (short-method-combination-identity-with-one-argument mc) :options options)) ((typep mc 'long-method-combination) (make-instance 'long-method-combination :name name :documentation (method-combination-documentation mc) :lambda-list (long-method-combination-lambda-list mc) :method-group-specs (long-method-combination-method-group-specs mc) :args-lambda-list (long-method-combination-args-lambda-list mc) :generic-function-symbol (long-method-combination-generic-function-symbol mc) :function (long-method-combination-function mc) :arguments (long-method-combination-arguments mc) :declarations (long-method-combination-declarations mc) :forms (long-method-combination-forms mc) :options options))))) (declaim (notinline find-method-combination)) (defun find-method-combination (gf name options) (std-find-method-combination gf name options)) (defconstant +the-standard-method-combination+ (let ((instance (std-allocate-instance (find-class 'method-combination)))) (setf (std-slot-value instance 'sys::name) 'standard) (setf (std-slot-value instance 'sys:%documentation) "The standard method combination.") (setf (std-slot-value instance 'options) nil) instance) "The standard method combination. Do not use this object for identity since it changes between compile-time and run-time. To detect the standard method combination, compare the method combination name to the symbol 'standard.") (setf (get 'standard 'method-combination-object) +the-standard-method-combination+) (define-funcallable-primordial-class standard-generic-function (generic-function) ((sys::name :initarg :name :initform nil) (sys::lambda-list :initarg :lambda-list :initform nil) (sys::required-args :initarg :required-args :initform nil) (sys::optional-args :initarg :optional-args :initform nil) (sys::initial-methods :initarg :initial-methods :initform nil) (sys::methods :initarg :methods :initform nil) (sys::method-class :initarg :method-class :initform +the-standard-method-class+) (sys::%method-combination :initarg :method-combination :initform +the-standard-method-combination+) (sys::argument-precedence-order :initarg :argument-precedence-order :initform nil) (sys::declarations :initarg :declarations :initform nil) (sys::%documentation :initarg :documentation :initform nil))) (defconstant +the-standard-generic-function-class+ (find-class 'standard-generic-function)) (defun std-generic-function-p (gf) (eq (class-of gf) +the-standard-generic-function-class+)) (defparameter *eql-specializer-table* (make-hash-table :test 'eql)) (defun intern-eql-specializer (object) (or (gethash object *eql-specializer-table*) (setf (gethash object *eql-specializer-table*) ;; we will be called during generic function invocation ;; setup, so have to rely on plain functions here. (let ((instance (std-allocate-instance (find-class 'eql-specializer)))) (setf (std-slot-value instance 'object) object) (setf (std-slot-value instance 'direct-methods) nil) instance)))) (defun eql-specializer-object (eql-specializer) (check-type eql-specializer eql-specializer) (std-slot-value eql-specializer 'object)) ;;; Initial versions of some method metaobject readers. Defined on ;;; AMOP pg. 218ff, will be redefined when generic functions are set up. (defun std-method-function (method) (std-slot-value method 'sys::%function)) (defun std-method-generic-function (method) (std-slot-value method 'sys::%generic-function)) (defun std-method-specializers (method) (std-slot-value method 'sys::specializers)) (defun std-method-qualifiers (method) (std-slot-value method 'sys::qualifiers)) (defun std-accessor-method-slot-definition (accessor-method) (std-slot-value accessor-method 'sys::%slot-definition)) ;;; Additional method readers (defun std-method-fast-function (method) (std-slot-value method 'sys::fast-function)) (defun std-function-keywords (method) (values (std-slot-value method 'sys::keywords) (std-slot-value method 'sys::other-keywords-p))) ;;; Preliminary accessor definitions, will be redefined as generic ;;; functions later in this file (declaim (notinline method-generic-function)) (defun method-generic-function (method) (std-method-generic-function method)) (declaim (notinline method-function)) (defun method-function (method) (std-method-function method)) (declaim (notinline method-specializers)) (defun method-specializers (method) (std-method-specializers method)) (declaim (notinline method-qualifiers)) (defun method-qualifiers (method) (std-method-qualifiers method)) ;;; MOP (p. 216) specifies the following reader generic functions: ;;; generic-function-argument-precedence-order ;;; generic-function-declarations ;;; generic-function-lambda-list ;;; generic-function-method-class ;;; generic-function-method-combination ;;; generic-function-methods ;;; generic-function-name ;;; Additionally, we define the following reader functions: ;;; generic-function-required-arguments ;;; generic-function-optional-arguments ;;; These are defined as functions here and redefined as generic ;;; functions via atomic-defgeneric once we're all set up. (defun generic-function-name (gf) (std-slot-value gf 'sys::name)) (defun generic-function-lambda-list (gf) (std-slot-value gf 'sys::lambda-list)) (defun generic-function-methods (gf) (std-slot-value gf 'sys::methods)) (defun generic-function-method-class (gf) (std-slot-value gf 'sys::method-class)) (defun generic-function-method-combination (gf) (std-slot-value gf 'sys::%method-combination)) (defun generic-function-argument-precedence-order (gf) (std-slot-value gf 'sys::argument-precedence-order)) (defun generic-function-required-arguments (gf) (std-slot-value gf 'sys::required-args)) (defun generic-function-optional-arguments (gf) (std-slot-value gf 'sys::optional-args)) (defun (setf method-lambda-list) (new-value method) (setf (std-slot-value method 'sys::lambda-list) new-value)) (defun (setf method-qualifiers) (new-value method) (setf (std-slot-value method 'sys::qualifiers) new-value)) (defun method-documentation (method) (std-slot-value method 'sys:%documentation)) (defun (setf method-documentation) (new-value method) (setf (std-slot-value method 'sys:%documentation) new-value)) ;;; defgeneric (defmacro defgeneric (function-name lambda-list &rest options-and-method-descriptions) (let ((options ()) (methods ()) (declarations ()) (documentation nil)) (dolist (item options-and-method-descriptions) (case (car item) (declare (setf declarations (append declarations (cdr item)))) (:documentation (when documentation (error 'program-error :format-control "Documentation option was specified twice for generic function ~S." :format-arguments (list function-name))) (setf documentation t) (push item options)) (:method ;; KLUDGE (rudi 2013-04-02): this only works with subclasses ;; of standard-generic-function, since the initial-methods ;; slot is not mandated by AMOP (push `(push (defmethod ,function-name ,@(cdr item)) (std-slot-value (fdefinition ',function-name) 'sys::initial-methods)) methods)) (t (push item options)))) (when declarations (push (list :declarations declarations) options)) (setf options (nreverse options) methods (nreverse methods)) ;; Since DEFGENERIC currently shares its argument parsing with ;; DEFMETHOD, we perform this check here. (when (find '&aux lambda-list) (error 'program-error :format-control "&AUX is not allowed in a generic function lambda list: ~S" :format-arguments (list lambda-list))) `(prog1 (%defgeneric ',function-name :lambda-list ',lambda-list ,@(canonicalize-defgeneric-options options)) (sys::record-source-information-for-type ',function-name '(:generic-function ,function-name)) ,@methods))) (defun canonicalize-defgeneric-options (options) (mapappend #'canonicalize-defgeneric-option options)) (defun canonicalize-defgeneric-option (option) (case (car option) (:generic-function-class (list :generic-function-class `(find-class ',(cadr option)))) (:method-class (list :method-class `(find-class ',(cadr option)))) (:method-combination (list :method-combination `',(cdr option))) (:argument-precedence-order (list :argument-precedence-order `',(cdr option))) (t (list `',(car option) `',(cadr option))))) ;; From OpenMCL (called canonicalize-argument-precedence-order there, ;; but AMOP specifies argument-precedence-order to return a permutation ;; of the required arguments, not a list of indices, so we calculate ;; them on demand). (defun argument-precedence-order-indices (apo req) (cond ((equal apo req) nil) ((not (eql (length apo) (length req))) (error 'program-error :format-control "Specified argument precedence order ~S does not match lambda list." :format-arguments (list apo))) (t (let ((res nil)) (dolist (arg apo (nreverse res)) (let ((index (position arg req))) (if (or (null index) (memq index res)) (error 'program-error :format-control "Specified argument precedence order ~S does not match lambda list." :format-arguments (list apo))) (push index res))))))) (defun find-generic-function (name &optional (errorp t)) (let ((function (and (fboundp name) (fdefinition name)))) (when function (when (typep function 'generic-function) (return-from find-generic-function function)) (when (and *traced-names* (find name *traced-names* :test #'equal)) (setf function (untraced-function name)) (when (typep function 'generic-function) (return-from find-generic-function function))))) (if errorp (error "There is no generic function named ~S." name) nil)) (defun lambda-lists-congruent-p (lambda-list1 lambda-list2) (let* ((plist1 (analyze-lambda-list lambda-list1)) (args1 (getf plist1 :required-args)) (plist2 (analyze-lambda-list lambda-list2)) (args2 (getf plist2 :required-args))) (= (length args1) (length args2)))) (defun %defgeneric (function-name &rest all-keys) (when (fboundp function-name) (let ((gf (fdefinition function-name))) (when (typep gf 'standard-generic-function) ;; Remove methods defined by previous DEFGENERIC forms, as ;; specified by CLHS, 7.7 (Macro DEFGENERIC). KLUDGE: only ;; works for subclasses of standard-generic-function. Since ;; AMOP doesn't specify a reader for initial methods, we have to ;; skip this step otherwise. (dolist (method (std-slot-value gf 'sys::initial-methods)) (std-remove-method gf method) (map-dependents gf #'(lambda (dep) (update-dependent gf dep 'remove-method method)))) (setf (std-slot-value gf 'sys::initial-methods) '())))) (apply 'ensure-generic-function function-name all-keys)) ;;; Bootstrap version of ensure-generic-function, handling only ;;; standard-generic-function. This function is replaced later. (declaim (notinline ensure-generic-function)) (defun ensure-generic-function (function-name &rest all-keys &key (lambda-list nil lambda-list-supplied-p) (generic-function-class +the-standard-generic-function-class+) (method-class +the-standard-method-class+) (method-combination +the-standard-method-combination+ mc-p) argument-precedence-order (documentation nil documentation-supplied-p) &allow-other-keys) (setf all-keys (copy-list all-keys)) ; since we modify it (remf all-keys :generic-function-class) (let ((gf (find-generic-function function-name nil))) (if gf (progn (when lambda-list-supplied-p (unless (or (null (generic-function-methods gf)) (lambda-lists-congruent-p lambda-list (generic-function-lambda-list gf))) (error 'simple-error :format-control "The lambda list ~S is incompatible with the existing methods of ~S." :format-arguments (list lambda-list gf))) (setf (std-slot-value gf 'sys::lambda-list) lambda-list) (let* ((plist (analyze-lambda-list lambda-list)) (required-args (getf plist ':required-args))) (setf (std-slot-value gf 'sys::required-args) required-args) (setf (std-slot-value gf 'sys::optional-args) (getf plist :optional-args)))) (setf (std-slot-value gf 'sys::argument-precedence-order) (or argument-precedence-order (generic-function-required-arguments gf))) (when documentation-supplied-p (setf (std-slot-value gf 'sys::%documentation) documentation)) (finalize-standard-generic-function gf) gf) (progn (when (and (null *clos-booting*) (and (fboundp function-name) ;; since we're overwriting an autoloader, ;; we're probably meant to redefine it, ;; so throwing an error here might be a bad idea. ;; also, resolving the symbol isn't ;; a good option either: we've seen that lead to ;; recursive loading of the same file (and (not (autoloadp function-name)) (and (consp function-name) (eq 'setf (first function-name)) (not (autoload-ref-p (second function-name))))))) (error 'program-error :format-control "~A already names an ordinary function, macro, or special operator." :format-arguments (list function-name))) (when mc-p (error "Preliminary ensure-method does not support :method-combination argument.")) (apply #'make-instance-standard-generic-function generic-function-class :name function-name :method-class method-class :method-combination method-combination all-keys))))) (defun collect-eql-specializer-objects (generic-function) (let ((result nil)) (dolist (method (generic-function-methods generic-function)) (dolist (specializer (method-specializers method)) (when (typep specializer 'eql-specializer) (pushnew (eql-specializer-object specializer) result :test 'eql)))) result)) (defun finalize-standard-generic-function (gf) (%reinit-emf-cache gf (collect-eql-specializer-objects gf)) (set-funcallable-instance-function gf (if (std-generic-function-p gf) (std-compute-discriminating-function gf) (compute-discriminating-function gf))) ;; FIXME Do we need to warn on redefinition somewhere else? (let ((*warn-on-redefinition* nil)) (setf (fdefinition (generic-function-name gf)) gf)) (values)) (defun make-instance-standard-generic-function (generic-function-class &key name lambda-list (method-class +the-standard-method-class+) (method-combination +the-standard-method-combination+) argument-precedence-order declarations documentation) ;; to avoid circularities, we do not call generic functions in here. (declare (ignore generic-function-class)) (check-argument-precedence-order lambda-list argument-precedence-order) (let ((gf (allocate-funcallable-instance +the-standard-generic-function-class+))) (unless (classp method-class) (setf method-class (find-class method-class))) (unless (typep method-combination 'method-combination) (setf method-combination (find-method-combination gf (car method-combination) (cdr method-combination)))) (setf (std-slot-value gf 'sys::name) name) (setf (std-slot-value gf 'sys::lambda-list) lambda-list) (setf (std-slot-value gf 'sys::initial-methods) ()) (setf (std-slot-value gf 'sys::methods) ()) (setf (std-slot-value gf 'sys::method-class) method-class) (setf (std-slot-value gf 'sys::%method-combination) method-combination) (setf (std-slot-value gf 'sys::declarations) declarations) (setf (std-slot-value gf 'sys::%documentation) documentation) (let* ((plist (analyze-lambda-list (generic-function-lambda-list gf))) (required-args (getf plist ':required-args))) (setf (std-slot-value gf 'sys::required-args) required-args) (setf (std-slot-value gf 'sys::optional-args) (getf plist :optional-args)) (setf (std-slot-value gf 'sys::argument-precedence-order) (or argument-precedence-order required-args))) (finalize-standard-generic-function gf) gf)) (defun canonicalize-specializers (specializers) (mapcar #'canonicalize-specializer specializers)) (defun canonicalize-specializer (specializer) (cond ((classp specializer) specializer) ((typep specializer 'eql-specializer) specializer) ((symbolp specializer) (find-class specializer)) ((and (consp specializer) (eq (car specializer) 'eql)) (let ((object (cadr specializer))) (when (and (consp object) (eq (car object) 'quote)) (setf object (cadr object))) (intern-eql-specializer object))) ((and (consp specializer) (eq (car specializer) 'java:jclass)) (let ((jclass (eval specializer))) (java::ensure-java-class jclass))) (t (error "Unknown specializer: ~S" specializer)))) (defun parse-defmethod (args) (let ((function-name (car args)) (qualifiers ()) (specialized-lambda-list ()) (body ()) (parse-state :qualifiers)) (dolist (arg (cdr args)) (ecase parse-state (:qualifiers (if (and (atom arg) (not (null arg))) (push arg qualifiers) (progn (setf specialized-lambda-list arg) (setf parse-state :body)))) (:body (push arg body)))) (setf qualifiers (nreverse qualifiers) body (nreverse body)) (multiple-value-bind (real-body declarations documentation) (parse-body body) (values function-name qualifiers (extract-lambda-list specialized-lambda-list) (extract-specializer-names specialized-lambda-list) documentation declarations (list* 'block (fdefinition-block-name function-name) real-body))))) (defun required-portion (gf args) (let ((number-required (length (generic-function-required-arguments gf)))) (when (< (length args) number-required) (error 'program-error :format-control "Not enough arguments for generic function ~S." :format-arguments (list (generic-function-name gf)))) (subseq args 0 number-required))) (defun extract-lambda-list (specialized-lambda-list) (let* ((plist (analyze-lambda-list specialized-lambda-list)) (requireds (getf plist :required-names)) (rv (getf plist :rest-var)) (ks (getf plist :key-args)) (keysp (getf plist :keysp)) (aok (getf plist :allow-other-keys)) (opts (getf plist :optional-args)) (auxs (getf plist :auxiliary-args))) `(,@requireds ,@(if opts `(&optional ,@opts) ()) ,@(if rv `(&rest ,rv) ()) ,@(if (or ks keysp aok) `(&key ,@ks) ()) ,@(if aok '(&allow-other-keys) ()) ,@(if auxs `(&aux ,@auxs) ())))) (defun extract-specializer-names (specialized-lambda-list) (let ((plist (analyze-lambda-list specialized-lambda-list))) (getf plist ':specializers))) (defun get-keyword-from-arg (arg) (if (listp arg) (if (listp (car arg)) (caar arg) (make-keyword (car arg))) (make-keyword arg))) (defun analyze-lambda-list (lambda-list) (let ((keys ()) ; Just the keywords (key-args ()) ; Keywords argument specs (keysp nil) ; (required-names ()) ; Just the variable names (required-args ()) ; Variable names & specializers (specializers ()) ; Just the specializers (rest-var nil) (optionals ()) (auxs ()) (allow-other-keys nil) (state :required)) (dolist (arg lambda-list) (if (member arg lambda-list-keywords) (ecase arg (&optional (unless (eq state :required) (error 'program-error :format-control "~A followed by &OPTIONAL not allowed ~ in lambda list ~S" :format-arguments (list state lambda-list))) (setq state '&optional)) (&rest (unless (or (eq state :required) (eq state '&optional)) (error 'program-error :format-control "~A followed by &REST not allowed ~ in lambda list ~S" :format-arguments (list state lambda-list))) (setq state '&rest)) (&key (unless (or (eq state :required) (eq state '&optional) (eq state '&rest)) (error 'program-error :format-control "~A followed by &KEY not allowed in lambda list ~S" :format-arguments (list state lambda-list))) (setq keysp t) (setq state '&key)) (&allow-other-keys (unless (eq state '&key) (error 'program-error :format-control "&ALLOW-OTHER-KEYS not allowed while parsing ~A in lambda list ~S" :format-arguments (list state lambda-list))) (setq allow-other-keys 't)) (&aux ;; &aux comes last; any other previous state is fine (setq state '&aux))) (case state (:required (push-on-end arg required-args) (if (listp arg) (progn (push-on-end (car arg) required-names) (push-on-end (cadr arg) specializers)) (progn (push-on-end arg required-names) (push-on-end 't specializers)))) (&optional (push-on-end arg optionals)) (&rest (setq rest-var arg)) (&key (push-on-end (get-keyword-from-arg arg) keys) (push-on-end arg key-args)) (&aux (push-on-end arg auxs))))) (list :required-names required-names :required-args required-args :specializers specializers :rest-var rest-var :keywords keys :key-args key-args :keysp keysp :auxiliary-args auxs :optional-args optionals :allow-other-keys allow-other-keys))) #+nil (defun check-method-arg-info (gf arg-info method) (multiple-value-bind (nreq nopt keysp restp allow-other-keys-p keywords) (analyze-lambda-list (if (consp method) (early-method-lambda-list method) (method-lambda-list method))) (flet ((lose (string &rest args) (error 'program-error :format-control "~@" :format-arguments (list method gf string args))) (comparison-description (x y) (if (> x y) "more" "fewer"))) (let ((gf-nreq (arg-info-number-required arg-info)) (gf-nopt (arg-info-number-optional arg-info)) (gf-key/rest-p (arg-info-key/rest-p arg-info)) (gf-keywords (arg-info-keys arg-info))) (unless (= nreq gf-nreq) (lose "the method has ~A required arguments than the generic function." (comparison-description nreq gf-nreq))) (unless (= nopt gf-nopt) (lose "the method has ~A optional arguments than the generic function." (comparison-description nopt gf-nopt))) (unless (eq (or keysp restp) gf-key/rest-p) (lose "the method and generic function differ in whether they accept~_~ &REST or &KEY arguments.")) (when (consp gf-keywords) (unless (or (and restp (not keysp)) allow-other-keys-p (every (lambda (k) (memq k keywords)) gf-keywords)) (lose "the method does not accept each of the &KEY arguments~2I~_~ ~S." gf-keywords))))))) (defun check-method-lambda-list (name method-lambda-list gf-lambda-list) (let* ((gf-restp (not (null (memq '&rest gf-lambda-list)))) (gf-plist (analyze-lambda-list gf-lambda-list)) (gf-keysp (getf gf-plist :keysp)) (gf-keywords (getf gf-plist :keywords)) (method-plist (analyze-lambda-list method-lambda-list)) (method-restp (not (null (memq '&rest method-lambda-list)))) (method-keysp (getf method-plist :keysp)) (method-keywords (getf method-plist :keywords)) (method-allow-other-keys-p (getf method-plist :allow-other-keys))) (unless (= (length (getf gf-plist :required-args)) (length (getf method-plist :required-args))) (error "The method-lambda-list ~S ~ has the wrong number of required arguments ~ for the generic function ~S." method-lambda-list name)) (unless (= (length (getf gf-plist :optional-args)) (length (getf method-plist :optional-args))) (error "The method-lambda-list ~S ~ has the wrong number of optional arguments ~ for the generic function ~S." method-lambda-list name)) (unless (eq (or gf-restp gf-keysp) (or method-restp method-keysp)) (error "The method-lambda-list ~S ~ and the generic function ~S ~ differ in whether they accept &REST or &KEY arguments." method-lambda-list name)) (when (consp gf-keywords) (unless (or (and method-restp (not method-keysp)) method-allow-other-keys-p (every (lambda (k) (memq k method-keywords)) gf-keywords)) (error "The method-lambda-list ~S does not accept ~ all of the keyword arguments defined for the ~ generic function." method-lambda-list name))))) (defun check-argument-precedence-order (lambda-list argument-precedence-order) (when argument-precedence-order (if lambda-list ;; raising the required program-errors is a side-effect of ;; calculating the given permutation of apo vs req (argument-precedence-order-indices argument-precedence-order (getf (analyze-lambda-list lambda-list) :required-args)) ;; AMOP pg. 198 (error 'program-error "argument precedence order specified without lambda list")))) (defvar *gf-initialize-instance* nil "Cached value of the INITIALIZE-INSTANCE generic function. Initialized with the true value near the end of the file.") (defvar *gf-allocate-instance* nil "Cached value of the ALLOCATE-INSTANCE generic function. Initialized with the true value near the end of the file.") (defvar *gf-shared-initialize* nil "Cached value of the SHARED-INITIALIZE generic function. Initialized with the true value near the end of the file.") (defvar *gf-reinitialize-instance* nil "Cached value of the REINITIALIZE-INSTANCE generic function. Initialized with the true value near the end of the file.") (declaim (ftype (function * method) ensure-method)) (defun ensure-method (name &rest all-keys) (let* ((method-lambda-list (getf all-keys :lambda-list)) (gf (find-generic-function name nil)) (gf-lambda-list (copy-tree method-lambda-list))) (when (or (eq gf *gf-initialize-instance*) (eq gf *gf-allocate-instance*) (eq gf *gf-shared-initialize*) (eq gf *gf-reinitialize-instance*)) ;; ### Clearly, this can be targeted much more exact ;; as we only need to remove the specializing class and all ;; its subclasses from the hash. (clrhash *make-instance-initargs-cache*) (clrhash *reinitialize-instance-initargs-cache*)) (let ((plist (analyze-lambda-list method-lambda-list))) (when (getf plist :keywords) ;; remove all keywords arguments for the generic function definition (setf gf-lambda-list (append (subseq gf-lambda-list 0 (position '&key gf-lambda-list)) '(&key) (if (getf plist :auxiliary-args) (subseq gf-lambda-list (position '&aux gf-lambda-list))))))) (if gf (restart-case (check-method-lambda-list name method-lambda-list (generic-function-lambda-list gf)) (unbind-and-try-again () :report (lambda(s) (format s "Undefine generic function #'~a and continue" name)) (fmakunbound name) (setf gf (ensure-generic-function name :lambda-list gf-lambda-list)))) (setf gf (ensure-generic-function name :lambda-list gf-lambda-list))) (let ((method (if (eq (generic-function-method-class gf) +the-standard-method-class+) (apply #'make-instance-standard-method gf all-keys) (apply #'make-instance (generic-function-method-class gf) all-keys)))) (if (and (eq (generic-function-method-class gf) +the-standard-method-class+) (std-generic-function-p gf)) (progn (std-add-method gf method) (map-dependents gf #'(lambda (dep) (update-dependent gf dep 'add-method method)))) (add-method gf method)) method))) (defun make-instance-standard-method (gf &key lambda-list qualifiers specializers documentation function fast-function) (declare (ignore gf)) (let ((method (std-allocate-instance +the-standard-method-class+)) (analyzed-args (analyze-lambda-list lambda-list))) (setf (method-lambda-list method) lambda-list) (setf (method-qualifiers method) qualifiers) (setf (std-slot-value method 'sys::specializers) (canonicalize-specializers specializers)) (setf (method-documentation method) documentation) (setf (std-slot-value method 'sys::%generic-function) nil) ; set by add-method (setf (std-slot-value method 'sys::%function) function) (setf (std-slot-value method 'sys::fast-function) fast-function) (setf (std-slot-value method 'sys::keywords) (getf analyzed-args :keywords)) (setf (std-slot-value method 'sys::other-keywords-p) (getf analyzed-args :allow-other-keys)) method)) ;;; To be redefined as generic functions later (declaim (notinline add-direct-method)) (defun add-direct-method (specializer method) (if (typep specializer 'eql-specializer) (pushnew method (std-slot-value specializer 'direct-methods)) (pushnew method (class-direct-methods specializer)))) (declaim (notinline remove-direct-method)) (defun remove-direct-method (specializer method) (if (typep specializer 'eql-specializer) (setf (std-slot-value specializer 'direct-methods) (remove method (std-slot-value specializer 'direct-methods))) (setf (class-direct-methods specializer) (remove method (class-direct-methods specializer))))) (defun std-add-method (gf method) ;; calls sites need to make sure that method is either a method of the ;; given gf or does not have a gf. (let ((old-method (%find-method gf (std-method-qualifiers method) (method-specializers method) nil))) (when old-method (if (and (std-generic-function-p gf) (eq (class-of old-method) +the-standard-method-class+)) (std-remove-method gf old-method) (remove-method gf old-method)))) (setf (std-slot-value method 'sys::%generic-function) gf) (push method (std-slot-value gf 'sys::methods)) (dolist (specializer (method-specializers method)) (add-direct-method specializer method)) (finalize-standard-generic-function gf) gf) (defun std-remove-method (gf method) (setf (std-slot-value gf 'sys::methods) (remove method (generic-function-methods gf))) (setf (std-slot-value method 'sys::%generic-function) nil) (dolist (specializer (method-specializers method)) (remove-direct-method specializer method)) (finalize-standard-generic-function gf) gf) (defun %find-method (gf qualifiers specializers &optional (errorp t)) ;; "If the specializers argument does not correspond in length to the number ;; of required arguments of the generic-function, an an error of type ERROR ;; is signaled." (unless (= (length specializers) (length (generic-function-required-arguments gf))) (error "The specializers argument has length ~S, but ~S has ~S required parameters." (length specializers) gf (length (generic-function-required-arguments gf)))) (let* ((canonical-specializers (canonicalize-specializers specializers)) (method (find-if #'(lambda (method) (and (equal qualifiers (method-qualifiers method)) (equal canonical-specializers (method-specializers method)))) (generic-function-methods gf)))) (if (and (null method) errorp) (error "No such method for ~S." (generic-function-name gf)) method))) (defun fast-callable-p (gf) (and (eq (method-combination-name (generic-function-method-combination gf)) 'standard) (null (intersection (generic-function-lambda-list gf) '(&rest &optional &key &allow-other-keys &aux))))) (defun std-compute-discriminating-function (gf) ;; In this function, we know that gf is of class ;; standard-generic-function, so we can access the instance's slots ;; via std-slot-value. This breaks circularities when redefining ;; generic function accessors. (let ((methods (std-slot-value gf 'sys::methods))) (cond ((and (= (length methods) 1) (eq (type-of (car methods)) 'standard-reader-method) (eq (type-of (car (std-method-specializers (car methods)))) 'standard-class)) (let* ((method (first methods)) (slot-definition (std-slot-value method 'sys::%slot-definition)) (slot-name (std-slot-value slot-definition 'sys:name)) (class (car (std-method-specializers method)))) #'(lambda (instance) ;; TODO: elide this test for low values of SAFETY (unless (typep instance class) (no-applicable-method gf (list instance))) ;; hash table lookup for slot position in Layout object via ;; StandardObject.SLOT_VALUE, so should be reasonably fast (std-slot-value instance slot-name)))) ((and (= (length methods) 1) (eq (type-of (car methods)) 'standard-writer-method) (eq (type-of (second (std-method-specializers (car methods)))) 'standard-class)) (let* ((method (first methods)) (slot-definition (std-slot-value method 'sys::%slot-definition)) (slot-name (std-slot-value slot-definition 'sys:name)) (class (car (std-method-specializers method)))) #'(lambda (new-value instance) ;; TODO: elide this test for low values of SAFETY (unless (typep instance class) (no-applicable-method gf (list new-value instance))) ;; hash table lookup for slot position in Layout object via ;; StandardObject.SET_SLOT_VALUE, so should be reasonably fast (setf (std-slot-value instance slot-name) new-value)))) (t (let* ((number-required (length (generic-function-required-arguments gf))) (lambda-list (generic-function-lambda-list gf)) (exact (null (intersection lambda-list '(&rest &optional &key &allow-other-keys)))) (no-aux (null (some (lambda (method) (find '&aux (std-slot-value method 'sys::lambda-list))) methods)))) (if (and exact no-aux) (cond ((= number-required 1) (cond ((and (eq (method-combination-name (std-slot-value gf 'sys::%method-combination)) 'standard) (= (length methods) 1) (std-method-fast-function (%car methods))) (let* ((method (%car methods)) (specializer (car (std-method-specializers method))) (function (std-method-fast-function method))) (if (typep specializer 'eql-specializer) (let ((specializer-object (eql-specializer-object specializer))) #'(lambda (arg) (declare (optimize speed)) (if (eql arg specializer-object) (funcall function arg) (no-applicable-method gf (list arg))))) #'(lambda (arg) (declare (optimize speed)) (unless (simple-typep arg specializer) ;; FIXME no applicable method (error 'simple-type-error :datum arg :expected-type specializer)) (funcall function arg))))) (t #'(lambda (arg) (declare (optimize speed)) (let* ((args (list arg)) (emfun (get-cached-emf gf args))) (if emfun (funcall emfun args) (slow-method-lookup gf args))))))) ((= number-required 2) #'(lambda (arg1 arg2) (declare (optimize speed)) (let* ((args (list arg1 arg2)) (emfun (get-cached-emf gf args))) (if emfun (funcall emfun args) (slow-method-lookup gf args))))) ((= number-required 3) #'(lambda (arg1 arg2 arg3) (declare (optimize speed)) (let* ((args (list arg1 arg2 arg3)) (emfun (get-cached-emf gf args))) (if emfun (funcall emfun args) (slow-method-lookup gf args))))) (t #'(lambda (&rest args) (declare (optimize speed)) (let ((len (length args))) (unless (= len number-required) (error 'program-error :format-control "Not enough arguments for generic function ~S." :format-arguments (list (generic-function-name gf))))) (let ((emfun (get-cached-emf gf args))) (if emfun (funcall emfun args) (slow-method-lookup gf args)))))) #'(lambda (&rest args) (declare (optimize speed)) (let ((len (length args))) (unless (>= len number-required) (error 'program-error :format-control "Not enough arguments for generic function ~S." :format-arguments (list (generic-function-name gf))))) (let ((emfun (get-cached-emf gf args))) (if emfun (funcall emfun args) (slow-method-lookup gf args)))))))))) (defun sort-methods (methods gf required-classes) (if (or (null methods) (null (%cdr methods))) methods (sort methods (if (std-generic-function-p gf) (let ((method-indices (argument-precedence-order-indices (generic-function-argument-precedence-order gf) (getf (analyze-lambda-list (generic-function-lambda-list gf)) ':required-args)))) #'(lambda (m1 m2) (std-method-more-specific-p m1 m2 required-classes method-indices))) #'(lambda (m1 m2) (method-more-specific-p gf m1 m2 required-classes)))))) (defun method-applicable-p (method args) (do* ((specializers (method-specializers method) (cdr specializers)) (args args (cdr args))) ((null specializers) t) (let ((specializer (car specializers))) (if (typep specializer 'eql-specializer) (unless (eql (car args) (eql-specializer-object specializer)) (return nil)) (unless (subclassp (class-of (car args)) specializer) (return nil)))))) (defun std-compute-applicable-methods (gf args) (let ((required-classes (mapcar #'class-of (required-portion gf args))) (methods '())) (dolist (method (generic-function-methods gf)) (when (method-applicable-p method args) (push method methods))) (sort-methods methods gf required-classes))) (declaim (notinline compute-applicable-methods)) (defun compute-applicable-methods (gf args) (std-compute-applicable-methods gf args)) ;;; METHOD-APPLICABLE-USING-CLASSES-P ;;; ;;; If the first return value is T, METHOD is definitely applicable to ;;; arguments that are instances of CLASSES. If the first value is ;;; NIL and the second value is T, METHOD is definitely not applicable ;;; to arguments that are instances of CLASSES; if the second value is ;;; NIL the applicability of METHOD cannot be determined by inspecting ;;; the classes of its arguments only. ;;; (defun method-applicable-using-classes-p (method classes) (do* ((specializers (method-specializers method) (cdr specializers)) (classes classes (cdr classes)) (knownp t)) ((null specializers) (if knownp (values t t) (values nil nil))) (let ((specializer (car specializers))) (if (typep specializer 'eql-specializer) (if (eql (class-of (eql-specializer-object specializer)) (car classes)) (setf knownp nil) (return (values nil t))) (unless (subclassp (car classes) specializer) (return (values nil t))))))) (defun check-applicable-method-keyword-args (gf args keyword-args applicable-keywords) (when (oddp (length keyword-args)) (error 'program-error :format-control "Odd number of keyword arguments in call to ~S ~ with arguments list ~S" :format-arguments (list gf args))) (unless (getf keyword-args :allow-other-keys) (loop for key in keyword-args by #'cddr unless (or (member key applicable-keywords) (eq key :allow-other-keys)) do (error 'program-error :format-control "Invalid keyword argument ~S in call ~ to ~S with argument list ~S." :format-arguments (list key gf args))))) (defun compute-applicable-keywords (gf applicable-methods) (let ((applicable-keywords (getf (analyze-lambda-list (generic-function-lambda-list gf)) :keywords))) (loop for method in applicable-methods do (multiple-value-bind (keywords allow-other-keys) (function-keywords method) (when allow-other-keys (setf applicable-keywords :any) (return)) (setf applicable-keywords (union applicable-keywords keywords)))) applicable-keywords)) (defun wrap-emfun-for-keyword-args-check (gf emfun non-keyword-args applicable-keywords) #'(lambda (args) (check-applicable-method-keyword-args gf args (nthcdr non-keyword-args args) applicable-keywords) (funcall emfun args))) (defun slow-method-lookup (gf args) (let ((applicable-methods (if (std-generic-function-p gf) (std-compute-applicable-methods gf args) (or (compute-applicable-methods-using-classes gf (mapcar #'class-of args)) (compute-applicable-methods gf args))))) (if applicable-methods (let* ((emfun (funcall (if (std-generic-function-p gf) #'std-compute-effective-method #'compute-effective-method) gf (generic-function-method-combination gf) applicable-methods)) (non-keyword-args (+ (length (generic-function-required-arguments gf)) (length (generic-function-optional-arguments gf)))) (gf-lambda-list (generic-function-lambda-list gf)) (checks-required (and (member '&key gf-lambda-list) (not (member '&allow-other-keys gf-lambda-list)))) (applicable-keywords (when checks-required ;; Don't do applicable keyword checks when this is ;; one of the 'exceptional four' or when the gf allows ;; other keywords. (compute-applicable-keywords gf applicable-methods)))) (when (and checks-required (not (eq applicable-keywords :any))) (setf emfun (wrap-emfun-for-keyword-args-check gf emfun non-keyword-args applicable-keywords))) (cache-emf gf args emfun) (funcall emfun args)) (apply #'no-applicable-method gf args)))) (defun sub-specializer-p (c1 c2 c-arg) (find c2 (cdr (memq c1 (%class-precedence-list c-arg))))) (defun std-method-more-specific-p (method1 method2 required-classes argument-precedence-order) (if argument-precedence-order (let ((specializers-1 (std-method-specializers method1)) (specializers-2 (std-method-specializers method2))) (dolist (index argument-precedence-order) (let ((spec1 (nth index specializers-1)) (spec2 (nth index specializers-2))) (unless (eq spec1 spec2) (cond ((typep spec1 'eql-specializer) (return t)) ((typep spec2 'eql-specializer) (return nil)) (t (return (sub-specializer-p spec1 spec2 (nth index required-classes))))))))) (do ((specializers-1 (std-method-specializers method1) (cdr specializers-1)) (specializers-2 (std-method-specializers method2) (cdr specializers-2)) (classes required-classes (cdr classes))) ((null specializers-1) nil) (let ((spec1 (car specializers-1)) (spec2 (car specializers-2))) (unless (eq spec1 spec2) (cond ((typep spec1 'eql-specializer) (return t)) ((typep spec2 'eql-specializer) (return nil)) (t (return (sub-specializer-p spec1 spec2 (car classes)))))))))) (defun primary-method-p (method) (null (intersection '(:before :after :around) (method-qualifiers method)))) (defun before-method-p (method) (equal '(:before) (method-qualifiers method))) (defun after-method-p (method) (equal '(:after) (method-qualifiers method))) (defun around-method-p (method) (equal '(:around) (method-qualifiers method))) (defun process-next-method-list (next-method-list) (mapcar #'(lambda (next-method-form) (cond ((listp next-method-form) (assert (eq (first next-method-form) 'make-method)) (let* ((rest-sym (gensym))) (make-instance-standard-method nil ;; ignored :lambda-list (list '&rest rest-sym) :function (compute-method-function `(lambda (&rest ,rest-sym) ,(second next-method-form)))))) (t (assert (typep next-method-form 'method)) next-method-form))) next-method-list)) (defun std-compute-effective-method (gf method-combination methods) (assert (typep method-combination 'method-combination)) (let* ((mc-name (method-combination-name method-combination)) (options (slot-value method-combination 'options)) (order (car options)) (primaries '()) (arounds '()) around emf-form (long-method-combination-p (typep method-combination 'long-method-combination))) (unless long-method-combination-p (dolist (m methods) (let ((qualifiers (method-qualifiers m))) (cond ((null qualifiers) (if (eq mc-name 'standard) (push m primaries) (error "Method combination type mismatch: missing qualifier for method combination ~S." method-combination))) ((cdr qualifiers) (error "Invalid method qualifiers.")) ((eq (car qualifiers) :around) (push m arounds)) ((eq (car qualifiers) mc-name) (push m primaries)) ((memq (car qualifiers) '(:before :after))) (t (error "Invalid method qualifiers.")))))) (unless (eq order :most-specific-last) (setf primaries (nreverse primaries))) (setf arounds (nreverse arounds)) (setf around (car arounds)) (when (and (null primaries) (not long-method-combination-p)) (error "No primary methods for the generic function ~S." gf)) (cond (around (let ((next-emfun (funcall (if (std-generic-function-p gf) #'std-compute-effective-method #'compute-effective-method) gf method-combination (remove around methods)))) (setf emf-form (generate-emf-lambda (method-function around) next-emfun)))) ((eq mc-name 'standard) (let* ((next-emfun (compute-primary-emfun (cdr primaries))) (befores (remove-if-not #'before-method-p methods)) (reverse-afters (reverse (remove-if-not #'after-method-p methods)))) (setf emf-form (cond ((and (null befores) (null reverse-afters)) (let ((fast-function (std-method-fast-function (car primaries)))) (if fast-function (ecase (length (generic-function-required-arguments gf)) (1 #'(lambda (args) (declare (optimize speed)) (funcall fast-function (car args)))) (2 #'(lambda (args) (declare (optimize speed)) (funcall fast-function (car args) (cadr args))))) (generate-emf-lambda (std-method-function (car primaries)) next-emfun)))) (t (let ((method-function (method-function (car primaries)))) #'(lambda (args) (declare (optimize speed)) (dolist (before befores) (funcall (method-function before) args nil)) (multiple-value-prog1 (funcall method-function args next-emfun) (dolist (after reverse-afters) (funcall (method-function after) args nil)))))))))) (long-method-combination-p (let ((function (long-method-combination-function method-combination)) (arguments (slot-value method-combination 'options))) (assert function) (setf emf-form (if arguments (apply function gf methods arguments) (funcall function gf methods))))) (t (unless (typep method-combination 'short-method-combination) (error "Unsupported method combination type ~A." mc-name)) (let ((operator (short-method-combination-operator method-combination)) (ioa (short-method-combination-identity-with-one-argument method-combination))) (setf emf-form (if (and ioa (null (cdr primaries))) (generate-emf-lambda (method-function (car primaries)) nil) `(lambda (args) (,operator ,@(mapcar (lambda (primary) `(funcall ,(method-function primary) args nil)) primaries)))))))) (assert (not (null emf-form))) (or #+nil (ignore-errors (autocompile emf-form)) (coerce-to-function emf-form)))) (defun generate-emf-lambda (method-function next-emfun) #'(lambda (args) (declare (optimize speed)) (funcall method-function args next-emfun))) ;;; compute an effective method function from a list of primary methods: (defun compute-primary-emfun (methods) (if (null methods) nil (let ((next-emfun (compute-primary-emfun (cdr methods)))) #'(lambda (args) (funcall (std-method-function (car methods)) args next-emfun))))) (defvar *call-next-method-p*) (defvar *next-method-p-p*) ;;; FIXME this doesn't work for macroized references (defun walk-form (form) (cond ((atom form) (cond ((eq form 'call-next-method) (setf *call-next-method-p* t)) ((eq form 'next-method-p) (setf *next-method-p-p* t)))) (t (walk-form (%car form)) (walk-form (%cdr form))))) (defmacro flet-call-next-method (args next-emfun &body body) `(flet ((call-next-method (&rest cnm-args) (if (null ,next-emfun) (error "No next method for generic function.") (funcall ,next-emfun (or cnm-args ,args)))) (next-method-p () (not (null ,next-emfun)))) (declare (ignorable (function call-next-method) (function next-method-p))) ,@body)) (defun compute-method-function (lambda-expression) (let ((lambda-list (allow-other-keys (cadr lambda-expression))) (body (cddr lambda-expression))) (multiple-value-bind (body declarations) (parse-body body) (let ((ignorable-vars '())) (dolist (var lambda-list) (if (memq var lambda-list-keywords) (return) (push var ignorable-vars))) (push `(declare (ignorable ,@ignorable-vars)) declarations)) (if (null (intersection lambda-list '(&rest &optional &key &allow-other-keys &aux))) ;; Required parameters only. (case (length lambda-list) (1 `(lambda (args next-emfun) (let ((,(%car lambda-list) (%car args))) (declare (ignorable ,(%car lambda-list))) ,@declarations (flet-call-next-method args next-emfun ,@body)))) (2 `(lambda (args next-emfun) (let ((,(%car lambda-list) (%car args)) (,(%cadr lambda-list) (%cadr args))) (declare (ignorable ,(%car lambda-list) ,(%cadr lambda-list))) ,@declarations (flet-call-next-method args next-emfun ,@body)))) (3 `(lambda (args next-emfun) (let ((,(%car lambda-list) (%car args)) (,(%cadr lambda-list) (%cadr args)) (,(%caddr lambda-list) (%caddr args))) (declare (ignorable ,(%car lambda-list) ,(%cadr lambda-list) ,(%caddr lambda-list))) ,@declarations (flet-call-next-method args next-emfun ,@body)))) (t `(lambda (args next-emfun) (apply #'(lambda ,lambda-list ,@declarations (flet-call-next-method args next-emfun ,@body)) args)))) `(lambda (args next-emfun) (apply #'(lambda ,lambda-list ,@declarations (flet-call-next-method args next-emfun ,@body)) args)))))) (defun compute-method-fast-function (lambda-expression) (let ((lambda-list (allow-other-keys (cadr lambda-expression)))) (when (intersection lambda-list '(&rest &optional &key &allow-other-keys &aux)) (return-from compute-method-fast-function nil)) ;; Only required args. (let ((body (cddr lambda-expression)) (*call-next-method-p* nil) (*next-method-p-p* nil)) (multiple-value-bind (body declarations) (parse-body body) ;;; N.b. The WALK-FORM check is bogus for "hidden" ;;; macroizations of CALL-NEXT-METHOD and NEXT-METHOD-P but ;;; the presence of FAST-FUNCTION slots in our CLOS is ;;; currently necessary to bootstrap CLOS in a way I didn't ;;; manage to easily untangle. (walk-form body) (when (or *call-next-method-p* *next-method-p-p*) (return-from compute-method-fast-function nil)) (let ((declaration `(declare (ignorable ,@lambda-list)))) ;;; 2020-10-19 refactored this expression from previous code ;;; that was only declaring a fast function for one or two ;;; element values of lamba-list (if (< 0 (length lambda-list) 3) `(lambda ,(cadr lambda-expression) ,declaration (flet ((call-next-method (&rest args) (declare (ignore args)) (error "No next method for generic function")) (next-method-p () nil)) (declare (ignorable (function call-next-method) (function next-method-p))) ,@body)) nil)))))) (declaim (notinline make-method-lambda)) (defun make-method-lambda (generic-function method lambda-expression env) (declare (ignore generic-function method env)) (values (compute-method-function lambda-expression) nil)) ;; From CLHS section 7.6.5: ;; "When a generic function or any of its methods mentions &key in a lambda ;; list, the specific set of keyword arguments accepted by the generic function ;; varies according to the applicable methods. The set of keyword arguments ;; accepted by the generic function for a particular call is the union of the ;; keyword arguments accepted by all applicable methods and the keyword ;; arguments mentioned after &key in the generic function definition, if any." ;; Adapted from Sacla. (defun allow-other-keys (lambda-list) (if (and (member '&key lambda-list) (not (member '&allow-other-keys lambda-list))) (let* ((key-end (or (position '&aux lambda-list) (length lambda-list))) (aux-part (subseq lambda-list key-end))) `(,@(subseq lambda-list 0 key-end) &allow-other-keys ,@aux-part)) lambda-list)) (defmacro defmethod (&rest args &environment env) (multiple-value-bind (function-name qualifiers lambda-list specializers documentation declarations body) (parse-defmethod args) (let* ((specializers-form '()) (lambda-expression `(lambda ,lambda-list ,@declarations ,body)) (gf (or (find-generic-function function-name nil) (class-prototype (find-class 'standard-generic-function)))) (method-function (make-method-lambda gf (class-prototype (generic-function-method-class gf)) lambda-expression env)) (fast-function (compute-method-fast-function lambda-expression)) ) (dolist (specializer specializers) (cond ((and (consp specializer) (eq (car specializer) 'eql)) (push `(list 'eql ,(cadr specializer)) specializers-form)) (t (push `',specializer specializers-form)))) (setf specializers-form `(list ,@(nreverse specializers-form))) `(progn (sys::record-source-information-for-type ',function-name '(:method ,function-name ,qualifiers ,specializers)) (ensure-method ',function-name :lambda-list ',lambda-list :qualifiers ',qualifiers :specializers (canonicalize-specializers ,specializers-form) ,@(when documentation `(:documentation ,documentation)) :function (function ,method-function) ,@(when fast-function `(:fast-function (function ,fast-function))) ))))) ;;; Reader and writer methods (defun make-instance-standard-accessor-method (method-class &key lambda-list qualifiers specializers documentation function fast-function slot-definition) (let ((method (std-allocate-instance method-class))) (setf (method-lambda-list method) lambda-list) (setf (method-qualifiers method) qualifiers) (setf (std-slot-value method 'sys::specializers) (canonicalize-specializers specializers)) (setf (method-documentation method) documentation) (setf (std-slot-value method 'sys::%generic-function) nil) (setf (std-slot-value method 'sys::%function) function) (setf (std-slot-value method 'sys::fast-function) fast-function) (setf (std-slot-value method 'sys::%slot-definition) slot-definition) (setf (std-slot-value method 'sys::keywords) nil) (setf (std-slot-value method 'sys::other-keywords-p) nil) method)) (defun add-reader-method (class function-name slot-definition) (let* ((slot-name (slot-definition-name slot-definition)) (lambda-expression (if (std-class-p class) `(lambda (object) (std-slot-value object ',slot-name)) `(lambda (object) (slot-value object ',slot-name)))) (method-function (compute-method-function lambda-expression)) (fast-function (compute-method-fast-function lambda-expression)) (method-lambda-list '(object)) (gf (find-generic-function function-name nil)) (initargs `(:lambda-list ,method-lambda-list :qualifiers () :specializers (,class) :function ,(if (autoloadp 'compile) method-function (autocompile method-function)) :fast-function ,(if (autoloadp 'compile) fast-function (autocompile fast-function)) :slot-definition ,slot-definition)) (method-class (if (std-class-p class) +the-standard-reader-method-class+ (apply #'reader-method-class class slot-definition initargs)))) ;; required by AMOP pg. 225 (assert (subtypep method-class +the-standard-reader-method-class+)) (if gf (check-method-lambda-list function-name method-lambda-list (generic-function-lambda-list gf)) (setf gf (ensure-generic-function function-name :lambda-list method-lambda-list))) (let ((method (if (eq method-class +the-standard-reader-method-class+) (apply #'make-instance-standard-accessor-method method-class initargs) (apply #'make-instance method-class :generic-function nil ; handled by add-method initargs)))) (if (std-generic-function-p gf) (progn (std-add-method gf method) (map-dependents gf #'(lambda (dep) (update-dependent gf dep 'add-method method)))) (add-method gf method)) (sys::record-source-information-for-type function-name `(:slot-reader ,function-name ,(class-name class))) method))) (defun add-writer-method (class function-name slot-definition) (let* ((slot-name (slot-definition-name slot-definition)) (lambda-expression (if (std-class-p class) `(lambda (new-value object) (setf (std-slot-value object ',slot-name) new-value)) `(lambda (new-value object) (setf (slot-value object ',slot-name) new-value)))) (method-function (compute-method-function lambda-expression)) (fast-function (compute-method-fast-function lambda-expression)) (method-lambda-list '(new-value object)) (gf (find-generic-function function-name nil)) (initargs `(:lambda-list ,method-lambda-list :qualifiers () :specializers (,+the-T-class+ ,class) :function ,(if (autoloadp 'compile) method-function (autocompile method-function)) :fast-function ,(if (autoloadp 'compile) fast-function (autocompile fast-function)) :slot-definition ,slot-definition)) (method-class (if (std-class-p class) +the-standard-writer-method-class+ (apply #'writer-method-class class slot-definition initargs)))) ;; required by AMOP pg. 242 (assert (subtypep method-class +the-standard-writer-method-class+)) (if gf (check-method-lambda-list function-name method-lambda-list (generic-function-lambda-list gf)) (setf gf (ensure-generic-function function-name :lambda-list method-lambda-list))) (let ((method (if (eq method-class +the-standard-writer-method-class+) (apply #'make-instance-standard-accessor-method method-class initargs) (apply #'make-instance method-class :generic-function nil ; handled by add-method initargs)))) (if (std-generic-function-p gf) (progn (std-add-method gf method) (map-dependents gf #'(lambda (dep) (update-dependent gf dep 'add-method method)))) (add-method gf method)) (sys::record-source-information-for-type function-name `(:slot-writer ,function-name ,(class-name class))) method))) (defmacro atomic-defgeneric (function-name &rest rest) "Macro to define a generic function and 'swap it into place' after it's been fully defined with all its methods. Note: the user should really use the (:method ..) method description way of defining methods; there's not much use in atomically defining generic functions without providing sensible behaviour." (let ((temp-sym (gensym))) `(progn (defgeneric ,temp-sym ,@rest) (sys::record-source-information-for-type ',function-name '(:generic-function ,function-name)) ,@(loop for method-form in rest when (eq (car method-form) :method) collect (multiple-value-bind (function-name qualifiers lambda-list specializers documentation declarations body) (mop::parse-defmethod `(,function-name ,@(rest method-form))) `(sys::record-source-information-for-type ',function-name '(:method ,function-name ,qualifiers ,specializers)))) (let ((gf (symbol-function ',temp-sym))) ;; FIXME (rudi 2012-07-08): fset gets the source location info ;; to charpos 23 always (but (setf fdefinition) leaves the ;; outdated source position in place, which is even worse). (fset ',function-name gf) (setf (std-slot-value gf 'sys::name) ',function-name) (fmakunbound ',temp-sym) gf)))) (defmacro redefine-class-forwarder (name slot &optional body-alist) "Define a generic function on a temporary symbol as an accessor for the slot `slot'. Then, when definition is complete (including allocation of methods), swap the definition in place. `body-alist' can be used to override the default method bodies for given metaclasses. In substitute method bodies, `class' names the class instance and, for setters, `new-value' the new value." (let* ((setterp (consp name)) (%name (intern (concatenate 'string "%" (if setterp (symbol-name 'set-) "") (symbol-name (if setterp (cadr name) name))) (find-package "SYS"))) (bodies (append body-alist (if setterp `((built-in-class . (,%name new-value class)) (forward-referenced-class . (,%name new-value class)) (structure-class . (,%name new-value class)) (standard-class . (setf (slot-value class ',slot) new-value)) (funcallable-standard-class . (setf (slot-value class ',slot) new-value))) `((built-in-class . (,%name class)) (forward-referenced-class . (,%name class)) (structure-class . (,%name class)) (standard-class . (slot-value class ',slot)) (funcallable-standard-class . (slot-value class ',slot))))))) `(atomic-defgeneric ,name (,@(when setterp (list 'new-value)) class) ,@(mapcar #'(lambda (class-name) `(:method (,@(when setterp (list 'new-value)) (class ,class-name)) ,(cdr (assoc class-name bodies)))) '(built-in-class forward-referenced-class structure-class standard-class funcallable-standard-class))))) ;;; The slot names here must agree with the ones defined in ;;; StandardClass.java:layoutStandardClass. (redefine-class-forwarder class-name sys:name) ;;; AMOP pg. 230 (redefine-class-forwarder (setf class-name) sys:name ((standard-class . (progn (reinitialize-instance class :name new-value) new-value)) (funcallable-standard-class . (progn (reinitialize-instance class :name new-value) new-value)))) (redefine-class-forwarder class-slots sys:slots) (redefine-class-forwarder (setf class-slots) sys:slots) (redefine-class-forwarder class-direct-slots sys:direct-slots) (redefine-class-forwarder (setf class-direct-slots) sys:direct-slots) (redefine-class-forwarder class-layout sys:layout) (redefine-class-forwarder (setf class-layout) sys:layout) (redefine-class-forwarder class-direct-superclasses sys:direct-superclasses) (redefine-class-forwarder (setf class-direct-superclasses) sys:direct-superclasses) (redefine-class-forwarder class-direct-subclasses sys:direct-subclasses) (redefine-class-forwarder (setf class-direct-subclasses) sys:direct-subclasses) (redefine-class-forwarder class-direct-methods sys:direct-methods) (redefine-class-forwarder (setf class-direct-methods) sys:direct-methods) (redefine-class-forwarder class-precedence-list sys:precedence-list) (redefine-class-forwarder (setf class-precedence-list) sys:precedence-list) (redefine-class-forwarder class-finalized-p sys:finalized-p) (redefine-class-forwarder (setf class-finalized-p) sys:finalized-p) (redefine-class-forwarder class-default-initargs sys:default-initargs) (redefine-class-forwarder (setf class-default-initargs) sys:default-initargs) (redefine-class-forwarder class-direct-default-initargs sys:direct-default-initargs) (redefine-class-forwarder (setf class-direct-default-initargs) sys:direct-default-initargs) ;;; Class definition (defun check-duplicate-slots (slots) (flet ((canonical-slot-name (canonical-slot) (getf canonical-slot :name))) (dolist (s1 slots) (let ((name1 (canonical-slot-name s1))) (dolist (s2 (cdr (memq s1 slots))) (when (eq name1 (canonical-slot-name s2)) (error 'program-error "Duplicate slot ~S" name1))))))) (defun check-duplicate-default-initargs (initargs) (let ((names ())) (dolist (initarg initargs) (push (car initarg) names)) (do* ((names names (cdr names)) (name (car names) (car names))) ((null names)) (when (memq name (cdr names)) (error 'program-error :format-control "Duplicate initialization argument name ~S in :DEFAULT-INITARGS." :format-arguments (list name)))))) (defun canonicalize-direct-superclasses (direct-superclasses) (let ((classes '())) (dolist (class-specifier direct-superclasses) (let ((class (if (classp class-specifier) class-specifier (find-class class-specifier nil)))) (unless class (setf class (make-instance +the-forward-referenced-class+ :name class-specifier)) (setf (find-class class-specifier) class)) (when (and (typep class 'built-in-class) (not (member class *extensible-built-in-classes*))) (error "Attempt to define a subclass of built-in-class ~S." class-specifier)) (push class classes))) (nreverse classes))) (atomic-defgeneric add-direct-subclass (superclass subclass) (:method ((superclass class) (subclass class)) (setf (class-direct-subclasses superclass) (adjoin subclass (class-direct-subclasses superclass))))) (atomic-defgeneric remove-direct-subclass (superclass subclass) (:method ((superclass class) (subclass class)) (setf (class-direct-subclasses superclass) (remove subclass (class-direct-subclasses superclass))))) ;;; AMOP pg. 182 (defun ensure-class (name &rest all-keys &key &allow-other-keys) (let ((class (find-class name nil))) ;; CLHS DEFCLASS: "If a class with the same proper name already ;; exists [...] the existing class is redefined." Ansi-tests ;; CLASS-0309 and CLASS-0310.1 demand this behavior. (if (and class (eql (class-name class) name)) (apply #'ensure-class-using-class class name all-keys) (apply #'ensure-class-using-class nil name all-keys)))) ;;; AMOP pg. 183ff. (defgeneric ensure-class-using-class (class name &key direct-default-initargs direct-slots direct-superclasses metaclass &allow-other-keys)) (defmethod ensure-class-using-class :before (class name &key direct-slots direct-default-initargs &allow-other-keys) (check-duplicate-slots direct-slots) (check-duplicate-default-initargs direct-default-initargs)) (defmethod ensure-class-using-class ((class null) name &rest all-keys &key (metaclass +the-standard-class+) direct-superclasses &allow-other-keys) (setf all-keys (copy-list all-keys)) ; since we modify it (remf all-keys :metaclass) (unless (classp metaclass) (setf metaclass (find-class metaclass))) (let ((class (apply (if (eq metaclass +the-standard-class+) #'make-instance-standard-class #'make-instance) metaclass :name name :direct-superclasses (canonicalize-direct-superclasses direct-superclasses) all-keys))) (%set-find-class name class) class)) (defmethod ensure-class-using-class ((class built-in-class) name &rest all-keys &key &allow-other-keys) (declare (ignore all-keys)) (error "The symbol ~S names a built-in class." name)) (defmethod ensure-class-using-class ((class forward-referenced-class) name &rest all-keys &key (metaclass +the-standard-class+) direct-superclasses &allow-other-keys) (setf all-keys (copy-list all-keys)) ; since we modify it (remf all-keys :metaclass) (unless (classp metaclass) (setf metaclass (find-class metaclass))) (apply #'change-class class metaclass all-keys) (apply #'reinitialize-instance class :name name :direct-superclasses (canonicalize-direct-superclasses direct-superclasses) all-keys) class) (defmethod ensure-class-using-class ((class class) name &rest all-keys &key (metaclass +the-standard-class+ metaclassp) direct-superclasses &allow-other-keys) (declare (ignore name)) (setf all-keys (copy-list all-keys)) ; since we modify it (remf all-keys :metaclass) (unless (classp metaclass) (setf metaclass (find-class metaclass))) (when (and metaclassp (not (eq (class-of class) metaclass))) (error 'program-error "Trying to redefine class ~S with different metaclass." (class-name class))) (apply #'reinitialize-instance class :direct-superclasses (canonicalize-direct-superclasses direct-superclasses) all-keys) class) (defmacro defclass (&whole form name direct-superclasses direct-slots &rest options) (unless (>= (length form) 3) (error 'program-error "Wrong number of arguments for DEFCLASS.")) (check-declaration-type name) `(progn (sys::record-source-information-for-type ',name :class) (ensure-class ',name :direct-superclasses (canonicalize-direct-superclasses ',direct-superclasses) :direct-slots ,(canonicalize-direct-slots direct-slots) ,@(canonicalize-defclass-options options)))) ;;; AMOP pg. 180 (defgeneric direct-slot-definition-class (class &rest initargs)) (defmethod direct-slot-definition-class ((class class) &rest initargs) (declare (ignore initargs)) +the-standard-direct-slot-definition-class+) ;;; AMOP pg. 181 (defgeneric effective-slot-definition-class (class &rest initargs)) (defmethod effective-slot-definition-class ((class class) &rest initargs) (declare (ignore initargs)) +the-standard-effective-slot-definition-class+) ;;; AMOP pg. 224 (defgeneric reader-method-class (class direct-slot &rest initargs)) (defmethod reader-method-class ((class standard-class) (direct-slot standard-direct-slot-definition) &rest initargs) (declare (ignore initargs)) +the-standard-reader-method-class+) (defmethod reader-method-class ((class funcallable-standard-class) (direct-slot standard-direct-slot-definition) &rest initargs) (declare (ignore initargs)) +the-standard-reader-method-class+) ;;; AMOP pg. 242 (defgeneric writer-method-class (class direct-slot &rest initargs)) (defmethod writer-method-class ((class standard-class) (direct-slot standard-direct-slot-definition) &rest initargs) (declare (ignore initargs)) +the-standard-writer-method-class+) (defmethod writer-method-class ((class funcallable-standard-class) (direct-slot standard-direct-slot-definition) &rest initargs) (declare (ignore initargs)) +the-standard-writer-method-class+) ;;; Applicable methods (atomic-defgeneric compute-applicable-methods (gf args) (:method ((gf standard-generic-function) args) (std-compute-applicable-methods gf args))) (defgeneric compute-applicable-methods-using-classes (gf classes) (:method ((gf standard-generic-function) classes) (let ((methods '())) (dolist (method (generic-function-methods gf)) (multiple-value-bind (applicable knownp) (method-applicable-using-classes-p method classes) (cond (applicable (push method methods)) ((not knownp) (return-from compute-applicable-methods-using-classes (values nil nil)))))) (values (sort-methods methods gf classes) t)))) ;;; Slot access ;;; ;;; See AMOP pg. 156ff. for an overview. ;;; ;;; AMOP specifies these generic functions to dispatch on slot objects ;;; (with the exception of slot-exists-p-using-class), although its ;;; sample implementation Closette dispatches on slot names. We let ;;; slot-value and friends call their gf counterparts with the effective ;;; slot definition, but leave the definitions dispatching on slot name ;;; in place for user convenience. ;;; AMOP pg. 235 (defgeneric slot-value-using-class (class instance slot)) (defmethod slot-value-using-class ((class standard-class) instance (slot symbol)) (std-slot-value instance slot)) (defmethod slot-value-using-class ((class standard-class) instance (slot standard-effective-slot-definition)) (let* ((location (slot-definition-location slot)) (value (if (consp location) (cdr location) ; :allocation :class (standard-instance-access instance location)))) (if (eq value +slot-unbound+) ;; fix SLOT-UNBOUND.5 from ansi test suite (nth-value 0 (slot-unbound class instance (slot-definition-name slot))) value))) (defmethod slot-value-using-class ((class funcallable-standard-class) instance (slot symbol)) (std-slot-value instance slot)) (defmethod slot-value-using-class ((class funcallable-standard-class) instance (slot standard-effective-slot-definition)) (let* ((location (slot-definition-location slot)) (value (if (consp location) (cdr location) ; :allocation :class (funcallable-standard-instance-access instance location)))) (if (eq value +slot-unbound+) ;; fix SLOT-UNBOUND.5 from ansi test suite (nth-value 0 (slot-unbound class instance (slot-definition-name slot))) value))) (defmethod slot-value-using-class ((class structure-class) instance (slot symbol)) (std-slot-value instance slot)) (defmethod slot-value-using-class ((class structure-class) instance (slot standard-effective-slot-definition)) (std-slot-value instance (slot-definition-name slot))) ;;; AMOP pg. 231 (defgeneric (setf slot-value-using-class) (new-value class instance slot)) (defmethod (setf slot-value-using-class) (new-value (class standard-class) instance (slot symbol)) (setf (std-slot-value instance slot) new-value)) (defmethod (setf slot-value-using-class) (new-value (class standard-class) instance (slot standard-effective-slot-definition)) (let ((location (slot-definition-location slot))) (if (consp location) ; :allocation :class (setf (cdr location) new-value) (setf (standard-instance-access instance location) new-value)))) (defmethod (setf slot-value-using-class) (new-value (class funcallable-standard-class) instance (slot symbol)) (setf (std-slot-value instance slot) new-value)) (defmethod (setf slot-value-using-class) (new-value (class funcallable-standard-class) instance (slot standard-effective-slot-definition)) (let ((location (slot-definition-location slot))) (if (consp location) ; :allocation :class (setf (cdr location) new-value) (setf (funcallable-standard-instance-access instance location) new-value)))) (defmethod (setf slot-value-using-class) (new-value (class structure-class) instance (slot symbol)) (setf (std-slot-value instance slot) new-value)) (defmethod (setf slot-value-using-class) (new-value (class structure-class) instance (slot standard-effective-slot-definition)) (setf (std-slot-value instance (slot-definition-name slot)) new-value)) ;;; slot-exists-p-using-class is not specified by AMOP, and obviously ;;; cannot be specialized on the slot type. Hence, its implementation ;;; differs from slot-(boundp|makunbound|value)-using-class (defgeneric slot-exists-p-using-class (class instance slot-name)) (defmethod slot-exists-p-using-class (class instance slot-name) nil) (defmethod slot-exists-p-using-class ((class standard-class) instance slot-name) (std-slot-exists-p instance slot-name)) (defmethod slot-exists-p-using-class ((class funcallable-standard-class) instance slot-name) (std-slot-exists-p instance slot-name)) (defmethod slot-exists-p-using-class ((class structure-class) instance slot-name) (dolist (dsd (class-slots class)) (when (eq (sys::dsd-name dsd) slot-name) (return-from slot-exists-p-using-class t))) nil) (defgeneric slot-boundp-using-class (class instance slot)) (defmethod slot-boundp-using-class ((class standard-class) instance (slot symbol)) (std-slot-boundp instance slot)) (defmethod slot-boundp-using-class ((class standard-class) instance (slot standard-effective-slot-definition)) (let ((location (slot-definition-location slot))) (if (consp location) (not (eq (cdr location) +slot-unbound+)) ; :allocation :class (not (eq (standard-instance-access instance location) +slot-unbound+))))) (defmethod slot-boundp-using-class ((class funcallable-standard-class) instance (slot symbol)) (std-slot-boundp instance slot)) (defmethod slot-boundp-using-class ((class funcallable-standard-class) instance (slot standard-effective-slot-definition)) (let ((location (slot-definition-location slot))) (if (consp location) (not (eq (cdr location) +slot-unbound+)) ; :allocation :class (not (eq (funcallable-standard-instance-access instance location) +slot-unbound+))))) (defmethod slot-boundp-using-class ((class structure-class) instance slot) "Structure slots can't be unbound, so this method always returns T." (declare (ignore class instance slot)) t) (defgeneric slot-makunbound-using-class (class instance slot)) (defmethod slot-makunbound-using-class ((class standard-class) instance (slot symbol)) (std-slot-makunbound instance slot)) (defmethod slot-makunbound-using-class ((class standard-class) instance (slot standard-effective-slot-definition)) (let ((location (slot-definition-location slot))) (if (consp location) (setf (cdr location) +slot-unbound+) (setf (standard-instance-access instance location) +slot-unbound+)))) (defmethod slot-makunbound-using-class ((class funcallable-standard-class) instance (slot symbol)) (std-slot-makunbound instance slot)) (defmethod slot-makunbound-using-class ((class funcallable-standard-class) instance (slot symbol)) (let ((location (slot-definition-location slot))) (if (consp location) (setf (cdr location) +slot-unbound+) (setf (funcallable-standard-instance-access instance location) +slot-unbound+)))) (defmethod slot-makunbound-using-class ((class structure-class) instance slot) (declare (ignore class instance slot)) (error "Structure slots can't be unbound")) (defgeneric slot-missing (class instance slot-name operation &optional new-value)) (defmethod slot-missing ((class t) instance slot-name operation &optional new-value) (declare (ignore new-value)) (error "The slot ~S is missing from the class ~S." slot-name class)) (defgeneric slot-unbound (class instance slot-name)) (defmethod slot-unbound ((class t) instance slot-name) (error 'unbound-slot :instance instance :name slot-name)) ;;; Instance creation and initialization ;;; AMOP pg. 168ff. (defgeneric allocate-instance (class &rest initargs &key &allow-other-keys)) (defmethod allocate-instance ((class standard-class) &rest initargs) (declare (ignore initargs)) (std-allocate-instance class)) (defmethod allocate-instance ((class funcallable-standard-class) &rest initargs) (declare (ignore initargs)) (allocate-funcallable-instance class)) (defmethod allocate-instance ((class structure-class) &rest initargs) (declare (ignore initargs)) (%make-structure (class-name class) (make-list (length (class-slots class)) :initial-element +slot-unbound+))) (defmethod allocate-instance ((class built-in-class) &rest initargs) (declare (ignore initargs)) (error "Cannot allocate instances of a built-in class: ~S" class)) (defmethod allocate-instance :before ((class class) &rest initargs) (declare (ignore initargs)) (unless (class-finalized-p class) (finalize-inheritance class))) ;; "The set of valid initialization arguments for a class is the set of valid ;; initialization arguments that either fill slots or supply arguments to ;; methods, along with the predefined initialization argument :ALLOW-OTHER-KEYS." ;; 7.1.2 (defun calculate-allowable-initargs (gf-list args instance shared-initialize-param initargs) (let* ((methods (nconc (std-compute-applicable-methods #'shared-initialize (list* instance shared-initialize-param initargs)) (mapcan #'(lambda (gf) (if (std-generic-function-p gf) (std-compute-applicable-methods gf args) (compute-applicable-methods gf args))) gf-list))) (method-keyword-args (reduce #'merge-initargs-sets (mapcar #'method-lambda-list methods) :key #'extract-lambda-list-keywords :initial-value nil)) (slots-initargs (mapappend #'slot-definition-initargs (class-slots (class-of instance))))) (merge-initargs-sets (merge-initargs-sets slots-initargs method-keyword-args) '(:allow-other-keys)))) ;; allow-other-keys is always allowed (defun check-initargs (gf-list args instance shared-initialize-param initargs cache call-site) "Checks the validity of `initargs' for the generic functions in `gf-list' when called with `args' by calculating the applicable methods for each gf. The applicable methods for SHARED-INITIALIZE based on `instance', `shared-initialize-param' and `initargs' are added to the list of applicable methods." (when (oddp (length initargs)) (error 'program-error :format-control "Odd number of keyword arguments.")) (unless (getf initargs :allow-other-keys) (multiple-value-bind (allowable-initargs present-p) (when cache (gethash (class-of instance) cache)) (unless present-p (setf allowable-initargs (calculate-allowable-initargs gf-list args instance shared-initialize-param initargs)) (when cache (setf (gethash (class-of instance) cache) allowable-initargs))) (unless (eq t allowable-initargs) (do* ((tail initargs (cddr tail)) (initarg (car tail) (car tail))) ((null tail)) (unless (memq initarg allowable-initargs) (error 'program-error :format-control "Invalid initarg ~S in call to ~S with arglist ~S." :format-arguments (list initarg call-site args)))))))) (defun merge-initargs-sets (list1 list2) (cond ((eq list1 t) t) ((eq list2 t) t) (t (union list1 list2)))) (defun extract-lambda-list-keywords (lambda-list) "Returns a list of keywords acceptable as keyword arguments, or T when any keyword is acceptable due to presence of &allow-other-keys." (when (member '&allow-other-keys lambda-list) (return-from extract-lambda-list-keywords t)) (loop with keyword-args = (cdr (memq '&key lambda-list)) for key in keyword-args when (eq key '&aux) do (loop-finish) when (eq key '&allow-other-keys) do (return t) when (listp key) do (setq key (car key)) collect (if (symbolp key) (make-keyword key) (car key)))) (defgeneric make-instance (class &rest initargs &key &allow-other-keys)) (defmethod make-instance :before ((class class) &rest initargs) (when (oddp (length initargs)) (error 'program-error :format-control "Odd number of keyword arguments.")) (unless (class-finalized-p class) (finalize-inheritance class))) (defun augment-initargs-with-defaults (class initargs) (let ((default-initargs '())) (dolist (initarg (class-default-initargs class)) (let ((key (first initarg)) (fn (third initarg))) (when (eq (getf initargs key +slot-unbound+) +slot-unbound+) (push key default-initargs) (push (funcall fn) default-initargs)))) (append initargs (nreverse default-initargs)))) (defmethod make-instance ((class standard-class) &rest initargs) (setf initargs (augment-initargs-with-defaults class initargs)) (let ((instance (std-allocate-instance class))) (check-initargs (list #'allocate-instance #'initialize-instance) (list* instance initargs) instance t initargs *make-instance-initargs-cache* 'make-instance) (apply #'initialize-instance instance initargs) instance)) (defmethod make-instance ((class funcallable-standard-class) &rest initargs) (setf initargs (augment-initargs-with-defaults class initargs)) (let ((instance (allocate-funcallable-instance class))) (check-initargs (list #'allocate-instance #'initialize-instance) (list* instance initargs) instance t initargs *make-instance-initargs-cache* 'make-instance) (apply #'initialize-instance instance initargs) instance)) (defmethod make-instance ((class symbol) &rest initargs) (apply #'make-instance (find-class class) initargs)) (defgeneric initialize-instance (instance &rest initargs &key &allow-other-keys)) (defmethod initialize-instance ((instance standard-object) &rest initargs) (apply #'shared-initialize instance t initargs)) (defgeneric reinitialize-instance (instance &rest initargs &key &allow-other-keys)) ;; "The system-supplied primary method for REINITIALIZE-INSTANCE checks the ;; validity of initargs and signals an error if an initarg is supplied that is ;; not declared as valid. The method then calls the generic function SHARED- ;; INITIALIZE with the following arguments: the instance, nil (which means no ;; slots should be initialized according to their initforms), and the initargs ;; it received." (defmethod reinitialize-instance ((instance standard-object) &rest initargs) (check-initargs (list #'reinitialize-instance) (list* instance initargs) instance () initargs *reinitialize-instance-initargs-cache* 'reinitialize-instance) (apply #'shared-initialize instance () initargs)) (defun std-shared-initialize (instance slot-names all-keys) (when (oddp (length all-keys)) (error 'program-error :format-control "Odd number of keyword arguments.")) ;; do a quick scan of the arguments list to see if it's a real ;; 'initialization argument list' (which is not the same as ;; checking initarg validity (do* ((tail all-keys (cddr tail)) (initarg (car tail) (car tail))) ((null tail)) (unless (symbolp initarg) (error 'program-error :format-control "Initarg ~S not a symbol." :format-arguments (list initarg)))) (dolist (slot (class-slots (class-of instance))) (let ((slot-name (slot-definition-name slot))) (multiple-value-bind (init-key init-value foundp) (get-properties all-keys (slot-definition-initargs slot)) (if foundp (setf (slot-value instance slot-name) init-value) (unless (slot-boundp instance slot-name) (let ((initfunction (slot-definition-initfunction slot))) (when (and initfunction (or (eq slot-names t) (memq slot-name slot-names))) (setf (slot-value instance slot-name) (funcall initfunction))))))))) instance) (defgeneric shared-initialize (instance slot-names &rest initargs &key &allow-other-keys)) (defmethod shared-initialize ((instance standard-object) slot-names &rest initargs) (std-shared-initialize instance slot-names initargs)) (defmethod shared-initialize ((slot slot-definition) slot-names &rest args &key name initargs initform initfunction readers writers allocation &allow-other-keys) ;;Keyword args are duplicated from init-slot-definition only to have ;;them checked. (declare (ignore slot-names)) ;;TODO? (declare (ignore name initargs initform initfunction readers writers allocation)) ;;For built-in slots (apply #'init-slot-definition slot :allow-other-keys t args) ;;For user-defined slots (call-next-method)) ;;; change-class (defgeneric change-class (instance new-class &key &allow-other-keys)) (defmethod change-class ((old-instance standard-object) (new-class standard-class) &rest initargs) (let ((old-slots (class-slots (class-of old-instance))) (new-slots (class-slots new-class)) (new-instance (allocate-instance new-class))) ;; "The values of local slots specified by both the class CTO and the class ;; CFROM are retained. If such a local slot was unbound, it remains ;; unbound." (dolist (new-slot new-slots) (when (instance-slot-p new-slot) (let* ((slot-name (slot-definition-name new-slot)) (old-slot (find slot-name old-slots :key 'slot-definition-name))) ;; "The values of slots specified as shared in the class CFROM and as ;; local in the class CTO are retained." (when (and old-slot (slot-boundp old-instance slot-name)) (setf (slot-value new-instance slot-name) (slot-value old-instance slot-name)))))) (swap-slots old-instance new-instance) (rotatef (std-instance-layout new-instance) (std-instance-layout old-instance)) (apply #'update-instance-for-different-class new-instance old-instance initargs) old-instance)) (defmethod change-class ((instance standard-object) (new-class symbol) &rest initargs) (apply #'change-class instance (find-class new-class) initargs)) (defgeneric update-instance-for-different-class (old new &rest initargs &key &allow-other-keys)) (defmethod update-instance-for-different-class ((old standard-object) (new standard-object) &rest initargs) (let ((added-slots (remove-if #'(lambda (slot-name) (slot-exists-p old slot-name)) (mapcar 'slot-definition-name (class-slots (class-of new)))))) (check-initargs (list #'update-instance-for-different-class) (list old new initargs) new added-slots initargs nil 'update-instance-for-different-class) (apply #'shared-initialize new added-slots initargs))) ;;; make-instances-obsolete (defgeneric make-instances-obsolete (class)) (defmethod make-instances-obsolete ((class standard-class)) (%make-instances-obsolete class)) (defmethod make-instances-obsolete ((class funcallable-standard-class)) (%make-instances-obsolete class)) (defmethod make-instances-obsolete ((class symbol)) (make-instances-obsolete (find-class class)) class) ;;; update-instance-for-redefined-class (defgeneric update-instance-for-redefined-class (instance added-slots discarded-slots property-list &rest initargs &key &allow-other-keys)) (defmethod update-instance-for-redefined-class ((instance standard-object) added-slots discarded-slots property-list &rest initargs) (check-initargs (list #'update-instance-for-redefined-class) (list* instance added-slots discarded-slots property-list initargs) instance added-slots initargs nil 'update-instance-for-redefined-class) (apply #'shared-initialize instance added-slots initargs)) ;;; Methods having to do with class metaobjects. (defmethod initialize-instance :after ((class standard-class) &rest args) (apply #'std-after-initialization-for-classes class args)) (defmethod initialize-instance :after ((class funcallable-standard-class) &rest args) (apply #'std-after-initialization-for-classes class args)) (defmethod reinitialize-instance :before ((class standard-class) &rest all-keys &key direct-superclasses) (check-initargs (list #'allocate-instance #'initialize-instance) (list* class all-keys) class t all-keys nil 'reinitialize-instance) (dolist (superclass (set-difference (class-direct-superclasses class) direct-superclasses)) (remove-direct-subclass superclass class)) (dolist (superclass (set-difference direct-superclasses (class-direct-superclasses class))) (add-direct-subclass superclass class))) (defmethod reinitialize-instance :before ((class funcallable-standard-class) &rest all-keys &key direct-superclasses) (check-initargs (list #'allocate-instance #'initialize-instance) (list* class all-keys) class t all-keys nil 'reinitialize-instance) (dolist (superclass (set-difference (class-direct-superclasses class) direct-superclasses)) (remove-direct-subclass superclass class)) (dolist (superclass (set-difference direct-superclasses (class-direct-superclasses class))) (add-direct-subclass superclass class))) (defun std-after-reinitialization-for-classes (class &rest all-keys &key (direct-superclasses nil direct-superclasses-p) (direct-slots nil direct-slots-p) (direct-default-initargs nil direct-default-initargs-p) &allow-other-keys) (remhash class *make-instance-initargs-cache*) (remhash class *reinitialize-instance-initargs-cache*) (%make-instances-obsolete class) (setf (class-finalized-p class) nil) (when direct-superclasses-p (let* ((old-supers (class-direct-superclasses class)) (new-supers (canonicalize-direct-superclass-list class direct-superclasses))) (setf (class-direct-superclasses class) new-supers) (dolist (old-superclass (set-difference old-supers new-supers)) (remove-direct-subclass old-superclass class)) (dolist (new-superclass (set-difference new-supers old-supers)) (add-direct-subclass new-superclass class)))) (when direct-slots-p ;; FIXME: maybe remove old reader and writer methods? (let ((slots (mapcar #'(lambda (slot-properties) (apply #'make-direct-slot-definition class slot-properties)) direct-slots))) (setf (class-direct-slots class) slots) (dolist (direct-slot slots) (dolist (reader (slot-definition-readers direct-slot)) (add-reader-method class reader direct-slot)) (dolist (writer (slot-definition-writers direct-slot)) (add-writer-method class writer direct-slot))))) (when direct-default-initargs-p (setf (class-direct-default-initargs class) direct-default-initargs)) (maybe-finalize-class-subtree class) (map-dependents class #'(lambda (dep) (update-dependent class dep all-keys)))) (defmethod reinitialize-instance :after ((class standard-class) &rest all-keys) (apply #'std-after-reinitialization-for-classes class all-keys)) (defmethod reinitialize-instance :after ((class funcallable-standard-class) &rest all-keys) (apply #'std-after-reinitialization-for-classes class all-keys)) (defmethod reinitialize-instance :before ((gf standard-generic-function) &key (lambda-list nil lambda-list-supplied-p) &allow-other-keys) (when lambda-list-supplied-p (unless (or (null (generic-function-methods gf)) (lambda-lists-congruent-p lambda-list (generic-function-lambda-list gf))) (error "The lambda list ~S is incompatible with the existing methods of ~S." lambda-list gf)))) (defmethod reinitialize-instance :after ((gf standard-generic-function) &rest all-keys) (map-dependents gf #'(lambda (dep) (update-dependent gf dep all-keys)))) ;;; Finalize inheritance (atomic-defgeneric finalize-inheritance (class) (:method ((class standard-class)) (std-finalize-inheritance class)) (:method ((class funcallable-standard-class)) (std-finalize-inheritance class))) ;;; Default initargs ;;; AMOP pg. 174 (atomic-defgeneric compute-default-initargs (class) (:method ((class standard-class)) (std-compute-default-initargs class)) (:method ((class funcallable-standard-class)) (std-compute-default-initargs class))) ;;; Class precedence lists (defgeneric compute-class-precedence-list (class)) (defmethod compute-class-precedence-list ((class standard-class)) (std-compute-class-precedence-list class)) (defmethod compute-class-precedence-list ((class funcallable-standard-class)) (std-compute-class-precedence-list class)) ;;; Slot inheritance (defgeneric compute-slots (class)) (defmethod compute-slots ((class standard-class)) (std-compute-slots class)) (defmethod compute-slots ((class funcallable-standard-class)) (std-compute-slots class)) (defgeneric compute-effective-slot-definition (class name direct-slots)) (defmethod compute-effective-slot-definition ((class standard-class) name direct-slots) (std-compute-effective-slot-definition class name direct-slots)) (defmethod compute-effective-slot-definition ((class funcallable-standard-class) name direct-slots) (std-compute-effective-slot-definition class name direct-slots)) ;;; Methods having to do with generic function invocation. (defgeneric compute-discriminating-function (gf)) (defmethod compute-discriminating-function ((gf standard-generic-function)) (std-compute-discriminating-function gf)) (defgeneric method-more-specific-p (gf method1 method2 required-classes)) (defmethod method-more-specific-p ((gf standard-generic-function) method1 method2 required-classes) (let ((method-indices (argument-precedence-order-indices (generic-function-argument-precedence-order gf) (getf (analyze-lambda-list (generic-function-lambda-list gf)) ':required-args)))) (std-method-more-specific-p method1 method2 required-classes method-indices))) ;;; AMOP pg. 176 (defgeneric compute-effective-method (gf method-combination methods)) (defmethod compute-effective-method ((gf standard-generic-function) method-combination methods) (std-compute-effective-method gf method-combination methods)) (defgeneric compute-applicable-methods (gf args)) (defmethod compute-applicable-methods ((gf standard-generic-function) args) (std-compute-applicable-methods gf args)) ;;; AMOP pg. 207 (atomic-defgeneric make-method-lambda (generic-function method lambda-expression environment) (:method ((generic-function standard-generic-function) (method standard-method) lambda-expression environment) (declare (ignore environment)) (values (compute-method-function lambda-expression) nil))) ;;; Slot definition accessors (defmacro slot-definition-dispatch (slot-definition std-form generic-form) `(let (($cl (class-of ,slot-definition))) (case $cl ((+the-standard-slot-definition-class+ +the-standard-direct-slot-definition-class+ +the-standard-effective-slot-definition-class+) ,std-form) (t ,generic-form)))) (atomic-defgeneric slot-definition-allocation (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::allocation) (slot-value slot-definition 'sys::allocation)))) (atomic-defgeneric (setf slot-definition-allocation) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::allocation) value) (setf (slot-value slot-definition 'sys::allocation) value)))) (atomic-defgeneric slot-definition-initargs (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::initargs) (slot-value slot-definition 'sys::initargs)))) (atomic-defgeneric (setf slot-definition-initargs) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::initargs) value) (setf (slot-value slot-definition 'sys::initargs) value)))) (atomic-defgeneric slot-definition-initform (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::initform) (slot-value slot-definition 'sys::initform)))) (atomic-defgeneric (setf slot-definition-initform) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::initform) value) (setf (slot-value slot-definition 'sys::initform) value)))) (atomic-defgeneric slot-definition-initfunction (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::initfunction) (slot-value slot-definition 'sys::initfunction)))) (atomic-defgeneric (setf slot-definition-initfunction) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::initfunction) value) (setf (slot-value slot-definition 'sys::initfunction) value)))) (atomic-defgeneric slot-definition-name (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys:name) (slot-value slot-definition 'sys:name)))) (atomic-defgeneric (setf slot-definition-name) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys:name) value) (setf (slot-value slot-definition 'sys:name) value)))) (atomic-defgeneric slot-definition-readers (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::readers) (slot-value slot-definition 'sys::readers)))) (atomic-defgeneric (setf slot-definition-readers) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::readers) value) (setf (slot-value slot-definition 'sys::readers) value)))) (atomic-defgeneric slot-definition-writers (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::writers) (slot-value slot-definition 'sys::writers)))) (atomic-defgeneric (setf slot-definition-writers) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::writers) value) (setf (slot-value slot-definition 'sys::writers) value)))) (atomic-defgeneric slot-definition-allocation-class (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::allocation-class) (slot-value slot-definition 'sys::allocation-class)))) (atomic-defgeneric (setf slot-definition-allocation-class) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::allocation-class) value) (setf (slot-value slot-definition 'sys::allocation-class) value)))) (atomic-defgeneric slot-definition-location (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::location) (slot-value slot-definition 'sys::location)))) (atomic-defgeneric (setf slot-definition-location) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::location) value) (setf (slot-value slot-definition 'sys::location) value)))) (atomic-defgeneric slot-definition-type (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys::%type) (slot-value slot-definition 'sys::%type)))) (atomic-defgeneric (setf slot-definition-type) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys::%type) value) (setf (slot-value slot-definition 'sys::%type) value)))) (atomic-defgeneric slot-definition-documentation (slot-definition) (:method ((slot-definition slot-definition)) (slot-definition-dispatch slot-definition (std-slot-value slot-definition 'sys:%documentation) (slot-value slot-definition 'sys:%documentation)))) (atomic-defgeneric (setf slot-definition-documentation) (value slot-definition) (:method (value (slot-definition slot-definition)) (slot-definition-dispatch slot-definition (setf (std-slot-value slot-definition 'sys:%documentation) value) (setf (slot-value slot-definition 'sys:%documentation) value)))) ;;; Conditions. (defmacro define-condition (name (&rest parent-types) (&rest slot-specs) &body options) (let ((parent-types (or parent-types '(condition))) (report nil)) (dolist (option options) (when (eq (car option) :report) (setf report (cadr option)) (setf options (delete option options :test #'equal)) (return))) (typecase report (null `(progn (sys::record-source-information-for-type ',name :condition) (defclass ,name ,parent-types ,slot-specs ,@options) ',name)) (string `(progn (sys::record-source-information-for-type ',name :condition) (defclass ,name ,parent-types ,slot-specs ,@options) (defmethod print-object ((condition ,name) stream) (if *print-escape* (call-next-method) (progn (write-string ,report stream) condition))) ',name)) (t `(progn (sys::record-source-information-for-type ',name :condition) (defclass ,name ,parent-types ,slot-specs ,@options) (defmethod print-object ((condition ,name) stream) (if *print-escape* (call-next-method) (funcall #',report condition stream))) ',name))))) (defun make-condition (type &rest initargs) (or (%make-condition type initargs) (let ((class (if (symbolp type) (find-class type) type))) (apply #'make-instance class initargs)))) ;; Adapted from SBCL. ;; Originally defined in signal.lisp. Redefined here now that we have MAKE-CONDITION. (defun coerce-to-condition (datum arguments default-type fun-name) (cond ((typep datum 'condition) (when arguments (error 'simple-type-error :datum arguments :expected-type 'null :format-control "You may not supply additional arguments when giving ~S to ~S." :format-arguments (list datum fun-name))) datum) ((symbolp datum) (apply #'make-condition datum arguments)) ((or (stringp datum) (functionp datum)) (make-condition default-type :format-control datum :format-arguments arguments)) (t (error 'simple-type-error :datum datum :expected-type '(or symbol string) :format-control "Bad argument to ~S: ~S." :format-arguments (list fun-name datum))))) (defgeneric make-load-form (object &optional environment)) (defmethod make-load-form ((object t) &optional environment) (declare (ignore environment)) (apply #'no-applicable-method #'make-load-form (list object))) (defmethod make-load-form ((class class) &optional environment) (declare (ignore environment)) (let ((name (class-name class))) (unless (and name (eq (find-class name nil) class)) (error 'simple-type-error :format-control "Can't use anonymous or undefined class as a constant: ~S." :format-arguments (list class))) `(find-class ',name))) (defun invalid-method-error (method format-control &rest args) (let ((message (apply #'format nil format-control args))) (error "Invalid method error for ~S:~% ~A" method message))) (defun method-combination-error (format-control &rest args) (let ((message (apply #'format nil format-control args))) (error "Method combination error in CLOS dispatch:~% ~A" message))) (atomic-defgeneric no-applicable-method (generic-function &rest args) (:method (generic-function &rest args) (error "There is no applicable method for the generic function ~S ~ when called with arguments ~S." generic-function args))) ;;; FIXME (rudi 2012-01-28): this can be a function, it only needs to ;;; use standard accessor functions (defgeneric find-method (generic-function qualifiers specializers &optional errorp)) (defmethod find-method ((generic-function standard-generic-function) qualifiers specializers &optional (errorp t)) (%find-method generic-function qualifiers specializers errorp)) (defgeneric find-method ((generic-function symbol) qualifiers specializers &optional (errorp t)) (find-method (find-generic-function generic-function errorp) qualifiers specializers errorp)) ;;; AMOP pg. 167 (defgeneric add-method (generic-function method)) (defmethod add-method :before ((generic-function generic-function) (method method)) (when (and (method-generic-function method) (not (eql generic-function (method-generic-function method)))) (error 'simple-error :format-control "~S is already a method of ~S, cannot add to ~S." :format-arguments (list method (method-generic-function method) generic-function))) (check-method-lambda-list (generic-function-name generic-function) (method-lambda-list method) (generic-function-lambda-list generic-function))) (defmethod add-method ((generic-function standard-generic-function) (method standard-method)) (std-add-method generic-function method)) (defmethod add-method :after ((generic-function generic-function) (method method)) (map-dependents generic-function #'(lambda (dep) (update-dependent generic-function dep 'add-method method)))) (defgeneric remove-method (generic-function method)) (defmethod remove-method ((generic-function standard-generic-function) (method standard-method)) (std-remove-method generic-function method)) (defmethod remove-method :after ((generic-function generic-function) (method method)) (map-dependents generic-function #'(lambda (dep) (update-dependent generic-function dep 'remove-method method)))) ;; See describe.lisp. (defgeneric describe-object (object stream)) ;; FIXME (defgeneric no-next-method (generic-function method &rest args)) (atomic-defgeneric function-keywords (method) (:method ((method standard-method)) (std-function-keywords method))) (setf *gf-initialize-instance* (symbol-function 'initialize-instance)) (setf *gf-allocate-instance* (symbol-function 'allocate-instance)) (setf *gf-shared-initialize* (symbol-function 'shared-initialize)) (setf *gf-reinitialize-instance* (symbol-function 'reinitialize-instance)) (setf *clos-booting* nil) (atomic-defgeneric class-prototype (class) (:method ((class standard-class)) (allocate-instance class)) (:method ((class funcallable-standard-class)) (allocate-instance class)) (:method ((class structure-class)) (allocate-instance class)) (:method :before (class) (unless (class-finalized-p class) (error "~@<~S is not finalized.~:@>" class)))) (defmethod shared-initialize :before ((instance generic-function) slot-names &key lambda-list argument-precedence-order &allow-other-keys) (check-argument-precedence-order lambda-list argument-precedence-order)) (defmethod shared-initialize :after ((instance standard-generic-function) slot-names &key (lambda-list nil lambda-list-p) (argument-precedence-order nil a-p-o-p) (method-combination '(standard)) &allow-other-keys) (when lambda-list-p (let* ((plist (analyze-lambda-list lambda-list)) (required-args (getf plist ':required-args))) (setf (std-slot-value instance 'sys::required-args) required-args) (setf (std-slot-value instance 'sys::optional-args) (getf plist :optional-args)) (setf (std-slot-value instance 'sys::argument-precedence-order) (or (and a-p-o-p argument-precedence-order) required-args)))) (unless (typep (generic-function-method-combination instance) 'method-combination) ;; this fixes (make-instance 'standard-generic-function) -- the ;; constructor of StandardGenericFunction sets this slot to '(standard) (setf (std-slot-value instance 'sys::%method-combination) (find-method-combination instance (car method-combination) (cdr method-combination)))) (finalize-standard-generic-function instance)) ;;; Readers for generic function metaobjects ;;; AMOP pg. 216ff. (atomic-defgeneric generic-function-argument-precedence-order (generic-function) (:method ((generic-function standard-generic-function)) (std-slot-value generic-function 'sys::argument-precedence-order))) (atomic-defgeneric generic-function-declarations (generic-function) (:method ((generic-function standard-generic-function)) (std-slot-value generic-function 'sys::declarations))) (atomic-defgeneric generic-function-lambda-list (generic-function) (:method ((generic-function standard-generic-function)) (std-slot-value generic-function 'sys::lambda-list))) (atomic-defgeneric generic-function-method-class (generic-function) (:method ((generic-function standard-generic-function)) (std-slot-value generic-function 'sys::method-class))) (atomic-defgeneric generic-function-method-combination (generic-function) (:method ((generic-function standard-generic-function)) (std-slot-value generic-function 'sys::%method-combination))) (atomic-defgeneric generic-function-methods (generic-function) (:method ((generic-function standard-generic-function)) (std-slot-value generic-function 'sys::methods))) (atomic-defgeneric generic-function-name (generic-function) (:method ((generic-function standard-generic-function)) (slot-value generic-function 'sys::name))) (atomic-defgeneric generic-function-required-arguments (generic-function) (:method ((generic-function standard-generic-function)) (std-slot-value generic-function 'sys::required-args))) (atomic-defgeneric generic-function-optional-arguments (generic-function) (:method ((generic-function standard-generic-function)) (std-slot-value generic-function 'sys::optional-args))) ;;; AMOP pg. 231 (defgeneric (setf generic-function-name) (new-value gf) (:method (new-value (gf generic-function)) (reinitialize-instance gf :name new-value))) ;;; Readers for Method Metaobjects ;;; AMOP pg. 218ff. (atomic-defgeneric method-function (method) (:method ((method standard-method)) (std-method-function method))) (atomic-defgeneric method-generic-function (method) (:method ((method standard-method)) (std-method-generic-function method))) (atomic-defgeneric method-lambda-list (method) (:method ((method standard-method)) (std-slot-value method 'sys::lambda-list))) (atomic-defgeneric method-specializers (method) (:method ((method standard-method)) (std-method-specializers method))) (atomic-defgeneric method-qualifiers (method) (:method ((method standard-method)) (std-method-qualifiers method))) (atomic-defgeneric accessor-method-slot-definition (method) (:method ((method standard-accessor-method)) (std-accessor-method-slot-definition method))) ;;; find-method-combination ;;; AMOP pg. 191 (atomic-defgeneric find-method-combination (gf name options) (:method (gf (name symbol) options) (std-find-method-combination gf name options))) ;;; specializer-direct-method and friends. ;;; AMOP pg. 237 (defgeneric specializer-direct-generic-functions (specializer)) (defmethod specializer-direct-generic-functions ((specializer class)) (delete-duplicates (mapcar #'method-generic-function (class-direct-methods specializer)))) (defmethod specializer-direct-generic-functions ((specializer eql-specializer)) (delete-duplicates (mapcar #'method-generic-function (slot-value specializer 'direct-methods)))) ;;; AMOP pg. 238 (defgeneric specializer-direct-methods (specializer)) (defmethod specializer-direct-methods ((specializer class)) (class-direct-methods specializer)) (defmethod specializer-direct-methods ((specializer eql-specializer)) (slot-value specializer 'direct-methods)) ;;; AMOP pg. 165 (atomic-defgeneric add-direct-method (specializer method) (:method ((specializer class) (method method)) (pushnew method (class-direct-methods specializer))) (:method ((specializer eql-specializer) (method method)) (pushnew method (slot-value specializer 'direct-methods)))) ;;; AMOP pg. 227 (atomic-defgeneric remove-direct-method (specializer method) (:method ((specializer class) (method method)) (setf (class-direct-methods specializer) (remove method (class-direct-methods specializer)))) (:method ((specializer eql-specializer) (method method)) (setf (slot-value specializer 'direct-methods) (remove method (slot-value specializer 'direct-methods))))) ;;; The Dependent Maintenance Protocol (AMOP pg. 160ff.) (defvar *dependents* (make-hash-table :test 'eq :weakness :key)) ;;; AMOP pg. 164 (defgeneric add-dependent (metaobject dependent)) (defmethod add-dependent ((metaobject standard-class) dependent) (pushnew dependent (gethash metaobject *dependents* nil))) (defmethod add-dependent ((metaobject funcallable-standard-class) dependent) (pushnew dependent (gethash metaobject *dependents* nil))) (defmethod add-dependent ((metaobject standard-generic-function) dependent) (pushnew dependent (gethash metaobject *dependents* nil))) ;;; AMOP pg. 225 (defgeneric remove-dependent (metaobject dependent)) (defmethod remove-dependent ((metaobject standard-class) dependent) (setf (gethash metaobject *dependents*) (delete dependent (gethash metaobject *dependents* nil) :test #'eq))) (defmethod remove-dependent ((metaobject funcallable-standard-class) dependent) (setf (gethash metaobject *dependents*) (delete dependent (gethash metaobject *dependents* nil) :test #'eq))) (defmethod remove-dependent ((metaobject standard-generic-function) dependent) (setf (gethash metaobject *dependents*) (delete dependent (gethash metaobject *dependents* nil) :test #'eq))) ;;; AMOP pg. 210 (atomic-defgeneric map-dependents (metaobject function) (:method ((metaobject standard-class) function) (dolist (dependent (gethash metaobject *dependents* nil)) (funcall function dependent))) (:method ((metaobject funcallable-standard-class) function) (dolist (dependent (gethash metaobject *dependents* nil)) (funcall function dependent))) (:method ((metaobject standard-generic-function) function) (dolist (dependent (gethash metaobject *dependents* nil)) (funcall function dependent)))) ;;; AMOP pg. 239 (defgeneric update-dependent (metaobject dependent &rest initargs)) ;;; ensure-generic-function(-using-class), AMOP pg. 185ff. (defgeneric ensure-generic-function-using-class (generic-function function-name &key argument-precedence-order declarations documentation generic-function-class lambda-list method-class method-combination name &allow-other-keys)) (defmethod ensure-generic-function-using-class ((generic-function generic-function) function-name &rest all-keys &key (generic-function-class (class-of generic-function)) (method-class (generic-function-method-class generic-function)) (method-combination (generic-function-method-combination generic-function)) &allow-other-keys) (setf all-keys (copy-list all-keys)) ; since we modify it (remf all-keys :generic-function-class) (unless (classp generic-function-class) (setf generic-function-class (find-class generic-function-class))) (unless (classp method-class) (setf method-class (find-class method-class))) (unless (eq generic-function-class (class-of generic-function)) (error "The class ~S is incompatible with the existing class (~S) of ~S." generic-function-class (class-of generic-function) generic-function)) ;; We used to check for changes in method class here, but CLHS says: ;; "If function-name specifies a generic function that has a different ;; value for the :method-class argument, the value is changed, but any ;; existing methods are not changed." (unless (typep method-combination 'method-combination) (setf method-combination (find-method-combination generic-function (car method-combination) (cdr method-combination)))) (apply #'reinitialize-instance generic-function :method-combination method-combination :method-class method-class all-keys) generic-function) (defmethod ensure-generic-function-using-class ((generic-function null) function-name &rest all-keys &key (generic-function-class +the-standard-generic-function-class+) &allow-other-keys) (setf all-keys (copy-list all-keys)) ; since we modify it (remf all-keys :generic-function-class) (unless (classp generic-function-class) (setf generic-function-class (find-class generic-function-class))) (when (and (null *clos-booting*) (fboundp function-name)) (if (or (autoloadp function-name) (and (consp function-name) (eq 'setf (first function-name)) (autoload-ref-p (second function-name)))) (fmakunbound function-name) (progn (cerror "Redefine as generic function" "~A already names an ordinary function, macro, or special operator." function-name) (fmakunbound function-name) ))) (apply (if (eq generic-function-class +the-standard-generic-function-class+) #'make-instance-standard-generic-function #'make-instance) generic-function-class :name function-name all-keys)) (defun ensure-generic-function (function-name &rest all-keys &key lambda-list generic-function-class method-class method-combination argument-precedence-order declarations documentation &allow-other-keys) (declare (ignore lambda-list generic-function-class method-class method-combination argument-precedence-order declarations documentation)) (apply #'ensure-generic-function-using-class (find-generic-function function-name nil) function-name all-keys)) ;;; SLIME compatibility functions. (defun %method-generic-function (method) (method-generic-function method)) (defun %method-function (method) (method-function method)) (eval-when (:compile-toplevel :load-toplevel :execute) (require "MOP")) (provide "CLOS") abcl-src-1.9.0/src/org/armedbear/lisp/coerce.lisp0100644 0000000 0000000 00000012331 14202767264 020350 0ustar000000000 0000000 ;;; coerce.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (declaim (ftype (function (t) t) coerce-list-to-vector)) (defun coerce-list-to-vector (list) (let* ((length (length list)) (result (make-array length))) (dotimes (i length) (declare (type index i)) (setf (aref result i) (pop list))) result)) (declaim (ftype (function (string) simple-string) copy-string)) (defun copy-string (string) (declare (optimize speed (safety 0))) (declare (type string string)) (let* ((length (length string)) (copy (make-string length))) (dotimes (i length copy) (declare (type fixnum i)) (setf (schar copy i) (char string i))))) (defun coerce-error (object result-type) (error 'simple-type-error :datum object :format-control "~S cannot be converted to type ~S." :format-arguments (list object result-type))) ;; FIXME This is a special case for LOOP code, which does things like ;; (AND SINGLE-FLOAT REAL) and (AND SINGLE-FLOAT (REAL (0))). (declaim (ftype (function (t t) t) coerce-object-to-and-type)) (defun coerce-object-to-and-type (object result-type) (when (and (consp result-type) (eq (%car result-type) 'AND) (= (length result-type) 3)) (let* ((type1 (%cadr result-type)) (type2 (%caddr result-type)) (result (coerce object type1))) (when (typep object type2) (return-from coerce-object-to-and-type result)))) (coerce-error object result-type)) (defun coerce (object result-type) (cond ((eq result-type t) object) ((typep object result-type) object) ((and (listp object) (eq result-type 'vector)) (coerce-list-to-vector object)) ((and (stringp object) ; a string, but not a simple-string (eq result-type 'simple-string)) (copy-string object)) ((eq result-type 'character) (cond ((and (stringp object) (= (length object) 1)) (char object 0)) ((and (symbolp object) (= (length (symbol-name object)) 1)) (char (symbol-name object) 0)) (t (coerce-error object result-type)))) ((memq result-type '(float single-float short-float)) (coerce-to-single-float object)) ((memq result-type '(double-float long-float)) (coerce-to-double-float object)) ((eq result-type 'complex) (cond ((floatp object) (complex object 0.0)) ((numberp object) object) (t (coerce-error object result-type)))) ((eq result-type 'function) (coerce-to-function object)) ((and (consp result-type) (eq (%car result-type) 'complex)) (when (complexp object) (return-from coerce (complex (coerce (realpart object) (cadr result-type)) (coerce (imagpart object) (cadr result-type))))) (if (memq (%cadr result-type) '(float single-float double-float short-float long-float)) (complex (coerce object (cadr result-type)) (coerce 0.0 (cadr result-type))) object)) ((and (consp result-type) (eq (%car result-type) 'AND)) (coerce-object-to-and-type object result-type)) ((and (simple-typep object 'sequence) (%subtypep result-type 'sequence)) (concatenate result-type object)) (t (let ((expanded-type (expand-deftype result-type))) (unless (eq expanded-type result-type) (return-from coerce (coerce object expanded-type)))) (coerce-error object result-type)))) abcl-src-1.9.0/src/org/armedbear/lisp/collect.lisp0100644 0000000 0000000 00000011714 14223403213 020521 0ustar000000000 0000000 ;;; collect.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "EXT") (export '(collect)) ;;; From CMUCL. ;;;; The Collect macro: ;;; Collect-Normal-Expander -- Internal ;;; ;;; This function does the real work of macroexpansion for normal collection ;;; macros. N-Value is the name of the variable which holds the current ;;; value. Fun is the function which does collection. Forms is the list of ;;; forms whose values we are supposed to collect. ;;; (defun collect-normal-expander (n-value fun forms) `(progn ,@(mapcar #'(lambda (form) `(setq ,n-value (,fun ,form ,n-value))) forms) ,n-value)) ;;; Collect-List-Expander -- Internal ;;; ;;; This function deals with the list collection case. N-Tail is the pointer ;;; to the current tail of the list, which is NIL if the list is empty. ;;; (defun collect-list-expander (n-value n-tail forms) (let ((n-res (gensym))) `(progn ,@(mapcar #'(lambda (form) `(let ((,n-res (cons ,form nil))) (cond (,n-tail (setf (cdr ,n-tail) ,n-res) (setq ,n-tail ,n-res)) (t (setq ,n-tail ,n-res ,n-value ,n-res))))) forms) ,n-value))) ;;; Collect -- Public ;;; ;;; The ultimate collection macro... ;;; (defmacro collect (collections &body body) "Collect ({(Name [Initial-Value] [Function])}*) {Form}* Collect some values somehow. Each of the collections specifies a bunch of things which collected during the evaluation of the body of the form. The name of the collection is used to define a local macro, a la MACROLET. Within the body, this macro will evaluate each of its arguments and collect the result, returning the current value after the collection is done. The body is evaluated as a PROGN; to get the final values when you are done, just call the collection macro with no arguments. Initial-Value is the value that the collection starts out with, which defaults to NIL. Function is the function which does the collection. It is a function which will accept two arguments: the value to be collected and the current collection. The result of the function is made the new value for the collection. As a totally magical special-case, the Function may be Collect, which tells us to build a list in forward order; this is the default. If an Initial-Value is supplied for Collect, the stuff will be rplacd'd onto the end. Note that Function may be anything that can appear in the functional position, including macros and lambdas." (let ((macros ()) (binds ())) (dolist (spec collections) (unless (<= 1 (length spec) 3) (error "Malformed collection specifier: ~S." spec)) (let ((n-value (gensym)) (name (first spec)) (default (second spec)) (kind (or (third spec) 'collect))) (push `(,n-value ,default) binds) (if (eq kind 'collect) (let ((n-tail (gensym))) (if default (push `(,n-tail (last ,n-value)) binds) (push n-tail binds)) (push `(,name (&rest args) (collect-list-expander ',n-value ',n-tail args)) macros)) (push `(,name (&rest args) (collect-normal-expander ',n-value ',kind args)) macros)))) `(macrolet ,macros (let* ,(nreverse binds) ,@body)))) (provide 'collect) abcl-src-1.9.0/src/org/armedbear/lisp/compile-file-pathname.lisp0100644 0000000 0000000 00000003565 14202767264 023261 0ustar000000000 0000000 ;;; compile-file-pathname.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun compile-file-pathname (input-file &key output-file &allow-other-keys) (let ((defaults (make-pathname :type *compile-file-type* :defaults (merge-pathnames input-file)))) (cond ((null output-file) defaults) (t (merge-pathnames output-file defaults))))) abcl-src-1.9.0/src/org/armedbear/lisp/compile-file.lisp0100644 0000000 0000000 00000137320 14242624277 021463 0ustar000000000 0000000 ;;; compile-file.lisp ;;; ;;; Copyright (C) 2004-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require "COMPILER-PASS2") (export 'compile-file-if-needed) (defvar *fbound-names*) (defvar *class-number*) (defvar *output-file-pathname*) (defvar *toplevel-functions*) (defvar *toplevel-macros*) (defvar *toplevel-exports*) (defvar *toplevel-setf-expanders*) (defvar *toplevel-setf-functions*) (defun base-classname (&optional (output-file-pathname *output-file-pathname*)) (sanitize-class-name (pathname-name output-file-pathname))) (defun fasl-loader-classname (&optional (output-file-pathname *output-file-pathname*)) (%format nil "~A_0" (base-classname output-file-pathname))) (declaim (ftype (function (t) t) compute-classfile)) (defun compute-classfile (n &optional (output-file-pathname *output-file-pathname*)) "Computes the pathname of the class file associated with number `n'." (let ((name (sanitize-class-name (%format nil "~A_~D" (pathname-name output-file-pathname) n)))) (merge-pathnames (make-pathname :name name :type *compile-file-class-extension*) output-file-pathname))) (defun sanitize-class-name (name) (let ((name (copy-seq name))) (dotimes (i (length name)) (declare (type fixnum i)) (when (or (char= (char name i) #\-) (char= (char name i) #\.) (char= (char name i) #\Space)) (setf (char name i) #\_))) name)) (declaim (ftype (function () t) next-classfile)) (defun next-classfile () (compute-classfile (incf *class-number*))) (defmacro report-error (&rest forms) `(handler-case (progn ,@forms) (compiler-unsupported-feature-error (condition) (fresh-line) (%format t "; UNSUPPORTED-FEATURE: ~A~%" condition) (values nil condition)))) ;; Dummy function. Should never be called. (defun dummy (&rest ignored) (declare (ignore ignored)) (assert nil)) ;;; ??? rename to something shorter? (defparameter *compiler-diagnostic* nil "The stream to emit compiler diagnostic messages to, or nil to muffle output.") (export '*compiler-diagnostic*) (defun diag (format &rest args) (apply #'cl:format *compiler-diagnostic* (cl:concatenate 'string "~&SYSTEM::*COMPILER-DIAGNOSTIC* " format "~&") (when args args))) (declaim (ftype (function (t) t) verify-load)) (defun verify-load (classfile &key (force nil)) "Return whether the file at the path denoted by CLASSFILE is a loadable JVM artifact." (declare (ignore force)) (unless classfile (diag "Nil classfile argument passed to verify-load.") (return-from verify-load nil)) (with-open-file (cf classfile :direction :input) (when (= 0 (file-length cf)) ;;; TODO hook into a real ABCL compiler condition hierarchy (diag "Internal compiler error detected: Fasl contains ~ zero-length jvm classfile corresponding to ~A." classfile) (return-from verify-load nil))) ;; ### FIXME ;; The section below can't work, because we have ;; circular references between classes of outer- and innerscoped ;; functions. We need the class loader to resolve these circular ;; references for us. Our FASL class loader does exactly that, ;; so we need a class loader here which knows how to find ;; all the .cls files related to the current scope being loaded. #+nil (when (or force (> *safety* *speed*)) (diag "Testing compiled bytecode by loading classfile into JVM.") (let ((*load-truename* *output-file-pathname*)) ;; load-compiled-function used to be wrapped via report-error (return-from verify-load (load-compiled-function classfile)))) t) (declaim (ftype (function (t) t) note-toplevel-form)) (defun note-toplevel-form (form) (when *compile-print* (fresh-line) (princ "; ") (let ((*print-length* 2) (*print-level* 2) (*print-pretty* nil)) (prin1 form)) (terpri))) (defun output-form (form) (if *binary-fasls* (push form *forms-for-output*) (progn (dump-form form *fasl-stream*) (%stream-terpri *fasl-stream*)))) (defun finalize-fasl-output () (when *binary-fasls* (let ((*package* (find-package :keyword)) (*double-colon-package-separators* T)) (dump-form (convert-toplevel-form (list* 'PROGN (nreverse *forms-for-output*)) t) *fasl-stream*)) (%stream-terpri *fasl-stream*))) (declaim (ftype (function (t) t) simple-toplevel-form-p)) (defun simple-toplevel-form-p (form) "Returns NIL if the form is too complex to become an interpreted toplevel form, non-NIL if it is 'simple enough'." (and (consp form) (every #'(lambda (arg) (or (and (atom arg) (not (and (symbolp arg) (symbol-macro-p arg)))) (and (consp arg) (eq 'QUOTE (car arg))))) (cdr form)))) (declaim (ftype (function (t t) t) convert-toplevel-form)) (defun convert-toplevel-form (form declare-inline) (when (or (simple-toplevel-form-p form) (and (eq (car form) 'SETQ) ;; for SETQ, look at the evaluated part (simple-toplevel-form-p (third form)))) ;; single form with simple or constant arguments ;; Without this exception, toplevel function calls ;; will be compiled into lambdas which get compiled to ;; compiled-functions. Those need to be loaded. ;; Conclusion: Top level interpreting the function call ;; and its arguments may be (and should be) more efficient. (return-from convert-toplevel-form (precompiler:precompile-form form nil *compile-file-environment*))) (let* ((toplevel-form (third form)) (expr `(lambda () ,form)) (saved-class-number *class-number*) (classfile (next-classfile)) (result (with-open-file (f classfile :direction :output :element-type '(unsigned-byte 8) :if-exists :supersede) (report-error (jvm:compile-defun nil expr *compile-file-environment* classfile f declare-inline)))) (compiled-function (verify-load classfile))) (declare (ignore toplevel-form result)) (progn #+nil (when (> *debug* 0) ;; TODO (annotate form toplevel-form classfile compiled-function fasl-class-number) ;;; ??? define an API by perhaps exporting these symbols? (setf (getf form 'form-source) toplevel-form (getf form 'classfile) classfile (getf form 'compiled-function) compiled-function (getf form 'class-number) saved-class-number)) (setf form (if compiled-function `(funcall (sys::get-fasl-function *fasl-loader* ,saved-class-number)) (precompiler:precompile-form form nil *compile-file-environment*)))))) (declaim (ftype (function (t stream t) t) process-progn)) (defun process-progn (forms stream compile-time-too) (dolist (form forms) (process-toplevel-form form stream compile-time-too)) nil) (declaim (ftype (function (t t t) t) process-toplevel-form)) (defun precompile-toplevel-form (form stream compile-time-too) (declare (ignore stream)) (let ((form (precompiler:precompile-form form nil *compile-file-environment*))) (when compile-time-too (eval form)) form)) (defun process-toplevel-macrolet (form stream compile-time-too) (let ((*compile-file-environment* (make-environment *compile-file-environment*))) (dolist (definition (cadr form)) (environment-add-macro-definition *compile-file-environment* (car definition) (make-macro (car definition) (make-macro-expander definition)))) (dolist (body-form (cddr form)) (process-toplevel-form body-form stream compile-time-too))) nil) (declaim (ftype (function (t t t) t) process-toplevel-defconstant)) (defun process-toplevel-defconstant (form stream compile-time-too) (declare (ignore stream compile-time-too)) ;; "If a DEFCONSTANT form appears as a top level form, the compiler ;; must recognize that [the] name names a constant variable. An ;; implementation may choose to evaluate the value-form at compile ;; time, load time, or both. Therefore, users must ensure that the ;; initial-value can be evaluated at compile time (regardless of ;; whether or not references to name appear in the file) and that ;; it always evaluates to the same value." (note-toplevel-form form) (eval form) ;;; emit make-array when initial-value is a specialized vector (let ((initial-value (third form))) (when (and (atom initial-value) (arrayp initial-value) (= (length (array-dimensions initial-value)) 1) (not (eq (array-element-type initial-value) t))) (setf (third form) `(common-lisp:make-array ',(array-dimensions initial-value) :element-type ',(array-element-type initial-value) :initial-contents ',(coerce initial-value 'list))))) `(progn (sys:put ',(second form) 'sys::source (cl:cons '(,(second form) ,(namestring *source*) ,*source-position*) (cl:get ',(second form) 'sys::source nil))) ,form)) (declaim (ftype (function (t t t) t) process-toplevel-quote)) (defun process-toplevel-quote (form stream compile-time-too) (declare (ignore stream)) (when compile-time-too (eval form)) nil) (declaim (ftype (function (t t t) t) process-toplevel-import)) (defun process-toplevel-import (form stream compile-time-too) (declare (ignore stream)) (let ((form (precompiler:precompile-form form nil *compile-file-environment*))) (let ((*package* +keyword-package+)) (output-form form)) (when compile-time-too (eval form))) nil) (declaim (ftype (function (t t t) t) process-toplevel-export)) (defun process-toplevel-export (form stream compile-time-too) (when (and (listp (second form)) (eq (car (second form)) 'QUOTE)) ;; constant export list (let ((sym-or-syms (second (second form)))) (setf *toplevel-exports* (append *toplevel-exports* (if (listp sym-or-syms) sym-or-syms (list sym-or-syms)))))) (precompile-toplevel-form form stream compile-time-too)) (declaim (ftype (function (t t t) t) process-record-source-information)) (defun process-record-source-information (form stream compile-time-too) (declare (ignore stream compile-time-too)) (let* ((name (second form)) (type (third form))) (when (quoted-form-p name) (setq name (second name))) (when (quoted-form-p type) (setq type (second type))) (let ((sym (if (consp name) (second name) name))) `(sys:put ',sym 'sys::source (cl:cons '(,type ,(namestring *source*) ,*source-position*) (cl:get ',sym 'sys::source nil)))))) (declaim (ftype (function (t t t) t) process-toplevel-mop.ensure-method)) (defun process-toplevel-mop.ensure-method (form stream compile-time-too) (declare (ignore stream)) (flet ((convert-ensure-method (form key) (let* ((tail (cddr form)) (function-form (getf tail key))) (when (and function-form (consp function-form) (eq (%car function-form) 'FUNCTION)) (let ((lambda-expression (cadr function-form))) (jvm::with-saved-compiler-policy (let* ((saved-class-number *class-number*) (classfile (next-classfile)) (result (with-open-file (f classfile :direction :output :element-type '(unsigned-byte 8) :if-exists :supersede) (report-error (jvm:compile-defun nil lambda-expression *compile-file-environment* classfile f nil)))) (compiled-function (verify-load classfile))) (declare (ignore result)) (cond (compiled-function (setf (getf tail key) `(sys::get-fasl-function *fasl-loader* ,saved-class-number))) (t ;; FIXME This should be a warning or error of some sort... (format *error-output* "; Unable to compile method~%")))))))))) (when compile-time-too (let* ((copy-form (copy-tree form)) ;; ### Ideally, the precompiler would leave the forms alone ;; and copy them where required, instead of forcing us to ;; do a deep copy in advance (precompiled-form (precompiler:precompile-form copy-form nil *compile-file-environment*))) (eval precompiled-form))) (convert-ensure-method form :function) (convert-ensure-method form :fast-function)) (precompiler:precompile-form form nil *compile-file-environment*)) (declaim (ftype (function (t t t) t) process-toplevel-defvar/defparameter)) (defun process-toplevel-defvar/defparameter (form stream compile-time-too) (declare (ignore stream)) (note-toplevel-form form) (if compile-time-too (eval form) ;; "If a DEFVAR or DEFPARAMETER form appears as a top level form, ;; the compiler must recognize that the name has been proclaimed ;; special. However, it must neither evaluate the initial-value ;; form nor assign the dynamic variable named NAME at compile ;; time." (let ((name (second form))) (%defvar name))) (let ((name (second form)) (initial-value (third form))) ;;; emit make-array when initial-value is a specialized vector (when (and (atom initial-value) (arrayp initial-value) (= (length (array-dimensions initial-value)) 1) (not (eq (array-element-type initial-value) t))) (setf (third form) `(common-lisp:make-array ',(array-dimensions initial-value) :element-type ',(array-element-type initial-value) :initial-contents ',(coerce initial-value 'list)))) `(progn (sys:put ',name 'sys::source (cl:cons (list :variable ,(namestring *source*) ,*source-position*) (cl:get ',name 'sys::source nil))) ,form))) (declaim (ftype (function (t t t) t) process-toplevel-defpackage/in-package)) (defun process-toplevel-defpackage/in-package (form stream compile-time-too) (declare (ignore stream compile-time-too)) (note-toplevel-form form) (let ((defpackage-name (and (eq (car form) 'defpackage) (intern (string (second form)) :keyword))) ) (setf form (precompiler:precompile-form form nil *compile-file-environment*)) (eval form) ;; Force package prefix to be used when dumping form. (let ((*package* +keyword-package+)) (output-form form)) ;; a bit ugly here. Since we precompile, and added ;; record-source-information we need to know where it is. ;; The defpackage is at top, so we know where the name is (though ;; it is a string by now) (if it is a defpackage) (if defpackage-name `(sys:put ,defpackage-name 'sys::source (cl:cons '(:package ,(namestring *source*) ,*source-position*) (cl:get ,defpackage-name 'sys::source nil))) nil))) (declaim (ftype (function (t t t) t) process-toplevel-declare)) (defun process-toplevel-declare (form stream compile-time-too) (declare (ignore stream compile-time-too)) (compiler-style-warn "Misplaced declaration: ~S" form) nil) (declaim (ftype (function (t t t) t) process-toplevel-progn)) (defun process-toplevel-progn (form stream compile-time-too) (process-progn (cdr form) stream compile-time-too) nil) (declaim (ftype (function (t t t) t) process-toplevel-deftype)) (defun process-toplevel-deftype (form stream compile-time-too) (declare (ignore stream compile-time-too)) (note-toplevel-form form) (eval form) `(progn (sys:put ',(second form) 'sys::source (cl:cons '(,(second form) ,(namestring *source*) ,*source-position*) (cl:get ',(second form) 'sys::source nil))) ,form)) (declaim (ftype (function (t t t) t) process-toplevel-eval-when)) (defun process-toplevel-eval-when (form stream compile-time-too) (flet ((parse-eval-when-situations (situations) "Parse an EVAL-WHEN situations list, returning three flags, (VALUES COMPILE-TOPLEVEL LOAD-TOPLEVEL EXECUTE), indicating the types of situations present in the list." ; Adapted from SBCL. (when (or (not (listp situations)) (set-difference situations '(:compile-toplevel compile :load-toplevel load :execute eval))) (error "Bad EVAL-WHEN situation list: ~S." situations)) (values (intersection '(:compile-toplevel compile) situations) (intersection '(:load-toplevel load) situations) (intersection '(:execute eval) situations)))) (multiple-value-bind (ct lt e) (parse-eval-when-situations (cadr form)) (let ((new-compile-time-too (or ct (and compile-time-too e))) (body (cddr form))) (if lt (process-progn body stream new-compile-time-too) (when new-compile-time-too (eval `(progn ,@body))))))) nil) (declaim (ftype (function (t t t) t) process-toplevel-defmethod/defgeneric)) (defun process-toplevel-defmethod/defgeneric (form stream compile-time-too) (note-toplevel-form form) (note-name-defined (second form)) (push (second form) *toplevel-functions*) (when (and (consp (second form)) (eq 'setf (first (second form)))) (push (second (second form)) *toplevel-setf-functions*)) (let ((*compile-print* nil)) (process-toplevel-form (macroexpand-1 form *compile-file-environment*) stream compile-time-too)) (let* ((sym (if (consp (second form)) (second (second form)) (second form)))) (when (eq (car form) 'defgeneric) `(progn (sys:put ',sym 'sys::source (cl:cons '((:generic-function ,(second form)) ,(namestring *source*) ,*source-position*) (cl:get ',sym 'sys::source nil))) ,@(loop for method-form in (cdddr form) when (eq (car method-form) :method) collect (multiple-value-bind (function-name qualifiers lambda-list specializers documentation declarations body) (mop::parse-defmethod `(,(second form) ,@(rest method-form))) ;;; FIXME: style points for refactoring double backquote to "normal" form `(sys:put ',sym 'sys::source (cl:cons `((:method ,',sym ,',qualifiers ,',specializers) ,,(namestring *source*) ,,*source-position*) (cl:get ',sym 'sys::source nil))))))))) (declaim (ftype (function (t t t) t) process-toplevel-locally)) (defun process-toplevel-locally (form stream compile-time-too) (jvm::with-saved-compiler-policy (multiple-value-bind (forms decls) (parse-body (cdr form) nil) (process-optimization-declarations decls) (let* ((jvm::*visible-variables* jvm::*visible-variables*) (specials (jvm::process-declarations-for-vars (cdr form) nil nil))) (dolist (special specials) (push special jvm::*visible-variables*)) (process-progn forms stream compile-time-too)))) nil) (declaim (ftype (function (t t t) t) process-toplevel-defmacro)) (defun process-toplevel-defmacro (form stream compile-time-too) (declare (ignore stream compile-time-too)) (note-toplevel-form form) (let ((name (second form))) (eval form) (push name *toplevel-macros*) (let* ((expr (function-lambda-expression (macro-function name))) (saved-class-number *class-number*) (classfile (next-classfile))) (with-open-file (f classfile :direction :output :element-type '(unsigned-byte 8) :if-exists :supersede) (ignore-errors (jvm:compile-defun nil expr *compile-file-environment* classfile f nil))) (when (null (verify-load classfile)) ;; FIXME error or warning (format *error-output* "; Unable to compile macro ~A~%" name) (return-from process-toplevel-defmacro form)) (if (special-operator-p name) `(sys:put ',name 'macroexpand-macro (sys:make-macro ',name (sys::get-fasl-function *fasl-loader* ,saved-class-number))) `(progn (sys:put ',name 'sys::source (cl:cons '(:macro ,(namestring *source*) ,*source-position*) (cl:get ',name 'sys::source nil))) (sys:fset ',name (sys:make-macro ',name (sys::get-fasl-function *fasl-loader* ,saved-class-number)) ,*source-position* ',(third form) ,(%documentation name 'cl:function))))))) (declaim (ftype (function (t t t) t) process-toplevel-defun)) (defun process-toplevel-defun (form stream compile-time-too) (declare (ignore stream)) (note-toplevel-form form) (let* ((name (second form)) (block-name (fdefinition-block-name name)) (lambda-list (third form)) (body (nthcdr 3 form))) (jvm::with-saved-compiler-policy (multiple-value-bind (body decls doc) (parse-body body) (let* ((expr `(lambda ,lambda-list ,@decls (block ,block-name ,@body))) (saved-class-number *class-number*) (classfile (next-classfile)) (internal-compiler-errors nil) (result (with-open-file (f classfile :direction :output :element-type '(unsigned-byte 8) :if-exists :supersede) (handler-bind ((internal-compiler-error #'(lambda (e) (push e internal-compiler-errors) (continue)))) (report-error (jvm:compile-defun name expr *compile-file-environment* classfile f nil))))) (compiled-function (if (not internal-compiler-errors) (verify-load classfile) nil))) (declare (ignore result)) (cond ((and (not internal-compiler-errors) compiled-function) (when compile-time-too (eval form)) (let ((sym (if (consp name) (second name) name))) (setf form `(progn (sys:put ',sym 'sys::source (cl:cons '((:function ,name) ,(namestring *source*) ,*source-position*) (cl:get ',sym 'sys::source nil))) (sys:fset ',name (sys::get-fasl-function *fasl-loader* ,saved-class-number) ,*source-position* ',lambda-list ,doc))))) (t (compiler-warn "Unable to compile function ~A. Using interpreted form instead.~%" name) (when internal-compiler-errors (dolist (e internal-compiler-errors) (format *error-output* "; ~A~%" e))) (let ((precompiled-function (precompiler:precompile-form expr nil *compile-file-environment*))) (setf form `(sys:fset ',name ,precompiled-function ,*source-position* ',lambda-list ,doc))) (when compile-time-too (eval form))))) (when (and (symbolp name) (eq (get name '%inline) 'INLINE)) ;; FIXME Need to support SETF functions too! (setf (inline-expansion name) (jvm::generate-inline-expansion block-name lambda-list (append decls body))) (output-form `(cl:setf (inline-expansion ',name) ',(inline-expansion name)))))) (push name jvm::*functions-defined-in-current-file*) (note-name-defined name) (push name *toplevel-functions*) (when (and (consp name) (or (eq 'setf (first name)) (eq 'cl:setf (first name)))) (push (second name) *toplevel-setf-functions*)) ;; If NAME is not fbound, provide a dummy definition so that ;; getSymbolFunctionOrDie() will succeed when we try to verify that ;; functions defined later in the same file can be loaded correctly. (unless (fboundp name) (setf (fdefinition name) #'dummy) (push name *fbound-names*))) form) ;; toplevel handlers ;; each toplevel handler takes a form and stream as input (defun install-toplevel-handler (symbol handler) (setf (get symbol 'toplevel-handler) handler)) (dolist (pair '((COMPILER-DEFSTRUCT precompile-toplevel-form) (DECLARE process-toplevel-declare) (DEFCONSTANT process-toplevel-defconstant) (DEFGENERIC process-toplevel-defmethod/defgeneric) (DEFMACRO process-toplevel-defmacro) (DEFMETHOD process-toplevel-defmethod/defgeneric) (DEFPACKAGE process-toplevel-defpackage/in-package) (DEFPARAMETER process-toplevel-defvar/defparameter) (DEFTYPE process-toplevel-deftype) (DEFUN process-toplevel-defun) (DEFVAR process-toplevel-defvar/defparameter) (EVAL-WHEN process-toplevel-eval-when) (EXPORT process-toplevel-export) (IMPORT process-toplevel-import) (IN-PACKAGE process-toplevel-defpackage/in-package) (LOCALLY process-toplevel-locally) (MACROLET process-toplevel-macrolet) (PROCLAIM precompile-toplevel-form) (PROGN process-toplevel-progn) (PROVIDE precompile-toplevel-form) (PUT precompile-toplevel-form) (QUOTE process-toplevel-quote) (REQUIRE precompile-toplevel-form) (SHADOW precompile-toplevel-form) (%SET-FDEFINITION precompile-toplevel-form) (MOP::ENSURE-METHOD process-toplevel-mop.ensure-method) (record-source-information-for-type process-record-source-information))) (install-toplevel-handler (car pair) (cadr pair))) (declaim (ftype (function (t stream t) t) process-toplevel-form)) (defun process-toplevel-form (form stream compile-time-too) (unless (atom form) (let* ((operator (%car form)) (handler (get operator 'toplevel-handler))) (when handler (let ((out-form (funcall handler form stream compile-time-too))) (when out-form (output-form out-form))) (return-from process-toplevel-form)) (when (and (symbolp operator) (macro-function operator *compile-file-environment*)) (when (eq operator 'define-setf-expander) (push (second form) *toplevel-setf-expanders*)) (when (and (eq operator 'defsetf) (consp (third form))) ;; long form of DEFSETF (push (second form) *toplevel-setf-expanders*)) (note-toplevel-form form) ;; Note that we want MACROEXPAND-1 and not MACROEXPAND here, in ;; case the form being expanded expands into something that needs ;; special handling by PROCESS-TOPLEVEL-FORM (e.g. DEFMACRO). (let ((*compile-print* nil)) (process-toplevel-form (macroexpand-1 form *compile-file-environment*) stream compile-time-too)) (return-from process-toplevel-form)) (cond ((and (symbolp operator) (not (special-operator-p operator)) (null (cdr form))) (setf form (precompiler:precompile-form form nil *compile-file-environment*))) (t (note-toplevel-form form) (setf form (convert-toplevel-form form nil))))) (when (consp form) (output-form form))) ;; Make sure the compiled-function loader knows where ;; to load the compiled functions. Note that this trickery ;; was already used in verify-load before I used it, ;; however, binding *load-truename* isn't fully compliant, I think. (when compile-time-too (let ((*load-truename* *output-file-pathname*) (*fasl-loader* (make-fasl-class-loader (concatenate 'string "org.armedbear.lisp." (base-classname))))) (eval form)))) (defun populate-zip-fasl (output-file) (let* ((type ;; Don't use ".zip", it'll result in an extension with ;; a dot, which is rejected by NAMESTRING (%format nil "~A~A" (pathname-type output-file) "-zip")) (output-file (if (logical-pathname-p output-file) (translate-logical-pathname output-file) output-file)) (zipfile (if (find :windows *features*) (make-pathname :defaults output-file :type type) (make-pathname :defaults output-file :type type :device :unspecific))) (pathnames nil) (fasl-loader (make-pathname :defaults output-file :name (fasl-loader-classname) :type *compile-file-class-extension*))) (when (probe-file fasl-loader) (push fasl-loader pathnames)) (dotimes (i *class-number*) (let ((truename (probe-file (compute-classfile (1+ i))))) (when truename (push truename pathnames) ;;; XXX it would be better to just use the recorded number ;;; of class constants, but probing for the first at least ;;; makes this subjectively bearable. (when (probe-file (make-pathname :name (format nil "~A_0" (pathname-name truename)) :type "clc" :defaults truename)) (dolist (resource (directory (make-pathname :name (format nil "~A_*" (pathname-name truename)) :type "clc" :defaults truename))) (push resource pathnames)))))) (setf pathnames (nreverse (remove nil pathnames))) (let ((load-file (make-pathname :defaults output-file :name "__loader__" :type "_"))) (rename-file output-file load-file) (push load-file pathnames)) (zip zipfile pathnames) (dolist (pathname pathnames) (ignore-errors (delete-file pathname))) (rename-file zipfile output-file))) (defun write-fasl-prologue (stream in-package) "Write the forms that form the fasl to STREAM. The last form will use IN-PACKAGE to set the *package* to its value when COMPILE-FILE was invoked." (let ((out stream) (*package* (find-package :keyword))) ;; write header (write "; -*- Mode: Lisp -*-" :escape nil :stream out) (%stream-terpri out) (write (list 'sys:init-fasl :version *fasl-version*) :stream out) (%stream-terpri out) (write (list 'cl:setq 'sys:*source* *compile-file-truename*) :stream out) (%stream-terpri out) ;; Note: Beyond this point, you can't use DUMP-FORM, ;; because the list of uninterned symbols has been fixed now. (when *fasl-uninterned-symbols* (write (list 'cl:setq 'sys::*fasl-uninterned-symbols* (coerce (mapcar #'car (nreverse *fasl-uninterned-symbols*)) 'vector)) :stream out :length nil)) (%stream-terpri out) (when (> *class-number* 0) (write (list 'cl:setq 'sys:*fasl-loader* `(sys::make-fasl-class-loader ,(concatenate 'string "org.armedbear.lisp." (base-classname)))) :stream out)) (%stream-terpri out) (write `(in-package ,(package-name in-package)) :stream out) (%stream-terpri out))) (defvar *binary-fasls* nil) (defvar *forms-for-output* nil) (defvar *fasl-stream* nil) (defun compile-from-stream (in output-file temp-file temp-file2 extract-toplevel-funcs-and-macros functions-file macros-file exports-file setf-functions-file setf-expanders-file) (let* ((*compile-file-pathname* (make-pathname :defaults (pathname in) :version nil)) (*compile-file-truename* (make-pathname :defaults (truename in) :version nil)) (*source* *compile-file-truename*) (*class-number* 0) (namestring (namestring *compile-file-truename*)) (start (get-internal-real-time)) *fasl-uninterned-symbols* (warnings-p nil) (in-package *package*) (failure-p nil)) (when *compile-verbose* (format t "; Compiling ~A ...~%" namestring)) (with-compilation-unit () (with-open-file (out temp-file :direction :output :if-exists :supersede :external-format *fasl-external-format*) (let ((*readtable* *readtable*) (*read-default-float-format* *read-default-float-format*) (*read-base* *read-base*) (*package* *package*) (jvm::*functions-defined-in-current-file* '()) (*fbound-names* '()) (*fasl-stream* out) *forms-for-output*) (jvm::with-saved-compiler-policy (jvm::with-file-compilation (handler-bind ((style-warning #'(lambda (c) (setf warnings-p t) ;; let outer handlers do their thing (signal c) ;; prevent the next handler ;; from running: we're a ;; WARNING subclass (continue))) ((or warning compiler-error) #'(lambda (c) (declare (ignore c)) (setf warnings-p t failure-p t)))) (loop (let* ((*source-position* (file-position in)) (jvm::*source-line-number* (stream-line-number in)) (form (read in nil in)) (*compiler-error-context* form)) (when (eq form in) (return)) (cond ((>= (length (format nil "~a" form)) 65536) ;; Following the solution propose here: ;; see https://github.com/armedbear/abcl/issues/246#issuecomment-698854437 ;; just include the offending interpreted form in the loader ;; using it instead of the compiled representation (diag "Falling back to interpreted version of top-level form longer ~ than 65535 bytes") (write (ext:macroexpand-all form *compile-file-environment*) :stream out)) (t (process-toplevel-form form out nil)))))) (finalize-fasl-output) (dolist (name *fbound-names*) (fmakunbound name))))))) (when extract-toplevel-funcs-and-macros (setf *toplevel-functions* (remove-if-not (lambda (func-name) (if (symbolp func-name) (symbol-package func-name) T)) (remove-duplicates *toplevel-functions*))) (when *toplevel-functions* (with-open-file (f-out functions-file :direction :output :if-does-not-exist :create :if-exists :supersede) (let ((*package* (find-package :keyword))) (write *toplevel-functions* :stream f-out)))) (setf *toplevel-macros* (remove-if-not (lambda (mac-name) (if (symbolp mac-name) (symbol-package mac-name) T)) (remove-duplicates *toplevel-macros*))) (when *toplevel-macros* (with-open-file (m-out macros-file :direction :output :if-does-not-exist :create :if-exists :supersede) (let ((*package* (find-package :keyword))) (write *toplevel-macros* :stream m-out)))) (setf *toplevel-exports* (remove-if-not (lambda (sym) (if (symbolp sym) (symbol-package sym) T)) (remove-duplicates *toplevel-exports*))) (when *toplevel-exports* (with-open-file (e-out exports-file :direction :output :if-does-not-exist :create :if-exists :supersede) (let ((*package* (find-package :keyword))) (write *toplevel-exports* :stream e-out)))) (setf *toplevel-setf-functions* (remove-if-not (lambda (sym) (if (symbolp sym) (symbol-package sym) T)) (remove-duplicates *toplevel-setf-functions*))) (when *toplevel-setf-functions* (with-open-file (e-out setf-functions-file :direction :output :if-does-not-exist :create :if-exists :supersede) (let ((*package* (find-package :keyword))) (write *toplevel-setf-functions* :stream e-out)))) (setf *toplevel-setf-expanders* (remove-if-not (lambda (sym) (if (symbolp sym) (symbol-package sym) T)) (remove-duplicates *toplevel-setf-expanders*))) (when *toplevel-setf-expanders* (with-open-file (e-out setf-expanders-file :direction :output :if-does-not-exist :create :if-exists :supersede) (let ((*package* (find-package :keyword))) (write *toplevel-setf-expanders* :stream e-out))))) (with-open-file (in temp-file :direction :input :external-format *fasl-external-format*) (with-open-file (out temp-file2 :direction :output :if-does-not-exist :create :if-exists :supersede :external-format *fasl-external-format*) (let ((*package* (find-package :keyword)) (*print-fasl* t) (*print-array* t) (*print-base* 10) (*print-case* :upcase) (*print-circle* nil) (*print-escape* t) (*print-gensym* t) (*print-length* nil) (*print-level* nil) (*print-lines* nil) (*print-pretty* nil) (*print-radix* nil) (*print-readably* t) (*print-right-margin* nil) (*print-structure* t) ;; make sure to write all floats with their exponent marker: ;; the dump-time default may not be the same at load-time (*read-default-float-format* nil)) ;; these values are also bound by WITH-STANDARD-IO-SYNTAX, ;; but not used by our reader/printer, so don't bind them, ;; for efficiency reasons. ;; (*read-eval* t) ;; (*read-suppress* nil) ;; (*print-miser-width* nil) ;; (*print-pprint-dispatch* (copy-pprint-dispatch nil)) ;; (*read-base* 10) ;; (*read-default-float-format* 'single-float) ;; (*readtable* (copy-readtable nil)) (write-fasl-prologue out in-package) ;; copy remaining content (loop for line = (read-line in nil :eof) while (not (eq line :eof)) do (write-line line out))))) (delete-file temp-file) (when (subtypep (type-of output-file) 'jar-pathname) (remove-zip-cache-entry output-file)) (rename-file temp-file2 output-file) (when *compile-file-zip* (populate-zip-fasl output-file)) (when *compile-verbose* (format t "~&; Wrote ~A (~A seconds)~%" (namestring output-file) (/ (- (get-internal-real-time) start) 1000.0))) (values (truename output-file) warnings-p failure-p))) (defun compile-file (input-file &key output-file ((:verbose *compile-verbose*) *compile-verbose*) ((:print *compile-print*) *compile-print*) (extract-toplevel-funcs-and-macros nil) (external-format :utf-8)) (flet ((pathname-with-type (pathname type &optional suffix) (when suffix (setq type (concatenate 'string type suffix))) (make-pathname :type type :defaults pathname))) (unless (or (and (probe-file input-file) (not (file-directory-p input-file))) (pathname-type input-file)) (let ((pathname (pathname-with-type input-file "lisp"))) (when (probe-file pathname) (setf input-file pathname)))) (setf output-file (compile-file-pathname input-file :output-file output-file)) (let* ((*output-file-pathname* output-file) (type (pathname-type output-file)) (temp-file (pathname-with-type output-file type "-tmp")) (temp-file2 (pathname-with-type output-file type "-tmp2")) (functions-file (pathname-with-type output-file "funcs")) (macros-file (pathname-with-type output-file "macs")) (exports-file (pathname-with-type output-file "exps")) (setf-functions-file (pathname-with-type output-file "setf-functions")) (setf-expanders-file (pathname-with-type output-file "setf-expanders")) *toplevel-functions* *toplevel-macros* *toplevel-exports* *toplevel-setf-functions* *toplevel-setf-expanders*) (with-open-file (in input-file :direction :input :external-format external-format) (multiple-value-bind (output-file-truename warnings-p failure-p) (compile-from-stream in output-file temp-file temp-file2 extract-toplevel-funcs-and-macros functions-file macros-file exports-file setf-functions-file setf-expanders-file) (values (truename output-file) warnings-p failure-p)))))) (defun compile-file-if-needed (input-file &rest allargs &key force-compile &allow-other-keys) (setf input-file (truename input-file)) (cond (force-compile (remf allargs :force-compile) (apply 'compile-file input-file allargs)) (t (let* ((source-write-time (file-write-date input-file)) (output-file (or (getf allargs :output-file) (compile-file-pathname input-file))) (target-write-time (and (probe-file output-file) (file-write-date output-file)))) (if (or (null target-write-time) (<= target-write-time source-write-time)) (apply #'compile-file input-file allargs) output-file))))) (provide 'compile-file) abcl-src-1.9.0/src/org/armedbear/lisp/compile-system.lisp0100644 0000000 0000000 00000055032 14223403213 022047 0ustar000000000 0000000 ;;; compile-system.lisp ;;; ;;; Copyright (C) 2004-2008 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (require "LOOP") (require "COLLECT") (require "COMPILE-FILE") (export '(grovel-java-definitions-in-file compile-system)) (defun check-lisp-home () (loop (cond ((and *lisp-home* (probe-directory (pathname *lisp-home*))) (return)) (t (cerror "Continue" "*LISP-HOME* is NIL or invalid.~% Please set *LISP-HOME* to the full pathname of the directory containing the Lisp system files."))))) (defun grovel-java-definitions-in-file (file out) (with-open-file (in file) (declare (type stream in)) (let ((system-package (find-package "SYSTEM")) (line-number 1)) (loop (let ((text (read-line in nil))) (when (null text) (return)) (let ((position (search "###" text))) (when position (let* ((name (string (read-from-string (subseq text (+ position 3))))) (symbol (or (find-symbol name system-package) ; uses CL and EXT (find-symbol name (find-package "MOP")) (find-symbol name (find-package "JAVA"))))) (when symbol ;; Force the symbol's package prefix to be written out ;; with "::" instead of ":" so there won't be a reader ;; error if a symbol that's external now is no longer ;; external when we read the tags file. (%format out "~A::~A ~S ~S~%" (package-name (symbol-package symbol)) name file line-number))))) (incf line-number)))))) (defun grovel-java-definitions () (check-lisp-home) (time (let ((files (directory (merge-pathnames "*.java" *lisp-home*)))) (with-open-file (stream (merge-pathnames "tags" *lisp-home*) :direction :output :if-exists :supersede) (dolist (file files) (grovel-java-definitions-in-file file stream)))))) ;; ;; Functions to generate autoloads.lisp ;; (defun packages-from-combos (combos) (remove-duplicates (mapcar #'symbol-package (mapcar #'sys:fdefinition-block-name (mapcar #'second combos))))) (defun remove-multi-combo-symbols (combos) (princ "; Removing multi-homed symbols") (let ((sym-hash (make-hash-table :size (* 2 (length combos))))) (dolist (combo combos) (incf (gethash (second combo) sym-hash 0))) (print (remove-if-not (lambda (x) (< 1 (gethash x sym-hash))) combos :key #'second)) (remove-if (lambda (x) (< 1 (gethash x sym-hash))) combos :key #'second))) (defun set-equal (set1 set2 &key test) (or (eq set1 set2) (equal set1 set2) (and (subsetp set2 set1 :test test) (subsetp set1 set2 :test test)))) (defun combos-to-symbol-filesets (combos) (let (filesets) (dolist (combo combos) (pushnew (list (second combo)) filesets :test #'equal :key #'first) (pushnew (first combo) (cdr (assoc (second combo) filesets :test #'equal)) :test #'string=)) filesets)) (defun combos-to-fileset-symbols (combos) (let (fileset-symbols) (dolist (symbol-fileset (combos-to-symbol-filesets combos)) (pushnew (list (cdr symbol-fileset)) fileset-symbols :test (lambda (x y) (set-equal x y :test #'string=)) :key #'first) (pushnew (first symbol-fileset) (cdr (assoc (cdr symbol-fileset) fileset-symbols :test (lambda (x y) (set-equal x y :test #'string=)))))) fileset-symbols)) (defun write-autoloader (stream package type fileset-symbols) (when fileset-symbols (write `(in-package ,package) :stream stream) (terpri stream) (let ((*package* (find-package package))) (write `(dolist (fs ',fileset-symbols) (funcall #',type (cdr fs) (car (car fs)))) :stream stream) (terpri stream)))) (defun write-package-filesets (stream package type filesets-symbols) (let* ((filter-package (find-package package)) (filtered-filesets (remove-if (lambda (x) (null (cdr x))) (mapcar (lambda (x) (cons (car x) (remove-if-not (lambda (x) (and (symbolp x) (eq (symbol-package x) filter-package))) (cdr x)))) filesets-symbols)))) (write-autoloader stream package type filtered-filesets))) (defun load-combos (path-spec) (let (all-functions) (dolist (functions-file (directory path-spec) all-functions) ;; every file has 1 form: the list of functions in it. (let ((base-name (pathname-name functions-file))) (unless (member base-name '("asdf" "gray-streams") :test #'string=) ;; exclude ASDF and GRAY-STREAMS: they have external ;; symbols we don't have until we load them, but we need ;; those symbols to read the symbols files (with-open-file (f functions-file :direction :input) (dolist (function-name (read f)) (push (list base-name function-name) all-functions)))))))) (defun generate-autoloads (symbol-files-pathspec) (labels ((filter-combos (combos) (remove-multi-combo-symbols (remove-if (lambda (x) ;; exclude the symbols from the files ;; below: putting autoloaders on some of ;; the symbols conflicts with the bootstrapping ;; Primitives which have been defined Java-side (member x '( ;; function definitions to be excluded "fdefinition" "early-defuns" "require" "signal" "restart" ;; extensible sequences override ;; lots of default functions; ;; java-collections implements ;; extensible sequences "extensible-sequences-base" "extensible-sequences" "java-collections" ;; macro definitions to be excluded "macros" ;; "backquote" "precompiler") :test #'string=)) combos :key #'first))) (filter-setf-combos (combos) (filter-combos (remove-multi-combo-symbols (remove-if (lambda (x) (member x '("clos") :test #'string=)) combos :key #'first)))) (symbols-pathspec (filespec) (merge-pathnames filespec symbol-files-pathspec))) (let ((funcs (filter-combos (load-combos (symbols-pathspec "*.funcs")))) (macs (filter-combos (load-combos (symbols-pathspec "*.macs")))) (setf-functions (filter-setf-combos (load-combos (symbols-pathspec "*.setf-functions")))) (setf-expanders (filter-setf-combos (load-combos (symbols-pathspec "*.setf-expanders")))) (exps (filter-combos (load-combos (symbols-pathspec "*.exps"))))) (with-open-file (f (symbols-pathspec "autoloads-gen.lisp") :direction :output :if-does-not-exist :create :if-exists :supersede) ;; Generate the lisp file. This file will be included after compilation, ;; so any comments are just for debugging purposes. (terpri f) (write-line ";; ---- GENERATED CONTENT BELOW" f) (terpri f) (dolist (package '(:format :sequence :loop :mop :xp :precompiler :profiler :java :jvm :extensions :threads :top-level :system :cl)) ;; Limit the set of packages: ;; During incremental compilation, the packages GRAY-STREAMS ;; and ASDF are not being created. Nor are these packages ;; vital to the correct operation of the base system. (let* ((*package* (find-package package)) (all-exported-symbols (remove-duplicates (mapcar #'second exps))) (externals (remove-if-not (lambda (sym) (eq (symbol-package sym) *package*)) all-exported-symbols))) (when externals (write-line ";; EXPORTS" f) (write `(cl:in-package ,package) :stream f) (terpri f) (write `(cl:export ',externals) :stream f) (terpri f))) (terpri f) (write-line ";; FUNCTIONS" f) (terpri f) (write-package-filesets f package 'ext:autoload (combos-to-fileset-symbols funcs)) (terpri f) (write-line ";; MACROS" f) (terpri f) (write-package-filesets f package 'ext:autoload-macro (combos-to-fileset-symbols macs)) (terpri f) (write-line ";; SETF-FUNCTIONS" f) (terpri f) (write-package-filesets f package 'ext:autoload-setf-function (combos-to-fileset-symbols setf-functions)) (terpri f) (write-line ";; SETF-EXPANDERS" f) (terpri f) (write-package-filesets f package 'ext:autoload-setf-expander (combos-to-fileset-symbols setf-expanders))))))) ;; ;; --- End of autoloads.lisp ;; (defun %compile-system (&key output-path) (let ((*default-pathname-defaults* (pathname *lisp-home*)) (*warn-on-redefinition* nil) (*prevent-fasl-circle-detection* t)) (unless output-path (setf output-path *default-pathname-defaults*)) (flet ((do-compile (file &key (extract t)) (let ((out (make-pathname :type *compile-file-type* :defaults (merge-pathnames file output-path)))) (compile-file-if-needed file :output-file out :extract-toplevel-funcs-and-macros extract)))) (load (do-compile "defstruct.lisp")) (load (do-compile "coerce.lisp")) (load (do-compile "open.lisp")) (load (do-compile "dump-form.lisp")) (load (do-compile "compiler-types.lisp")) (load (do-compile "compile-file.lisp")) (load (do-compile "precompiler.lisp")) (load (do-compile "compiler-pass1.lisp")) (load (do-compile "compiler-pass2.lisp")) (load (do-compile "jvm-class-file.lisp")) (load (do-compile "jvm.lisp")) (load (do-compile "source-transform.lisp")) (load (do-compile "compiler-macro.lisp")) (load (do-compile "jvm-instructions.lisp")) (load (do-compile "setf.lisp")) (load (do-compile "extensible-sequences-base.lisp")) (load (do-compile "require.lisp")) (load (do-compile "substitute.lisp")) (load (do-compile "clos.lisp")) (load (do-compile "mop.lisp")) ;; Order matters for these files. (mapc #'do-compile '("collect.lisp" "macros.lisp" "loop.lisp")) (load (do-compile "backquote.lisp")) (load (do-compile "early-defuns.lisp")) (load (do-compile "typep.lisp")) (load (do-compile "subtypep.lisp")) (load (do-compile "find.lisp")) (load (do-compile "print.lisp")) (load (do-compile "pprint-dispatch.lisp")) (load (do-compile "pprint.lisp")) (load (do-compile "format.lisp")) (load (do-compile "delete.lisp")) (load (do-compile "concatenate.lisp")) (load (do-compile "ldb.lisp")) (load (do-compile "destructuring-bind.lisp")) (load (do-compile "featurep.lisp")) ;; But not for these. (mapc #'do-compile '("adjoin.lisp" "and.lisp" "apropos.lisp" "arrays.lisp" "assert.lisp" "assoc.lisp" "aver.lisp" "bit-array-ops.lisp" "boole.lisp" "butlast.lisp" "byte-io.lisp" "case.lisp" "chars.lisp" "check-type.lisp" "compile-file-pathname.lisp" "compile-system.lisp" "compiler-error.lisp" "cond.lisp" "copy-seq.lisp" "copy-symbol.lisp" "count.lisp" "digest.lisp" "debug.lisp" "define-modify-macro.lisp" "define-symbol-macro.lisp" "defmacro.lisp" "defpackage.lisp" "defsetf.lisp" "deftype.lisp" "delete-duplicates.lisp" "deposit-field.lisp" "describe.lisp" "describe-compiler-policy.lisp" "directory.lisp" "disassemble.lisp" "do-all-symbols.lisp" "do-external-symbols.lisp" "do-symbols.lisp" "do.lisp" "documentation.lisp" "dolist.lisp" "dotimes.lisp" "dribble.lisp" "dump-class.lisp" "ed.lisp" "enough-namestring.lisp" "ensure-directories-exist.lisp" "error.lisp" "extensible-sequences.lisp" "fasl-concat.lisp" "fdefinition.lisp" "fill.lisp" "find-all-symbols.lisp" "get-pid.lisp" "gentemp.lisp" "gray-streams.lisp" "gui.lisp" "inline.lisp" "inspect.lisp" "java.lisp" "java-collections.lisp" "known-functions.lisp" "known-symbols.lisp" "late-setf.lisp" "lcm.lisp" "ldiff.lisp" "list-length.lisp" "list.lisp" "load.lisp" "make-hash-table.lisp" "make-load-form-saving-slots.lisp" "make-sequence.lisp" "make-string-output-stream.lisp" "make-string.lisp" "map-into.lisp" "map.lisp" "map1.lisp" "mask-field.lisp" "member-if.lisp" "mismatch.lisp" "multiple-value-bind.lisp" "multiple-value-list.lisp" "multiple-value-setq.lisp" "nsubstitute.lisp" "nth-value.lisp" "numbers.lisp" "or.lisp" "parse-integer.lisp" "parse-lambda-list.lisp" "package.lisp" "pathnames.lisp" "print-object.lisp" "print-unreadable-object.lisp" "proclaim.lisp" "profiler.lisp" "prog.lisp" "psetf.lisp" "query.lisp" "read-circle.lisp" "read-conditional.lisp" "read-from-string.lisp" "read-sequence.lisp" "reduce.lisp" "remf.lisp" "remove-duplicates.lisp" "remove.lisp" "replace.lisp" "restart.lisp" "revappend.lisp" "rotatef.lisp" "run-program.lisp" "run-shell-command.lisp" "runtime-class.lisp" "search.lisp" "sequences.lisp" "sets.lisp" "shiftf.lisp" "signal.lisp" "socket.lisp" "sort.lisp" "step.lisp" "strings.lisp" "sublis.lisp" "subst.lisp" "tailp.lisp" "threads.lisp" "time.lisp" "top-level.lisp" "trace.lisp" "tree-equal.lisp" "upgraded-complex-part-type.lisp" "with-accessors.lisp" "with-hash-table-iterator.lisp" "with-input-from-string.lisp" "with-open-file.lisp" "with-output-to-string.lisp" "with-package-iterator.lisp" "with-slots.lisp" "with-standard-io-syntax.lisp" "write-sequence.lisp")) ;; Compile ASDF after the whole ANSI system has been ;; constructed. (load (do-compile "asdf.lisp")) ;; ABCL-CONTRIB depends on ASDF (load (do-compile "abcl-contrib.lisp")) ;; With all files compiled, we need to use the symbols collected ;; to generate and compile autoloads.lisp ;; Generate the autoloads-gen file in the build directory in order ;; not to clobber the source file - that should keep the system ;; buildable (format t "; Generating autoloads...~%") (generate-autoloads output-path) ;; Compile the file in the build directory instead of the one in the ;; sources directory - the latter being for bootstrapping only. (do-compile (merge-pathnames #p"autoloads-gen.lisp" output-path) :extract nil) (do-compile "autoloads.lisp" :extract nil)) t)) (defun compile-system (&key quit (zip t) (cls-ext *compile-file-class-extension*) (abcl-ext *compile-file-type*) output-path) (let ((status -1) (*compile-file-class-extension* cls-ext) (*compile-file-type* abcl-ext)) (check-lisp-home) (time (with-compilation-unit () (let ((*compile-file-zip* zip) failure-p) (handler-bind (((or warning compiler-error) #'(lambda (c) (declare (ignore c)) (setf failure-p t) ;; only register that we had this type of signal ;; defer the actual handling to another handler nil))) (%compile-system :output-path output-path)) (unless failure-p (setf status 0))))) (create-system-logical-translations output-path) (when quit (quit :status status)))) (defun create-system-logical-translations (output-path) (let* ((dir (directory-namestring (pathname output-path))) (system (merge-pathnames "system.lisp" dir)) (home (pathname *lisp-home*)) (src (format nil "~A**/*.*" home)) (java (format nil "~A../../../**/*.*" home))) (with-open-file (s system :direction :output :if-exists :supersede) (pprint `(setf (logical-pathname-translations "sys") '(("SYS:SRC;**;*.*" ,src) ("SYS:JAVA;**;*.*" ,java))) s)))) abcl-src-1.9.0/src/org/armedbear/lisp/compiler-error.lisp0100644 0000000 0000000 00000005615 14202767264 022060 0ustar000000000 0000000 ;;; compiler-error.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (export '(*compiler-error-context* compiler-style-warn compiler-warn compiler-error internal-compiler-error compiler-unsupported)) (defvar *compiler-error-context* nil) (define-condition compiler-error (error) ()) (define-condition internal-compiler-error (compiler-error) ()) (define-condition compiler-unsupported-feature-error (compiler-error) ()) (defun compiler-style-warn (format-control &rest format-arguments) (warn 'style-warning :format-control format-control :format-arguments format-arguments)) (defun compiler-warn (format-control &rest format-arguments) (warn 'warning :format-control format-control :format-arguments format-arguments)) (defun compiler-error (format-control &rest format-arguments) (error 'compiler-error :format-control format-control :format-arguments format-arguments)) (defun internal-compiler-error (format-control &rest format-arguments) (cerror "Eventually use interpreted form instead" 'internal-compiler-error :format-control format-control :format-arguments format-arguments)) (defun compiler-unsupported (format-control &rest format-arguments) (error 'compiler-unsupported-feature-error :format-control format-control :format-arguments format-arguments)) abcl-src-1.9.0/src/org/armedbear/lisp/compiler-macro.lisp0100644 0000000 0000000 00000007424 14223403213 022010 0ustar000000000 0000000 ;;; compiler-macro.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (export 'compiler-macroexpand) (defvar *compiler-macros* (make-hash-table :test #'equal)) (defun compiler-macro-function (name &optional environment) (declare (ignore environment)) (gethash1 name (the hash-table *compiler-macros*))) (defun (setf compiler-macro-function) (new-function name &optional environment) (declare (ignore environment)) (setf (gethash name (the hash-table *compiler-macros*)) new-function)) (defmacro define-compiler-macro (name lambda-list &rest body) (let* ((form (gensym)) (env (gensym)) (block-name (fdefinition-block-name name))) (multiple-value-bind (body decls) (parse-defmacro lambda-list form body name 'defmacro :environment env ;; when we encounter an error ;; parsing the arguments in the call ;; (not in the difinition!), return ;; the arguments unmodified -- ie skip the ;; transform (see also source-transform.lisp) :error-fun `(lambda (&rest ignored) (declare (ignore ignored)) (return-from ,block-name ,form))) (let ((expander `(lambda (,form ,env) (declare (ignorable ,env)) (block ,block-name ,body)))) `(progn (record-source-information-for-type ',name :compiler-macro) (setf (compiler-macro-function ',name) (function ,expander)) ',name))))) ;;; Adapted from OpenMCL. (defun compiler-macroexpand-1 (form &optional env) (let ((expander nil) (new-form nil)) (if (and (consp form) (symbolp (%car form)) (setq expander (compiler-macro-function (%car form) env))) (values (setq new-form (funcall expander form env)) (neq new-form form)) (values form nil)))) (defun compiler-macroexpand (form &optional env) (let ((expanded-p nil)) (loop (multiple-value-bind (expansion exp-p) (compiler-macroexpand-1 form env) (if exp-p (setf form expansion expanded-p t) (return)))) (values form expanded-p))) abcl-src-1.9.0/src/org/armedbear/lisp/compiler-pass1.lisp0100644 0000000 0000000 00000170175 14202767264 021762 0ustar000000000 0000000 ;;; compiler-pass1.lisp ;;; ;;; Copyright (C) 2003-2008 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :jvm) (require "LOOP") (require "FORMAT") (require "CLOS") (require "PRINT-OBJECT") (require "COMPILER-TYPES") (require "KNOWN-FUNCTIONS") (require "KNOWN-SYMBOLS") (require "DUMP-FORM") (require "JAVA") (proclaim '(optimize speed)) (defun generate-inline-expansion (name lambda-list body &optional (args nil args-p)) "Generates code that can be used to expand a named local function inline. It can work either per-function (no args provided) or per-call." (if args-p (multiple-value-bind (body decls) (parse-body body) (expand-function-call-inline nil lambda-list ;; the forms below get wrapped ;; in a LET, making the decls ;; part of the decls of the LET. (copy-tree `(,@decls (block ,name ,@body))) args)) (cond ((intersection lambda-list '(&optional &rest &key &allow-other-keys &aux) :test #'eq) nil) (t (multiple-value-bind (body decls) (parse-body body) (setf body (copy-tree body)) `(lambda ,lambda-list ,@decls (block ,name ,@body))))))) ;;; Pass 1. (defun parse-lambda-list (lambda-list) "Breaks the lambda list into the different elements, returning the values required-vars optional-vars key-vars key-p rest-var allow-other-keys-p aux-vars whole-var env-var where each of the vars returned is a list with these elements: var - the actual variable name initform - the init form if applicable; optional, keyword and aux vars p-var - variable indicating presence keyword - the keyword argument to match against " (let ((remaining lambda-list) (state :req) keyword-required req opt key rest whole env aux key-p allow-others-p) (when (eq (car lambda-list) '&WHOLE) (let ((var (second lambda-list))) (when (memq var lambda-list-keywords) (error 'program-error :format-control "Lambda list keyword ~A found where &WHOLE ~ variable expected in lambda list ~A." :format-arguments (list var lambda-list))) (setf whole (list var)) (setf remaining (nthcdr 2 lambda-list)))) (do* ((arg (pop remaining) (pop tail)) (tail remaining tail)) ((and (null arg) (endp tail))) (let* ((allowable-previous-states ;; even if the arglist could theoretically contain the ;; keyword :req, this still works, because the cdr will ;; be NIL, meaning that the code below thinks we DIDN'T ;; find a new state. Which happens to be true. (cdr (member arg '(&whole &environment &aux &allow-other-keys &key &rest &optional :req))))) (cond (allowable-previous-states (setf keyword-required nil) ;; we have a keyword... (case arg (&key (setf key-p t)) (&rest (when (endp tail) (error 'program-error :format-control "&REST without variable in lambda list ~A." :format-arguments (list lambda-list))) (setf rest (list (pop tail)) keyword-required t)) (&allow-other-keys (unless (eq state '&KEY) (error 'program-error :format-control "&ALLOW-OTHER-KEYS outside of &KEY ~ section in lambda list ~A" :format-arguments (list lambda-list))) (setf allow-others-p t keyword-required t arg nil)) (&environment (setf env (list (pop tail)) keyword-required t ;; &ENVIRONMENT can appear anywhere; retain our last ;; state so we know what next keywords are valid arg state)) (&whole (error 'program-error :format-control "&WHOLE must appear first in lambda list ~A." :format-arguments (list lambda-list)))) (when arg ;; ### verify that the next state is valid (unless (or (null state) (member state allowable-previous-states)) (error 'program-error :format-control "~A not allowed after ~A ~ in lambda-list ~S" :format-arguments (list arg state lambda-list))) (setf state arg))) (keyword-required ;; a keyword was required, but none was found... (error 'program-error :format-control "Lambda list keyword expected, but found ~ ~A in lambda list ~A" :format-arguments (list arg lambda-list))) (t ;; a variable specification (case state (:req (push (list arg) req)) (&optional (cond ((symbolp arg) (push (list arg) opt)) ((consp arg) (push (list (car arg) (cadr arg) (caddr arg)) opt)) (t (error "Invalid &OPTIONAL variable.")))) (&key (cond ((symbolp arg) (push (list arg nil nil (sys::keywordify arg)) key)) ((consp arg) (push (list (if (consp (car arg)) (cadar arg) (car arg)) (cadr arg) (caddr arg) (if (consp (car arg)) (caar arg) (sys::keywordify (car arg)))) key)) (t (error "Invalid &KEY variable.")))) (&aux (cond ((symbolp arg) (push (list arg nil nil nil) aux)) ((consp arg) (push (list (car arg) (cadr arg) nil nil) aux)) (t (error "Invalid &aux state.")))) (t (error 'program-error :format-control "Invalid state found: ~A." :format-arguments (list state)))))))) (values (nreverse req) (nreverse opt) (nreverse key) key-p rest allow-others-p (nreverse aux) whole env))) (define-condition lambda-list-mismatch (error) ((mismatch-type :reader lambda-list-mismatch-type :initarg :mismatch-type))) (defmacro push-argument-binding (var form temp-bindings bindings) (let ((g (gensym))) `(let ((,g (gensym (symbol-name '#:temp)))) (push (list ,g ,form) ,temp-bindings) (push (list ,var ,g) ,bindings)))) (defun match-lambda-list (parsed-lambda-list arguments) (flet ((pop-required-argument () (if (null arguments) (error 'lambda-list-mismatch :mismatch-type :too-few-arguments) (pop arguments))) (var (var-info) (car var-info)) (initform (var-info) (cadr var-info)) (p-var (var-info) (caddr var-info))) (destructuring-bind (req opt key key-p rest allow-others-p aux whole env) parsed-lambda-list (declare (ignore whole env)) (let (req-bindings temp-bindings bindings ignorables) ;;Required arguments. (setf req-bindings (loop :for (var) :in req :collect `(,var ,(pop-required-argument)))) ;;Optional arguments. (when opt (dolist (var-info opt) (if arguments (progn (push-argument-binding (var var-info) (pop arguments) temp-bindings bindings) (when (p-var var-info) (push `(,(p-var var-info) t) bindings))) (progn (push `(,(var var-info) ,(initform var-info)) bindings) (when (p-var var-info) (push `(,(p-var var-info) nil) bindings))))) (setf bindings (nreverse bindings))) (unless (or key-p rest (null arguments)) (error 'lambda-list-mismatch :mismatch-type :too-many-arguments)) ;;Keyword and rest arguments. (if key-p (multiple-value-bind (kbindings ktemps kignor) (match-keyword-and-rest-args key allow-others-p rest arguments) (setf bindings (append bindings kbindings) temp-bindings (append temp-bindings ktemps) ignorables (append kignor ignorables))) (when rest (let (rest-binding) (push-argument-binding (var rest) `(list ,@arguments) temp-bindings rest-binding) (setf bindings (append bindings rest-binding))))) ;;Aux parameters. (when aux (setf bindings `(,@bindings ,@(loop :for var-info :in aux :collect `(,(var var-info) ,(initform var-info)))))) (values (append req-bindings temp-bindings bindings) ignorables))))) (defun match-keyword-and-rest-args (key allow-others-p rest arguments) (flet ((var (var-info) (car var-info)) (initform (var-info) (cadr var-info)) (p-var (var-info) (caddr var-info)) (keyword (var-info) (cadddr var-info))) (when (oddp (list-length arguments)) (error 'lambda-list-mismatch :mismatch-type :odd-number-of-keyword-arguments)) (let (temp-bindings bindings other-keys-found-p ignorables already-seen args) ;;If necessary, make up a fake argument to hold :allow-other-keys, ;;needed later. This also handles nicely: ;; 3.4.1.4.1 Suppressing Keyword Argument Checking ;;third statement. (unless (find :allow-other-keys key :key #'keyword) (let ((allow-other-keys-temp (gensym (symbol-name :allow-other-keys)))) (push allow-other-keys-temp ignorables) (push (list allow-other-keys-temp nil nil :allow-other-keys) key))) ;;First, let's bind the keyword arguments that have been passed by ;;the caller. If we encounter an unknown keyword, remember it. ;;As per the above, :allow-other-keys will never be considered ;;an unknown keyword. (loop :for var :in arguments :by #'cddr :for value :in (cdr arguments) :by #'cddr :do (let ((var-info (find var key :key #'keyword))) (if (and var-info (not (member var already-seen))) ;;var is one of the declared keyword arguments (progn (push-argument-binding (var var-info) value temp-bindings bindings) (when (p-var var-info) (push `(,(p-var var-info) t) bindings)) (push var args) (push (var var-info) args) (push var already-seen)) (let ((g (gensym))) (push `(,g ,value) temp-bindings) (push var args) (push g args) (push g ignorables) (unless var-info (setf other-keys-found-p t)))))) ;;Then, let's bind those arguments that haven't been passed in ;;to their default value, in declaration order. (let (defaults) (loop :for var-info :in key :do (unless (find (var var-info) bindings :key #'car) (push `(,(var var-info) ,(initform var-info)) defaults) (when (p-var var-info) (push `(,(p-var var-info) nil) defaults)))) (setf bindings (append (nreverse defaults) bindings))) ;;If necessary, check for unrecognized keyword arguments. (when (and other-keys-found-p (not allow-others-p)) (if (loop :for var :in arguments :by #'cddr :if (eq var :allow-other-keys) :do (return t)) ;;We know that :allow-other-keys has been passed, so we ;;can access the binding for it and be sure to get the ;;value passed by the user and not an initform. (let* ((arg (var (find :allow-other-keys key :key #'keyword))) (binding (find arg bindings :key #'car)) (form (cadr binding))) (if (constantp form) (unless (eval form) (error 'lambda-list-mismatch :mismatch-type :unknown-keyword)) (setf (cadr binding) `(or ,(cadr binding) (error 'program-error "Unrecognized keyword argument"))))) ;;TODO: it would be nice to report *which* keyword ;;is unknown (error 'lambda-list-mismatch :mismatch-type :unknown-keyword))) (when rest (setf bindings (append bindings `((,(var rest) (list ,@(nreverse args))))))) (values bindings temp-bindings ignorables)))) #||test for the above (handler-case (let ((lambda-list (multiple-value-list (jvm::parse-lambda-list '(a b &optional (c 42) &rest foo &key (bar c) baz ((kaz kuz) bar)))))) (jvm::match-lambda-list lambda-list '((print 1) 3 (print 32) :bar 2))) (jvm::lambda-list-mismatch (x) (jvm::lambda-list-mismatch-type x))) ||# (defun expand-function-call-inline (form lambda-list body args) (handler-case (multiple-value-bind (bindings ignorables) (match-lambda-list (multiple-value-list (parse-lambda-list lambda-list)) args) `(let* ,bindings ,@(when ignorables `((declare (ignorable ,@ignorables)))) ,@body)) (lambda-list-mismatch (x) (compiler-warn "Invalid function call: ~S (mismatch type: ~A)" form (lambda-list-mismatch-type x)) form))) ;; Returns a list of declared free specials, if any are found. (declaim (ftype (function (list list block-node) list) process-declarations-for-vars)) (defun process-declarations-for-vars (body variables block) (let ((free-specials '())) (dolist (subform body) (unless (and (consp subform) (eq (%car subform) 'DECLARE)) (return)) (let ((decls (%cdr subform))) (dolist (decl decls) (case (car decl) ((DYNAMIC-EXTENT FTYPE INLINE NOTINLINE OPTIMIZE) ;; Nothing to do here. ) ((IGNORE IGNORABLE) (process-ignore/ignorable (%car decl) (%cdr decl) variables)) (SPECIAL (dolist (name (%cdr decl)) (let ((variable (find-variable name variables))) (cond ((and variable ;; see comment below (and DO-ALL-SYMBOLS.11) (eq (variable-compiland variable) *current-compiland*)) (setf (variable-special-p variable) t)) (t (dformat t "adding free special ~S~%" name) (push (make-variable :name name :special-p t :block block) free-specials)))))) (TYPE (dolist (name (cddr decl)) (let ((variable (find-variable name variables))) (when (and variable ;; Don't apply a declaration in a local function to ;; a variable defined in its parent. For an example, ;; see CREATE-GREEDY-NO-ZERO-MATCHER in cl-ppcre. ;; FIXME suboptimal, since we ignore the declaration (eq (variable-compiland variable) *current-compiland*)) (setf (variable-declared-type variable) (make-compiler-type (cadr decl))))))) (t (dolist (name (cdr decl)) (let ((variable (find-variable name variables))) (when variable (setf (variable-declared-type variable) (make-compiler-type (%car decl))))))))))) free-specials)) (defun check-name (name) ;; FIXME Currently this error is signalled by the precompiler. (unless (symbolp name) (compiler-error "The variable ~S is not a symbol." name)) (when (constantp name) (compiler-error "The name of the variable ~S is already in use to name a constant." name)) name) (declaim (ftype (function (t) t) p1-body)) (defun p1-body (body) (declare (optimize speed)) (loop for form in body for processed-form = (p1 form) collect processed-form while (not (and (consp processed-form) (memq (car processed-form) '(GO RETURN-FROM THROW)))))) (defknown p1-default (t) t) (declaim (inline p1-default)) (defun p1-default (form) (declare (optimize speed)) (cons (car form) (loop for f in (cdr form) collect (p1 f)))) (defun let/let*-variables (block bindings) (loop for binding in bindings if (consp binding) collect (make-variable :name (check-name (car binding)) :initform (cadr binding) :block block) else collect (make-variable :name (check-name binding) :block block))) (defun valid-let/let*-binding-p (varspec) (when (consp varspec) (unless (<= 1 (length varspec) 2) (compiler-error "The LET/LET* binding specification ~ ~S is invalid." varspec))) T) (defun check-let/let*-bindings (bindings) (every #'valid-let/let*-binding-p bindings)) (defknown p1-let-vars (t) t) (defun p1-let-vars (block varlist) (check-let/let*-bindings varlist) (let ((vars (let/let*-variables block varlist))) (dolist (variable vars) (setf (variable-initform variable) (p1 (variable-initform variable)))) (dolist (variable vars) (push variable *visible-variables*) (push variable *all-variables*)) vars)) (defknown p1-let*-vars (t) t) (defun p1-let*-vars (block varlist) (check-let/let*-bindings varlist) (let ((vars (let/let*-variables block varlist))) (dolist (variable vars) (setf (variable-initform variable) (p1 (variable-initform variable))) (push variable *visible-variables*) (push variable *all-variables*)) vars)) (defun p1-let/let* (form) (declare (type cons form)) (let* ((*visible-variables* *visible-variables*) (block (make-let/let*-node)) (*block* block) (op (%car form)) (varlist (cadr form)) (body (cddr form))) (aver (or (eq op 'LET) (eq op 'LET*))) (when (eq op 'LET) ;; Convert to LET* if possible. (if (null (cdr varlist)) (setf op 'LET*) (dolist (varspec varlist (setf op 'LET*)) (or (atom varspec) (constantp (cadr varspec)) (eq (car varspec) (cadr varspec)) (return))))) (let ((vars (if (eq op 'LET) (p1-let-vars block varlist) (p1-let*-vars block varlist)))) ;; Check for globally declared specials. (dolist (variable vars) (when (special-variable-p (variable-name variable)) (setf (variable-special-p variable) t (let-environment-register block) t))) ;; For processing declarations, we want to walk the variable list from ;; last to first, since declarations apply to the last-defined variable ;; with the specified name. (setf (let-free-specials block) (process-declarations-for-vars body (reverse vars) block)) (setf (let-vars block) vars) ;; Make free specials visible. (dolist (variable (let-free-specials block)) (push variable *visible-variables*))) (with-saved-compiler-policy (process-optimization-declarations body) (let ((*blocks* (cons block *blocks*))) (setf body (p1-body body))) (setf (let-form block) (list* op varlist body)) block))) (defun p1-locally (form) (let* ((*visible-variables* *visible-variables*) (block (make-locally-node)) (*block* block) (free-specials (process-declarations-for-vars (cdr form) nil block))) (setf (locally-free-specials block) free-specials) (dolist (special free-specials) ;; (format t "p1-locally ~S is special~%" name) (push special *visible-variables*)) (let ((*blocks* (cons block *blocks*))) (with-saved-compiler-policy (process-optimization-declarations (cdr form)) (setf (locally-form block) (list* 'LOCALLY (p1-body (cdr form)))) block)))) (defknown p1-m-v-b (t) t) (defun p1-m-v-b (form) (when (= (length (cadr form)) 1) (let ((new-form `(let* ((,(caadr form) ,(caddr form))) ,@(cdddr form)))) (return-from p1-m-v-b (p1-let/let* new-form)))) (let* ((*visible-variables* *visible-variables*) (block (make-m-v-b-node)) (*block* block) (varlist (cadr form)) ;; Process the values-form first. ("The scopes of the name binding and ;; declarations do not include the values-form.") (values-form (p1 (caddr form))) (*blocks* (cons block *blocks*)) (body (cdddr form))) (let ((vars ())) (dolist (symbol varlist) (let ((var (make-variable :name symbol :block block))) (push var vars) (push var *visible-variables*) (push var *all-variables*))) ;; Check for globally declared specials. (dolist (variable vars) (when (special-variable-p (variable-name variable)) (setf (variable-special-p variable) t (m-v-b-environment-register block) t))) (setf (m-v-b-free-specials block) (process-declarations-for-vars body vars block)) (dolist (special (m-v-b-free-specials block)) (push special *visible-variables*)) (setf (m-v-b-vars block) (nreverse vars))) (with-saved-compiler-policy (process-optimization-declarations body) (setf body (p1-body body)) (setf (m-v-b-form block) (list* 'MULTIPLE-VALUE-BIND varlist values-form body)) block))) (defun p1-block (form) (let* ((block (make-block-node (cadr form))) (*block* block) (*blocks* (cons block *blocks*)) (form (list* (car form) (cadr form) (p1-body (cddr form))))) (setf (block-form block) form) (when (block-non-local-return-p block) ;; Add a closure variable for RETURN-FROM to use (push (setf (block-id-variable block) (make-variable :name (gensym) :block block :used-non-locally-p t)) *all-variables*)) block)) (defun p1-catch (form) (let* ((tag (p1 (cadr form))) (body (cddr form)) (block (make-catch-node)) (*block* block) ;; our subform processors need to know ;; they're enclosed in a CATCH block (*blocks* (cons block *blocks*)) (result '())) (dolist (subform body) (let ((op (and (consp subform) (%car subform)))) (push (p1 subform) result) (when (memq op '(GO RETURN-FROM THROW)) (return)))) (setf result (nreverse result)) (when (and (null (cdr result)) (consp (car result)) (eq (caar result) 'GO)) (return-from p1-catch (car result))) (push tag result) (push 'CATCH result) (setf (catch-form block) result) block)) (defun p1-threads-synchronized-on (form) (let* ((synchronized-object (p1 (cadr form))) (body (cddr form)) (block (make-synchronized-node)) (*block* block) (*blocks* (cons block *blocks*))) (setf (synchronized-form block) (list* 'threads:synchronized-on synchronized-object (p1-body body))) block)) (defun p1-java-jrun-exception-protected (form) (assert (eq (first form) 'java:jrun-exception-protected)) (assert (or (eq (car (second form)) 'lambda) (and (eq (car (second form)) 'function) (eq (car (second (second form))) 'lambda)))) (let* ((body (if (eq (car (second form)) 'lambda) (cddr (second form)) (cddr (second (second form))))) (block (make-exception-protected-node)) (*block* block) (*blocks* (cons block *blocks*))) (setf (exception-protected-form block) (p1-body body)) block)) (defun p1-unwind-protect (form) (if (= (length form) 2) (p1 (second form)) ; No cleanup forms: (unwind-protect (...)) => (...) ;; in order to compile the cleanup forms twice (see ;; p2-unwind-protect-node), we need to p1 them twice; p1 outcomes ;; can be compiled (in the same compiland?) only once. ;; ;; However, p1 transforms the forms being processed, so, we ;; need to copy the forms to create a second copy. (let* ((block (make-unwind-protect-node)) (*block* block) ;; i believe this comment is misleading... ;; - from an /opstack/ safety perspective, all forms (including cleanup) can have non-local returns ;; original comment: (and unwinding-forms and unprotected-forms were above this line previously, meaning they ;; did not fall under an unwind-protect /block/ and hence lead to stack inconsistency problems) ;; ... because only the protected form is ;; protected by the UNWIND-PROTECT block (*blocks* (cons block *blocks*)) ;; this may be ok to have /above/ the blocks decl, since these should not be present inside the ;; exception handler and are therefore opstack safe ;; my little test case passes either way (whether this is here or above) ;; /but/ if the protected-form is marked as opstack unsafe, this should be too ;; why is the protected form marked opstack unsafe? (unwinding-forms (p1-body (copy-tree (cddr form)))) ;; the unprotected-forms actually end up inside an exception handler and as such, /do/ need ;; to be marked opstack unsafe (so this is now below the *blocks* decl) ;; (this name is now misleading from an opstack safety perspective) (unprotected-forms (p1-body (cddr form))) (protected-form (p1 (cadr form)))) (setf (unwind-protect-form block) `(unwind-protect ,protected-form (progn ,@unwinding-forms) ,@unprotected-forms)) block))) (defknown p1-return-from (t) t) (defun p1-return-from (form) (let* ((name (second form)) (block (find-block name)) non-local-p) (when (null block) (compiler-error "RETURN-FROM ~S: no block named ~S is currently visible." name name)) (dformat t "p1-return-from block = ~S~%" (block-name block)) (cond ((eq (block-compiland block) *current-compiland*) ;; Local case. If the RETURN is nested inside an UNWIND-PROTECT ;; which is inside the block we're returning from, we'll do a non- ;; local return anyway so that UNWIND-PROTECT can catch it and run ;; its cleanup forms. ;;(dformat t "*blocks* = ~S~%" (mapcar #'node-name *blocks*)) (let ((protected (enclosed-by-protected-block-p block))) (dformat t "p1-return-from protected = ~S~%" protected) (if protected (setf (block-non-local-return-p block) t non-local-p t) ;; non-local GO's ensure environment restoration ;; find out about this local GO (when (null (block-needs-environment-restoration block)) (setf (block-needs-environment-restoration block) (enclosed-by-environment-setting-block-p block)))))) (t (setf (block-non-local-return-p block) t non-local-p t))) (when (block-non-local-return-p block) (dformat t "non-local return from block ~S~%" (block-name block))) (let ((value-form (p1 (caddr form)))) (push value-form (block-return-value-forms block)) (make-jump-node (list 'RETURN-FROM name value-form) non-local-p block)))) (defun p1-tagbody (form) (let* ((block (make-tagbody-node)) (*block* block) (*blocks* (cons block *blocks*)) (*visible-tags* *visible-tags*) (local-tags '()) (body (cdr form))) ;; Make all the tags visible before processing the body forms. (dolist (subform body) (when (or (symbolp subform) (integerp subform)) (let* ((tag (make-tag :name subform :label (gensym) :block block))) (push tag local-tags) (push tag *visible-tags*)))) (let ((new-body '()) (live t)) (dolist (subform body) (cond ((or (symbolp subform) (integerp subform)) (push subform new-body) (push (find subform local-tags :key #'tag-name :test #'eql) (tagbody-tags block)) (setf live t)) ((not live) ;; Nothing to do. ) (t (when (and (consp subform) (memq (%car subform) '(GO RETURN-FROM THROW))) ;; Subsequent subforms are unreachable until we see another ;; tag. (setf live nil)) (push (p1 subform) new-body)))) (setf (tagbody-form block) (list* 'TAGBODY (nreverse new-body)))) (when (some #'tag-used-non-locally (tagbody-tags block)) (push (setf (tagbody-id-variable block) (make-variable :name (gensym) :block block :used-non-locally-p t)) *all-variables*)) block)) (defknown p1-go (t) t) (defun p1-go (form) (let* ((name (cadr form)) (tag (find-tag name))) (unless tag (error "p1-go: tag not found: ~S" name)) (setf (tag-used tag) t) (let ((tag-block (tag-block tag)) non-local-p) (cond ((eq (tag-compiland tag) *current-compiland*) ;; Does the GO leave an enclosing UNWIND-PROTECT or CATCH? (if (enclosed-by-protected-block-p tag-block) (setf (tagbody-non-local-go-p tag-block) t (tag-used-non-locally tag) t non-local-p t) ;; non-local GO's ensure environment restoration ;; find out about this local GO (when (null (tagbody-needs-environment-restoration tag-block)) (setf (tagbody-needs-environment-restoration tag-block) (enclosed-by-environment-setting-block-p tag-block))))) (t (setf (tagbody-non-local-go-p tag-block) t (tag-used-non-locally tag) t non-local-p t))) (make-jump-node form non-local-p tag-block tag)))) (defun split-decls (forms specific-vars) (let ((other-decls nil) (specific-decls nil)) (dolist (form forms) (unless (and (consp form) (eq (car form) 'DECLARE)) ; shouldn't happen (return)) (dolist (decl (cdr form)) (case (car decl) ((OPTIMIZE DECLARATION DYNAMIC-EXTENT FTYPE INLINE NOTINLINE) (push (list 'DECLARE decl) other-decls)) (SPECIAL (dolist (name (cdr decl)) (if (memq name specific-vars) (push `(DECLARE (SPECIAL ,name)) specific-decls) (push `(DECLARE (SPECIAL ,name)) other-decls)))) (TYPE (dolist (name (cddr decl)) (if (memq name specific-vars) (push `(DECLARE (TYPE ,(cadr decl) ,name)) specific-decls) (push `(DECLARE (TYPE ,(cadr decl) ,name)) other-decls)))) (t (dolist (name (cdr decl)) (if (memq name specific-vars) (push `(DECLARE (,(car decl) ,name)) specific-decls) (push `(DECLARE (,(car decl) ,name)) other-decls))))))) (values (nreverse other-decls) (nreverse specific-decls)))) (defun lambda-list-names (lambda-list) "Returns a list of variable names extracted from `lambda-list'." (multiple-value-bind (req opt key key-p rest allow-key-p aux whole env) (parse-lambda-list lambda-list) (declare (ignore key-p allow-key-p)) (mapcan (lambda (x) (mapcar #'first x)) (list req opt key aux (list rest) (list whole) (list env))))) (defun lambda-list-keyword-p (x) (memq x lambda-list-keywords)) (defun rewrite-aux-vars (form) (let* ((lambda-list (cadr form)) (aux-p (memq '&AUX lambda-list)) (post-aux-&environment (memq '&ENVIRONMENT aux-p)) (lets (ldiff (cdr aux-p) post-aux-&environment)) ; strip trailing &environment aux-vars) (unless aux-p ;; no rewriting required (return-from rewrite-aux-vars form)) (dolist (var lets) (when (lambda-list-keyword-p var) (error 'program-error :format-control "Lambda list keyword ~A not allowed after &AUX in ~A." :format-arguments (list var lambda-list)))) (multiple-value-bind (body decls) (parse-body (cddr form)) (dolist (form lets) (cond ((consp form) (push (car form) aux-vars)) (t (push form aux-vars)))) (setf lambda-list (append (subseq lambda-list 0 (position '&AUX lambda-list)) post-aux-&environment)) (multiple-value-bind (let-decls lambda-decls) (split-decls decls (lambda-list-names lambda-list)) `(lambda ,lambda-list ,@lambda-decls (let* ,lets ,@let-decls ,@body)))))) (defun rewrite-lambda (form) (setf form (rewrite-aux-vars form)) (let* ((lambda-list (cadr form))) (if (not (or (memq '&optional lambda-list) (memq '&key lambda-list))) ;; no need to rewrite: no arguments with possible initforms anyway form (multiple-value-bind (body decls doc) (parse-body (cddr form)) (let (state let-bindings new-lambda-list (non-constants 0)) (do* ((vars lambda-list (cdr vars)) (var (car vars) (car vars))) ((endp vars)) (push (car vars) new-lambda-list) (let ((replacement (gensym))) (flet ((parse-compound-argument (arg) "Returns the values NAME, KEYWORD, INITFORM, INITFORM-P, SUPPLIED-P and SUPPLIED-P-P assuming ARG is a compound argument." (destructuring-bind (name &optional (initform nil initform-supplied-p) (supplied-p nil supplied-p-supplied-p)) (if (listp arg) arg (list arg)) (if (listp name) (values (cadr name) (car name) initform initform-supplied-p supplied-p supplied-p-supplied-p) (values name (make-keyword name) initform initform-supplied-p supplied-p supplied-p-supplied-p))))) (case var (&optional (setf state :optional)) (&key (setf state :key)) ((&whole &environment &rest &body &allow-other-keys) ;; do nothing special ) (t (cond ((atom var) (setf (car new-lambda-list) (if (eq state :key) (list (list (make-keyword var) replacement)) replacement)) (push (list var replacement) let-bindings)) ((constantp (second var)) ;; so, we must have a consp-type var we're looking at ;; and it has a constantp initform (multiple-value-bind (name keyword initform initform-supplied-p supplied-p supplied-p-supplied-p) (parse-compound-argument var) (let ((var-form (if (eq state :key) (list keyword replacement) replacement)) (supplied-p-replacement (gensym))) (setf (car new-lambda-list) (cond ((not initform-supplied-p) (list var-form)) ((not supplied-p-supplied-p) (list var-form initform)) (t (list var-form initform supplied-p-replacement)))) (push (list name replacement) let-bindings) ;; if there was a 'supplied-p' variable, it might ;; be used in the declarations. Since those will be ;; moved below the LET* block, we need to move the ;; supplied-p parameter too. (when supplied-p-supplied-p (push (list supplied-p supplied-p-replacement) let-bindings))))) (t (incf non-constants) ;; this is either a keyword or an optional argument ;; with a non-constantp initform (multiple-value-bind (name keyword initform initform-supplied-p supplied-p supplied-p-supplied-p) (parse-compound-argument var) (declare (ignore initform-supplied-p)) (let ((var-form (if (eq state :key) (list keyword replacement) replacement)) (supplied-p-replacement (gensym))) (setf (car new-lambda-list) (list var-form nil supplied-p-replacement)) (push (list name `(if ,supplied-p-replacement ,replacement ,initform)) let-bindings) (when supplied-p-supplied-p (push (list supplied-p supplied-p-replacement) let-bindings))))))))))) (if (zerop non-constants) ;; there was no reason to rewrite... form (let ((rv `(lambda ,(nreverse new-lambda-list) ,@(when doc (list doc)) (let* ,(nreverse let-bindings) ,@decls ,@body)))) rv))))))) (defun validate-function-name (name) (unless (or (symbolp name) (setf-function-name-p name)) (compiler-error "~S is not a valid function name." name)) name) (defun construct-flet/labels-function (definition) (let* ((name (car definition)) (block-name (fdefinition-block-name (validate-function-name name))) (lambda-list (cadr definition)) (compiland (make-compiland :name name :parent *current-compiland*)) (local-function (make-local-function :name name :compiland compiland))) (push local-function (compiland-children *current-compiland*)) (multiple-value-bind (body decls) (parse-body (cddr definition)) (setf (local-function-definition local-function) (copy-tree (cdr definition))) (setf (compiland-lambda-expression compiland) (rewrite-lambda `(lambda ,lambda-list ,@decls (block ,block-name ,@body))))) local-function)) (defun p1-flet (form) (let* ((local-functions (mapcar #'(lambda (definition) (construct-flet/labels-function definition)) (cadr form))) (*local-functions* *local-functions*)) (dolist (local-function local-functions) (p1-compiland (local-function-compiland local-function))) (dolist (local-function local-functions) (push local-function *local-functions*)) (with-saved-compiler-policy (process-optimization-declarations (cddr form)) (let* ((block (make-flet-node)) (*block* block) (*blocks* (cons block *blocks*)) (body (cddr form)) (*visible-variables* *visible-variables*)) (setf (flet-free-specials block) (process-declarations-for-vars body nil block)) (dolist (special (flet-free-specials block)) (push special *visible-variables*)) (setf body (p1-body body) ;; affects the outcome of references-needed-p (flet-form block) (list* (car form) (remove-if #'(lambda (fn) (and (inline-p (local-function-name fn)) (not (local-function-references-needed-p fn)))) local-functions) body)) block)))) (defun p1-labels (form) (let* ((local-functions (mapcar #'(lambda (definition) (construct-flet/labels-function definition)) (cadr form))) (*local-functions* *local-functions*) (*visible-variables* *visible-variables*)) (dolist (local-function local-functions) (push local-function *local-functions*)) (dolist (local-function local-functions) (p1-compiland (local-function-compiland local-function))) (let* ((block (make-labels-node)) (*block* block) (*blocks* (cons block *blocks*)) (body (cddr form)) (*visible-variables* *visible-variables*)) (setf (labels-free-specials block) (process-declarations-for-vars body nil block)) (dolist (special (labels-free-specials block)) (push special *visible-variables*)) (with-saved-compiler-policy (process-optimization-declarations (cddr form)) (setf (labels-form block) (list* (car form) local-functions (p1-body (cddr form)))) block)))) (defknown p1-funcall (t) t) (defun p1-funcall (form) (unless (> (length form) 1) (compiler-warn "Wrong number of arguments for ~A." (car form)) (return-from p1-funcall form)) (let ((function-form (%cadr form))) (when (and (consp function-form) (eq (%car function-form) 'FUNCTION)) (let ((name (%cadr function-form))) (let ((source-transform (source-transform name))) (when source-transform (let ((new-form (expand-source-transform (list* name (cddr form))))) (return-from p1-funcall (p1 new-form))) ))))) ;; Otherwise... (p1-function-call form)) (defun p1-function (form) (let ((form (copy-tree form)) local-function) (cond ((and (consp (cadr form)) (or (eq (caadr form) 'LAMBDA) (eq (caadr form) 'NAMED-LAMBDA))) (let* ((named-lambda-p (eq (caadr form) 'NAMED-LAMBDA)) (named-lambda-form (when named-lambda-p (cadr form))) (name (when named-lambda-p (cadr named-lambda-form))) (lambda-form (if named-lambda-p (cons 'LAMBDA (cddr named-lambda-form)) (cadr form))) (lambda-list (cadr lambda-form)) (body (cddr lambda-form)) (compiland (make-compiland :name (if named-lambda-p name (gensym "ANONYMOUS-LAMBDA-")) :lambda-expression lambda-form :parent *current-compiland*)) (local-function (make-local-function :compiland compiland))) (push local-function (compiland-children *current-compiland*)) (multiple-value-bind (body decls) (parse-body body) (setf (compiland-lambda-expression compiland) ;; if there still was a doc-string present, remove it (rewrite-lambda `(lambda ,lambda-list ,@decls ,@body))) (let ((*visible-variables* *visible-variables*) (*current-compiland* compiland)) (p1-compiland compiland))) (list 'FUNCTION local-function))) ((setf local-function (find-local-function (cadr form))) (dformat "p1-function local function ~S~%" (cadr form)) ;;we found out that the function needs a reference (setf (local-function-references-needed-p local-function) t) form) (t form)))) (defun p1-lambda (form) (setf form (rewrite-lambda form)) (let* ((lambda-list (cadr form))) (when (or (memq '&optional lambda-list) (memq '&key lambda-list)) (let ((state nil)) (dolist (arg lambda-list) (cond ((memq arg lambda-list-keywords) (setf state arg)) ((memq state '(&optional &key)) (when (and (consp arg) (not (constantp (second arg)))) (compiler-unsupported "P1-LAMBDA: can't handle optional argument with non-constant initform."))))))) (p1-function (list 'FUNCTION form)))) (defun p1-eval-when (form) (list* (car form) (cadr form) (mapcar #'p1 (cddr form)))) (defknown p1-progv (t) t) (defun p1-progv (form) ;; We've already checked argument count in PRECOMPILE-PROGV. (let* ((symbols-form (p1 (cadr form))) (values-form (p1 (caddr form))) (block (make-progv-node)) (*block* block) (*blocks* (cons block *blocks*)) (body (cdddr form))) ;; The (commented out) block below means to detect compile-time ;; enumeration of bindings to be created (a quoted form in the symbols ;; position). ;; (when (and (quoted-form-p symbols-form) ;; (listp (second symbols-form))) ;; (dolist (name (second symbols-form)) ;; (let ((variable (make-variable :name name :special-p t))) ;; (push (setf (progv-environment-register block) t (progv-form block) `(progv ,symbols-form ,values-form ,@(p1-body body))) block)) (defun p1-quote (form) (unless (= (length form) 2) (compiler-error "Wrong number of arguments for special operator ~A (expected 1, but received ~D)." 'QUOTE (1- (length form)))) (let ((arg (%cadr form))) (if (or (numberp arg) (characterp arg)) arg form))) (defun p1-setq (form) (unless (= (length form) 3) (error "Too many arguments for SETQ.")) (let ((arg1 (%cadr form)) (arg2 (%caddr form))) (let ((variable (find-visible-variable arg1))) (if variable (progn (when (variable-ignore-p variable) (compiler-style-warn "Variable ~S is assigned even though it was declared to be ignored." (variable-name variable))) (incf (variable-writes variable)) (cond ((eq (variable-compiland variable) *current-compiland*) (dformat t "p1-setq: write ~S~%" arg1)) (t (dformat t "p1-setq: non-local write ~S~%" arg1) (setf (variable-used-non-locally-p variable) t)))) (dformat t "p1-setq: unknown variable ~S~%" arg1))) (list 'SETQ arg1 (p1 arg2)))) (defun p1-the (form) (unless (= (length form) 3) (compiler-error "Wrong number of arguments for special operator ~A (expected 2, but received ~D)." 'THE (1- (length form)))) (let ((type (%cadr form)) (expr (%caddr form))) (cond ((and (listp type) (eq (car type) 'VALUES)) ;; FIXME (p1 expr)) ((= *safety* 3) (let* ((sym (gensym)) (new-expr `(let ((,sym ,expr)) (require-type ,sym ',type) ,sym))) (p1 new-expr))) ((and (<= 1 *safety* 2) ;; at safety 1 or 2 check relatively (symbolp type)) ;; simple types (those specified by a single symbol) (let* ((sym (gensym)) (new-expr `(let ((,sym ,expr)) (require-type ,sym ',type) ,sym))) (p1 new-expr))) (t (list 'THE type (p1 expr)))))) (defun p1-truly-the (form) (unless (= (length form) 3) (compiler-error "Wrong number of arguments for special operator ~A (expected 2, but received ~D)." 'TRULY-THE (1- (length form)))) (list 'TRULY-THE (%cadr form) (p1 (%caddr form)))) (defknown p1-throw (t) t) (defun p1-throw (form) (list* 'THROW (mapcar #'p1 (cdr form)))) (defknown rewrite-function-call (t) t) (defun rewrite-function-call (form) (let ((op (car form)) (args (cdr form))) (cond ((and (eq op 'funcall) (listp (car args)) (eq (caar args) 'lambda)) ;;(funcall (lambda (...) ...) ...) (let ((op (car args)) (args (cdr args))) (expand-function-call-inline form (cadr op) (copy-tree (cddr op)) args))) ((and (listp op) (eq (car op) 'lambda)) ;;((lambda (...) ...) ...) (expand-function-call-inline form (cadr op) (copy-tree (cddr op)) args)) (t form)))) (defknown p1-function-call (t) t) (defun p1-function-call (form) (let ((new-form (rewrite-function-call form))) (when (neq new-form form) (return-from p1-function-call (p1 new-form)))) (let* ((op (car form)) (local-function (find-local-function op))) (when local-function (when (and *enable-inline-expansion* (inline-p op) (local-function-definition local-function)) (let* ((definition (local-function-definition local-function)) (lambda-list (car definition)) (body (cdr definition)) (expansion (generate-inline-expansion op lambda-list body (cdr form)))) (when expansion (let ((explain *explain*)) (when (and explain (memq :calls explain)) (format t "; inlining call to local function ~S~%" op))) (return-from p1-function-call (let ((*inline-declarations* (remove op *inline-declarations* :key #'car :test #'equal))) (p1 expansion)))))))) (p1-default form)) (defun %funcall (fn &rest args) "Dummy FUNCALL wrapper to force p1 not to optimize the call." (apply fn args)) (defun p1-variable-reference (var) (let ((variable (find-visible-variable var))) (when (null variable) (unless (or (special-variable-p var) (memq var *undefined-variables*)) (compiler-style-warn "Undefined variable ~S assumed special" var) (push var *undefined-variables*)) (setf variable (make-variable :name var :special-p t)) (push variable *visible-variables*)) (let ((ref (make-var-ref variable))) (unless (variable-special-p variable) (when (variable-ignore-p variable) (compiler-style-warn "Variable ~S is read even though it was declared to be ignored." (variable-name variable))) (push ref (variable-references variable)) (incf (variable-reads variable)) (cond ((eq (variable-compiland variable) *current-compiland*) (dformat t "p1: read ~S~%" var)) (t (dformat t "p1: non-local read ~S variable-compiland = ~S current compiland = ~S~%" var (compiland-name (variable-compiland variable)) (compiland-name *current-compiland*)) (setf (variable-used-non-locally-p variable) t)))) ref))) (defknown p1 (t) t) (defun p1 (form) (cond ((symbolp form) (let (value) (cond ((null form) form) ((eq form t) form) ((keywordp form) form) ((and (constantp form) (progn (setf value (symbol-value form)) (or (numberp value) (stringp value) (pathnamep value)))) (setf form value)) (t (p1-variable-reference form))))) ((atom form) form) (t (let ((op (%car form)) handler) (cond ((symbolp op) (when (find-local-function op) ;; local functions shadow macros and functions in ;; the global environment as well as compiler macros (return-from p1 (p1-function-call form))) (when (compiler-macro-function op) (unless (notinline-p op) (multiple-value-bind (expansion expanded-p) (compiler-macroexpand form) ;; Fall through if no change... (when expanded-p (return-from p1 (p1 expansion)))))) (cond ((setf handler (get op 'p1-handler)) (funcall handler form)) ((macro-function op *compile-file-environment*) (p1 (macroexpand form *compile-file-environment*))) ((special-operator-p op) (compiler-unsupported "P1: unsupported special operator ~S" op)) (t (p1-function-call form)))) ((and (consp op) (eq (%car op) 'LAMBDA)) (let ((maybe-optimized-call (rewrite-function-call form))) (if (eq maybe-optimized-call form) (p1 `(%funcall (function ,op) ,@(cdr form))) (p1 maybe-optimized-call)))) (t (compiler-unsupported "P1 unhandled case ~S" form))))))) (defun install-p1-handler (symbol handler) (setf (get symbol 'p1-handler) handler)) (defun initialize-p1-handlers () (dolist (pair '((AND p1-default) (BLOCK p1-block) (CATCH p1-catch) (DECLARE identity) (EVAL-WHEN p1-eval-when) (FLET p1-flet) (FUNCALL p1-funcall) (FUNCTION p1-function) (GO p1-go) (IF p1-default) ;; used to be p1-if, which was used to rewrite the test ;; form to a LET-binding; that's not necessary, because ;; the test form doesn't lead to multiple operands on the ;; operand stack (LABELS p1-labels) (LAMBDA p1-lambda) (LET p1-let/let*) (LET* p1-let/let*) (LOAD-TIME-VALUE identity) (LOCALLY p1-locally) (MULTIPLE-VALUE-BIND p1-m-v-b) (MULTIPLE-VALUE-CALL p1-default) (MULTIPLE-VALUE-LIST p1-default) (MULTIPLE-VALUE-PROG1 p1-default) (OR p1-default) (PROGN p1-default) (PROGV p1-progv) (QUOTE p1-quote) (RETURN-FROM p1-return-from) (SETQ p1-setq) (SYMBOL-MACROLET identity) (TAGBODY p1-tagbody) (THE p1-the) (THROW p1-throw) (TRULY-THE p1-truly-the) (UNWIND-PROTECT p1-unwind-protect) (THREADS:SYNCHRONIZED-ON p1-threads-synchronized-on) (JAVA:JRUN-EXCEPTION-PROTECTED p1-java-jrun-exception-protected) (JVM::WITH-INLINE-CODE identity))) (install-p1-handler (%car pair) (%cadr pair)))) (initialize-p1-handlers) (defun p1-compiland (compiland) (let ((*current-compiland* compiland) (*local-functions* *local-functions*) (*visible-variables* *visible-variables*) (form (compiland-lambda-expression compiland))) (aver (eq (car form) 'LAMBDA)) (setf form (rewrite-lambda form)) (with-saved-compiler-policy (process-optimization-declarations (cddr form)) (let* ((lambda-list (cadr form)) (body (cddr form)) (closure (make-closure `(lambda ,lambda-list nil) nil)) (syms (sys::varlist closure)) (vars nil) compiland-result) (dolist (sym syms) (let ((var (make-variable :name sym :special-p (special-variable-p sym)))) (push var vars) (push var *all-variables*) (push var *visible-variables*))) (setf (compiland-arg-vars compiland) (nreverse vars)) (let ((free-specials (process-declarations-for-vars body vars nil))) (setf (compiland-free-specials compiland) free-specials) (dolist (var free-specials) (push var *visible-variables*))) (setf compiland-result (list* 'LAMBDA lambda-list (p1-body body))) (setf (compiland-%single-valued-p compiland) (single-valued-p compiland-result)) (setf (compiland-p1-result compiland) compiland-result))))) (provide "COMPILER-PASS1") abcl-src-1.9.0/src/org/armedbear/lisp/compiler-pass2.lisp0100644 0000000 0000000 00001207377 14223403213 021751 0ustar000000000 0000000 ;;; compiler-pass2.lisp ;;; ;;; Copyright (C) 2003-2008 Peter Graves ;;; Copyright (C) 2008 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :jvm) (eval-when (:compile-toplevel :load-toplevel :execute) (require "LOOP") (require "FORMAT") (require "CLOS") (require "PRINT-OBJECT") (require "COMPILER-TYPES") (require "KNOWN-FUNCTIONS") (require "KNOWN-SYMBOLS") (require "DUMP-FORM") (require "JVM-INSTRUCTIONS") (require "JVM-CLASS-FILE") (require "JVM") (require "COMPILER-PASS1") (require "JAVA")) (declaim (inline pool-name pool-string pool-name-and-type pool-class pool-field pool-method pool-int pool-float pool-long pool-double)) (declaim (special *memory-class-loader*)) (declaim (inline pool-name pool-name-and-type pool-string pool-field pool-method pool-int pool-float pool-long pool-double add-exception-handler)) (defun pool-name (name) (pool-add-utf8 *pool* name)) (defun pool-name-and-type (name type) (pool-add-name/type *pool* name type)) (defun pool-class (name) (pool-add-class *pool* name)) (defun pool-string (string) (pool-add-string *pool* string)) (defun pool-field (class-name field-name type-name) (pool-add-field-ref *pool* class-name field-name type-name)) (defun pool-method (class-name method-name type-name) (pool-add-method-ref *pool* class-name method-name type-name)) (defun pool-int (int) (pool-add-int *pool* int)) (defun pool-float (float) (pool-add-float *pool* float)) (defun pool-long (long) (pool-add-long *pool* long)) (defun pool-double (double) (pool-add-double *pool* double)) (defun add-exception-handler (start end handler type) (code-add-exception-handler *current-code-attribute* start end handler type)) (defknown emit-push-nil () t) (declaim (inline emit-push-nil)) (defun emit-push-nil () (emit-getstatic +lisp+ "NIL" +lisp-symbol+)) (defknown emit-push-nil-symbol () t) (declaim (inline emit-push-nil-symbol)) (defun emit-push-nil-symbol () (emit-getstatic +lisp-nil+ "NIL" +lisp-symbol+)) (defknown emit-push-t () t) (declaim (inline emit-push-t)) (defun emit-push-t () (emit-getstatic +lisp+ "T" +lisp-symbol+)) (defknown emit-push-false (t) t) (defun emit-push-false (representation) (declare (optimize speed (safety 0))) (ecase representation (:boolean (emit 'iconst_0)) ((nil) (emit-push-nil)))) (defknown emit-push-true (t) t) (defun emit-push-true (representation) (declare (optimize speed (safety 0))) (ecase representation (:boolean (emit 'iconst_1)) ((nil) (emit-push-t)))) (defknown emit-push-constant-int (fixnum) t) (defun emit-push-constant-int (n) (case n (-1 (emit 'iconst_m1)) (0 (emit 'iconst_0)) (1 (emit 'iconst_1)) (2 (emit 'iconst_2)) (3 (emit 'iconst_3)) (4 (emit 'iconst_4)) (5 (emit 'iconst_5)) (t (if (<= -128 n 127) (emit 'bipush n) (if (<= -32768 n 32767) (emit 'sipush n) (emit 'ldc (pool-int n))))))) (defknown emit-push-constant-long (integer) t) (defun emit-push-constant-long (n) (case n (0 (emit 'lconst_0)) (1 (emit 'lconst_1)) (t (emit 'ldc2_w (pool-long n))))) (defknown emit-push-constant-float (single-float) t) (defun emit-push-constant-float (n) (case n (0.0s0 (emit 'fconst_0)) (1.0s0 (emit 'fconst_1)) (2.0s0 (emit 'fconst_2)) (t (emit 'ldc (pool-float n))))) (defknown emit-push-constant-double (double-float) t) (defun emit-push-constant-double (n) (case n (0.0d0 (emit 'dconst_0)) (1.0d0 (emit 'dconst_1)) (t (emit 'ldc2_w (pool-double n))))) (defknown emit-dup (symbol) t) (defun emit-dup (representation &key (past nil past-supplied-p)) "Emits the 'dup' instruction required to duplicate `representation'. If `past' is specified, the newly duplicated value is inserted on the stack past the top-most value, which is assumed to be of the representation passed in `past'." (emit (nth (if past-supplied-p (representation-size past) 0) (ecase (representation-size representation) (1 '(dup dup_x1 dup_x2)) (2 '(dup2 dup2_x1 dup2_x2)))))) (defknown emit-swap (symbol symbol) t) (defun emit-swap (rep1 rep2) "Swaps 2 values on the stack, the top-most value's representation being 'rep1'." (let ((r1-size (representation-size rep1)) (r2-size (representation-size rep2))) (cond ((and (= 1 r1-size) (= 1 r2-size)) (emit 'swap)) ((and (= 1 r1-size) (= 2 r2-size)) (emit 'dup2_x1) (emit 'pop2)) ((and (= 2 r1-size) (= 1 r2-size)) (emit 'dup_x2) (emit 'pop)) ((and (= 2 r1-size) (= 2 r2-size)) (emit 'dup2_x2) (emit 'pop2))))) (declaim (ftype (function * t) emit-invokestatic)) (defun emit-invokestatic (class-name method-name arg-types return-type) (let* ((stack-effect (apply #'descriptor-stack-effect return-type arg-types)) (index (pool-add-method-ref *pool* class-name method-name (cons return-type arg-types))) (instruction (%emit 'invokestatic index))) (setf (instruction-stack instruction) stack-effect))) (declaim (ftype (function t string) pretty-java-class)) (defun pretty-java-class (class) (cond ((equal class +lisp-object+) "LispObject") ((equal class +lisp-symbol+) "Symbol") ((equal class +lisp-thread+) "LispThread") (t class))) (defknown emit-invokevirtual (t t t t) t) (defun emit-invokevirtual (class-name method-name arg-types return-type) (let* ((stack-effect (apply #'descriptor-stack-effect return-type arg-types)) (index (pool-add-method-ref *pool* class-name method-name (cons return-type arg-types))) (instruction (%emit 'invokevirtual index))) (declare (type (signed-byte 8) stack-effect)) (let ((explain *explain*)) (when (and explain (memq :java-calls explain)) (unless (string= method-name "execute") (format t "; call to ~A ~A.~A(~{~A~^,~})~%" (pretty-java-type return-type) (pretty-java-class class-name) method-name (mapcar 'pretty-java-type arg-types))))) (setf (instruction-stack instruction) (1- stack-effect)))) (defknown emit-invokespecial-init (string list) t) (defun emit-invokespecial-init (class-name arg-types) (let* ((stack-effect (apply #'descriptor-stack-effect :void arg-types)) (index (pool-add-method-ref *pool* class-name "" (cons nil arg-types))) (instruction (%emit 'invokespecial index))) (declare (type (signed-byte 8) stack-effect)) (setf (instruction-stack instruction) (1- stack-effect)))) (defknown pretty-java-type (t) string) (defun pretty-java-type (type) (let ((arrayp nil) (pretty-string nil)) (when (and (stringp type) (> (length type) 0) (char= (char type 0) #\[)) (setf arrayp t type (subseq type 1))) (setf pretty-string (cond ((equal type +lisp-object+) "LispObject") ((equal type +lisp-symbol+) "Symbol") ((equal type +lisp-thread+) "LispThread") ((equal type :char) "char") ((equal type :int) "int") ((equal type :boolean) "boolean") ((or (null type) (eq type :void)) "void") (t type))) (when arrayp (setf pretty-string (concatenate 'string pretty-string "[]"))) pretty-string)) (declaim (inline emit-getstatic emit-putstatic)) (defknown emit-getstatic (t t t) t) (defun emit-getstatic (class-name field-name type) (let ((index (pool-add-field-ref *pool* class-name field-name type))) (%emit 'getstatic index))) (defknown emit-putstatic (t t t) t) (defun emit-putstatic (class-name field-name type) (let ((index (pool-add-field-ref *pool* class-name field-name type))) (%emit 'putstatic index))) (declaim (inline emit-getfield emit-putfield)) (defknown emit-getfield (t t t) t) (defun emit-getfield (class-name field-name type) (let* ((index (pool-add-field-ref *pool* class-name field-name type))) (%emit 'getfield index))) (defknown emit-putfield (t t t) t) (defun emit-putfield (class-name field-name type) (let* ((index (pool-add-field-ref *pool* class-name field-name type))) (%emit 'putfield index))) (defknown emit-new (t) t) (declaim (inline emit-new emit-anewarray emit-checkcast emit-instanceof)) (defun emit-new (class-name) (%emit 'new (pool-class class-name))) (defknown emit-anewarray (t) t) (defun emit-anewarray (class-name) (apply #'%emit 'anewarray (u2 (pool-class class-name)))) (defknown emit-checkcast (t) t) (defun emit-checkcast (class-name) (apply #'%emit 'checkcast (list (pool-class class-name)))) (defknown emit-instanceof (t) t) (defun emit-instanceof (class-name) (apply #'%emit 'instanceof (list (pool-class class-name)))) (defvar type-representations '((:int fixnum) (:long (integer #.most-negative-java-long #.most-positive-java-long)) (:float single-float) (:double double-float) (:char base-char character) (:boolean boolean) ) "Lists the widest Lisp types to be stored in each of the Java primitives supported (and used) by the compiler.") (defun type-representation (the-type) "Converts a type specification or compiler type into a representation." (when (null the-type) (return-from type-representation)) (do* ((types type-representations (cdr types))) ((endp types) nil) (do* ((type-list (cdr (car types)) (cdr type-list)) (type (car type-list) (car type-list))) ((endp type-list)) (when (or (subtypep the-type type) (compiler-subtypep the-type (make-compiler-type type))) (return-from type-representation (caar types)))))) (defknown emit-unbox-boolean () t) (defun emit-unbox-boolean () (emit-instanceof +lisp-nil+) (emit 'iconst_1) (emit 'ixor)) ;; 1 -> 0 && 0 -> 1: in other words, negate the low bit (defknown emit-unbox-character () t) (defun emit-unbox-character () (cond ((> *safety* 0) (emit-invokestatic +lisp-character+ "getValue" (lisp-object-arg-types 1) :char)) (t (emit-checkcast +lisp-character+) (emit-getfield +lisp-character+ "value" :char)))) ;; source type / ;; targets :boolean :char :int :long :float :double (defvar rep-conversion `((NIL . #( ,#'emit-unbox-boolean ,#'emit-unbox-character "intValue" "longValue" "floatValue" "doubleValue")) (:boolean . #( NIL :err :err :err :err :err)) (:char . #( 1 NIL :err :err :err :err)) (:int . #( 1 :err NIL i2l i2f i2d)) (:long . #( 1 :err l2i NIL l2f l2d)) (:float . #( 1 :err :err :err NIL f2d)) (:double . #( 1 :err :err :err d2f NIL))) "Contains a table with operations to be performed to do internal representation conversion.") (defvar rep-classes `((:boolean . ,+lisp-object+) (:char . ,+lisp-character+) (:int . ,+lisp-integer+) (:long . ,+lisp-integer+) (:float . ,+lisp-single-float+) (:double . ,+lisp-double-float+)) "Lists the class on which to call the `getInstance' method on, when converting the internal representation to a LispObject.") (defun convert-representation (in out) "Converts the value on the stack in the `in' representation to a value on the stack in the `out' representation." (when (eql in out) ;; no-op (return-from convert-representation)) (when (null out) ;; Convert back to a lisp object (when in (let ((class (cdr (assoc in rep-classes)))) (emit-invokestatic class "getInstance" (list in) class))) (return-from convert-representation)) (let* ((in-map (cdr (assoc in rep-conversion))) (op-num (position out '(:boolean :char :int :long :float :double))) (op (aref in-map op-num))) (when op ;; Convert from one internal representation into another (assert (neq op :err)) (cond ((eql op 1) (emit-move-from-stack nil in) (emit 'iconst_1)) ((functionp op) (funcall op)) ((stringp op) (emit-invokevirtual +lisp-object+ op nil out)) (t (emit op)))))) (defvar common-representations '((:int :long :long) (:int :float :double) (:int :double :double) (:float :int :double) (:float :double :double) (:double :int :double) (:double :float :double)) "Representations to convert unequal representations to, in order to get the correct (exact where required) comparisons.") (defun common-representation (rep1 rep2) (when (eq rep1 rep2) (return-from common-representation rep1)) (do* ((remaining common-representations (cdr remaining)) (rep (car remaining) (car remaining))) ((endp remaining)) (destructuring-bind (r1 r2 result) rep (when (and (eq rep1 r1) (eq rep2 r2)) (return-from common-representation result))))) ;; Index of local variable used to hold the current thread. (defvar *thread* nil) (defvar *initialize-thread-var* nil) (defun maybe-initialize-thread-var () (when *initialize-thread-var* (emit-invokestatic +lisp-thread+ "currentThread" nil +lisp-thread+) (astore *thread*) (setf *initialize-thread-var* nil))) (defknown ensure-thread-var-initialized () t) (declaim (inline ensure-thread-var-initialized)) (defun ensure-thread-var-initialized () (setf *initialize-thread-var* t)) (defknown emit-push-current-thread () t) (defun emit-push-current-thread () (declare (optimize speed)) (ensure-thread-var-initialized) (aload *thread*)) (defun variable-local-p (variable) "Return non-NIL if `variable' is a local variable. Special variables are not considered local." (or (variable-register variable) ;; either register or index (variable-index variable))) ;; is non-nil for local variables (defun emit-load-local-variable (variable) "Loads a local variable in the top stack position." (aver (variable-local-p variable)) (if (variable-register variable) (aload (variable-register variable)) (progn (aload (compiland-argument-register *current-compiland*)) (emit-push-constant-int (variable-index variable)) (emit 'aaload)))) (defun emit-push-variable-name (variable) (emit-load-externalized-object (variable-name variable))) (defknown generate-instanceof-type-check-for-variable (t t) t) (defun generate-instanceof-type-check-for-variable (variable expected-type) "Generate a type check for `variable'. The stack pointer is returned to the position from before the emitted code: the code is 'stack-neutral'." (declare (type symbol expected-type)) (unless (variable-local-p variable) (return-from generate-instanceof-type-check-for-variable)) (let ((instanceof-class (ecase expected-type (SYMBOL +lisp-symbol+) (CHARACTER +lisp-character+) (CONS +lisp-cons+) (HASH-TABLE +lisp-hash-table+) (FIXNUM +lisp-fixnum+) (STREAM +lisp-stream+) (STRING +lisp-abstract-string+) (VECTOR +lisp-abstract-vector+))) (expected-type-java-symbol-name (case expected-type (HASH-TABLE "HASH_TABLE") (t (symbol-name expected-type)))) (LABEL1 (gensym))) (emit-load-local-variable variable) (emit-instanceof instanceof-class) (emit 'ifne LABEL1) (emit-load-local-variable variable) (emit-getstatic +lisp-symbol+ expected-type-java-symbol-name +lisp-symbol+) (emit-invokestatic +lisp+ "type_error" (lisp-object-arg-types 2) +lisp-object+) (emit 'areturn) ; Needed for JVM stack consistency. (label LABEL1)) t) (defun find-type-for-type-check (declared-type) (if (eq declared-type :none) nil (or (when (fixnum-type-p declared-type) 'FIXNUM) (find-if #'(lambda (type) (eq type declared-type)) '(SYMBOL CHARACTER CONS HASH-TABLE)) (find-if #'(lambda (type) (subtypep declared-type type)) '(STRING VECTOR STREAM))))) (defknown generate-type-check-for-variable (t) t) (defun generate-type-check-for-variable (variable) (let ((type-to-use (find-type-for-type-check (variable-declared-type variable)))) (when type-to-use (generate-instanceof-type-check-for-variable variable type-to-use)))) (defknown maybe-generate-type-check (t) t) (defun maybe-generate-type-check (variable) (unless (or (zerop *safety*) (variable-special-p variable) ;### (eq (variable-representation variable) :int)) (let ((declared-type (variable-declared-type variable))) (unless (eq declared-type :none) (unless (subtypep (derive-type (variable-initform variable)) declared-type) (generate-type-check-for-variable variable)))))) (defknown generate-type-checks-for-variables (list) t) (defun generate-type-checks-for-variables (variables) (unless (zerop *safety*) (dolist (variable variables) (unless (variable-special-p variable) (generate-type-check-for-variable variable))) t)) (defun generate-arg-count-check (arity) (aver (fixnump arity)) (aver (not (minusp arity))) (aver (not (null (compiland-argument-register *current-compiland*)))) (let ((label1 (gensym))) (aload (compiland-argument-register *current-compiland*)) (emit 'arraylength) (emit-push-constant-int arity) (emit 'if_icmpeq label1) (aload 0) ; this (emit-invokevirtual *this-class* "argCountError" nil nil) (label label1))) (defun maybe-generate-interrupt-check () (unless (> *speed* *safety*) (let ((label1 (gensym))) (emit-getstatic +lisp+ "interrupted" :boolean) (emit 'ifeq label1) (emit-invokestatic +lisp+ "handleInterrupt" nil nil) (label label1)))) (defknown single-valued-p (t) t) (defun single-valued-p (form) (cond ((node-p form) (cond ((tagbody-node-p form) t) ((block-node-p form) (and (single-valued-p (car (last (node-form form)))) ;; return-from value forms (every #'single-valued-p (block-return-value-forms form)))) ((or (flet-node-p form) (labels-node-p form) (let/let*-node-p form) (m-v-b-node-p form) (progv-node-p form) (locally-node-p form) (synchronized-node-p form)) (single-valued-p (car (last (node-form form))))) ((unwind-protect-node-p form) (single-valued-p (second (node-form form)))) ((catch-node-p form) nil) ((jump-node-p form) (single-valued-p (node-form form))) ((exception-protected-node-p form) (single-valued-p (exception-protected-form form))) (t (assert (not "SINGLE-VALUED-P unhandled NODE-P branch"))))) ((var-ref-p form) t) ((atom form) t) (t (let ((op (%car form)) result-type compiland) (assert (not (member op '(LET LET* FLET LABELS TAGBODY CATCH MULTIPLE-VALUE-BIND UNWIND-PROTECT BLOCK PROGV LOCALLY)))) (cond ((eq op 'IF) (and (single-valued-p (third form)) (single-valued-p (fourth form)))) ((eq op 'PROGN) (single-valued-p (car (last form)))) ((memq op '(AND OR)) (every #'single-valued-p (cdr form))) ((eq op 'RETURN-FROM) (single-valued-p (third form))) ((memq op '(THE TRULY-THE)) (single-valued-p (third form))) ((setf result-type (or (function-result-type op) (and (proclaimed-ftype op) (ftype-result-type (proclaimed-ftype op))))) (cond ((eq result-type '*) nil) ((atom result-type) t) ((eq (%car result-type) 'VALUES) (= (length result-type) 2)) (t t))) ((and (setf compiland *current-compiland*) (eq op (compiland-name compiland))) (compiland-%single-valued-p compiland)) (t nil)))))) (defknown emit-clear-values () t) (defun emit-clear-values () (declare (optimize speed (safety 0))) (ensure-thread-var-initialized) (emit 'clear-values *thread*)) (defknown maybe-emit-clear-values (&rest t) t) (defun maybe-emit-clear-values (&rest forms) (declare (optimize speed)) (dolist (form forms) (unless (single-valued-p form) (ensure-thread-var-initialized) (emit 'clear-values *thread*) (return)))) (defun compile-forms-and-maybe-emit-clear-values (&rest forms-and-compile-args) (let ((forms-for-emit-clear (loop for (form arg1 arg2) on forms-and-compile-args by #'cdddr do (compile-form form arg1 arg2) collecting form))) (apply #'maybe-emit-clear-values forms-for-emit-clear))) (declaim (special *saved-operands* *operand-representations*)) (defmacro with-operand-accumulation ((&body argument-accumulation-body) &body call-body) "Macro used to operand-stack-safely collect arguments in the `argument-accumulation-body' to be available on the stack upon entry of the `call-body'. The argument-accumulation-body code may not assume arguments are actually on the stack while accumulating. This macro closes over a code-generating block. Operands can be collected using the `accumulate-operand', `compile-operand', `emit-variable-operand' and `emit-load-externalized-object-operand'." `(let (*saved-operands* *operand-representations* (*register* *register*) ) ;; hmm can we do this?? either body ;; could allocate registers ... ,@argument-accumulation-body (load-saved-operands) ,@call-body)) (defmacro accumulate-operand ((representation &key unsafe-p) &body body) "Macro used to collect a single operand. This macro closes over a code-generating block. The generated code should leave a single operand on the stack, with representation `representation'. The value `unsafe-p', when provided, is an expression evaluated at run time to indicate if the body is opstack unsafe." `(progn ,@(when unsafe-p `((when ,unsafe-p (save-existing-operands)))) ,@body (save-operand ,representation))) (defun load-saved-operands () "Load any operands which have been saved into registers back onto the stack in preparation of the execution of the opcode." (mapcar #'emit-push-register (reverse *saved-operands*) (reverse *operand-representations*))) (defun save-existing-operands () "If any operands have been compiled to the stack, save them in registers." (when (null *saved-operands*) (dolist (representation *operand-representations*) (let ((register (allocate-register representation))) (push register *saved-operands*) (emit-move-from-stack register representation))) (setf *saved-operands* (nreverse *saved-operands*)))) (defun save-operand (representation) "Saves an operand from the stack (with `representation') to a register and updates associated operand collection variables." (push representation *operand-representations*) (when *saved-operands* (let ((register (allocate-register representation))) (push register *saved-operands*) (emit-move-from-stack register representation)))) (defun compile-operand (form representation &optional cast) "Compiles `form' into `representation', storing the resulting value on the operand stack, if it's safe to do so. Otherwise stores the value in a register" (let ((unsafe (or *saved-operands* (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks form))))) (when (and unsafe (null *saved-operands*)) (save-existing-operands)) (compile-form form 'stack representation) (when cast (emit-checkcast cast)) (when unsafe (let ((register (allocate-register representation))) (push register *saved-operands*) (emit-move-from-stack register representation))) (push representation *operand-representations*))) (defun emit-variable-operand (variable) "Pushes a variable onto the operand stack, if it's safe to do so. Otherwise stores the value in a register." (push (variable-representation variable) *operand-representations*) (cond ((and *saved-operands* (variable-register variable)) ;; we're in 'safe mode' and the variable is in a register, ;; instead of binding a new register, just load the existing one (push (variable-register variable) *saved-operands*)) (t (emit-push-variable variable) (when *saved-operands* ;; safe-mode (let ((register (allocate-register (variable-representation variable)))) (push register *saved-operands*) (emit-move-from-stack register (variable-representation variable))))))) (defun emit-register-operand (register representation) (push representation *operand-representations*) (cond (*saved-operands* (push register *saved-operands*)) (t (emit-push-register register representation)))) (defun emit-thread-operand () (ensure-thread-var-initialized) (emit-register-operand *thread* nil)) (defun emit-load-externalized-object-operand (object) (push nil *operand-representations*) (emit-load-externalized-object object) (when *saved-operands* ;; safe-mode (let ((register (allocate-register nil))) (push register *saved-operands*) (emit 'astore register)))) (defknown emit-unbox-fixnum () t) (defun emit-unbox-fixnum () (declare (optimize speed)) (cond ((= *safety* 3) (emit-invokestatic +lisp-fixnum+ "getValue" (lisp-object-arg-types 1) :int)) (t (emit-checkcast +lisp-fixnum+) (emit-getfield +lisp-fixnum+ "value" :int)))) (defknown emit-unbox-long () t) (defun emit-unbox-long () (emit-invokestatic +lisp-bignum+ "longValue" (lisp-object-arg-types 1) :long)) (defknown emit-unbox-float () t) (defun emit-unbox-float () (declare (optimize speed)) (cond ((= *safety* 3) (emit-invokestatic +lisp-single-float+ "getValue" (lisp-object-arg-types 1) :float)) (t (emit-checkcast +lisp-single-float+) (emit-getfield +lisp-single-float+ "value" :float)))) (defknown emit-unbox-double () t) (defun emit-unbox-double () (declare (optimize speed)) (cond ((= *safety* 3) (emit-invokestatic +lisp-double-float+ "getValue" (lisp-object-arg-types 1) :double)) (t (emit-checkcast +lisp-double-float+) (emit-getfield +lisp-double-float+ "value" :double)))) (defknown fix-boxing (t t) t) (defun fix-boxing (required-representation derived-type) "Generate code to convert a boxed LispObject on the stack to the specified representation, based on the derived type of the LispObject." (cond ((null required-representation)) ; Nothing to do. ((eq required-representation :int) (cond ((and (fixnum-type-p derived-type) (< *safety* 3)) (emit-checkcast +lisp-fixnum+) (emit-getfield +lisp-fixnum+ "value" :int)) (t (emit-invokevirtual +lisp-object+ "intValue" nil :int)))) ((eq required-representation :char) (emit-unbox-character)) ((eq required-representation :boolean) (emit-unbox-boolean)) ((eq required-representation :long) (emit-invokevirtual +lisp-object+ "longValue" nil :long)) ((eq required-representation :float) (emit-invokevirtual +lisp-object+ "floatValue" nil :float)) ((eq required-representation :double) (emit-invokevirtual +lisp-object+ "doubleValue" nil :double)) (t (assert nil)))) (defknown emit-move-from-stack (t &optional t) t) (defun emit-move-from-stack (target &optional representation) (declare (optimize speed)) (cond ((null target) (ecase representation ((:long :double) (emit 'pop2)) ((NIL :int :boolean :char :float) (emit 'pop)))) ((eq target 'stack)) ; Nothing to do. ((fixnump target) ;; A register. (emit (ecase representation ((:int :boolean :char) 'istore) (:long 'lstore) (:float 'fstore) (:double 'dstore) ((nil) 'astore)) target)) (t (sys::%format t "emit-move-from-stack general case~%") (aver nil)))) (defknown emit-push-register (t &optional t) t) (defun emit-push-register (source &optional representation) (declare (optimize speed)) (assert (fixnump source)) (emit (ecase representation ((:int :boolean :char) 'iload) (:long 'lload) (:float 'fload) (:double 'dload) ((nil) 'aload)) source)) ;; Expects value on stack. (defknown emit-invoke-method (t t t) t) (defun emit-invoke-method (method-name target representation) (emit-invokevirtual +lisp-object+ method-name nil +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) ;; "In addition to situations for which the standard specifies that conditions ;; of type WARNING must or might be signaled, warnings might be signaled in ;; situations where the compiler can determine that the consequences are ;; undefined or that a run-time error will be signaled. Examples of this ;; situation are as follows: violating type declarations, altering or assigning ;; the value of a constant defined with DEFCONSTANT, calling built-in Lisp ;; functions with a wrong number of arguments or malformed keyword argument ;; lists, and using unrecognized declaration specifiers." (3.2.5) (defun check-number-of-args (form n &optional minimum) (declare (type fixnum n)) (let* ((op (car form)) (args (cdr form)) (ok (if minimum (>= (length args) n) (= (length args) n)))) (declare (type boolean ok)) (unless ok (funcall (if (eq (symbol-package op) +cl-package+) #'compiler-warn ; See above! #'compiler-style-warn) "Wrong number of arguments for ~A (expected~:[~; at least~] ~D, but received ~D)." op minimum n (length args))) ok)) (defknown check-arg-count (t fixnum) t) (defun check-arg-count (form n) (check-number-of-args form n)) (declaim (ftype (function (t fixnum) t) check-min-args)) (defun check-min-args (form n) (check-number-of-args form n t)) (defun emit-constructor-lambda-name (lambda-name) (cond ((and lambda-name (symbolp lambda-name) (symbol-package (truly-the symbol lambda-name))) (emit 'ldc (pool-string (symbol-name (truly-the symbol lambda-name)))) (emit 'ldc (pool-string (package-name (symbol-package (truly-the symbol lambda-name))))) (emit-invokestatic +lisp+ "internInPackage" (list +java-string+ +java-string+) +lisp-symbol+)) (t ;; No name. (emit-push-nil)))) (defun emit-constructor-lambda-list (lambda-list) (if lambda-list (serialize-object lambda-list) (emit-push-nil))) (defun emit-read-from-string (object) (emit-constructor-lambda-list object)) (defun make-constructor (class lambda-name args) (let* ((*compiler-debug* nil) (method (make-jvm-method :constructor :void nil :flags '(:public))) ;; We don't normally need to see debugging output for constructors. (super (class-file-superclass class)) opt-params-register key-params-register req-count rest-p keys-p more-keys-p alp-register) (with-code-to-method (class method) (allocate-register nil) (unless (eq super +lisp-compiled-primitive+) (multiple-value-bind (req opt key key-p rest allow-other-keys-p) (parse-lambda-list args) (setf rest-p rest more-keys-p allow-other-keys-p keys-p key-p req-count (length req)) (macrolet ((parameters-to-array ((param params register class) &body body) (let ((count-sym (gensym))) `(progn (emit-push-constant-int (length ,params)) (emit-anewarray ,class) (astore (setf ,register *registers-allocated*)) (allocate-register nil) (do* ((,count-sym 0 (1+ ,count-sym)) (,params ,params (cdr ,params)) (,param (car ,params) (car ,params))) ((endp ,params)) (declare (ignorable ,param)) (aload ,register) (emit-push-constant-int ,count-sym) (emit-new ,class) (emit 'dup) ,@body (emit 'aastore)))))) (parameters-to-array (param opt opt-params-register +alp-optional-parameter+) (if (null (third param)) ;; supplied-p or not? (emit 'iconst_0) (emit 'iconst_1)) (emit-read-from-string (second param)) ;; initform (emit-invokespecial-init +alp-optional-parameter+ (list :boolean +lisp-object+))) (parameters-to-array (param key key-params-register +alp-keyword-parameter+) (if (null (third param)) ;; supplied-p or not? (emit 'iconst_0) (emit 'iconst_1)) (emit-read-from-string (second param)) ;; initform (let ((keyword (fourth param))) (if (keywordp keyword) (progn (emit 'ldc (pool-string (symbol-name keyword))) (emit-invokestatic +lisp+ "internKeyword" (list +java-string+) +lisp-symbol+)) ;; symbol is not really a keyword; yes, that's allowed! (progn (emit 'ldc (pool-string (symbol-name keyword))) (emit 'ldc (pool-string (package-name (symbol-package keyword)))) (emit-invokestatic +lisp+ "internInPackage" (list +java-string+ +java-string+) +lisp-symbol+)))) (emit-invokespecial-init +alp-keyword-parameter+ (list :boolean +lisp-object+ +lisp-symbol+)))))) (aload 0) ;; this (cond ((eq super +lisp-compiled-primitive+) (emit-constructor-lambda-name lambda-name) (emit-constructor-lambda-list args) (emit-invokespecial-init super (lisp-object-arg-types 2))) ((equal super +lisp-compiled-closure+) ;;### only needs EQ when SUPER is guaranteed to be CLASS-NAME (emit-new +argument-list-processor+) (emit 'dup) (emit 'dup) (astore (setf alp-register (allocate-register nil))) (emit 'aconst_null) (emit-push-int req-count) (aload opt-params-register) (aload key-params-register) (if keys-p (emit 'iconst_1) (emit 'iconst_0)) (if more-keys-p (emit 'iconst_1) (emit 'iconst_0)) (if rest-p (emit-push-t) (emit 'aconst_null)) (emit-invokespecial-init +argument-list-processor+ (list +lisp-operator+ :int (class-array +alp-optional-parameter+) (class-array +alp-keyword-parameter+) :boolean :boolean +lisp-symbol+)) (emit-invokespecial-init super (list +argument-list-processor+)) (aload alp-register) (aload 0) (emit-invokevirtual +argument-list-processor+ "setFunction" (list +lisp-operator+) nil)) (t (sys::%format t "unhandled superclass ~A for ~A~%" super (abcl-class-file-class-name class)) (aver nil)))) method)) (defun make-static-initializer (class) (let ((*compiler-debug* nil) (method (make-jvm-method :static-initializer :void nil :flags '(:public :static)))) ;; We don't normally need to see debugging output for . (with-code-to-method (class method) method))) (defvar *source-line-number* nil) (defun finish-class (class stream) "Finalizes the `class' and writes the result to `stream'. The compiler calls this function to indicate it doesn't want to extend the class any further." (with-code-to-method (class (abcl-class-file-constructor class)) (emit 'return)) (with-code-to-method (class (abcl-class-file-static-initializer class)) (if (= 0 (length *code*)) (class-remove-method class (abcl-class-file-static-initializer class)) (emit 'return))) (when *compiler-debug* (print "; Writing class file ") (print (abcl-class-file-class-name class)) (terpri)) (finalize-class-file class) (write-class-file class stream)) (defknown declare-field (t t t) t) (defun declare-field (name descriptor) (let ((field (make-field name descriptor :flags '(:final :static)))) (class-add-field *class-file* field))) (defknown sanitize (symbol) string) (defun sanitize (symbol) (declare (type symbol symbol)) (declare (optimize speed)) (let* ((input (symbol-name symbol)) (output (make-array (length input) :fill-pointer 0 :element-type 'character))) (dotimes (i (length input)) (declare (type fixnum i)) (let ((c (char-upcase (char input i)))) (cond ((<= #.(char-code #\A) (char-code c) #.(char-code #\Z)) (vector-push c output)) ((<= #.(char-code #\0) (char-code c) #.(char-code #\9)) (vector-push c output)) ((eql c #\-) (vector-push #\_ output))))) (when (plusp (length output)) output))) (defvar *declare-inline* nil) (defmacro declare-with-hashtable (declared-item hashtable hashtable-var item-var &body body) `(let* ((,hashtable-var ,hashtable) (,item-var (gethash1 ,declared-item ,hashtable-var))) (declare (type hash-table ,hashtable-var)) (unless ,item-var ,@body) ,item-var)) ;; The protocol of the serialize-* functions is to serialize ;; the type to which they apply and emit code which leaves the ;; restored object on the stack. ;; The functions may generate only Java code, or decide to defer ;; some of the process of restoring the object to the reader. The ;; latter is generally applicable to more complex structures. ;; This way, the serialize-* functions can be used to depend on ;; each other to serialize nested constructs. They are also the ;; building blocks of the EMIT-LOAD-EXTERNALIZED-OBJECT function, ;; which is called from the compiler. (defun serialize-integer (n) "Generates code to restore a serialized integer." (cond((<= 0 n 255) (emit-getstatic +lisp-fixnum+ "constants" +lisp-fixnum-array+) (emit-push-constant-int n) (emit 'aaload)) ((<= most-negative-fixnum n most-positive-fixnum) (emit-push-constant-int n) (emit-invokestatic +lisp-fixnum+ "getInstance" '(:int) +lisp-fixnum+)) ((<= most-negative-java-long n most-positive-java-long) (emit-push-constant-long n) (emit-invokestatic +lisp-bignum+ "getInstance" '(:long) +lisp-integer+)) (t (let* ((*print-base* 10) (s (with-output-to-string (stream) (dump-form n stream)))) (emit 'ldc (pool-string s)) (emit-push-constant-int 10) (emit-invokestatic +lisp-bignum+ "getInstance" (list +java-string+ :int) +lisp-integer+))))) (defun serialize-character (c) "Generates code to restore a serialized character." (emit-push-constant-int (char-code c)) (emit-invokestatic +lisp-character+ "getInstance" '(:char) +lisp-character+)) (defun serialize-float (s) "Generates code to restore a serialized single-float." (emit-new +lisp-single-float+) (emit 'dup) (emit 'ldc (pool-float s)) (emit-invokespecial-init +lisp-single-float+ '(:float))) (defun serialize-double (d) "Generates code to restore a serialized double-float." (emit-new +lisp-double-float+) (emit 'dup) (emit 'ldc2_w (pool-double d)) (emit-invokespecial-init +lisp-double-float+ '(:double))) (defun serialize-string (string) "Generate code to restore a serialized string." (cond ((< (length string) #xFFFF) (emit-new +lisp-simple-string+) (emit 'dup) (emit 'ldc (pool-string string)) (emit-invokespecial-init +lisp-simple-string+ (list +java-string+))) (t (serialize-object string)))) (defun serialize-package (pkg) "Generate code to restore a serialized package." (emit 'ldc (pool-string (concatenate 'string "#.(CL:FIND-PACKAGE \"" (package-name pkg) "\")"))) (emit-invokestatic +lisp+ "readObjectFromString" (list +java-string+) +lisp-object+)) (defun compiland-external-constant-resource-name (compiland) (let ((resource-number (compiland-next-resource compiland)) (pathname (abcl-class-file-pathname (compiland-class-file compiland)))) (incf (compiland-next-resource compiland)) (make-pathname :name (format nil "~A_~D" (pathname-name pathname) resource-number) :type "clc" :defaults pathname))) (defun serialize-object (object) "Generate code to restore a serialized object which is not of any of the other types." (let ((s (with-output-to-string (stream) (dump-form object stream)))) (cond ((< (length s) #xFFFF) ;; maximum string size in class file (emit 'ldc (pool-string s)) (emit-invokestatic +lisp+ "readObjectFromString" (list +java-string+) +lisp-object+)) (t ;; get a 'class literal' for this class (emit 'ldc_w (pool-class *this-class*)) (let ((pathname (compiland-external-constant-resource-name *current-compiland*))) (with-open-file (f pathname :direction :output :if-exists :supersede :if-does-not-exist :create) (write-string s f)) (emit 'ldc (pool-string (namestring (make-pathname :name (pathname-name pathname) :type (pathname-type pathname) :version nil))))) (emit-invokevirtual +java-class+ "getResourceAsStream" (list +java-string+) +java-io-input-stream+) (emit-invokestatic +lisp+ "readObjectFromStream" (list +java-io-input-stream+) +lisp-object+))))) (defun serialize-symbol (symbol) "Generate code to restore a serialized symbol." (multiple-value-bind (name class) (lookup-known-symbol symbol) (cond (name (emit-getstatic class name +lisp-symbol+)) ((null (symbol-package symbol)) (emit-push-constant-int (dump-uninterned-symbol-index symbol)) (emit-invokestatic +lisp-load+ "getUninternedSymbol" '(:int) +lisp-object+) (emit-checkcast +lisp-symbol+)) ((keywordp symbol) (emit 'ldc (pool-string (symbol-name symbol))) (emit-invokestatic +lisp+ "internKeyword" (list +java-string+) +lisp-symbol+)) (t (emit 'ldc (pool-string (symbol-name symbol))) (emit 'ldc (pool-string (package-name (symbol-package symbol)))) (emit-invokestatic +lisp+ "internInPackage" (list +java-string+ +java-string+) +lisp-symbol+))))) (defvar serialization-table `((integer "INT" ,#'eql ,#'serialize-integer ,+lisp-integer+) (character "CHR" ,#'eql ,#'serialize-character ,+lisp-character+) (single-float "FLT" ,#'eql ,#'serialize-float ,+lisp-single-float+) (double-float "DBL" ,#'eql ,#'serialize-double ,+lisp-double-float+) (string "STR" ,#'equal ,#'serialize-string ,+lisp-abstract-string+) ;; because of (not compile-file) (package "PKG" ,#'eq ,#'serialize-package ,+lisp-object+) (symbol "SYM" ,#'eq ,#'serialize-symbol ,+lisp-symbol+) (T "OBJ" ,#'eq ,#'serialize-object ,+lisp-object+)) "A list of 5-element lists. The elements of the sublists mean: 1. The type of the value to be serialized 2. The string to be used as a field prefix 3. The function to be used to determine equality (coalescing or not) 4. The function to dispatch serialization to 5. The type of the field to save the serialized result to") (defknown emit-load-externalized-object (t &optional t) string) (defun emit-load-externalized-object (object &optional cast) "Externalizes `object' for use in a FASL. Returns the name of the field (in `*this-class*') from which the value of the object can be loaded. Objects may be coalesced based on the equality indicator in the `serialization-table'. Code to restore the serialized object is inserted into the current method or the constructor if `*declare-inline*' is non-nil. " ;; TODO: rewrite to become EMIT-LOAD-EXTERNALIZED-OBJECT which ;; - instead of returning the name of the field - returns the type ;; of the field it just loaded (to allow casting and what not). ;; The function should still do what it does today: de-serialize the ;; object and storing its value. (destructuring-bind (type prefix similarity-fn dispatch-fn field-type) (assoc-if #'(lambda (x) (typep object x)) serialization-table) (declare (ignore type)) ;; the type has been used in the selection process (when (not *file-compilation*) ;; in-memory compilation wants object EQ-ness (setf similarity-fn #'eq)) (let ((existing (assoc object *externalized-objects* :test similarity-fn))) (when existing (emit-getstatic *this-class* (cdr existing) field-type) (when cast (emit-checkcast cast)) (return-from emit-load-externalized-object field-type))) ;; We need to set up the serialized value (let ((field-name (symbol-name (gensym prefix)))) (declare-field field-name field-type) (push (cons object field-name) *externalized-objects*) (cond ((not *file-compilation*) (with-code-to-method (*class-file* (abcl-class-file-static-initializer *class-file*)) (remember field-name object) (emit 'ldc (pool-string field-name)) (emit-invokestatic +lisp+ "recall" (list +java-string+) +lisp-object+) (when (not (eq field-type +lisp-object+)) (emit-checkcast field-type)) (emit-putstatic *this-class* field-name field-type))) (*declare-inline* (funcall dispatch-fn object) (emit-putstatic *this-class* field-name field-type)) (t (with-code-to-method (*class-file* (abcl-class-file-static-initializer *class-file*)) (funcall dispatch-fn object) (emit-putstatic *this-class* field-name field-type)))) (emit-getstatic *this-class* field-name field-type) (when cast (emit-checkcast cast)) field-type))) (defknown declare-function (symbol &optional setf) string) (defun declare-function (symbol &optional setf) (declare (type symbol symbol)) (declare-with-hashtable symbol *declared-functions* ht f (setf f (symbol-name (if setf (gensym "SETF") (gensym "FUN")))) (let ((s (sanitize symbol))) (when s (setf f (concatenate 'string f "_" s)))) (declare-field f +lisp-object+) (multiple-value-bind (name class) (lookup-known-symbol symbol) ;; This is a work-around for the fact that ;; EMIT-LOAD-EXTERNALIZED-OBJECT can't be used due to the fact that ;; here we won't know where to send the code yet (the LET ;; selects between *code* and *static-code*, while ;; EMIT-LOAD-EXTERNALIZED-OBJECT wants to modify those specials too (unless name (setf name (if *file-compilation* (declare-object-as-string symbol) (declare-object symbol)) class *this-class*)) (with-code-to-method (*class-file* (if *declare-inline* *method* (abcl-class-file-constructor *class-file*))) (if (eq class *this-class*) (progn ;; generated by the DECLARE-OBJECT*'s above (emit-getstatic class name +lisp-object+) (emit-checkcast +lisp-symbol+)) (emit-getstatic class name +lisp-symbol+)) (emit-invokevirtual +lisp-symbol+ (if setf "getSymbolSetfFunctionOrDie" "getSymbolFunctionOrDie") nil +lisp-object+) ;; make sure we're not cacheing a proxied function ;; (AutoloadedFunctionProxy) by allowing it to resolve itself (emit-invokevirtual +lisp-object+ "resolve" nil +lisp-object+) (emit-putstatic *this-class* f +lisp-object+) (setf (gethash symbol ht) f)) f))) (defknown declare-setf-function (name) string) (defun declare-setf-function (name) (declare-function (cadr name) t)) (defun local-function-class-and-field (local-function) (let ((local-function-parent-compiland (compiland-parent (local-function-compiland local-function)))) (values (abcl-class-file-class-name (compiland-class-file local-function-parent-compiland)) (local-function-field local-function)))) (defknown declare-local-function (local-function) string) (defun declare-local-function (local-function) (let ((class-name (abcl-class-file-class-name (compiland-class-file (local-function-compiland local-function)))) (field-name (local-function-field local-function))) (with-code-to-method (*class-file* (abcl-class-file-static-initializer *class-file*)) ;; fixme *declare-inline* (declare-field field-name +lisp-object+) (emit-new class-name) (emit 'dup) (emit-invokespecial-init class-name '()) (emit-putstatic *this-class* field-name +lisp-object+)))) (defknown declare-object-as-string (t) string) (defun declare-object-as-string (obj) ;; TODO: replace with emit-load-externalized-object ;; just replacing won't work however: ;; field identification in Java includes the field type ;; and we're not letting the caller know about the type of ;; field we're creating in emit-load-externalized-object. ;; The solution is to rewrite externalize-object to ;; EMIT-LOAD-EXTERNALIZED-OBJECT, which serializes *and* ;; emits the right loading code (not just de-serialization anymore) (let ((g (symbol-name (gensym "OBJSTR"))) (s (with-output-to-string (stream) (dump-form obj stream)))) (with-code-to-method (*class-file* (if *declare-inline* *method* (abcl-class-file-static-initializer *class-file*))) ;; strings may contain evaluated bits which may depend on ;; previous statements (declare-field g +lisp-object+) (emit 'ldc (pool-string s)) (emit-invokestatic +lisp+ "readObjectFromString" (list +java-string+) +lisp-object+) (emit-putstatic *this-class* g +lisp-object+)) g)) (defun declare-load-time-value (obj) (let ((g (symbol-name (gensym "LTV"))) (s (with-output-to-string (stream) (dump-form obj stream)))) (with-code-to-method (*class-file* (if *declare-inline* *method* (abcl-class-file-static-initializer *class-file*))) ;; The readObjectFromString call may require evaluation of ;; lisp code in the string (think #.() syntax), of which the outcome ;; may depend on something which was declared inline (declare-field g +lisp-object+) (emit 'ldc (pool-string s)) (emit-invokestatic +lisp+ "readObjectFromString" (list +java-string+) +lisp-object+) (emit-invokestatic +lisp+ "loadTimeValue" (lisp-object-arg-types 1) +lisp-object+) (emit-putstatic *this-class* g +lisp-object+)) g)) (declaim (ftype (function (t) string) declare-object)) (defun declare-object (obj) "Stores the object OBJ in the object-lookup-table, loading the object value into a field upon class-creation time. The field type of the object is specified by OBJ-REF." (let ((g (symbol-name (gensym "OBJ")))) ;; fixme *declare-inline*? (remember g obj) (with-code-to-method (*class-file* (abcl-class-file-static-initializer *class-file*)) (declare-field g +lisp-object+) (emit 'ldc (pool-string g)) (emit-invokestatic +lisp+ "recall" (list +java-string+) +lisp-object+) (emit-putstatic *this-class* g +lisp-object+)) g)) (defknown compile-constant (t t t) t) (defun compile-constant (form target representation) (unless target (return-from compile-constant)) (ecase representation (:int (cond ((fixnump form) (emit-push-constant-int form)) ((integerp form) (emit-load-externalized-object form) (emit-invokevirtual +lisp-object+ "intValue" nil :int)) (t (sys::%format t "compile-constant int representation~%") (assert nil))) (emit-move-from-stack target representation) (return-from compile-constant)) (:long (cond ((<= most-negative-java-long form most-positive-java-long) (emit-push-constant-long form)) ((integerp form) (emit-load-externalized-object form) (emit-invokevirtual +lisp-object+ "longValue" nil :long)) (t (sys::%format t "compile-constant long representation~%") (assert nil))) (emit-move-from-stack target representation) (return-from compile-constant)) (:char (cond ((characterp form) (emit-push-constant-int (char-code form)) (emit-move-from-stack target representation) (return-from compile-constant)) (t (sys::%format t "compile-constant :char representation~%") (assert nil)))) (:boolean (emit (if form 'iconst_1 'iconst_0)) (emit-move-from-stack target representation) (return-from compile-constant)) (:float (cond ((integerp form) (emit-push-constant-float (coerce form 'single-float))) ((typep form 'single-float) (emit-push-constant-float form)) ((typep form 'double-float) (emit-push-constant-double form) (emit 'd2f)) (t (sys::%format t "compile-constant :float representation~%") (assert nil))) (emit-move-from-stack target representation) (return-from compile-constant)) (:double (cond ((or (integerp form) (typep form 'single-float)) (emit-push-constant-double (coerce form 'double-float))) ((typep form 'double-float) (emit-push-constant-double form)) (t (sys::%format t "compile-constant :double representation~%") (assert nil))) (emit-move-from-stack target representation) (return-from compile-constant)) ((NIL))) (cond ((or (numberp form) (typep form 'single-float) (typep form 'double-float) (characterp form) (stringp form) (packagep form) (pathnamep form) (arrayp form) (structure-object-p form) (standard-object-p form) (java:java-object-p form)) (emit-load-externalized-object form)) (t (if *file-compilation* (error "COMPILE-CONSTANT unhandled case ~S" form) (emit-load-externalized-object form)))) (emit-move-from-stack target representation)) (defparameter *unary-operators* nil) (defun initialize-unary-operators () (let ((ht (make-hash-table :test 'eq))) (dolist (pair '((ABS "ABS") (CADDR "caddr") (CADR "cadr") (CDDR "cddr") (CDR "cdr") (CLASS-OF "classOf") (COMPLEXP "COMPLEXP") (DENOMINATOR "DENOMINATOR") (FIRST "car") (SYS::%LENGTH "LENGTH") (NREVERSE "nreverse") (NUMERATOR "NUMERATOR") (REST "cdr") (REVERSE "reverse") (SECOND "cadr") (SIMPLE-STRING-P "SIMPLE_STRING_P") (STRING "STRING") (THIRD "caddr"))) (setf (gethash (%car pair) ht) (%cadr pair))) (setf *unary-operators* ht))) (initialize-unary-operators) (defknown install-p2-handler * t) (defun install-p2-handler (symbol &optional handler) (declare (type symbol symbol)) (let ((handler (or handler (find-symbol (concatenate 'string "COMPILE-" (symbol-name symbol)) 'jvm)))) (unless (and handler (fboundp handler)) (error "Handler not found: ~S" handler)) (setf (get symbol 'p2-handler) handler))) (defparameter *predicates* (make-hash-table :test 'eq)) (defun define-predicate (name boxed-method-name unboxed-method-name) (setf (gethash name *predicates*) (cons boxed-method-name unboxed-method-name)) (install-p2-handler name 'p2-predicate)) (defmacro define-inlined-function (name params preamble-and-test &body body) (let* ((test (second preamble-and-test)) (preamble (and test (first preamble-and-test))) (test (or test (first preamble-and-test)))) `(defun ,name ,params ,preamble (unless ,test (compile-function-call ,@params) (return-from ,name)) ,@body))) (defknown p2-predicate (t t t) t) (define-inlined-function p2-predicate (form target representation) ((= (length form) 2)) (let* ((op (car form)) (info (gethash op *predicates*)) (boxed-method-name (car info)) (unboxed-method-name (cdr info))) (cond ((and boxed-method-name unboxed-method-name) (let ((arg (cadr form))) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (ecase representation (:boolean (emit-invokevirtual +lisp-object+ unboxed-method-name nil :boolean)) ((NIL) (emit-invokevirtual +lisp-object+ boxed-method-name nil +lisp-object+))) (emit-move-from-stack target representation))) (t (compile-function-call form target representation))))) (define-predicate 'constantp "CONSTANTP" "constantp") (define-predicate 'endp "ENDP" "endp") (define-predicate 'evenp "EVENP" "evenp") (define-predicate 'floatp "FLOATP" "floatp") (define-predicate 'integerp "INTEGERP" "integerp") (define-predicate 'listp "LISTP" "listp") (define-predicate 'minusp "MINUSP" "minusp") (define-predicate 'numberp "NUMBERP" "numberp") (define-predicate 'oddp "ODDP" "oddp") (define-predicate 'plusp "PLUSP" "plusp") (define-predicate 'rationalp "RATIONALP" "rationalp") (define-predicate 'realp "REALP" "realp") (declaim (ftype (function (t t t t) t) compile-function-call-1)) (defun compile-function-call-1 (op args target representation) (let ((arg (first args))) (when (eq op '1+) (p2-plus (list '+ arg 1) target representation) (return-from compile-function-call-1 t)) (when (eq op '1-) (p2-minus (list '- arg 1) target representation) (return-from compile-function-call-1 t)) (let ((s (gethash1 op (the hash-table *unary-operators*)))) (cond (s (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-invoke-method s target representation) t) (t nil))))) (defparameter *binary-operators* nil) (defun initialize-binary-operators () (let ((ht (make-hash-table :test 'eq))) (dolist (pair '((EQL "EQL") (EQUAL "EQUAL") (+ "add") (- "subtract") (/ "divideBy") (* "multiplyBy") (< "IS_LT") (<= "IS_LE") (> "IS_GT") (>= "IS_GE") ( = "IS_E") (/= "IS_NE") (ASH "ash") (AREF "AREF") (SIMPLE-TYPEP "typep") (RPLACA "RPLACA") (RPLACD "RPLACD"))) (setf (gethash (%car pair) ht) (%cadr pair))) (setf *binary-operators* ht))) (initialize-binary-operators) (defun compile-binary-operation (op args target representation) (let ((arg1 (car args)) (arg2 (cadr args))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2)) (emit-invokevirtual +lisp-object+ op (lisp-object-arg-types 1) +lisp-object+)) (fix-boxing representation nil) (emit-move-from-stack target representation))) (declaim (ftype (function (t t t t) t) compile-function-call-2)) (defun compile-function-call-2 (op args target representation) (let ((translation (gethash1 op (the hash-table *binary-operators*)))) (when translation (compile-binary-operation translation args target representation)))) (declaim (ftype (function (t) t) fixnum-or-unboxed-variable-p)) (defun fixnum-or-unboxed-variable-p (arg) (or (fixnump arg) (unboxed-fixnum-variable arg))) (declaim (ftype (function (t) t) emit-push-int)) (defun emit-push-int (arg) (if (fixnump arg) (emit-push-constant-int arg) (let ((variable (unboxed-fixnum-variable arg))) (if variable (emit 'iload (variable-register variable)) (progn (sys::%format t "emit-push-int~%") (aver nil)))))) (declaim (ftype (function (t) t) emit-push-long)) (defun emit-push-long (arg) (cond ((eql arg 0) (emit 'lconst_0)) ((eql arg 1) (emit 'lconst_1)) ((fixnump arg) (emit-push-constant-int arg) (emit 'i2l)) (t (let ((variable (unboxed-fixnum-variable arg))) (aver (not (null variable))) (aver (not (null (variable-register variable)))) (emit 'iload (variable-register variable)) (emit 'i2l))))) (defknown p2-eq/neq (t t t) t) (define-inlined-function p2-eq/neq (form target representation) ((aver (or (null representation) (eq representation :boolean))) (check-arg-count form 2)) (let* ((op (%car form)) (args (%cdr form)) (arg1 (%car args)) (arg2 (%cadr args))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2)) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit (if (eq op 'EQ) 'if_acmpne 'if_acmpeq) LABEL1) (emit-push-true representation) (emit 'goto LABEL2) (label LABEL1) (emit-push-false representation) (label LABEL2))) (emit-move-from-stack target representation)) t) (defun emit-ifne-for-eql (representation instruction-type) (emit-invokevirtual +lisp-object+ "eql" instruction-type :boolean) (convert-representation :boolean representation)) (defknown p2-eql (t t t) t) (define-inlined-function p2-eql (form target representation) ((aver (or (null representation) (eq representation :boolean))) (check-arg-count form 2)) (let* ((arg1 (%cadr form)) (arg2 (%caddr form)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((and (fixnum-type-p type1) (fixnum-type-p type2)) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (let ((label1 (gensym)) (label2 (gensym))) (emit 'if_icmpeq label1) (emit-push-false representation) (emit 'goto label2) (label label1) (emit-push-true representation) (label label2))) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-ifne-for-eql representation '(:int))) ((fixnum-type-p type1) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit 'swap) (emit-ifne-for-eql representation '(:int))) ((eq type2 'CHARACTER) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :char) (maybe-emit-clear-values arg1 arg2))) (emit-ifne-for-eql representation '(:char))) ((eq type1 'CHARACTER) (with-operand-accumulation ((compile-operand arg1 :char) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit 'swap) (emit-ifne-for-eql representation '(:char))) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (ecase representation (:boolean (emit-invokevirtual +lisp-object+ "eql" (lisp-object-arg-types 1) :boolean)) ((NIL) (emit-invokevirtual +lisp-object+ "EQL" (lisp-object-arg-types 1) +lisp-object+))))) (emit-move-from-stack target representation))) (defknown p2-memq (t t t) t) (define-inlined-function p2-memq (form target representation) ((check-arg-count form 2)) (cond ((eq representation :boolean) (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokestatic +lisp+ "memq" (lisp-object-arg-types 2) :boolean) (emit-move-from-stack target representation))) (t (compile-function-call form target representation)))) (defknown p2-memql (t t t) t) (define-inlined-function p2-memql (form target representation) ((check-arg-count form 2)) (cond ((eq representation :boolean) (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args)) (type1 (derive-compiler-type arg1))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (cond ((eq type1 'SYMBOL) ; FIXME (emit-invokestatic +lisp+ "memq" (lisp-object-arg-types 2) :boolean)) (t (emit-invokestatic +lisp+ "memql" (lisp-object-arg-types 2) :boolean))) (emit-move-from-stack target representation))) (t (compile-function-call form target representation)))) (defun p2-gensym (form target representation) (cond ((and (null representation) (null (cdr form))) (emit-push-current-thread) (emit-invokestatic +lisp+ "gensym" (list +lisp-thread+) +lisp-symbol+) (emit-move-from-stack target)) (t (compile-function-call form target representation)))) ;; get symbol indicator &optional default => value (defun p2-get (form target representation) (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args)) (arg3 (third args))) (case (length args) ((2 3) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (when arg3 (compile-operand arg3 nil)) (maybe-emit-clear-values arg1 arg2 arg3))) (emit-invokestatic +lisp+ "get" (lisp-object-arg-types (if arg3 3 2)) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (compiler-warn "Wrong number of arguments for ~A (expected 2 or 3, but received ~D)." 'GET (length args)) (compile-function-call form target representation))))) ;; getf plist indicator &optional default => value (defun p2-getf (form target representation) (let* ((args (cdr form)) (arg-count (length args))) (case arg-count ((2 3) (let ((arg1 (first args)) (arg2 (second args)) (arg3 (third args))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (compile-operand arg3 nil) (maybe-emit-clear-values arg1 arg2 arg3))) (emit-invokestatic +lisp+ "getf" (lisp-object-arg-types 3) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation))) (t (compile-function-call form target representation))))) ;; gethash key hash-table &optional default => value, present-p (defun p2-gethash (form target representation) (cond ((and (eq (car form) 'GETHASH1) (= (length form) 3) (eq (derive-type (%caddr form)) 'HASH-TABLE)) (let ((key-form (%cadr form)) (ht-form (%caddr form))) (with-operand-accumulation ((compile-operand ht-form nil +lisp-hash-table+) (compile-operand key-form nil) (maybe-emit-clear-values ht-form key-form))) (emit-invokevirtual +lisp-hash-table+ "gethash1" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation))) (t (compile-function-call form target representation)))) ;; puthash key hash-table new-value &optional default => value (defun p2-puthash (form target representation) (cond ((and (= (length form) 4) (eq (derive-type (%caddr form)) 'HASH-TABLE)) (let ((key-form (%cadr form)) (ht-form (%caddr form)) (value-form (fourth form))) (with-operand-accumulation ((compile-operand ht-form nil +lisp-hash-table+) (compile-operand key-form nil) (compile-operand value-form nil) (maybe-emit-clear-values ht-form key-form value-form))) (cond (target (emit-invokevirtual +lisp-hash-table+ "puthash" (lisp-object-arg-types 2) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (emit-invokevirtual +lisp-hash-table+ "put" (lisp-object-arg-types 2) nil))))) (t (compile-function-call form target representation)))) (defvar *functions-defined-in-current-file* nil) (defun inline-ok (name) (declare (optimize speed)) (cond ((notinline-p name) nil) ((built-in-function-p name) t) ((memq name *functions-defined-in-current-file*) t) (t nil))) (defknown process-args (t t) t) (defun process-args (args stack) "Compiles forms specified as function call arguments. The results are either accumulated on the stack or in an array in order to call the relevant `execute' form. The function call itself is *not* compiled by this function." (when args (let ((numargs (length args))) (let ((must-clear-values nil) (unsafe-args (some-nested-block #'node-opstack-unsafe-p (mapcan #'find-enclosed-blocks args)))) (declare (type boolean must-clear-values)) (cond ((and unsafe-args (<= numargs call-registers-limit)) (let ((*register* *register*) operand-registers) (dolist (stack-item stack) (let ((register (allocate-register nil))) (push register operand-registers) (emit-move-from-stack register stack-item))) (setf operand-registers (reverse operand-registers)) (dolist (arg args) (push (allocate-register nil) operand-registers) (compile-form arg (car operand-registers) nil) (unless must-clear-values (unless (single-valued-p arg) (setf must-clear-values t)))) (dolist (register (nreverse operand-registers)) (aload register)))) ((<= numargs call-registers-limit) (dolist (arg args) (compile-form arg 'stack nil) (unless must-clear-values (unless (single-valued-p arg) (setf must-clear-values t))))) (t (let* ((*register* *register*) ;; ### FIXME: this doesn't work, but why not? (array-register (allocate-register nil)) saved-stack) (when unsafe-args (dolist (stack-item stack) (let ((register (allocate-register nil))) (push register saved-stack) (emit-move-from-stack register stack-item)))) (emit-push-constant-int numargs) (emit-anewarray +lisp-object+) ;; be operand stack safe by not accumulating ;; any arguments on the stack. ;; ;; The overhead of storing+loading the array register ;; at the beginning and ending is small: there are at ;; least nine parameters to be calculated. (astore array-register) (let ((i 0)) (dolist (arg args) (cond ((not (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks arg))) (aload array-register) (emit-push-constant-int i) (compile-form arg 'stack nil)) (t (compile-form arg 'stack nil) (aload array-register) (emit 'swap) (emit-push-constant-int i) (emit 'swap))) (emit 'aastore) ; store value in array (unless must-clear-values (unless (single-valued-p arg) (setf must-clear-values t))) (incf i)) (when unsafe-args (mapcar #'emit-push-register saved-stack (reverse stack))) (aload array-register))))) (when must-clear-values (emit-clear-values))))) t) (defknown lisp-object-arg-types (fixnum) list) (let ((table (make-array 10))) (dotimes (i 10) (declare (type fixnum i)) (setf (aref table i) (make-list i :initial-element +lisp-object+))) (defun lisp-object-arg-types (n) (declare (type fixnum n)) (declare (optimize speed (safety 0))) (if (< n 10) (aref table n) (make-list n :initial-element +lisp-object+)))) (declaim (ftype (function (t) t) emit-call-execute)) (defun emit-call-execute (numargs) (let ((arg-types (if (<= numargs call-registers-limit) (lisp-object-arg-types numargs) (list +lisp-object-array+))) (return-type +lisp-object+)) (emit-invokevirtual +lisp-object+ "execute" arg-types return-type))) (declaim (ftype (function (t) t) emit-call-thread-execute)) (defun emit-call-thread-execute (numargs) (let ((arg-types (if (<= numargs call-registers-limit) (lisp-object-arg-types (1+ numargs)) (list +lisp-object+ +lisp-object-array+))) (return-type +lisp-object+)) (emit-invokevirtual +lisp-thread+ "execute" arg-types return-type))) (defknown compile-function-call (t t t) t) (defun compile-function-call (form target representation) (let ((op (car form)) (args (cdr form))) (declare (type symbol op)) (when (find-local-function op) (return-from compile-function-call (compile-local-function-call form target representation))) (when (and (boundp '*defined-functions*) (boundp '*undefined-functions*)) (unless (or (fboundp op) (eq op (compiland-name *current-compiland*)) (memq op *defined-functions*) (proclaimed-ftype op)) (pushnew op *undefined-functions*))) (let ((numargs (length args))) (case numargs (1 (when (compile-function-call-1 op args target representation) (return-from compile-function-call))) (2 (when (compile-function-call-2 op args target representation) (return-from compile-function-call)))) (let ((explain *explain*)) (when (and explain (memq :calls explain)) (let ((package (symbol-package op))) (when (or (eq package +cl-package+) (eq package (find-package "SYSTEM"))) (format t "; full call to ~S~%" op))))) (when (or (<= *speed* *debug*) *require-stack-frame*) (emit-push-current-thread)) (cond ((and (eq op (compiland-name *current-compiland*)) (null (compiland-parent *current-compiland*))) ; recursive call (if (notinline-p op) (emit-load-externalized-object op) (aload 0))) (t (emit-load-externalized-object op))) (process-args args (if (or (<= *speed* *debug*) *require-stack-frame*) '(nil nil) '(nil))) (if (or (<= *speed* *debug*) *require-stack-frame*) (emit-call-thread-execute numargs) (emit-call-execute numargs)) (fix-boxing representation (derive-compiler-type form)) (emit-move-from-stack target representation)))) (defun compile-call (args stack) "Compiles a function call. Depending on the `*speed*' and `*debug*' settings, a stack frame is registered (or not)." (let ((numargs (length args))) (cond ((> *speed* *debug*) (process-args args stack) (emit-call-execute numargs)) (t (emit-push-current-thread) (emit 'swap) ; Stack: thread function (process-args args (list* (car stack) nil (cdr stack))) (emit-call-thread-execute numargs))))) (define-source-transform funcall (&whole form fun &rest args) (cond ((> *debug* *speed*) form) ((and (consp fun) (eq (%car fun) 'FUNCTION) (symbolp (cadr fun))) `(,(cadr fun) ,@args)) ((and (consp fun) (eq (%car fun) 'QUOTE)) (let ((sym (cadr fun))) (if (and (symbolp sym) (eq (symbol-package (truly-the symbol sym)) +cl-package+) (not (special-operator-p sym)) (not (macro-function sym))) `(,(cadr fun) ,@args) form))) (t form))) (define-source-transform mapcar (&whole form function &rest lists) (cond ((or (> *debug* *speed*) (> *space* *speed*)) form) ((= (length lists) 1) (let ((list (gensym)) (result (gensym)) (temp (gensym))) `(let* ((,list ,(car lists)) (,result (list nil)) (,temp ,result)) (loop (when (null ,list) (return (cdr ,result))) (rplacd ,temp (setf ,temp (list (funcall ,function (car ,list))))) (setf ,list (cdr ,list)))))) (t form))) (define-source-transform mapc (&whole form function &rest lists) (cond ((or (> *debug* *speed*) (> *space* *speed*)) form) ((= (length lists) 1) (let ((list (gensym)) (result (gensym))) `(let* ((,list ,(car lists)) (,result ,list)) (loop (when (null ,list) (return ,result)) (funcall ,function (car ,list)) (setf ,list (%cdr ,list)))))) (t form))) (defknown p2-funcall (t t t) t) (defun p2-funcall (form target representation) (unless (> (length form) 1) (compiler-warn "Wrong number of arguments for ~A." (car form)) (compile-function-call form target representation) (return-from p2-funcall)) (when (> *debug* *speed*) (return-from p2-funcall (compile-function-call form target representation))) (compile-forms-and-maybe-emit-clear-values (cadr form) 'stack nil) (compile-call (cddr form) '(nil)) (fix-boxing representation nil) (emit-move-from-stack target)) (defun duplicate-closure-array (compiland) (let* ((*register* *register*) (register (allocate-register nil))) (aload (compiland-closure-register compiland)) ;; src (emit-push-constant-int 0) ;; srcPos (emit-push-constant-int (length *closure-variables*)) (emit-anewarray +lisp-closure-binding+) ;; dest (emit 'dup) (astore register) ;; save dest value (emit-push-constant-int 0) ;; destPos (emit-push-constant-int (length *closure-variables*)) ;; length (emit-invokestatic +java-system+ "arraycopy" (list +java-object+ :int +java-object+ :int :int) nil) (aload register))) ;; reload dest value (defun emit-load-local-function (local-function) (when (eq *current-compiland* (local-function-compiland local-function)) (aload 0) (return-from emit-load-local-function)) (multiple-value-bind (class field) (local-function-class-and-field local-function) (emit-getstatic class field +lisp-object+)) (when *closure-variables* (emit-checkcast +lisp-compiled-closure+) (duplicate-closure-array *current-compiland*) (emit-invokestatic +lisp+ "makeCompiledClosure" (list +lisp-object+ +closure-binding-array+) +lisp-object+))) (defknown compile-local-function-call (t t t) t) (defun compile-local-function-call (form target representation) "Compiles a call to a function marked as `*child-p*'; a local function. Functions this applies to can be FLET, LABELS, LAMBDA or NAMED-LAMBDA. Note: DEFUN implies a named lambda." (let* ((op (car form)) (args (cdr form)) (local-function (find-local-function op)) (*register* *register*)) (cond ((local-function-environment local-function) (assert (local-function-references-allowed-p local-function)) (assert (not *file-compilation*)) (emit-load-externalized-object (local-function-environment local-function) +lisp-environment+) (emit-load-externalized-object (local-function-name local-function)) (emit-invokevirtual +lisp-environment+ "lookupFunction" (list +lisp-object+) +lisp-object+)) (t (dformat t "compile-local-function-call default case~%") (emit-load-local-function local-function))) (process-args args '(nil)) (emit-call-execute (length args)) (fix-boxing representation nil) (emit-move-from-stack target representation)) t) ;; < <= > >= = (defvar comparison-ops '(< <= > >= =)) (defvar comparison-ins '((:int . #(if_icmpge if_icmpgt if_icmple if_icmplt if_icmpne)) (:long . #((lcmp ifge) (lcmp ifgt) (lcmp ifle) (lcmp iflt) (lcmp ifne))) (:float . #((fcmpg ifge) (fcmpg ifgt) (fcmpl ifle) (fcmpl iflt) (fcmpl ifne))) (:double . #((dcmpg ifge) (dcmpg ifgt) (dcmpl ifle) (dcmpl iflt) (dcmpl ifne)))) "Instructions to be generated upon each comparison operation, given a specific common representation.") (defun emit-numeric-comparison (op representation false-LABEL) (let* ((pos (position op comparison-ops)) (ops-table (cdr (assoc representation comparison-ins))) (ops (aref ops-table pos))) (if (listp ops) (progn (emit (car ops)) (emit (cadr ops) false-LABEL)) (emit ops false-LABEL)))) ;; Note that /= is not transitive, so we don't handle it here. (defknown p2-numeric-comparison (t t t) t) (defun p2-numeric-comparison (form target representation) (aver (or (null representation) (eq representation :boolean))) (let ((op (car form)) (args (%cdr form))) (case (length args) (2 (let* ((arg1 (%car args)) (arg2 (%cadr args)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2)) (common-rep (common-representation (type-representation type1) (type-representation type2)))) (cond ((and (integerp arg1) (integerp arg2)) (let ((result (funcall op arg1 arg2))) (if result (emit-push-true representation) (emit-push-false representation))) (emit-move-from-stack target representation) (return-from p2-numeric-comparison)) (common-rep (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (with-operand-accumulation ((compile-operand arg1 common-rep) (compile-operand arg2 common-rep) (maybe-emit-clear-values arg1 arg2)) (emit-numeric-comparison op common-rep LABEL1) (emit-push-true representation) (emit 'goto LABEL2) (label LABEL1) (emit-push-false representation) (label LABEL2))) (emit-move-from-stack target representation) (return-from p2-numeric-comparison)) ((fixnump arg2) (compile-forms-and-maybe-emit-clear-values arg1 'stack nil) (emit-push-constant-int arg2) (emit-invokevirtual +lisp-object+ (case op (< "isLessThan") (<= "isLessThanOrEqualTo") (> "isGreaterThan") (>= "isGreaterThanOrEqualTo") (= "isEqualTo")) '(:int) :boolean) ;; Java boolean on stack here (convert-representation :boolean representation) (emit-move-from-stack target representation) (return-from p2-numeric-comparison))))) (3 (when (dolist (arg args t) (unless (fixnum-type-p (derive-compiler-type arg)) (return nil))) (let* ((arg1 (%car args)) (arg2 (%cadr args)) (arg3 (%caddr args)) (test (case op (< 'if_icmpge) (<= 'if_icmpgt) (> 'if_icmple) (>= 'if_icmplt) (= 'if_icmpne))) (LABEL1 (gensym)) (LABEL2 (gensym)) ;; If we do both tests, we need to use the arg2 value twice, ;; so we store that value in a temporary register. (*register* *register*) (arg2-register (unless (and (or (node-constant-p arg2) (var-ref-p arg2)) (node-constant-p arg3)) (allocate-register nil))) (arg3-register (unless (node-constant-p arg3) (allocate-register nil)))) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (when arg3-register (compile-operand arg3 :int)) (maybe-emit-clear-values arg1 arg2 arg3)) (when arg3-register (emit 'istore arg3-register)) (when arg2-register (emit 'dup) (emit 'istore arg2-register))) ;; First test. (emit test LABEL1) ;; Second test. (cond (arg2-register (emit 'iload arg2-register)) (t (compile-form arg2 'stack :int))) (cond (arg3-register (emit 'iload arg3-register)) (t (compile-form arg3 'stack :int))) (emit test LABEL1) (emit-push-true representation) (emit 'goto LABEL2) (label LABEL1) (emit-push-false representation) (label LABEL2) (emit-move-from-stack target representation) (return-from p2-numeric-comparison)))))) ;; Still here? (compile-function-call form target representation)) (defparameter *p2-test-handlers* nil) (defun p2-test-handler (op) (gethash1 op (the hash-table *p2-test-handlers*))) (defun initialize-p2-test-handlers () (let ((ht (make-hash-table :test 'eq))) (dolist (pair '( (/= p2-test-/=) (< p2-test-numeric-comparison) (<= p2-test-numeric-comparison) (= p2-test-numeric-comparison) (> p2-test-numeric-comparison) (>= p2-test-numeric-comparison) (AND p2-test-and) (OR p2-test-or) (ATOM p2-test-atom) (BIT-VECTOR-P p2-test-bit-vector-p) (CHAR= p2-test-char=) (CHARACTERP p2-test-characterp) (CONSP p2-test-consp) (CONSTANTP p2-test-constantp) (ENDP p2-test-endp) (EQ p2-test-eq) (NEQ p2-test-neq) (EQL p2-test-eql) (EQUAL p2-test-equality) (EQUALP p2-test-equality) (EVENP p2-test-evenp) (FIXNUMP p2-test-fixnump) (FLOATP p2-test-floatp) (INTEGERP p2-test-integerp) (LISTP p2-test-listp) (MEMQ p2-test-memq) (MEMQL p2-test-memql) (MINUSP p2-test-minusp) (NOT p2-test-not/null) (NULL p2-test-not/null) (NUMBERP p2-test-numberp) (PACKAGEP p2-test-packagep) (ODDP p2-test-oddp) (PLUSP p2-test-plusp) (RATIONALP p2-test-rationalp) (REALP p2-test-realp) (SIMPLE-TYPEP p2-test-simple-typep) (SIMPLE-VECTOR-P p2-test-simple-vector-p) (SPECIAL-OPERATOR-P p2-test-special-operator-p) (SPECIAL-VARIABLE-P p2-test-special-variable-p) (STRINGP p2-test-stringp) (SYMBOLP p2-test-symbolp) (VECTORP p2-test-vectorp) (ZEROP p2-test-zerop) )) (setf (gethash (%car pair) ht) (%cadr pair))) (setf *p2-test-handlers* ht))) (initialize-p2-test-handlers) (defknown negate-jump-condition (t) t) (defun negate-jump-condition (jump-instruction) (ecase jump-instruction ('if_acmpeq 'if_acmpne) ('if_acmpne 'if_acmpeq) ('ifeq 'ifne) ('ifne 'ifeq) ('iflt 'ifge) ('ifge 'iflt) ('ifgt 'ifle) ('ifle 'ifgt) ('if_icmpeq 'if_icmpne) ('if_icmpne 'if_icmpeq) ('if_icmplt 'if_icmpge) ('if_icmpge 'if_icmplt) ('if_icmpgt 'if_icmple) ('if_icmple 'if_icmpgt))) (defknown emit-test-jump (t t t) t) (defun emit-test-jump (jump success-label failure-label) (cond (failure-label (emit jump failure-label) (when success-label (emit 'goto success-label))) (t (emit (negate-jump-condition jump) success-label))) t) (defknown p2-test-predicate (t t) t) (defun p2-test-predicate (form java-predicate success-label failure-label) (when (check-arg-count form 1) (let ((arg (%cadr form))) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-invokevirtual +lisp-object+ java-predicate nil :boolean) (emit-test-jump 'ifeq success-label failure-label)))) (declaim (ftype (function (t t t t) t) p2-test-instanceof-predicate)) (defun p2-test-instanceof-predicate (form java-class success-label failure-label) (when (check-arg-count form 1) (let ((arg (%cadr form))) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-instanceof java-class) (emit-test-jump 'ifeq success-label failure-label)))) (defun p2-test-bit-vector-p (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-abstract-bit-vector+ success-label failure-label)) (defun p2-test-characterp (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-character+ success-label failure-label)) ;; constantp form &optional environment => generalized-boolean (defun p2-test-constantp (form success-label failure-label) (when (= (length form) 2) (let ((arg (%cadr form))) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-invokevirtual +lisp-object+ "constantp" nil :boolean) (emit-test-jump 'ifeq success-label failure-label)))) (defun p2-test-endp (form success-label failure-label) (p2-test-predicate form "endp" success-label failure-label)) (defmacro p2-test-integer-predicate ((form predicate success-label failure-label) &body instructions) (let ((tmpform (gensym))) `(let ((,tmpform ,form)) (when (check-arg-count ,tmpform 1) (let ((arg (%cadr ,tmpform))) (cond ((fixnum-type-p (derive-compiler-type arg)) (compile-forms-and-maybe-emit-clear-values arg 'stack :int) ,@instructions) (t (p2-test-predicate ,tmpform ,predicate ,success-label ,failure-label)))))))) (defun p2-test-evenp (form success-label failure-label) (p2-test-integer-predicate (form "evenp" success-label failure-label) (emit-push-constant-int 1) (emit 'iand) (emit-test-jump 'ifne success-label failure-label))) (defun p2-test-oddp (form success-label failure-label) (p2-test-integer-predicate (form "oddp" success-label failure-label) (emit-push-constant-int 1) (emit 'iand) (emit-test-jump 'ifeq success-label failure-label))) (defun p2-test-floatp (form success-label failure-label) (p2-test-predicate form "floatp" success-label failure-label)) (defun p2-test-integerp (form success-label failure-label) (p2-test-predicate form "integerp" success-label failure-label)) (defun p2-test-listp (form success-label failure-label) (when (check-arg-count form 1) (let* ((arg (%cadr form)) (arg-type (derive-compiler-type arg))) (cond ((memq arg-type '(CONS LIST NULL)) (compile-forms-and-maybe-emit-clear-values arg nil nil) :consequent) ((neq arg-type t) (compile-forms-and-maybe-emit-clear-values arg nil nil) :alternate) (t (p2-test-predicate form "listp" success-label failure-label)))))) (defun p2-test-minusp (form success-label failure-label) (p2-test-integer-predicate (form "minusp" success-label failure-label) (emit-test-jump 'ifge success-label failure-label))) (defun p2-test-plusp (form success-label failure-label) (p2-test-integer-predicate (form "plusp" success-label failure-label) (emit-test-jump 'ifle success-label failure-label))) (defun p2-test-zerop (form success-label failure-label) (p2-test-integer-predicate (form "zerop" success-label failure-label) (emit-test-jump 'ifne success-label failure-label))) (defun p2-test-numberp (form success-label failure-label) (p2-test-predicate form "numberp" success-label failure-label)) (defun p2-test-packagep (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-package+ success-label failure-label)) (defun p2-test-rationalp (form success-label failure-label) (p2-test-predicate form "rationalp" success-label failure-label)) (defun p2-test-realp (form success-label failure-label) (p2-test-predicate form "realp" success-label failure-label)) (defun p2-test-special-operator-p (form success-label failure-label) (p2-test-predicate form "isSpecialOperator" success-label failure-label)) (defun p2-test-special-variable-p (form success-label failure-label) (p2-test-predicate form "isSpecialVariable" success-label failure-label)) (defun p2-test-symbolp (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-symbol+ success-label failure-label)) (defun p2-test-consp (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-cons+ success-label failure-label)) (defun p2-test-atom (form success-label failure-label) ;; The test below is a negative test, so, reverse the labels for failure and success (p2-test-instanceof-predicate form +lisp-cons+ failure-label success-label)) (defun p2-test-fixnump (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-fixnum+ success-label failure-label)) (defun p2-test-stringp (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-abstract-string+ success-label failure-label)) (defun p2-test-vectorp (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-abstract-vector+ success-label failure-label)) (defun p2-test-simple-vector-p (form success-label failure-label) (p2-test-instanceof-predicate form +lisp-simple-vector+ success-label failure-label)) (defknown compile-test-form (t) t) (defun compile-test-form (test-form success-label failure-label) (when (consp test-form) (let* ((op (%car test-form)) (handler (p2-test-handler op)) (result (and handler (funcall handler test-form success-label failure-label)))) (when result (return-from compile-test-form result)))) (cond ((eq test-form t) :consequent) ((eq (derive-compiler-type test-form) 'BOOLEAN) (compile-forms-and-maybe-emit-clear-values test-form 'stack :boolean) (emit-test-jump 'ifeq success-label failure-label)) (t (compile-forms-and-maybe-emit-clear-values test-form 'stack nil) (emit-push-nil) (emit-test-jump 'if_acmpeq success-label failure-label)))) (defun p2-test-not/null (form success-label failure-label) (when (check-arg-count form 1) (let* ((arg (%cadr form)) (result (compile-test-form arg failure-label success-label))) (case result (:consequent :alternate) (:alternate :consequent) (t result))))) (defun p2-test-char= (form success-label failure-label) (when (= (length form) 3) ;; only optimize the "exactly 2 arguments" case (let* ((arg1 (%cadr form)) (arg2 (%caddr form))) (with-operand-accumulation ((compile-operand arg1 :char) (compile-operand arg2 :char) (maybe-emit-clear-values arg1 arg2))) (emit-test-jump 'if_icmpne success-label failure-label)))) (defun p2-test-eq (form success-label failure-label) (when (check-arg-count form 2) (let ((arg1 (%cadr form)) (arg2 (%caddr form))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-test-jump 'if_acmpne success-label failure-label)))) (defun p2-test-or (form success-label failure-label) (let ((args (cdr form))) (case (length args) (0 :alternate) (1 (compile-test-form (%car args) success-label failure-label)) (t (loop with local-success-label = (or success-label (gensym)) for arg in args for result = (compile-test-form arg local-success-label nil) when (eq :consequent result) do (progn (emit 'goto local-success-label) (loop-finish)) finally (progn (when failure-label (emit 'goto failure-label)) (unless (eq success-label local-success-label) (label local-success-label)) (return t))))))) (defun p2-test-and (form success-label failure-label) (let ((args (cdr form))) (case (length args) (0 :consequent) (1 (compile-test-form (%car args) success-label failure-label)) (t (loop with local-fail-label = (or failure-label (gensym)) for arg in args for result = (compile-test-form arg nil local-fail-label) when (eq :alternate result) do (progn (emit 'goto local-fail-label) (loop-finish)) finally (progn (when success-label (emit 'goto success-label)) (unless (eq failure-label local-fail-label) (label local-fail-label)) (return t))))))) (defun p2-test-neq (form success-label failure-label) (p2-test-eq form failure-label success-label)) (defun p2-test-eql (form success-label failure-label) (when (check-arg-count form 2) (let* ((arg1 (%cadr form)) (arg2 (%caddr form)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((and (fixnum-type-p type1) (fixnum-type-p type2)) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-test-jump 'if_icmpne success-label failure-label)) ((and (eq type1 'CHARACTER) (eq type2 'CHARACTER)) (with-operand-accumulation ((compile-operand arg1 :char) (compile-operand arg2 :char) (maybe-emit-clear-values arg1 arg2))) (emit-test-jump 'if_icmpne success-label failure-label)) ((eq type2 'CHARACTER) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :char) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "eql" '(:char) :boolean) (emit-test-jump 'ifeq success-label failure-label)) ((eq type1 'CHARACTER) (with-operand-accumulation ((compile-operand arg1 :char) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit 'swap) (emit-invokevirtual +lisp-object+ "eql" '(:char) :boolean) (emit-test-jump 'ifeq success-label failure-label)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "eql" '(:int) :boolean) (emit-test-jump 'ifeq success-label failure-label)) ((fixnum-type-p type1) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit 'swap) (emit-invokevirtual +lisp-object+ "eql" '(:int) :boolean) (emit-test-jump 'ifeq success-label failure-label)) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "eql" (lisp-object-arg-types 1) :boolean) (emit-test-jump 'ifeq success-label failure-label)))))) (defun p2-test-equality (form success-label failure-label) (when (check-arg-count form 2) (let* ((op (%car form)) (translated-op (ecase op (EQUAL "equal") (EQUALP "equalp"))) (arg1 (%cadr form)) (arg2 (%caddr form))) (cond ((fixnum-type-p (derive-compiler-type arg2)) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ translated-op '(:int) :boolean)) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ translated-op (lisp-object-arg-types 1) :boolean))) (emit-test-jump 'ifeq success-label failure-label)))) (defun p2-test-simple-typep (form success-label failure-label) (when (check-arg-count form 2) (let ((arg1 (%cadr form)) (arg2 (%caddr form))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "typep" (lisp-object-arg-types 1) +lisp-object+) (emit-push-nil) (emit-test-jump 'if_acmpeq success-label failure-label)))) (defun p2-test-memq (form success-label failure-label) (when (check-arg-count form 2) (let ((arg1 (%cadr form)) (arg2 (%caddr form))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokestatic +lisp+ "memq" (lisp-object-arg-types 2) :boolean) (emit-test-jump 'ifeq success-label failure-label)))) (defun p2-test-memql (form success-label failure-label) (when (check-arg-count form 2) (let ((arg1 (%cadr form)) (arg2 (%caddr form))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokestatic +lisp+ "memql" (lisp-object-arg-types 2) :boolean) (emit-test-jump 'ifeq success-label failure-label)))) (defun p2-test-/= (form success-label failure-label) (when (= (length form) 3) (let* ((arg1 (%cadr form)) (arg2 (%caddr form)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((and (numberp arg1) (numberp arg2)) (if (/= arg1 arg2) :consequent :alternate)) ((and (fixnum-type-p type1) (fixnum-type-p type2)) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-test-jump 'if_icmpeq success-label failure-label)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "isNotEqualTo" '(:int) :boolean) (emit-test-jump 'ifeq success-label failure-label)) ((fixnum-type-p type1) ;; FIXME Compile the args in reverse order and avoid the swap if ;; either arg is a fixnum or a lexical variable. (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit 'swap) (emit-invokevirtual +lisp-object+ "isNotEqualTo" '(:int) :boolean) (emit-test-jump 'ifeq success-label failure-label)) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "isNotEqualTo" (lisp-object-arg-types 1) :boolean) (emit-test-jump 'ifeq success-label failure-label)))))) (defun p2-test-numeric-comparison (form success-label failure-label) (when (check-min-args form 1) (when (= (length form) 3) (let* ((op (%car form)) (args (%cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((and (fixnump arg1) (fixnump arg2)) (if (funcall op arg1 arg2) :consequent :alternate)) ((and (fixnum-type-p type1) (fixnum-type-p type2)) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-test-jump (ecase op (< 'if_icmpge) (<= 'if_icmpgt) (> 'if_icmple) (>= 'if_icmplt) (= 'if_icmpne)) success-label failure-label)) ((and (java-long-type-p type1) (java-long-type-p type2)) (with-operand-accumulation ((compile-operand arg1 :long) (compile-operand arg2 :long) (maybe-emit-clear-values arg1 arg2))) (emit 'lcmp) (emit-test-jump (ecase op (< 'ifge) (<= 'ifgt) (> 'ifle) (>= 'iflt) (= 'ifne)) success-label failure-label)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ (ecase op (< "isLessThan") (<= "isLessThanOrEqualTo") (> "isGreaterThan") (>= "isGreaterThanOrEqualTo") (= "isEqualTo")) '(:int) :boolean) (emit-test-jump 'ifeq success-label failure-label)) ((fixnum-type-p type1) ;; FIXME We can compile the args in reverse order and avoid ;; the swap if either arg is a fixnum or a lexical variable. (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit 'swap) (emit-invokevirtual +lisp-object+ (ecase op (< "isGreaterThan") (<= "isGreaterThanOrEqualTo") (> "isLessThan") (>= "isLessThanOrEqualTo") (= "isEqualTo")) '(:int) :boolean) (emit-test-jump 'ifeq success-label failure-label)) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ (ecase op (< "isLessThan") (<= "isLessThanOrEqualTo") (> "isGreaterThan") (>= "isGreaterThanOrEqualTo") (= "isEqualTo")) (lisp-object-arg-types 1) :boolean) (emit-test-jump 'ifeq success-label failure-label))))))) (defknown p2-if (t t t) t) (defun p2-if (form target representation) (let* ((test (second form)) (consequent (third form)) (alternate (fourth form)) (LABEL1 (gensym)) (LABEL2 (gensym))) (let ((result (compile-test-form test nil LABEL1))) (case result (:consequent (compile-form consequent target representation)) (:alternate (compile-form alternate target representation)) (t (compile-form consequent target representation) (emit 'goto LABEL2) (label LABEL1) (compile-form alternate target representation) (label LABEL2)))))) (defun compile-multiple-value-list (form target representation) (emit-clear-values) (compile-form (second form) 'stack nil) (emit-invokestatic +lisp+ "multipleValueList" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target)) (defun compile-multiple-value-prog1 (form target representation) (let ((first-subform (cadr form)) (subforms (cddr form)) (result-register (allocate-register nil)) (values-register (allocate-register nil))) ;; Make sure there are no leftover values from previous calls. (emit-clear-values) (compile-form first-subform result-register nil) ;; Save multiple values returned by first subform. (emit-push-current-thread) (emit-getfield +lisp-thread+ "_values" +lisp-object-array+) (astore values-register) (compile-progn-body subforms nil nil) ;; Restore multiple values returned by first subform. (emit-push-current-thread) (aload values-register) (emit-putfield +lisp-thread+ "_values" +lisp-object-array+) ;; Result. (aload result-register) (fix-boxing representation nil) (emit-move-from-stack target))) (defun compile-multiple-value-call (form target representation) ;; FIXME What if we're called with a non-NIL representation? (aver (null representation)) (case (length form) (1 (error "Wrong number of arguments for MULTIPLE-VALUE-CALL.")) (2 (compile-form (second form) 'stack nil) (emit-invokestatic +lisp+ "coerceToFunction" (lisp-object-arg-types 1) +lisp-object+) (emit-invokevirtual +lisp-object+ "execute" nil +lisp-object+)) (3 (let* ((*register* *register*) (function-register (allocate-register nil))) (compile-form (second form) function-register nil) (compile-form (third form) 'stack nil) (aload function-register) (emit-push-current-thread) (emit-invokestatic +lisp+ "multipleValueCall1" (list +lisp-object+ +lisp-object+ +lisp-thread+) +lisp-object+))) (t ;; The general case. (let* ((*register* *register*) (function-register (allocate-register nil)) (values-register (allocate-register nil))) (compile-form (second form) 'stack nil) (emit-invokestatic +lisp+ "coerceToFunction" (lisp-object-arg-types 1) +lisp-object+) (emit-move-from-stack function-register) (emit 'aconst_null) (astore values-register) (dolist (values-form (cddr form)) (compile-form values-form 'stack nil) (emit-push-current-thread) (emit 'swap) (aload values-register) (emit-invokevirtual +lisp-thread+ "accumulateValues" (list +lisp-object+ +lisp-object-array+) +lisp-object-array+) (astore values-register) (maybe-emit-clear-values values-form)) (aload function-register) (aload values-register) (emit-invokevirtual +lisp-object+ "dispatch" (list +lisp-object-array+) +lisp-object+)))) (fix-boxing representation nil) (emit-move-from-stack target)) (defknown unused-variable (t) t) (defun unused-variable (variable) (unless (or (variable-ignore-p variable) (variable-ignorable-p variable)) (compiler-style-warn "The variable ~S is defined but never used." (variable-name variable)))) (defknown check-for-unused-variables (list) t) (defun check-for-unused-variables (list) (dolist (variable list) (when (and (not (variable-special-p variable)) (zerop (variable-reads variable)) (zerop (variable-writes variable))) (unused-variable variable)))) (declaim (ftype (function (t) t) emit-new-closure-binding)) (defun emit-new-closure-binding (variable) "" (emit-new +lisp-closure-binding+) ;; value c-b (emit 'dup_x1) ;; c-b value c-b (emit 'swap) ;; c-b c-b value (emit-invokespecial-init +lisp-closure-binding+ (list +lisp-object+)) ;; c-b (aload (compiland-closure-register *current-compiland*)) ;; c-b array (emit 'swap) ;; array c-b (emit-push-constant-int (variable-closure-index variable)) ;; array c-b int (emit 'swap) ; array index value (emit 'aastore)) ;; Generates code to bind variable to value at top of runtime stack. (declaim (ftype (function (t) t) compile-binding)) (defun compile-binding (variable) (cond ((variable-register variable) (astore (variable-register variable))) ((variable-special-p variable) (emit-push-current-thread) (emit 'swap) (emit-push-variable-name variable) (emit 'swap) (emit-invokevirtual +lisp-thread+ "bindSpecial" (list +lisp-symbol+ +lisp-object+) +lisp-special-binding+) (if (variable-binding-register variable) (astore (variable-binding-register variable)) (emit 'pop))) ((variable-closure-index variable) ;; stack: (emit-new-closure-binding variable)) (t (sys::%format t "compile-binding~%") (aver nil)))) (defknown compile-progn-body (t t &optional t) t) (defun compile-progn-body (body target &optional representation) (cond ((null body) (when target (emit-push-nil) (emit-move-from-stack target))) (t (loop with clear-values = nil for tail on body for form = (car tail) do (cond ((null (cdr tail)) ;; Last form. (when clear-values (emit-clear-values)) (compile-form form target representation) (return)) (t ;; Not the last form. (compile-form form nil nil) (unless clear-values (unless (single-valued-p form) (setq clear-values t)))))))) t) (defun restore-dynamic-environment (register) (emit-push-current-thread) (aload register) (emit-invokevirtual +lisp-thread+ "resetSpecialBindings" (list +lisp-special-bindings-mark+) nil) ) (defun save-dynamic-environment (register) (emit-push-current-thread) (emit-invokevirtual +lisp-thread+ "markSpecialBindings" nil +lisp-special-bindings-mark+) (astore register) ) (defun p2-m-v-b-node (block target) (let* ((*register* *register*) (form (m-v-b-form block)) (*visible-variables* *visible-variables*) (vars (second form)) (bind-special-p nil) (variables (m-v-b-vars block))) (dolist (variable variables) (let ((special-p (variable-special-p variable))) (cond (special-p (setf bind-special-p t)) (t (unless (variable-closure-index variable) (setf (variable-register variable) (allocate-register nil))))))) ;; If we're going to bind any special variables... (when bind-special-p (dformat t "p2-m-v-b-node lastSpecialBinding~%") ;; Save current dynamic environment. (setf (m-v-b-environment-register block) (allocate-register nil)) (save-dynamic-environment (m-v-b-environment-register block))) ;; Make sure there are no leftover values from previous calls. (emit-clear-values) ;; Bind the variables. (aver (= (length vars) (length variables))) (cond ((= (length vars) 1) (compile-forms-and-maybe-emit-clear-values (third form) 'stack nil) (compile-binding (car variables))) (t (let* ((*register* *register*) (result-register (allocate-register nil)) (values-register (allocate-register nil)) (LABEL1 (gensym)) (LABEL2 (gensym))) ;; Store primary value from values form in result register. (compile-form (third form) result-register nil) ;; Store values from values form in values register. (emit-push-current-thread) (emit-getfield +lisp-thread+ "_values" +lisp-object-array+) (emit-move-from-stack values-register) ;; Did we get just one value? (aload values-register) (emit 'ifnull LABEL1) ;; Reaching here, we have multiple values (or no values at all). ;; We need the slow path if we have more variables than values. (aload values-register) (emit 'arraylength) (emit-push-constant-int (length vars)) (emit 'if_icmplt LABEL1) ;; Reaching here, we have enough values for all the variables. ;; We can use the values we have. This is the fast path. (aload values-register) (emit 'goto LABEL2) (label LABEL1) (emit-push-current-thread) (aload result-register) (emit-push-constant-int (length vars)) (emit-invokevirtual +lisp-thread+ "getValues" (list +lisp-object+ :int) +lisp-object-array+) ;; Values array is now on the stack at runtime. (label LABEL2) (let ((index 0)) (dolist (variable variables) (when (< index (1- (length vars))) (emit 'dup)) (emit-push-constant-int index) (incf index) (emit 'aaload) ;; Value is on the runtime stack at this point. (compile-binding variable))) (maybe-emit-clear-values (third form))))) ;; Make the variables visible for the body forms. (dolist (variable variables) (push variable *visible-variables*)) (dolist (variable (m-v-b-free-specials block)) (push variable *visible-variables*)) ;; Body. (with-saved-compiler-policy (process-optimization-declarations (cdddr form)) (let ((*blocks* (cons block *blocks*))) (compile-progn-body (cdddr form) target))) (when bind-special-p (restore-dynamic-environment (m-v-b-environment-register block))))) (defun propagate-vars (block) (let ((removed '())) (dolist (variable (let-vars block)) (unless (or (variable-special-p variable) (variable-closure-index variable)) (when (eql (variable-writes variable) 0) ;; There are no writes to the variable. (let ((initform (variable-initform variable))) (cond ((var-ref-p initform) (let ((source-var (var-ref-variable initform))) (cond ((null source-var) (aver (var-ref-constant-p initform)) (let ((value (var-ref-constant-value initform))) (dolist (ref (variable-references variable)) (aver (eq (var-ref-variable ref) variable)) (setf (var-ref-variable ref) nil (var-ref-constant-p ref) t (var-ref-constant-value ref) value)))) (t (unless (or (variable-special-p source-var) (variable-used-non-locally-p source-var)) (when (eql (variable-writes source-var) 0) ;; We can eliminate the variable. ;; FIXME This may no longer be true when we start tracking writes! (aver (= (variable-reads variable) (length (variable-references variable)))) (dolist (ref (variable-references variable)) (aver (eq (var-ref-variable ref) variable)) (setf (var-ref-variable ref) source-var)) ;; Check for DOTIMES limit variable. (when (get (variable-name variable) 'sys::dotimes-limit-variable-p) (let* ((symbol (get (variable-name variable) 'sys::dotimes-index-variable-name)) (index-variable (find-variable symbol (let-vars block)))) (when index-variable (setf (get (variable-name index-variable) 'sys::dotimes-limit-variable-name) (variable-name source-var))))) (push variable removed))))))) ((fixnump initform) (dolist (ref (variable-references variable)) (aver (eq (var-ref-variable ref) variable)) (setf (var-ref-variable ref) nil (var-ref-constant-p ref) t (var-ref-constant-value ref) initform)) (push variable removed))))))) (when removed (dolist (variable removed) (setf (let-vars block) (remove variable (let-vars block))))))) (defun derive-variable-representation (variable block &key (type nil type-supplied-p)) (when (not (null (variable-representation variable))) ;; representation already derived (return-from derive-variable-representation)) (when type-supplied-p (setf (variable-declared-type variable) type)) (when (or (variable-closure-index variable) (variable-index variable)) ;; variables in one of the arrays cannot be represented ;; other than by the boxed representation LispObject (return-from derive-variable-representation)) (let ((type (variable-declared-type variable))) (when (and (eq (variable-declared-type variable) :none) (eql (variable-writes variable) 0)) (variable-derived-type variable)) (cond ((neq type :none) (setf (variable-representation variable) (type-representation type)) (unless (memq (variable-representation variable) '(:int :long)) ;; We don't support unboxed variables other than INT and LONG (yet) (setf (variable-representation variable) NIL))) ((zerop (variable-writes variable)) (when (eq :none (variable-derived-type variable)) (setf (variable-derived-type variable) (derive-compiler-type (variable-initform variable)))) (let ((derived-type (variable-derived-type variable))) (setf (variable-derived-type variable) derived-type) (setf (variable-representation variable) (type-representation derived-type)) (unless (memq (variable-representation variable) '(:int :long)) ;; We don't support unboxed variables other than INT and LONG (yet) (setf (variable-representation variable) NIL)))) ((and block (get (variable-name variable) 'sys::dotimes-index-variable-p)) ;; DOTIMES index variable. (let* ((name (get (variable-name variable) 'sys::dotimes-limit-variable-name)) (limit-variable (and name (or (find-variable name (let-vars block)) (find-visible-variable name))))) (when limit-variable (derive-variable-representation limit-variable block) (setf (variable-representation variable) (variable-representation limit-variable)) (let ((limit-type (variable-derived-type limit-variable))) (when (integer-type-p limit-type) (setf (variable-derived-type variable) (%make-integer-type 0 (integer-type-high limit-type))))))))))) (defun allocate-variable-register (variable) (setf (variable-register variable) (allocate-register (variable-representation variable)))) (defun emit-move-to-variable (variable) (let ((representation (variable-representation variable))) (cond ((variable-register variable) (emit (ecase (variable-representation variable) ((:int :boolean :char) 'istore) (:long 'lstore) (:float 'fstore) (:double 'dstore) ((nil) 'astore)) (variable-register variable))) ((variable-index variable) (aload (compiland-argument-register *current-compiland*)) (emit-swap representation nil) (emit-push-constant-int (variable-index variable)) (emit-swap representation :int) (emit 'aastore)) ((variable-closure-index variable) (aload (compiland-closure-register *current-compiland*)) (emit-push-constant-int (variable-closure-index variable)) (emit 'aaload) (emit-swap representation nil) (emit-putfield +lisp-closure-binding+ "value" +lisp-object+)) ((variable-environment variable) (assert (not *file-compilation*)) (emit-load-externalized-object (variable-environment variable) +lisp-environment+) (emit 'swap) (emit-push-variable-name variable) (emit 'swap) (emit-invokevirtual +lisp-environment+ "rebind" (list +lisp-symbol+ +lisp-object+) nil)) (t (assert nil))))) (defun emit-push-variable (variable) (cond ((variable-register variable) (emit (ecase (variable-representation variable) ((:int :boolean :char) 'iload) (:long 'lload) (:float 'fload) (:double 'dload) ((nil) 'aload)) (variable-register variable))) ((variable-index variable) (aload (compiland-argument-register *current-compiland*)) (emit-push-constant-int (variable-index variable)) (emit 'aaload)) ((variable-closure-index variable) (aload (compiland-closure-register *current-compiland*)) (emit-push-constant-int (variable-closure-index variable)) (emit 'aaload) (emit-getfield +lisp-closure-binding+ "value" +lisp-object+)) ((variable-environment variable) (assert (not *file-compilation*)) (emit-load-externalized-object (variable-environment variable) +lisp-environment+) (emit-push-variable-name variable) (emit-invokevirtual +lisp-environment+ "lookup" (list +lisp-object+) +lisp-object+)) (t (assert nil)))) (defknown p2-let-bindings (t) t) (defun p2-let-bindings (block) (dolist (variable (let-vars block)) (unless (or (variable-special-p variable) (variable-closure-index variable) (zerop (variable-reads variable))) (aver (null (variable-register variable))) (setf (variable-register variable) t))) (let (must-clear-values temporary-storage) (declare (type boolean must-clear-values)) ;; Evaluate each initform. If the variable being bound is special, allocate ;; a temporary register for the result; LET bindings must be done in ;; parallel, so we can't modify any specials until all the initforms have ;; been evaluated. Note that we can't just push the values on the stack ;; because we'll lose JVM stack consistency if there is a non-local ;; transfer of control from one of the initforms. (dolist (variable (let-vars block)) (let* ((initform (variable-initform variable)) (unused-p (and (not (variable-special-p variable)) ;; If it's never read, we don't care about writes. (zerop (variable-reads variable))))) (cond (unused-p (compile-form initform nil nil)) ; for effect (t (cond (initform (when (eq (variable-register variable) t) (derive-variable-representation variable block)) (compile-form initform 'stack (variable-representation variable)) (unless must-clear-values (unless (single-valued-p initform) (setf must-clear-values t)))) (t ;; No initform. (emit-push-nil))) (when (eq (variable-register variable) t) ;; Now allocate the register. (allocate-variable-register variable)) (when (variable-special-p variable) (setf (variable-binding-register variable) (allocate-register nil))) (cond ((variable-special-p variable) (let ((temp-register (allocate-register nil))) ;; FIXME: this permanently allocates a register ;; which has only a single local use (push (cons temp-register variable) temporary-storage) (emit-move-from-stack temp-register))) ((variable-representation variable) (emit-move-to-variable variable)) (t (compile-binding variable))))))) (when must-clear-values (emit-clear-values)) ;; Now that all the initforms have been evaluated, move the results from ;; the temporary registers (if any) to their proper destinations. (dolist (temp temporary-storage) (aload (car temp)) (compile-binding (cdr temp)))) ;; Now make the variables visible. (dolist (variable (let-vars block)) (push variable *visible-variables*)) t) (defknown p2-let*-bindings (t) t) (defun p2-let*-bindings (block) (let ((must-clear-values nil)) (declare (type boolean must-clear-values)) ;; Generate code to evaluate initforms and bind variables. (dolist (variable (let-vars block)) (let* ((initform (variable-initform variable)) (unused-p (and (not (variable-special-p variable)) (zerop (variable-reads variable)) (zerop (variable-writes variable)))) (boundp nil)) (declare (type boolean unused-p boundp)) (macrolet ((update-must-clear-values () `(unless must-clear-values (unless (single-valued-p initform) (setf must-clear-values t))))) (cond ((and (variable-special-p variable) (eq initform (variable-name variable))) ;; The special case of binding a special to its current value. (emit-push-current-thread) (emit-push-variable-name variable) (emit-invokevirtual +lisp-thread+ "bindSpecialToCurrentValue" (list +lisp-symbol+) +lisp-special-binding+) (if (variable-binding-register variable) (astore (variable-binding-register variable)) (emit 'pop)) (setf boundp t)) ((and (not (variable-special-p variable)) (zerop (variable-reads variable))) ;; We don't have to bind it if we never read it. (compile-form initform nil nil) ; for effect (update-must-clear-values) (setf boundp t)) ((null initform) (cond ((and (null (variable-closure-index variable)) (not (variable-special-p variable)) (eq (variable-declared-type variable) 'BOOLEAN)) (setf (variable-representation variable) :boolean) (setf (variable-register variable) (allocate-register nil)) (emit 'iconst_0) (emit 'istore (variable-register variable)) (setf boundp t)) (t (emit-push-nil)))) (t (cond (unused-p (compile-form initform nil nil) ; for effect (update-must-clear-values) (setf boundp t)) ((and (null (variable-closure-index variable)) (not (variable-special-p variable))) (when (and (eq (variable-declared-type variable) :none) (eql (variable-writes variable) 0)) (setf (variable-derived-type variable) (derive-compiler-type initform))) (derive-variable-representation variable block) (allocate-variable-register variable) (compile-form initform 'stack (variable-representation variable)) (update-must-clear-values) (emit-move-to-variable variable) (setf boundp t)) (t (compile-form initform 'stack nil) (update-must-clear-values)))))) (unless (or boundp (variable-special-p variable)) (unless (or (variable-closure-index variable) (variable-register variable)) (setf (variable-register variable) (allocate-register nil)))) (push variable *visible-variables*) (unless boundp (when (variable-special-p variable) (setf (variable-binding-register variable) (allocate-register nil))) (compile-binding variable)) (maybe-generate-type-check variable))) (when must-clear-values (emit-clear-values))) t) (defun p2-let/let*-node (block target representation) (let* ( (*register* *register*) (form (let-form block)) (*visible-variables* *visible-variables*) (specialp nil)) ;; Walk the variable list looking for special bindings and unused lexicals. (dolist (variable (let-vars block)) (cond ((variable-special-p variable) (setf specialp t)) ((zerop (variable-reads variable)) (unused-variable variable)))) ;; If there are any special bindings... (when specialp ;; We need to save current dynamic environment. (setf (let-environment-register block) (allocate-register nil)) (save-dynamic-environment (let-environment-register block))) (propagate-vars block) (ecase (car form) (LET (p2-let-bindings block)) (LET* (p2-let*-bindings block))) ;; Make declarations of free specials visible. (dolist (variable (let-free-specials block)) (push variable *visible-variables*)) ;; Body of LET/LET*. (with-saved-compiler-policy (process-optimization-declarations (cddr form)) (let ((*blocks* (cons block *blocks*))) (compile-progn-body (cddr form) target representation))) (when specialp (restore-dynamic-environment (let-environment-register block))))) (defknown p2-locally-node (t t t) t) (defun p2-locally-node (block target representation) (with-saved-compiler-policy (let* ((body (cdr (locally-form block))) (*visible-variables* (append (locally-free-specials block) *visible-variables*)) (*blocks* (cons block *blocks*))) (process-optimization-declarations body) (compile-progn-body body target representation)))) (defknown p2-tagbody-node (t t) t) (defun p2-tagbody-node (block target) (let* ((*blocks* (cons block *blocks*)) (*visible-tags* *visible-tags*) (*register* *register*) (form (tagbody-form block)) (body (cdr form)) (BEGIN-BLOCK (gensym "F")) (END-BLOCK (gensym "U")) (RETHROW (gensym "T")) (EXIT (gensym "E")) (must-clear-values nil) (specials-register (when (tagbody-non-local-go-p block) (allocate-register nil)))) ;; Scan for tags. (dolist (tag (tagbody-tags block)) (push tag *visible-tags*)) (when (tagbody-id-variable block) ;; we have a block variable; that should be a closure variable (assert (not (null (variable-closure-index (tagbody-id-variable block))))) (emit-new +lisp-object+) (emit 'dup) (emit-invokespecial-init +lisp-object+ '()) (emit-new-closure-binding (tagbody-id-variable block))) (when (tagbody-non-local-go-p block) (save-dynamic-environment specials-register)) (label BEGIN-BLOCK) (do* ((rest body (cdr rest)) (subform (car rest) (car rest))) ((null rest)) (cond ((or (symbolp subform) (integerp subform)) (let ((tag (find subform (tagbody-tags block) :key #'tag-name :test #'eql))) (unless tag (error "COMPILE-TAGBODY: tag not found: ~S~%" subform)) (when (tag-used tag) (label (tag-label tag))))) (t (compile-form subform nil nil) (unless must-clear-values (setf must-clear-values (not (single-valued-p subform))))))) (label END-BLOCK) (emit 'goto EXIT) (when (tagbody-non-local-go-p block) ; We need a handler to catch non-local GOs. (let* ((HANDLER (gensym "H")) (EXTENT-EXIT-HANDLER (gensym "HE")) (*register* *register*) (go-register (allocate-register nil)) (tag-register (allocate-register nil))) (label HANDLER) ;; The Go object is on the runtime stack. Stack depth is 1. (emit 'dup) (astore go-register) ;; Get the tag. (emit-getfield +lisp-go+ "tagbody" +lisp-object+) ; Stack depth is still 1. (emit-push-variable (tagbody-id-variable block)) (emit 'if_acmpne RETHROW) ;; Not this TAGBODY (aload go-register) (emit-getfield +lisp-go+ "tag" +lisp-object+) ; Stack depth is still 1. (astore tag-register) (restore-dynamic-environment specials-register) ;; Don't actually generate comparisons for tags ;; to which there is no non-local GO instruction (dolist (tag (remove-if-not #'tag-used-non-locally (tagbody-tags block))) (aload tag-register) (emit-load-externalized-object (tag-label tag)) ;; Jump if EQ. (emit 'if_acmpeq (tag-label tag))) (label RETHROW) ;; Not found. Re-throw Go. (aload go-register) (emit 'aconst_null) ;; load null value (emit-move-to-variable (tagbody-id-variable block)) (emit 'athrow) (label EXTENT-EXIT-HANDLER) (emit 'aconst_null) ;; load null value (emit-move-to-variable (tagbody-id-variable block)) (emit 'athrow) ;; Finally... (add-exception-handler BEGIN-BLOCK END-BLOCK HANDLER +lisp-go+) (add-exception-handler BEGIN-BLOCK END-BLOCK EXTENT-EXIT-HANDLER nil))) (label EXIT) (when (tagbody-non-local-go-p block) (emit 'aconst_null) ;; load null value (emit-move-to-variable (tagbody-id-variable block))) (when must-clear-values (emit-clear-values)) ;; TAGBODY returns NIL. (when target (emit-push-nil) (emit-move-from-stack target))) ) (defknown p2-go (t t t) t) (defun p2-go (form target representation) ;; FIXME What if we're called with a non-NIL representation? (declare (ignore target representation)) (let* ((node form) (form (node-form form)) (name (cadr form)) (tag (jump-target-tag node)) (tag-block (when tag (jump-target-block node)))) (unless tag (error "p2-go: tag not found: ~S" name)) (when (and (eq (tag-compiland tag) *current-compiland*) (not (enclosed-by-protected-block-p tag-block))) ;; Local case with local transfer of control ;; Note: Local case with non-local transfer of control handled below (when (and (tagbody-needs-environment-restoration tag-block) (enclosed-by-environment-setting-block-p tag-block)) ;; If there's a dynamic environment to restore, do it. (restore-dynamic-environment (environment-register-to-restore tag-block))) (maybe-generate-interrupt-check) (emit 'goto (tag-label tag)) (return-from p2-go)) ;; Non-local GO. (emit-push-variable (tagbody-id-variable tag-block)) (emit-load-externalized-object (tag-label tag)) ; Tag. (emit-invokestatic +lisp+ "nonLocalGo" (lisp-object-arg-types 2) +lisp-object+) ;; Following code will not be reached, but is needed for JVM stack ;; consistency. (emit 'areturn))) (defknown p2-atom (t t t) t) (define-inlined-function p2-atom (form target representation) ((aver (or (null representation) (eq representation :boolean))) (check-arg-count form 1)) (compile-forms-and-maybe-emit-clear-values (cadr form) 'stack nil) (emit-instanceof +lisp-cons+) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit 'ifeq LABEL1) (ecase representation (:boolean (emit 'iconst_0)) ((nil) (emit-push-nil))) (emit 'goto LABEL2) (label LABEL1) (ecase representation (:boolean (emit 'iconst_1)) ((nil) (emit-push-t))) (label LABEL2) (emit-move-from-stack target representation))) (defknown p2-instanceof-predicate (t t t t) t) (defun p2-instanceof-predicate (form target representation java-class) (unless (check-arg-count form 1) (compile-function-call form target representation) (return-from p2-instanceof-predicate)) (let ((arg (%cadr form))) (cond ((null target) (compile-forms-and-maybe-emit-clear-values arg nil nil)) (t (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-instanceof java-class) (convert-representation :boolean representation) (emit-move-from-stack target representation))))) (defun p2-bit-vector-p (form target representation) (p2-instanceof-predicate form target representation +lisp-abstract-bit-vector+)) (defun p2-characterp (form target representation) (p2-instanceof-predicate form target representation +lisp-character+)) (defun p2-consp (form target representation) (p2-instanceof-predicate form target representation +lisp-cons+)) (defun p2-fixnump (form target representation) (p2-instanceof-predicate form target representation +lisp-fixnum+)) (defun p2-packagep (form target representation) (p2-instanceof-predicate form target representation +lisp-package+)) (defun p2-readtablep (form target representation) (p2-instanceof-predicate form target representation +lisp-readtable+)) (defun p2-simple-vector-p (form target representation) (p2-instanceof-predicate form target representation +lisp-simple-vector+)) (defun p2-stringp (form target representation) (p2-instanceof-predicate form target representation +lisp-abstract-string+)) (defun p2-symbolp (form target representation) (p2-instanceof-predicate form target representation +lisp-symbol+)) (defun p2-vectorp (form target representation) (p2-instanceof-predicate form target representation +lisp-abstract-vector+)) (define-inlined-function p2-coerce-to-function (form target representation) ((check-arg-count form 1)) (compile-forms-and-maybe-emit-clear-values (%cadr form) 'stack nil) (emit-invokestatic +lisp+ "coerceToFunction" (lisp-object-arg-types 1) +lisp-object+) (emit-move-from-stack target)) (defun p2-block-node (block target representation) (unless (block-node-p block) (sys::%format t "type-of block = ~S~%" (type-of block)) (aver (block-node-p block))) (let* ((*blocks* (cons block *blocks*)) (*register* *register*) (BEGIN-BLOCK (gensym "F")) (END-BLOCK (gensym "U")) (BLOCK-EXIT (block-exit block)) (specials-register (when (block-non-local-return-p block) (allocate-register nil)))) (setf (block-target block) target) (when (block-id-variable block) ;; we have a block variable; that should be a closure variable (assert (not (null (variable-closure-index (block-id-variable block))))) (emit-new +lisp-object+) (emit 'dup) (emit-invokespecial-init +lisp-object+ '()) (emit-new-closure-binding (block-id-variable block))) (dformat t "*all-variables* = ~S~%" (mapcar #'variable-name *all-variables*)) (when (block-non-local-return-p block) (save-dynamic-environment specials-register)) (label BEGIN-BLOCK) ; Start of protected range, for non-local returns ;; Implicit PROGN. (compile-progn-body (cddr (block-form block)) target) (label END-BLOCK) ; End of protected range, for non-local returns (when (block-non-local-return-p block) ;; We need a handler to catch non-local RETURNs. (emit 'goto BLOCK-EXIT) ; Jump over handler, when inserting one (let ((HANDLER (gensym "H")) (EXTENT-EXIT-HANDLER (gensym "HE")) (THIS-BLOCK (gensym))) (label HANDLER) ;; The Return object is on the runtime stack. Stack depth is 1. (emit 'dup) ; Stack depth is 2. (emit-getfield +lisp-return+ "tag" +lisp-object+) ; Still 2. (emit-push-variable (block-id-variable block)) ;; If it's not the block we're looking for... (emit 'if_acmpeq THIS-BLOCK) ; Stack depth is 1. ;; Not the tag we're looking for. (emit 'aconst_null) ;; load null value (emit-move-to-variable (block-id-variable block)) (emit 'athrow) (label EXTENT-EXIT-HANDLER) ;; Not the tag we're looking for. (emit 'aconst_null) ;; load null value (emit-move-to-variable (block-id-variable block)) (emit 'athrow) (label THIS-BLOCK) (restore-dynamic-environment specials-register) (emit-getfield +lisp-return+ "result" +lisp-object+) (emit-move-from-stack target) ; Stack depth is 0. ;; Finally... (add-exception-handler BEGIN-BLOCK END-BLOCK HANDLER +lisp-return+) (add-exception-handler BEGIN-BLOCK END-BLOCK EXTENT-EXIT-HANDLER nil))) (label BLOCK-EXIT) (when (block-id-variable block) (emit 'aconst_null) ;; load null value (emit-move-to-variable (block-id-variable block))) (fix-boxing representation nil))) (defknown p2-return-from (t t t) t) (defun p2-return-from (form target representation) ;; FIXME What if we're called with a non-NIL representation? (declare (ignore target representation)) (let* ((node form) (form (node-form form)) (name (second form)) (result-form (third form)) (block (jump-target-block node))) (when (null block) (error "No block named ~S is currently visible." name)) (let ((compiland *current-compiland*)) (when (eq (block-compiland block) compiland) ;; Local case. Is the RETURN nested inside an UNWIND-PROTECT which is ;; inside the block we're returning from? (unless (enclosed-by-protected-block-p block) (emit-clear-values) (compile-form result-form (block-target block) nil) (when (and (block-needs-environment-restoration block) (enclosed-by-environment-setting-block-p block)) (restore-dynamic-environment (environment-register-to-restore block))) (emit 'goto (block-exit block)) (return-from p2-return-from)))) ;; Non-local RETURN. (aver (block-non-local-return-p block)) (emit-clear-values) (with-operand-accumulation ((emit-variable-operand (block-id-variable block)) (emit-load-externalized-object-operand (block-name block)) (compile-operand result-form nil)) (emit-invokestatic +lisp+ "nonLocalReturn" (lisp-object-arg-types 3) +lisp-object+)) ;; Following code will not be reached, but is needed for JVM stack ;; consistency. (emit 'areturn))) (defun emit-car/cdr (arg target representation field) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-invoke-method field target representation)) (define-inlined-function p2-car (form target representation) ((check-arg-count form 1)) (let ((arg (%cadr form))) (cond ((and (null target) (< *safety* 3)) (compile-form arg target nil)) ((and (consp arg) (eq (%car arg) 'cdr) (= (length arg) 2)) (compile-forms-and-maybe-emit-clear-values (second arg) 'stack nil) (emit-invoke-method "cadr" target representation)) (t (emit-car/cdr arg target representation "car"))))) (define-inlined-function p2-cdr (form target representation) ((check-arg-count form 1)) (let ((arg (%cadr form))) (emit-car/cdr arg target representation "cdr"))) (define-inlined-function p2-cons (form target representation) ((check-arg-count form 2)) (let* ((args (%cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) (cons-register (when (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks args)) (allocate-register nil)))) (emit-new +lisp-cons+) (if cons-register (astore cons-register) (emit 'dup)) (with-operand-accumulation ((when cons-register (emit-register-operand cons-register nil)) (compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokespecial-init +lisp-cons+ (lisp-object-arg-types 2)) (when cons-register (emit-push-register cons-register nil)) (emit-move-from-stack target))) (defun compile-progn (form target representation) (compile-progn-body (cdr form) target) (fix-boxing representation nil)) (defun p2-eval-when (form target representation) (cond ((or (memq :execute (cadr form)) (memq 'eval (cadr form))) (compile-progn-body (cddr form) target) (fix-boxing representation nil)) (t (emit-push-nil) (emit-move-from-stack target)))) (defun p2-load-time-value (form target representation) (cond (*file-compilation* (emit-getstatic *this-class* (declare-load-time-value (second form)) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (compile-constant (eval (second form)) target representation)))) (defun p2-progv-node (block target representation) (let* ((form (progv-form block)) (symbols-form (cadr form)) (values-form (caddr form)) (*register* *register*) (environment-register (setf (progv-environment-register block) (allocate-register nil)))) (with-operand-accumulation ((compile-operand symbols-form nil) (compile-operand values-form nil)) (unless (and (single-valued-p symbols-form) (single-valued-p values-form)) (emit-clear-values)) (save-dynamic-environment environment-register) ;; Compile call to Lisp.progvBindVars(). (emit-push-current-thread) (emit-invokestatic +lisp+ "progvBindVars" (list +lisp-object+ +lisp-object+ +lisp-thread+) nil)) ;; Implicit PROGN. (let ((*blocks* (cons block *blocks*))) (compile-progn-body (cdddr form) target representation)) (restore-dynamic-environment environment-register))) (defun p2-quote (form target representation) (aver (or (null representation) (eq representation :boolean))) (let ((obj (second form))) (cond ((null obj) (when target (emit-push-false representation) (emit-move-from-stack target representation))) ((eq representation :boolean) (emit 'iconst_1) (emit-move-from-stack target representation)) ((symbolp obj) (emit-load-externalized-object obj) (emit-move-from-stack target representation)) ((listp obj) (emit-load-externalized-object obj) (emit-move-from-stack target representation)) ((constantp obj) (compile-constant obj target representation)) (t (compiler-unsupported "COMPILE-QUOTE: unsupported case: ~S" form))))) (define-inlined-function p2-rplacd (form target representation) ((check-arg-count form 2)) (let* ((args (cdr form)) (*register* *register*) (target-register (allocate-register nil))) (with-operand-accumulation ((accumulate-operand (nil :unsafe-p (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks (first args)))) (compile-form (first args) 'stack nil) (when target-register (emit 'dup) (astore target-register))) (compile-operand (second args) nil))) (maybe-emit-clear-values (car args) (cadr args)) (emit-invokevirtual +lisp-object+ "setCdr" (lisp-object-arg-types 1) nil) (when target-register (aload target-register) (fix-boxing representation nil) (emit-move-from-stack target representation)))) (define-inlined-function p2-set-car/cdr (form target representation) ((check-arg-count form 2)) (let* ((op (%car form)) (args (%cdr form)) (*register* *register*) (target-register (when target (allocate-register nil)))) (with-operand-accumulation ((compile-operand (%car args) nil) (accumulate-operand (nil :unsafe-p (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks (cadr args)))) (compile-form (%cadr args) 'stack nil) (when target-register (emit 'dup) (astore target-register))) (maybe-emit-clear-values (car args) (cadr args)))) (emit-invokevirtual +lisp-object+ (if (eq op 'sys:set-car) "setCar" "setCdr") (lisp-object-arg-types 1) nil) (when target-register (aload target-register) (fix-boxing representation nil) (emit-move-from-stack target representation)))) (defun compile-declare (form target representation) (declare (ignore form representation)) (when target (emit-push-nil) (emit-move-from-stack target))) (defun compile-local-function (local-function) (let* ((compiland (local-function-compiland local-function)) (pathname (funcall *pathnames-generator*)) (class-file (make-abcl-class-file :pathname pathname)) (stream (unless *file-compilation* (sys::%make-byte-array-output-stream)))) (setf (compiland-class-file compiland) class-file) (with-open-stream (f (or stream (open pathname :direction :output :element-type '(unsigned-byte 8) :if-exists :supersede))) (with-class-file class-file (compile-to-jvm-class compiland) (finish-class (compiland-class-file compiland) f))) (when stream (let ((bytes (sys::%get-output-stream-bytes stream))) (sys::put-memory-function *memory-class-loader* (class-name-internal (abcl-class-file-class-name (compiland-class-file compiland))) bytes))))) (defknown p2-flet-node (t t t) t) (defun p2-flet-node (block target representation) (let* ((form (flet-form block)) (*local-functions* *local-functions*) (*visible-variables* *visible-variables*) (local-functions (cadr form)) (body (cddr form))) (dolist (local-function local-functions) (compile-local-function local-function)) (dolist (local-function local-functions) (push local-function *local-functions*)) (dolist (special (flet-free-specials block)) (push special *visible-variables*)) (with-saved-compiler-policy (process-optimization-declarations body) (let ((*blocks* (cons block *blocks*))) (compile-progn-body body target representation))))) (defknown p2-labels-node (t t t) t) (defun p2-labels-node (block target representation) (let* ((form (labels-form block)) (*local-functions* *local-functions*) (*visible-variables* *visible-variables*) (local-functions (cadr form)) (body (cddr form))) (dolist (local-function local-functions) (push local-function *local-functions*)) (dolist (local-function local-functions) (compile-local-function local-function)) (dolist (special (labels-free-specials block)) (push special *visible-variables*)) (with-saved-compiler-policy (process-optimization-declarations body) (let ((*blocks* (cons block *blocks*))) (compile-progn-body body target representation))))) (defun p2-lambda (local-function target) (compile-local-function local-function) (emit-load-local-function local-function) (emit-move-from-stack target)) (defknown p2-function (t t t) t) (defun p2-function (form target representation) ;; FIXME What if we're called with a non-NIL representation? (declare (ignore representation)) (let ((name (second form)) local-function) (cond ((symbolp name) (dformat t "p2-function case 1~%") (cond ((setf local-function (find-local-function name)) (dformat t "p2-function 1~%") (emit-load-local-function local-function) (emit-move-from-stack target)) ((inline-ok name) ;; ### FASLATONCE: when compiling fasl functions after the ;; full fasl has been processed, forward referenced functions ;; may not be available during the load process ;; This case is particularly triggered with circular referencing ;; functions, both marked as 'notinline' (emit-getstatic *this-class* (declare-function name) +lisp-object+) (emit-move-from-stack target)) (t (emit-load-externalized-object name) (emit-invokevirtual +lisp-object+ "getSymbolFunctionOrDie" nil +lisp-object+) (emit-move-from-stack target)))) ((and (consp name) (eq (%car name) 'SETF)) (dformat t "p2-function case 2~%") ;; FIXME Need to check for NOTINLINE declaration! (cond ((setf local-function (find-local-function name)) (dformat t "p2-function 1~%") (emit-load-local-function local-function)) ((and (member name *functions-defined-in-current-file* :test #'equal) (not (notinline-p name))) ;; ### FASLATONCE: when compiling fasl functions after the ;; full fasl has been processed, forward referenced functions ;; may not be available during the load process ;; This case is particularly triggered with circular referencing ;; functions, both marked as 'notinline' (emit-getstatic *this-class* (declare-setf-function name) +lisp-object+) (emit-move-from-stack target)) ((and (null *file-compilation*) (fboundp name) (fdefinition name)) (emit-load-externalized-object (fdefinition name)) (emit-move-from-stack target)) (t (emit-load-externalized-object (cadr name)) (emit-invokevirtual +lisp-symbol+ "getSymbolSetfFunctionOrDie" nil +lisp-object+) (emit-move-from-stack target)))) ((local-function-p name) (dformat t "p2-function case 3~%") (p2-lambda name target)) (t (compiler-unsupported "p2-function: unsupported case: ~S" form))))) (defknown p2-ash (t t t) t) (define-inlined-function p2-ash (form target representation) ((check-arg-count form 2)) (let* ((args (%cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2)) (low2 (and (fixnum-type-p type2) (integer-type-low type2))) (high2 (and (fixnum-type-p type2) (integer-type-high type2))) (constant-shift (fixnum-constant-value type2)) (result-type (derive-compiler-type form))) (cond ((and (integerp arg1) (integerp arg2)) ;; test t/ash.lisp: ash-constant (compile-constant (ash arg1 arg2) target representation)) ((and (integerp arg1) constant-shift) ;; test t/ash.lisp: ash-constant2 (compile-constant (ash arg1 constant-shift) target representation)) ((and constant-shift ;; ishl/ishr only use the low five bits of the mask. (<= -31 constant-shift 31) (fixnum-type-p type1) (fixnum-type-p result-type)) (cond ((plusp constant-shift) ;; test t/ash.lisp: ash-fixnum1-pos-constant-shift2 (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit 'ishl)) ((minusp constant-shift) (cond ((fixnump arg2) ;; test t/ash.lisp: ash-fixnum1-neg-constant-shift2 (with-operand-accumulation ((compile-operand arg1 :int) (accumulate-operand (:int) (emit-push-constant-int (- arg2))) (maybe-emit-clear-values arg1)))) (t ;; test t/ash.lisp: ash-fixnum1-neg-constant-shift-form2 (with-operand-accumulation ((compile-operand arg1 :int) (accumulate-operand (:int) (compile-form arg2 'stack :int) (emit 'ineg)) (maybe-emit-clear-values arg1 arg2))))) (maybe-emit-clear-values arg1 arg2) (emit 'ishr)) ((zerop constant-shift) ;; test t/ash.lisp: ash-fixnum1-zero-shift2 (compile-form arg1 'stack :int) (compile-form arg2 nil nil))) ; for effect (convert-representation :int representation) (emit-move-from-stack target representation)) ((and constant-shift ;; lshl/lshr only use the low six bits of the mask. (<= -63 constant-shift 63) (java-long-type-p type1) (java-long-type-p result-type)) (cond ((plusp constant-shift) ;; test t/ash.lisp: ash-long1-pos-constant-shift2 (with-operand-accumulation ((compile-operand arg1 :long) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit 'lshl)) ((minusp constant-shift) (cond ((fixnump arg2) ;; test t/ash.lisp: ash-long1-neg-constant-shift2 (with-operand-accumulation ((compile-operand arg1 :long) (with-operand-accumulation (:int) (emit-push-constant-int (- arg2))) (maybe-emit-clear-values arg1)))) (t ;; test t/ash.lisp: ash-long1-neg-constant-shift-form2 (with-operand-accumulation ((compile-operand arg1 :long) (accumulate-operand (:int) (compile-form arg2 'stack :int) (emit 'ineg)) (maybe-emit-clear-values arg1 arg2))))) (maybe-emit-clear-values arg1 arg2) (emit 'lshr)) ((zerop constant-shift) ;; test t/ash.lisp: ash-long1-zero-shift2 (compile-form arg1 'stack :long) (compile-form arg2 nil nil))) ; for effect (convert-representation :long representation) (emit-move-from-stack target representation)) ((and (fixnum-type-p type1) low2 high2 (<= -31 low2 high2 0)) ; Negative shift. ;; t/ash.lisp: ash-fixnum1-neg-2 (with-operand-accumulation ((compile-operand arg1 :int) (accumulate-operand (:int) (compile-operand arg2 :int) (emit 'ineg)))) (maybe-emit-clear-values arg1 arg2) (emit 'ishr) (convert-representation :int representation) (emit-move-from-stack target representation)) ((fixnum-type-p type2) (cond ((and low2 high2 (<= 0 low2 high2 63) ; Non-negative shift. (java-long-type-p type1) (java-long-type-p result-type)) ;; test t/ash.lisp: ash-long1-pos-fixnum2 (with-operand-accumulation ((compile-operand arg1 :long) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit 'lshl) (convert-representation :long representation)) ((and low2 high2 (<= -63 low2 high2 0) ; Negative shift. (java-long-type-p type1) (java-long-type-p result-type)) ;; test t/ash.lisp: ash-long1-neg-fixnum2 (with-operand-accumulation ((compile-operand arg1 :long) (accumulate-operand (:int) (compile-operand arg2 :int) (emit 'ineg)))) (maybe-emit-clear-values arg1 arg2) (emit 'lshr) (convert-representation :long representation)) (t ;; test t/ash.lisp ash-long1-fixnum2 (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "ash" '(:int) +lisp-object+) (fix-boxing representation result-type))) (emit-move-from-stack target representation)) (t ;; test t/ash.lisp: ash-regular (compile-function-call form target representation))))) (defknown p2-logand (t t t) t) (defun p2-logand (form target representation) (let* ((args (cdr form))) (case (length args) (2 (let* ((arg1 (%car args)) (arg2 (%cadr args)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2)) (result-type (derive-compiler-type form))) (cond ((and (integerp arg1) (integerp arg2)) (compile-constant (logand arg1 arg2) target representation)) ((and (integer-type-p type1) (eql arg2 0)) (compile-forms-and-maybe-emit-clear-values arg1 nil nil) (compile-constant 0 target representation)) ((eql (fixnum-constant-value type1) -1) (compile-forms-and-maybe-emit-clear-values arg1 nil nil arg2 target representation)) ((eql (fixnum-constant-value type2) -1) (let ((target-register (if (or (not (eq target 'stack)) (not (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks arg2)))) target (allocate-register representation)))) (compile-form arg1 target-register representation) (compile-form arg2 nil nil) (when (and (eq target 'stack) (not (eq target-register 'stack))) (emit-push-register target-register)) (maybe-emit-clear-values arg1 arg2))) ((and (fixnum-type-p type1) (fixnum-type-p type2)) ;; Both arguments are fixnums. (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit 'iand) (convert-representation :int representation) (emit-move-from-stack target representation)) ((or (and (fixnum-type-p type1) (member type2 '(:long :int)) (compiler-subtypep type1 'unsigned-byte)) (and (fixnum-type-p type2) (member type1 '(:long :int)) (compiler-subtypep type2 'unsigned-byte))) ;; One of the arguments is a positive fixnum. (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit 'iand) (convert-representation :int representation) (emit-move-from-stack target representation)) ((and (java-long-type-p type1) (java-long-type-p type2)) ;; Both arguments are longs. (with-operand-accumulation ((compile-operand arg1 :long) (compile-operand arg2 :long) (maybe-emit-clear-values arg1 arg2))) (emit 'land) (convert-representation :long representation) (emit-move-from-stack target representation)) ((or (and (java-long-type-p type1) (member type2 '(:long :int)) (compiler-subtypep type1 'unsigned-byte)) (and (java-long-type-p type2) (member type1 '(:long :int)) (compiler-subtypep type2 'unsigned-byte))) ;; One of the arguments is a positive long. (with-operand-accumulation ((compile-operand arg1 :long) (compile-operand arg2 :long) (maybe-emit-clear-values arg1 arg2))) (emit 'land) (convert-representation :long representation) (emit-move-from-stack target representation)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "LOGAND" '(:int) +lisp-object+) (fix-boxing representation result-type) (emit-move-from-stack target representation)) ((fixnum-type-p type1) ;; arg1 is a fixnum, but arg2 is not (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) ;; swap args (emit 'swap) (emit-invokevirtual +lisp-object+ "LOGAND" '(:int) +lisp-object+) (fix-boxing representation result-type) (emit-move-from-stack target representation)) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "LOGAND" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation result-type) (emit-move-from-stack target representation))))) (t (compile-function-call form target representation))))) (defknown p2-logior (t t t) t) (defun p2-logior (form target representation) (let ((args (cdr form))) (case (length args) (0 (compile-constant 0 target representation)) (1 (let ((arg (%car args))) (compile-forms-and-maybe-emit-clear-values arg target representation))) (2 (let* ((arg1 (%car args)) (arg2 (%cadr args)) type1 type2 result-type) (when (and (integerp arg1) (integerp arg2)) (compile-constant (logior arg1 arg2) target representation) (return-from p2-logior t)) (when (integerp arg1) (setf arg1 (%cadr args) arg2 (%car args))) (setf type1 (derive-compiler-type arg1) type2 (derive-compiler-type arg2) result-type (derive-compiler-type form)) (cond ((and (fixnum-constant-value type1) (fixnum-constant-value type2)) (compile-constant (logior (fixnum-constant-value type1) (fixnum-constant-value type2)) target representation)) ((and (fixnum-type-p type1) (fixnum-type-p type2)) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit 'ior) (convert-representation :int representation) (emit-move-from-stack target representation)) ((and (eql (fixnum-constant-value type1) 0) (< *safety* 3)) (compile-forms-and-maybe-emit-clear-values arg1 nil nil arg2 target representation)) ((and (eql (fixnum-constant-value type2) 0) (< *safety* 3)) (let ((target-register (if (or (not (eq target 'stack)) (not (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks arg2)))) target (allocate-register representation)))) (compile-form arg1 target-register representation) (compile-form arg2 nil nil) (when (and (eq target 'stack) (not (eq target-register 'stack))) (emit-push-register target-register)) (maybe-emit-clear-values arg1 arg2))) ((or (eq representation :long) (and (java-long-type-p type1) (java-long-type-p type2))) (with-operand-accumulation ((compile-operand arg1 :long) (compile-operand arg2 :long) (maybe-emit-clear-values arg1 arg2))) (emit 'lor) (convert-representation :long representation) (emit-move-from-stack target representation)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "LOGIOR" '(:int) +lisp-object+) (fix-boxing representation result-type) (emit-move-from-stack target representation)) ((fixnum-type-p type1) ;; arg1 is of fixnum type, but arg2 is not (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) ;; swap args (emit 'swap) (emit-invokevirtual +lisp-object+ "LOGIOR" '(:int) +lisp-object+) (fix-boxing representation result-type) (emit-move-from-stack target representation)) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "LOGIOR" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation result-type) (emit-move-from-stack target representation))))) (t ;; (logior a b c d ...) => (logior a (logior b c d ...)) (let ((new-form `(logior ,(car args) (logior ,@(cdr args))))) (p2-logior new-form target representation)))))) (defknown p2-logxor (t t t) t) (defun p2-logxor (form target representation) (let* ((args (cdr form)) (len (length args))) (case len (0 (compile-constant 0 target representation)) (1 (let ((arg (%car args))) (compile-forms-and-maybe-emit-clear-values arg target representation))) (2 (let* ((arg1 (%car args)) (arg2 (%cadr args)) type1 type2 result-type) (when (and (integerp arg1) (integerp arg2)) (compile-constant (logxor arg1 arg2) target representation) (return-from p2-logxor)) (when (integerp arg1) (setf arg1 (%cadr args) arg2 (%car args))) (setf type1 (derive-compiler-type arg1) type2 (derive-compiler-type arg2) result-type (derive-compiler-type form)) (cond ((or (eq representation :int) (and (fixnum-type-p type1) (fixnum-type-p type2))) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit 'ixor) (convert-representation :int representation)) ((and (java-long-type-p type1) (java-long-type-p type2)) (with-operand-accumulation ((compile-operand arg1 :long) (compile-operand arg2 :long) (maybe-emit-clear-values arg1 arg2))) (emit 'lxor) (convert-representation :long representation)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "LOGXOR" '(:int) +lisp-object+) (fix-boxing representation result-type)) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "LOGXOR" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation result-type))) (emit-move-from-stack target representation))) (t ;; (logxor a b c d ...) => (logxor a (logxor b c d ...)) (let ((new-form `(logxor ,(car args) (logxor ,@(cdr args))))) (p2-logxor new-form target representation)))))) (defknown p2-lognot (t t t) t) (define-inlined-function p2-lognot (form target representation) ((check-arg-count form 1)) (cond ((and (fixnum-type-p (derive-compiler-type form))) (let ((arg (%cadr form))) (compile-forms-and-maybe-emit-clear-values arg 'stack :int) (emit 'iconst_m1) (emit 'ixor) (convert-representation :int representation) (emit-move-from-stack target representation))) (t (let ((arg (%cadr form))) (compile-forms-and-maybe-emit-clear-values arg 'stack nil)) (emit-invokevirtual +lisp-object+ "LOGNOT" nil +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)))) ;; %ldb size position integer => byte (defknown p2-%ldb (t t t) t) (define-inlined-function p2-%ldb (form target representation) ((check-arg-count form 3)) (let* ((args (cdr form)) (size-arg (%car args)) (position-arg (%cadr args)) (arg3 (%caddr args)) (size-type (derive-compiler-type size-arg)) (position-type (derive-compiler-type position-arg)) (size (fixnum-constant-value size-type)) (position (fixnum-constant-value position-type))) ;; FIXME Inline the case where all args are of fixnum type. ;; FIXME Add LispObject.ldb(), returning a Java int, for the case where we ;; need an unboxed fixnum result. (cond ((eql size 0) (compile-forms-and-maybe-emit-clear-values size-arg nil nil position-arg nil nil arg3 nil nil) (compile-constant 0 target representation)) ((and size position) (cond ((<= (+ position size) 31) (compile-forms-and-maybe-emit-clear-values size-arg nil nil position-arg nil nil arg3 'stack :int) (unless (zerop position) (emit-push-constant-int position) (emit 'ishr)) (emit-push-constant-int (1- (expt 2 size))) ; mask (emit 'iand) (convert-representation :int representation) (emit-move-from-stack target representation)) ((<= (+ position size) 63) (compile-forms-and-maybe-emit-clear-values size-arg nil nil position-arg nil nil arg3 'stack :long) (unless (zerop position) (emit-push-constant-int position) (emit 'lshr)) (cond ((<= size 31) (emit 'l2i) (emit-push-constant-int (1- (expt 2 size))) (emit 'iand) (convert-representation :int representation)) (t (emit-push-constant-long (1- (expt 2 size))) ; mask (emit 'land) (convert-representation :long representation))) (emit-move-from-stack target representation)) (t (compile-forms-and-maybe-emit-clear-values arg3 'stack nil) (emit-push-constant-int size) (emit-push-constant-int position) (emit-invokevirtual +lisp-object+ "LDB" '(:int :int) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)))) ((and (fixnum-type-p size-type) (fixnum-type-p position-type)) (with-operand-accumulation ((compile-operand size-arg :int) (compile-operand position-arg :int) (compile-operand arg3 nil) (maybe-emit-clear-values size-arg position-arg arg3))) (emit 'dup_x2) ;; use not supported by emit-dup: 3 values involved (emit 'pop) (emit-invokevirtual +lisp-object+ "LDB" '(:int :int) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (compile-function-call form target representation))))) (defknown p2-mod (t t t) t) (define-inlined-function p2-mod (form target representation) ((check-arg-count form 2)) (let* ((args (cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((and (eq representation :int) (fixnum-type-p type1) (fixnum-type-p type2)) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokestatic +lisp+ "mod" '(:int :int) :int) (emit-move-from-stack target representation)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "MOD" '(:int) +lisp-object+) (fix-boxing representation nil) ; FIXME use derived result type (emit-move-from-stack target representation)) (t (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ "MOD" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation nil) ; FIXME use derived result type (emit-move-from-stack target representation))))) (defknown p2-zerop (t t t) t) (define-inlined-function p2-zerop (form target representation) ((aver (or (null representation) (eq representation :boolean))) (check-arg-count form 1)) (let* ((arg (cadr form)) (type (derive-compiler-type arg))) (cond ((fixnum-type-p type) (compile-forms-and-maybe-emit-clear-values arg 'stack :int) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit 'ifne LABEL1) (ecase representation (:boolean (emit 'iconst_1)) ((nil) (emit-push-t))) (emit 'goto LABEL2) (label LABEL1) (ecase representation (:boolean (emit 'iconst_0)) ((nil) (emit-push-nil))) (label LABEL2) (emit-move-from-stack target representation))) ((java-long-type-p type) (compile-forms-and-maybe-emit-clear-values arg 'stack :long) (emit 'lconst_0) (emit 'lcmp) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit 'ifne LABEL1) (emit-push-true representation) (emit 'goto LABEL2) (label LABEL1) (emit-push-false representation) (label LABEL2) (emit-move-from-stack target representation))) (t (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-invoke-method "ZEROP" target representation))))) ;; find-class symbol &optional errorp environment => class (defknown p2-find-class (t t t) t) (defun p2-find-class (form target representation) (let* ((args (cdr form)) (arg-count (length args)) (arg1 (first args)) class) (when (and (<= 1 arg-count 2) ; no environment arg (consp arg1) (= (length arg1) 2) (eq (first arg1) 'QUOTE) (symbolp (second arg1)) (eq (symbol-package (second arg1)) (find-package "CL")) (setf class (find-class (second arg1) nil))) (compile-constant class target representation) (return-from p2-find-class)) (case arg-count (1 ;; errorp is true (compile-forms-and-maybe-emit-clear-values arg1 'stack nil) (emit-push-constant-int 1) ; errorp (emit-invokestatic +lisp-class+ "findClass" (list +lisp-object+ :boolean) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (2 (let ((arg2 (second args))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :boolean) (maybe-emit-clear-values arg1 arg2))) (emit-invokestatic +lisp-class+ "findClass" (list +lisp-object+ :boolean) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation))) (t (compile-function-call form target representation))))) ;; vector-push-extend new-element vector &optional extension => new-index (defun p2-vector-push-extend (form target representation) (let* ((args (cdr form)) (arg-count (length args)) (arg1 (first args)) (arg2 (second args))) (case arg-count (2 (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil))) (maybe-emit-clear-values arg1 arg2) (emit 'swap) (cond (target (emit-invokevirtual +lisp-object+ "VECTOR_PUSH_EXTEND" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (emit-invokevirtual +lisp-object+ "vectorPushExtend" (lisp-object-arg-types 1) nil)))) (t (compile-function-call form target representation))))) (defknown p2-std-slot-value (t t t) t) (define-inlined-function p2-std-slot-value (form target representation) ((check-arg-count form 2)) (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil))) (maybe-emit-clear-values arg1 arg2) (emit-invokevirtual +lisp-object+ "SLOT_VALUE" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation))) ;; set-std-slot-value instance slot-name new-value => new-value (defknown p2-set-std-slot-value (t t t) t) (define-inlined-function p2-set-std-slot-value (form target representation) ((check-arg-count form 3)) (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args)) (arg3 (third args)) (*register* *register*) (value-register (when target (allocate-register nil)))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil) (compile-operand arg3 nil))) (when value-register (emit 'dup) (astore value-register)) (maybe-emit-clear-values arg1 arg2 arg3) (emit-invokevirtual +lisp-object+ "setSlotValue" (lisp-object-arg-types 2) nil) (when value-register (aload value-register) (fix-boxing representation nil) (emit-move-from-stack target representation)))) (defknown p2-stream-element-type (t t t) t) (define-inlined-function p2-stream-element-type (form target representation) ((check-arg-count form 1)) (let ((arg (%cadr form))) (cond ((eq (derive-compiler-type arg) 'STREAM) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-checkcast +lisp-stream+) (emit-invokevirtual +lisp-stream+ "getElementType" nil +lisp-object+) (emit-move-from-stack target representation)) (t (compile-function-call form target representation))))) ;; write-8-bits byte stream => nil (defknown p2-write-8-bits (t t t) t) (define-inlined-function p2-write-8-bits (form target representation) ((check-arg-count form 2)) (let* ((arg1 (%cadr form)) (arg2 (%caddr form)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((and (compiler-subtypep type1 '(UNSIGNED-BYTE 8)) (eq type2 'STREAM)) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil +lisp-stream+))) (maybe-emit-clear-values arg1 arg2) (emit 'swap) (emit-invokevirtual +lisp-stream+ "_writeByte" '(:int) nil) (when target (emit-push-nil) (emit-move-from-stack target))) ((fixnum-type-p type1) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil))) (maybe-emit-clear-values arg1 arg2) (emit-invokestatic +lisp+ "writeByte" (list :int +lisp-object+) nil) (when target (emit-push-nil) (emit-move-from-stack target))) (t (compile-function-call form target representation))))) (defun p2-read-line (form target representation) (let* ((args (cdr form)) (len (length args))) (case len (1 (let* ((arg1 (%car args)) (type1 (derive-compiler-type arg1))) (cond ((compiler-subtypep type1 'stream) (compile-forms-and-maybe-emit-clear-values arg1 'stack nil) (emit-checkcast +lisp-stream+) (emit-push-constant-int 1) (emit-push-nil) (emit-invokevirtual +lisp-stream+ "readLine" (list :boolean +lisp-object+) +lisp-object+) (emit-move-from-stack target)) (t (compile-function-call form target representation))))) (2 (let* ((arg1 (%car args)) (type1 (derive-compiler-type arg1)) (arg2 (%cadr args))) (cond ((and (compiler-subtypep type1 'stream) (null arg2)) (compile-forms-and-maybe-emit-clear-values arg1 'stack nil) (emit-checkcast +lisp-stream+) (emit-push-constant-int 0) (emit-push-nil) (emit-invokevirtual +lisp-stream+ "readLine" (list :boolean +lisp-object+) +lisp-object+) (emit-move-from-stack target) ) (t (compile-function-call form target representation))))) (t (compile-function-call form target representation))))) (defmacro define-derive-type-handler (op lambda-list &body body) (let ((name (intern (concatenate 'string "DERIVE-TYPE-" (symbol-name op))))) `(progn (defknown ,name (t) t) (defun ,name ,lambda-list ,@body) (setf (get ',op 'derive-type-handler) ',name)))) (define-derive-type-handler aref (form) (let* ((args (cdr form)) (array-arg (car args)) (array-type (normalize-type (derive-type array-arg))) (result-type t)) (cond ((and (consp array-type) (memq (%car array-type) '(ARRAY SIMPLE-ARRAY VECTOR))) (let ((element-type (second array-type))) (unless (eq element-type '*) (setf result-type element-type)))) ((and (consp array-type) (memq (%car array-type) '(STRING SIMPLE-STRING))) (setf result-type 'CHARACTER))) result-type)) (define-derive-type-handler fixnump (form) (if (fixnum-type-p (derive-compiler-type (cadr form))) +true-type+ 'BOOLEAN)) (define-derive-type-handler setq (form) (if (= (length form) 3) (derive-compiler-type (third form)) t)) (defknown derive-type-logior/logxor (t) t) (defun derive-type-logior/logxor (form) (let ((op (car form)) (args (cdr form)) (result-type +integer-type+)) (case (length args) (0 (setf result-type (make-integer-type '(INTEGER 0 0)))) (1 (setf result-type (derive-compiler-type (car args)))) (2 (let ((type1 (derive-compiler-type (%car args))) (type2 (derive-compiler-type (%cadr args)))) (cond ((and (compiler-subtypep type1 'unsigned-byte) (compiler-subtypep type2 'unsigned-byte)) (let ((high1 (integer-type-high type1)) (high2 (integer-type-high type2))) (cond ((and high1 high2) (let ((length (integer-length (max high1 high2)))) (setf result-type (make-compiler-type (list 'INTEGER 0 (1- (expt 2 length))))))) (t (setf result-type (make-compiler-type 'unsigned-byte)))))) ((and (fixnum-type-p type1) (fixnum-type-p type2)) (setf result-type (make-compiler-type 'fixnum)))))) (t (setf result-type (derive-type-logior/logxor `(,op ,(car args) (,op ,@(cdr args))))))) result-type)) (defknown derive-type-logand (t) t) (defun derive-type-logand (form) (let ((args (cdr form))) (case (length args) (0 (make-integer-type '(INTEGER -1 -1))) (1 (let ((type (derive-compiler-type (%car args)))) (if (integer-type-p type) type (make-integer-type 'INTEGER)))) (2 (dformat t "derive-type-logand 2-arg case~%") (let* ((type1 (derive-compiler-type (%car args))) (type2 (derive-compiler-type (%cadr args))) low1 high1 low2 high2 result-low result-high result-type) (when (integer-type-p type1) (setf low1 (integer-type-low type1) high1 (integer-type-high type1))) (when (integer-type-p type2) (setf low2 (integer-type-low type2) high2 (integer-type-high type2))) (cond ((and low1 low2 (>= low1 0) (>= low2 0)) ;; Both arguments are non-negative. (dformat t "both args are non-negative~%") (setf result-low 0) (setf result-high (if (and high1 high2) (min high1 high2) (or high1 high2)))) ((and low1 (>= low1 0)) ;; arg1 is non-negative (dformat t "arg1 is non-negative~%") (setf result-low 0) (setf result-high high1)) ((and low2 (>= low2 0)) ;; arg2 is non-negative (dformat t "arg2 is non-negative~%") (setf result-low 0) (setf result-high high2))) (dformat t "result-low = ~S~%" result-low) (dformat t "result-high = ~S~%" result-high) (setf result-type (make-integer-type (list 'INTEGER result-low result-high))) (dformat t "result-type = ~S~%" result-type) result-type)) (t (make-integer-type 'INTEGER))))) (declaim (ftype (function (t) t) derive-type-lognot)) (defun derive-type-lognot (form) (let (arg-type) (if (and (= (length form) 2) (fixnum-type-p (setf arg-type (derive-compiler-type (%cadr form))))) (let* ((arg-low (integer-type-low arg-type)) (arg-high (integer-type-high arg-type)) (result-low (if arg-high (lognot arg-high) nil)) (result-high (if arg-low (lognot arg-low) nil))) (make-integer-type (list 'INTEGER result-low result-high))) +integer-type+))) ;; mod number divisor (declaim (ftype (function (t) t) derive-type-mod)) (defun derive-type-mod (form) (if (= (length form) 3) (let* ((arg1 (%cadr form)) (arg2 (%caddr form)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((and (integer-type-p type1) (fixnum-type-p type2)) 'FIXNUM) (t t))) t)) (defknown derive-type-coerce (t) t) (defun derive-type-coerce (form) (if (= (length form) 3) (let ((type-form (%caddr form))) (if (and (consp type-form) (eq (%car type-form) 'QUOTE) (= (length type-form) 2)) (%cadr type-form) t)) t)) (defknown derive-type-copy-seq (t) t) (defun derive-type-copy-seq (form) (if (= (length form) 2) (let ((type (derive-compiler-type (second form)))) (case type ((STRING SIMPLE-STRING) (make-compiler-type type)) (t t))) t)) (defknown derive-type-integer-length (t) t) (defun derive-type-integer-length (form) (when (= (length form) 2) (let ((type (make-integer-type (derive-type (%cadr form))))) (when type (let ((low (integer-type-low type)) (high (integer-type-high type))) (when (and (integerp low) (integerp high)) (return-from derive-type-integer-length (list 'INTEGER 0 (max (integer-length low) (integer-length high))))))))) (list 'INTEGER 0 '*)) (defknown derive-type-%ldb (t) t) (defun derive-type-%ldb (form) (when (= (length form) 4) (let* ((args (cdr form)) (size-arg (first args))) (when (fixnump size-arg) (return-from derive-type-%ldb (list 'INTEGER 0 (1- (expt 2 size-arg))))))) (list 'INTEGER 0 '*)) (defmacro define-int-bounds-derivation (name (low1 high1 low2 high2) &body body) "Associates an integer-bounds calculation function with a numeric operator `name', assuming 2 integer arguments." `(setf (get ',name 'int-bounds) #'(lambda (,low1 ,high1 ,low2 ,high2) (declare (ignorable ,low1 ,high1 ,low2 ,high2)) ,@body))) (defun derive-integer-type (op type1 type2) "Derives the composed integer type of operation `op' given integer types `type1' and `type2'." (let ((low1 (integer-type-low type1)) (high1 (integer-type-high type1)) (low2 (integer-type-low type2)) (high2 (integer-type-high type2)) (op-fn (get op 'int-bounds))) (assert op-fn) (multiple-value-bind (low high non-int-p) (funcall op-fn low1 high1 low2 high2) (if non-int-p non-int-p (%make-integer-type low high))))) (defvar numeric-op-type-derivation `(((+ - *) (integer integer ,#'derive-integer-type) (integer single-float single-float) (integer double-float double-float) (single-float integer single-float) (single-float double-float double-float) (double-float integer double-float) (double-float single-float double-float)) ((/) (integer single-float single-float) (integer double-float double-float) (single-float integer single-float) (single-float double-float double-float) (double-float integer double-float) (double-float single-float double-float)) ((ash) (integer integer ,#'derive-integer-type)) ((min max) (integer integer ,#'derive-integer-type) (integer single-float single-float) (integer double-float double-float) (single-float double-float double-float) (double-float single-float double-float))) "Table used to derive the return type of a numeric operation, based on the types of the arguments.") (defun derive-type-numeric-op (op &rest types) "Returns the result type of the numeric operation `op' and the types of the operation arguments given in `types'." (let ((types-table (cdr (assoc op numeric-op-type-derivation :test #'member)))) (assert types-table) (flet ((match (type1 type2) (do* ((remaining-types types-table (cdr remaining-types))) ((endp remaining-types) ;; when we don't find a matching type, return T T) (destructuring-bind (t1 t2 result-type) (car remaining-types) (when (and (or (subtypep type1 t1) (compiler-subtypep type1 t1)) (or (subtypep type2 t2) (compiler-subtypep type2 t2))) (return-from match (if (functionp result-type) (funcall result-type op type1 type2) result-type))))))) (let ((type1 (car types)) (type2 (cadr types))) (when (and (eq type1 type2) (memq type1 '(SINGLE-FLOAT DOUBLE-FLOAT))) (return-from derive-type-numeric-op type1)) (match type1 type2))))) (defvar zero-integer-type (%make-integer-type 0 0) "Integer type representing the 0 (zero) value for use with derive-type-minus and derive-type-plus.") (define-int-bounds-derivation - (low1 high1 low2 high2) (values (when (and low1 high2) ;; low1 or high2 undefined: no lower bound (if low2 (min (- low1 low2) (- low1 high2)) ;; low2 undefined: no effect on lower bound (- low1 high2))) (when (and high1 low2) ;; high1 or low2 undefined: no upper bound (if high2 (max (- high1 low2) (- high1 high2)) ;; high2 undefined: no effect on upper bound (- high1 low2))))) (defun derive-compiler-types (args op) (flet ((combine (x y) (derive-type-numeric-op op x y))) (reduce #'combine (cdr args) :key #'derive-compiler-type :initial-value (derive-compiler-type (car args))))) (defknown derive-type-minus (t) t) (defun derive-type-minus (form) (let ((op (car form)) (args (cdr form))) (case (length args) (1 (derive-type-numeric-op (car form) zero-integer-type (derive-compiler-type (%car args)))) (2 (derive-compiler-types args op))))) (define-int-bounds-derivation + (low1 high1 low2 high2) (values (and low1 low2 (+ low1 low2)) (and high1 high2 (+ high1 high2)))) (defknown derive-type-plus (t) t) (defun derive-type-plus (form) (let ((op (car form)) (args (cdr form))) (if (null args) zero-integer-type (derive-compiler-types args op)))) (define-int-bounds-derivation * (low1 high1 low2 high2) (cond ((or (null low1) (null low2)) (values nil nil)) ((or (null high1) (null high2)) (values (if (or (minusp low1) (minusp low2)) (- (* (abs low1) (abs low2))) (* low1 low2)) nil)) ((or (minusp low1) (minusp low2)) (let ((max (* (max (abs low1) (abs high1)) (max (abs low2) (abs high2))))) (values (- max) max))) (t (values (* low1 low2) (* high1 high2))))) (defvar one-integer-type (%make-integer-type 1 1) "Integer type representing the value 1 (one) for use with derive-type-times.") (defun derive-type-times (form) (let ((op (car form)) (args (cdr form))) (if (null args) one-integer-type (derive-compiler-types args op)))) (define-int-bounds-derivation max (low1 high1 low2 high2) (values (or (when (and low1 low2) (max low1 low2)) low1 low2) ; if either maximum is unbound, their maximum is unbound (when (and high1 high2) (max high1 high2)))) (declaim (ftype (function (t) t) derive-type-max)) (defun derive-type-max (form) (let ((op (car form)) (args (cdr form))) (derive-compiler-types args op))) (define-int-bounds-derivation min (low1 high1 low2 high2) (values (when (and low1 low2) (min low1 low2)) ; if either minimum is unbound, their minimum is unbound (or (when (and high1 high2) (min high1 high2)) high1 high2))) (defknown derive-type-min (t) t) (defun derive-type-min (form) (let ((op (car form)) (args (cdr form))) (derive-compiler-types args op))) ;; read-char &optional input-stream eof-error-p eof-value recursive-p => char (declaim (ftype (function (t) t) derive-type-read-char)) (defun derive-type-read-char (form) (if (< (length form) 3) ; no EOF-ERROR-P arg 'CHARACTER t)) (define-int-bounds-derivation ash (low1 high1 low2 high2) (when (and low1 high1 low2 high2) (cond ((and (>= low1 0) (>= high1 0) (>= low2 0) (>= high2 0)) ;; Everything is non-negative. (values (ash low1 low2) (unless (<= 64 high2) (ash high1 high2)))) ((and (>= low1 0) (>= high1 0) (<= low2 0) (<= high2 0)) ;; Negative (or zero) second argument. (values (ash low1 low2) (ash high1 high2)))))) ;; ash integer count => shifted-integer (defknown derive-type-ash (t) t) (defun derive-type-ash (form) (derive-type-numeric-op (car form) (derive-compiler-type (cadr form)) (derive-compiler-type (caddr form)))) (defknown derive-type (t) t) (defun derive-type (form) (cond ((consp form) (let* ((op (%car form)) (handler (and (symbolp op) (get op 'derive-type-handler)))) (if handler (funcall handler form) (case op (ASH (derive-type-ash form)) ((CHAR SCHAR) 'CHARACTER) (COERCE (derive-type-coerce form)) (COPY-SEQ (derive-type-copy-seq form)) (INTEGER-LENGTH (derive-type-integer-length form)) (%LDB (derive-type-%ldb form)) (LENGTH '(INTEGER 0 #.(1- most-positive-fixnum))) (LOGAND (derive-type-logand form)) (LOGNOT (derive-type-lognot form)) ((LOGIOR LOGXOR) (derive-type-logior/logxor form)) (MOD (derive-type-mod form)) (- (derive-type-minus form)) (1- (derive-type-minus (list '- (cadr form) 1))) (+ (derive-type-plus form)) (1+ (derive-type-plus (list '+ (cadr form) 1))) (* (derive-type-times form)) (MAX (derive-type-max form)) (MIN (derive-type-min form)) (READ-CHAR (derive-type-read-char form)) ((THE TRULY-THE) (second form)) (t (let ((type (or (function-result-type op) (ftype-result-type (proclaimed-ftype op))))) (if (eq type '*) t type))))))) ((null form) 'NULL) ((integerp form) (list 'INTEGER form form)) ((typep form 'single-float) 'SINGLE-FLOAT) ((typep form 'double-float) 'DOUBLE-FLOAT) ((characterp form) 'CHARACTER) ((stringp form) 'STRING) ((arrayp form) (type-of form)) ((variable-p form) (cond ((neq (variable-declared-type form) :none) (variable-declared-type form)) ((neq (variable-derived-type form) :none) (variable-derived-type form)) (t t))) ((var-ref-p form) (cond ((var-ref-constant-p form) (derive-type (var-ref-constant-value form))) (t (let ((variable (var-ref-variable form))) (cond ((variable-special-p variable) (or (proclaimed-type (variable-name variable)) t)) ((neq (variable-declared-type variable) :none) (variable-declared-type variable)) ((neq (variable-derived-type variable) :none) (variable-derived-type variable)) ((= 0 (variable-writes variable)) (derive-type (variable-initform variable))) (t t)))))) ((symbolp form) (cond ((keywordp form) 'SYMBOL) ((eq form t) t) ((and (special-variable-p form) (constantp form)) (derive-type (symbol-value form))) (t (let ((variable (find-visible-variable form))) (if variable (derive-type variable) t))))) ((node-p form) (let ((result t)) ;;; ### FIXME #| the statements below used to work, maybe ... We need more thought here. (cond ((and (block-node-p form) (equal (block-name form) '(LET))) ;; (format t "derive-type LET/LET* node case~%") (let* ((forms (cddr (node-form form))) (last-form (car (last forms))) (derived-type (derive-compiler-type last-form))) ;; (unless (eq derived-type t) ;; (let ((*print-structure* nil)) ;; (format t "last-form = ~S~%" last-form)) ;; (format t "derived-type = ~S~%" derived-type) ;; ) (setf result derived-type))) ((and (block-node-p form) (symbolp (block-name form))) (unless (block-return-p form) (let* ((forms (cddr (block-form form))) (last-form (car (last forms))) (derived-type (derive-compiler-type last-form))) ;; (unless (eq derived-type t) ;; (let ((*print-structure* nil)) ;; (format t "last-form = ~S~%" last-form)) ;; (format t "derived-type = ~S~%" derived-type) ;; ) (setf result derived-type))))) |# result)) (t t))) (defun derive-compiler-type (form) (make-compiler-type (derive-type form))) ;; delete item sequence &key from-end test test-not start end count key (defknown p2-delete (t t t) t) (defun p2-delete (form target representation) (unless (notinline-p 'delete) (when (= (length form) 3) ;; No keyword arguments. (let* ((args (cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) (type1 (derive-type arg1)) (type2 (derive-type arg2)) (test (if (memq type1 '(SYMBOL NULL)) 'eq 'eql))) (cond ((subtypep type2 'VECTOR) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil +lisp-abstract-vector+))) (maybe-emit-clear-values arg1 arg2) (emit 'swap) (emit-invokevirtual +lisp-abstract-vector+ (if (eq test 'eq) "deleteEq" "deleteEql") (lisp-object-arg-types 1) +lisp-object+) (emit-move-from-stack target) (return-from p2-delete t)) (t (setf (car form) (if (eq test 'eq) 'delete-eq 'delete-eql))))))) (compile-function-call form target representation)) (define-inlined-function p2-length (form target representation) ((check-arg-count form 1)) (let ((arg (cadr form))) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (ecase representation (:int (emit-invokevirtual +lisp-object+ "length" nil :int)) ((:long :float :double) (emit-invokevirtual +lisp-object+ "length" nil :int) (convert-representation :int representation)) (:boolean ;; FIXME We could optimize this all away in unsafe calls. (emit-invokevirtual +lisp-object+ "length" nil :int) (emit 'pop) (emit 'iconst_1)) (:char (sys::%format t "p2-length: :char case~%") (aver nil)) ((nil) (emit-invokevirtual +lisp-object+ "LENGTH" nil +lisp-object+))) (emit-move-from-stack target representation))) (defun cons-for-list/list* (form target representation &optional list-star-p) (let* ((args (cdr form)) (length (length args)) (cons-heads (if list-star-p (butlast args 1) args))) (cond ((and (not (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks args))) (>= 4 length 1)) (dolist (cons-head cons-heads) (emit-new +lisp-cons+) (emit 'dup) (compile-form cons-head 'stack nil)) (if list-star-p (compile-form (first (last args)) 'stack nil) (progn (emit-invokespecial-init +lisp-cons+ (lisp-object-arg-types 1)) (pop cons-heads))) ; we've handled one of the args, so remove it (dolist (cons-head cons-heads) (declare (ignore cons-head)) (emit-invokespecial-init +lisp-cons+ (lisp-object-arg-types 2))) (if list-star-p (progn (apply #'maybe-emit-clear-values args) (emit-move-from-stack target representation)) (progn (unless (every 'single-valued-p args) (emit-clear-values)) (emit-move-from-stack target)))) (t (compile-function-call form target representation))))) (defun p2-list (form target representation) (cons-for-list/list* form target representation)) (defun p2-list* (form target representation) (cons-for-list/list* form target representation t)) (define-inlined-function compile-nth (form target representation) ((check-arg-count form 2)) (let* ((index-form (second form)) (list-form (third form)) (index-type (derive-compiler-type index-form))) (unless (fixnum-type-p index-type) (compile-function-call form target representation) (return-from compile-nth)) (with-operand-accumulation ((compile-operand index-form :int) (compile-operand list-form nil) (maybe-emit-clear-values index-form list-form)) (emit 'swap) (emit-invokevirtual +lisp-object+ "NTH" '(:int) +lisp-object+)) (fix-boxing representation nil) ; FIXME use derived result type (emit-move-from-stack target representation))) (defun p2-times (form target representation) (case (length form) (1 (compile-constant 1 target representation)) (2 (compile-form (cadr form) target representation)) (3 (let* ((args (cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) result-type result-rep value) (when (fixnump arg1) (rotatef arg1 arg2)) (setf result-type (derive-compiler-type form) result-rep (type-representation result-type)) (cond ((and (numberp arg1) (numberp arg2)) (dformat t "p2-times case 1~%") (compile-constant (* arg1 arg2) target representation)) ((setf value (fixnum-constant-value result-type)) (dformat t "p2-times case 1a~%") (compile-constant value target representation)) (result-rep (with-operand-accumulation ((compile-operand arg1 result-rep) (compile-operand arg2 result-rep) (maybe-emit-clear-values arg1 arg2)) (emit (case result-rep (:int 'imul) (:long 'lmul) (:float 'fmul) (:double 'dmul) (t (sys::format t "p2-times: unsupported rep case"))))) (convert-representation result-rep representation) (emit-move-from-stack target representation)) ((fixnump arg2) (compile-forms-and-maybe-emit-clear-values arg1 'stack nil) (emit-push-int arg2) (emit-invokevirtual +lisp-object+ "multiplyBy" '(:int) +lisp-object+) (fix-boxing representation result-type) (emit-move-from-stack target representation)) (t (dformat t "p2-times case 4~%") (compile-binary-operation "multiplyBy" args target representation))))) (t (dformat t "p2-times case 5~%") (p2-times `(,(car form) (,(car form) ,(second form) ,(third form)) ,@(nthcdr 3 form)) target representation)))) (defknown p2-min/max (t t t) t) (defun p2-min/max (form target representation) (case (length form) (1 (error 'program-error "Wrong number of arguments for ~A." (car form))) (2 (compile-form (cadr form) target representation)) (3 (let* ((op (%car form)) (args (%cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) (*register* *register*)) (when (null target) ;; compile for effect (compile-forms-and-maybe-emit-clear-values arg1 nil nil arg2 nil nil) (return-from p2-min/max)) (when (notinline-p op) (compile-function-call form target representation) (return-from p2-min/max)) (let ((type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((and (java-long-type-p type1) (java-long-type-p type2)) (let* ((common-rep (if (and (fixnum-type-p type1) (fixnum-type-p type2)) :int :long)) (LABEL1 (gensym)) (LABEL2 (gensym)) (arg1-register (allocate-register common-rep)) (arg2-register (allocate-register common-rep))) (compile-form arg1 arg1-register common-rep) (compile-form arg2 'stack common-rep) (emit-dup common-rep) (emit-move-from-stack arg2-register common-rep) (emit-push-register arg1-register common-rep) ;; note: we've now reversed the arguments on the stack! (emit-numeric-comparison (if (eq op 'max) '<= '>=) common-rep LABEL1) (emit-push-register arg1-register common-rep) (emit 'goto LABEL2) (label LABEL1) (emit-push-register arg2-register common-rep) (label LABEL2) (convert-representation common-rep representation) (emit-move-from-stack target representation))) (t (let* ((arg1-register (allocate-register nil)) (arg2-register (allocate-register nil))) (compile-form arg1 arg1-register nil) (compile-form arg2 'stack nil) (emit-dup nil) (astore arg2-register) (emit-push-register arg1-register nil) (emit-invokevirtual +lisp-object+ (if (eq op 'max) "isLessThanOrEqualTo" "isGreaterThanOrEqualTo") (lisp-object-arg-types 1) :boolean) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit 'ifeq LABEL1) (emit-push-register arg1-register nil) (emit 'goto LABEL2) (label LABEL1) (emit-push-register arg2-register nil) (label LABEL2)) (fix-boxing representation nil) (emit-move-from-stack target representation))))))) (t (p2-min/max `(,(car form) (,(car form) ,(second form) ,(third form)) ,@(nthcdr 3 form)) target representation)))) (defun p2-plus (form target representation) (case (length form) (1 (compile-constant 0 target representation)) (2 (compile-form (cadr form) target representation)) (3 (let* ((args (%cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2)) (result-type (derive-compiler-type form)) (result-rep (type-representation result-type))) (cond ((and (numberp arg1) (numberp arg2)) (compile-constant (+ arg1 arg2) target representation)) ((and (numberp arg1) (eql arg1 0)) (compile-forms-and-maybe-emit-clear-values arg1 nil nil arg2 'stack representation) (emit-move-from-stack target representation)) ((and (numberp arg2) (eql arg2 0)) (compile-forms-and-maybe-emit-clear-values arg1 'stack representation arg2 nil nil) (emit-move-from-stack target representation)) (result-rep (with-operand-accumulation ((compile-operand arg1 result-rep) (compile-operand arg2 result-rep) (maybe-emit-clear-values arg1 arg2)) (emit (case result-rep (:int 'iadd) (:long 'ladd) (:float 'fadd) (:double 'dadd) (t (sys::format t "p2-plus: Unexpected result-rep ~S for form ~S." result-rep form) (assert nil))))) (convert-representation result-rep representation) (emit-move-from-stack target representation)) ((eql arg2 1) (compile-forms-and-maybe-emit-clear-values arg1 'stack nil) (emit-invoke-method "incr" target representation)) ((eql arg1 1) (compile-forms-and-maybe-emit-clear-values arg2 'stack nil) (emit-invoke-method "incr" target representation)) ((or (fixnum-type-p type1) (fixnum-type-p type2)) (with-operand-accumulation ((compile-operand arg1 (when (fixnum-type-p type1) :int)) (compile-operand arg2 (when (null (fixnum-type-p type1)) :int)) (maybe-emit-clear-values arg1 arg2)) (when (fixnum-type-p type1) (emit 'swap)) (emit-invokevirtual +lisp-object+ "add" '(:int) +lisp-object+)) (fix-boxing representation result-type) (emit-move-from-stack target representation)) (t (compile-binary-operation "add" args target representation))))) (t ;; (+ a b c) => (+ (+ a b) c) (let ((new-form `(+ (+ ,(second form) ,(third form)) ,@(nthcdr 3 form)))) (p2-plus new-form target representation))))) (defun p2-minus (form target representation) (case (length form) (1 ;; generates "Insufficient arguments" error (compile-function-call form target representation)) (2 (let* ((arg (%cadr form)) (type (derive-compiler-type form)) (type-rep (type-representation type))) (cond ((numberp arg) (compile-constant (- arg) 'stack representation) (emit-move-from-stack target representation)) (type-rep (compile-form arg 'stack type-rep) (emit (case type-rep (:int 'ineg) (:long 'lneg) (:float 'fneg) (:double 'dneg) (t (sys::format t "p2-minus: unsupported rep (~S) for '~S'~%" type-rep form) (assert nil)))) (convert-representation type-rep representation) (emit-move-from-stack target representation)) (t (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-invokevirtual +lisp-object+ "negate" nil +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation))))) (3 (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args)) (type2 (derive-compiler-type arg2)) (result-type (derive-compiler-type form)) (result-rep (type-representation result-type))) (cond ((and (numberp arg1) (numberp arg2)) (compile-constant (- arg1 arg2) target representation)) (result-rep (with-operand-accumulation ((compile-operand arg1 result-rep) (compile-operand arg2 result-rep) (maybe-emit-clear-values arg1 arg2)) (emit (case result-rep (:int 'isub) (:long 'lsub) (:float 'fsub) (:double 'dsub) (t (sys::%format t "p2-minus sub-instruction (rep: ~S); form: ~S~%" result-rep form) (assert nil))))) (convert-representation result-rep representation) (emit-move-from-stack target representation)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2)) (emit-invokevirtual +lisp-object+ "subtract" '(:int) +lisp-object+)) (fix-boxing representation result-type) (emit-move-from-stack target representation)) (t (compile-binary-operation "subtract" args target representation))))) (t (let ((new-form `(- (- ,(second form) ,(third form)) ,@(nthcdr 3 form)))) (p2-minus new-form target representation))))) ;; char/schar string index => character (defknown p2-char/schar (t t t) t) (define-inlined-function p2-char/schar (form target representation) ((check-arg-count form 2)) (let* ((op (%car form)) (args (%cdr form)) (arg1 (%car args)) (arg2 (%cadr args)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2))) (cond ((or (and (eq representation :char) (zerop *safety*)) (and (eq representation :char) (or (eq op 'CHAR) (< *safety* 3)) (compiler-subtypep type1 'STRING) (fixnum-type-p type2))) (with-operand-accumulation ((compile-operand arg1 nil +lisp-abstract-string+) (compile-operand arg2 :int))) (maybe-emit-clear-values arg1 arg2) (emit-invokevirtual +lisp-abstract-string+ "charAt" '(:int) :char) (emit-move-from-stack target representation)) ((fixnum-type-p type2) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2))) (emit-invokevirtual +lisp-object+ (symbol-name op) ;; "CHAR" or "SCHAR" '(:int) +lisp-object+) (when (eq representation :char) (emit-unbox-character)) (emit-move-from-stack target representation)) (t (compile-function-call form target representation))))) ;; set-char/schar string index character => character (defknown p2-set-char/schar (t t t) t) (define-inlined-function p2-set-char/schar (form target representation) ((check-arg-count form 3)) (let* ((op (%car form)) (args (%cdr form)) (arg1 (first args)) (arg2 (second args)) (arg3 (third args)) (type1 (derive-compiler-type arg1)) (type2 (derive-compiler-type arg2)) (type3 (derive-compiler-type arg3))) (cond ((and (< *safety* 3) (or (null representation) (eq representation :char)) (compiler-subtypep type1 'STRING) (fixnum-type-p type2) (compiler-subtypep type3 'CHARACTER)) (let* ((*register* *register*) (value-register (when target (allocate-register nil))) (class (if (eq op 'SCHAR) +lisp-simple-string+ +lisp-abstract-string+))) (with-operand-accumulation ((compile-operand arg1 nil class) (compile-operand arg2 :int) (accumulate-operand (:char :unsafe-p (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks arg3))) (compile-form arg3 'stack :char) (when target (emit 'dup) (emit-move-from-stack value-register :char))))) (maybe-emit-clear-values arg1 arg2 arg3) (emit-invokevirtual class "setCharAt" '(:int :char) nil) (when target (emit 'iload value-register) (convert-representation :char representation) (emit-move-from-stack target representation)))) (t (compile-function-call form target representation))))) (defun p2-svref (form target representation) (cond ((and (check-arg-count form 2) (neq representation :char)) ; FIXME (let ((arg1 (%cadr form)) (arg2 (%caddr form))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 :int))) (maybe-emit-clear-values arg1 arg2) (emit-invokevirtual +lisp-object+ "SVREF" '(:int) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation))) (t (compile-function-call form target representation)))) (defun p2-svset (form target representation) (cond ((check-arg-count form 3) (let* ((arg1 (%cadr form)) (arg2 (%caddr form)) (arg3 (fourth form)) (*register* *register*) (value-register (when target (allocate-register nil)))) (with-operand-accumulation ((compile-operand arg1 nil) ;; vector (compile-operand arg2 :int) ;; intex (compile-operand arg3 nil) ;; new value )) (when value-register (emit 'dup) (emit-move-from-stack value-register nil)) (maybe-emit-clear-values arg1 arg2 arg3) (emit-invokevirtual +lisp-object+ "svset" (list :int +lisp-object+) nil) (when value-register (aload value-register) (emit-move-from-stack target nil)))) (t (compile-function-call form target representation)))) (defun p2-truncate (form target representation) (let ((args (cdr form)) arg1 arg2) (case (length args) (1 (setf arg1 (%car args) arg2 1)) (2 (setf arg1 (%car args) arg2 (%cadr args))) (t (compiler-warn "Wrong number of arguments for ~A (expected 1 or 2, but received ~D)." 'truncate (length args)) (compile-function-call form target representation) (return-from p2-truncate))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg2 nil))) (maybe-emit-clear-values arg1 arg2) (emit-invokevirtual +lisp-object+ "truncate" (lisp-object-arg-types 1) +lisp-object+) (fix-boxing representation nil) ; FIXME use derived result type (emit-move-from-stack target representation))) (defun p2-elt (form target representation) (cond ((and (check-arg-count form 2) (fixnum-type-p (derive-compiler-type (third form))) (neq representation :char)) ; FIXME (with-operand-accumulation ((compile-operand (second form) nil) (compile-operand (third form) :int) (maybe-emit-clear-values (second form) (third form)))) (emit-invokevirtual +lisp-object+ "elt" '(:int) +lisp-object+) (fix-boxing representation nil) ; FIXME use derived result type (emit-move-from-stack target representation)) (t (compile-function-call form target representation)))) (defun p2-aref (form target representation) ;; We only optimize the 2-arg case. (case (length form) (3 (let* ((arg1 (%cadr form)) (arg2 (%caddr form)) (type1 (derive-compiler-type arg1))) (with-operand-accumulation ((compile-operand arg1 nil (when (compiler-subtypep type1 'string) +lisp-abstract-string+)) (compile-operand arg2 :int) (maybe-emit-clear-values arg1 arg2)) (ecase representation (:int (emit-invokevirtual +lisp-object+ "aref" '(:int) :int)) (:long (emit-invokevirtual +lisp-object+ "aref_long" '(:int) :long)) (:char (cond ((compiler-subtypep type1 'string) (emit-invokevirtual +lisp-abstract-string+ "charAt" '(:int) :char)) (t (emit-invokevirtual +lisp-object+ "AREF" '(:int) +lisp-object+) (emit-unbox-character)))) ((nil :float :double :boolean) ;;###FIXME for float and double, we probably want ;; separate java methods to retrieve the values. (emit-invokevirtual +lisp-object+ "AREF" '(:int) +lisp-object+) (convert-representation nil representation)))) (emit-move-from-stack target representation))) (t (compile-function-call form target representation)))) (defun p2-aset (form target representation) ;; We only optimize the 3-arg case. (cond ((= (length form) 4) (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args)) (arg3 (third args)) (type3 (derive-compiler-type arg3)) (*register* *register*) (value-register (unless (null target) (allocate-register nil)))) (with-operand-accumulation ( ;; array (compile-operand arg1 nil) ;; index (compile-operand arg2 :int) ;; value (accumulate-operand ((when (fixnum-type-p type3) :int) :unsafe-p (some-nested-block #'node-opstack-unsafe-p (find-enclosed-blocks arg3))) (cond ((fixnum-type-p type3) (compile-form arg3 'stack :int) (when value-register (emit 'dup) (emit-move-from-stack value-register :int))) (t (compile-form arg3 'stack nil) (when value-register (emit 'dup) (emit-move-from-stack value-register nil))))))) (maybe-emit-clear-values arg1 arg2 arg3) (cond ((fixnum-type-p type3) (emit-invokevirtual +lisp-object+ "aset" '(:int :int) nil)) (t (emit-invokevirtual +lisp-object+ "aset" (list :int +lisp-object+) nil))) (when value-register (cond ((fixnum-type-p type3) (emit 'iload value-register) (convert-representation :int representation)) (t (aload value-register) (fix-boxing representation type3))) (emit-move-from-stack target representation)))) (t (compile-function-call form target representation)))) (defknown p2-structure-ref (t t t) t) (define-inlined-function p2-structure-ref (form target representation) ((check-arg-count form 2)) (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args))) (cond ((and (fixnump arg2) (null representation)) (compile-forms-and-maybe-emit-clear-values arg1 'stack nil) (case arg2 (0 (emit-invokevirtual +lisp-object+ "getSlotValue_0" nil +lisp-object+)) (1 (emit-invokevirtual +lisp-object+ "getSlotValue_1" nil +lisp-object+)) (2 (emit-invokevirtual +lisp-object+ "getSlotValue_2" nil +lisp-object+)) (3 (emit-invokevirtual +lisp-object+ "getSlotValue_3" nil +lisp-object+)) (t (emit-push-constant-int arg2) (emit-invokevirtual +lisp-object+ "getSlotValue" '(:int) +lisp-object+))) (emit-move-from-stack target representation)) ((fixnump arg2) (compile-forms-and-maybe-emit-clear-values arg1 'stack nil) (emit-push-constant-int arg2) (ecase representation (:int (emit-invokevirtual +lisp-object+ "getFixnumSlotValue" '(:int) :int)) ((nil :char :long :float :double) (emit-invokevirtual +lisp-object+ "getSlotValue" '(:int) +lisp-object+) ;; (convert-representation NIL NIL) is a no-op (convert-representation nil representation)) (:boolean (emit-invokevirtual +lisp-object+ "getSlotValueAsBoolean" '(:int) :boolean))) (emit-move-from-stack target representation)) (t (compile-function-call form target representation))))) (defknown p2-structure-set (t t t) t) (define-inlined-function p2-structure-set (form target representation) ((check-arg-count form 3)) (let* ((args (cdr form)) (arg1 (first args)) (arg2 (second args)) (arg3 (third args))) (cond ((and (fixnump arg2) (<= 0 arg2 3)) (let* ((*register* *register*) (value-register (when target (allocate-register nil)))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg3 nil))) (when value-register (emit 'dup) (astore value-register)) (maybe-emit-clear-values arg1 arg3) (emit-invokevirtual +lisp-object+ (format nil "setSlotValue_~D" arg2) (lisp-object-arg-types 1) nil) (when value-register (aload value-register) (fix-boxing representation nil) (emit-move-from-stack target representation)))) ((fixnump arg2) (let* ((*register* *register*) (value-register (when target (allocate-register nil)))) (with-operand-accumulation ((compile-operand arg1 nil) (compile-operand arg3 nil))) (maybe-emit-clear-values arg1 arg3) (when value-register (emit 'dup) (astore value-register)) (emit-push-constant-int arg2) (emit 'swap) ;; prevent the integer ;; from being pushed, saved and restored (emit-invokevirtual +lisp-object+ "setSlotValue" (list :int +lisp-object+) nil) (when value-register (aload value-register) (fix-boxing representation nil) (emit-move-from-stack target representation)))) (t (compile-function-call form target representation))))) (define-inlined-function p2-not/null (form target representation) ((aver (or (null representation) (eq representation :boolean))) (check-arg-count form 1)) (let ((arg (second form))) (cond ((null arg) (emit-push-true representation)) ((node-constant-p arg) (emit-push-false representation)) ((and (consp arg) (memq (%car arg) '(NOT NULL))) (compile-forms-and-maybe-emit-clear-values (second arg) 'stack nil) (emit-push-nil) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit 'if_acmpeq LABEL1) (emit-push-true representation) (emit 'goto LABEL2) (label LABEL1) (emit-push-false representation) (label LABEL2))) ((eq representation :boolean) (compile-forms-and-maybe-emit-clear-values arg 'stack :boolean) (emit 'iconst_1) (emit 'ixor)) ((eq (derive-compiler-type arg) 'BOOLEAN) (compile-forms-and-maybe-emit-clear-values arg 'stack :boolean) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit 'ifeq LABEL1) (emit-push-nil) (emit 'goto LABEL2) (label LABEL1) (emit-push-t) (label LABEL2))) (t (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit-push-nil) (emit 'if_acmpeq LABEL1) (emit-push-nil) (emit 'goto LABEL2) (label LABEL1) (emit-push-t) (label LABEL2))))) (emit-move-from-stack target representation)) (define-inlined-function p2-nthcdr (form target representation) ((check-arg-count form 2)) (let* ((args (%cdr form)) (arg1 (%car args)) (arg2 (%cadr args))) (cond ((fixnum-type-p (derive-compiler-type arg1)) (with-operand-accumulation ((compile-operand arg1 :int) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2))) (emit 'swap) (emit-invokevirtual +lisp-object+ "nthcdr" '(:int) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (compile-function-call form target representation))))) (defun p2-and (form target representation) (aver (or (null representation) (eq representation :boolean))) (let ((args (cdr form))) (case (length args) (0 (emit-push-true representation) (emit-move-from-stack target representation)) (1 (compile-form (%car args) target representation)) (t (let ((FAIL (gensym)) (DONE (gensym)) (butlast-args (butlast args))) (loop for form in butlast-args do (compile-form form 'stack nil) do (emit-push-nil) do (emit 'if_acmpeq FAIL)) (apply #'maybe-emit-clear-values butlast-args) (compile-form (car (last args)) target representation) (emit 'goto DONE) (label FAIL) (apply #'maybe-emit-clear-values butlast-args) (emit-push-false representation) (emit-move-from-stack target representation) (label DONE)))))) (defknown p2-or (t t t) t) (defun p2-or (form target representation) (let ((args (cdr form))) (case (length args) (0 (emit-push-false representation) (emit-move-from-stack target representation)) (1 (compile-form (%car args) target representation)) (t (let ((SUCCESS (gensym)) (DONE (gensym)) (butlast-args (butlast args))) (loop for form in butlast-args do (compile-form form 'stack nil) do (emit 'dup) ;; leave value on the stack for SUCCESS to use do (emit-push-nil) do (emit 'if_acmpne SUCCESS) do (emit 'pop)) (apply #'maybe-emit-clear-values butlast-args) (compile-form (car (last args)) target representation) (emit 'goto DONE) (label SUCCESS) (fix-boxing representation nil) ;; value is still on the stack (emit-move-from-stack target representation) (apply #'maybe-emit-clear-values butlast-args) (label DONE)))))) (defun p2-values (form target representation) (let* ((args (cdr form)) (len (length args))) (case len (0 (emit-push-current-thread) (emit-invokevirtual +lisp-thread+ "setValues" nil +lisp-object+) (emit-move-from-stack target)) (1 (let ((arg (%car args))) (compile-forms-and-maybe-emit-clear-values arg target representation))) (2 (let ((arg1 (%car args)) (arg2 (%cadr args))) (cond ((and (eq arg1 t) (eq arg2 t)) (emit-push-current-thread) (emit-push-t) (emit 'dup)) ((and (eq arg1 nil) (eq arg2 nil)) (emit-push-current-thread) (emit-push-nil) (emit 'dup)) (t (with-operand-accumulation ((emit-thread-operand) (compile-operand arg1 nil) (compile-operand arg2 nil) (maybe-emit-clear-values arg1 arg2)))))) (emit-invokevirtual +lisp-thread+ "setValues" (lisp-object-arg-types len) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target)) ((3 4) (with-operand-accumulation ((emit-thread-operand) (dolist (arg args) (compile-operand arg nil)))) (when (notevery #'single-valued-p args) (emit-clear-values)) (emit-invokevirtual +lisp-thread+ "setValues" (lisp-object-arg-types len) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target)) (t (compile-function-call form target representation))))) (defun compile-special-reference (variable target representation) (let ((name (variable-name variable))) (when (constantp name) (let ((value (symbol-value name))) (when (or (null *file-compilation*) (stringp value) (numberp value) (packagep value)) (compile-constant value target representation) (return-from compile-special-reference)))) (unless (and (variable-binding-register variable) (eq (variable-compiland variable) *current-compiland*) (not (enclosed-by-runtime-bindings-creating-block-p (variable-block variable)))) (emit-load-externalized-object name)) (cond ((constantp name) ;; "... a reference to a symbol declared with DEFCONSTANT always ;; refers to its global value." (emit-invokevirtual +lisp-symbol+ "getSymbolValue" nil +lisp-object+)) ((and (variable-binding-register variable) (eq (variable-compiland variable) *current-compiland*) (not (enclosed-by-runtime-bindings-creating-block-p (variable-block variable)))) (aload (variable-binding-register variable)) (emit-getfield +lisp-special-binding+ "value" +lisp-object+)) (t (emit-push-current-thread) (emit-invokevirtual +lisp-symbol+ "symbolValue" (list +lisp-thread+) +lisp-object+))) (fix-boxing representation nil) (emit-move-from-stack target representation))) (defknown compile-var-ref (t t t) t) (defun compile-var-ref (ref target representation) (when target (if (var-ref-constant-p ref) (compile-constant (var-ref-constant-value ref) target representation) (let ((variable (var-ref-variable ref))) (cond ((variable-special-p variable) (compile-special-reference variable target representation)) ((or (variable-representation variable) (variable-register variable) (variable-closure-index variable) (variable-index variable) (variable-environment variable)) (emit-push-variable variable) (convert-representation (variable-representation variable) representation) (emit-move-from-stack target representation)) (t (sys::%format t "compile-var-ref general case~%") (aver nil))))))) (defun p2-set (form target representation) (cond ((and (check-arg-count form 2) (eq (derive-type (%cadr form)) 'SYMBOL)) (with-operand-accumulation ((emit-thread-operand) (compile-operand (%cadr form) nil +lisp-symbol+) (compile-operand (%caddr form) nil))) (maybe-emit-clear-values (%cadr form) (%caddr form)) (emit-invokevirtual +lisp-thread+ "setSpecialVariable" (list +lisp-symbol+ +lisp-object+) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (compile-function-call form target representation)))) (defknown p2-setq (t t t) t) (defun p2-setq (form target representation) (unless (= (length form) 3) (assert (not "p2-setq should receive exactly 2 arguments!"))) (let* ((name (%cadr form)) (variable (find-visible-variable name)) (value-form (%caddr form))) (when (or (null variable) (variable-special-p variable)) ;; We're setting a special variable. (cond ((and variable (variable-binding-register variable) (eq (variable-compiland variable) *current-compiland*) (not (enclosed-by-runtime-bindings-creating-block-p (variable-block variable)))) ;; choose this compilation order to prevent ;; with-operand-accumulation (compile-forms-and-maybe-emit-clear-values value-form 'stack nil) (emit 'dup) (aload (variable-binding-register variable)) (emit 'swap) (emit-putfield +lisp-special-binding+ "value" +lisp-object+)) ((and (consp value-form) (eq (first value-form) 'CONS) (= (length value-form) 3) (var-ref-p (third value-form)) (eq (variable-name (var-ref-variable (third value-form))) name)) (with-operand-accumulation ((emit-thread-operand) (emit-load-externalized-object-operand name) (compile-operand (second value-form) nil) (maybe-emit-clear-values (second value-form))) (emit-invokevirtual +lisp-thread+ "pushSpecial" (list +lisp-symbol+ +lisp-object+) +lisp-object+))) (t (unless (symbolp name) (error 'program-error "First argument to SETQ is not a symbol in ~S" form)) (with-operand-accumulation ((emit-thread-operand) (emit-load-externalized-object-operand name) (compile-operand value-form nil) (maybe-emit-clear-values value-form)) (emit-invokevirtual +lisp-thread+ "setSpecialVariable" (list +lisp-symbol+ +lisp-object+) +lisp-object+)))) (fix-boxing representation nil) (emit-move-from-stack target representation) (return-from p2-setq)) (when (zerop (variable-reads variable)) ;; If we never read the variable, we don't have to set it. (cond (target (compile-forms-and-maybe-emit-clear-values value-form 'stack nil) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (compile-form value-form nil nil))) (return-from p2-setq)) ;; Optimize the (INCF X) case. (let ((incf-p nil)) (when (and (eq (variable-representation variable) :int) (consp value-form)) (let ((op (car value-form)) (len (length value-form))) (case op (1+ (when (= len 2) (let ((arg (cadr value-form))) (when (and (var-ref-p arg) (eq (var-ref-variable arg) variable)) (setf incf-p t))))) (+ (when (= len 3) (let ((arg1 (second value-form)) (arg2 (third value-form))) (when (eql arg1 1) (setf arg1 arg2 arg2 1)) ;; (+ 1 X) => (+ X 1) (when (eql arg2 1) (when (and (var-ref-p arg1) (eq (var-ref-variable arg1) variable)) (setf incf-p t))))))))) (when incf-p (aver (variable-register variable)) (emit 'iinc (variable-register variable) 1) (when target (emit 'iload (variable-register variable)) (convert-representation :int representation) (emit-move-from-stack target representation)) (return-from p2-setq))) (cond ((and (eq (variable-representation variable) :int) (or (equal value-form (list '1+ (variable-name variable))) (equal value-form (list '+ (variable-name variable) 1)) (equal value-form (list '+ 1 (variable-name variable))))) ;; FIXME This is the old (INCF X) case. We should be able to remove ;; this case once the new code is stable. (emit 'iinc (variable-register variable) 1) (when target (convert-representation :int representation) (emit-move-from-stack target representation))) ((and (eq (variable-representation variable) :int) (or (equal value-form (list '1- (variable-name variable))) (equal value-form (list '- (variable-name variable) 1)))) (dformat t "p2-setq decf :int case~%") (emit 'iinc (variable-register variable) -1) (when target (convert-representation :int representation) (emit-move-from-stack target representation))) (t (let ((rep (variable-representation variable))) (dformat t "p2-setq ~A case value-form = ~S~%" rep value-form) (compile-forms-and-maybe-emit-clear-values value-form 'stack rep) (when target (emit-dup rep)) (emit-move-to-variable variable) (when target (convert-representation rep representation) (emit-move-from-stack target representation))))))) (defun p2-sxhash (form target representation) (cond ((check-arg-count form 1) (let ((arg (%cadr form))) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-invokevirtual +lisp-object+ "sxhash" nil :int) (convert-representation :int representation) (emit-move-from-stack target representation))) (t (compile-function-call form target representation)))) (defknown p2-symbol-name (t t t) t) (define-inlined-function p2-symbol-name (form target representation) ((check-arg-count form 1)) (let ((arg (%cadr form))) (cond ((and (eq (derive-compiler-type arg) 'SYMBOL) (< *safety* 3)) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-checkcast +lisp-symbol+) (emit-getfield +lisp-symbol+ "name" +lisp-simple-string+) (emit-move-from-stack target representation)) (t (compile-function-call form target representation))))) (defknown p2-symbol-package (t t t) t) (define-inlined-function p2-symbol-package (form target representation) ((check-arg-count form 1)) (let ((arg (%cadr form))) (cond ((and (eq (derive-compiler-type arg) 'SYMBOL) (< *safety* 3)) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-checkcast +lisp-symbol+) (emit-invokevirtual +lisp-symbol+ "getPackage" nil +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (compile-function-call form target representation))))) (defknown p2-symbol-value (t t t) t) (defun p2-symbol-value (form target representation) (when (check-arg-count form 1) (let ((arg (%cadr form))) (when (eq (derive-compiler-type arg) 'SYMBOL) (compile-forms-and-maybe-emit-clear-values arg 'stack nil) (emit-checkcast +lisp-symbol+) (emit-push-current-thread) (emit-invokevirtual +lisp-symbol+ "symbolValue" (list +lisp-thread+) +lisp-object+) (fix-boxing representation nil) (emit-move-from-stack target representation) (return-from p2-symbol-value)))) ;; Otherwise... (compile-function-call form target representation)) (defknown generate-instanceof-type-check-for-value (t) t) (defun generate-instanceof-type-check-for-value (expected-type) ;; The value to be checked is on the stack. (declare (type symbol expected-type)) (let ((instanceof-class (ecase expected-type (SYMBOL +lisp-symbol+) (CHARACTER +lisp-character+) (CONS +lisp-cons+) (HASH-TABLE +lisp-hash-table+) (FIXNUM +lisp-fixnum+) (STREAM +lisp-stream+) (STRING +lisp-abstract-string+) (VECTOR +lisp-abstract-vector+))) (expected-type-java-symbol-name (case expected-type (HASH-TABLE "HASH_TABLE") (t (symbol-name expected-type)))) (LABEL1 (gensym))) (emit 'dup) (emit-instanceof instanceof-class) (emit 'ifne LABEL1) (emit-getstatic +lisp-symbol+ expected-type-java-symbol-name +lisp-symbol+) (emit-invokestatic +lisp+ "type_error" (lisp-object-arg-types 2) +lisp-object+) (label LABEL1)) t) (declaim (ftype (function (t) t) generate-type-check-for-value)) (defun generate-type-check-for-value (declared-type) (let ((type-to-use (find-type-for-type-check declared-type))) (when type-to-use (generate-instanceof-type-check-for-value type-to-use)))) (defun p2-the (form target representation) (let ((type-form (second form)) (value-form (third form))) (cond ((and (subtypep type-form 'FIXNUM) (consp value-form) (eq (car value-form) 'structure-ref)) ;; Special case for structure slot references: getFixnumSlotValue() ;; signals an error if the slot's value is not a fixnum. (compile-form value-form target representation)) ((and (> *safety* 0) (not (compiler-subtypep (derive-type value-form) type-form))) (compile-form value-form 'stack nil) (generate-type-check-for-value type-form) ;; The value is left on the stack here if the type check succeeded. (fix-boxing representation nil) (emit-move-from-stack target representation)) (t (compile-form value-form target representation))))) (defun p2-truly-the (form target representation) (compile-form (third form) target representation)) (defknown p2-char-code (t t t) t) (define-inlined-function p2-char-code (form target representation) ((check-arg-count form 1)) (let ((arg (second form))) (cond ((characterp arg) (compile-constant (char-code arg) target representation)) ((and (< *safety* 3) (eq (derive-compiler-type arg) 'character)) (compile-form arg 'stack :char) ;; we change the representation between the above and here ;; ON PURPOSE! (convert-representation :int representation) (emit-move-from-stack target representation)) (t (compile-function-call form target representation))))) (defknown p2-java-jclass (t t t) t) (define-inlined-function p2-java-jclass (form target representation) ((and (= 2 (length form)) (stringp (cadr form)))) (let ((c (ignore-errors (java:jclass (cadr form))))) (if c (compile-constant c target representation) ;; delay resolving the method to run-time; it's unavailable now (compile-function-call form target representation)))) (defknown p2-java-jconstructor (t t t) t) (define-inlined-function p2-java-jconstructor (form target representation) ((and (< 1 (length form)) (every #'stringp (cdr form)))) (let ((c (ignore-errors (apply #'java:jconstructor (cdr form))))) (if c (compile-constant c target representation) ;; delay resolving the method to run-time; it's unavailable now (compile-function-call form target representation)))) (defknown p2-java-jmethod (t t t) t) (define-inlined-function p2-java-jmethod (form target representation) ((and (< 1 (length form)) (every #'stringp (cdr form)))) (let ((m (ignore-errors (apply #'java:jmethod (cdr form))))) (if m (compile-constant m target representation) ;; delay resolving the method to run-time; it's unavailable now (compile-function-call form target representation)))) #|(defknown p2-java-jcall (t t t) t) (define-inlined-function p2-java-jcall (form target representation) ((and (> *speed* *safety*) (< 1 (length form)) (eq 'jmethod (car (cadr form))) (every #'stringp (cdr (cadr form))))) (let ((m (ignore-errors (eval (cadr form))))) (if m (let ((must-clear-values nil) (arg-types (raw-arg-types (jmethod-params m)))) (declare (type boolean must-clear-values)) (dolist (arg (cddr form)) (compile-form arg 'stack nil) (unless must-clear-values (unless (single-valued-p arg) (setf must-clear-values t)))) (when must-clear-values (emit-clear-values)) (dotimes (i (jarray-length raw-arg-types)) (push (jarray-ref raw-arg-types i) arg-types)) (emit-invokevirtual (jclass-name (jmethod-declaring-class m)) (jmethod-name m) (nreverse arg-types) (jmethod-return-type m))) ;; delay resolving the method to run-time; it's unavailable now (compile-function-call form target representation))))|# (defknown p2-char= (t t t) t) (defun p2-char= (form target representation) (let* ((args (cdr form)) (numargs (length args))) (when (= numargs 0) (compiler-warn "Wrong number of arguments for ~A." (car form)) (compile-function-call form target representation) (return-from p2-char=)) (unless (= numargs 2) (compile-function-call form target representation) (return-from p2-char=)) (let ((arg1 (%car args)) (arg2 (%cadr args))) (when (and (characterp arg1) (characterp arg2)) (cond ((eql arg1 arg2) (emit-push-true representation)) (t (emit-push-false representation))) (emit-move-from-stack target representation) (return-from p2-char=)) (cond ((characterp arg1) ;; prevent need for with-operand-accumulation: reverse args (compile-forms-and-maybe-emit-clear-values arg2 'stack :char) (emit-push-constant-int (char-code arg1))) ((characterp arg2) (compile-forms-and-maybe-emit-clear-values arg1 'stack :char) (emit-push-constant-int (char-code arg2))) (t (with-operand-accumulation ((compile-operand arg1 :char) (compile-operand arg2 :char) (maybe-emit-clear-values arg1 arg2))))) (let ((LABEL1 (gensym)) (LABEL2 (gensym))) (emit 'if_icmpeq LABEL1) (emit-push-false representation) (emit 'goto LABEL2) (label LABEL1) (emit-push-true representation) (label LABEL2) (emit-move-from-stack target representation))))) (defknown p2-threads-synchronized-on (t t) t) (defun p2-threads-synchronized-on (block target) (let* ((form (synchronized-form block)) (*register* *register*) (object-register (allocate-register nil)) (BEGIN-PROTECTED-RANGE (gensym "F")) (END-PROTECTED-RANGE (gensym "U")) (EXIT (gensym "E"))) (compile-form (cadr form) 'stack nil) (emit-invokevirtual +lisp-object+ "lockableInstance" nil +java-object+) ; value to synchronize (emit 'dup) (astore object-register) (emit 'monitorenter) (label BEGIN-PROTECTED-RANGE) (let ((*blocks* (cons block *blocks*))) (compile-progn-body (cddr form) target)) (emit 'goto EXIT) (label END-PROTECTED-RANGE) (aload object-register) (emit 'monitorexit) (emit 'athrow) (label EXIT) (aload object-register) (emit 'monitorexit) (add-exception-handler BEGIN-PROTECTED-RANGE END-PROTECTED-RANGE END-PROTECTED-RANGE nil))) (defun p2-java-jrun-exception-protected (block target) (let* ((form (exception-protected-form block)) (*register* *register*) (*blocks* (cons block *blocks*)) (BEGIN-PROTECTED-RANGE (gensym "F")) (END-PROTECTED-RANGE (gensym "U")) (STACK-EXHAUST (gensym "S")) (MEMORY-EXHAUST (gensym "M")) (EXIT (gensym "E"))) (label BEGIN-PROTECTED-RANGE) (compile-progn-body form target) (emit 'goto EXIT) (label END-PROTECTED-RANGE) (label STACK-EXHAUST) (emit 'pop) (emit-invokestatic +lisp+ "stackError" nil +lisp-object+) (emit 'areturn) (add-exception-handler BEGIN-PROTECTED-RANGE END-PROTECTED-RANGE STACK-EXHAUST +java-stack-overflow+) (label MEMORY-EXHAUST) (emit-invokestatic +lisp+ "memoryError" (list +java-out-of-memory+) +lisp-object+) (emit 'areturn) (add-exception-handler BEGIN-PROTECTED-RANGE END-PROTECTED-RANGE MEMORY-EXHAUST +java-out-of-memory+) (label EXIT))) (defknown p2-catch-node (t t) t) (defun p2-catch-node (block target) (let ((form (catch-form block))) (when (= (length form) 2) ; (catch 'foo) (when target (emit-push-nil) (emit-move-from-stack target)) (return-from p2-catch-node)) (let* ((*register* *register*) (tag-register (allocate-register nil)) (BEGIN-PROTECTED-RANGE (gensym "F")) (END-PROTECTED-RANGE (gensym "U")) (THROW-HANDLER (gensym "H")) (RETHROW (gensym)) (DEFAULT-HANDLER (gensym)) (EXIT (gensym "E")) (specials-register (allocate-register nil))) (compile-form (second form) tag-register nil) ; Tag. (emit-push-current-thread) (aload tag-register) (emit-invokevirtual +lisp-thread+ "pushCatchTag" (lisp-object-arg-types 1) nil) (let ((*blocks* (cons block *blocks*))) ; Stack depth is 0. (save-dynamic-environment specials-register) (label BEGIN-PROTECTED-RANGE) ; Start of protected range. (compile-progn-body (cddr form) target) ; Implicit PROGN. (label END-PROTECTED-RANGE) ; End of protected range. (emit 'goto EXIT)) ; Jump over handlers. (label THROW-HANDLER) ; Start of handler for THROW. ;; The Throw object is on the runtime stack. Stack depth is 1. (emit 'dup) ; Stack depth is 2. (emit-getfield +lisp-throw+ "tag" +lisp-object+) ; Still 2. (aload tag-register) ; Stack depth is 3. ;; If it's not the tag we're looking for, we branch to the start of the ;; catch-all handler, which will do a re-throw. (emit 'if_acmpne RETHROW) ; Stack depth is 1. (restore-dynamic-environment specials-register) (emit-push-current-thread) (emit-invokevirtual +lisp-throw+ "getResult" (list +lisp-thread+) +lisp-object+) (emit-move-from-stack target) ; Stack depth is 0. (emit 'goto EXIT) (label RETHROW) ; Start of handler for all other Throwables. ;; A Throwable object is on the runtime stack here. Stack depth is 1. (emit-push-current-thread) (emit-invokevirtual +lisp-thread+ "popCatchTag" nil nil) (emit 'athrow) ; Re-throw. (label DEFAULT-HANDLER) ; Start of handler for all other Throwables. ;; A Throwable object is on the runtime stack here. Stack depth is 1. (emit-push-current-thread) (emit-invokevirtual +lisp-thread+ "popCatchTag" nil nil) (emit 'athrow) ; Re-throw. (label EXIT) ;; Finally... (emit-push-current-thread) (emit-invokevirtual +lisp-thread+ "popCatchTag" nil nil) (add-exception-handler BEGIN-PROTECTED-RANGE END-PROTECTED-RANGE THROW-HANDLER +lisp-throw+) (add-exception-handler BEGIN-PROTECTED-RANGE END-PROTECTED-RANGE DEFAULT-HANDLER nil))) t) (defun p2-throw (form target representation) (with-operand-accumulation ((emit-thread-operand) (compile-operand (second form) nil) ; Tag. (emit-clear-values) ; Do this unconditionally! (MISC.503) (compile-operand (third form) nil)) ; Result. (emit-invokevirtual +lisp-thread+ "throwToTag" (lisp-object-arg-types 2) nil)) ;; Following code will not be reached. (when target (ecase representation ((:int :boolean :char) (emit 'iconst_0)) ((nil) (emit-push-nil))) (emit-move-from-stack target))) (defun p2-unwind-protect-node (block target) (let ((form (unwind-protect-form block))) (when (= (length form) 2) ; No cleanup form. (compile-form (second form) target nil) (return-from p2-unwind-protect-node)) ;; The internal representation of UNWIND-PROTECT ;; as generated by P1-UNWIND-PROTECT differs a bit ;; from what the spec says; ours is: ;; (UNWIND-PROTECT protected-form (progn cleanup-forms) cleanup-forms), ;; because we need to compile the cleanup forms twice and ;; we can compile a p1 outcome only once. ;; ;; We used to use JSR and RET JVM instructions to prevent ;; duplication of output code. However, this led to JVM stack ;; inconsistency errors ;; (see http://trac.common-lisp.net/armedbear/ticket/21) (let* ((protected-form (cadr form)) (unwinding-form (caddr form)) (cleanup-forms (cdddr form)) (*register* *register*) (exception-register (allocate-register nil)) (result-register (allocate-register nil)) (values-register (allocate-register nil)) (specials-register (allocate-register nil)) (BEGIN-PROTECTED-RANGE (gensym "F")) (END-PROTECTED-RANGE (gensym "U")) (HANDLER (gensym "H")) (EXIT (gensym "E"))) ;; Make sure there are no leftover multiple return values from previous calls. (emit-clear-values) (let* ((*blocks* (cons block *blocks*))) (save-dynamic-environment specials-register) (label BEGIN-PROTECTED-RANGE) (compile-form protected-form result-register nil) (unless (single-valued-p protected-form) (emit-push-current-thread) (emit-getfield +lisp-thread+ "_values" +lisp-object-array+) (astore values-register)) (label END-PROTECTED-RANGE)) (let ((*register* *register*)) (compile-form unwinding-form nil nil)) (when (single-valued-p protected-form) ;; otherwise, we'll load the values register below (maybe-emit-clear-values unwinding-form)) (emit 'goto EXIT) ; Jump over handler. (label HANDLER) ; Start of exception handler. ;; The Throwable object is on the runtime stack. Stack depth is 1. (astore exception-register) (emit-push-current-thread) (emit-getfield +lisp-thread+ "_values" +lisp-object-array+) (astore values-register) (restore-dynamic-environment specials-register) (let ((*register* *register*)) (compile-progn-body cleanup-forms nil nil)) (emit-push-current-thread) (aload values-register) (emit-putfield +lisp-thread+ "_values" +lisp-object-array+) (aload exception-register) (emit 'athrow) ; Re-throw exception. (label EXIT) ;; Restore multiple values returned by protected form. (unless (single-valued-p protected-form) (emit-push-current-thread) (aload values-register) (emit-putfield +lisp-thread+ "_values" +lisp-object-array+)) ;; Result. (aload result-register) (emit-move-from-stack target) (add-exception-handler BEGIN-PROTECTED-RANGE END-PROTECTED-RANGE HANDLER nil)))) (defknown compile-form (t t t) t) (defun compile-form (form target representation) (cond ((consp form) (let* ((op (%car form)) (handler (and (symbolp op) (get op 'p2-handler)))) (cond (handler (funcall handler form target representation)) ((symbolp op) (cond ((special-operator-p op) (dformat t "form = ~S~%" form) (compiler-unsupported "COMPILE-FORM: unsupported special operator ~S" op)) (t (compile-function-call form target representation)))) ((and (consp op) (eq (%car op) 'LAMBDA)) (aver (progn 'unexpected-lambda nil)) (let ((new-form (list* 'FUNCALL form))) (compile-form new-form target representation))) (t (compiler-unsupported "COMPILE-FORM unhandled case ~S" form))))) ((symbolp form) (cond ((null form) (emit-push-false representation) (emit-move-from-stack target representation)) ((eq form t) (emit-push-true representation) (emit-move-from-stack target representation)) ((keywordp form) (ecase representation (:boolean (emit 'iconst_1)) ((nil) (emit-load-externalized-object form))) (emit-move-from-stack target representation)) (t ;; Shouldn't happen. (aver nil)))) ((var-ref-p form) (compile-var-ref form target representation)) ((node-p form) (cond ((jump-node-p form) (let ((op (car (node-form form)))) (cond ((eq op 'go) (p2-go form target representation)) ((eq op 'return-from) (p2-return-from form target representation)) (t (assert (not "jump-node: can't happen")))))) ((block-node-p form) (p2-block-node form target representation)) ((let/let*-node-p form) (p2-let/let*-node form target representation)) ((tagbody-node-p form) (p2-tagbody-node form target) (fix-boxing representation nil)) ((unwind-protect-node-p form) (p2-unwind-protect-node form target) (fix-boxing representation nil)) ((m-v-b-node-p form) (p2-m-v-b-node form target) (fix-boxing representation nil)) ((flet-node-p form) (p2-flet-node form target representation)) ((labels-node-p form) (p2-labels-node form target representation)) ((locally-node-p form) (p2-locally-node form target representation)) ((catch-node-p form) (p2-catch-node form target) (fix-boxing representation nil)) ((progv-node-p form) (p2-progv-node form target representation)) ((synchronized-node-p form) (p2-threads-synchronized-on form target) (fix-boxing representation nil)) ((protected-node-p form) (p2-java-jrun-exception-protected form target) (fix-boxing representation nil)) (t (aver (not "Can't happen"))))) ((constantp form) (compile-constant form target representation)) (t (compiler-unsupported "COMPILE-FORM unhandled case ~S" form))) t) (defmacro with-open-class-file ((var class-file) &body body) `(with-open-file (,var (abcl-class-file-pathname ,class-file) :direction :output :element-type '(unsigned-byte 8) :if-exists :supersede) ,@body)) (defknown p2-compiland-process-type-declarations (list) t) (defun p2-compiland-process-type-declarations (body) (flet ((process-declaration (name type) (let ((variable (find-visible-variable name))) (when variable (setf (variable-declared-type variable) type))))) (dolist (subform body) (unless (and (consp subform) (eq (%car subform) 'DECLARE)) (return)) (let ((decls (%cdr subform))) (dolist (decl decls) (case (car decl) (TYPE (let ((type (make-compiler-type (cadr decl)))) (dolist (name (cddr decl)) (process-declaration name type)))) ((IGNORE IGNORABLE) (process-ignore/ignorable (%car decl) (%cdr decl) *visible-variables*)) ((DYNAMIC-EXTENT FTYPE INLINE NOTINLINE OPTIMIZE SPECIAL) ;; Nothing to do here. ) (t (let ((type (make-compiler-type (car decl)))) (dolist (name (cdr decl)) (process-declaration name type))))))))) t) (defknown p2-compiland-unbox-variable (variable) t) (defun p2-compiland-unbox-variable (variable) (let ((register (variable-register variable))) (when (and register (not (variable-special-p variable)) (not (variable-used-non-locally-p variable)) (null (compiland-children *current-compiland*))) (when (memq (type-representation (variable-declared-type variable)) '(:int :long)) (emit-push-variable variable) (derive-variable-representation variable nil) (when (< 1 (representation-size (variable-representation variable))) (allocate-variable-register variable)) (convert-representation nil (variable-representation variable)) (emit-move-to-variable variable)))) t) (defun assign-field-name (local-function) (setf (local-function-field local-function) (symbol-name (gensym "LFUN")))) (defknown p2-compiland (t) t) (defun p2-compiland (compiland method) (let* ((p1-result (compiland-p1-result compiland)) (class-file (compiland-class-file compiland)) (*this-class* (abcl-class-file-class class-file)) (closure-args (intersection *closure-variables* (compiland-arg-vars compiland))) (local-closure-vars (find compiland *closure-variables* :key #'variable-compiland)) (body (cddr p1-result)) (*child-p* (not (null (compiland-parent compiland)))) (*visible-variables* *visible-variables*) (*thread* nil) (*initialize-thread-var* nil) (*current-compiland* compiland)) (with-code-to-method (class-file method) (setf *register* 1 ;; register 0: "this" pointer *registers-allocated* 1) (when (fixnump *source-line-number*) (let ((table (make-line-numbers-attribute))) (code-add-attribute *current-code-attribute* table) (line-numbers-add-line table 0 *source-line-number*))) (dolist (local-function (compiland-children compiland)) (assign-field-name local-function)) (dolist (var (compiland-arg-vars compiland)) (push var *visible-variables*)) (dolist (var (compiland-free-specials compiland)) (push var *visible-variables*)) (when *using-arg-array* (setf (compiland-argument-register compiland) (allocate-register nil))) ;; Assign indices or registers, depending on where the args are ;; located: the arg-array or the call-stack (let ((index 0)) (dolist (variable (compiland-arg-vars compiland)) (aver (null (variable-register variable))) (aver (null (variable-index variable))) (if *using-arg-array* (setf (variable-index variable) index) (setf (variable-register variable) (allocate-register nil))) (incf index))) ;; Reserve the next available slot for the thread register. (setf *thread* (allocate-register nil)) (when *closure-variables* (setf (compiland-closure-register compiland) (allocate-register nil)) (dformat t "p2-compiland 2 closure register = ~S~%" (compiland-closure-register compiland))) (when *closure-variables* (if (not *child-p*) (progn ;; if we're the ultimate parent: create the closure array (emit-push-constant-int (length *closure-variables*)) (emit-anewarray +lisp-closure-binding+)) (progn (aload 0) (emit-getfield +lisp-compiled-closure+ "ctx" +closure-binding-array+) (when local-closure-vars ;; in all other cases, it gets stored in the register below (emit 'astore (compiland-closure-register compiland)) (duplicate-closure-array compiland))))) ;; Move args from their original registers to the closure variables array (when (or closure-args (and *closure-variables* (not *child-p*))) (dformat t "~S moving arguments to closure array~%" (compiland-name compiland)) (dotimes (i (length *closure-variables*)) ;; Loop over all slots, setting their value ;; unconditionally if we're the parent creating it (using null ;; values if no real value is available) ;; or selectively if we're a child binding certain slots. (let ((variable (find i closure-args :key #'variable-closure-index :test #'eql))) (when (or (not *child-p*) variable) ;; we're the parent, or we have a variable to set. (emit 'dup) ; array (emit-push-constant-int i) (emit-new +lisp-closure-binding+) (emit 'dup) (cond ((null variable) (assert (not *child-p*)) (emit 'aconst_null)) ((variable-register variable) (assert (not (eql (variable-register variable) (compiland-closure-register compiland)))) (aload (variable-register variable)) (setf (variable-register variable) nil)) ((variable-index variable) (aload (compiland-argument-register compiland)) (emit-push-constant-int (variable-index variable)) (emit 'aaload) (setf (variable-index variable) nil)) (t (assert (not "Can't happen!!")))) (emit-invokespecial-init +lisp-closure-binding+ (list +lisp-object+)) (emit 'aastore))))) (when *closure-variables* (aver (not (null (compiland-closure-register compiland)))) (astore (compiland-closure-register compiland)) (dformat t "~S done moving arguments to closure array~%" (compiland-name compiland))) ;; If applicable, move args from arg array to registers. (when *using-arg-array* (dolist (variable (compiland-arg-vars compiland)) (unless (or (variable-special-p variable) (null (variable-index variable)) ;; not in the array anymore (< (+ (variable-reads variable) (variable-writes variable)) 2)) (let ((register (allocate-register nil))) (aload (compiland-argument-register compiland)) (emit-push-constant-int (variable-index variable)) (emit 'aaload) (astore register) (setf (variable-register variable) register) (setf (variable-index variable) nil))))) (with-saved-compiler-policy (process-optimization-declarations body) (p2-compiland-process-type-declarations body) (generate-type-checks-for-variables (compiland-arg-vars compiland)) ;; Unbox variables. (dolist (variable (compiland-arg-vars compiland)) (p2-compiland-unbox-variable variable)) ;; Establish dynamic bindings for any variables declared special. (when (some #'variable-special-p (compiland-arg-vars compiland)) ;; Save the dynamic environment (setf (compiland-environment-register compiland) (allocate-register nil)) (save-dynamic-environment (compiland-environment-register compiland)) (dolist (variable (compiland-arg-vars compiland)) (when (variable-special-p variable) (setf (variable-binding-register variable) (allocate-register nil)) (emit-push-current-thread) (emit-push-variable-name variable) (cond ((variable-register variable) (aload (variable-register variable)) (setf (variable-register variable) nil)) ((variable-index variable) (aload (compiland-argument-register compiland)) (emit-push-constant-int (variable-index variable)) (emit 'aaload) (setf (variable-index variable) nil))) (emit-invokevirtual +lisp-thread+ "bindSpecial" (list +lisp-symbol+ +lisp-object+) +lisp-special-binding+) (astore (variable-binding-register variable))))) (compile-progn-body body 'stack)) (when (compiland-environment-register compiland) (restore-dynamic-environment (compiland-environment-register compiland))) (unless *code* (emit-push-nil)) (emit 'areturn) ;; Warn if any unused args. (Is this the right place?) (check-for-unused-variables (compiland-arg-vars compiland)) (dolist (local-function (compiland-children compiland)) (when (compiland-class-file (local-function-compiland local-function)) (declare-local-function local-function))) ;; Go back and fill in prologue. (let ((code *code*)) (setf *code* ()) (let ((arity (compiland-arity compiland))) (when (and arity *using-arg-array*) (generate-arg-count-check arity))) (when *hairy-arglist-p* (aload 0) ; this (aver (not (null (compiland-argument-register compiland)))) (aload (compiland-argument-register compiland)) ; arg vector (emit 'aconst_null) ;; no thread arg required: ;; there's no non-constant initform or special ;; which might require the thread (emit-invokevirtual *this-class* "processArgs" (list +lisp-object-array+ +lisp-thread+) +lisp-object-array+) (astore (compiland-argument-register compiland))) (maybe-initialize-thread-var) (setf *code* (nconc code *code*))))) t) (defun compile-to-jvm-class (compiland) "Returns ?what? ### a jvm class-file object?" (let* ((class-file (compiland-class-file compiland)) (args (cadr (compiland-p1-result compiland))) (*hairy-arglist-p* (or (memq '&KEY args) (memq '&OPTIONAL args) (memq '&REST args))) (*using-arg-array* (or *hairy-arglist-p* (< call-registers-limit (length args))))) (setf (abcl-class-file-superclass class-file) (if (or *hairy-arglist-p* (and (not (null (compiland-parent compiland))) *closure-variables*)) +lisp-compiled-closure+ +lisp-compiled-primitive+)) (unless *hairy-arglist-p* (setf (compiland-arity compiland) (length args))) ;; Static initializer (let ((clinit (make-static-initializer class-file))) (setf (abcl-class-file-static-initializer class-file) clinit) (class-add-method class-file clinit)) ;; Constructor (let ((constructor (make-constructor class-file (compiland-name compiland) args))) (setf (abcl-class-file-constructor class-file) constructor) (class-add-method class-file constructor)) ;; Main method (let* ((method-arg-types (if *using-arg-array* (list +lisp-object-array+) (lisp-object-arg-types (length args)))) (method (make-jvm-method "execute" +lisp-object+ method-arg-types :flags '(:final :public)))) (class-add-method class-file method) (p2-compiland compiland method)))) (defun p2-with-inline-code (form target representation) ;;form = (with-inline-code (&optional target-var repr-var) ...body...) (destructuring-bind (&optional target-var repr-var) (cadr form) (eval `(let (,@(when target-var `((,target-var ,target))) ,@(when repr-var `((,repr-var ,representation)))) ,@(cddr form))))) (defun compile-1 (compiland stream) (let ((*all-variables* nil) (*closure-variables* nil) (*undefined-variables* nil) (*local-functions* nil)) (p1-compiland compiland) ;; *all-variables* doesn't contain variables which ;; are in an enclosing lexical environment (variable-environment) ;; so we don't need to filter them out (setf *closure-variables* (remove-if #'variable-special-p (remove-if-not #'variable-used-non-locally-p *all-variables*))) (let ((i 0)) (dolist (var (reverse *closure-variables*)) (setf (variable-closure-index var) i) (dformat t "var = ~S closure index = ~S~%" (variable-name var) (variable-closure-index var)) (incf i))) ;; Assert that we're not refering to any variables ;; we're not allowed to use (assert (= 0 (length (remove-if (complement #'variable-references) (remove-if #'variable-references-allowed-p *visible-variables*))))) ;; Pass 2. (with-class-file (compiland-class-file compiland) (compile-to-jvm-class compiland) (finish-class (compiland-class-file compiland) stream)))) (defvar *compiler-error-bailout*) (defun make-compiler-error-form (form condition) `(lambda ,(cadr form) (error 'program-error :format-control "Program error while compiling ~a" :format-arguments (if ,condition (list (apply 'format nil ,(slot-value condition 'sys::format-control) ',(slot-value condition 'sys::format-arguments))) (list "a form"))))) (defun compile-defun (name form environment filespec stream *declare-inline*) "Compiles a lambda expression `form'. If `filespec' is NIL, a random Java class name is generated, if it is non-NIL, it's used to derive a Java class name from. Returns the a abcl-class-file structure containing the description of the generated class." (aver (eq (car form) 'LAMBDA)) (catch 'compile-defun-abort (flet ((compiler-bailout (&optional condition) (let ((class-file (make-abcl-class-file :pathname filespec)) (error-form (make-compiler-error-form form condition))) (compile-1 (make-compiland :name name :lambda-expression error-form :class-file class-file) stream) class-file))) (let* ((class-file (make-abcl-class-file :pathname filespec)) (*compiler-error-bailout* #'compiler-bailout) (*compile-file-environment* environment) (precompiled-form (pre:precompile-form form t environment))) (compile-1 (make-compiland :name name :lambda-expression precompiled-form :class-file class-file) stream) class-file)))) (defvar *catch-errors* t) (defvar *last-error-context* nil) (defun note-error-context () (let ((context *compiler-error-context*)) (when (and context (neq context *last-error-context*)) (fresh-line *error-output*) (princ "; in " *error-output*) (let ((*print-length* 2) (*print-level* 2) (*print-pretty* nil)) (prin1 context *error-output*)) (terpri *error-output*) (terpri *error-output*) (setf *last-error-context* context)))) (defvar *resignal-compiler-warnings* nil "This generalized boolean JVM:*RESIGNAL-COMPILER-WARNINGS* controls whether the compiler signals dignaostics to the condition system or merely outputs them to the standard reporting stream. The default is to not signal. Could arguably better named as *SIGNAL-COMPILE-WARNINGS-P*.") (defun handle-warning (condition) (cond (*resignal-compiler-warnings* (signal condition)) (t (unless *suppress-compiler-warnings* (fresh-line *error-output*) (note-error-context) (format *error-output* "; Caught ~A:~%; ~A~2%" (type-of condition) condition)) (muffle-warning)))) (defun handle-compiler-error (condition) (fresh-line *error-output*) (note-error-context) (format *error-output* "; Caught ERROR:~%; ~A~2%" condition) (throw 'compile-defun-abort (funcall *compiler-error-bailout* condition))) (defvar *in-compilation-unit* nil) (defmacro with-compilation-unit (options &body body) `(%with-compilation-unit (lambda () ,@body) ,@options)) (defun %with-compilation-unit (fn &key override) (if (and *in-compilation-unit* (not override)) (funcall fn) (let ((style-warnings 0) (warnings 0) (errors 0) (*defined-functions* nil) (*undefined-functions* nil) (*in-compilation-unit* t)) (unwind-protect (handler-bind ((style-warning #'(lambda (c) (incf style-warnings) (handle-warning c))) (warning #'(lambda (c) (incf warnings) (handle-warning c))) (compiler-error #'(lambda (c) (incf errors) (handle-compiler-error c)))) (funcall fn)) (unless (or (and *suppress-compiler-warnings* (zerop errors)) (and (zerop (+ errors warnings style-warnings)) (null *undefined-functions*))) (format *error-output* "~%; Compilation unit finished~%") (unless (zerop errors) (format *error-output* "; Caught ~D ERROR condition~P~%" errors errors)) (unless *suppress-compiler-warnings* (unless (zerop warnings) (format *error-output* "; Caught ~D WARNING condition~P~%" warnings warnings)) (unless (zerop style-warnings) (format *error-output* "; Caught ~D STYLE-WARNING condition~P~%" style-warnings style-warnings)) (when *undefined-functions* (format *error-output* "; The following functions were used but not defined:~%") (dolist (name *undefined-functions*) (format *error-output* "; ~S~%" name)))) (terpri *error-output*)))))) (defun %jvm-compile (name definition expr env) ;; This function is part of the call chain from COMPILE, but ;; not COMPILE-FILE (let* (compiled-function (*memory-class-loader* (sys::make-memory-class-loader))) (with-compilation-unit () (with-saved-compiler-policy (setf compiled-function (with-open-stream (s (sys::%make-byte-array-output-stream)) (let* ((class-file (compile-defun name expr env nil s nil)) (bytes (progn (finish-output s) (sys::%get-output-stream-bytes s))) (class-name (class-name-internal (abcl-class-file-class-name class-file)))) (sys::put-memory-function *memory-class-loader* class-name bytes) (sys::get-memory-function *memory-class-loader* class-name)))))) (when (and name (functionp compiled-function)) (sys::set-function-definition name compiled-function definition)) (or name compiled-function))) (defun jvm-compile (name &optional definition) ;; This function is part of the call chain from COMPILE, but ;; not COMPILE-FILE (unless definition (resolve name) ;; Make sure the symbol has been resolved by the autoloader (setf definition (fdefinition name))) (when (compiled-function-p definition) (return-from jvm-compile (values (or name definition) nil nil))) (let ((catch-errors *catch-errors*) (warnings-p nil) (failure-p nil) (*package* (or (and name (symbol-package name)) *package*)) (expression definition) (*file-compilation* nil) (*visible-variables* nil) (*local-functions* nil) (*pathnames-generator* (constantly nil)) environment) (unless (and (consp definition) (eq (car definition) 'LAMBDA)) (let ((function definition)) (when (typep definition 'mop:funcallable-standard-object) (setf function (mop::funcallable-instance-function function))) (multiple-value-setq (expression environment) (function-lambda-expression function)))) (unless expression (error "Can't find a definition for ~S." definition)) (when environment (dolist (var (reverse (environment-all-variables environment))) ;; We need to add all variables, even symbol macros, ;; because the latter may shadow other variables by the same name ;; The precompiler should have resolved all symbol-macros, so ;; later we assert we didn't get any references to the symbol-macro. (push (make-variable :name (if (symbolp var) var (car var)) :special-p (symbolp var) :environment environment :references-allowed-p (not (sys:symbol-macro-p (cdr var))) :compiland NIL) *visible-variables*)) (dolist (fun (reverse (environment-all-functions environment))) (push (make-local-function :name (car fun) :references-allowed-p (not (macro-function-p (cdr fun))) :environment environment) *local-functions*))) (handler-bind ((compiler-unsupported-feature-error #'(lambda (c) (when catch-errors (fresh-line) (sys::%format t "; UNSUPPORTED FEATURE: ~A~%" c) (sys::%format t "; Unable to compile ~S.~%" (or name "top-level form")) (return-from jvm-compile (sys:precompile name definition))))) (style-warning #'(lambda (c) (declare (ignore c)) (setf warnings-p t) nil)) ((or warning compiler-error) #'(lambda (c) (declare (ignore c)) (setf warnings-p t failure-p t) nil))) (values (%jvm-compile name definition expression environment) warnings-p failure-p)))) (defvar *file-compilation* nil) (defvar *pathnames-generator* #'make-temp-file) (defun compile (name &optional definition) (jvm-compile name definition)) (defmacro with-file-compilation (&body body) `(let ((*file-compilation* t) (*pathnames-generator* #'sys::next-classfile)) ,@body)) (defun initialize-p2-handlers () (mapc #'install-p2-handler '(declare multiple-value-call multiple-value-list multiple-value-prog1 nth progn)) (install-p2-handler '%ldb 'p2-%ldb) (install-p2-handler '* 'p2-times) (install-p2-handler '+ 'p2-plus) (install-p2-handler '- 'p2-minus) (install-p2-handler '< 'p2-numeric-comparison) (install-p2-handler '<= 'p2-numeric-comparison) (install-p2-handler '= 'p2-numeric-comparison) (install-p2-handler '> 'p2-numeric-comparison) (install-p2-handler '>= 'p2-numeric-comparison) (install-p2-handler 'and 'p2-and) (install-p2-handler 'aref 'p2-aref) (install-p2-handler 'aset 'p2-aset) (install-p2-handler 'ash 'p2-ash) (install-p2-handler 'atom 'p2-atom) (install-p2-handler 'bit-vector-p 'p2-bit-vector-p) (install-p2-handler 'car 'p2-car) (install-p2-handler 'cdr 'p2-cdr) (install-p2-handler 'char 'p2-char/schar) (install-p2-handler 'char-code 'p2-char-code) (install-p2-handler 'java:jclass 'p2-java-jclass) (install-p2-handler 'java:jconstructor 'p2-java-jconstructor) (install-p2-handler 'java:jmethod 'p2-java-jmethod) ; (install-p2-handler 'java:jcall 'p2-java-jcall) (install-p2-handler 'char= 'p2-char=) (install-p2-handler 'characterp 'p2-characterp) (install-p2-handler 'coerce-to-function 'p2-coerce-to-function) (install-p2-handler 'cons 'p2-cons) (install-p2-handler 'sys::backq-cons 'p2-cons) (install-p2-handler 'consp 'p2-consp) (install-p2-handler 'delete 'p2-delete) (install-p2-handler 'elt 'p2-elt) (install-p2-handler 'eq 'p2-eq/neq) (install-p2-handler 'eql 'p2-eql) (install-p2-handler 'eval-when 'p2-eval-when) (install-p2-handler 'find-class 'p2-find-class) (install-p2-handler 'fixnump 'p2-fixnump) (install-p2-handler 'funcall 'p2-funcall) (install-p2-handler 'function 'p2-function) (install-p2-handler 'gensym 'p2-gensym) (install-p2-handler 'get 'p2-get) (install-p2-handler 'getf 'p2-getf) (install-p2-handler 'gethash 'p2-gethash) (install-p2-handler 'gethash1 'p2-gethash) (install-p2-handler 'go 'p2-go) (install-p2-handler 'if 'p2-if) (install-p2-handler 'sys::%length 'p2-length) (install-p2-handler 'list 'p2-list) (install-p2-handler 'sys::backq-list 'p2-list) (install-p2-handler 'list* 'p2-list*) (install-p2-handler 'sys::backq-list* 'p2-list*) (install-p2-handler 'load-time-value 'p2-load-time-value) (install-p2-handler 'logand 'p2-logand) (install-p2-handler 'logior 'p2-logior) (install-p2-handler 'lognot 'p2-lognot) (install-p2-handler 'logxor 'p2-logxor) (install-p2-handler 'max 'p2-min/max) (install-p2-handler 'memq 'p2-memq) (install-p2-handler 'memql 'p2-memql) (install-p2-handler 'min 'p2-min/max) (install-p2-handler 'mod 'p2-mod) (install-p2-handler 'neq 'p2-eq/neq) (install-p2-handler 'not 'p2-not/null) (install-p2-handler 'nthcdr 'p2-nthcdr) (install-p2-handler 'null 'p2-not/null) (install-p2-handler 'or 'p2-or) (install-p2-handler 'packagep 'p2-packagep) (install-p2-handler 'puthash 'p2-puthash) (install-p2-handler 'quote 'p2-quote) (install-p2-handler 'read-line 'p2-read-line) (install-p2-handler 'readtablep 'p2-readtablep) (install-p2-handler 'return-from 'p2-return-from) (install-p2-handler 'rplacd 'p2-rplacd) (install-p2-handler 'schar 'p2-char/schar) (install-p2-handler 'set 'p2-set) (install-p2-handler 'set-car 'p2-set-car/cdr) (install-p2-handler 'set-cdr 'p2-set-car/cdr) (install-p2-handler 'set-char 'p2-set-char/schar) (install-p2-handler 'set-schar 'p2-set-char/schar) (install-p2-handler 'set-std-slot-value 'p2-set-std-slot-value) (install-p2-handler 'setq 'p2-setq) (install-p2-handler 'simple-vector-p 'p2-simple-vector-p) (install-p2-handler 'std-slot-value 'p2-std-slot-value) (install-p2-handler 'stream-element-type 'p2-stream-element-type) (install-p2-handler 'stringp 'p2-stringp) (install-p2-handler 'structure-ref 'p2-structure-ref) (install-p2-handler 'structure-set 'p2-structure-set) (install-p2-handler 'svref 'p2-svref) (install-p2-handler 'svset 'p2-svset) (install-p2-handler 'sxhash 'p2-sxhash) (install-p2-handler 'symbol-name 'p2-symbol-name) (install-p2-handler 'symbol-package 'p2-symbol-package) (install-p2-handler 'symbol-value 'p2-symbol-value) (install-p2-handler 'symbolp 'p2-symbolp) (install-p2-handler 'the 'p2-the) (install-p2-handler 'throw 'p2-throw) (install-p2-handler 'truly-the 'p2-truly-the) (install-p2-handler 'truncate 'p2-truncate) (install-p2-handler 'values 'p2-values) (install-p2-handler 'vectorp 'p2-vectorp) (install-p2-handler 'vector-push-extend 'p2-vector-push-extend) (install-p2-handler 'write-8-bits 'p2-write-8-bits) (install-p2-handler 'zerop 'p2-zerop) (install-p2-handler 'with-inline-code 'p2-with-inline-code) t) (initialize-p2-handlers) (defvar sys:*enable-autocompile*) (defun sys:autocompile (function) (when sys:*enable-autocompile* (let ((sys:*enable-autocompile* nil)) (values (compile nil function))))) (setf sys:*enable-autocompile* t) (provide "COMPILER-PASS2") abcl-src-1.9.0/src/org/armedbear/lisp/compiler-types.lisp0100644 0000000 0000000 00000023605 14202767264 022072 0ustar000000000 0000000 ;;; compiler-types.lisp ;;; ;;; Copyright (C) 2005-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Type information that matters to the compiler. (in-package #:system) (export '(+true-type+ +false-type+ integer-type-low integer-type-high integer-type-p %make-integer-type make-integer-type +fixnum-type+ +integer-type+ fixnum-type-p fixnum-constant-value integer-constant-value java-long-type-p make-compiler-type compiler-subtypep function-result-type defknown)) (defstruct constant-type value) (defconst +true-type+ (make-constant-type :value t)) (defconst +false-type+ (make-constant-type :value nil)) (defstruct (integer-type (:constructor %make-integer-type (low high))) low high) (defmethod print-object ((type integer-type) stream) (print-unreadable-object (type stream :type t :identity t) (format stream "~D ~D" (integer-type-low type) (integer-type-high type)))) (defconstant +fixnum-type+ (%make-integer-type most-negative-fixnum most-positive-fixnum)) (defconstant +integer-type+ (%make-integer-type nil nil)) (declaim (ftype (function (t) t) make-integer-type)) (defun make-integer-type (type) (if (integer-type-p type) type (cond ((eq type 'FIXNUM) +fixnum-type+) ((eq type 'INTEGER) +integer-type+) (t (setf type (normalize-type type)) (when (and (consp type) (eq (%car type) 'INTEGER)) (let ((low (second type)) (high (third type))) (if (eq low '*) (setf low nil) (when (and (consp low) (integerp (%car low))) (setf low (1+ (%car low))))) (if (eq high '*) (setf high nil) (when (and (consp high) (integerp (%car high))) (setf high (1- (%car high))))) (%make-integer-type low high))))))) (declaim (ftype (function (t) t) fixnum-type-p)) (defun fixnum-type-p (compiler-type) (and (integer-type-p compiler-type) (fixnump (integer-type-low compiler-type)) (fixnump (integer-type-high compiler-type)))) (declaim (ftype (function (t) t) fixnum-constant-value)) (defun fixnum-constant-value (compiler-type) (when (and compiler-type (integer-type-p compiler-type)) (let ((low (integer-type-low compiler-type)) high) (when (fixnump low) (setf high (integer-type-high compiler-type)) (when (and (fixnump high) (= high low)) high))))) (declaim (ftype (function (t) t) integer-constant-value)) (defun integer-constant-value (compiler-type) (when (and compiler-type (integer-type-p compiler-type)) (let ((low (integer-type-low compiler-type)) high) (when (integerp low) (setf high (integer-type-high compiler-type)) (when (and (integerp high) (= high low)) high))))) (declaim (ftype (function (t) t) java-long-type-p)) (defun java-long-type-p (compiler-type) (and (integer-type-p compiler-type) (typep (integer-type-low compiler-type) (list 'INTEGER most-negative-java-long most-positive-java-long)) (typep (integer-type-high compiler-type) (list 'INTEGER most-negative-java-long most-positive-java-long)))) (declaim (ftype (function (t t) t) make-union-type)) (defun make-union-type (type1 type2) (cond ((and (integer-type-p type1) (integer-type-p type2)) (let ((low1 (integer-type-low type1)) (low2 (integer-type-low type2)) (high1 (integer-type-high type1)) (high2 (integer-type-high type2))) (if (and low1 low2 high1 high2) (%make-integer-type (min low1 low2) (max high1 high2)) +integer-type+))) (t t))) (declaim (ftype (function (t) t) make-compiler-type)) (defun make-compiler-type (typespec) (cond ((integer-type-p typespec) typespec) ((constant-type-p typespec) typespec) ((eq typespec 'SINGLE-FLOAT) 'SINGLE-FLOAT) ((eq typespec 'DOUBLE-FLOAT) 'DOUBLE-FLOAT) ((and (consp typespec) (eq (%car typespec) 'SINGLE-FLOAT)) 'SINGLE-FLOAT) ((and (consp typespec) (eq (%car typespec) 'DOUBLE-FLOAT)) 'DOUBLE-FLOAT) (t (let ((type (normalize-type typespec))) (cond ((consp type) (let ((car (%car type))) (cond ((eq car 'INTEGER) (make-integer-type type)) ((eq car 'SINGLE-FLOAT) 'SINGLE-FLOAT) ((eq car 'DOUBLE-FLOAT) 'DOUBLE-FLOAT) ((memq car '(STRING SIMPLE-STRING LIST)) car) ((memq car '(VECTOR SIMPLE-VECTOR ARRAY SIMPLE-ARRAY)) type) ((eq car 'OR) (case (length (cdr type)) (1 (make-compiler-type (second type))) (2 (make-union-type (make-compiler-type (second type)) (make-compiler-type (third type)))) (t t))) ((subtypep type 'FIXNUM) +fixnum-type+) (t t)))) ((memq type '(BOOLEAN CHARACTER HASH-TABLE STREAM SYMBOL)) type) ((eq type 'INTEGER) (%make-integer-type nil nil)) (t t)))))) (defun integer-type-subtypep (type1 typespec) (if (eq typespec 'INTEGER) t (let ((type2 (make-integer-type typespec))) (when type2 (let ((low1 (integer-type-low type1)) (high1 (integer-type-high type1)) (low2 (integer-type-low type2)) (high2 (integer-type-high type2))) (cond ((and low1 low2 high1 high2) (and (>= low1 low2) (<= high1 high2))) ((and low1 low2 (< low1 low2)) nil) ((and high1 high2) (> high1 high2) nil) ((and (null low1) low2) nil) ((and (null high1) high2) nil) (t t))))))) (declaim (ftype (function (t t) t) compiler-subtypep)) (defun compiler-subtypep (compiler-type typespec) (cond ((eq typespec t) t) ((eq compiler-type t) nil) ((eq compiler-type typespec) t) ((eq typespec 'STRING) (eq compiler-type 'SIMPLE-STRING)) ((integer-type-p compiler-type) (integer-type-subtypep compiler-type typespec)) (t (values (subtypep compiler-type typespec))))) (declaim (type hash-table *function-result-types*)) (defvar *function-result-types* (make-hash-table :test 'equal)) (declaim (ftype (function (t) t) function-result-type)) (defun function-result-type (name) (if (symbolp name) (get name 'function-result-type) (gethash1 name *function-result-types*))) (declaim (ftype (function (t t) t) set-function-result-type)) (defun set-function-result-type (name result-type) (if (symbolp name) (setf (get name 'function-result-type) result-type) (setf (gethash name *function-result-types*) result-type))) (defun %defknown (name-or-names argument-types result-type) (let ((ftype `(function ,argument-types ,result-type)) (result-type (make-compiler-type result-type))) (cond ((or (symbolp name-or-names) (setf-function-name-p name-or-names)) (proclaim-ftype-1 ftype name-or-names) (set-function-result-type name-or-names result-type)) (t (proclaim-ftype ftype name-or-names) (dolist (name name-or-names) (set-function-result-type name result-type))))) name-or-names) (defmacro defknown (name-or-names argument-types result-type) `(eval-when (:compile-toplevel :load-toplevel :execute) (%defknown ',name-or-names ',argument-types ',result-type))) (provide '#:compiler-types) abcl-src-1.9.0/src/org/armedbear/lisp/concatenate.lisp0100644 0000000 0000000 00000005605 14202767264 021402 0ustar000000000 0000000 ;;; concatenate.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun concatenate-to-string (sequences) (declare (optimize speed (safety 0))) (let ((length 0)) (declare (type fixnum length)) (dolist (seq sequences) (incf length (length seq))) (let ((result (make-string length)) (i 0)) (declare (type index i)) (dolist (seq sequences result) (if (stringp seq) (dotimes (j (length seq)) (declare (type index j)) (setf (schar result i) (char (truly-the string seq) j)) (incf i)) (dotimes (j (length seq)) (declare (type index j)) (setf (schar result i) (elt seq j)) (incf i))))))) ;;It uses make-sequence: it should already be user-extensible as-is (defun concatenate (result-type &rest sequences) (case result-type (LIST (let ((result ())) (dolist (seq sequences (nreverse result)) (dotimes (i (length seq)) (push (elt seq i) result))))) ((STRING SIMPLE-STRING) (concatenate-to-string sequences)) (t (let* ((length (apply '+ (mapcar 'length sequences))) (result (make-sequence result-type length)) (i 0)) (declare (type index i)) (dolist (seq sequences result) (dotimes (j (length seq)) (setf (elt result i) (elt seq j)) (incf i))))))) abcl-src-1.9.0/src/org/armedbear/lisp/cond.lisp0100644 0000000 0000000 00000004175 14223403213 020022 0ustar000000000 0000000 ;;; cond.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defmacro cond (&rest clauses) (if (endp clauses) nil (let ((clause (first clauses))) (when (atom clause) (error "COND clause is not a list: ~S" clause)) (let ((test (first clause)) (forms (rest clause))) (if (endp forms) (let ((n-result (gensym))) `(let ((,n-result ,test)) (if ,n-result ,n-result (cond ,@(rest clauses))))) `(if ,test (progn ,@forms) (cond ,@(rest clauses)))))))) abcl-src-1.9.0/src/org/armedbear/lisp/copy-seq.lisp0100644 0000000 0000000 00000004651 14223403213 020636 0ustar000000000 0000000 ;;; copy-seq.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (require "EXTENSIBLE-SEQUENCES-BASE") (in-package "SYSTEM") ;; From CMUCL. (defmacro vector-copy-seq (sequence type) `(let ((length (length ,sequence))) (do ((index 0 (1+ index)) (copy (make-sequence-of-type ,type length))) ((= index length) copy) (aset copy index (aref ,sequence index))))) (defmacro list-copy-seq (list) `(if (atom ,list) '() (let ((result (cons (car ,list) '()) )) (do ((x (cdr ,list) (cdr x)) (splice result (cdr (rplacd splice (cons (car x) '() ))) )) ((atom x) (unless (null x) (rplacd splice x)) result))))) (defun copy-seq (sequence) "Return a copy of SEQUENCE which is EQUAL to SEQUENCE but not EQ." (sequence::seq-dispatch sequence (list-copy-seq sequence) (vector-copy-seq sequence (type-of sequence)) (sequence:copy-seq sequence))) abcl-src-1.9.0/src/org/armedbear/lisp/copy-symbol.lisp0100644 0000000 0000000 00000003767 14202767264 021402 0ustar000000000 0000000 ;;; copy-symbol.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) ;;; From CMUCL. (defun copy-symbol (symbol &optional (copy-props nil) &aux new-symbol) (declare (type symbol symbol)) (setq new-symbol (make-symbol (symbol-name symbol))) (when copy-props (when (boundp symbol) (set new-symbol (symbol-value symbol))) (setf (symbol-plist new-symbol) (copy-list (symbol-plist symbol))) (when (fboundp symbol) (setf (symbol-function new-symbol) (symbol-function symbol)))) new-symbol) abcl-src-1.9.0/src/org/armedbear/lisp/copy_list.java0100644 0000000 0000000 00000004305 14202767264 021071 0ustar000000000 0000000 /* * copy_list.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### copy-list list => copy public final class copy_list extends Primitive { private copy_list() { super(Symbol.COPY_LIST, "list"); } @Override public LispObject execute(LispObject arg) { if (arg == NIL) return NIL; Cons result = new Cons(arg.car()); Cons splice = result; arg = arg.cdr(); while (arg instanceof Cons) { Cons cons = (Cons) arg; Cons temp = new Cons(cons.car); splice.cdr = temp; splice = temp; arg = cons.cdr; } splice.cdr = arg; return result; } private static final Primitive COPY_LIST = new copy_list(); }; abcl-src-1.9.0/src/org/armedbear/lisp/count.lisp0100644 0000000 0000000 00000010626 14223403213 020225 0ustar000000000 0000000 ;;; count.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "COMMON-LISP") (require "EXTENSIBLE-SEQUENCES-BASE") ;;; From CMUCL. (defmacro vector-count-if (not-p from-end-p predicate sequence) (let ((next-index (if from-end-p '(1- index) '(1+ index))) (pred `(funcall ,predicate (sys::apply-key key (aref ,sequence index))))) `(let ((%start ,(if from-end-p '(1- end) 'start)) (%end ,(if from-end-p '(1- start) 'end))) (do ((index %start ,next-index) (count 0)) ((= index %end) count) (,(if not-p 'unless 'when) ,pred (setq count (1+ count))))))) (defmacro list-count-if (not-p from-end-p predicate sequence) (let ((pred `(funcall ,predicate (sys::apply-key key (pop sequence))))) `(let ((%start ,(if from-end-p '(- length end) 'start)) (%end ,(if from-end-p '(- length start) 'end)) (sequence ,(if from-end-p '(reverse sequence) 'sequence))) (do ((sequence (nthcdr %start ,sequence)) (index %start (1+ index)) (count 0)) ((or (= index %end) (null sequence)) count) (,(if not-p 'unless 'when) ,pred (setq count (1+ count))))))) (defun count (item sequence &rest args &key from-end (test #'eql test-p) (test-not nil test-not-p) (start 0) end key) (when (and test-p test-not-p) (error "test and test-not both supplied")) (let* ((length (length sequence)) (end (or end length))) (let ((%test (if test-not-p (lambda (x) (not (funcall test-not item x))) (lambda (x) (funcall test item x))))) (sequence::seq-dispatch sequence (if from-end (list-count-if nil t %test sequence) (list-count-if nil nil %test sequence)) (if from-end (vector-count-if nil t %test sequence) (vector-count-if nil nil %test sequence)) (apply #'sequence:count item sequence args))))) (defun count-if (test sequence &rest args &key from-end (start 0) end key) (let* ((length (length sequence)) (end (or end length))) (sequence::seq-dispatch sequence (if from-end (list-count-if nil t test sequence) (list-count-if nil nil test sequence)) (if from-end (vector-count-if nil t test sequence) (vector-count-if nil nil test sequence)) (apply #'sequence:count-if test sequence args)))) (defun count-if-not (test sequence &rest args &key from-end (start 0) end key) (let* ((length (length sequence)) (end (or end length))) (sequence::seq-dispatch sequence (if from-end (list-count-if t t test sequence) (list-count-if t nil test sequence)) (if from-end (vector-count-if t t test sequence) (vector-count-if t nil test sequence)) (apply #'sequence:count-if-not test sequence args)))) abcl-src-1.9.0/src/org/armedbear/lisp/create_new_file.java0100644 0000000 0000000 00000004312 14202767264 022175 0ustar000000000 0000000 /* * create_new_file.java * * Copyright (C) 2004-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.IOException; // ### create-new-file public final class create_new_file extends Primitive { private create_new_file() { super("create-new-file", PACKAGE_SYS, true, "namestring"); } @Override public LispObject execute(LispObject arg) { final String namestring = arg.getStringValue(); try { return new File(namestring).createNewFile() ? T : NIL; } catch (IOException e) { return error(new StreamError(null, e)); } } private static final Primitive CREATE_NEW_FILE = new create_new_file(); } abcl-src-1.9.0/src/org/armedbear/lisp/cxr.java0100644 0000000 0000000 00000021042 14202767264 017655 0ustar000000000 0000000 /* * cxr.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class cxr { // ### set-car private static final Primitive SET_CAR = new pf_set_car(); private static final class pf_set_car extends Primitive { pf_set_car() { super("set-car", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { first.setCar(second); return second; } }; // ### set-cdr private static final Primitive SET_CDR = new pf_set_cdr(); private static final class pf_set_cdr extends Primitive { pf_set_cdr() { super("set-cdr", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { first.setCdr(second); return second; } }; // ### car private static final Primitive CAR = new pf_car(); private static final class pf_car extends Primitive { pf_car() { super(Symbol.CAR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.car(); } }; // ### cdr private static final Primitive CDR = new pf_cdr(); private static final class pf_cdr extends Primitive { pf_cdr() { super(Symbol.CDR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cdr(); } }; // ### caar private static final Primitive CAAR = new pf_caar(); private static final class pf_caar extends Primitive { pf_caar() { super(Symbol.CAAR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.car().car(); } }; // ### cadr private static final Primitive CADR = new pf_cadr(); private static final class pf_cadr extends Primitive { pf_cadr() { super(Symbol.CADR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cadr(); } }; // ### cdar private static final Primitive CDAR = new pf_cdar(); private static final class pf_cdar extends Primitive { pf_cdar() { super(Symbol.CDAR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.car().cdr(); } }; // ### cddr private static final Primitive CDDR = new pf_cddr(); private static final class pf_cddr extends Primitive { pf_cddr() { super(Symbol.CDDR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cdr().cdr(); } }; // ### caddr private static final Primitive CADDR = new pf_caddr(); private static final class pf_caddr extends Primitive { pf_caddr() { super(Symbol.CADDR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.caddr(); } }; // ### caadr private static final Primitive CAADR = new pf_caadr(); private static final class pf_caadr extends Primitive { pf_caadr() { super(Symbol.CAADR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cdr().car().car(); } }; // ### caaar private static final Primitive CAAAR = new pf_caaar(); private static final class pf_caaar extends Primitive { pf_caaar() { super(Symbol.CAAAR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.car().car().car(); } }; // ### cdaar private static final Primitive CDAAR = new pf_cdaar(); private static final class pf_cdaar extends Primitive { pf_cdaar() { super(Symbol.CDAAR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.car().car().cdr(); } }; // ### cddar private static final Primitive CDDAR = new pf_cddar(); private static final class pf_cddar extends Primitive { pf_cddar() { super(Symbol.CDDAR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.car().cdr().cdr(); } }; // ### cdddr private static final Primitive CDDDR = new pf_cdddr(); private static final class pf_cdddr extends Primitive { pf_cdddr() { super(Symbol.CDDDR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cdr().cdr().cdr(); } }; // ### cadar private static final Primitive CADAR = new pf_cadar(); private static final class pf_cadar extends Primitive { pf_cadar() { super(Symbol.CADAR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.car().cdr().car(); } }; // ### cdadr private static final Primitive CDADR = new pf_cdadr(); private static final class pf_cdadr extends Primitive { pf_cdadr() { super(Symbol.CDADR, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cdr().car().cdr(); } }; // ### first private static final Primitive FIRST = new pf_first(); private static final class pf_first extends Primitive { pf_first() { super(Symbol.FIRST, "list"); } @Override public LispObject execute(LispObject arg) { return arg.car(); } }; // ### second private static final Primitive SECOND = new pf_second(); private static final class pf_second extends Primitive { pf_second() { super(Symbol.SECOND, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cadr(); } }; // ### third private static final Primitive THIRD = new pf_third(); private static final class pf_third extends Primitive { pf_third() { super(Symbol.THIRD, "list"); } @Override public LispObject execute(LispObject arg) { return arg.caddr(); } }; // ### fourth private static final Primitive FOURTH = new pf_fourth(); private static final class pf_fourth extends Primitive { pf_fourth() { super(Symbol.FOURTH, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cdr().cdr().cadr(); } }; // ### rest private static final Primitive REST = new pf_rest(); private static final class pf_rest extends Primitive { pf_rest() { super(Symbol.REST, "list"); } @Override public LispObject execute(LispObject arg) { return arg.cdr(); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/debug.lisp0100644 0000000 0000000 00000013712 14223403213 020162 0ustar000000000 0000000 ;;; debug.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:extensions) (export '(*debug-condition* *debug-level* show-restarts)) (defvar *debug-condition* nil) (defvar *debug-level* 0) (in-package #:system) (defun show-restarts (restarts stream) (when restarts (fresh-line stream) (%format stream "Restarts:~%") (let ((max-name-len 0)) (dolist (restart restarts) (let ((name (restart-name restart))) (when name (let ((len (length (princ-to-string name)))) (when (> len max-name-len) (setf max-name-len len)))))) (let ((count 0)) (dolist (restart restarts) (let ((name (restart-name restart)) (report-function (restart-report-function restart))) (%format stream " ~D: ~A" count name) (when (functionp report-function) (dotimes (i (1+ (- max-name-len (length (princ-to-string name))))) (write-char #\space stream)) (funcall report-function stream)) (terpri stream)) (incf count)))))) (defun internal-debug () (if (fboundp 'tpl::repl) (let* ((current-debug-io (if (typep *debug-io* 'synonym-stream) (symbol-value (synonym-stream-symbol *debug-io*)) *debug-io*)) (in (two-way-stream-input-stream current-debug-io)) (out (two-way-stream-output-stream current-debug-io))) (loop (tpl::repl in out))) (quit))) (defun debug-loop () (let ((*debug-level* (1+ *debug-level*))) (show-restarts (compute-restarts) *debug-io*) (internal-debug))) (defun invoke-debugger-report-condition (condition) (when condition (fresh-line *debug-io*) (with-standard-io-syntax (let ((*print-structure* nil) (*print-readably* nil)) (when (and *load-truename* (streamp *load-stream*)) (simple-format *debug-io* "Error loading ~A at line ~D (offset ~D)~%" *load-truename* (stream-line-number *load-stream*) (stream-offset *load-stream*))) (simple-format *debug-io* (if (fboundp 'tpl::repl) "~S: Debugger invoked on condition of type ~A~%" "~S: Unhandled condition of type ~A:~%") (threads:current-thread) (type-of condition)) (simple-format *debug-io* " ~A~%" condition))))) (declaim (inline run-hook)) (defun run-hook (hook &rest args) (let ((hook-function (symbol-value hook))) (when hook-function (progv (list hook) (list nil) (apply hook-function args))))) (defvar *invoke-debugger-hook* nil "Like *DEBUGGER-HOOK* but observed by INVOKE-DEBUGGER even when called by BREAK. This hook is run before *DEBUGGER-HOOK*.") ;;; We run *INVOKE-DEBUGGER-HOOK* before *DEBUGGER-HOOK* because SBCL ;;; does so, too, and for good reason: This way, you can specify ;;; default debugger behaviour that trumps over whatever the users ;;; wants to do with *DEBUGGER-HOOK*. (defun invoke-debugger (condition) (let ((*saved-backtrace* (sys:backtrace))) (run-hook '*invoke-debugger-hook* condition *invoke-debugger-hook*) (run-hook '*debugger-hook* condition *debugger-hook*) (invoke-debugger-report-condition condition) (unless (fboundp 'tpl::repl) (quit)) (let ((original-package *package*)) (with-standard-io-syntax (let ((*package* original-package) (*print-readably* nil) ; Top-level default. (*print-structure* nil) (*debug-condition* condition) (level *debug-level*)) (clear-input *debug-io*) (if (> level 0) (with-simple-restart (abort "Return to debug level ~D." level) (debug-loop)) (debug-loop))))))) (defun break (&optional (format-control "BREAK called") &rest format-arguments) (let ((*debugger-hook* nil)) ; Specifically required by ANSI. (with-simple-restart (continue "Return from BREAK.") (invoke-debugger (%make-condition 'simple-condition (list :format-control format-control :format-arguments format-arguments)))) nil)) (defun backtrace-as-list (&optional (n 0)) "Return BACKTRACE with each element converted to a list." (mapcar #'sys::frame-to-list (sys:backtrace n))) abcl-src-1.9.0/src/org/armedbear/lisp/define-modify-macro.lisp0100644 0000000 0000000 00000012114 14223403213 022705 0ustar000000000 0000000 ;;; define-modify-macro.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) ;; FIXME See section 5.1.3. (defmacro define-modify-macro (name lambda-list function &optional doc-string) "Creates a new read-modify-write macro like PUSH or INCF." (let ((other-args nil) (rest-arg nil) (env (gensym)) (reference (gensym))) ;; Parse out the variable names and &REST arg from the lambda list. (do ((ll lambda-list (cdr ll)) (arg nil)) ((null ll)) (setq arg (car ll)) (cond ((eq arg '&optional)) ((eq arg '&rest) (if (symbolp (cadr ll)) (setq rest-arg (cadr ll)) (error "Non-symbol &REST arg in definition of ~S." name)) (if (null (cddr ll)) (return nil) (error "Illegal stuff after &REST argument in DEFINE-MODIFY-MACRO."))) ((memq arg '(&key &allow-other-keys &aux)) (error "~S not allowed in DEFINE-MODIFY-MACRO lambda list." arg)) ((symbolp arg) (push arg other-args)) ((and (listp arg) (symbolp (car arg))) (push (car arg) other-args)) (t (error "Illegal stuff in DEFINE-MODIFY-MACRO lambda list.")))) (setq other-args (nreverse other-args)) `(eval-when (:compile-toplevel :load-toplevel :execute) (defmacro ,name (,reference ,@lambda-list &environment ,env) ,doc-string (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion ,reference ,env) (do ((d dummies (cdr d)) (v vals (cdr v)) (let-list nil (cons (list (car d) (car v)) let-list))) ((null d) (push (list (car newval) ,(if rest-arg `(list* ',function getter ,@other-args ,rest-arg) `(list ',function getter ,@other-args))) let-list) `(let* ,(nreverse let-list) ,setter)))))))) (define-modify-macro incf-complex (&optional (delta 1)) + "The first argument is some location holding a number. This number is incremented by the second argument, DELTA, which defaults to 1.") (define-modify-macro decf-complex (&optional (delta 1)) - "The first argument is some location holding a number. This number is decremented by the second argument, DELTA, which defaults to 1.") (defmacro incf (place &optional (delta 1)) (cond ((symbolp place) (cond ((constantp delta) `(setq ,place (+ ,place ,delta))) (t ;; See section 5.1.3. (let ((temp (gensym))) `(let ((,temp ,delta)) (setq ,place (+ ,place ,temp))))))) ((and (consp place) (eq (car place) 'THE)) (let ((res (gensym))) `(let ((,res (the ,(second place) (+ ,place ,delta)))) (setf ,(third place) ,res)))) (t `(incf-complex ,place ,delta)))) (defmacro decf (place &optional (delta 1)) (cond ((symbolp place) (cond ((constantp delta) `(setq ,place (- ,place ,delta))) (t ;; See section 5.1.3. (let ((temp (gensym))) `(let ((,temp ,delta)) (setq ,place (- ,place ,temp))))))) ((and (consp place) (eq (car place) 'THE)) (let ((res (gensym))) `(let ((,res (the ,(second place) (- ,place ,delta)))) (setf ,(third place) ,res)))) (t `(decf-complex ,place ,delta)))) abcl-src-1.9.0/src/org/armedbear/lisp/define-symbol-macro.lisp0100644 0000000 0000000 00000004175 14202767264 022753 0ustar000000000 0000000 ;;; define-symbol-macro.lisp ;;; ;;; Copyright (C) 2003-2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun %define-symbol-macro (symbol expansion) (%set-symbol-macro symbol (make-symbol-macro expansion)) symbol) (defmacro define-symbol-macro (symbol expansion) (when (special-variable-p symbol) ;;TODO astalla also check local declarations? (error 'program-error "~S has already been defined as a global variable." symbol)) `(eval-when (:compile-toplevel :load-toplevel :execute) (record-source-information-for-type ',symbol :symbol-macro) (record-source-information-for-type ',symbol :symbol-macro) (%define-symbol-macro ',symbol ',expansion))) abcl-src-1.9.0/src/org/armedbear/lisp/defmacro.lisp0100644 0000000 0000000 00000005023 14223403213 020650 0ustar000000000 0000000 ;;; defmacro.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id: defmacro.lisp 13696 2011-11-15 22:34:19Z astalla $ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;;; Adapted from CMUCL/SBCL. (in-package #:system) ;; Redefine DEFMACRO to use PARSE-DEFMACRO. (defmacro defmacro (name lambda-list &rest body) (let* ((whole (gensym "WHOLE-")) (env (gensym "ENVIRONMENT-"))) (multiple-value-bind (body decls documentation) (parse-defmacro lambda-list whole body name 'defmacro :environment env) (let ((expander `(lambda (,whole ,env) ,@decls ,body))) `(progn (sys::record-source-information-for-type ',name :macro) (let ((macro (make-macro ',name (or (precompile nil ,expander) ,expander)))) ,@(if (special-operator-p name) `((put ',name 'macroexpand-macro macro)) `((fset ',name macro))) (%set-arglist macro ',lambda-list) ,@(when documentation `((%set-documentation ',name 'cl:function ,documentation))) ',name)))))) abcl-src-1.9.0/src/org/armedbear/lisp/defpackage.lisp0100644 0000000 0000000 00000016023 14223403213 021144 0ustar000000000 0000000 ;;; defpackage.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") ;;; Adapted from CMUCL. (defun designated-package-name (designator) (cond ((packagep designator) (package-name designator)) (t (string designator)))) (defun stringify-names (names) (mapcar #'string names)) (defun check-disjoint (&rest args) (let ((rest-args args)) (dolist (arg1 args) (let ((key1 (car arg1)) (set1 (cdr arg1))) (setq rest-args (cdr rest-args)) (dolist (arg2 rest-args) (let* ((key2 (car arg2)) (set2 (cdr arg2)) (common (remove-duplicates (intersection set1 set2 :test #'string=)))) (when common (error 'program-error :format-control "Parameters ~S and ~S must be disjoint, but have common elements: ~S" :format-arguments (list key1 key2 common))))))))) (defun ensure-available-symbols (symbols) symbols) (defmacro defpackage (package &rest options) (let ((nicknames nil) (size nil) (shadows nil) (shadowing-imports nil) (use nil) (use-p nil) (imports nil) (interns nil) (exports nil) (local-nicknames nil) (doc nil)) (dolist (option options) (unless (consp option) (error 'program-error "bad DEFPACKAGE option: ~S" option)) (case (car option) (:nicknames (setq nicknames (stringify-names (cdr option)))) (:size (cond (size (error 'program-error "can't specify :SIZE twice")) ((and (consp (cdr option)) (typep (second option) 'unsigned-byte)) (setq size (second option))) (t (error 'program-error "bad :SIZE, must be a positive integer: ~S" (second option))))) (:shadow (let ((new (stringify-names (cdr option)))) (setq shadows (append shadows new)))) (:shadowing-import-from (let ((package-name (designated-package-name (cadr option))) (symbol-names (stringify-names (cddr option)))) (let ((assoc (assoc package-name shadowing-imports :test #'string=))) (if assoc (setf (cdr assoc) (append (cdr assoc) symbol-names)) (setq shadowing-imports (acons package-name symbol-names shadowing-imports)))))) (:use (let ((new (mapcar #'designated-package-name (cdr option)))) (setq use (delete-duplicates (nconc use new) :test #'string=)) (setq use-p t))) (:import-from (let ((package-name (designated-package-name (cadr option))) (symbol-names (stringify-names (cddr option)))) (let ((assoc (assoc package-name imports :test #'string=))) (if assoc (setf (cdr assoc) (append (cdr assoc) symbol-names)) (setq imports (acons package-name symbol-names imports)))))) (:intern (let ((new (stringify-names (cdr option)))) (setq interns (append interns new)))) (:export (let ((new (stringify-names (cdr option)))) (setq exports (append exports new)))) (:documentation (when doc (error 'program-error "can't specify :DOCUMENTATION twice")) (setq doc (coerce (cadr option) 'simple-string))) (:local-nicknames (dolist (nickdecl (cdr option)) (unless (= (length nickdecl) 2) (error 'program-error "Malformed local nickname declaration ~A" nickdecl)) (let ((local-nickname (string (first nickdecl))) (package-name (designated-package-name (second nickdecl)))) (when (member local-nickname '("CL" "COMMON-LISP" "KEYWORD") :test #'string=) (cerror "Continue anyway" (format nil "Trying to define a local nickname for package ~A" local-nickname))) (when (member local-nickname (list* package nicknames) :test #'string=) (cerror "Continue anyway" "Trying to override the name or a nickname (~A) ~ with a local nickname for another package ~A" local-nickname package-name)) (push (list local-nickname package-name) local-nicknames)))) (t (error 'program-error "bad DEFPACKAGE option: ~S" option)))) (check-disjoint `(:intern ,@interns) `(:export ,@exports)) (check-disjoint `(:intern ,@interns) `(:import-from ,@(apply #'append (mapcar #'rest imports))) `(:shadow ,@shadows) `(:shadowing-import-from ,@(apply #'append (mapcar #'rest shadowing-imports)))) `(prog1 (%defpackage ,(string package) ',nicknames ',size ',shadows (ensure-available-symbols ',shadowing-imports) ',(if use-p use nil) (ensure-available-symbols ',imports) ',interns ',exports ',local-nicknames ',doc) ,(when (and (symbolp package) (not (keywordp package))) `(record-source-information-for-type ',package :package)) (record-source-information-for-type ,(intern (string package) :keyword) :package) ))) abcl-src-1.9.0/src/org/armedbear/lisp/defsetf.lisp0100644 0000000 0000000 00000007444 14223403213 020521 0ustar000000000 0000000 ;;; defsetf.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (require '#:collect) (defun %defsetf (orig-access-form num-store-vars expander) (collect ((subforms) (subform-vars) (subform-exprs) (store-vars)) (dolist (subform (cdr orig-access-form)) (if (constantp subform) (subforms subform) (let ((var (gensym))) (subforms var) (subform-vars var) (subform-exprs subform)))) (dotimes (i num-store-vars) (store-vars (gensym))) (values (subform-vars) (subform-exprs) (store-vars) (funcall expander (cons (subforms) (store-vars))) `(,(car orig-access-form) ,@(subforms))))) (defmacro defsetf (access-fn &rest rest) (cond ((not (listp (car rest))) `(eval-when (:load-toplevel :compile-toplevel :execute) (%define-setf-macro ',access-fn nil ',(car rest) ,(when (and (car rest) (stringp (cadr rest))) `',(cadr rest))))) ((and (cdr rest) (listp (cadr rest))) (destructuring-bind (lambda-list (&rest store-variables) &body body) rest (let ((arglist-var (gensym "ARGS-")) (access-form-var (gensym "ACCESS-FORM-")) (env-var (gensym "ENVIRONMENT-"))) (multiple-value-bind (body doc) (parse-defmacro `(,lambda-list ,@store-variables) arglist-var body access-fn 'defsetf :anonymousp t) `(eval-when (:load-toplevel :compile-toplevel :execute) (%define-setf-macro ',access-fn #'(lambda (,access-form-var ,env-var) (declare (ignore ,env-var)) (%defsetf ,access-form-var ,(length store-variables) #'(lambda (,arglist-var) (block ,access-fn ,body)))) nil ',doc)))))) (t (error "Ill-formed DEFSETF for ~S" access-fn)))) abcl-src-1.9.0/src/org/armedbear/lisp/defstruct.lisp0100644 0000000 0000000 00000075300 14223403213 021100 0ustar000000000 0000000 ;;; defstruct.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (export 'compiler-defstruct) ;;; DEFSTRUCT-DESCRIPTION (defmacro dd-name (x) `(aref ,x 0)) (defmacro dd-conc-name (x) `(aref ,x 1)) (defmacro dd-default-constructor (x) `(aref ,x 2)) (defmacro dd-constructors (x) `(aref ,x 3)) (defmacro dd-copier (x) `(aref ,x 4)) (defmacro dd-include (x) `(aref ,x 5)) (defmacro dd-type (x) `(aref ,x 6)) (defmacro dd-named (x) `(aref ,x 7)) (defmacro dd-initial-offset (x) `(aref ,x 8)) (defmacro dd-predicate (x) `(aref ,x 9)) (defmacro dd-print-function (x) `(aref ,x 10)) (defmacro dd-print-object (x) `(aref ,x 11)) (defmacro dd-direct-slots (x) `(aref ,x 12)) (defmacro dd-slots (x) `(aref ,x 13)) (defmacro dd-inherited-accessors (x) `(aref ,x 14)) (defun make-defstruct-description (&key name conc-name default-constructor constructors copier include type named initial-offset predicate print-function print-object direct-slots slots inherited-accessors) (let ((dd (make-array 15))) (setf (dd-name dd) name (dd-conc-name dd) conc-name (dd-default-constructor dd) default-constructor (dd-constructors dd) constructors (dd-copier dd) copier (dd-include dd) include (dd-type dd) type (dd-named dd) named (dd-initial-offset dd) initial-offset (dd-predicate dd) predicate (dd-print-function dd) print-function (dd-print-object dd) print-object (dd-direct-slots dd) direct-slots (dd-slots dd) slots (dd-inherited-accessors dd) inherited-accessors) dd)) ;;; DEFSTRUCT-SLOT-DESCRIPTION (defmacro dsd-name (x) `(aref ,x 1)) (defmacro dsd-index (x) `(aref ,x 2)) (defmacro dsd-reader (x) `(aref ,x 3)) (defmacro dsd-initform (x) `(aref ,x 4)) (defmacro dsd-type (x) `(aref ,x 5)) (defmacro dsd-read-only (x) `(aref ,x 6)) (defun make-defstruct-slot-description (&key name index reader initform (type t) read-only) (let ((dsd (make-array 7))) (setf (aref dsd 0) 'defstruct-slot-description (dsd-name dsd) name (dsd-index dsd) index (dsd-reader dsd) reader (dsd-initform dsd) initform (dsd-type dsd) type (dsd-read-only dsd) read-only) dsd)) (defvar *dd-name*) (defvar *dd-conc-name*) (defvar *dd-default-constructor*) (defvar *dd-constructors*) (defvar *dd-copier*) (defvar *dd-include*) (defvar *dd-type*) (defvar *dd-default-slot-type* t) (defvar *dd-named*) (defvar *dd-initial-offset*) (defvar *dd-predicate*) (defvar *dd-print-function*) (defvar *dd-print-object*) (defvar *dd-direct-slots*) (defvar *dd-slots*) (defvar *dd-inherited-accessors*) (defvar *dd-documentation*) (defun keywordify (symbol) (intern (symbol-name symbol) +keyword-package+)) (defun define-keyword-constructor (constructor) (let* ((constructor-name (car constructor)) (keys ()) (values ())) (dolist (slot *dd-slots*) (let ((name (dsd-name slot)) (initform (dsd-initform slot))) (if (or name (dsd-reader slot)) (let ((dummy (gensym))) (push (list (list (keywordify name) dummy) initform) keys) (push dummy values)) (push initform values)))) (setf keys (cons '&key (nreverse keys)) values (nreverse values)) (cond ((eq *dd-type* 'list) `((defun ,constructor-name ,keys (list ,@values)))) ((or (eq *dd-type* 'vector) (and (consp *dd-type*) (eq (car *dd-type*) 'vector))) (let ((element-type (if (consp *dd-type*) (cadr *dd-type*) t))) `((defun ,constructor-name ,keys (make-array ,(length values) :element-type ',element-type :initial-contents (list ,@values)))))) ((<= 1 (length values) 6) `((defun ,constructor-name ,keys (make-structure (truly-the symbol ',*dd-name*) ,@values)))) (t `((defun ,constructor-name ,keys (%make-structure (truly-the symbol ',*dd-name*) (list ,@values)))))))) (defun find-dsd (name) (dolist (dsd *dd-slots*) (when (string= name (dsd-name dsd)) (return dsd)))) (defun get-slot (name) ;; (let ((res (find name (dd-slots defstruct) :test #'string= :key #'dsd-name))) (let ((res nil)) (dolist (dsd *dd-slots*) (when (string= name (dsd-name dsd)) (setf res dsd) (return))) (if res (values (dsd-type res) (dsd-initform res)) (values t nil)))) (defun define-boa-constructor (constructor) (multiple-value-bind (req opt restp rest keyp keys allowp auxp aux) (parse-lambda-list (cadr constructor)) (let ((arglist ()) (vars ()) (types ()) (skipped-vars ())) (dolist (arg req) (push arg arglist) (push arg vars) (push (get-slot arg) types)) (when opt (push '&optional arglist) (dolist (arg opt) (cond ((consp arg) (destructuring-bind (name &optional (def (nth-value 1 (get-slot name))) (supplied-test nil supplied-test-p)) arg (push `(,name ,def ,@(if supplied-test-p `(,supplied-test) nil)) arglist) (push name vars) (push (get-slot name) types))) (t (multiple-value-bind (type default) (get-slot arg) (push `(,arg ,default) arglist) (push arg vars) (push type types)))))) (when restp (push '&rest arglist) (push rest arglist) (push rest vars) (push 'list types)) (when keyp (push '&key arglist) (dolist (key keys) (if (consp key) (destructuring-bind (wot &optional (def nil def-p) (supplied-test nil supplied-test-p)) key (let ((name (if (consp wot) (destructuring-bind (key var) wot (declare (ignore key)) var) wot))) (multiple-value-bind (type slot-def) (get-slot name) (push `(,wot ,(if def-p def slot-def) ,@(if supplied-test-p `(,supplied-test) nil)) arglist) (push name vars) (push type types)))) (multiple-value-bind (type default) (get-slot key) (push `(,key ,default) arglist) (push key vars) (push type types))))) (when allowp (push '&allow-other-keys arglist)) (when auxp (push '&aux arglist) (dolist (arg aux) (push arg arglist) (if (and (consp arg) (eql (length arg) 2)) (let ((var (first arg))) (push var vars) (push (get-slot var) types)) (push (if (consp arg) (first arg) arg) skipped-vars)))) (setq arglist (nreverse arglist)) (setq vars (nreverse vars)) (setq types (nreverse types)) (setq skipped-vars (nreverse skipped-vars)) (let ((values ())) (dolist (dsd *dd-slots*) (let ((name (dsd-name dsd)) var) (cond ((find name skipped-vars :test #'string=) (push nil values)) ((setf var (find name vars :test #'string=)) (push var values)) (t (push (dsd-initform dsd) values))))) (setf values (nreverse values)) (let* ((constructor-name (car constructor))) (cond ((eq *dd-type* 'list) `((defun ,constructor-name ,arglist (list ,@values)))) ((or (eq *dd-type* 'vector) (and (consp *dd-type*) (eq (car *dd-type*) 'vector))) (let ((element-type (if (consp *dd-type*) (cadr *dd-type*) t))) `((defun ,constructor-name ,arglist (make-array ,(length values) :element-type ',element-type :initial-contents (list ,@values)))))) ((<= 1 (length values) 6) `((declaim (inline ,constructor-name)) (defun ,constructor-name ,arglist (make-structure (truly-the symbol ',*dd-name*) ,@values)))) (t `((declaim (inline ,constructor-name)) (defun ,constructor-name ,arglist (%make-structure (truly-the symbol ',*dd-name*) (list ,@values))))))))))) (defun default-constructor-name () (intern (concatenate 'string "MAKE-" (symbol-name *dd-name*)))) (defun define-constructors () (if *dd-constructors* (let ((results ())) (dolist (constructor *dd-constructors*) (when (car constructor) (setf results (nconc results (if (cadr constructor) (define-boa-constructor constructor) (define-keyword-constructor constructor)))))) results) (define-keyword-constructor (cons (default-constructor-name) nil)))) (defun name-index () (dolist (dsd *dd-slots*) (let ((name (dsd-name dsd)) (initform (dsd-initform dsd))) (when (and (null name) (equal initform (list 'quote *dd-name*))) (return-from name-index (dsd-index dsd))))) ;; We shouldn't get here. nil) (defun define-predicate () (when (and *dd-predicate* (or *dd-named* (null *dd-type*))) (let ((pred (if (symbolp *dd-predicate*) *dd-predicate* (intern *dd-predicate*)))) (cond ((eq *dd-type* 'list) (let ((index (name-index))) `((defun ,pred (object) (and (consp object) (> (length object) ,index) (eq (nth ,index object) ',*dd-name*)))))) ((or (eq *dd-type* 'vector) (and (consp *dd-type*) (eq (car *dd-type*) 'vector))) (let ((index (name-index))) `((defun ,pred (object) (and (vectorp object) (> (length object) ,index) (eq (aref object ,index) ',*dd-name*)))))) (t `((defun ,pred (object) (simple-typep object ',*dd-name*)))))))) (defun make-list-reader (index) #'(lambda (instance) (elt instance index))) (defun make-vector-reader (index) #'(lambda (instance) (aref instance index))) (defun make-structure-reader (index structure-type) (declare (ignore structure-type)) #'(lambda (instance) ;; (unless (typep instance structure-type) ;; (error 'type-error ;; :datum instance ;; :expected-type structure-type)) (structure-ref instance index))) (defun define-reader (slot) (let ((accessor-name (dsd-reader slot)) (index (dsd-index slot)) (type (dsd-type slot))) (cond ((eq *dd-type* 'list) `((declaim (ftype (function * ,type) ,accessor-name)) (record-source-information-for-type ',accessor-name '(:structure-reader ,*dd-name*)) (setf (symbol-function ',accessor-name) (make-list-reader ,index)))) ((or (eq *dd-type* 'vector) (and (consp *dd-type*) (eq (car *dd-type*) 'vector))) `((declaim (ftype (function * ,type) ,accessor-name)) (record-source-information-for-type ',accessor-name '(:structure-reader ,*dd-name*)) (setf (symbol-function ',accessor-name) (make-vector-reader ,index)) (record-source-information-for-type ',accessor-name '(:structure-reader ,*dd-name*)) (define-source-transform ,accessor-name (instance) `(aref (truly-the ,',*dd-type* ,instance) ,,index)))) (t `((declaim (ftype (function * ,type) ,accessor-name)) (setf (symbol-function ',accessor-name) (make-structure-reader ,index ',*dd-name*)) (record-source-information-for-type ',accessor-name '(:structure-reader ,*dd-name*)) (define-source-transform ,accessor-name (instance) ,(if (eq type 't) ``(structure-ref (the ,',*dd-name* ,instance) ,,index) ``(the ,',type (structure-ref (the ,',*dd-name* ,instance) ,,index))))))))) (defun make-list-writer (index) #'(lambda (value instance) (%set-elt instance index value))) (defun make-vector-writer (index) #'(lambda (value instance) (aset instance index value))) (defun make-structure-writer (index structure-type) (declare (ignore structure-type)) #'(lambda (value instance) ;; (unless (typep instance structure-type) ;; (error 'type-error ;; :datum instance ;; :expected-type structure-type)) (structure-set instance index value))) (defun define-writer (slot) (let ((accessor-name (dsd-reader slot)) (index (dsd-index slot))) (cond ((eq *dd-type* 'list) `((record-source-information-for-type '(setf ,accessor-name) '(:structure-writer ,*dd-name*)) (setf (get ',accessor-name 'setf-function) (make-list-writer ,index)))) ((or (eq *dd-type* 'vector) (and (consp *dd-type*) (eq (car *dd-type*) 'vector))) `((setf (get ',accessor-name 'setf-function) (make-vector-writer ,index)) (record-source-information-for-type '(setf ,accessor-name) '(:structure-writer ,*dd-name*)) (define-source-transform (setf ,accessor-name) (value instance) `(aset (truly-the ,',*dd-type* ,instance) ,,index ,value)))) (t `((setf (get ',accessor-name 'setf-function) (make-structure-writer ,index ',*dd-name*)) (record-source-information-for-type '(setf ,accessor-name) '(:structure-writer ,*dd-name*)) (define-source-transform (setf ,accessor-name) (value instance) `(structure-set (the ,',*dd-name* ,instance) ,,index ,value))))))) (defun define-access-functions () (let ((result ())) (dolist (slot *dd-slots*) (let ((accessor-name (dsd-reader slot))) (unless (null accessor-name) (unless (assoc accessor-name *dd-inherited-accessors*) (setf result (nconc result (define-reader slot))) (unless (dsd-read-only slot) (setf result (nconc result (define-writer slot)))))))) result)) (defun define-copier () (when *dd-copier* (cond ((eq *dd-type* 'list) `((declaim (ftype (function (list) list) ,*dd-copier*)) (setf (fdefinition ',*dd-copier*) #'copy-list))) ((or (eq *dd-type* 'vector) (and (consp *dd-type*) (eq (car *dd-type*) 'vector))) `((declaim (ftype (function (vector) vector) ,*dd-copier*)) (setf (fdefinition ',*dd-copier*) #'copy-seq))) (t `((declaim (ftype (function (T) T) ,*dd-copier*)) (setf (fdefinition ',*dd-copier*) #'copy-structure)))))) (defun define-print-function () (cond (*dd-print-function* (if (cadr *dd-print-function*) `((defmethod print-object ((instance ,*dd-name*) stream) (funcall (function ,(cadr *dd-print-function*)) instance stream *current-print-level*))) `((defmethod print-object ((instance ,*dd-name*) stream) (write-string (%write-to-string instance) stream))))) (*dd-print-object* (if (cadr *dd-print-object*) `((defmethod print-object ((instance ,*dd-name*) stream) (funcall (function ,(cadr *dd-print-object*)) instance stream))) `((defmethod print-object ((instance ,*dd-name*) stream) (write-string (%write-to-string instance) stream))))) (t nil))) (defun parse-1-option (option) (case (car option) (:conc-name (setf *dd-conc-name* (if (symbolp (cadr option)) (cadr option) (make-symbol (string (cadr option)))))) (:constructor (let* ((args (cdr option)) (numargs (length args))) (case numargs (0 ; Use default name. (push (list (default-constructor-name) nil) *dd-constructors*)) (1 (push (list (car args) nil) *dd-constructors*)) (2 (push args *dd-constructors*))))) (:copier (when (eql (length option) 2) (setf *dd-copier* (cadr option)))) (:include (setf *dd-include* (cdr option))) (:initial-offset (setf *dd-initial-offset* (cadr option))) (:predicate (when (eql (length option) 2) (setf *dd-predicate* (cadr option)))) (:print-function (setf *dd-print-function* option)) (:print-object (setf *dd-print-object* option)) (:type (setf *dd-type* (cadr option)) (when (and (consp *dd-type*) (eq (car *dd-type*) 'vector)) (unless (eq (second *dd-type*) '*) (setf *dd-default-slot-type* (second *dd-type*))))))) (defun parse-name-and-options (name-and-options) (setf *dd-name* (the symbol (car name-and-options))) (setf *dd-conc-name* (make-symbol (concatenate 'string (symbol-name *dd-name*) "-"))) (setf *dd-copier* (intern (concatenate 'string "COPY-" (symbol-name *dd-name*)))) (setf *dd-predicate* (concatenate 'string (symbol-name *dd-name*) "-P")) (let ((options (cdr name-and-options))) (dolist (option options) (cond ((consp option) (parse-1-option option)) ((eq option :named) (setf *dd-named* t)) ((member option '(:constructor :copier :predicate :named :conc-name)) (parse-1-option (list option))) (t (error "Unrecognized DEFSTRUCT option: ~S." option)))))) (defun compiler-defstruct (name &key conc-name default-constructor constructors copier include type named initial-offset predicate print-function print-object direct-slots slots inherited-accessors documentation) (let ((description (make-defstruct-description :name name :conc-name conc-name :default-constructor default-constructor :constructors constructors :copier copier :include include :type type :named named :initial-offset initial-offset :predicate predicate :print-function print-function :print-object print-object :direct-slots direct-slots :slots slots :inherited-accessors inherited-accessors)) (old (get name 'structure-definition))) (when old (unless ;; Assert that the structure definitions are exactly the same ;; we need to support this type of redefinition during bootstrap ;; building ourselves (and (equalp (aref old 0) (aref description 0)) ;; the CONC-NAME slot is an uninterned symbol if not supplied ;; thus different on each redefinition round. Check that the ;; names are equal, because it produces the same end result ;; when they are. (string= (aref old 1) (aref description 1)) (equalp (aref old 5) (aref description 5)) (equalp (aref old 6) (aref description 6)) (equalp (aref old 7) (aref description 7)) (equalp (aref old 8) (aref description 8)) (every (lambda (x y) (and (equalp (dsd-name x) (dsd-name y)) (equalp (dsd-index x) (dsd-index y)) (equalp (dsd-type x) (dsd-type y)))) (append (aref old 12) (aref old 13)) (append (aref description 12) (aref description 13)))) (error 'program-error :format-control "Structure redefinition not supported ~ in DEFSTRUCT for ~A" :format-arguments (list name))) ;; Since they're the same, continue with the old one. (setf description old)) (setf (get name 'structure-definition) description)) (%set-documentation name 'structure documentation) (when (or (null type) named) (let ((structure-class (make-structure-class name direct-slots slots (car include)))) (%set-documentation name 'type documentation) (%set-documentation structure-class t documentation))) (when default-constructor (proclaim `(ftype (function * t) ,default-constructor)))) (defmacro defstruct (name-and-options &rest slots) (let ((*dd-name* nil) (*dd-conc-name* nil) (*dd-default-constructor* nil) (*dd-constructors* nil) (*dd-copier* nil) (*dd-include* nil) (*dd-type* nil) (*dd-default-slot-type* t) (*dd-named* nil) (*dd-initial-offset* nil) (*dd-predicate* nil) (*dd-print-function* nil) (*dd-print-object* nil) (*dd-direct-slots* ()) (*dd-slots* ()) (*dd-inherited-accessors* ()) (*dd-documentation* nil)) (parse-name-and-options (if (atom name-and-options) (list name-and-options) name-and-options)) (check-declaration-type *dd-name*) (if *dd-constructors* (dolist (constructor *dd-constructors*) (unless (cadr constructor) (setf *dd-default-constructor* (car constructor)) (return))) (setf *dd-default-constructor* (default-constructor-name))) (when (stringp (car slots)) (setf *dd-documentation* (pop slots))) (dolist (slot slots) (let* ((name (if (atom slot) slot (car slot))) (reader (if *dd-conc-name* (intern (concatenate 'string (symbol-name *dd-conc-name*) (symbol-name name))) name)) (initform (if (atom slot) nil (cadr slot))) (dsd (apply #'make-defstruct-slot-description :name name :reader reader :initform initform (cond ((atom slot) (list :type *dd-default-slot-type*)) ((getf (cddr slot) :type) (cddr slot)) (t (list* :type *dd-default-slot-type* (cddr slot))))))) (push dsd *dd-direct-slots*))) (setf *dd-direct-slots* (nreverse *dd-direct-slots*)) (let ((index 0)) (when *dd-include* (let ((dd (get (car *dd-include*) 'structure-definition))) (unless dd (error 'simple-error :format-control "Class ~S is undefined." :format-arguments (list (car *dd-include*)))) (dolist (dsd (dd-slots dd)) ;; MUST COPY SLOT DESCRIPTION! (setf dsd (copy-seq dsd)) (setf (dsd-index dsd) index (dsd-reader dsd) (if *dd-conc-name* (intern (concatenate 'string (symbol-name *dd-conc-name*) (symbol-name (dsd-name dsd)))) (dsd-name dsd))) (push dsd *dd-slots*) (incf index)) (setf *dd-inherited-accessors* (dd-inherited-accessors dd)) (dolist (dsd (dd-direct-slots dd)) (push (cons (dsd-reader dsd) (dsd-name dsd)) *dd-inherited-accessors*))) (when (cdr *dd-include*) (dolist (slot (cdr *dd-include*)) (let* ((name (if (atom slot) slot (car slot))) (initform (if (atom slot) nil (cadr slot))) (dsd (find-dsd name))) (when dsd (setf (dsd-initform dsd) initform)))))) (when *dd-initial-offset* (dotimes (i *dd-initial-offset*) (push (make-defstruct-slot-description :name nil :index index :reader nil :initform nil :type t :read-only t) *dd-slots*) (incf index))) (when *dd-named* (push (make-defstruct-slot-description :name nil :index index :reader nil :initform (list 'quote *dd-name*) :type t :read-only t) *dd-slots*) (incf index)) (dolist (dsd *dd-direct-slots*) (setf (dsd-index dsd) index) (push dsd *dd-slots*) (incf index))) (setf *dd-slots* (nreverse *dd-slots*)) `(progn (eval-when (:compile-toplevel :load-toplevel :execute) (compiler-defstruct ',*dd-name* :conc-name ',*dd-conc-name* :default-constructor ',*dd-default-constructor* ,@(if *dd-constructors* `(:constructors ',*dd-constructors*)) :copier ',*dd-copier* ,@(if *dd-include* `(:include ',*dd-include*)) ,@(if *dd-type* `(:type ',*dd-type*)) ,@(if *dd-named* `(:named ,*dd-named*)) ,@(if *dd-initial-offset* `(:initial-offset ,*dd-initial-offset*)) :predicate ',*dd-predicate* ,@(if *dd-print-function* `(:print-function ',*dd-print-function*)) ,@(if *dd-print-object* `(:print-object ',*dd-print-object*)) :direct-slots ',*dd-direct-slots* :slots ',*dd-slots* :inherited-accessors ',*dd-inherited-accessors* :documentation ',*dd-documentation*)) (record-source-information-for-type ',*dd-name* :structure) ,@(define-constructors) ,@(define-predicate) ,@(define-access-functions) ,@(define-copier) ,@(when (or *dd-print-function* *dd-print-object*) `((require "PRINT-OBJECT"))) ,@(define-print-function) ',*dd-name*))) (defun defstruct-default-constructor (arg) (let ((type (cond ((symbolp arg) arg) ((classp arg) (class-name arg)) (t (type-of arg))))) (when type (let ((dd (get type 'structure-definition))) (and dd (dd-default-constructor dd)))))) abcl-src-1.9.0/src/org/armedbear/lisp/deftype.lisp0100644 0000000 0000000 00000006132 14202767264 020552 0ustar000000000 0000000 ;;; deftype.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defmacro deftype (name lambda-list &rest body) (when (eq (symbol-package name) +cl-package+) (error :format-control "Attempt to define ~S, a symbol in the COMMON-LISP package, as a type specifier." :format-arguments (list name))) (check-declaration-type name) ;; Optional and keyword parameters default to * rather than NIL. (when (or (memq '&optional lambda-list) (memq '&key lambda-list)) (let ((new-lambda-list ()) (state nil)) (dolist (thing lambda-list) (cond ((eq thing '&optional) (setf state '&optional)) ((eq thing '&key) (setf state '&key)) ((memq thing lambda-list-keywords) (setf state nil)) ((eq state '&optional) (when (symbolp thing) (setf thing (list thing ''*)))) ((eq state '&key) (when (symbolp thing) (setf thing (list thing ''*))))) (push thing new-lambda-list)) (setf lambda-list (nreverse new-lambda-list)))) `(progn (record-source-information-for-type ',name :type) (setf (get ',name 'deftype-definition) #'(lambda ,lambda-list (block ,name ,@body))) ',name)) (defun expand-deftype (type) (let (tp i) (loop (if (consp type) (setf tp (%car type) i (%cdr type)) (setf tp type i nil)) (if (and (symbolp tp) (get tp 'deftype-definition)) (setf type (apply (get tp 'deftype-definition) i)) (return)))) type) abcl-src-1.9.0/src/org/armedbear/lisp/delete-duplicates.lisp0100644 0000000 0000000 00000007610 14223403213 022471 0ustar000000000 0000000 ;;; delete-duplicates.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (require "EXTENSIBLE-SEQUENCES-BASE") ;;; From CMUCL. (defun list-delete-duplicates* (list test test-not key from-end start end) (let ((handle (cons nil list))) (do ((current (nthcdr start list) (cdr current)) (previous (nthcdr start handle)) (index start (1+ index))) ((or (and end (= index end)) (null current)) (cdr handle)) (if (do ((x (if from-end (nthcdr (1+ start) handle) (cdr current)) (cdr x)) (i (1+ index) (1+ i))) ((or (null x) (and (not from-end) end (= i end)) (eq x current)) nil) (if (if test-not (not (funcall test-not (sys::apply-key key (car current)) (sys::apply-key key (car x)))) (funcall test (sys::apply-key key (car current)) (sys::apply-key key (car x)))) (return t))) (rplacd previous (cdr current)) (setq previous (cdr previous)))))) (defun vector-delete-duplicates* (vector test test-not key from-end start end &optional (length (length vector))) (when (null end) (setf end (length vector))) (do ((index start (1+ index)) (jndex start)) ((= index end) (do ((index index (1+ index)) ; copy the rest of the vector (jndex jndex (1+ jndex))) ((= index length) (shrink-vector vector jndex) vector) (setf (aref vector jndex) (aref vector index)))) (setf (aref vector jndex) (aref vector index)) (unless (position (sys::apply-key key (aref vector index)) vector :key key :start (if from-end start (1+ index)) :test test :end (if from-end jndex end) :test-not test-not) (setq jndex (1+ jndex))))) (defun delete-duplicates (sequence &rest args &key (test #'eql) test-not (start 0) from-end end key) (sequence::seq-dispatch sequence (if sequence (list-delete-duplicates* sequence test test-not key from-end start end)) (vector-delete-duplicates* sequence test test-not key from-end start end) (apply #'sequence:delete-duplicates sequence args))) abcl-src-1.9.0/src/org/armedbear/lisp/delete.lisp0100644 0000000 0000000 00000017351 14223403213 020341 0ustar000000000 0000000 ;;; delete.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (require "EXTENSIBLE-SEQUENCES-BASE") ;;; From CMUCL. (defmacro real-count (count) `(cond ((null ,count) most-positive-fixnum) ((fixnump ,count) (if (minusp ,count) 0 ,count)) ((integerp ,count) (if (minusp ,count) 0 most-positive-fixnum)) (t ,count))) (defmacro mumble-delete (pred) `(do ((index start (1+ index)) (jndex start) (number-zapped 0)) ((or (= index end) (= number-zapped count)) (do ((index index (1+ index)) ; copy the rest of the vector (jndex jndex (1+ jndex))) ((= index length) (shrink-vector sequence jndex)) (aset sequence jndex (aref sequence index)))) (aset sequence jndex (aref sequence index)) (if ,pred (setq number-zapped (1+ number-zapped)) (setq jndex (1+ jndex))))) (defmacro mumble-delete-from-end (pred) `(do ((index (1- end) (1- index)) ; find the losers (number-zapped 0) (losers ()) this-element (terminus (1- start))) ((or (= index terminus) (= number-zapped count)) (do ((losers losers) ; delete the losers (index start (1+ index)) (jndex start)) ((or (null losers) (= index end)) (do ((index index (1+ index)) ; copy the rest of the vector (jndex jndex (1+ jndex))) ((= index length) (shrink-vector sequence jndex)) (aset sequence jndex (aref sequence index)))) (aset sequence jndex (aref sequence index)) (if (= index (car losers)) (pop losers) (setq jndex (1+ jndex))))) (setq this-element (aref sequence index)) (when ,pred (setq number-zapped (1+ number-zapped)) (push index losers)))) (defmacro normal-mumble-delete () `(mumble-delete (if test-not (not (funcall test-not item (funcall-key key (aref sequence index)))) (funcall test item (funcall-key key (aref sequence index)))))) (defmacro normal-mumble-delete-from-end () `(mumble-delete-from-end (if test-not (not (funcall test-not item (funcall-key key this-element))) (funcall test item (funcall-key key this-element))))) (defmacro list-delete (pred) `(let ((handle (cons nil sequence))) (do ((current (nthcdr start sequence) (cdr current)) (previous (nthcdr start handle)) (index start (1+ index)) (number-zapped 0)) ((or (= index end) (= number-zapped count)) (cdr handle)) (cond (,pred (rplacd previous (cdr current)) (setq number-zapped (1+ number-zapped))) (t (setq previous (cdr previous))))))) (defmacro list-delete-from-end (pred) `(let* ((reverse (nreverse sequence)) (handle (cons nil reverse))) (do ((current (nthcdr (- length end) reverse) (cdr current)) (previous (nthcdr (- length end) handle)) (index start (1+ index)) (number-zapped 0)) ((or (= index end) (= number-zapped count)) (nreverse (cdr handle))) (cond (,pred (rplacd previous (cdr current)) (setq number-zapped (1+ number-zapped))) (t (setq previous (cdr previous))))))) (defmacro normal-list-delete () '(list-delete (if test-not (not (funcall test-not item (funcall-key key (car current)))) (funcall test item (funcall-key key (car current)))))) (defmacro normal-list-delete-from-end () '(list-delete-from-end (if test-not (not (funcall test-not item (funcall-key key (car current)))) (funcall test item (funcall-key key (car current)))))) (defun delete (item sequence &rest args &key from-end (test #'eql) test-not (start 0) end count key) (when key (setq key (coerce-to-function key))) (let* ((length (length sequence)) (end (or end length)) (count (real-count count))) (sequence::seq-dispatch sequence (if from-end (normal-list-delete-from-end) (normal-list-delete)) (if from-end (normal-mumble-delete-from-end) (normal-mumble-delete)) (apply #'sequence:delete item sequence args)))) (defmacro if-mumble-delete () `(mumble-delete (funcall predicate (funcall-key key (aref sequence index))))) (defmacro if-mumble-delete-from-end () `(mumble-delete-from-end (funcall predicate (funcall-key key this-element)))) (defmacro if-list-delete () '(list-delete (funcall predicate (funcall-key key (car current))))) (defmacro if-list-delete-from-end () '(list-delete-from-end (funcall predicate (funcall-key key (car current))))) (defun delete-if (predicate sequence &rest args &key from-end (start 0) key end count) (when key (setq key (coerce-to-function key))) (let* ((length (length sequence)) (end (or end length)) (count (real-count count))) (sequence::seq-dispatch sequence (if from-end (if-list-delete-from-end) (if-list-delete)) (if from-end (if-mumble-delete-from-end) (if-mumble-delete)) (apply #'sequence:delete-if predicate sequence args)))) (defmacro if-not-mumble-delete () `(mumble-delete (not (funcall predicate (funcall-key key (aref sequence index)))))) (defmacro if-not-mumble-delete-from-end () `(mumble-delete-from-end (not (funcall predicate (funcall-key key this-element))))) (defmacro if-not-list-delete () '(list-delete (not (funcall predicate (funcall-key key (car current)))))) (defmacro if-not-list-delete-from-end () '(list-delete-from-end (not (funcall predicate (funcall-key key (car current)))))) (defun delete-if-not (predicate sequence &rest args &key from-end (start 0) end key count) (when key (setq key (coerce-to-function key))) (let* ((length (length sequence)) (end (or end length)) (count (real-count count))) (sequence::seq-dispatch sequence (if from-end (if-not-list-delete-from-end) (if-not-list-delete)) (if from-end (if-not-mumble-delete-from-end) (if-not-mumble-delete)) (apply #'sequence:delete-if-not predicate sequence args)))) abcl-src-1.9.0/src/org/armedbear/lisp/delete_file.java0100644 0000000 0000000 00000010050 14223403213 021277 0ustar000000000 0000000 /* * delete_file.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.IOException; public final class delete_file extends Primitive { private delete_file() { super("delete-file", "filespec"); } // ### delete-file filespec => t @Override public LispObject execute(LispObject arg) { // Don't follow symlinks! We want to delete the symlink itself, not // the linked-to file. Pathname pathname = coerceToPathname(arg); if (arg instanceof Stream) ((Stream)arg)._close(); if (pathname instanceof LogicalPathname) pathname = LogicalPathname.translateLogicalPathname((LogicalPathname)pathname); if (pathname.isWild()) return error(new FileError("Bad place for a wild pathname.", pathname)); final Pathname defaultedPathname = Pathname.mergePathnames(pathname, coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), NIL); File file; if (defaultedPathname.isRemote()) { return error(new FileError("Unable to delete remote pathnames", defaultedPathname)); } else if (defaultedPathname instanceof JarPathname) { JarPathname jar = (JarPathname)defaultedPathname; Pathname root = (Pathname)jar.getRootJar(); Cons jars = (Cons)jar.getJars(); if (jar.isArchiveEntry() || jars.length() > 1) { return error(new FileError("Unable to delete entries within JAR-PATHNAME", jar)); } ZipCache.remove(jar); file = root.getFile(); } else { file = defaultedPathname.getFile(); } if (file.exists()) { // File exists. for (int i = 0; i < 2; i++) { if (file.delete()) { return T; } // Under Windows our fasls get placed in the ZipCache when compiled ZipCache.remove(defaultedPathname); System.gc(); Thread.yield(); } Pathname truename = (Pathname)Pathname.create(file.getAbsolutePath()); StringBuilder sb = new StringBuilder("Unable to delete "); sb.append(file.isDirectory() ? "directory " : "file "); sb.append(truename.princToString()); sb.append('.'); return error(new FileError(sb.toString(), truename)); } else { // File does not exist. return T; } } private static final Primitive DELETE_FILE = new delete_file(); } abcl-src-1.9.0/src/org/armedbear/lisp/deposit-field.lisp0100644 0000000 0000000 00000003447 14202767264 021650 0ustar000000000 0000000 ;;; deposit-field.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun deposit-field (newbyte spec integer) (let* ((size (byte-size spec)) (pos (byte-position spec)) (mask (ash (ldb (byte size 0) -1) pos))) (logior (logand newbyte mask) (logand integer (lognot mask))))) abcl-src-1.9.0/src/org/armedbear/lisp/describe-compiler-policy.lisp0100644 0000000 0000000 00000003434 14202767264 024001 0ustar000000000 0000000 ;;; describe-compiler-policy.lisp ;;; ;;; Copyright (C) 2008 Peter Graves ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (export 'describe-compiler-policy) (defun describe-compiler-policy () (format t "~&; Compiler policy: safety ~D, space ~D, speed ~D, debug ~D~%" *safety* *space* *speed* *debug*) (values)) abcl-src-1.9.0/src/org/armedbear/lisp/describe.lisp0100644 0000000 0000000 00000016310 14223403213 020651 0ustar000000000 0000000 ;;; describe.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require '#:clos) (require '#:format) (defun describe-arglist (object stream) (multiple-value-bind (arglist known-p) (arglist object) (when known-p (format stream "~&The function's lambda list is:~% ~A~%" arglist)))) (defun %describe-object (object stream) (format stream "~S is an object of type ~S.~%" object (type-of object))) (defun describe (object &optional stream) (describe-object object (out-synonym-of stream)) (values)) (defmethod describe-object ((object t) stream) (let ((*print-pretty* t)) (typecase object (SYMBOL (let ((package (symbol-package object))) (if package (multiple-value-bind (sym status) (find-symbol (symbol-name object) package) (format stream "~S is an ~A symbol in the ~A package.~%" object (if (eq status :internal) "internal" "external") (package-name package))) (format stream "~S is an uninterned symbol.~%" object)) (cond ((special-variable-p object) (format stream "It is a ~A; " (if (constantp object) "constant" "special variable")) (if (boundp object) (format stream "its value is ~S.~%" (symbol-value object)) (format stream "it is unbound.~%"))) ((boundp object) (format stream "It is an undefined variable; its value is ~S.~%" (symbol-value object))))) (when (autoloadp object) (resolve object)) (let ((function (and (fboundp object) (symbol-function object)))) (when function (format stream "Its function binding is ~S.~%" function) (describe-arglist function stream))) (let ((doc (documentation object 'function))) (when doc (format stream "Function documentation:~% ~A~%" doc))) (let ((doc (documentation object 'variable))) (when doc (format stream "Variable documentation:~% ~A~%" doc))) (let ((plist (symbol-plist object))) (when plist (format stream "The symbol's property list contains these indicator/value pairs:~%") (loop (when (null plist) (return)) (format stream " ~S ~S~%" (car plist) (cadr plist)) (setf plist (cddr plist)))))) (FUNCTION (%describe-object object stream) (describe-arglist object stream) (let ((function-symbol (nth-value 2 (function-lambda-expression object)))) (if (and (consp function-symbol) (eq (car function-symbol) 'macro-function)) (setq function-symbol (second function-symbol))) (when function-symbol (let ((doc (documentation function-symbol 'function))) (when doc (format stream "Function documentation:~% ~A~%" doc))) ))) (INTEGER (%describe-object object stream) (format stream "~D.~%~ #x~X~%~ #o~O~%~ #b~B~%" object object object object)) (t (%describe-object object stream)))) (values)) (defmethod describe-object ((object pathname) stream) (format stream "~S is an object of type ~S:~%" object (type-of object)) (format stream " HOST ~S~%" (pathname-host object)) (format stream " DEVICE ~S~%" (pathname-device object)) (format stream " DIRECTORY ~S~%" (pathname-directory object)) (format stream " NAME ~S~%" (pathname-name object)) (format stream " TYPE ~S~%" (pathname-type object)) (format stream " VERSION ~S~%" (pathname-version object))) (defun %describe-standard-object/funcallable (object stream) (let* ((class (class-of object)) (slotds (mop:class-slots class)) (max-slot-name-length 0) (instance-slotds ()) (class-slotds ())) (format stream "~S is an instance of ~S.~%" object class) (dolist (slotd slotds) (let* ((name (mop:slot-definition-name slotd)) (length (length (symbol-name name)))) (when (> length max-slot-name-length) (setf max-slot-name-length length))) (case (mop:slot-definition-allocation slotd) (:instance (push slotd instance-slotds)) (:class (push slotd class-slotds)))) (setf max-slot-name-length (min (+ max-slot-name-length 3) 30)) (flet ((describe-slot (slot-name) (if (slot-boundp object slot-name) (format stream "~& ~A~VT ~S" slot-name max-slot-name-length (slot-value object slot-name)) (format stream "~& ~A~VT unbound" slot-name max-slot-name-length)))) (when instance-slotds (format stream "The following slots have :INSTANCE allocation:~%") (dolist (slotd (nreverse instance-slotds)) (describe-slot (mop:slot-definition-name slotd)))) (format stream "~%") (when class-slotds (format stream "The following slots have :CLASS allocation:~%") (dolist (slotd (nreverse class-slotds)) (describe-slot (mop:slot-definition-name slotd))) (format stream "~%"))))) (defmethod describe-object ((object standard-object) stream) (%describe-standard-object/funcallable object stream) (values)) (defmethod describe-object ((object mop:funcallable-standard-object) stream) (%describe-standard-object/funcallable object stream) (values)) (defmethod describe-object ((object java:java-object) stream) (java:describe-java-object object stream)) abcl-src-1.9.0/src/org/armedbear/lisp/destructuring-bind.lisp0100644 0000000 0000000 00000055072 14223403213 022715 0ustar000000000 0000000 ;;; destructuring-bind.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;;; Adapted from CMUCL/SBCL. (in-package #:system) (export '(parse-body)) (defun parse-body (body &optional (doc-string-allowed t)) (let ((decls ()) (doc nil)) (do ((tail body (cdr tail))) ((endp tail) (values tail (nreverse decls) doc)) (let ((form (car tail))) (cond ((and (stringp form) (cdr tail)) (if doc-string-allowed (setq doc form ;; Only one doc string is allowed. doc-string-allowed nil) (return (values tail (nreverse decls) doc)))) ((not (and (consp form) (symbolp (car form)))) (return (values tail (nreverse decls) doc))) ((eq (car form) 'declare) (push form decls)) (t (return (values tail (nreverse decls) doc)))))))) ;; We don't have DEFVAR yet... (eval-when (:compile-toplevel :load-toplevel :execute) (%defvar '*arg-tests* ()) (%defvar '*system-lets* ()) (%defvar '*user-lets* ()) (%defvar '*ignorable-vars* ()) (%defvar '*env-var* nil)) (defun arg-count-error (error-kind name arg lambda-list minimum maximum) (declare (ignore error-kind arg lambda-list minimum maximum)) (error 'program-error :format-control "Wrong number of arguments for ~S." :format-arguments (list name))) (defun bogus-sublist-error (&key kind name object lambda-list) (error 'program-error :format-control "Error while parsing arguments to ~A ~S:~%Bogus sublist:~% ~S~%to satisfy lambda-list:~% ~:S~%" :format-arguments (list kind name object lambda-list))) (defun lambda-list-broken-key-list-error (&key kind name problem info) (error 'program-error :format-control (concatenate 'string "Error while parsing arguments to ~A ~S:~%" (ecase problem (:dotted-list "Keyword/value list is dotted: ~S") (:odd-length "Odd number of elements in keyword/value list: ~S") (:duplicate "Duplicate keyword: ~S") (:unknown-keyword "~{Unknown keyword: ~S ; expected one of ~{~S~^, ~}~}"))) :format-arguments (list kind name info))) ;;; Return, as multiple values, a body, possibly a DECLARE form to put ;;; where this code is inserted, the documentation for the parsed ;;; body, and bounds on the number of arguments. (defun parse-defmacro (lambda-list arg-list-name body name context &key (anonymousp nil) (doc-string-allowed t) ((:environment env-arg-name)) (error-fun 'error) (wrap-block t)) (multiple-value-bind (forms declarations documentation) (parse-body body doc-string-allowed) (let ((*arg-tests* ()) (*user-lets* ()) (*system-lets* ()) (*ignorable-vars* ()) (*env-var* nil)) (multiple-value-bind (env-arg-used minimum maximum) (parse-defmacro-lambda-list lambda-list arg-list-name name context error-fun (not anonymousp) nil) (values `(let* (,@(when env-arg-used `((,*env-var* ,env-arg-name))) ,@(nreverse *system-lets*)) ,@(when *ignorable-vars* `((declare (ignorable ,@*ignorable-vars*)))) ,@*arg-tests* (let* ,(nreverse *user-lets*) ,@declarations ,@(if wrap-block `((block ,(fdefinition-block-name name) ,@forms)) forms))) `(,@(when (and env-arg-name (not env-arg-used)) `((declare (ignore ,env-arg-name))))) documentation minimum maximum))))) (defun defmacro-error (problem name) (error 'type-error "~S is not of type ~S~%" problem name)) (defun verify-keywords (key-list valid-keys allow-other-keys) (do ((already-processed nil) (unknown-keyword nil) (remaining key-list (cddr remaining))) ((null remaining) (if (and unknown-keyword (not allow-other-keys) (not (lookup-keyword :allow-other-keys key-list))) (values :unknown-keyword (list unknown-keyword valid-keys)) (values nil nil))) (cond ((not (and (consp remaining) (listp (cdr remaining)))) (return (values :dotted-list key-list))) ((null (cdr remaining)) (return (values :odd-length key-list))) ((or (eq (car remaining) :allow-other-keys) (memql (car remaining) valid-keys)) (push (car remaining) already-processed)) (t (setq unknown-keyword (car remaining)))))) (defun lookup-keyword (keyword key-list) (do ((remaining key-list (cddr remaining))) ((endp remaining)) (when (eq keyword (car remaining)) (return (cadr remaining))))) (defun keyword-supplied-p (keyword key-list) (do ((remaining key-list (cddr remaining))) ((endp remaining)) (when (eq keyword (car remaining)) (return t)))) (defun dot-length (cons) (do ((rest cons (cdr rest)) (length 0 (1+ length))) ((or (null rest) (atom rest)) length))) (defun parse-defmacro-lambda-list (lambda-list arg-list-name name error-kind error-fun &optional top-level env-illegal ;;env-arg-name ) (let* ((path-0 (if top-level `(cdr ,arg-list-name) arg-list-name)) (path path-0) (now-processing :required) (maximum 0) (minimum 0) (keys ()) rest-name restp allow-other-keys-p env-arg-used) ;; This really strange way to test for &WHOLE is necessary because MEMBER ;; does not have to work on dotted lists, and dotted lists are legal ;; in lambda lists. (when (and (do ((list lambda-list (cdr list))) ((atom list) nil) (when (eq (car list) '&WHOLE) (return t))) (not (eq (car lambda-list) '&WHOLE))) (error "&Whole must appear first in ~S lambda-list." error-kind)) (do ((rest-of-args lambda-list (cdr rest-of-args))) ((atom rest-of-args) (cond ((null rest-of-args) nil) ;; Varlist is dotted, treat as &rest arg and exit. (t (push-let-binding rest-of-args path nil) (setq restp t)))) (let ((var (car rest-of-args))) (cond ((eq var '&whole) (cond ((and (cdr rest-of-args) (symbolp (cadr rest-of-args))) (setq rest-of-args (cdr rest-of-args)) (push-let-binding (car rest-of-args) arg-list-name nil)) ((and (cdr rest-of-args) (consp (cadr rest-of-args))) (pop rest-of-args) (let* ((destructuring-lambda-list (car rest-of-args)) (sub (gensym "WHOLE-SUBLIST"))) (push-sub-list-binding sub arg-list-name destructuring-lambda-list name error-kind error-fun) (parse-defmacro-lambda-list destructuring-lambda-list sub name error-kind error-fun))) (t (defmacro-error "&WHOLE" name)))) ((eq var '&environment) (cond (env-illegal (error "&ENVIRONMENT is not valid with ~S." error-kind)) ((not top-level) (error "&ENVIRONMENT is only valid at top level of lambda list."))) (cond ((and (cdr rest-of-args) (symbolp (cadr rest-of-args))) (setq rest-of-args (cdr rest-of-args)) (setq *env-var* (car rest-of-args) env-arg-used t)) (t (defmacro-error "&ENVIRONMENT" name)))) ((or (eq var '&rest) (eq var '&body)) (cond ((and (cdr rest-of-args) (symbolp (cadr rest-of-args))) (setq rest-of-args (cdr rest-of-args)) (setq restp t) (push-let-binding (car rest-of-args) path nil)) ((and (cdr rest-of-args) (consp (cadr rest-of-args))) (pop rest-of-args) (setq restp t) (let* ((destructuring-lambda-list (car rest-of-args)) (sub (gensym "REST-SUBLIST"))) (push-sub-list-binding sub path destructuring-lambda-list name error-kind error-fun) (parse-defmacro-lambda-list destructuring-lambda-list sub name error-kind error-fun))) (t (defmacro-error (symbol-name var) name)))) ((eq var '&optional) (setq now-processing :optionals)) ((eq var '&key) (setq now-processing :keywords) (setq rest-name (gensym "KEYWORDS-")) (push rest-name *ignorable-vars*) (setq restp t) (push-let-binding rest-name path t)) ((eq var '&allow-other-keys) (setq allow-other-keys-p t)) ((eq var '&aux) (setq now-processing :auxs)) ((listp var) (case now-processing (:required (let ((sub-list-name (gensym "SUBLIST-"))) (push-sub-list-binding sub-list-name `(car ,path) var name error-kind error-fun) (parse-defmacro-lambda-list var sub-list-name name error-kind error-fun)) (setq path `(cdr ,path)) (incf minimum) (incf maximum)) (:optionals (when (> (length var) 3) (error "more than variable, initform, and suppliedp in &optional binding ~S" var)) (push-optional-binding (car var) (cadr var) (caddr var) `(not (null ,path)) `(car ,path) name error-kind error-fun) (setq path `(cdr ,path)) (incf maximum)) (:keywords (let* ((keyword-given (consp (car var))) (variable (if keyword-given (cadar var) (car var))) (keyword (if keyword-given (caar var) (make-keyword variable))) (supplied-p (caddr var))) (push-optional-binding variable (cadr var) supplied-p `(keyword-supplied-p ',keyword ,rest-name) `(lookup-keyword ',keyword ,rest-name) name error-kind error-fun) (push keyword keys))) (:auxs (push-let-binding (car var) (cadr var) nil)))) ((symbolp var) (case now-processing (:required (incf minimum) (incf maximum) (push-let-binding var `(car ,path) nil) (setq path `(cdr ,path))) (:optionals (incf maximum) (push-let-binding var `(car ,path) nil `(not (null ,path))) (setq path `(cdr ,path))) (:keywords (let ((key (make-keyword var))) (push-let-binding var `(lookup-keyword ,key ,rest-name) nil) (push key keys))) (:auxs (push-let-binding var nil nil)))) (t (error "non-symbol in lambda-list: ~S" var))))) ;; Generate code to check the number of arguments. (push `(unless (<= ,minimum (dot-length ,path-0) ,@(unless restp (list maximum))) ,(if (eq error-fun 'error) `(arg-count-error ',error-kind ',name ,path-0 ',lambda-list ,minimum ,(unless restp maximum)) `(,error-fun 'arg-count-error :kind ',error-kind ,@(when name `(:name ',name)) :argument ,path-0 :lambda-list ',lambda-list :minimum ,minimum ,@(unless restp `(:maximum ,maximum))))) *arg-tests*) (if keys (let ((problem (gensym "KEY-PROBLEM-")) (info (gensym "INFO-"))) (push `(multiple-value-bind (,problem ,info) (verify-keywords ,rest-name ',keys ',allow-other-keys-p) (when ,problem ,(if (eq error-fun 'error) `(lambda-list-broken-key-list-error :kind ',error-kind ,@(when name `(:name ',name)) :problem ,problem :info ,info) `(,error-fun 'defmacro-lambda-list-broken-key-list-error :kind ',error-kind ,@(when name `(:name ',name)) :problem ,problem :info ,info)))) *arg-tests*))) (values env-arg-used minimum (if (null restp) maximum nil)))) (defun push-sub-list-binding (variable path object name error-kind error-fun) (let ((var (gensym "TEMP-"))) (push `(,variable (let ((,var ,path)) (if (listp ,var) ,var ,(if (eq error-fun 'error) `(bogus-sublist-error :kind ',error-kind ,@(when name `(:name ',name)) :object ,var :lambda-list ',object) `(,error-fun 'defmacro-bogus-sublist-error :kind ',error-kind ,@(when name `(:name ',name)) :object ,var :lambda-list ',object))))) *system-lets*))) (defun push-let-binding (variable path systemp &optional condition (init-form nil)) (let ((let-form (if condition `(,variable (if ,condition ,path ,init-form)) `(,variable ,path)))) (if systemp (push let-form *system-lets*) (push let-form *user-lets*)))) (defun push-optional-binding (value-var init-form supplied-var condition path name error-kind error-fun) (unless supplied-var (setq supplied-var (gensym "SUPPLIEDP-"))) (push-let-binding supplied-var condition t) (cond ((consp value-var) (let ((whole-thing (gensym "OPTIONAL-SUBLIST-"))) (push-sub-list-binding whole-thing `(if ,supplied-var ,path ,init-form) value-var name error-kind error-fun) (parse-defmacro-lambda-list value-var whole-thing name error-kind error-fun))) ((symbolp value-var) (push-let-binding value-var path nil supplied-var init-form)) (t (error "Illegal optional variable name: ~S" value-var)))) (defmacro destructuring-bind (lambda-list arg-list &rest body) (let* ((arg-list-name (gensym "ARG-LIST-"))) (multiple-value-bind (body local-decls) (parse-defmacro lambda-list arg-list-name body nil 'destructuring-bind :anonymousp t :doc-string-allowed nil :wrap-block nil) `(let ((,arg-list-name ,arg-list)) ,@local-decls ,body)))) ;; Redefine SYS:MAKE-MACRO-EXPANDER to use PARSE-DEFMACRO. (defun make-macro-expander (definition) (let* ((name (car definition)) (lambda-list (cadr definition)) (form (gensym "WHOLE-")) (env (gensym "ENVIRONMENT-")) (body (parse-defmacro lambda-list form (cddr definition) name 'defmacro :environment env))) `(lambda (,form ,env) (block ,name ,body)))) #| These conditions might be signaled but are not defined. Probably can't define them here as clos might not be active. Taken from cmucl. (define-condition defmacro-lambda-list-bind-error (program-error) ((kind :reader defmacro-lambda-list-bind-error-kind :initarg :kind) (name :reader defmacro-lambda-list-bind-error-name :initarg :name :initform nil))) (defun print-defmacro-ll-bind-error-intro (condition stream) (if (null (defmacro-lambda-list-bind-error-name condition)) (format stream "Error while parsing arguments to ~A in ~S:~%" (defmacro-lambda-list-bind-error-kind condition) (condition-function-name condition)) (format stream "Error while parsing arguments to ~A ~S:~%" (defmacro-lambda-list-bind-error-kind condition) (defmacro-lambda-list-bind-error-name condition)))) (define-condition defmacro-bogus-sublist-error (defmacro-lambda-list-bind-error) ((object :reader defmacro-bogus-sublist-error-object :initarg :object) (lambda-list :reader defmacro-bogus-sublist-error-lambda-list :initarg :lambda-list)) (:report (lambda (condition stream) (print-defmacro-ll-bind-error-intro condition stream) (format stream "Bogus sublist:~% ~S~%to satisfy lambda-list:~% ~:S~%" (defmacro-bogus-sublist-error-object condition) (defmacro-bogus-sublist-error-lambda-list condition))))) (define-condition arg-count-error (defmacro-lambda-list-bind-error) ((argument :reader defmacro-ll-arg-count-error-argument :initarg :argument) (lambda-list :reader defmacro-ll-arg-count-error-lambda-list :initarg :lambda-list) (minimum :reader defmacro-ll-arg-count-error-minimum :initarg :minimum) (maximum :reader defmacro-ll-arg-count-error-maximum :initarg :maximum)) (:report (lambda (condition stream) (print-defmacro-ll-bind-error-intro condition stream) (format stream "Invalid number of elements in:~% ~:S~%~ to satisfy lambda-list:~% ~:S~%" (defmacro-ll-arg-count-error-argument condition) (defmacro-ll-arg-count-error-lambda-list condition)) (cond ((null (defmacro-ll-arg-count-error-maximum condition)) (format stream "Expected at least ~D" (defmacro-ll-arg-count-error-minimum condition))) ((= (defmacro-ll-arg-count-error-minimum condition) (defmacro-ll-arg-count-error-maximum condition)) (format stream "Expected exactly ~D" (defmacro-ll-arg-count-error-minimum condition))) (t (format stream "Expected between ~D and ~D" (defmacro-ll-arg-count-error-minimum condition) (defmacro-ll-arg-count-error-maximum condition)))) (format stream ", but got ~D." (length (defmacro-ll-arg-count-error-argument condition)))))) (define-condition defmacro-lambda-list-broken-key-list-error (defmacro-lambda-list-bind-error) ((problem :reader defmacro-ll-broken-key-list-error-problem :initarg :problem) (info :reader defmacro-ll-broken-key-list-error-info :initarg :info)) (:report (lambda (condition stream) (print-defmacro-ll-bind-error-intro condition stream) (format stream (ecase (defmacro-ll-broken-key-list-error-problem condition) (:dotted-list "Keyword/value list is dotted: ~S") (:odd-length "Odd number of elements in keyword/value list: ~S") (:duplicate "Duplicate keyword: ~S") (:unknown-keyword "~{Unknown keyword: ~S; expected one of ~{~S~^, ~}~}")) (defmacro-ll-broken-key-list-error-info condition))))) |# abcl-src-1.9.0/src/org/armedbear/lisp/digest.lisp0100644 0000000 0000000 00000013210 14223403213 020344 0ustar000000000 0000000 ;;; digest.lisp ;;; ;;; Copyright (C) 2012 Mark Evenson ;;; $Id$ ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (require :java) (in-package :system) (defun asciify (digest) (format nil "~{~2,'0X~}" (mapcar (lambda (b) (if (< b 0) (+ 256 b) b)) (java::list-from-jarray digest)))) ;;;; Really needs to concatenate all input into a single source of ;;;; bytes, running digest over that concatentation. (defun sha256 (&rest paths-or-strings) ;;; XXX more than one arg is very broken. "Returned ASCIIfied representation of SHA256 digest of byte-based resource at PATHS-OR-STRINGs." (unless (and (null (rest paths-or-strings)) (pathnamep (first paths-or-strings))) (warn "Unaudited computation of cryptographic digest initiated.")) ;; TODO Need tests with some tool for verification (let ((first (first paths-or-strings)) (rest (rest paths-or-strings))) (concatenate 'string (when first (asciify (typecase first (pathname (digest first)) (string (digest first)) (null) (list (concatenate 'string (sha256 (first first)) (sha256 (rest first))))))) (when rest (sha256 rest))))) #+nil ;; Bugs out the compiler (defun sha256 (paths-or-strings) (labels ((walk (p-or-s) ((atom p-or-s) (typecase p-or-s (pathname (digest-path p-or-s)) (string (error "Somebody implement me please")))) ((cons p-or-s) (walk (first p-or-s) (rest p-or-s))))) (concatenate 'string (walk paths-or-strings)))) (defgeneric digest (resource &key (digest 'sha-256)) (:documentation "Digest byte based resource at RESOURCE.")) (defun digest-path (path) (asciify (digest path 'nio 'sha-256))) (defvar *digest-types* '((sha-1 . "SHA-1") (sha-256 . "SHA-256") (sha-512 . "SHA-512")) "Normalization of cryptographic digest naming.") ;;; Implementation (defconstant +byte-buffer-rewind+ (java:jmethod "java.nio.ByteBuffer" "rewind")) (defconstant +byte-buffer-get+ (java:jmethod "java.nio.ByteBuffer" "get" "[B" "int" "int")) (defconstant +digest-update+ (java:jmethod "java.security.MessageDigest" "update" "[B" "int" "int")) (defmethod digest ((url pathname) &key (digest 'sha-256)) (digest-nio url :digest digest)) (defun digest-nio (source &key (digest 'sha-256)) "Calculate digest with default of :SHA-256 pathname specified by URL. Returns an array of JVM primitive signed 8-bit bytes. Uses \"New I/O\" in JVM \"worse named API of all time\". *DIGEST-TYPES* controls the allowable digest types." (let* ((channel (typecase source (pathname (java:jcall "getChannel" (java:jnew "java.io.FileInputStream" (namestring source)))) (string (java:jstatic "newChannel" "java.nio.channels.Channels" (java:jnew "java.io.ByteArrayInputStream" (java:jcall "getBytes" source)))) (error "Typecase failed of object of type ~S." source))) (digest-type (cdr (assoc digest *digest-types*))) (digest (java:jstatic "getInstance" "java.security.MessageDigest" digest-type)) (length 8192) (buffer (java:jstatic "allocateDirect" "java.nio.ByteBuffer" length)) (array (java:jnew-array "byte" length))) (do ((read (java:jcall "read" channel buffer) (java:jcall "read" channel buffer))) ((not (> read 0))) (java:jcall +byte-buffer-rewind+ buffer) (java:jcall +byte-buffer-get+ buffer array 0 read) (java:jcall +byte-buffer-rewind+ buffer) (java:jcall +digest-update+ digest array 0 read)) (java:jcall "digest" digest))) (defmethod digest ((source string) &key (digest 'sha-256)) (digest-nio source :digest digest)) (export 'sha256 :system) abcl-src-1.9.0/src/org/armedbear/lisp/directory.lisp0100644 0000000 0000000 00000021151 14242624277 021114 0ustar000000000 0000000 ;;; directory.lisp ;;; ;;; Copyright (C) 2004-2007 Peter Graves ;;; Copyright (C) 2008 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") ;;; utility function for LIST-DIRECTORIES-WITH-WILDCARDS (defun directory-as-file (pathname) "Convert a PATHNAME referencing a directory to a file" (let ((directory (pathname-directory pathname))) (make-pathname :host nil :device (pathname-device pathname) :directory (butlast directory) :name (car (last directory)) :type nil :version nil))) ;;; utility function for LIST-DIRECTORIES-WITH-WILDCARDS (defun wild-inferiors-p (component) (eq component :wild-inferiors)) (defun list-directories-with-wildcards (pathname wild-inferiors-found resolve-symlinks) (let* ((directory (pathname-directory pathname)) (first-wild-inferior (and (not wild-inferiors-found) (position-if #'wild-inferiors-p directory))) (first-wild (position-if #'wild-p directory)) (wild (when (or first-wild-inferior first-wild) (nthcdr (or first-wild-inferior first-wild) directory))) (non-wild (if (or first-wild-inferior first-wild) (nbutlast directory (- (length directory) (or first-wild-inferior first-wild))) directory)) (newpath (make-pathname :directory non-wild :name nil :type nil :defaults pathname)) (entries (list-directory newpath resolve-symlinks))) (when (not (or wild wild-inferiors-found)) ;; no further recursion necessary (return-from list-directories-with-wildcards entries)) (let ((inferior-entries (when (or wild-inferiors-found first-wild-inferior) entries))) (nconc (mapcan (lambda (entry) (when (pathname-match-p (pathname entry) pathname) (list entry))) inferior-entries) (mapcan (lambda (entry) (let* ((pathname (pathname entry)) (directory (pathname-directory pathname)) (rest-wild (cdr wild))) (unless (pathname-name pathname) (when (pathname-match-p (first (last directory)) (cond ((eql (car wild) :wild) "*") ((eql (car wild) :wild-inferiors) "*") (wild (car wild)) (t ""))) (when (and (not (or first-wild-inferior wild-inferiors-found)) rest-wild) (setf directory (nconc directory rest-wild))) (let ((recurse (make-pathname :directory directory :defaults newpath))) (when (not (equal recurse newpath)) (list-directories-with-wildcards recurse (or first-wild-inferior wild-inferiors-found) resolve-symlinks))))))) entries))))) ;;; The extension to ANSI via :RESOLVE-SYMLINKS was added as ;;; , in which it was argued that ;;; symlinks should be considered contents of a directory, and that in ;;; any event, performing a DIRECTORY on a dangling symlink should not ;;; signal an error. ;;; ;;; See for additional ;;; information on implementation decision. (defun directory (pathspec &key (resolve-symlinks nil)) "Determines which, if any, files that are present in the file system have names matching PATHSPEC, and returns a fresh list of pathnames corresponding to the potential truenames of those files. With :RESOLVE-SYMLINKS set to nil, not all pathnames returned may correspond to an existing file. Symbolic links are considered to be be valid entries even if they do not currently have a valid file or directory as a target. Therefore, subsequent CL:TRUENAME call on individual pathnames in the list may signal an error, i.e. the pathnames have been constructed as truenames, without calling the entire resolution routine of CL:TRUENAME. If called with :RESOLVE-SYMLINKS set to T, and any of the pathnames have truenames which do not exist, this routine will signal a file error to its caller." (let ((pathname (merge-pathnames pathspec))) (when (equalp (pathname-host pathname) '(:scheme "file")) (setq pathname (subseq (namestring pathname) #.(length "file://")))) (when (logical-pathname-p pathname) (setq pathname (translate-logical-pathname pathname))) (if (or (position #\* (namestring pathname)) (wild-pathname-p pathname)) (if (pathname-jar-p pathname) (match-wild-jar-pathname pathname) (let ((namestring (directory-namestring pathname))) (when (and namestring (> (length namestring) 0)) (when (featurep :windows) (let ((host (pathname-host pathname)) (device (pathname-device pathname))) (cond ((and host device) (setq namestring (concatenate 'string "//" host "/" device namestring))) (device (setq namestring (concatenate 'string device ":" namestring)))))) (let ((entries (list-directories-with-wildcards namestring nil resolve-symlinks)) (matching-entries nil)) (flet ((no-dots (path) (merge-pathnames (make-pathname :directory (let ((reversed nil)) (dolist (el (pathname-directory path)) (if (eq el :up) (pop reversed) (unless (equal el ".") (push el reversed)))) (reverse reversed))) path))) (let ((pathname (no-dots pathname))) (dolist (entry entries) (when (or (and (file-directory-p entry :wild-error-p nil) (pathname-match-p (directory-as-file entry) pathname)) (pathname-match-p entry pathname)) (push (if resolve-symlinks (truename entry) ;; Normalize nil DEVICE to :UNSPECIFIC under non-Windows ;; fixes ANSI DIRECTORY.[67] (if (and (not (find :windows *features*)) (not (pathname-device entry))) (make-pathname :defaults entry :device :unspecific) entry)) matching-entries))))) matching-entries)))) ;; Not wild. (let ((truename (probe-file pathname))) (if truename (list (pathname truename)) nil))))) abcl-src-1.9.0/src/org/armedbear/lisp/disassemble.lisp0100644 0000000 0000000 00000025261 14242624277 021411 0ustar000000000 0000000 ;;; disassemble.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :system) (require :clos) (defvar *disassembler-function* nil "The underlying function last used for CL:DISASSEMBLE or nil if not invoked Available disassemblers are configured by pushing a strategy to SYSTEM:*DISASSEMBLERS*. The function SYSTEM:CHOOSE-DISASSEMBLER is used to select a current strategy from this list of strategies.") (defvar *disassemblers* `((:system-javap . disassemble-class-bytes)) "Methods of invoking CL:DISASSEMBLE consisting of a list of (KEYWORD FUNCTION) pairs The pairs (KEYWORD FUNCTION) contain a KEYWORD uniquely identifying a particular disassembler and a SYMBOL designating its invocation function. The KEYWORD values are used by SYS:CHOOSE-DISASSEMBLER to install a given disassembler as the one used by CL:DISASSEMBLE. Additional disassemblers/decompilers are packaged in the ABCL-INTROSPECT contrib. The initial default is :SYSTEM-JAVAP which attempts to invoke the javap command line tool shipped as part of the Java Developement Kit which may or may not be installed locally. ") (defun choose-disassembler (&optional name) "Report current disassembler that would be used by CL:DISASSEMBLE When the optional keyword NAME is specified, select the associated disassembler from SYS:*DISASSEMBLERS* for future invocations of CL:DISASSEMBLE." (flet ((sane-disassembler-p (disassembler) (and disassembler (fboundp disassembler)))) (setf *disassembler-function* (if name (let ((disassembler (cdr (assoc name *disassemblers*)))) (if (sane-disassembler-p disassembler) disassembler (error "Disassembler ~a doesn't appear to work." name))) (if (sane-disassembler-p *disassembler-function*) *disassembler-function* ;; simplest strategy: choose the first working one (loop :for (nil . disassembler) in *disassemblers* :when (sane-disassembler-p disassembler) :do (return disassembler) :finally (warn "Can't find suitable disassembler."))))))) (eval-when (:compile-toplevel :load-toplevel :execute) (defmacro with-open ((name value) &body body) `(let ((,name ,value)) (unwind-protect (progn ,@body) (java:jcall-raw "close" ,name))))) (defun read-byte-array-from-stream (stream) (let ((buffer (java:jnew-array (java:jclass "byte") 4096))) (with-open (output (java:jnew "java.io.ByteArrayOutputStream")) (loop for length = (java:jcall "read" stream buffer) until (eql length -1) do (java:jcall-raw "write" output buffer 0 length)) (java:jcall-raw "flush" output) (java:jcall-raw "toByteArray" output)))) (defun class-resource-path (class) (format NIL "~A.class" (substitute #\/ #\. (java:jcall "getName" class)))) (defun class-bytes (class) (with-open (stream (java:jcall-raw "getResourceAsStream" (java:jcall-raw "getClassLoader" class) (class-resource-path class))) (read-byte-array-from-stream stream))) (defun disassemble-bytes (bytes) "Disassemble jvm code BYTES returning a string." (funcall (or *disassembler-function* (choose-disassembler)) bytes)) (defun disassemble-function (arg) (let ((function (cond ((java::java-object-p arg) (cond ((java::jinstance-of-p arg "java.lang.Class") arg) ((java::jinstance-of-p arg "java.lang.reflect.Method") (java::jmethod-declaring-class arg)) )) ((functionp arg) arg) ((symbolp arg) (or (macro-function arg) (symbol-function arg))) (t arg)))) (when (typep function 'generic-function) (setf function (mop::funcallable-instance-function function))) ;; use isInstance instead of jinstance-of-p ;; because the latter checked java-object-p ;; which fails since its a lisp object (when (and (java:jcall "isInstance" (java:jclass "org.armedbear.lisp.Closure") function) (not (java:jcall "isInstance" (java:jclass "org.armedbear.lisp.CompiledClosure") function))) (return-from disassemble-function (with-output-to-string (s) (format s "Not a compiled function: ~%") (pprint (java:jcall "getBody" function) s)))) (let ((bytes (or (and (java:jcall "isInstance" (java:jclass "org.armedbear.lisp.Function") function) (ignore-errors (getf (function-plist function))) 'class-bytes) (and (java:jcall "isInstance" (java:jclass "org.armedbear.lisp.CompiledClosure") function) (equalp (java::jcall "getName" (java::jobject-class (java:jcall "getClassLoader" (java::jcall "getClass" function)))) "org.armedbear.lisp.FaslClassLoader") (fasl-compiled-closure-class-bytes function))))) ;; we've got bytes here then we've covered the case that the disassembler already handled ;; If not then we've either got a primitive (in function) or we got passed a method object as arg. (if bytes (disassemble-bytes bytes) (let ((class (if (java:java-object-p function) function (java:jcall "getClass" function)))) (let ((classloader (java:jcall "getClassLoader" class))) (if (or (java:jinstance-of-p classloader "org.armedbear.lisp.MemoryClassLoader") (java:jinstance-of-p classloader "org.armedbear.lisp.FaslClassLoader")) (disassemble-bytes (or (ignore-errors (java:jcall "getFunctionClassBytes" classloader class)) ;;; alanr found that in certain situations (under ;;; OSGI?) that one has to explicitly FUNCALL the ;;; function slot, so we fall back to that strategy. (ignore-errors (funcall (java:jfield "org.armedbear.lisp.Function" "FUNCTION_CLASS_BYTES") function)))) (disassemble-bytes (read-byte-array-from-stream (java:jcall-raw "getResourceAsStream" (java:jcall-raw "getClassLoader" class) (class-resource-path class))))))))))) (defparameter +propertyList+ (load-time-value (let ((it (find "propertyList" (java::jcall "getDeclaredFields" (java::jclass "org.armedbear.lisp.Function")) :key (lambda(e)(java::jcall "getName" e)) :test 'equal))) (java::jcall "setAccessible" it t) it))) (defun function-plist (function) (java::jcall "get" +propertylist+ function)) (defun (setf function-plist) (new function) (java::jcall "set" +propertylist+ function new)) ;; PITA. make loadedFrom public ;;; TODO Java9 work out a sensible story to preserve existing values if required (defun get-loaded-from (function) (let* ((jfield (find "loadedFrom" (java:jcall "getDeclaredFields" (java:jclass "org.armedbear.lisp.Function")) :key 'java:jfield-name :test 'equal))) (java:jcall "setAccessible" jfield java:+true+) (java:jcall "get" jfield function))) (defun set-loaded-from (function value) (let* ((jfield (find "loadedFrom" (java:jcall "getDeclaredFields" (java:jclass "org.armedbear.lisp.Function")) :key 'java:jfield-name :test 'equal))) (java:jcall "setAccessible" jfield java:+true+) (java:jcall "set" jfield function value))) ;; because getFunctionClassBytes gets a null pointer exception (defun fasl-compiled-closure-class-bytes (function) (let* ((loaded-from (get-loaded-from function)) (class-name (subseq (java:jcall "getName" (java:jcall "getClass" function)) (length "org.armedbear.lisp."))) (url (if (not (eq (pathname-device loaded-from) :unspecific)) ;; we're loading from a jar (java:jnew "java.net.URL" (namestring (make-pathname :directory (pathname-directory loaded-from) :device (pathname-device loaded-from) :name class-name :type "cls"))) ;; we're loading from a fasl file (java:jnew "java.net.URL" (namestring (make-pathname :device (list loaded-from) :name class-name :type "cls")))))) (read-byte-array-from-stream (java:jcall "openStream" url)))) ;; closure bindings ;; (get-java-field (elt (#"get" (elt (#"getFields" (#"getClass" #'foo)) 0) #'foo) 0) "value") (defun disassemble (arg) (print-lines-with-prefix (disassemble-function arg))) (defun print-lines-with-prefix (string) (with-input-from-string (stream string) (loop (let ((line (read-line stream nil))) (unless line (return)) (write-string "; ") (write-string line) (terpri))))) abcl-src-1.9.0/src/org/armedbear/lisp/disassemble_class_bytes.java0100644 0000000 0000000 00000006662 14202767264 023762 0ustar000000000 0000000 /* * disassemble_class_bytes.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; // ### disassemble-class-bytes public final class disassemble_class_bytes extends Primitive { private disassemble_class_bytes() { super("disassemble-class-bytes", PACKAGE_SYS, true, "java-object"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof JavaObject) { byte[] bytes = (byte[]) ((JavaObject)arg).getObject(); try { File file = File.createTempFile("abcl", ".class", null); FileOutputStream out = new FileOutputStream(file); out.write(bytes); out.close(); LispObject disassembler = _DISASSEMBLER_.symbolValue(); StringBuffer command = new StringBuffer(); if (disassembler instanceof AbstractString) { command.append(disassembler.getStringValue()); command.append(" "); command.append(file.getPath()); } else if (disassembler instanceof Operator) { Pathname p = Pathname.makePathname(file); LispObject commandResult = disassembler.execute(p); command.append(commandResult.getStringValue()); } else { return new SimpleString("No disassembler is available."); } ShellCommand sc = new ShellCommand(command.toString(), null, null); sc.run(); file.delete(); return new SimpleString(sc.getOutput()); } catch (IOException e) { Debug.trace(e); } } return NIL; } private static final Primitive DISASSEMBLE_CLASS_BYTES = new disassemble_class_bytes(); } abcl-src-1.9.0/src/org/armedbear/lisp/do-all-symbols.lisp0100644 0000000 0000000 00000004572 14202767264 021756 0ustar000000000 0000000 ;;; do-all-symbols.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (defmacro do-all-symbols ((var &optional result-form) &body body) (multiple-value-bind (forms decls) (parse-body body nil) (let ((flet-name (gensym "DO-SYMBOLS-"))) `(block nil (flet ((,flet-name (,var) ,@decls (tagbody ,@forms))) (mapc #'(lambda (package) (flet ((iterate-over-symbols (symbols) (mapc #',flet-name symbols))) (iterate-over-symbols (package-internal-symbols package)) (iterate-over-symbols (package-external-symbols package)))) (list-all-packages))) (let ((,var nil)) (declare (ignorable ,var)) ,@decls ,result-form))))) abcl-src-1.9.0/src/org/armedbear/lisp/do-external-symbols.lisp0100644 0000000 0000000 00000003343 14202767264 023023 0ustar000000000 0000000 ;;; do-external-symbols.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defmacro do-external-symbols ((var &optional (package '*package*) (result nil)) &body body) `(dolist (,var (sys::package-external-symbols ,package) ,result) ,@body)) abcl-src-1.9.0/src/org/armedbear/lisp/do-symbols.lisp0100644 0000000 0000000 00000003442 14202767264 021203 0ustar000000000 0000000 ;;; do-symbols.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defmacro do-symbols ((var &optional (package '*package*) (result nil)) &body body) `(dolist (,var (append (package-symbols ,package) (package-inherited-symbols ,package)) ,result) ,@body)) abcl-src-1.9.0/src/org/armedbear/lisp/do.lisp0100644 0000000 0000000 00000006167 14223403213 017504 0ustar000000000 0000000 ;;; do.lisp ;;; ;;; Copyright (C) 2004-2006 Peter Graves ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package "SYSTEM") (defun do-do-body (varlist endlist decls-and-code bind step name block) (let* ((inits ()) (steps ()) (L1 (gensym)) (L2 (gensym))) ;; Check for illegal old-style do. (when (or (not (listp varlist)) (atom endlist)) (error "Ill-formed ~S -- possibly illegal old style DO?" name)) ;; Parse the varlist to get inits and steps. (dolist (v varlist) (cond ((symbolp v) (push v inits)) ((listp v) (unless (symbolp (first v)) (error "~S step variable is not a symbol: ~S" name (first v))) (case (length v) (1 (push (first v) inits)) (2 (push v inits)) (3 (push (list (first v) (second v)) inits) (setq steps (list* (third v) (first v) steps))) (t (error "~S is an illegal form for a ~S varlist." v name)))) (t (error "~S is an illegal form for a ~S varlist." v name)))) ;; Construct the new form. (multiple-value-bind (code decls) (parse-body decls-and-code nil) `(block ,block (,bind ,(nreverse inits) ,@decls (tagbody (go ,L2) ,L1 ,@code (,step ,@(nreverse steps)) ,L2 (unless ,(car endlist) (go ,L1)) (return-from ,block (progn ,@(cdr endlist))))))))) (defmacro do (varlist endlist &rest body) (do-do-body varlist endlist body 'let 'psetq 'do nil)) (defmacro do* (varlist endlist &rest body) (do-do-body varlist endlist body 'let* 'setq 'do* nil)) abcl-src-1.9.0/src/org/armedbear/lisp/documentation.lisp0100644 0000000 0000000 00000015264 14202767264 021771 0ustar000000000 0000000 ;;; documentation.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; Copyright (C) 2010-2013 Mark Evenson ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:mop) (require "CLOS") (defgeneric documentation (x doc-type) (:method ((x symbol) doc-type) (%documentation x doc-type)) (:method ((x function) doc-type) (%documentation x doc-type))) (defgeneric (setf documentation) (new-value x doc-type) (:method (new-value (x symbol) doc-type) (%set-documentation x doc-type new-value)) (:method (new-value (x function) doc-type) (%set-documentation x doc-type new-value))) ;; FIXME This should be a weak hashtable! (defvar *list-documentation-hashtable* (make-hash-table :test #'equal)) (defmethod documentation ((x list) (doc-type (eql 'function))) (let ((alist (gethash x *list-documentation-hashtable*))) (and alist (cdr (assoc doc-type alist))))) (defmethod documentation ((x list) (doc-type (eql 'compiler-macro))) (let ((alist (gethash x *list-documentation-hashtable*))) (and alist (cdr (assoc doc-type alist))))) (defmethod (setf documentation) (new-value (x list) (doc-type (eql 'function))) (let* ((alist (gethash x *list-documentation-hashtable*)) (entry (and alist (assoc doc-type alist)))) (cond (entry (setf (cdr entry) new-value)) (t (setf (gethash x *list-documentation-hashtable*) (push (cons doc-type new-value) alist))))) new-value) (defmethod (setf documentation) (new-value (x list) (doc-type (eql 'compiler-macro))) (let* ((alist (gethash x *list-documentation-hashtable*)) (entry (and alist (assoc doc-type alist)))) (cond (entry (setf (cdr entry) new-value)) (t (setf (gethash x *list-documentation-hashtable*) (push (cons doc-type new-value) alist))))) new-value) (defmethod documentation ((x class) (doc-type (eql 't))) (class-documentation x)) (defmethod documentation ((x class) (doc-type (eql 'type))) (class-documentation x)) (defmethod (setf documentation) (new-value (x class) (doc-type (eql 't))) (%set-class-documentation x new-value)) (defmethod (setf documentation) (new-value (x class) (doc-type (eql 'type))) (%set-class-documentation x new-value)) (defmethod documentation ((x structure-class) (doc-type (eql 't))) (%documentation x t)) (defmethod documentation ((x structure-class) (doc-type (eql 'type))) (%documentation x t)) (defmethod (setf documentation) (new-value (x structure-class) (doc-type (eql 't))) (%set-documentation x t new-value)) (defmethod (setf documentation) (new-value (x structure-class) (doc-type (eql 'type))) (%set-documentation x t new-value)) (defmethod documentation ((x standard-generic-function) (doc-type (eql 't))) (std-slot-value x 'sys::%documentation)) (defmethod (setf documentation) (new-value (x standard-generic-function) (doc-type (eql 't))) (setf (std-slot-value x 'sys::%documentation) new-value)) (defmethod documentation ((x standard-generic-function) (doc-type (eql 'function))) (std-slot-value x 'sys::%documentation)) (defmethod (setf documentation) (new-value (x standard-generic-function) (doc-type (eql 'function))) (setf (std-slot-value x 'sys::%documentation) new-value)) (defmethod documentation ((x standard-method) (doc-type (eql 't))) (method-documentation x)) (defmethod (setf documentation) (new-value (x standard-method) (doc-type (eql 't))) (setf (method-documentation x) new-value)) (defmethod documentation ((x standard-slot-definition) (doc-type (eql 't))) (slot-definition-documentation x)) (defmethod (setf documentation) (new-value (x standard-slot-definition) (doc-type (eql 't))) (setf (slot-definition-documentation x) new-value)) (defmethod documentation ((x package) (doc-type (eql 't))) (%documentation x doc-type)) (defmethod (setf documentation) (new-value (x package) (doc-type (eql 't))) (%set-documentation x doc-type new-value)) (defmethod documentation ((x symbol) (doc-type (eql 'function))) (if (and (fboundp x) (typep (fdefinition x) 'generic-function)) (documentation (fdefinition x) doc-type) (%documentation x doc-type))) (defmethod (setf documentation) (new-value (x symbol) (doc-type (eql 'function))) (if (and (fboundp x) (typep (fdefinition x) 'generic-function)) (setf (documentation (fdefinition x) 'function) new-value) (%set-documentation x 'function new-value))) (defmethod documentation ((x symbol) (doc-type (eql 'type))) (let ((class (find-class x nil))) (if class (documentation class t) (%documentation x 'type)))) (defmethod documentation ((x symbol) (doc-type (eql 'structure))) (%documentation x 'structure)) (defmethod (setf documentation) (new-value (x symbol) (doc-type (eql 'type))) (let ((class (find-class x nil))) (if class (setf (documentation class t) new-value) (%set-documentation x 'type new-value)))) (defmethod (setf documentation) (new-value (x symbol) (doc-type (eql 'structure))) (%set-documentation x 'structure new-value)) abcl-src-1.9.0/src/org/armedbear/lisp/dolist.java0100644 0000000 0000000 00000010462 14206360343 020352 0ustar000000000 0000000 /* * dolist.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### dolist public final class dolist extends SpecialOperator { private dolist() { super(Symbol.DOLIST); } @Override public LispObject execute(LispObject args, Environment env) { LispObject bodyForm = args.cdr(); args = args.car(); Symbol var = checkSymbol(args.car()); LispObject listForm = args.cadr(); final LispThread thread = LispThread.currentThread(); LispObject resultForm = args.cdr().cdr().car(); final SpecialBindingsMark mark = thread.markSpecialBindings(); // Process declarations. LispObject bodyAndDecls = parseBody(bodyForm, false); LispObject specials = parseSpecials(bodyAndDecls.NTH(1)); bodyForm = bodyAndDecls.car(); LispObject blockId = new LispObject(); final Environment ext = new Environment(env); thread.envStack.push(ext); try { // Implicit block. ext.addBlock(NIL, blockId); // Evaluate the list form. LispObject list = checkList(eval(listForm, ext, thread)); // Look for tags. LispObject remaining = bodyForm; LispObject localTags = preprocessTagBody(bodyForm, ext); final Object binding; if (specials != NIL && memq(var, specials)) { thread.bindSpecial(var, null); binding = thread.getSpecialBinding(var); ext.declareSpecial(var); } else if (var.isSpecialVariable()) { thread.bindSpecial(var, null); binding = thread.getSpecialBinding(var); } else { ext.bind(var, null); binding = ext.getBinding(var); } while (specials != NIL) { ext.declareSpecial(checkSymbol(specials.car())); specials = specials.cdr(); } while (list != NIL) { if (binding instanceof SpecialBinding) ((SpecialBinding)binding).value = list.car(); else ((Binding)binding).value = list.car(); processTagBody(bodyForm, localTags, ext); list = list.cdr(); if (interrupted) handleInterrupt(); } if (binding instanceof SpecialBinding) ((SpecialBinding)binding).value = NIL; else ((Binding)binding).value = NIL; LispObject result = eval(resultForm, ext, thread); return result; } catch (Return ret) { if (ret.getBlock() == blockId) { return ret.getResult(); } throw ret; } finally { while (thread.envStack.pop() != ext) {}; thread.resetSpecialBindings(mark); ext.inactive = true; } } private static final dolist DOLIST = new dolist(); } abcl-src-1.9.0/src/org/armedbear/lisp/dolist.lisp0100644 0000000 0000000 00000005322 14202767264 020410 0ustar000000000 0000000 ;;; dolist.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (defmacro dolist ((var list-form &optional (result-form nil)) &body body) ;; We repeatedly bind the var instead of setting it so that we never ;; have to give the var an arbitrary value such as NIL (which might ;; conflict with a declaration). If there is a result form, we ;; introduce a gratuitous binding of the variable to NIL without the ;; declarations, then evaluate the result form in that ;; environment. We spuriously reference the gratuitous variable, ;; since we don't want to use IGNORABLE on what might be a special ;; var. (multiple-value-bind (forms decls) (parse-body body nil) (let ((list (gensym "LIST-")) (top (gensym "TOP-"))) `(block nil (let ((,list ,list-form)) (tagbody ,top (unless (endp ,list) (let ((,var (%car ,list))) ,@decls (setq ,list (%cdr ,list)) (tagbody ,@forms)) (go ,top)))) ,(if (constantp result-form) `,result-form `(let ((,var nil)) ,@decls ,var ,result-form)))))) abcl-src-1.9.0/src/org/armedbear/lisp/dotimes.java0100644 0000000 0000000 00000012303 14223403213 020505 0ustar000000000 0000000 /* * dotimes.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class dotimes extends SpecialOperator { private dotimes() { super(Symbol.DOTIMES); } @Override public LispObject execute(LispObject args, Environment env) { LispObject bodyForm = args.cdr(); args = args.car(); Symbol var = checkSymbol(args.car()); LispObject countForm = args.cadr(); final LispThread thread = LispThread.currentThread(); LispObject resultForm = args.cdr().cdr().car(); final SpecialBindingsMark mark = thread.markSpecialBindings(); LispObject bodyAndDecls = parseBody(bodyForm, false); LispObject specials = parseSpecials(bodyAndDecls.NTH(1)); bodyForm = bodyAndDecls.car(); LispObject blockId = new LispObject(); final Environment ext = new Environment(env); thread.envStack.push(ext); try { ext.addBlock(NIL, blockId); LispObject limit = eval(countForm, ext, thread); LispObject localTags = preprocessTagBody(bodyForm, ext); LispObject result; // Establish a reusable binding. final Object binding; if (specials != NIL && memq(var, specials)) { thread.bindSpecial(var, null); binding = thread.getSpecialBinding(var); ext.declareSpecial(var); } else if (var.isSpecialVariable()) { thread.bindSpecial(var, null); binding = thread.getSpecialBinding(var); } else { ext.bind(var, null); binding = ext.getBinding(var); } while (specials != NIL) { ext.declareSpecial(checkSymbol(specials.car())); specials = specials.cdr(); } if (limit instanceof Fixnum) { int count = ((Fixnum)limit).value; int i; for (i = 0; i < count; i++) { if (binding instanceof SpecialBinding) ((SpecialBinding)binding).value = Fixnum.getInstance(i); else ((Binding)binding).value = Fixnum.getInstance(i); processTagBody(bodyForm, localTags, ext); if (interrupted) handleInterrupt(); } if (binding instanceof SpecialBinding) ((SpecialBinding)binding).value = Fixnum.getInstance(i); else ((Binding)binding).value = Fixnum.getInstance(i); result = eval(resultForm, ext, thread); } else if (limit instanceof Bignum) { LispObject i = Fixnum.ZERO; while (i.isLessThan(limit)) { if (binding instanceof SpecialBinding) ((SpecialBinding)binding).value = i; else ((Binding)binding).value = i; processTagBody(bodyForm, localTags, ext); i = i.incr(); if (interrupted) handleInterrupt(); } if (binding instanceof SpecialBinding) ((SpecialBinding)binding).value = i; else ((Binding)binding).value = i; result = eval(resultForm, ext, thread); } else return type_error(limit, Symbol.INTEGER); return result; } catch (Return ret) { if (ret.getBlock() == blockId) { return ret.getResult(); } throw ret; } finally { thread.resetSpecialBindings(mark); ext.inactive = true; while (thread.envStack.pop() != ext) {}; } } private static final dotimes DOTIMES = new dotimes(); } abcl-src-1.9.0/src/org/armedbear/lisp/dotimes.lisp0100644 0000000 0000000 00000006133 14202767264 020557 0ustar000000000 0000000 ;;; dotimes.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defmacro dotimes ((var count &optional (result nil)) &body body) (multiple-value-bind (forms decls) (parse-body body nil) (let ((index (gensym "INDEX-")) (top (gensym "TOP-"))) (if (numberp count) `(block nil (let ((,var 0) (,index 0)) (declare (type (integer 0 ,count) ,index)) (declare (ignorable ,var)) ,@decls (when (> ,count 0) (tagbody ,top ,@forms (setq ,index (1+ ,index)) (setq ,var ,index) (when (< ,index ,count) (go ,top)))) (progn ,result))) (let ((limit (gensym "LIMIT-"))) ;; Annotations for the compiler. (setf (get limit 'dotimes-limit-variable-p) t) (setf (get index 'dotimes-index-variable-name) index) (setf (get index 'dotimes-index-variable-p) t) (setf (get limit 'dotimes-limit-variable-name) limit) `(block nil (let ((,var 0) (,limit ,count) (,index 0)) (declare (ignorable ,var)) ,@decls (when (> ,limit 0) (tagbody ,top ,@forms (setq ,index (1+ ,index)) (setq ,var ,index) (when (< ,index ,limit) (go ,top)))) (progn ,result)))))))) abcl-src-1.9.0/src/org/armedbear/lisp/dribble.lisp0100644 0000000 0000000 00000010677 14223403213 020506 0ustar000000000 0000000 ;;; dribble.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Each time we start dribbling to a new stream, we put it in ;;; *DRIBBLE-STREAM*, and push a list of *DRIBBLE-STREAM*, *STANDARD-INPUT*, ;;; *STANDARD-OUTPUT* and *ERROR-OUTPUT* in *PREVIOUS-DRIBBLE-STREAMS*. ;;; *STANDARD-OUTPUT* and *ERROR-OUTPUT* is changed to a broadcast stream that ;;; broadcasts to *DRIBBLE-STREAM* and to the old values of the variables. ;;; *STANDARD-INPUT* is changed to an echo stream that echos input from the old ;;; value of standard input to *DRIBBLE-STREAM*. ;;; ;;; When dribble is called with no arguments, *DRIBBLE-STREAM* is closed, ;;; and the values of *DRIBBLE-STREAM*, *STANDARD-INPUT*, and ;;; *STANDARD-OUTPUT* are popped from *PREVIOUS-DRIBBLE-STREAMS*. ;;; From SBCL. (in-package "SYSTEM") (defvar *previous-dribble-streams* nil) (defvar *dribble-stream* nil) (defun dribble (&optional pathname &key (if-exists :append)) "With a file name as an argument, dribble opens the file and sends a record of further I/O to that file. Without an argument, it closes the dribble file, and quits logging." (cond (pathname (let* ((new-dribble-stream (open pathname :direction :output :if-exists if-exists :if-does-not-exist :create)) (new-standard-output (make-broadcast-stream *standard-output* new-dribble-stream)) (new-error-output (make-broadcast-stream *error-output* new-dribble-stream)) (new-standard-input (make-echo-stream *standard-input* new-dribble-stream))) (push (list *dribble-stream* *standard-input* *standard-output* *error-output*) *previous-dribble-streams*) (setf *dribble-stream* new-dribble-stream) (setf *standard-input* new-standard-input) (setf *standard-output* new-standard-output) (setf *error-output* new-error-output) ;; Starting a new internal REPL for dribbling (loop do (format t "~a> " (package-name *package*)) (with-simple-restart (abort "Error detected in dribbling") (handler-case (let ((input (read *standard-input*))) (print (eval input) *standard-output*) (terpri) (when (equal input '(dribble)) (return))) (error (c) (format *error-output* "~a~%" c) (error c))))))) ((null *dribble-stream*) (error "Not currently dribbling.")) (t (let ((old-streams (pop *previous-dribble-streams*))) (close *dribble-stream*) (setf *dribble-stream* (first old-streams)) (setf *standard-input* (second old-streams)) (setf *standard-output* (third old-streams)) (setf *error-output* (fourth old-streams))))) (values)) abcl-src-1.9.0/src/org/armedbear/lisp/dump-class.lisp0100644 0000000 0000000 00000021021 14202767264 021154 0ustar000000000 0000000 ;;; dump-class.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (require '#:jvm-instructions) (in-package #:jvm) (defvar *pool* nil) (defun read-u1 (stream) (read-byte stream)) (defun read-u2 (stream) (+ (ash (read-byte stream) 8) (read-byte stream))) (defun read-u4 (stream) (+ (ash (read-u2 stream) 16) (read-u2 stream))) (defun lookup-utf8 (index) (let ((entry (svref *pool* index))) (when (eql (car entry) 1) (caddr entry)))) (defun read-constant-pool-entry (stream) (let ((tag (read-u1 stream))) (case tag ((7 8) (list tag (read-u2 stream))) (1 ` (let* ((len (read-u2 stream)) (s (make-string len))) (dotimes (i len) (setf (char s i) (code-char (read-u1 stream)))) (list tag len s))) ((3 4) (list tag (read-u4 stream))) ((5 6) (list tag (read-u4 stream) (read-u4 stream))) ((12 9 10 11) (list tag (read-u2 stream) (read-u2 stream))) (t (error "READ-CONSTANT-POOL-ENTRY unhandled tag ~D" tag))))) (defvar *indent* 0) (defparameter *spaces* (make-string 256 :initial-element #\space)) (defmacro out (&rest args) `(progn (format t (subseq *spaces* 0 *indent*)) (format t ,@args))) (defun dump-code (code) (let ((code-length (length code))) (do ((i 0)) ((>= i code-length)) (let* ((opcode (svref code i)) (size (opcode-size opcode))) (out "~D: ~D (#x~X) ~A~%" i opcode opcode (opcode-name opcode)) (incf i) (dotimes (j (1- size)) (let ((byte (svref code i))) (out "~D: ~D (#x~X)~%" i byte byte)) (incf i)))))) (defun dump-code-attribute (stream) (let ((*indent* (+ *indent* 2))) (out "Stack: ~D~%" (read-u2 stream)) (out "Locals: ~D~%" (read-u2 stream)) (let* ((code-length (read-u4 stream)) (code (make-array code-length))) (out "Code length: ~D~%" code-length) (out "Code:~%") (dotimes (i code-length) (setf (svref code i) (read-u1 stream))) (let ((*indent* (+ *indent* 2))) (dump-code code))) (let ((exception-table-length (read-u2 stream))) (out "Exception table length: ~D~%" exception-table-length) (let ((*indent* (+ *indent* 2))) (dotimes (i exception-table-length) (out "Start PC: ~D~%" (read-u2 stream)) (out "End PC: ~D~%" (read-u2 stream)) (out "Handler PC: ~D~%" (read-u2 stream)) (out "Catch type: ~D~%" (read-u2 stream))))) (let ((attributes-count (read-u2 stream))) (out "Number of attributes: ~D~%" attributes-count) (let ((*indent* (+ *indent* 2))) (dotimes (i attributes-count) (read-attribute i stream)))))) (defun dump-exceptions (stream) (declare (ignore stream)) ) (defun read-attribute (index stream) (let* ((name-index (read-u2 stream)) (name (lookup-utf8 name-index)) (length (read-u4 stream)) (*indent* (+ *indent* 2))) (out "Attribute ~D: Name index: ~D (~S)~%" index name-index name) (out "Attribute ~D: Length: ~D~%" index length) (cond ((string= name "Code") (dump-code-attribute stream)) ((string= name "Exceptions") (let ((count (read-u2 stream))) (out "Attribute ~D: Number of exceptions: ~D~%" index count) (let ((*indent* (+ *indent* 2))) (dotimes (i count) (out "Exception ~D: ~D~%" i (read-u2 stream)))))) ((string= name "SourceFile") (let ((source-file-index (read-u2 stream))) (out "Attribute ~D: Source file index: ~D (~S)~%" index source-file-index (lookup-utf8 source-file-index)))) (t (dotimes (i length) (read-u1 stream)))))) (defun read-info (index stream type) (let* ((access-flags (read-u2 stream)) (name-index (read-u2 stream)) (descriptor-index (read-u2 stream)) (attributes-count (read-u2 stream)) (*indent* (+ *indent* 2)) (type (case type ('field "Field") ('method "Method")))) (out "~A ~D: Access flags: #x~X~%" type index access-flags) (out "~A ~D: Name index: ~D (~S)~%" type index name-index (lookup-utf8 name-index)) (out "~A ~D: Descriptor index: ~D~%" type index descriptor-index) (out "~A ~D: Number of attributes: ~D~%" type index attributes-count) (let ((*indent* (+ *indent* 2))) (dotimes (i attributes-count) (read-attribute i stream))))) (defun dump-class (filename) (let ((*indent* 0) (*pool* nil)) (with-open-file (stream filename :direction :input :element-type 'unsigned-byte) (handler-bind ((end-of-file #'(lambda (c) (return-from dump-class c)))) (out "Magic number: #x~X~%" (read-u4 stream)) (let ((minor (read-u2 stream)) (major (read-u2 stream))) (out "Version: ~D.~D~%" major minor)) ;; Constant pool. (let ((count (read-u2 stream)) entry type) (out "Constant pool (~D entries):~%" count) (setq *pool* (make-array count)) (let ((*indent* (+ *indent* 2))) (dotimes (index (1- count)) (setq entry (read-constant-pool-entry stream)) (setf (svref *pool* (1+ index)) entry) (setq type (case (car entry) (7 'class) (9 'field) (10 'method) (11 'interface) (8 'string) (3 'integer) (4 'float) (5 'long) (6 'double) (12 'name-and-type) (1 'utf8))) (out "~D: ~A ~S~%" (1+ index) type entry)))) (out "Access flags: #x~X~%" (read-u2 stream)) (out "This class: ~D~%" (read-u2 stream)) (out "Superclass: ~D~%" (read-u2 stream)) ;; Interfaces. (let ((count (read-u2 stream))) (cond ((zerop count) (out "No interfaces~%")) (t (out "Interfaces (~D):~%" count) (dotimes (i count) (out " ~D: ~D~%" i (read-u2 stream)))))) ;; Fields. (let ((count (read-u2 stream))) (cond ((zerop count) (out "No fields~%")) (t (out "Fields (~D):~%" count))) (dotimes (index count) (read-info index stream 'field))) ;; Methods. (let ((count (read-u2 stream))) (cond ((zerop count) (out "No methods~%")) (t (out "Methods (~D):~%" count))) (dotimes (index count) (read-info index stream 'method))) ;; Attributes. (let ((count (read-u2 stream))) (cond ((zerop count) (out "No attributes~%")) (t (out "Attributes (~D):~%" count))) (dotimes (index count) (read-attribute index stream)))))) t) abcl-src-1.9.0/src/org/armedbear/lisp/dump-form.lisp0100644 0000000 0000000 00000024623 14202767264 021025 0ustar000000000 0000000 ;;; dump-form.lisp ;;; ;;; Copyright (C) 2004-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (export '(dump-form dump-uninterned-symbol-index)) (declaim (special *circularity* *circle-counter* *instance-forms*)) (defun get-instance-form (object) (multiple-value-bind (value presence) (gethash object *instance-forms*) (cond (presence value) (t (multiple-value-bind (creation-form initialization-form) (make-load-form object) (if initialization-form (let* ((instance (gensym)) load-form) (setf initialization-form (subst instance object initialization-form)) (setf initialization-form (subst instance (list 'quote instance) initialization-form :test #'equal)) (setf load-form `(progn (let ((,instance ,creation-form)) ,initialization-form ,instance))) (setf (gethash object *instance-forms*) load-form)) (setf (gethash object *instance-forms*) creation-form))))))) (defun df-register-circularity (object) (setf (gethash object *circularity*) (if (gethash object *circularity*) :circular t))) (defun df-check-cons (object) (loop (df-check-object (car object)) (setf object (cdr object)) (when (atom object) (df-check-object object) (return)) (when (null object) (return-from df-check-cons)) (when (eq :circular (df-register-circularity object)) (return)))) (defun df-check-vector (object) (dotimes (index (length object)) (df-check-object (aref object index)))) (defun df-check-instance (object) (df-check-object (get-instance-form object))) (defun df-check-object (object) (unless (eq :circular (df-register-circularity object)) (cond ((consp object) (df-check-cons object)) ((vectorp object) (df-check-vector object)) ((or (structure-object-p object) (standard-object-p object) (java:java-object-p object)) (df-check-instance object))))) (defun df-handle-circularity (object stream within-list) (let ((index (gethash object *circularity*))) (cond ((eq index :circular) (setf index (incf *circle-counter*)) (setf (gethash object *circularity*) index) (when within-list (write-string " . " stream)) (%stream-write-char #\# stream) (write index :stream stream) (%stream-write-char #\= stream) (when within-list (dump-cons object stream) ;; ### *cough* (return-from df-handle-circularity t)) (return-from df-handle-circularity)) ((integerp index) (when within-list (write-string " . " stream)) (%stream-write-char #\# stream) (write index :stream stream) (%stream-write-char #\# stream) (%stream-write-char #\Space stream) (return-from df-handle-circularity t)) (t (unless *prevent-fasl-circle-detection* (assert (or (eq index t) (integerp object)))))))) ;; strictly this should be 'long' (declaim (ftype (function (cons stream) t) dump-cons)) (defun dump-cons (object stream) (cond ((and (eq (car object) 'QUOTE) (proper-list-of-length-p object 2)) (%stream-write-char #\' stream) (dump-object (%cadr object) stream)) (t (%stream-write-char #\( stream) (loop (dump-object (%car object) stream) (setf object (%cdr object)) (when (null object) (return)) ;; escape loop (%stream-write-char #\space stream) (when (atom object) (%stream-write-char #\. stream) (%stream-write-char #\space stream) (dump-object object stream) (return)) (when (df-handle-circularity object stream t) (return)) (when (> (charpos stream) 80) (%stream-terpri stream))) (%stream-write-char #\) stream)))) (declaim (ftype (function (t stream) t) dump-vector)) (defun dump-vector (object stream) (write-string "#(" stream) (let ((length (length object))) (when (> length 0) (dotimes (i (1- length)) (declare (type index i)) (dump-object (aref object i) stream) (when (> (charpos stream) 80) (%stream-terpri stream)) (%stream-write-char #\space stream)) (dump-object (aref object (1- length)) stream)) (%stream-write-char #\) stream))) (declaim (ftype (function (t stream) t) dump-instance)) (defun dump-instance (object stream) (write-string "#." stream) (dump-object (get-instance-form object) stream)) (declaim (ftype (function (symbol) integer) dump-uninterned-symbol-index)) (defun dump-uninterned-symbol-index (symbol) (let ((index (cdr (assoc symbol *fasl-uninterned-symbols*)))) (unless index (setq index (1+ (or (cdar *fasl-uninterned-symbols*) -1))) (setq *fasl-uninterned-symbols* (acons symbol index *fasl-uninterned-symbols*))) index)) (declaim (ftype (function (pathname stream) t) dump-pathname)) (defun dump-pathname (pathname stream) (write-string "#P(" stream) (write-string ":HOST " stream) (dump-form (pathname-host pathname) stream) (write-string " :DEVICE " stream) (dump-form (pathname-device pathname) stream) (write-string " :DIRECTORY " stream) (dump-form (pathname-directory pathname) stream) (write-string " :NAME " stream) (dump-form (pathname-name pathname) stream) (write-string " :TYPE " stream) (dump-form (pathname-type pathname) stream) (write-string " :VERSION " stream) (dump-form (pathname-version pathname) stream) (write-string ")" stream)) (declaim (ftype (function (t stream) t) dump-object)) (defun dump-object (object stream) (unless (df-handle-circularity object stream nil) (cond ((consp object) (dump-cons object stream)) ((stringp object) (%stream-output-object object stream)) ((pathnamep object) (dump-pathname object stream)) ((bit-vector-p object) (%stream-output-object object stream)) ((vectorp object) (dump-vector object stream)) ((or (structure-object-p object) ;; FIXME instance-p (standard-object-p object) (java:java-object-p object)) (dump-instance object stream)) ((and (symbolp object) ;; uninterned symbol (null (symbol-package object))) (write-string "#" stream) (write (dump-uninterned-symbol-index object) :stream stream) (write-string "?" stream)) (t (%stream-output-object object stream))))) (defvar *the-fasl-printer-readtable* (copy-readtable (get-fasl-readtable)) "This variable holds a copy of the FASL readtable which we need to bind below, in order to prevent the current readtable from influencing the content being written to the FASL: the READTABLE-CASE setting influences symbol printing.") (defvar *prevent-fasl-circle-detection* nil) (declaim (ftype (function (t stream) t) dump-form)) (defun dump-form (form stream) (let ((*print-fasl* t) (*print-array* t) (*print-base* 10) (*print-case* :upcase) (*print-circle* nil) (*print-escape* t) (*print-gensym* t) (*print-length* nil) (*print-level* nil) (*print-lines* nil) (*print-pretty* nil) (*print-radix* nil) #+nil ;; XXX Some types (q.v. (UNSIGNED-BYTE 32)) don't have a ;; readable syntax because they don't roundtrip to the same ;; type, but still return a Lisp object that "works", albeit ;; perhaps inefficiently when READ from their DUMP-FORM ;; representation. (*print-readably* t) (*print-right-margin* nil) (*print-structure* t) (*readtable* *the-fasl-printer-readtable*) ;; make sure to write all floats with their exponent marker: ;; the dump-time default may not be the same at load-time (*read-default-float-format* nil) ;; these values are also bound by WITH-STANDARD-IO-SYNTAX, ;; but not used by our reader/printer, so don't bind them, ;; for efficiency reasons. ;; (*read-eval* t) ;; (*read-suppress* nil) ;; (*print-miser-width* nil) ;; (*print-pprint-dispatch* (copy-pprint-dispatch nil)) ;; (*read-base* 10) ;; (*read-default-float-format* 'single-float) ;; (*readtable* (copy-readtable nil)) (*circularity* (make-hash-table :test #'eq)) (*instance-forms* (make-hash-table :test #'eq)) (*circle-counter* 0)) ;; (print form) (unless *prevent-fasl-circle-detection* (df-check-object form)) (dump-object form stream))) (provide 'dump-form) abcl-src-1.9.0/src/org/armedbear/lisp/early-defuns.lisp0100644 0000000 0000000 00000025367 14202767264 021523 0ustar000000000 0000000 ;;; early-defuns.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (export '(index java-long %type-error check-sequence-bounds require-type normalize-type)) ;; (deftype index () '(integer 0 (#.most-positive-fixnum))) (put 'index 'deftype-definition (lambda () '(integer 0 (#.most-positive-fixnum)))) ;; (deftype java-long () ;; '(integer #.most-negative-java-long #.most-positive-java-long)) (put 'java-long 'deftype-definition (lambda () '(integer #.most-negative-java-long #.most-positive-java-long))) (defun %type-error (datum expected-type) (error 'type-error :datum datum :expected-type expected-type)) (defun check-sequence-bounds (sequence start end) (declare (optimize speed)) (unless (fixnump start) (%type-error start 'fixnum)) (if end (unless (fixnump end) (%type-error end 'fixnum)) (setf end (length sequence))) end) (defun require-type (arg type) (if (typep arg type) arg (error 'simple-type-error :datum arg :expected-type type))) (defun normalize-type (type) (cond ((symbolp type) (case type (BIT (return-from normalize-type '(integer 0 1))) (CONS (return-from normalize-type '(cons t t))) (FIXNUM (return-from normalize-type '(integer #.most-negative-fixnum #.most-positive-fixnum))) (SIGNED-BYTE (return-from normalize-type 'integer)) (UNSIGNED-BYTE (return-from normalize-type '(integer 0 *))) (BASE-CHAR (return-from normalize-type 'character)) (SHORT-FLOAT (return-from normalize-type 'single-float)) (LONG-FLOAT (return-from normalize-type 'double-float)) (COMPLEX (return-from normalize-type '(complex *))) (ARRAY (return-from normalize-type '(array * *))) (SIMPLE-ARRAY (return-from normalize-type '(simple-array * *))) (VECTOR (return-from normalize-type '(array * (*)))) (SIMPLE-VECTOR (return-from normalize-type '(simple-array t (*)))) (BIT-VECTOR (return-from normalize-type '(bit-vector *))) (SIMPLE-BIT-VECTOR (return-from normalize-type '(simple-bit-vector *))) (BASE-STRING (return-from normalize-type '(array base-char (*)))) (SIMPLE-BASE-STRING (return-from normalize-type '(simple-array base-char (*)))) (STRING (return-from normalize-type '(string *))) (SIMPLE-STRING (return-from normalize-type '(simple-string *))) ((nil) (return-from normalize-type nil)) (t (unless (get type 'deftype-definition) (return-from normalize-type type))))) ((classp type) (return-from normalize-type (if (eq (%class-name type) 'fixnum) '(integer #.most-negative-fixnum #.most-positive-fixnum) type))) ((and (consp type) (memq (%car type) '(and or not eql member satisfies mod values))) (cond ((or (equal type '(and fixnum unsigned-byte)) (equal type '(and unsigned-byte fixnum))) (return-from normalize-type '(integer 0 #.most-positive-fixnum))) (t (return-from normalize-type type))))) ;; Fall through... (let (tp i) (loop (if (consp type) (setf tp (%car type) i (%cdr type)) (setf tp type i nil)) (if (and (symbolp tp) (get tp 'deftype-definition)) (setf type (apply (get tp 'deftype-definition) i)) (return))) (case tp (INTEGER (return-from normalize-type (if i (cons tp i) tp))) (CONS (let* ((len (length i)) (car-typespec (if (> len 0) (car i) t)) (cdr-typespec (if (> len 1) (cadr i) t))) (unless (and car-typespec cdr-typespec) (return-from normalize-type nil)) (when (eq car-typespec '*) (setf car-typespec t)) (when (eq cdr-typespec '*) (setf cdr-typespec t)) (return-from normalize-type (cons tp (list car-typespec cdr-typespec))))) (SIGNED-BYTE (if (or (null i) (eq (car i) '*)) (return-from normalize-type 'integer) (return-from normalize-type (list 'integer (- (expt 2 (1- (car i)))) (1- (expt 2 (1- (car i)))))))) (UNSIGNED-BYTE (if (or (null i) (eq (car i) '*)) (return-from normalize-type '(integer 0 *))) (return-from normalize-type (list 'integer 0 (1- (expt 2 (car i)))))) ((ARRAY SIMPLE-ARRAY) (unless i (return-from normalize-type (list tp '* '*))) (when (= (length i) 1) (setf i (append i '(*)))) (setf (car i) (normalize-type (car i))) (return-from normalize-type (cons tp i))) (VECTOR (case (length i) (0 (return-from normalize-type '(array * (*)))) (1 (setf (car i) (normalize-type (car i))) (return-from normalize-type (list 'array (car i) '(*)))) (2 (setf (car i) (normalize-type (car i))) (return-from normalize-type (list 'array (car i) (list (cadr i))))) (t (error "Invalid type specifier ~S." type)))) (SIMPLE-VECTOR (case (length i) (0 (return-from normalize-type '(simple-array t (*)))) (1 (return-from normalize-type (list 'simple-array t (list (car i))))) (t (error "Invalid type specifier ~S." type)))) (BIT-VECTOR (case (length i) (0 (return-from normalize-type '(bit-vector *))) (1 (return-from normalize-type (list 'bit-vector (car i)))) (t (error "Invalid type specifier ~S." type)))) (SIMPLE-BIT-VECTOR (case (length i) (0 (return-from normalize-type '(simple-bit-vector *))) (1 (return-from normalize-type (list 'simple-bit-vector (car i)))) (t (error "Invalid type specifier ~S." type)))) (BASE-STRING (if i (return-from normalize-type (list 'array 'base-char (list (car i)))) (return-from normalize-type '(array base-char (*))))) (SIMPLE-BASE-STRING (if i (return-from normalize-type (list 'simple-array 'base-char (list (car i)))) (return-from normalize-type '(simple-array base-char (*))))) (SHORT-FLOAT (setf tp 'single-float)) (LONG-FLOAT (setf tp 'double-float)) (COMPLEX (cond ((null i) (return-from normalize-type '(complex *))) ((eq (car i) 'short-float) (return-from normalize-type '(complex single-float))) ((eq (car i) 'long-float) (return-from normalize-type '(complex double-float)))))) (if i (cons tp i) tp))) (defun caaaar (list) (car (car (car (car list))))) (defun caaadr (list) (car (car (car (cdr list))))) (defun caaddr (list) (car (car (cdr (cdr list))))) (defun cadddr (list) (car (cdr (cdr (cdr list))))) (defun cddddr (list) (cdr (cdr (cdr (cdr list))))) (defun cdaaar (list) (cdr (car (car (car list))))) (defun cddaar (list) (cdr (cdr (car (car list))))) (defun cdddar (list) (cdr (cdr (cdr (car list))))) (defun caadar (list) (car (car (cdr (car list))))) (defun cadaar (list) (car (cdr (car (car list))))) (defun cadadr (list) (car (cdr (car (cdr list))))) (defun caddar (list) (car (cdr (cdr (car list))))) (defun cdaadr (list) (cdr (car (car (cdr list))))) (defun cdadar (list) (cdr (car (cdr (car list))))) (defun cdaddr (list) (cdr (car (cdr (cdr list))))) (defun cddadr (list) (cdr (cdr (car (cdr list))))) ;;; SOME, EVERY, NOTANY, NOTEVERY (adapted from ECL) (defun some (predicate sequence &rest more-sequences) (setq more-sequences (cons sequence more-sequences)) (do ((i 0 (1+ i)) (l (apply #'min (mapcar #'length more-sequences)))) ((>= i l) nil) (let ((that-value (apply predicate (mapcar #'(lambda (z) (elt z i)) more-sequences)))) (when that-value (return that-value))))) (defun every (predicate sequence &rest more-sequences) (declare (optimize speed)) (cond ((null more-sequences) (cond ((listp sequence) (dolist (x sequence t) (unless (funcall predicate x) (return nil)))) (t (dotimes (i (length sequence) t) (declare (type index i)) (unless (funcall predicate (elt sequence i)) (return nil)))))) (t (setq more-sequences (cons sequence more-sequences)) (do ((i 0 (1+ i)) (l (apply #'min (mapcar #'length more-sequences)))) ((>= i l) t) (unless (apply predicate (mapcar #'(lambda (z) (elt z i)) more-sequences)) (return nil)))))) (defun notany (predicate sequence &rest more-sequences) (not (apply #'some predicate sequence more-sequences))) (defun notevery (predicate sequence &rest more-sequences) (not (apply #'every predicate sequence more-sequences))) abcl-src-1.9.0/src/org/armedbear/lisp/ed.lisp0100644 0000000 0000000 00000014455 14223403213 017471 0ustar000000000 0000000 ;;; ed.lisp ;;; ;;; Copyright (C) 2004-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (defun ed (&optional x) "Starts the editor (on a file or a function if named). Functions from the list *ED-FUNCTIONS* are called in order with X as an argument until one of them returns non-NIL; these functions are responsible for signalling a FILE-ERROR to indicate failure to perform an operation on the file system." (dolist (fun *ed-functions* (error 'simple-error :format-control "Don't know how to ~S ~A" :format-arguments (list 'ed x))) (when (funcall fun x) (return))) (values)) (defun default-ed-function (what) (let ((portfile (merge-pathnames ".j/port" (if (featurep :windows) (if (ext:probe-directory "C:\\.j") "C:\\" (ext:probe-directory (pathname (ext:getenv "APPDATA")))) (user-homedir-pathname)))) stream) (when (probe-file portfile) (let* ((port (with-open-file (s portfile) (read s nil nil))) (socket (and (integerp port) (ext:make-socket "127.0.0.1" port)))) (setf stream (and socket (ext:get-socket-stream socket))))) (unwind-protect (cond ((stringp what) (if stream (progn (write-string (namestring (user-homedir-pathname)) stream) (terpri stream) (write-string (format nil "~S~%" what) stream)) (run-shell-command (format nil "j ~S" what)))) ((and what (symbolp what)) (when (autoloadp what) (let ((*load-verbose* nil) (*load-print* nil) (*autoload-verbose* nil)) (resolve what))) (cond ((source what) (let ((file (namestring (source-pathname what))) (position (source-file-position what)) (line-number 1) (pattern (string what))) (with-open-file (s file) (dotimes (i position) (let ((c (read-char s nil s))) (cond ((eq c s) (return)) ((eql c #\newline) (incf line-number))))) (dotimes (i 10) (let ((text (read-line s nil s))) (cond ((eq text s) (return)) ((search pattern text :test 'string-equal) (return)) (t (incf line-number)))))) (if stream (progn (write-string (namestring (user-homedir-pathname)) stream) (terpri stream) (write-string (format nil "+~D~%~S~%" line-number file) stream)) (run-shell-command (format nil "j +~D ~S" line-number file))))) ((not (null *lisp-home*)) (let ((tagfile (merge-pathnames "tags" *lisp-home*))) (when (and tagfile (probe-file tagfile)) (with-open-file (s tagfile) (loop (let ((text (read-line s nil s))) (cond ((eq text s) (return)) ((eq what (read-from-string text nil nil)) ;; Found it! (with-input-from-string (string-stream text) (let* ((symbol (read string-stream text nil nil)) ; Ignored. (file (read string-stream text nil nil)) (line-number (read string-stream text nil nil))) (declare (ignore symbol)) (when (pathnamep file) (setf file (namestring file))) (if stream (progn (write-string (namestring (user-homedir-pathname)) stream) (terpri stream) (write-string (format nil "+~D~%~S~%" line-number file) stream)) (run-shell-command (format nil "j +~D ~S" line-number file)))))))))))))))) (when stream (close stream)))) t) abcl-src-1.9.0/src/org/armedbear/lisp/enough-namestring.lisp0100644 0000000 0000000 00000006166 14202767264 022553 0ustar000000000 0000000 ;;; enough-namestring.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (declaim (inline equal-components-p)) (defun equal-components-p (component1 component2) #+win32 (equalp component1 component2) #-win32 (equal component1 component2)) (defun enough-namestring (pathname &optional (defaults *default-pathname-defaults*)) (unless (equal (pathname-host pathname) (pathname-host defaults)) (return-from enough-namestring (namestring pathname))) (let ((pathname-directory (pathname-directory pathname))) (if pathname-directory (let* ((defaults-directory (pathname-directory defaults)) (prefix-len (length defaults-directory)) (result-directory (cond ((and (>= prefix-len 1) (>= (length pathname-directory) prefix-len) (equal-components-p (subseq pathname-directory 0 prefix-len) defaults-directory)) (cons :relative (nthcdr prefix-len pathname-directory))) ((eq (car pathname-directory) :absolute) pathname-directory) (t (return-from enough-namestring (namestring pathname)))))) (if (equal result-directory '(:relative)) (file-namestring pathname) (concatenate 'simple-string (directory-namestring (make-pathname :directory result-directory)) (file-namestring pathname)))) (file-namestring pathname)))) abcl-src-1.9.0/src/org/armedbear/lisp/ensure-directories-exist.lisp0100644 0000000 0000000 00000006461 14223403213 024044 0ustar000000000 0000000 ;;; ensure-directories-exist.lisp ;;; ;;; Copyright (C) 2004-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package "SYSTEM") (defun ensure-directories-exist (pathspec &key (verbose nil)) (let ((pathname (pathname pathspec)) (created-p nil)) ;;; CLHS: Function ENSURE-DIRECTORIES-EXIST "An error of type ;;; file-error is signaled if the host, device, or directory part of ;;; pathspec is wild." (when (or (wild-pathname-p pathname :host) (wild-pathname-p pathname :device) (wild-pathname-p pathname :directory)) (error 'file-error :format-control "Bad place for a wild HOST, DEVICE, or DIRECTORY component." :pathname pathname)) (let ((dir (pathname-directory pathname))) (loop :for i :from 1 :upto (length dir) :doing (let ((newpath (make-pathname :host (pathname-host pathname) :device (if (pathname-device pathname) (pathname-device pathname) :unspecific) :directory (subseq dir 0 i)))) (unless (probe-directory newpath) (when verbose (fresh-line) (format *standard-output* "Creating directory of pathname ~A.~&" newpath)) (mkdir newpath) (unless (probe-directory newpath) (error 'file-error :pathname newpath :format-control "Can't ensure directory~& ~S ~&ancestor of~& ~S." :format-arguments (list newpath pathname))) (setq created-p t))))) (values pathname created-p))) abcl-src-1.9.0/src/org/armedbear/lisp/error.lisp0100644 0000000 0000000 00000000314 14202767264 020237 0ustar000000000 0000000 ;;; error.lisp (in-package "COMMON-LISP") (export '(ignore-errors)) (defmacro ignore-errors (&rest forms) `(handler-case (progn ,@forms) (error (condition) (values nil condition)))) abcl-src-1.9.0/src/org/armedbear/lisp/extensible-sequences-base.lisp0100644 0000000 0000000 00000007611 14223403213 024140 0ustar000000000 0000000 ;;;This file only defines the minimum set of symbols and operators ;;;that is needed to make standard CL sequence functions refer to generic ;;;functions in the SEQUENCE package, without actually definining those ;;;generic functions and supporting code, which is in extensible-sequences.lisp. ;;; ;;;The rationale for splitting the code this way is that CLOS depends on ;;;some sequence functions, and if those in turn depend on CLOS we have ;;;a circular dependency. (in-package :sequence) (shadow '(ELT LENGTH COUNT "COUNT-IF" "COUNT-IF-NOT" "FIND" "FIND-IF" "FIND-IF-NOT" "POSITION" "POSITION-IF" "POSITION-IF-NOT" "SUBSEQ" "COPY-SEQ" "FILL" "NSUBSTITUTE" "NSUBSTITUTE-IF" "NSUBSTITUTE-IF-NOT" "SUBSTITUTE" "SUBSTITUTE-IF" "SUBSTITUTE-IF-NOT" "REPLACE" "REVERSE" "NREVERSE" "REDUCE" "MISMATCH" "SEARCH" "DELETE" "DELETE-IF" "DELETE-IF-NOT" "REMOVE" "REMOVE-IF" "REMOVE-IF-NOT" "DELETE-DUPLICATES" "REMOVE-DUPLICATES" "SORT" "STABLE-SORT")) (export '(DOSEQUENCE MAKE-SEQUENCE-ITERATOR MAKE-SIMPLE-SEQUENCE-ITERATOR ITERATOR-STEP ITERATOR-ENDP ITERATOR-ELEMENT ITERATOR-INDEX ITERATOR-COPY WITH-SEQUENCE-ITERATOR WITH-SEQUENCE-ITERATOR-FUNCTIONS CANONIZE-TEST CANONIZE-KEY LENGTH ELT MAKE-SEQUENCE-LIKE ADJUST-SEQUENCE COUNT COUNT-IF COUNT-IF-NOT FIND FIND-IF FIND-IF-NOT POSITION POSITION-IF POSITION-IF-NOT SUBSEQ COPY-SEQ FILL NSUBSTITUTE NSUBSTITUTE-IF NSUBSTITUTE-IF-NOT SUBSTITUTE SUBSTITUTE-IF SUBSTITUTE-IF-NOT REPLACE REVERSE NREVERSE REDUCE MISMATCH SEARCH DELETE DELETE-IF DELETE-IF-NOT REMOVE REMOVE-IF REMOVE-IF-NOT DELETE-DUPLICATES REMOVE-DUPLICATES SORT STABLE-SORT)) ;;; Adapted from SBCL ;;; SEQ-DISPATCH does an efficient type-dispatch on the given SEQUENCE. ;;; ;;; FIXME: It might be worth making three cases here, LIST, ;;; SIMPLE-VECTOR, and VECTOR, instead of the current LIST and VECTOR. ;;; It tends to make code run faster but be bigger; some benchmarking ;;; is needed to decide. (defmacro seq-dispatch (sequence list-form array-form &optional other-form) `(if (listp ,sequence) (let ((,sequence (ext:truly-the list ,sequence))) (declare (ignorable ,sequence)) ,list-form) ,@(if other-form `((if (arrayp ,sequence) (let ((,sequence (ext:truly-the vector ,sequence))) (declare (ignorable ,sequence)) ,array-form) (if (typep ,sequence 'sequence) ,other-form (error 'type-error :datum ,sequence :expected-type 'sequence)))) `((let ((,sequence (ext:truly-the vector ,sequence))) (declare (ignorable ,sequence)) ,array-form))))) (defun %check-generic-sequence-bounds (seq start end) (let ((length (sequence:length seq))) (if (<= 0 start (or end length) length) (or end length) (sequence-bounding-indices-bad-error seq start end)))) (defun sequence-bounding-indices-bad-error (sequence start end) (let ((size (length sequence))) (error "The bounding indices ~S and ~S are bad for a sequence of length ~S" start end size))) (defun %set-elt (sequence index value) (seq-dispatch sequence (sys::%set-elt sequence index value) (sys::%set-elt sequence index value) (setf (sequence:elt sequence index) value))) (defsetf cl:elt %set-elt) #| (error 'bounding-indices-bad-error :datum (cons start end) :expected-type `(cons (integer 0 ,size) (integer ,start ,size)) :object sequence)))|# (provide "EXTENSIBLE-SEQUENCES-BASE") abcl-src-1.9.0/src/org/armedbear/lisp/extensible-sequences.lisp0100644 0000000 0000000 00000134315 14223403213 023232 0ustar000000000 0000000 ;;;Extensible Sequences for ABCL based on the SBCL API (in-package :sequence) (require "CLOS") (require "EXTENSIBLE-SEQUENCES-BASE") (require "LOOP") #|| We specify generic functions length, elt and (setf elt) to correspond to the Common Lisp functions with the same name. In each case, there are two primary methods with the sequence argument specialized on list and on vector, pro- viding the standard-defined behaviour for the Common Lisp operator, and a third method with the sequence argument specialized on sequence, which signals an error of type type- error, for compatibility with the standard requirement of the sequence argument to be a proper sequence. ||# (fmakunbound 'length) (defgeneric length (sequence) (:documentation "Extension point for user-defined sequences. Invoked by cl:length.")) (defmethod length ((sequence sequence)) (error 'type-error :datum sequence :expected-type 'proper-sequence)) (defmethod length ((sequence vector)) (sys::%length sequence)) (defmethod length ((sequence list)) (sys::%length sequence)) (defmethod length (sequence) (error 'type-error :datum sequence :expected-type 'sequence)) (defun cl:length (sequence) (seq-dispatch sequence (sys::%length sequence) (sys::%length sequence) (length sequence))) (defgeneric elt (sequence index)) (defmethod elt ((sequence vector) index) (sys::%elt sequence index)) (defmethod elt ((sequence list) index) (sys::%elt sequence index)) (defmethod elt ((sequence sequence) index) (declare (ignore index)) (error 'type-error :datum sequence :expected-type 'proper-sequence)) (defmethod elt (sequence index) (declare (ignore index)) (error 'type-error :datum sequence :expected-type 'sequence)) (defun cl:elt (sequence index) (seq-dispatch sequence (sys::%elt sequence index) (sys::%elt sequence index) (elt sequence index))) (defgeneric (setf elt) (value sequence index)) (defmethod (setf elt) (value (sequence vector) index) (sys::%set-elt sequence index value)) (defmethod (setf elt) (value (sequence list) index) (sys::%set-elt sequence index value)) (defmethod (setf elt) (value (sequence sequence) index) (declare (ignore index value)) (error 'type-error :datum sequence :expected-type 'proper-sequence)) (defmethod (setf elt) (value sequence index) (declare (ignore index value)) (error 'type-error :datum sequence :expected-type 'sequence)) (defun cl:subseq (sequence start &optional end) "Return a copy of a subsequence of SEQUENCE starting with element number START and continuing to the end of SEQUENCE or the optional END." (seq-dispatch sequence (sys::%subseq sequence start end) (sys::%subseq sequence start end) (sequence:subseq sequence start end))) (defun cl:reverse (sequence) (seq-dispatch sequence (sys::%reverse sequence) (sys::%reverse sequence) (sequence:reverse sequence))) (defun cl:nreverse (sequence) (seq-dispatch sequence (sys::%nreverse sequence) (sys::%nreverse sequence) (sequence:nreverse sequence))) ;;;Adapted from SBCL (define-condition sequence::protocol-unimplemented (type-error) ()) (defun sequence::protocol-unimplemented (sequence) (error 'sequence::protocol-unimplemented :datum sequence :expected-type '(or list vector))) (defgeneric sequence:make-sequence-like (sequence length &key initial-element initial-contents) (:method ((s list) length &key (initial-element nil iep) (initial-contents nil icp)) (cond ((and icp iep) (error "Can't specify both :initial-element and :initial-contents")) (iep (make-list length :initial-element initial-element)) (icp (unless (= (length initial-contents) length) (error "initial-contents is of length ~S but should be of the same length of the input sequence (~S)" (length initial-contents) length)) (let ((result (make-list length))) (replace result initial-contents) result)) (t (make-list length)))) (:method ((s vector) length &key (initial-element nil iep) (initial-contents nil icp)) (cond ((and icp iep) (error "Can't specify both :initial-element and :initial-contents")) (iep (make-array length :element-type (array-element-type s) :initial-element initial-element)) (icp (make-array length :element-type (array-element-type s) :initial-contents initial-contents)) (t (make-array length :element-type (array-element-type s))))) (:method ((s sequence) length &key initial-element initial-contents) (declare (ignore initial-element initial-contents)) (sequence::protocol-unimplemented s))) (defgeneric sequence:adjust-sequence (sequence length &key initial-element initial-contents) (:method ((s list) length &key initial-element (initial-contents nil icp)) (if (eql length 0) nil (let ((olength (length s))) (cond ((eql length olength) (if icp (replace s initial-contents) s)) ((< length olength) (rplacd (nthcdr (1- length) s) nil) (if icp (replace s initial-contents) s)) ((null s) (let ((return (make-list length :initial-element initial-element))) (if icp (replace return initial-contents) return))) (t (rplacd (nthcdr (1- olength) s) (make-list (- length olength) :initial-element initial-element)) (if icp (replace s initial-contents) s)))))) (:method ((s vector) length &rest args &key (initial-contents nil icp) initial-element) (declare (ignore initial-element)) (cond ((and (array-has-fill-pointer-p s) (>= (array-total-size s) length)) (setf (fill-pointer s) length) (if icp (replace s initial-contents) s)) ((eql (length s) length) (if icp (replace s initial-contents) s)) (t (apply #'adjust-array s length args)))) (:method (new-value (s sequence) &rest args) (declare (ignore args)) (sequence::protocol-unimplemented s))) ;;;; iterator protocol ;;; The general protocol (defgeneric sequence:make-sequence-iterator (sequence &key from-end start end) (:method ((s sequence) &key from-end (start 0) end) (multiple-value-bind (iterator limit from-end) (sequence:make-simple-sequence-iterator s :from-end from-end :start start :end end) (values iterator limit from-end #'sequence:iterator-step #'sequence:iterator-endp #'sequence:iterator-element #'(setf sequence:iterator-element) #'sequence:iterator-index #'sequence:iterator-copy))) (:method ((s t) &key from-end start end) (declare (ignore from-end start end)) (error 'type-error :datum s :expected-type 'sequence))) ;;; the simple protocol: the simple iterator returns three values, ;;; STATE, LIMIT and FROM-END. ;;; magic termination value for list :from-end t (defvar *exhausted* (cons nil nil)) (defgeneric sequence:make-simple-sequence-iterator (sequence &key from-end start end) (:method ((s list) &key from-end (start 0) end) (if from-end (let* ((termination (if (= start 0) *exhausted* (nthcdr (1- start) s))) (init (if (<= (or end (length s)) start) termination (if end (last s (- (length s) (1- end))) (last s))))) (values init termination t)) (cond ((not end) (values (nthcdr start s) nil nil)) (t (let ((st (nthcdr start s))) (values st (nthcdr (- end start) st) nil)))))) (:method ((s vector) &key from-end (start 0) end) (let ((end (or end (length s)))) (if from-end (values (1- end) (1- start) t) (values start end nil)))) (:method ((s sequence) &key from-end (start 0) end) (let ((end (or end (length s)))) (if from-end (values (1- end) (1- start) from-end) (values start end nil))))) (defgeneric sequence:iterator-step (sequence iterator from-end) (:method ((s list) iterator from-end) (if from-end (if (eq iterator s) *exhausted* (do* ((xs s (cdr xs))) ((eq (cdr xs) iterator) xs))) (cdr iterator))) (:method ((s vector) iterator from-end) (if from-end (1- iterator) (1+ iterator))) (:method ((s sequence) iterator from-end) (if from-end (1- iterator) (1+ iterator)))) (defgeneric sequence:iterator-endp (sequence iterator limit from-end) (:method ((s list) iterator limit from-end) (eq iterator limit)) (:method ((s vector) iterator limit from-end) (= iterator limit)) (:method ((s sequence) iterator limit from-end) (= iterator limit))) (defgeneric sequence:iterator-element (sequence iterator) (:method ((s list) iterator) (car iterator)) (:method ((s vector) iterator) (aref s iterator)) (:method ((s sequence) iterator) (elt s iterator))) (defgeneric (setf sequence:iterator-element) (new-value sequence iterator) (:method (o (s list) iterator) (setf (car iterator) o)) (:method (o (s vector) iterator) (setf (aref s iterator) o)) (:method (o (s sequence) iterator) (setf (elt s iterator) o))) (defgeneric sequence:iterator-index (sequence iterator) (:method ((s list) iterator) ;; FIXME: this sucks. (In my defence, it is the equivalent of the ;; Apple implementation in Dylan...) (loop for l on s for i from 0 when (eq l iterator) return i)) (:method ((s vector) iterator) iterator) (:method ((s sequence) iterator) iterator)) (defgeneric sequence:iterator-copy (sequence iterator) (:method ((s list) iterator) iterator) (:method ((s vector) iterator) iterator) (:method ((s sequence) iterator) iterator)) (defmacro sequence:with-sequence-iterator ((&rest vars) (s &rest args &key from-end start end) &body body) (declare (ignore from-end start end)) `(multiple-value-bind (,@vars) (sequence:make-sequence-iterator ,s ,@args) (declare (type function ,@(nthcdr 3 vars))) ,@body)) (defmacro sequence:with-sequence-iterator-functions ((step endp elt setf index copy) (s &rest args &key from-end start end) &body body) (declare (ignore from-end start end)) (let ((nstate (gensym "STATE")) (nlimit (gensym "LIMIT")) (nfrom-end (gensym "FROM-END-")) (nstep (gensym "STEP")) (nendp (gensym "ENDP")) (nelt (gensym "ELT")) (nsetf (gensym "SETF")) (nindex (gensym "INDEX")) (ncopy (gensym "COPY"))) `(sequence:with-sequence-iterator (,nstate ,nlimit ,nfrom-end ,nstep ,nendp ,nelt ,nsetf ,nindex ,ncopy) (,s ,@args) (flet ((,step () (setq ,nstate (funcall ,nstep ,s ,nstate ,nfrom-end))) (,endp () (funcall ,nendp ,s ,nstate ,nlimit ,nfrom-end)) (,elt () (funcall ,nelt ,s ,nstate)) (,setf (new-value) (funcall ,nsetf new-value ,s ,nstate)) (,index () (funcall ,nindex ,s ,nstate)) (,copy () (funcall ,ncopy ,s ,nstate))) (declare (truly-dynamic-extent #',step #',endp #',elt #',setf #',index #',copy)) ,@body)))) (defun sequence:canonize-test (test test-not) (cond (test (if (functionp test) test (fdefinition test))) (test-not (if (functionp test-not) (complement test-not) (complement (fdefinition test-not)))) (t #'eql))) (defun sequence:canonize-key (key) (or (and key (if (functionp key) key (fdefinition key))) #'identity)) ;;;; generic implementations for sequence functions. ;;; FIXME: COUNT, POSITION and FIND share an awful lot of structure. ;;; They could usefully be defined in an OAOO way. (defgeneric sequence:count (item sequence &key from-end start end test test-not key) (:argument-precedence-order sequence item)) (defmethod sequence:count (item (sequence sequence) &key from-end (start 0) end test test-not key) (let ((test (sequence:canonize-test test test-not)) (key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do ((count 0)) ((funcall endp sequence state limit from-end) count) (let ((o (funcall elt sequence state))) (when (funcall test item (funcall key o)) (incf count)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:count-if (pred sequence &key from-end start end key) (:argument-precedence-order sequence pred)) (defmethod sequence:count-if (pred (sequence sequence) &key from-end (start 0) end key) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do ((count 0)) ((funcall endp sequence state limit from-end) count) (let ((o (funcall elt sequence state))) (when (funcall pred (funcall key o)) (incf count)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:count-if-not (pred sequence &key from-end start end key) (:argument-precedence-order sequence pred)) (defmethod sequence:count-if-not (pred (sequence sequence) &key from-end (start 0) end key) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do ((count 0)) ((funcall endp sequence state limit from-end) count) (let ((o (funcall elt sequence state))) (unless (funcall pred (funcall key o)) (incf count)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:find (item sequence &key from-end start end test test-not key) (:argument-precedence-order sequence item)) (defmethod sequence:find (item (sequence sequence) &key from-end (start 0) end test test-not key) (let ((test (sequence:canonize-test test test-not)) (key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do () ((funcall endp sequence state limit from-end) nil) (let ((o (funcall elt sequence state))) (when (funcall test item (funcall key o)) (return o)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:find-if (pred sequence &key from-end start end key) (:argument-precedence-order sequence pred)) (defmethod sequence:find-if (pred (sequence sequence) &key from-end (start 0) end key) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do () ((funcall endp sequence state limit from-end) nil) (let ((o (funcall elt sequence state))) (when (funcall pred (funcall key o)) (return o)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:find-if-not (pred sequence &key from-end start end key) (:argument-precedence-order sequence pred)) (defmethod sequence:find-if-not (pred (sequence sequence) &key from-end (start 0) end key) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do () ((funcall endp sequence state limit from-end) nil) (let ((o (funcall elt sequence state))) (unless (funcall pred (funcall key o)) (return o)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:position (item sequence &key from-end start end test test-not key) (:argument-precedence-order sequence item)) (defmethod sequence:position (item (sequence sequence) &key from-end (start 0) end test test-not key) (let ((test (sequence:canonize-test test test-not)) (key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do ((s (if from-end -1 1)) (pos (if from-end (1- (or end (length sequence))) start) (+ pos s))) ((funcall endp sequence state limit from-end) nil) (let ((o (funcall elt sequence state))) (when (funcall test item (funcall key o)) (return pos)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:position-if (pred sequence &key from-end start end key) (:argument-precedence-order sequence pred)) (defmethod sequence:position-if (pred (sequence sequence) &key from-end (start 0) end key) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do ((s (if from-end -1 1)) (pos (if from-end (1- (or end (length sequence))) start) (+ pos s))) ((funcall endp sequence state limit from-end) nil) (let ((o (funcall elt sequence state))) (when (funcall pred (funcall key o)) (return pos)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:position-if-not (pred sequence &key from-end start end key) (:argument-precedence-order sequence pred)) (defmethod sequence:position-if-not (pred (sequence sequence) &key from-end (start 0) end key) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :from-end from-end :start start :end end) (do ((s (if from-end -1 1)) (pos (if from-end (1- (or end (length sequence))) start) (+ pos s))) ((funcall endp sequence state limit from-end) nil) (let ((o (funcall elt sequence state))) (unless (funcall pred (funcall key o)) (return pos)) (setq state (funcall step sequence state from-end))))))) (defgeneric sequence:subseq (sequence start &optional end)) (defmethod sequence:subseq ((sequence sequence) start &optional end) (let* ((end (or end (length sequence))) (length (- end start)) (result (sequence:make-sequence-like sequence length))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :start start :end end) (declare (ignore limit endp)) (sequence:with-sequence-iterator (rstate rlimit rfrom-end rstep rendp relt rsetelt) (result) (declare (ignore rlimit rendp relt)) (do ((i 0 (+ i 1))) ((>= i length) result) (funcall rsetelt (funcall elt sequence state) result rstate) (setq state (funcall step sequence state from-end)) (setq rstate (funcall rstep result rstate rfrom-end))))))) (defgeneric sequence:copy-seq (sequence)) (defmethod sequence:copy-seq ((sequence sequence)) (sequence:subseq sequence 0)) (fmakunbound 'sequence:fill) (defgeneric sequence:fill (sequence item &key start end)) (defmethod sequence:fill ((sequence sequence) item &key (start 0) end) (sequence:with-sequence-iterator (state limit from-end step endp elt setelt) (sequence :start start :end end) (declare (ignore elt)) (do () ((funcall endp sequence state limit from-end) sequence) (funcall setelt item sequence state) (setq state (funcall step sequence state from-end))))) (defgeneric sequence:nsubstitute (new old sequence &key start end from-end test test-not count key) (:argument-precedence-order sequence new old)) (defmethod sequence:nsubstitute (new old (sequence sequence) &key (start 0) end from-end test test-not count key) (let ((test (sequence:canonize-test test test-not)) (key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt setelt) (sequence :start start :end end :from-end from-end) (do ((c 0)) ((or (and count (>= c count)) (funcall endp sequence state limit from-end)) sequence) (when (funcall test old (funcall key (funcall elt sequence state))) (incf c) (funcall setelt new sequence state)) (setq state (funcall step sequence state from-end)))))) (defgeneric sequence:nsubstitute-if (new predicate sequence &key start end from-end count key) (:argument-precedence-order sequence new predicate)) (defmethod sequence:nsubstitute-if (new predicate (sequence sequence) &key (start 0) end from-end count key) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt setelt) (sequence :start start :end end :from-end from-end) (do ((c 0)) ((or (and count (>= c count)) (funcall endp sequence state limit from-end)) sequence) (when (funcall predicate (funcall key (funcall elt sequence state))) (incf c) (funcall setelt new sequence state)) (setq state (funcall step sequence state from-end)))))) (defgeneric sequence:nsubstitute-if-not (new predicate sequence &key start end from-end count key) (:argument-precedence-order sequence new predicate)) (defmethod sequence:nsubstitute-if-not (new predicate (sequence sequence) &key (start 0) end from-end count key) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt setelt) (sequence :start start :end end :from-end from-end) (do ((c 0)) ((or (and count (>= c count)) (funcall endp sequence state limit from-end)) sequence) (unless (funcall predicate (funcall key (funcall elt sequence state))) (incf c) (funcall setelt new sequence state)) (setq state (funcall step sequence state from-end)))))) (defgeneric sequence:substitute (new old sequence &key start end from-end test test-not count key) (:argument-precedence-order sequence new old)) (defmethod sequence:substitute (new old (sequence sequence) &rest args &key (start 0) end from-end test test-not count key) (declare (truly-dynamic-extent args)) (declare (ignore start end from-end test test-not count key)) (let ((result (copy-seq sequence))) (apply #'sequence:nsubstitute new old result args))) (defgeneric sequence:substitute-if (new predicate sequence &key start end from-end count key) (:argument-precedence-order sequence new predicate)) (defmethod sequence:substitute-if (new predicate (sequence sequence) &rest args &key (start 0) end from-end count key) (declare (truly-dynamic-extent args)) (declare (ignore start end from-end count key)) (let ((result (copy-seq sequence))) (apply #'sequence:nsubstitute-if new predicate result args))) (defgeneric sequence:substitute-if-not (new predicate sequence &key start end from-end count key) (:argument-precedence-order sequence new predicate)) (defmethod sequence:substitute-if-not (new predicate (sequence sequence) &rest args &key (start 0) end from-end count key) (declare (truly-dynamic-extent args)) (declare (ignore start end from-end count key)) (let ((result (copy-seq sequence))) (apply #'sequence:nsubstitute-if-not new predicate result args))) (defun %sequence-replace (sequence1 sequence2 start1 end1 start2 end2) (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1) (sequence1 :start start1 :end end1) (declare (ignore elt1)) (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2) (sequence2 :start start2 :end end2) (do () ((or (funcall endp1 sequence1 state1 limit1 from-end1) (funcall endp2 sequence2 state2 limit2 from-end2)) sequence1) (funcall setelt1 (funcall elt2 sequence2 state2) sequence1 state1) (setq state1 (funcall step1 sequence1 state1 from-end1)) (setq state2 (funcall step2 sequence2 state2 from-end2)))))) (defgeneric sequence:replace (sequence1 sequence2 &key start1 end1 start2 end2) (:argument-precedence-order sequence2 sequence1)) (defmethod sequence:replace ((sequence1 sequence) (sequence2 sequence) &key (start1 0) end1 (start2 0) end2) (print sequence1) (print sequence2) (cond ((eq sequence1 sequence2) (let ((replaces (subseq sequence2 start2 end2))) (%sequence-replace sequence1 replaces start1 end1 0 nil))) (t (%sequence-replace sequence1 sequence2 start1 end1 start2 end2)))) (defgeneric sequence:nreverse (sequence)) (defmethod sequence:nreverse ((sequence sequence)) ;; FIXME: this, in particular the :from-end iterator, will suck ;; mightily if the user defines a list-like structure. (let ((length (length sequence))) (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1) (sequence :end (floor length 2)) (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2 setelt2) (sequence :start (ceiling length 2) :from-end t) (declare (ignore limit2 endp2)) (do () ((funcall endp1 sequence state1 limit1 from-end1) sequence) (let ((x (funcall elt1 sequence state1)) (y (funcall elt2 sequence state2))) (funcall setelt1 y sequence state1) (funcall setelt2 x sequence state2)) (setq state1 (funcall step1 sequence state1 from-end1)) (setq state2 (funcall step2 sequence state2 from-end2))))))) (defgeneric sequence:reverse (sequence)) (defmethod sequence:reverse ((sequence sequence)) (let ((result (copy-seq sequence))) (sequence:nreverse result))) (defgeneric sequence:reduce (function sequence &key from-end start end initial-value) (:argument-precedence-order sequence function)) (defmethod sequence:reduce (function (sequence sequence) &key from-end (start 0) end key (initial-value nil ivp)) (let ((key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence :start start :end end :from-end from-end) (if (funcall endp sequence state limit from-end) (if ivp initial-value (funcall function)) (do* ((state state (funcall step sequence state from-end)) (value (cond (ivp initial-value) (t (prog1 (funcall key (funcall elt sequence state)) (setq state (funcall step sequence state from-end))))))) ((funcall endp sequence state limit from-end) value) (let ((e (funcall key (funcall elt sequence state)))) (if from-end (setq value (funcall function e value)) (setq value (funcall function value e))))))))) (defgeneric sequence:mismatch (sequence1 sequence2 &key from-end start1 end1 start2 end2 test test-not key)) (defmethod sequence:mismatch ((sequence1 sequence) (sequence2 sequence) &key from-end (start1 0) end1 (start2 0) end2 test test-not key) (let ((test (sequence:canonize-test test test-not)) (key (sequence:canonize-key key))) (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1) (sequence1 :start start1 :end end1 :from-end from-end) (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2) (sequence2 :start start2 :end end2 :from-end from-end) (if from-end (do ((result (or end1 (length sequence1)) (1- result)) (e1 (funcall endp1 sequence1 state1 limit1 from-end1) (funcall endp1 sequence1 state1 limit1 from-end1)) (e2 (funcall endp2 sequence2 state2 limit2 from-end2) (funcall endp2 sequence2 state2 limit2 from-end2))) ((or e1 e2) (if (and e1 e2) nil result)) (let ((o1 (funcall key (funcall elt1 sequence1 state1))) (o2 (funcall key (funcall elt2 sequence2 state2)))) (unless (funcall test o1 o2) (return result)) (setq state1 (funcall step1 sequence1 state1 from-end1)) (setq state2 (funcall step2 sequence2 state2 from-end2)))) (do ((result start1 (1+ result)) (e1 (funcall endp1 sequence1 state1 limit1 from-end1) (funcall endp1 sequence1 state1 limit1 from-end1)) (e2 (funcall endp2 sequence2 state2 limit2 from-end2) (funcall endp2 sequence2 state2 limit2 from-end2))) ((or e1 e2) (if (and e1 e2) nil result)) (let ((o1 (funcall key (funcall elt1 sequence1 state1))) (o2 (funcall key (funcall elt2 sequence2 state2)))) (unless (funcall test o1 o2) (return result))) (setq state1 (funcall step1 sequence1 state1 from-end1)) (setq state2 (funcall step2 sequence2 state2 from-end2)))))))) (defgeneric sequence:search (sequence1 sequence2 &key from-end start1 end1 start2 end2 test test-not key)) (defmethod sequence:search ((sequence1 sequence) (sequence2 sequence) &key from-end (start1 0) end1 (start2 0) end2 test test-not key) (let ((test (sequence:canonize-test test test-not)) (key (sequence:canonize-key key)) (mainend2 (- (or end2 (length sequence2)) (- (or end1 (length sequence1)) start1)))) (when (< mainend2 0) (return-from sequence:search nil)) (sequence:with-sequence-iterator (statem limitm from-endm stepm endpm) (sequence2 :start start2 :end mainend2 :from-end from-end) (do ((s2 (if from-end mainend2 0) (if from-end (1- s2) (1+ s2)))) (nil) (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1) (sequence1 :start start1 :end end1) (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2) (sequence2 :start s2) (declare (ignore limit2 endp2)) (when (do () ((funcall endp1 sequence1 state1 limit1 from-end1) t) (let ((o1 (funcall key (funcall elt1 sequence1 state1))) (o2 (funcall key (funcall elt2 sequence2 state2)))) (unless (funcall test o1 o2) (return nil))) (setq state1 (funcall step1 sequence1 state1 from-end1)) (setq state2 (funcall step2 sequence2 state2 from-end2))) (return-from sequence:search s2)))) (when (funcall endpm sequence2 statem limitm from-endm) (return nil)) (setq statem (funcall stepm sequence2 statem from-endm)))))) (defgeneric sequence:delete (item sequence &key from-end test test-not start end count key) (:argument-precedence-order sequence item)) (defmethod sequence:delete (item (sequence sequence) &key from-end test test-not (start 0) end count key) (let ((test (sequence:canonize-test test test-not)) (key (sequence:canonize-key key)) (c 0)) (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1) (sequence :start start :end end :from-end from-end) (declare (ignore limit1 endp1 elt1)) (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2) (sequence :start start :end end :from-end from-end) (flet ((finish () (if from-end (replace sequence sequence :start1 start :end1 (- (length sequence) c) :start2 (+ start c) :end2 (length sequence)) (unless (or (null end) (= end (length sequence))) (replace sequence sequence :start2 end :start1 (- end c) :end1 (- (length sequence) c)))) (sequence:adjust-sequence sequence (- (length sequence) c)))) (declare (truly-dynamic-extent #'finish)) (do () ((funcall endp2 sequence state2 limit2 from-end2) (finish)) (let ((e (funcall elt2 sequence state2))) (loop (when (and count (>= c count)) (return)) (if (funcall test item (funcall key e)) (progn (incf c) (setq state2 (funcall step2 sequence state2 from-end2)) (when (funcall endp2 sequence state2 limit2 from-end2) (return-from sequence:delete (finish))) (setq e (funcall elt2 sequence state2))) (return))) (funcall setelt1 e sequence state1)) (setq state1 (funcall step1 sequence state1 from-end1)) (setq state2 (funcall step2 sequence state2 from-end2)))))))) (defgeneric sequence:delete-if (predicate sequence &key from-end start end count key) (:argument-precedence-order sequence predicate)) (defmethod sequence:delete-if (predicate (sequence sequence) &key from-end (start 0) end count key) (let ((key (sequence:canonize-key key)) (c 0)) (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1) (sequence :start start :end end :from-end from-end) (declare (ignore limit1 endp1 elt1)) (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2) (sequence :start start :end end :from-end from-end) (flet ((finish () (if from-end (replace sequence sequence :start1 start :end1 (- (length sequence) c) :start2 (+ start c) :end2 (length sequence)) (unless (or (null end) (= end (length sequence))) (replace sequence sequence :start2 end :start1 (- end c) :end1 (- (length sequence) c)))) (sequence:adjust-sequence sequence (- (length sequence) c)))) (declare (truly-dynamic-extent #'finish)) (do () ((funcall endp2 sequence state2 limit2 from-end2) (finish)) (let ((e (funcall elt2 sequence state2))) (loop (when (and count (>= c count)) (return)) (if (funcall predicate (funcall key e)) (progn (incf c) (setq state2 (funcall step2 sequence state2 from-end2)) (when (funcall endp2 sequence state2 limit2 from-end2) (return-from sequence:delete-if (finish))) (setq e (funcall elt2 sequence state2))) (return))) (funcall setelt1 e sequence state1)) (setq state1 (funcall step1 sequence state1 from-end1)) (setq state2 (funcall step2 sequence state2 from-end2)))))))) (defgeneric sequence:delete-if-not (predicate sequence &key from-end start end count key) (:argument-precedence-order sequence predicate)) (defmethod sequence:delete-if-not (predicate (sequence sequence) &key from-end (start 0) end count key) (let ((key (sequence:canonize-key key)) (c 0)) (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1) (sequence :start start :end end :from-end from-end) (declare (ignore limit1 endp1 elt1)) (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2) (sequence :start start :end end :from-end from-end) (flet ((finish () (if from-end (replace sequence sequence :start1 start :end1 (- (length sequence) c) :start2 (+ start c) :end2 (length sequence)) (unless (or (null end) (= end (length sequence))) (replace sequence sequence :start2 end :start1 (- end c) :end1 (- (length sequence) c)))) (sequence:adjust-sequence sequence (- (length sequence) c)))) (declare (truly-dynamic-extent #'finish)) (do () ((funcall endp2 sequence state2 limit2 from-end2) (finish)) (let ((e (funcall elt2 sequence state2))) (loop (when (and count (>= c count)) (return)) (if (funcall predicate (funcall key e)) (return) (progn (incf c) (setq state2 (funcall step2 sequence state2 from-end2)) (when (funcall endp2 sequence state2 limit2 from-end2) (return-from sequence:delete-if-not (finish))) (setq e (funcall elt2 sequence state2))))) (funcall setelt1 e sequence state1)) (setq state1 (funcall step1 sequence state1 from-end1)) (setq state2 (funcall step2 sequence state2 from-end2)))))))) (defgeneric sequence:remove (item sequence &key from-end test test-not start end count key) (:argument-precedence-order sequence item)) (defmethod sequence:remove (item (sequence sequence) &rest args &key from-end test test-not (start 0) end count key) (declare (dynamic-extent args)) (declare (ignore from-end test test-not start end count key)) (let ((result (copy-seq sequence))) (apply #'sequence:delete item result args))) (defgeneric sequence:remove-if (predicate sequence &key from-end start end count key) (:argument-precedence-order sequence predicate)) (defmethod sequence:remove-if (predicate (sequence sequence) &rest args &key from-end (start 0) end count key) (declare (truly-dynamic-extent args)) (declare (ignore from-end start end count key)) (let ((result (copy-seq sequence))) (apply #'sequence:delete-if predicate result args))) (defgeneric sequence:remove-if-not (predicate sequence &key from-end start end count key) (:argument-precedence-order sequence predicate)) (defmethod sequence:remove-if-not (predicate (sequence sequence) &rest args &key from-end (start 0) end count key) (declare (truly-dynamic-extent args)) (declare (ignore from-end start end count key)) (let ((result (copy-seq sequence))) (apply #'sequence:delete-if-not predicate result args))) (defgeneric sequence:delete-duplicates (sequence &key from-end test test-not start end key)) (defmethod sequence:delete-duplicates ((sequence sequence) &key from-end test test-not (start 0) end key) (let ((test (sequence:canonize-test test test-not)) (key (sequence:canonize-key key)) (c 0)) (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1) (sequence :start start :end end :from-end from-end) (declare (ignore limit1 endp1 elt1)) (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2) (sequence :start start :end end :from-end from-end) (flet ((finish () (if from-end (replace sequence sequence :start1 start :end1 (- (length sequence) c) :start2 (+ start c) :end2 (length sequence)) (unless (or (null end) (= end (length sequence))) (replace sequence sequence :start2 end :start1 (- end c) :end1 (- (length sequence) c)))) (sequence:adjust-sequence sequence (- (length sequence) c)))) (declare (truly-dynamic-extent #'finish)) (do ((end (or end (length sequence))) (step 0 (1+ step))) ((funcall endp2 sequence state2 limit2 from-end2) (finish)) (let ((e (funcall elt2 sequence state2))) (loop ;; FIXME: replace with POSITION once position is ;; working (if (> (count (funcall key e) sequence :test test :key key :start (if from-end start (+ start step 1)) :end (if from-end (- end step 1) end)) 0) (progn (incf c) (incf step) (setq state2 (funcall step2 sequence state2 from-end2)) (when (funcall endp2 sequence state2 limit2 from-end2) (return-from sequence:delete-duplicates (finish))) (setq e (funcall elt2 sequence state2))) (progn (return)))) (funcall setelt1 e sequence state1)) (setq state1 (funcall step1 sequence state1 from-end1)) (setq state2 (funcall step2 sequence state2 from-end2)))))))) (defgeneric sequence:remove-duplicates (sequence &key from-end test test-not start end key)) (defmethod sequence:remove-duplicates ((sequence sequence) &rest args &key from-end test test-not (start 0) end key) (declare (truly-dynamic-extent args)) (declare (ignore from-end test test-not start end key)) (let ((result (copy-seq sequence))) (apply #'sequence:delete-duplicates result args))) (defgeneric sequence:sort (sequence predicate &key key)) (defmethod sequence:sort ((sequence sequence) predicate &rest args &key key) (declare (dynamic-extent args)) (declare (ignore key)) (let* ((length (length sequence)) (vector (make-array length))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence) (declare (ignore limit endp)) (do ((i 0 (1+ i))) ((>= i length)) (setf (aref vector i) (funcall elt sequence state)) (setq state (funcall step sequence state from-end)))) (apply #'cl:sort vector predicate args) (sequence:with-sequence-iterator (state limit from-end step endp elt setelt) (sequence) (declare (ignore limit endp elt)) (do ((i 0 (1+ i))) ((>= i length) sequence) (funcall setelt (aref vector i) sequence state) (setq state (funcall step sequence state from-end)))))) (defgeneric sequence:stable-sort (sequence predicate &key key)) (defmethod sequence:stable-sort ((sequence sequence) predicate &rest args &key key) (declare (dynamic-extent args)) (declare (ignore key)) (let* ((length (length sequence)) (vector (make-array length))) (sequence:with-sequence-iterator (state limit from-end step endp elt) (sequence) (declare (ignore limit endp)) (do ((i 0 (1+ i))) ((>= i length)) (setf (aref vector i) (funcall elt sequence state)) (setq state (funcall step sequence state from-end)))) (apply #'cl:stable-sort vector predicate args) (sequence:with-sequence-iterator (state limit from-end step endp elt setelt) (sequence) (declare (ignore limit endp elt)) (do ((i 0 (1+ i))) ((>= i length) sequence) (funcall setelt (aref vector i) sequence state) (setq state (funcall step sequence state from-end)))))) ;;LOOP extension (defun loop-elements-iteration-path (variable data-type prep-phrases) (let (of-phrase) (loop for (prep . rest) in prep-phrases do (ecase prep ((:of :in) (if of-phrase (loop::loop-error "Too many prepositions") (setq of-phrase rest))))) (destructuring-bind (it lim f-e step endp elt seq) (loop repeat 7 collect (gensym)) (push `(let ((,seq ,(car of-phrase)))) loop::*loop-wrappers*) (push `(sequence:with-sequence-iterator (,it ,lim ,f-e ,step ,endp ,elt) (,seq)) loop::*loop-wrappers*) `(((,variable nil ,data-type)) () () nil (funcall ,endp ,seq ,it ,lim ,f-e) (,variable (funcall ,elt ,seq ,it) ,it (funcall ,step ,seq ,it ,f-e)))))) (loop::add-loop-path '(element elements) 'loop-elements-iteration-path loop::*loop-ansi-universe* :preposition-groups '((:of :in)) :inclusive-permitted nil) ;;;DOSEQUENCE ;;From SBCL (eval-when (:compile-toplevel :load-toplevel :execute) (defun filter-dolist-declarations (decls) (mapcar (lambda (decl) `(declare ,@(remove-if (lambda (clause) (and (consp clause) (or (eq (car clause) 'type) (eq (car clause) 'ignore)))) (cdr decl)))) decls))) ;; just like DOLIST, but with one-dimensional arrays (defmacro dovector ((elt vector &optional result) &body body) (multiple-value-bind (forms decls) (sys:parse-body body nil) (let ((index (gensym "INDEX")) (length (gensym "LENGTH")) (vec (gensym "VEC"))) `(let ((,vec ,vector)) (declare (type vector ,vec)) (do ((,index 0 (1+ ,index)) (,length (length ,vec))) ((>= ,index ,length) (let ((,elt nil)) ,@(filter-dolist-declarations decls) ,elt ,result)) (let ((,elt (aref ,vec ,index))) ,@decls (tagbody ,@forms))))))) (defmacro sequence:dosequence ((e sequence &optional return &rest args &key from-end start end) &body body) (declare (ignore from-end start end)) (multiple-value-bind (forms decls) (sys:parse-body body nil) (let ((s sequence) (sequence (gensym "SEQUENCE"))) `(block nil (let ((,sequence ,s)) (seq-dispatch ,sequence (dolist (,e ,sequence ,return) ,@body) (dovector (,e ,sequence ,return) ,@body) (multiple-value-bind (state limit from-end step endp elt) (sequence:make-sequence-iterator ,sequence ,@args) (do ((state state (funcall step ,sequence state from-end))) ((funcall endp ,sequence state limit from-end) (let ((,e nil)) ,@(filter-dolist-declarations decls) ,e ,return)) (let ((,e (funcall elt ,sequence state))) ,@decls (tagbody ,@forms)))))))))) (provide "EXTENSIBLE-SEQUENCES") (pushnew :extensible-sequences *features*) abcl-src-1.9.0/src/org/armedbear/lisp/fasl-concat.lisp0100644 0000000 0000000 00000010211 14202767264 021275 0ustar000000000 0000000 ;;; fasl-concat.lisp ;;; ;;; Copyright (C) 2013 Erik Huelsmann ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (export '(concatenate-fasls)) (defun pathname-directory-p (pathname) (and (null (pathname-type pathname)) (null (pathname-name pathname)) (null (pathname-version pathname)))) (defun load-concatenated-fasl (sub-fasl) (let ((fasl-path (merge-pathnames (make-pathname :directory (list :relative sub-fasl) :name "__loader__" :type "_") *load-truename-fasl*))) (load fasl-path))) (defun concatenate-fasls (inputs output) (let ((directory (ext:make-temp-directory)) paths) (unwind-protect (let* ((unpacked (mapcan #'(lambda (input) (sys:unzip input (ensure-directories-exist (sub-directory directory (pathname-name input))))) inputs)) (chain-loader (make-pathname :name "__loader__" :type "_" :defaults directory))) (with-open-file (f chain-loader :direction :output :if-does-not-exist :create :if-exists :overwrite) (write-string ";; loader code to delegate loading of the embedded fasls below" f) (terpri f) (sys::dump-form `(sys:init-fasl :version ,sys:*fasl-version*) f) (terpri f) (dolist (input inputs) (sys::dump-form `(load-concatenated-fasl ,(pathname-name input)) f) (terpri f))) (setf paths (directory (merge-pathnames (make-pathname :directory '(:relative :wild-inferiors) :name "*" :type "*") directory))) (sys:zip output (remove-if #'pathname-directory-p paths) directory) (values directory unpacked chain-loader)) (dolist (path paths) (ignore-errors (delete-file path))) (ignore-errors (delete-file directory))))) (defun sub-directory (directory name) (merge-pathnames (make-pathname :directory (list :relative name)) directory)) abcl-src-1.9.0/src/org/armedbear/lisp/fdefinition.lisp0100644 0000000 0000000 00000017371 14223403213 021377 0ustar000000000 0000000 ;;; fdefinition.lisp ;;; ;;; Copyright (C) 2005-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (export '(record-source-information untraced-function)) (defun check-redefinition (name) (when (and *warn-on-redefinition* (fboundp name) (not (autoloadp name))) (when (and (symbolp name) (source-pathname name)) ;; SOURCE-PATHNAME is badly named as it is either a PATHNAME, ;; the keyword :TOP-LEVEL. ;; ;; Unfortunately, as of SLIME v2.26 the pathname may have a ;; device containing the string "emacs-buffer" whose PATHNAME ;; name denotes the buffer, which often contain wild-pathname ;; characters (e.g. "*slime-scratch*"). We code around that ;; situation with the following convolution of intelligibility. (flet ((truename-no-error (p) (if (and (pathnamep p) (not (and (stringp (pathname-device p)) (string= (pathname-device p) "emacs-buffer"))) (not (wild-pathname-p p))) (probe-file p) p))) (let ((source (source-pathname name))) (let ((old-source (if (keywordp source) source (truename-no-error source))) (current-source (if (not *source*) :top-level (truename-no-error source)))) (cond ((equal old-source current-source)) ; OK (t (if (eq current-source :top-level) (style-warn "redefining ~S at top level" name) (let ((*package* +cl-package+)) (if (eq old-source :top-level) (style-warn "redefining ~S in ~S (previously defined at top level)" name current-source) (style-warn "redefining ~S in ~S (previously defined in ~S)" name current-source old-source)))))))))))) ;;; DEPRECATED: to be removed in abcl-1.7 (defun record-source-information (name &optional source-pathname source-position) (unless source-pathname (setf source-pathname (or *source* :top-level))) (unless source-position (setf source-position *source-position*)) (let ((source (if source-position (cons source-pathname source-position) source-pathname))) (cond ((symbolp name) (put name '%source source))))) (defun record-source-information-for-type (name type &optional source-pathname source-position) "Record source information on the SYS:SOURCE property for symbol with NAME TYPE is either a symbol or list. Source information for functions, methods, and generic functions are represented as lists of the following form: (:generic-function function-name) (:function function-name) (:method method-name qualifiers specializers) Where FUNCTION-NAME or METHOD-NAME can be a either be of the form 'symbol or '(setf symbol). Source information for all other forms have a symbol for TYPE which is one of the following: :class, :variable, :condition, :constant, :compiler-macro, :macro :package, :structure, :type, :setf-expander, :source-transform These values follow SBCL'S implemenation in SLIME c.f. " #| Modifications are in two places, one at the definitions, calling record-source-information-by-type and then again in the file-compiler, which writes forms like (put 'source name (cons (list type pathname position) (get 'source name))) In theory this can lead to redundancy if a fasl is loaded again and again. I'm not sure how to fix this yet. Forms in the __loader__ get called early in build when many of the sequence functions aren't present. Will probably just filter when presenting in slime. |# (unless source-pathname (setf source-pathname (or *source* :top-level))) (unless source-position (setf source-position *source-position*)) (let ((source (if source-position (list source-pathname source-position) (list source-pathname)))) (let ((sym (if (consp name) (second name) name)) (new `(,type ,(if (symbolp (car source)) (car source) (namestring (car source))) ,(second source)))) (if (autoloadp 'delete) (put sym 'sys::source (cons new (get sym 'sys::source nil))) (put sym 'sys::source (cons new (delete new (get sym 'sys::source nil) :test (lambda(a b) (and (equalp (car a) (car b)) (equalp (second a) (second b) )))))))))) ;; Redefined in trace.lisp. (defun trace-redefined-update (&rest args) (declare (ignore args))) ;; Redefined in trace.lisp. (defun untraced-function (name) (declare (ignore name)) nil) (%defvar '*fset-hooks* nil) (defun fset (name function &optional source-position arglist documentation) (cond ((symbolp name) (check-redefinition name) (record-source-information name nil source-position) (when arglist (%set-arglist function arglist)) (%set-documentation function 'function documentation) (%set-symbol-function name function)) ((setf-function-name-p name) (check-redefinition name) (record-source-information name nil source-position) ;; FIXME arglist documentation (setf (get (%cadr name) 'setf-function) function)) (t (require-type name '(or symbol (cons (eql setf) (cons symbol null)))))) (when (functionp function) ; FIXME Is this test needed? (%set-lambda-name function name)) (dolist (hook *fset-hooks*) (ignore-errors (funcall hook name function))) (trace-redefined-update name function) function) (defun fdefinition (name) (cond ((symbolp name) (symbol-function name)) ((setf-function-name-p name) (or (get (%cadr name) 'setf-function) (error 'undefined-function :name name))) (t (require-type name '(or symbol (cons (eql setf) (cons symbol null))))))) (defun %set-fdefinition (name function) (fset name function)) (defsetf fdefinition %set-fdefinition) abcl-src-1.9.0/src/org/armedbear/lisp/featurep.lisp0100644 0000000 0000000 00000006235 14202767264 020731 0ustar000000000 0000000 ;;; featurep.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:extensions) (export 'featurep) (defun featurep (form) (if (atom form) (not (null (memq form *features*))) (case (car form) ((:not not) (if (cddr form) (error "Too many subexpressions in feature expression: ~S" form) (not (featurep (cadr form))))) ((:and and) (dolist (subform (cdr form) t) (unless (featurep subform) (return)))) ((:or or) (dolist (subform (cdr form) nil) (when (featurep subform) (return t)))) (t (error "Unknown operator in feature expression: ~S" form))))) ;;;; Cribbed from ASDF 3.1.7; duplicated to establish runtime conditionals before ASDF is constructed (defun os-macosx-p () "Is the underlying operating system MacOS X?" ;; OS-MACOSX is not mutually exclusive with OS-UNIX, ;; in fact the former implies the latter. (featurep '(:or :darwin (:and :allegro :macosx) (:and :clisp :macos)))) (defun os-unix-p () "Is the underlying operating system some Unix variant?" (or (featurep '(:or :unix :cygwin)) (os-macosx-p))) (defun os-windows-p () "Is the underlying operating system Microsoft Windows?" (and (not (os-unix-p)) (featurep '(:or :win32 :windows :mswindows :mingw32 :mingw64)))) (defun os-genera-p () "Is the underlying operating system Genera (running on a Symbolics Lisp Machine)?" (featurep :genera)) (defun os-oldmac-p () "Is the underlying operating system an (emulated?) MacOS 9 or earlier?" (featurep :mcl)) (defun os-haiku-p () "Is the underlying operating system Haiku?" (featurep :haiku)) (export '(os-unix-p os-windows-p)) abcl-src-1.9.0/src/org/armedbear/lisp/file_author.java0100644 0000000 0000000 00000004064 14202767264 021367 0ustar000000000 0000000 /* * file_author.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; // ### file-author public final class file_author extends Primitive { private file_author() { super("file-author"); } @Override public LispObject execute(LispObject arg) { Pathname pathname = coerceToPathname(arg); if (pathname.isWild()) error(new FileError("Bad place for a wild pathname.", pathname)); return NIL; } private static final Primitive FILE_AUTHOR = new file_author(); } abcl-src-1.9.0/src/org/armedbear/lisp/file_length.java0100644 0000000 0000000 00000003705 14202767264 021347 0ustar000000000 0000000 /* * file_length.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class file_length extends Primitive { private file_length() { super("file-length", "stream"); } // ### file-length // file-length stream => length @Override public LispObject execute(LispObject arg) { return checkStream(arg).fileLength(); } private static final Primitive FILE_LENGTH = new file_length(); } abcl-src-1.9.0/src/org/armedbear/lisp/file_string_length.java0100644 0000000 0000000 00000004001 14202767264 022723 0ustar000000000 0000000 /* * file_string_length.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### file-string-length public final class file_string_length extends Primitive { private file_string_length() { super("file-string-length", "stream object"); } @Override public LispObject execute(LispObject first, LispObject second) { return checkStream(first).fileStringLength(second); } private static final Primitive FILE_STRING_LENGTH = new file_string_length(); } abcl-src-1.9.0/src/org/armedbear/lisp/file_write_date.java0100644 0000000 0000000 00000004512 14202767264 022212 0ustar000000000 0000000 /* * file_write_date.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; // ### file-write-date public final class file_write_date extends Primitive { private file_write_date() { super("file-write-date"); } @Override public LispObject execute(LispObject arg) { Pathname pathname = coerceToPathname(arg); if (pathname.isWild()) error(new FileError("Bad place for a wild pathname.", pathname)); Pathname defaultedPathname = (Pathname) Pathname.MERGE_PATHNAMES.execute(pathname); long lastModified = defaultedPathname.getLastModified(); if (lastModified == 0) return NIL; return number(lastModified / 1000 + 2208988800L); } private static final Primitive FILE_WRITE_DATE = new file_write_date(); } abcl-src-1.9.0/src/org/armedbear/lisp/fill.lisp0100644 0000000 0000000 00000005110 14223403213 020013 0ustar000000000 0000000 ;;; fill.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (require "EXTENSIBLE-SEQUENCES-BASE") ;;; Adapted from CMUCL. (defun list-fill (sequence item start end) (do ((current (nthcdr start sequence) (cdr current)) (index start (1+ index))) ((or (atom current) (and end (= index end))) sequence) (rplaca current item))) (defun vector-fill (sequence item start end) (unless end (setf end (length sequence))) (do ((index start (1+ index))) ((= index end) sequence) (setf (aref sequence index) item))) (defun fill (sequence item &key (start 0) end) "Replace the specified elements of SEQUENCE with ITEM." (sequence::seq-dispatch sequence (list-fill sequence item start end) (cond ((and (stringp sequence) (zerop start) (null end)) (simple-string-fill sequence item)) (t (vector-fill sequence item start end))) (sequence:fill sequence item :start start :end (sequence::%check-generic-sequence-bounds sequence start end)))) abcl-src-1.9.0/src/org/armedbear/lisp/find-all-symbols.lisp0100644 0000000 0000000 00000003476 14223403213 022256 0ustar000000000 0000000 ;;; find-all-symbols.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun find-all-symbols (string) (let ((string (string string)) (res ())) (dolist (package (list-all-packages)) (multiple-value-bind (symbol status) (find-symbol string package) (when status (pushnew symbol res)))) res)) abcl-src-1.9.0/src/org/armedbear/lisp/find.lisp0100644 0000000 0000000 00000023336 14223403213 020017 0ustar000000000 0000000 ;;; find.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require "EXTENSIBLE-SEQUENCES-BASE") ;;; From CMUCL. (defmacro vector-locater-macro (sequence body-form return-type) `(let ((incrementer (if from-end -1 1)) (start (if from-end (1- (the fixnum end)) start)) (end (if from-end (1- (the fixnum start)) end))) (declare (fixnum start end incrementer)) (do ((index start (+ index incrementer)) ,@(case return-type (:position nil) (:element '(current)))) ((= index end) ()) (declare (fixnum index)) ,@(case return-type (:position nil) (:element `((setf current (aref ,sequence index))))) ,body-form))) (defmacro locater-test-not (item sequence seq-type return-type) (let ((seq-ref (case return-type (:position (case seq-type (:vector `(aref ,sequence index)) (:list `(pop ,sequence)))) (:element 'current))) (return (case return-type (:position 'index) (:element 'current)))) `(if test-not (if (not (funcall test-not ,item (sys::apply-key key ,seq-ref))) (return ,return)) (if (funcall test ,item (sys::apply-key key ,seq-ref)) (return ,return))))) (defmacro vector-locater (item sequence return-type) `(vector-locater-macro ,sequence (locater-test-not ,item ,sequence :vector ,return-type) ,return-type)) (defmacro locater-if-test (test sequence seq-type return-type sense) (let ((seq-ref (case return-type (:position (case seq-type (:vector `(aref ,sequence index)) (:list `(pop ,sequence)))) (:element 'current))) (return (case return-type (:position 'index) (:element 'current)))) (if sense `(if (funcall ,test (sys::apply-key key ,seq-ref)) (return ,return)) `(if (not (funcall ,test (sys::apply-key key ,seq-ref))) (return ,return))))) (defmacro vector-locater-if-macro (test sequence return-type sense) `(vector-locater-macro ,sequence (locater-if-test ,test ,sequence :vector ,return-type ,sense) ,return-type)) (defmacro vector-locater-if (test sequence return-type) `(vector-locater-if-macro ,test ,sequence ,return-type t)) (defmacro vector-locater-if-not (test sequence return-type) `(vector-locater-if-macro ,test ,sequence ,return-type nil)) (defmacro list-locater-macro (sequence body-form return-type) `(if from-end (do ((sequence (nthcdr (- (the fixnum (length sequence)) (the fixnum end)) (reverse (the list ,sequence)))) (index (1- (the fixnum end)) (1- index)) (terminus (1- (the fixnum start))) ,@(case return-type (:position nil) (:element '(current)))) ((or (= index terminus) (null sequence)) ()) (declare (fixnum index terminus)) ,@(case return-type (:position nil) (:element `((setf current (pop ,sequence))))) ,body-form) (do ((sequence (nthcdr start ,sequence)) (index start (1+ index)) ,@(case return-type (:position nil) (:element '(current)))) ((or (= index (the fixnum end)) (null sequence)) ()) (declare (fixnum index)) ,@(case return-type (:position nil) (:element `((setf current (pop ,sequence))))) ,body-form))) (defmacro list-locater (item sequence return-type) `(list-locater-macro ,sequence (locater-test-not ,item ,sequence :list ,return-type) ,return-type)) (defmacro list-locater-if-macro (test sequence return-type sense) `(list-locater-macro ,sequence (locater-if-test ,test ,sequence :list ,return-type ,sense) ,return-type)) (defmacro list-locater-if (test sequence return-type) `(list-locater-if-macro ,test ,sequence ,return-type t)) (defmacro list-locater-if-not (test sequence return-type) `(list-locater-if-macro ,test ,sequence ,return-type nil)) (defmacro vector-position (item sequence) `(vector-locater ,item ,sequence :position)) (defmacro list-position (item sequence) `(list-locater ,item ,sequence :position)) (defun position (item sequence &rest args &key from-end (test #'eql) test-not (start 0) end key) (sequence::seq-dispatch sequence (list-position* item sequence from-end test test-not start end key) (vector-position* item sequence from-end test test-not start end key) (apply #'sequence:position item sequence args))) (defun list-position* (item sequence from-end test test-not start end key) (declare (type fixnum start)) (let ((end (or end (length sequence)))) (declare (type fixnum end)) (list-position item sequence))) (defun vector-position* (item sequence from-end test test-not start end key) (declare (type fixnum start)) (let ((end (or end (length sequence)))) (declare (type fixnum end)) (vector-position item sequence))) (defmacro vector-position-if (test sequence) `(vector-locater-if ,test ,sequence :position)) (defmacro list-position-if (test sequence) `(list-locater-if ,test ,sequence :position)) (defun position-if (test sequence &rest args &key from-end (start 0) key end) (declare (type fixnum start)) (let ((end (or end (length sequence)))) (declare (type fixnum end)) (sequence::seq-dispatch sequence (list-position-if test sequence) (vector-position-if test sequence) (apply #'sequence:position-if test sequence args)))) (defmacro vector-position-if-not (test sequence) `(vector-locater-if-not ,test ,sequence :position)) (defmacro list-position-if-not (test sequence) `(list-locater-if-not ,test ,sequence :position)) (defun position-if-not (test sequence &rest args &key from-end (start 0) key end) (declare (type fixnum start)) (let ((end (or end (length sequence)))) (declare (type fixnum end)) (sequence::seq-dispatch sequence (list-position-if-not test sequence) (vector-position-if-not test sequence) (apply #'sequence:position-if-not test sequence args)))) (defmacro vector-find (item sequence) `(vector-locater ,item ,sequence :element)) (defmacro list-find (item sequence) `(list-locater ,item ,sequence :element)) (defun list-find* (item sequence from-end test test-not start end key) (declare (type fixnum start end)) (unless (or test test-not) (setf test 'eql)) (list-find item sequence)) (defun vector-find* (item sequence from-end test test-not start end key) (declare (type fixnum start end)) (unless (or test test-not) (setf test 'eql)) (vector-find item sequence)) (defun find (item sequence &rest args &key from-end (test #'eql) test-not (start 0) end key) (let ((end (check-sequence-bounds sequence start end))) (sequence::seq-dispatch sequence (list-find* item sequence from-end test test-not start end key) (vector-find* item sequence from-end test test-not start end key) (apply #'sequence:find item sequence args)))) (defmacro vector-find-if (test sequence) `(vector-locater-if ,test ,sequence :element)) (defmacro list-find-if (test sequence) `(list-locater-if ,test ,sequence :element)) (defun find-if (test sequence &rest args &key from-end (start 0) end key) (let ((end (or end (length sequence)))) (declare (type fixnum end)) (sequence::seq-dispatch sequence (list-find-if test sequence) (vector-find-if test sequence) (apply #'sequence:find-if test sequence args)))) (defmacro vector-find-if-not (test sequence) `(vector-locater-if-not ,test ,sequence :element)) (defmacro list-find-if-not (test sequence) `(list-locater-if-not ,test ,sequence :element)) (defun find-if-not (test sequence &rest args &key from-end (start 0) end key) (let ((end (or end (length sequence)))) (declare (type fixnum end)) (sequence::seq-dispatch sequence (list-find-if-not test sequence) (vector-find-if-not test sequence) (apply #'sequence:find-if-not test sequence args)))) abcl-src-1.9.0/src/org/armedbear/lisp/float_sign.java0100644 0000000 0000000 00000005506 14202767264 021215 0ustar000000000 0000000 /* * float_sign.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### float-sign public final class float_sign extends Primitive { private float_sign() { super("float-sign", "float-1 &optional float-2"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof SingleFloat) { float f = ((SingleFloat)arg).value; int bits = Float.floatToRawIntBits(f); return bits < 0 ? SingleFloat.MINUS_ONE : SingleFloat.ONE; } if (arg instanceof DoubleFloat) { double d = ((DoubleFloat)arg).value; long bits = Double.doubleToRawLongBits(d); return bits < 0 ? DoubleFloat.MINUS_ONE : DoubleFloat.ONE; } return type_error(arg, Symbol.FLOAT); } @Override public LispObject execute(LispObject first, LispObject second) { if (!first.floatp()) return type_error(first, Symbol.FLOAT); if (!second.floatp()) return type_error(second, Symbol.FLOAT); if (first.minusp()) { if (second.minusp()) return second; else return Fixnum.ZERO.subtract(second); } else return second.ABS(); } private static final Primitive FLOAT_SIGN = new float_sign(); } abcl-src-1.9.0/src/org/armedbear/lisp/floor.java0100644 0000000 0000000 00000006063 14202767264 020210 0ustar000000000 0000000 /* * floor.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### floor number &optional divisor public final class floor extends Primitive { private floor() { super("floor", "number &optional divisor"); } @Override public LispObject execute(LispObject number) { LispObject quotient = number.truncate(Fixnum.ONE); final LispThread thread = LispThread.currentThread(); LispObject remainder = thread._values[1]; if (!remainder.zerop()) { if (number.minusp()) { quotient = quotient.decr(); remainder = remainder.incr(); thread._values[0] = quotient; thread._values[1] = remainder; } } return quotient; } @Override public LispObject execute(LispObject number, LispObject divisor) { LispObject quotient = number.truncate(divisor); final LispThread thread = LispThread.currentThread(); LispObject remainder = thread._values[1]; boolean adjust = false; if (!remainder.zerop()) { if (divisor.minusp()) { if (number.plusp()) adjust = true; } else { if (number.minusp()) adjust = true; } } if (adjust) { quotient = quotient.decr(); remainder = remainder.add(divisor); thread._values[0] = quotient; thread._values[1] = remainder; } return quotient; } private static final Primitive FLOOR = new floor(); } abcl-src-1.9.0/src/org/armedbear/lisp/format.lisp0100644 0000000 0000000 00000377357 14223403213 020406 0ustar000000000 0000000 ;;; format.lisp ;;; ;;; Copyright (C) 2004-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL/SBCL. (in-package "SYSTEM") ;; If we're here due to an autoloader, ;; we should prevent a circular dependency: ;; when the debugger tries to print an error, ;; it autoloads us, but if that autoloading causes ;; another error, it circularly starts autoloading us. ;; ;; So, we replace whatever is in the function slot until ;; we can reliably call FORMAT (setf (symbol-function 'format) #'sys::%format) (require "PRINT-OBJECT") ;;; From primordial-extensions.lisp. ;;; Concatenate together the names of some strings and symbols, ;;; producing a symbol in the current package. (eval-when (:compile-toplevel :load-toplevel :execute) (defun symbolicate (&rest things) (let ((name (apply #'concatenate 'string (mapcar #'string things)))) (values (intern name))))) ;;; a helper function for various macros which expect clauses of a ;;; given length, etc. ;;; ;;; Return true if X is a proper list whose length is between MIN and ;;; MAX (inclusive). (eval-when (:compile-toplevel :load-toplevel :execute) (defun proper-list-of-length-p (x min &optional (max min)) ;; FIXME: This implementation will hang on circular list ;; structure. Since this is an error-checking utility, i.e. its ;; job is to deal with screwed-up input, it'd be good style to fix ;; it so that it can deal with circular list structure. (cond ((minusp max) nil) ((null x) (zerop min)) ((consp x) (and (plusp max) (proper-list-of-length-p (cdr x) (if (plusp (1- min)) (1- min) 0) (1- max)))) (t nil)))) ;;; From early-extensions.lisp. (defconstant form-feed-char-code 12) (defmacro named-let (name binds &body body) (dolist (x binds) (unless (proper-list-of-length-p x 2) (error "malformed NAMED-LET variable spec: ~S" x))) `(labels ((,name ,(mapcar #'first binds) ,@body)) (,name ,@(mapcar #'second binds)))) ;;;; ONCE-ONLY ;;;; ;;;; "The macro ONCE-ONLY has been around for a long time on various ;;;; systems [..] if you can understand how to write and when to use ;;;; ONCE-ONLY, then you truly understand macro." -- Peter Norvig, ;;;; _Paradigms of Artificial Intelligence Programming: Case Studies ;;;; in Common Lisp_, p. 853 ;;; ONCE-ONLY is a utility useful in writing source transforms and ;;; macros. It provides a concise way to wrap a LET around some code ;;; to ensure that some forms are only evaluated once. ;;; ;;; Create a LET* which evaluates each value expression, binding a ;;; temporary variable to the result, and wrapping the LET* around the ;;; result of the evaluation of BODY. Within the body, each VAR is ;;; bound to the corresponding temporary variable. (defmacro once-only (specs &body body) (named-let frob ((specs specs) (body body)) (if (null specs) `(progn ,@body) (let ((spec (first specs))) ;; FIXME: should just be DESTRUCTURING-BIND of SPEC (unless (proper-list-of-length-p spec 2) (error "malformed ONCE-ONLY binding spec: ~S" spec)) (let* ((name (first spec)) (exp-temp (gensym (symbol-name name)))) `(let ((,exp-temp ,(second spec)) (,name (gensym "ONCE-ONLY-"))) `(let ((,,name ,,exp-temp)) ,,(frob (rest specs) body)))))))) ;;; From print.lisp. ;;; FLONUM-TO-STRING (and its subsidiary function FLOAT-STRING) does ;;; most of the work for all printing of floating point numbers in the ;;; printer and in FORMAT. It converts a floating point number to a ;;; string in a free or fixed format with no exponent. The ;;; interpretation of the arguments is as follows: ;;; ;;; X - The floating point number to convert, which must not be ;;; negative. ;;; WIDTH - The preferred field width, used to determine the number ;;; of fraction digits to produce if the FDIGITS parameter ;;; is unspecified or NIL. If the non-fraction digits and the ;;; decimal point alone exceed this width, no fraction digits ;;; will be produced unless a non-NIL value of FDIGITS has been ;;; specified. Field overflow is not considerd an error at this ;;; level. ;;; FDIGITS - The number of fractional digits to produce. Insignificant ;;; trailing zeroes may be introduced as needed. May be ;;; unspecified or NIL, in which case as many digits as possible ;;; are generated, subject to the constraint that there are no ;;; trailing zeroes. ;;; SCALE - If this parameter is specified or non-NIL, then the number ;;; printed is (* x (expt 10 scale)). This scaling is exact, ;;; and cannot lose precision. ;;; FMIN - This parameter, if specified or non-NIL, is the minimum ;;; number of fraction digits which will be produced, regardless ;;; of the value of WIDTH or FDIGITS. This feature is used by ;;; the ~E format directive to prevent complete loss of ;;; significance in the printed value due to a bogus choice of ;;; scale factor. ;;; ;;; Most of the optional arguments are for the benefit for FORMAT and are not ;;; used by the printer. ;;; ;;; Returns: ;;; (VALUES DIGIT-STRING DIGIT-LENGTH LEADING-POINT TRAILING-POINT DECPNT) ;;; where the results have the following interpretation: ;;; ;;; DIGIT-STRING - The decimal representation of X, with decimal point. ;;; DIGIT-LENGTH - The length of the string DIGIT-STRING. ;;; LEADING-POINT - True if the first character of DIGIT-STRING is the ;;; decimal point. ;;; TRAILING-POINT - True if the last character of DIGIT-STRING is the ;;; decimal point. ;;; POINT-POS - The position of the digit preceding the decimal ;;; point. Zero indicates point before first digit. ;;; ;;; NOTE: FLONUM-TO-STRING goes to a lot of trouble to guarantee ;;; accuracy. Specifically, the decimal number printed is the closest ;;; possible approximation to the true value of the binary number to ;;; be printed from among all decimal representations with the same ;;; number of digits. In free-format output, i.e. with the number of ;;; digits unconstrained, it is guaranteed that all the information is ;;; preserved, so that a properly- rounding reader can reconstruct the ;;; original binary number, bit-for-bit, from its printed decimal ;;; representation. Furthermore, only as many digits as necessary to ;;; satisfy this condition will be printed. ;;; ;;; FLOAT-STRING actually generates the digits for positive numbers. ;;; The algorithm is essentially that of algorithm Dragon4 in "How to ;;; Print Floating-Point Numbers Accurately" by Steele and White. The ;;; current (draft) version of this paper may be found in ;;; [CMUC]tradix.press. DO NOT EVEN THINK OF ATTEMPTING TO ;;; UNDERSTAND THIS CODE WITHOUT READING THE PAPER! (defun flonum-to-string (x &optional width fdigits scale fmin) (declare (ignore fmin)) ; FIXME (cond ((zerop x) ;; Zero is a special case which FLOAT-STRING cannot handle. (if fdigits (let ((s (make-string (1+ fdigits) :initial-element #\0))) (setf (schar s 0) #\.) (values s (length s) t (zerop fdigits) 0)) (values "." 1 t t 0))) (t (when scale (setf x (* x (expt 10 scale)))) (let* ((s (float-string x)) (length (length s)) (index (position #\. s))) (when (and (< x 1) (> length 0) (eql (schar s 0) #\0)) (setf s (subseq s 1) length (length s) index (position #\. s))) (when fdigits ;; "Leading zeros are not permitted, except that a single zero ;; digit is output before the decimal point if the printed value ;; is less than one, and this single zero digit is not output at ;; all if w=d+1." (let ((actual-fdigits (- length index 1))) (cond ((< actual-fdigits fdigits) ;; Add the required number of trailing zeroes. (setf s (concatenate 'string s (make-string (- fdigits actual-fdigits) :initial-element #\0)) length (length s))) ((> actual-fdigits fdigits) (let* ((desired-length (+ index 1 fdigits)) (c (schar s desired-length))) (setf s (subseq s 0 (+ index 1 fdigits)) length (length s) index (position #\. s)) (when (char>= c #\5) (setf s (round-up s) length (length s) index (position #\. s)))))))) (when (and width (> length width)) ;; The string is too long. Shorten it by removing insignificant ;; trailing zeroes if possible. (let ((minimum-width (+ (1+ index) (or fdigits 0)))) (when (< minimum-width width) (setf minimum-width width)) (when (> length minimum-width) ;; But we don't want to shorten e.g. "1.7d100"... (when (every #'digit-char-p (subseq s (1+ index))) (let ((c (schar s minimum-width))) (setf s (subseq s 0 minimum-width) length minimum-width) (when (char>= c #\5) (setf s (round-up s) length (length s) index (position #\. s)))))))) (values s length (eql index 0) (eql index (1- length)) index))))) (defun round-up (string) (let* ((index (position #\. string)) (n (read-from-string (setf string (remove #\. string)))) (s (princ-to-string (incf n)))) (loop for char across string while (equal char #\0) do (setf s (concatenate 'string "0" s))) (cond ((null index) s) (t (when (> (length s) (length string)) ;; Rounding up made the string longer, which means we went from (say) 99 ;; to 100. Drop the trailing #\0 and move the #\. one character to the ;; right. (setf s (subseq s 0 (1- (length s)))) (incf index)) (concatenate 'string (subseq s 0 index) "." (subseq s index)))))) (defun scale-exponent (original-x) (let* ((x (coerce original-x 'long-float))) (multiple-value-bind (sig exponent) (decode-float x) (declare (ignore sig)) (if (= x 0.0l0) (values (float 0.0l0 original-x) 1) (let* ((ex (locally (declare (optimize (safety 0))) (the fixnum (round (* exponent (log 2l0 10)))))) (x (if (minusp ex) (if (float-denormalized-p x) (* x 1.0l16 (expt 10.0l0 (- (- ex) 16))) (* x 10.0l0 (expt 10.0l0 (- (- ex) 1)))) (/ x 10.0l0 (expt 10.0l0 (1- ex)))))) (do ((d 10.0l0 (* d 10.0l0)) (y x (/ x d)) (ex ex (1+ ex))) ((< y 1.0l0) (do ((m 10.0l0 (* m 10.0l0)) (z y (* y m)) (ex ex (1- ex))) ((>= z 0.1l0) (values (float z original-x) ex)) (declare (long-float m) (integer ex)))) (declare (long-float d)))))))) (defconstant double-float-exponent-byte (byte 11 20)) (defun float-denormalized-p (x) "Return true if the double-float X is denormalized." (and (zerop (ldb double-float-exponent-byte (double-float-high-bits x))) (not (zerop x)))) ;;; From early-format.lisp. (in-package #:format) (defparameter *format-whitespace-chars* (vector #\space #\newline #\tab)) (defvar *format-directive-expanders* (make-hash-table :test #'eq)) (defvar *format-directive-interpreters* (make-hash-table :test #'eq)) (defvar *default-format-error-control-string* nil) (defvar *default-format-error-offset* nil) ;;;; specials used to communicate information ;;; Used both by the expansion stuff and the interpreter stuff. When it is ;;; non-NIL, up-up-and-out (~:^) is allowed. Otherwise, ~:^ isn't allowed. (defvar *up-up-and-out-allowed* nil) ;;; Used by the interpreter stuff. When it's non-NIL, it's a function ;;; that will invoke PPRINT-POP in the right lexical environemnt. (declaim (type (or null function) *logical-block-popper*)) (defvar *logical-block-popper* nil) ;;; Used by the expander stuff. This is bindable so that ~<...~:> ;;; can change it. (defvar *expander-next-arg-macro* 'expander-next-arg) ;;; Used by the expander stuff. Initially starts as T, and gets set to NIL ;;; if someone needs to do something strange with the arg list (like use ;;; the rest, or something). (defvar *only-simple-args*) ;;; Used by the expander stuff. We do an initial pass with this as NIL. ;;; If someone doesn't like this, they (THROW 'NEED-ORIG-ARGS NIL) and we try ;;; again with it bound to T. If this is T, we don't try to do anything ;;; fancy with args. (defvar *orig-args-available* nil) ;;; Used by the expander stuff. List of (symbol . offset) for simple args. (defvar *simple-args*) ;;; From late-format.lisp. (in-package #:format) (define-condition format-error (error) ((complaint :reader format-error-complaint :initarg :complaint) (args :reader format-error-args :initarg :args :initform nil) (control-string :reader format-error-control-string :initarg :control-string :initform *default-format-error-control-string*) (offset :reader format-error-offset :initarg :offset :initform *default-format-error-offset*) (print-banner :reader format-error-print-banner :initarg :print-banner :initform t)) (:report %print-format-error)) (defun %print-format-error (condition stream) (format stream "~:[~;error in format: ~]~ ~?~@[~% ~A~% ~V@T^~]" (format-error-print-banner condition) (format-error-complaint condition) (format-error-args condition) (format-error-control-string condition) (format-error-offset condition))) (defun missing-arg () (error "Missing argument in format directive")) (defstruct format-directive (string (missing-arg) :type simple-string) (start (missing-arg) :type (and unsigned-byte fixnum)) (end (missing-arg) :type (and unsigned-byte fixnum)) (character (missing-arg) :type base-char) (colonp nil :type (member t nil)) (atsignp nil :type (member t nil)) (params nil :type list)) (defmethod print-object ((x format-directive) stream) (print-unreadable-object (x stream) (write-string (format-directive-string x) stream :start (format-directive-start x) :end (format-directive-end x)))) ;;;; TOKENIZE-CONTROL-STRING (defun tokenize-control-string (string) (declare (simple-string string)) (let ((index 0) (end (length string)) (result nil) (in-block nil) (pprint nil) (semi nil) (justification-semi 0)) (declare (type index fixnum)) (loop (let ((next-directive (or (position #\~ string :start index) end))) (declare (type index next-directive)) (when (> next-directive index) (push (subseq string index next-directive) result)) (when (= next-directive end) (return)) (let* ((directive (parse-directive string next-directive)) (directive-char (format-directive-character directive))) (declare (type character directive-char)) ;; We are looking for illegal combinations of format ;; directives in the control string. See the last paragraph ;; of CLHS 22.3.5.2: "an error is also signaled if the ;; ~<...~:;...~> form of ~<...~> is used in the same format ;; string with ~W, ~_, ~<...~:>, ~I, or ~:T." (cond ((char= #\< directive-char) ;; Found a justification or logical block (setf in-block t)) ((and in-block (char= #\; directive-char)) ;; Found a semi colon in a justification or logical block (setf semi t)) ((char= #\> directive-char) ;; End of justification or logical block. Figure out which. (setf in-block nil) (cond ((format-directive-colonp directive) ;; A logical-block directive. Note that fact, and also ;; note that we don't care if we found any ~; ;; directives in the block. (setf pprint t) (setf semi nil)) (semi ;; A justification block with a ~; directive in it. (incf justification-semi)))) ((and (not in-block) (or (and (char= #\T directive-char) (format-directive-colonp directive)) (char= #\W directive-char) (char= #\_ directive-char) (char= #\I directive-char))) (setf pprint t))) (push directive result) (setf index (format-directive-end directive))))) (when (and pprint (plusp justification-semi)) (error 'format-error :complaint "A justification directive cannot be in the same format string~%~ as ~~W, ~~I, ~~:T, or a logical-block directive." :control-string string :offset 0)) (nreverse result))) (defun parse-directive (string start) (let ((posn (1+ start)) (params nil) (colonp nil) (atsignp nil) (end (length string))) (flet ((get-char () (if (= posn end) (error 'format-error :complaint "String ended before directive was found." :control-string string :offset start) (schar string posn))) (check-ordering () (when (or colonp atsignp) (error 'format-error :complaint "parameters found after #\\: or #\\@ modifier" :control-string string :offset posn)))) (loop (let ((char (get-char))) (cond ((or (char<= #\0 char #\9) (char= char #\+) (char= char #\-)) (check-ordering) (multiple-value-bind (param new-posn) (parse-integer string :start posn :junk-allowed t) (push (cons posn param) params) (setf posn new-posn) (case (get-char) (#\,) ((#\: #\@) (decf posn)) (t (return))))) ((or (char= char #\v) (char= char #\V)) (check-ordering) (push (cons posn :arg) params) (incf posn) (case (get-char) (#\,) ((#\: #\@) (decf posn)) (t (return)))) ((char= char #\#) (check-ordering) (push (cons posn :remaining) params) (incf posn) (case (get-char) (#\,) ((#\: #\@) (decf posn)) (t (return)))) ((char= char #\') (check-ordering) (incf posn) (push (cons posn (get-char)) params) (incf posn) (unless (char= (get-char) #\,) (decf posn))) ((char= char #\,) (check-ordering) (push (cons posn nil) params)) ((char= char #\:) (if colonp (error 'format-error :complaint "too many colons supplied" :control-string string :offset posn) (setf colonp t))) ((char= char #\@) (if atsignp (error 'format-error :complaint "too many #\\@ characters supplied" :control-string string :offset posn) (setf atsignp t))) (t (when (and (char= (schar string (1- posn)) #\,) (or (< posn 2) (char/= (schar string (- posn 2)) #\'))) (check-ordering) (push (cons (1- posn) nil) params)) (return)))) (incf posn)) (let ((char (get-char))) (when (char= char #\/) (let ((closing-slash (position #\/ string :start (1+ posn)))) (if closing-slash (setf posn closing-slash) (error 'format-error :complaint "no matching closing slash" :control-string string :offset posn)))) (make-format-directive :string string :start start :end (1+ posn) :character (char-upcase char) :colonp colonp :atsignp atsignp :params (nreverse params)))))) ;;;; FORMATTER stuff (defmacro formatter (control-string) `#',(%formatter control-string)) (defun %formatter (control-string) (block nil (catch 'need-orig-args (let* ((*simple-args* nil) (*only-simple-args* t) (guts (expand-control-string control-string)) (args nil)) (dolist (arg *simple-args*) (push `(,(car arg) (error 'format-error :complaint "required argument missing" :control-string ,control-string :offset ,(cdr arg))) args)) (return `(lambda (stream &optional ,@args &rest args) ,guts args)))) (let ((*orig-args-available* t) (*only-simple-args* nil)) `(lambda (stream &rest orig-args) (let ((args orig-args)) ,(expand-control-string control-string) args))))) (defun expand-control-string (string) (let* ((string (etypecase string (simple-string string) (string (coerce string 'simple-string)))) (*default-format-error-control-string* string) (directives (tokenize-control-string string))) `(block nil ,@(expand-directive-list directives)))) (defun expand-directive-list (directives) (let ((results nil) (remaining-directives directives)) (loop (unless remaining-directives (return)) (multiple-value-bind (form new-directives) (expand-directive (car remaining-directives) (cdr remaining-directives)) (push form results) (setf remaining-directives new-directives))) (reverse results))) (defun expand-directive (directive more-directives) (etypecase directive (format-directive (let ((expander (gethash (format-directive-character directive) *format-directive-expanders*)) (*default-format-error-offset* (1- (format-directive-end directive)))) (declare (type (or null function) expander)) (if expander (funcall expander directive more-directives) (error 'format-error :complaint "unknown directive ~@[(character: ~A)~]" :args (list (char-name (format-directive-character directive))))))) (simple-string (values `(write-string ,directive stream) more-directives)))) (defmacro expander-next-arg (string offset) `(if args (pop args) (error 'format-error :complaint "no more arguments" :control-string ,string :offset ,offset))) (defun expand-next-arg (&optional offset) (if (or *orig-args-available* (not *only-simple-args*)) `(,*expander-next-arg-macro* ,*default-format-error-control-string* ,(or offset *default-format-error-offset*)) (let ((symbol (gensym "FORMAT-ARG-"))) (push (cons symbol (or offset *default-format-error-offset*)) *simple-args*) symbol))) (defmacro expand-bind-defaults (specs params &body body) (sys::once-only ((params params)) (if specs (collect ((expander-bindings) (runtime-bindings)) (dolist (spec specs) (destructuring-bind (var default) spec (let ((symbol (gensym))) (expander-bindings `(,var ',symbol)) (runtime-bindings `(list ',symbol (let* ((param-and-offset (pop ,params)) (offset (car param-and-offset)) (param (cdr param-and-offset))) (case param (:arg `(or ,(expand-next-arg offset) ,,default)) (:remaining (setf *only-simple-args* nil) '(length args)) ((nil) ,default) (t param)))))))) `(let ,(expander-bindings) `(let ,(list ,@(runtime-bindings)) ,@(if ,params (error 'format-error :complaint "too many parameters, expected no more than ~W" :args (list ,(length specs)) :offset (caar ,params))) ,,@body))) `(progn (when ,params (error 'format-error :complaint "too many parameters, expected none" :offset (caar ,params))) ,@body)))) ;;;; format directive machinery ;;; FIXME: only used in this file, could be SB!XC:DEFMACRO in EVAL-WHEN (defmacro def-complex-format-directive (char lambda-list &body body) (let ((defun-name (intern (concatenate 'string (let ((name (char-name char))) (cond (name (string-capitalize name)) (t (string char)))) "-FORMAT-DIRECTIVE-EXPANDER"))) (directive (gensym)) (directives (if lambda-list (car (last lambda-list)) (gensym)))) `(progn (defun ,defun-name (,directive ,directives) ,@(if lambda-list `((let ,(mapcar (lambda (var) `(,var (,(sys::symbolicate "FORMAT-DIRECTIVE-" var) ,directive))) (butlast lambda-list)) ,@body)) `((declare (ignore ,directive ,directives)) ,@body))) (%set-format-directive-expander ,char #',defun-name)))) ;;; FIXME: only used in this file, could be SB!XC:DEFMACRO in EVAL-WHEN (defmacro def-format-directive (char lambda-list &body body) (let ((directives (gensym)) (declarations nil) (body-without-decls body)) (loop (let ((form (car body-without-decls))) (unless (and (consp form) (eq (car form) 'declare)) (return)) (push (pop body-without-decls) declarations))) (setf declarations (reverse declarations)) `(def-complex-format-directive ,char (,@lambda-list ,directives) ,@declarations (values (progn ,@body-without-decls) ,directives)))) (eval-when (:compile-toplevel :load-toplevel :execute) (defun %set-format-directive-expander (char fn) (setf (gethash (char-upcase char) *format-directive-expanders*) fn) char) (defun %set-format-directive-interpreter (char fn) (setf (gethash (char-upcase char) *format-directive-interpreters*) fn) char) (defun find-directive (directives kind stop-at-semi) (if directives (let ((next (car directives))) (if (format-directive-p next) (let ((char (format-directive-character next))) (if (or (char= kind char) (and stop-at-semi (char= char #\;))) (car directives) (find-directive (cdr (flet ((after (char) (member (find-directive (cdr directives) char nil) directives))) (case char (#\( (after #\))) (#\< (after #\>)) (#\[ (after #\])) (#\{ (after #\})) (t directives)))) kind stop-at-semi))) (find-directive (cdr directives) kind stop-at-semi))))) ) ; EVAL-WHEN ;;;; format directives for simple output (def-format-directive #\A (colonp atsignp params) (if params (expand-bind-defaults ((mincol 0) (colinc 1) (minpad 0) (padchar #\space)) params `(format-princ stream ,(expand-next-arg) ',colonp ',atsignp ,mincol ,colinc ,minpad ,padchar)) `(princ ,(if colonp `(or ,(expand-next-arg) "()") (expand-next-arg)) stream))) (def-format-directive #\S (colonp atsignp params) (cond (params (expand-bind-defaults ((mincol 0) (colinc 1) (minpad 0) (padchar #\space)) params `(format-prin1 stream ,(expand-next-arg) ,colonp ,atsignp ,mincol ,colinc ,minpad ,padchar))) (colonp `(let ((arg ,(expand-next-arg))) (if arg (prin1 arg stream) (princ "()" stream)))) (t `(prin1 ,(expand-next-arg) stream)))) (def-format-directive #\C (colonp atsignp params) (expand-bind-defaults () params (if colonp `(format-print-named-character ,(expand-next-arg) stream) (if atsignp `(prin1 ,(expand-next-arg) stream) `(write-char ,(expand-next-arg) stream))))) (def-format-directive #\W (colonp atsignp params) (expand-bind-defaults () params (if (or colonp atsignp) `(let (,@(when colonp '((*print-pretty* t))) ,@(when atsignp '((*print-level* nil) (*print-length* nil)))) (sys::output-object ,(expand-next-arg) stream)) `(sys::output-object ,(expand-next-arg) stream)))) ;;;; format directives for integer output (defun expand-format-integer (base colonp atsignp params) (if (or colonp atsignp params) (expand-bind-defaults ((mincol 0) (padchar #\space) (commachar #\,) (commainterval 3)) params `(format-print-integer stream ,(expand-next-arg) ,colonp ,atsignp ,base ,mincol ,padchar ,commachar ,commainterval)) `(write ,(expand-next-arg) :stream stream :base ,base :radix nil :escape nil))) (def-format-directive #\D (colonp atsignp params) (expand-format-integer 10 colonp atsignp params)) (def-format-directive #\B (colonp atsignp params) (expand-format-integer 2 colonp atsignp params)) (def-format-directive #\O (colonp atsignp params) (expand-format-integer 8 colonp atsignp params)) (def-format-directive #\X (colonp atsignp params) (expand-format-integer 16 colonp atsignp params)) (def-format-directive #\R (colonp atsignp params) (expand-bind-defaults ((base nil) (mincol 0) (padchar #\space) (commachar #\,) (commainterval 3)) params (let ((n-arg (gensym))) `(let ((,n-arg ,(expand-next-arg))) (if ,base (format-print-integer stream ,n-arg ,colonp ,atsignp ,base ,mincol ,padchar ,commachar ,commainterval) ,(if atsignp (if colonp `(format-print-old-roman stream ,n-arg) `(format-print-roman stream ,n-arg)) (if colonp `(format-print-ordinal stream ,n-arg) `(format-print-cardinal stream ,n-arg)))))))) ;;;; format directive for pluralization (def-format-directive #\P (colonp atsignp params end) (expand-bind-defaults () params (let ((arg (cond ((not colonp) (expand-next-arg)) (*orig-args-available* `(if (eq orig-args args) (error 'format-error :complaint "no previous argument" :offset ,(1- end)) (do ((arg-ptr orig-args (cdr arg-ptr))) ((eq (cdr arg-ptr) args) (car arg-ptr))))) (*only-simple-args* (unless *simple-args* (error 'format-error :complaint "no previous argument")) (caar *simple-args*)) (t (throw 'need-orig-args nil))))) (if atsignp `(write-string (if (eql ,arg 1) "y" "ies") stream) `(unless (eql ,arg 1) (write-char #\s stream)))))) ;;;; format directives for floating point output (def-format-directive #\F (colonp atsignp params) (when colonp (error 'format-error :complaint "The colon modifier cannot be used with this directive.")) (expand-bind-defaults ((w nil) (d nil) (k nil) (ovf nil) (pad #\space)) params `(format-fixed stream ,(expand-next-arg) ,w ,d ,k ,ovf ,pad ,atsignp))) (def-format-directive #\E (colonp atsignp params) (when colonp (error 'format-error :complaint "The colon modifier cannot be used with this directive.")) (expand-bind-defaults ((w nil) (d nil) (e nil) (k 1) (ovf nil) (pad #\space) (mark nil)) params `(format-exponential stream ,(expand-next-arg) ,w ,d ,e ,k ,ovf ,pad ,mark ,atsignp))) (def-format-directive #\G (colonp atsignp params) (when colonp (error 'format-error :complaint "The colon modifier cannot be used with this directive.")) (expand-bind-defaults ((w nil) (d nil) (e nil) (k nil) (ovf nil) (pad #\space) (mark nil)) params `(format-general stream ,(expand-next-arg) ,w ,d ,e ,k ,ovf ,pad ,mark ,atsignp))) (def-format-directive #\$ (colonp atsignp params) (expand-bind-defaults ((d 2) (n 1) (w 0) (pad #\space)) params `(format-dollars stream ,(expand-next-arg) ,d ,n ,w ,pad ,colonp ,atsignp))) ;;;; format directives for line/page breaks etc. (def-format-directive #\% (colonp atsignp params) (when (or colonp atsignp) (error 'format-error :complaint "The colon and atsign modifiers cannot be used with this directive." )) (if params (expand-bind-defaults ((count 1)) params `(dotimes (i ,count) (terpri stream))) '(terpri stream))) (def-format-directive #\& (colonp atsignp params) (when (or colonp atsignp) (error 'format-error :complaint "The colon and atsign modifiers cannot be used with this directive." )) (if params (expand-bind-defaults ((count 1)) params `(progn (fresh-line stream) (dotimes (i (1- ,count)) (terpri stream)))) '(fresh-line stream))) (def-format-directive #\| (colonp atsignp params) (when (or colonp atsignp) (error 'format-error :complaint "The colon and atsign modifiers cannot be used with this directive." )) (if params (expand-bind-defaults ((count 1)) params `(dotimes (i ,count) (write-char (code-char sys::form-feed-char-code) stream))) '(write-char (code-char sys::form-feed-char-code) stream))) (def-format-directive #\~ (colonp atsignp params) (when (or colonp atsignp) (error 'format-error :complaint "The colon and atsign modifiers cannot be used with this directive." )) (if params (expand-bind-defaults ((count 1)) params `(dotimes (i ,count) (write-char #\~ stream))) '(write-char #\~ stream))) (def-complex-format-directive #\newline (colonp atsignp params directives) (when (and colonp atsignp) (error 'format-error :complaint "both colon and atsign modifiers used simultaneously")) (values (expand-bind-defaults () params (if atsignp '(write-char #\newline stream) nil)) (if (and (not colonp) directives (simple-string-p (car directives))) (cons (string-left-trim *format-whitespace-chars* (car directives)) (cdr directives)) directives))) ;;;; format directives for tabs and simple pretty printing (def-format-directive #\T (colonp atsignp params) (if colonp (expand-bind-defaults ((n 1) (m 1)) params `(pprint-tab ,(if atsignp :section-relative :section) ,n ,m stream)) (if atsignp (expand-bind-defaults ((colrel 1) (colinc 1)) params `(format-relative-tab stream ,colrel ,colinc)) (expand-bind-defaults ((colnum 1) (colinc 1)) params `(format-absolute-tab stream ,colnum ,colinc))))) (def-format-directive #\_ (colonp atsignp params) (expand-bind-defaults () params `(pprint-newline ,(if colonp (if atsignp :mandatory :fill) (if atsignp :miser :linear)) stream))) (def-format-directive #\I (colonp atsignp params) (when atsignp (error 'format-error :complaint "cannot use the at-sign modifier with this directive")) (expand-bind-defaults ((n 0)) params `(pprint-indent ,(if colonp :current :block) ,n stream))) ;;;; format directive for ~* (def-format-directive #\* (colonp atsignp params end) (if atsignp (if colonp (error 'format-error :complaint "both colon and atsign modifiers used simultaneously") (expand-bind-defaults ((posn 0)) params (unless *orig-args-available* (throw 'need-orig-args nil)) `(if (<= 0 ,posn (length orig-args)) (setf args (nthcdr ,posn orig-args)) (error 'format-error :complaint "Index ~W out of bounds. Should have been ~ between 0 and ~W." :args (list ,posn (length orig-args)) :offset ,(1- end))))) (if colonp (expand-bind-defaults ((n 1)) params (unless *orig-args-available* (throw 'need-orig-args nil)) `(do ((cur-posn 0 (1+ cur-posn)) (arg-ptr orig-args (cdr arg-ptr))) ((eq arg-ptr args) (let ((new-posn (- cur-posn ,n))) (if (<= 0 new-posn (length orig-args)) (setf args (nthcdr new-posn orig-args)) (error 'format-error :complaint "Index ~W is out of bounds; should have been ~ between 0 and ~W." :args (list new-posn (length orig-args)) :offset ,(1- end))))))) (if params (expand-bind-defaults ((n 1)) params (setf *only-simple-args* nil) `(dotimes (i ,n) ,(expand-next-arg))) (expand-next-arg))))) ;;;; format directive for indirection (def-format-directive #\? (colonp atsignp params string end) (when colonp (error 'format-error :complaint "cannot use the colon modifier with this directive")) (expand-bind-defaults () params `(handler-bind ((format-error (lambda (condition) (error 'format-error :complaint "~A~%while processing indirect format string:" :args (list condition) :print-banner nil :control-string ,string :offset ,(1- end))))) ,(if atsignp (if *orig-args-available* `(setf args (%format stream ,(expand-next-arg) orig-args args)) (throw 'need-orig-args nil)) `(%format stream ,(expand-next-arg) ,(expand-next-arg)))))) ;;;; format directives for capitalization (def-complex-format-directive #\( (colonp atsignp params directives) (let ((close (find-directive directives #\) nil))) (unless close (error 'format-error :complaint "no corresponding close parenthesis")) (let* ((posn (position close directives)) (before (subseq directives 0 posn)) (after (nthcdr (1+ posn) directives))) (values (expand-bind-defaults () params `(let ((stream (sys::make-case-frob-stream (if (typep stream 'xp::xp-structure) (xp::base-stream stream) stream) ,(if colonp (if atsignp :upcase :capitalize) (if atsignp :capitalize-first :downcase))))) ,@(expand-directive-list before))) after)))) (def-complex-format-directive #\) () (error 'format-error :complaint "no corresponding open parenthesis")) ;;;; format directives and support functions for conditionalization (def-complex-format-directive #\[ (colonp atsignp params directives) (multiple-value-bind (sublists last-semi-with-colon-p remaining) (parse-conditional-directive directives) (values (if atsignp (if colonp (error 'format-error :complaint "both colon and atsign modifiers used simultaneously") (if (cdr sublists) (error 'format-error :complaint "Can only specify one section") (expand-bind-defaults () params (expand-maybe-conditional (car sublists))))) (if colonp (if (= (length sublists) 2) (expand-bind-defaults () params (expand-true-false-conditional (car sublists) (cadr sublists))) (error 'format-error :complaint "must specify exactly two sections")) (expand-bind-defaults ((index nil)) params (setf *only-simple-args* nil) (let ((clauses nil) (case `(or ,index ,(expand-next-arg)))) (when last-semi-with-colon-p (push `(t ,@(expand-directive-list (pop sublists))) clauses)) (let ((count (length sublists))) (dolist (sublist sublists) (push `(,(decf count) ,@(expand-directive-list sublist)) clauses))) `(case ,case ,@clauses))))) remaining))) (defun parse-conditional-directive (directives) (let ((sublists nil) (last-semi-with-colon-p nil) (remaining directives)) (loop (let ((close-or-semi (find-directive remaining #\] t))) (unless close-or-semi (error 'format-error :complaint "no corresponding close bracket")) (let ((posn (position close-or-semi remaining))) (push (subseq remaining 0 posn) sublists) (setf remaining (nthcdr (1+ posn) remaining)) (when (char= (format-directive-character close-or-semi) #\]) (return)) (setf last-semi-with-colon-p (format-directive-colonp close-or-semi))))) (values sublists last-semi-with-colon-p remaining))) (defun expand-maybe-conditional (sublist) (flet ((hairy () `(let ((prev-args args) (arg ,(expand-next-arg))) (when arg (setf args prev-args) ,@(expand-directive-list sublist))))) (if *only-simple-args* (multiple-value-bind (guts new-args) (let ((*simple-args* *simple-args*)) (values (expand-directive-list sublist) *simple-args*)) (cond ((and new-args (eq *simple-args* (cdr new-args))) (setf *simple-args* new-args) `(when ,(caar new-args) ,@guts)) (t (setf *only-simple-args* nil) (hairy)))) (hairy)))) (defun expand-true-false-conditional (true false) (let ((arg (expand-next-arg))) (flet ((hairy () `(if ,arg (progn ,@(expand-directive-list true)) (progn ,@(expand-directive-list false))))) (if *only-simple-args* (multiple-value-bind (true-guts true-args true-simple) (let ((*simple-args* *simple-args*) (*only-simple-args* t)) (values (expand-directive-list true) *simple-args* *only-simple-args*)) (multiple-value-bind (false-guts false-args false-simple) (let ((*simple-args* *simple-args*) (*only-simple-args* t)) (values (expand-directive-list false) *simple-args* *only-simple-args*)) (if (= (length true-args) (length false-args)) `(if ,arg (progn ,@true-guts) ,(do ((false false-args (cdr false)) (true true-args (cdr true)) (bindings nil (cons `(,(caar false) ,(caar true)) bindings))) ((eq true *simple-args*) (setf *simple-args* true-args) (setf *only-simple-args* (and true-simple false-simple)) (if bindings `(let ,bindings ,@false-guts) `(progn ,@false-guts))))) (progn (setf *only-simple-args* nil) (hairy))))) (hairy))))) (def-complex-format-directive #\; () (error 'format-error :complaint "~~; directive not contained within either ~~[...~~] or ~~<...~~>")) (def-complex-format-directive #\] () (error 'format-error :complaint "no corresponding open bracket")) ;;;; format directive for up-and-out (def-format-directive #\^ (colonp atsignp params) (when atsignp (error 'format-error :complaint "cannot use the at-sign modifier with this directive")) (when (and colonp (not *up-up-and-out-allowed*)) (error 'format-error :complaint "attempt to use ~~:^ outside a ~~:{...~~} construct")) `(when ,(expand-bind-defaults ((arg1 nil) (arg2 nil) (arg3 nil)) params `(cond (,arg3 (<= ,arg1 ,arg2 ,arg3)) (,arg2 (eql ,arg1 ,arg2)) (,arg1 (eql ,arg1 0)) (t ,(if colonp '(null outside-args) (progn (setf *only-simple-args* nil) '(null args)))))) ,(if colonp '(return-from outside-loop nil) '(return)))) ;;;; format directives for iteration (def-complex-format-directive #\{ (colonp atsignp params string end directives) (let ((close (find-directive directives #\} nil))) (unless close (error 'format-error :complaint "no corresponding close brace")) (let* ((closed-with-colon (format-directive-colonp close)) (posn (position close directives))) (labels ((compute-insides () (if (zerop posn) (if *orig-args-available* `((handler-bind ((format-error (lambda (condition) (error 'format-error :complaint "~A~%while processing indirect format string:" :args (list condition) :print-banner nil :control-string ,string :offset ,(1- end))))) (setf args (%format stream inside-string orig-args args)))) (throw 'need-orig-args nil)) (let ((*up-up-and-out-allowed* colonp)) (expand-directive-list (subseq directives 0 posn))))) (compute-loop (count) (when atsignp (setf *only-simple-args* nil)) `(loop ,@(unless closed-with-colon '((when (null args) (return)))) ,@(when count `((when (and ,count (minusp (decf ,count))) (return)))) ,@(if colonp (let ((*expander-next-arg-macro* 'expander-next-arg) (*only-simple-args* nil) (*orig-args-available* t)) `((let* ((orig-args ,(expand-next-arg)) (outside-args args) (args orig-args)) (declare (ignorable orig-args outside-args args)) (block nil ,@(compute-insides))))) (compute-insides)) ,@(when closed-with-colon '((when (null args) (return)))))) (compute-block (count) (if colonp `(block outside-loop ,(compute-loop count)) (compute-loop count))) (compute-bindings (count) (if atsignp (compute-block count) `(let* ((orig-args ,(expand-next-arg)) (args orig-args)) (declare (ignorable orig-args args)) ,(let ((*expander-next-arg-macro* 'expander-next-arg) (*only-simple-args* nil) (*orig-args-available* t)) (compute-block count)))))) (values (if params (expand-bind-defaults ((count nil)) params (if (zerop posn) `(let ((inside-string ,(expand-next-arg))) ,(compute-bindings count)) (compute-bindings count))) (if (zerop posn) `(let ((inside-string ,(expand-next-arg))) ,(compute-bindings nil)) (compute-bindings nil))) (nthcdr (1+ posn) directives)))))) (def-complex-format-directive #\} () (error 'format-error :complaint "no corresponding open brace")) ;;;; format directives and support functions for justification (defparameter *illegal-inside-justification* (mapcar (lambda (x) (parse-directive x 0)) '("~W" "~:W" "~@W" "~:@W" "~_" "~:_" "~@_" "~:@_" "~:>" "~:@>" "~I" "~:I" "~@I" "~:@I" "~:T" "~:@T"))) (defun illegal-inside-justification-p (directive) (member directive *illegal-inside-justification* :test (lambda (x y) (and (format-directive-p x) (format-directive-p y) (eql (format-directive-character x) (format-directive-character y)) (eql (format-directive-colonp x) (format-directive-colonp y)) (eql (format-directive-atsignp x) (format-directive-atsignp y)))))) (def-complex-format-directive #\< (colonp atsignp params string end directives) (multiple-value-bind (segments first-semi close remaining) (parse-format-justification directives) (values (if (format-directive-colonp close) (multiple-value-bind (prefix per-line-p insides suffix) (parse-format-logical-block segments colonp first-semi close params string end) (expand-format-logical-block prefix per-line-p insides suffix atsignp)) (let ((count (reduce #'+ (mapcar (lambda (x) (count-if #'illegal-inside-justification-p x)) segments)))) (when (> count 0) ;; ANSI specifies that "an error is signalled" in this ;; situation. (error 'format-error :complaint "~D illegal directive~:P found inside justification block" :args (list count))) (expand-format-justification segments colonp atsignp first-semi params))) remaining))) (def-complex-format-directive #\> () (error 'format-error :complaint "no corresponding open bracket")) (defun parse-format-logical-block (segments colonp first-semi close params string end) (when params (error 'format-error :complaint "No parameters can be supplied with ~~<...~~:>." :offset (caar params))) (multiple-value-bind (prefix insides suffix) (multiple-value-bind (prefix-default suffix-default) (if colonp (values "(" ")") (values "" "")) (flet ((extract-string (list prefix-p) (let ((directive (find-if #'format-directive-p list))) (if directive (error 'format-error :complaint "cannot include format directives inside the ~ ~:[suffix~;prefix~] segment of ~~<...~~:>" :args (list prefix-p) :offset (1- (format-directive-end directive))) (apply #'concatenate 'string list))))) (case (length segments) (0 (values prefix-default nil suffix-default)) (1 (values prefix-default (car segments) suffix-default)) (2 (values (extract-string (car segments) t) (cadr segments) suffix-default)) (3 (values (extract-string (car segments) t) (cadr segments) (extract-string (caddr segments) nil))) (t (error 'format-error :complaint "too many segments for ~~<...~~:>"))))) (when (format-directive-atsignp close) (setf insides (add-fill-style-newlines insides string (if first-semi (format-directive-end first-semi) end)))) (values prefix (and first-semi (format-directive-atsignp first-semi)) insides suffix))) (defun add-fill-style-newlines (list string offset &optional last-directive) (cond (list (let ((directive (car list))) (cond ((simple-string-p directive) (let* ((non-space (position #\Space directive :test #'char/=)) (newlinep (and last-directive (char= (format-directive-character last-directive) #\Newline)))) (cond ((and newlinep non-space) (nconc (list (subseq directive 0 non-space)) (add-fill-style-newlines-aux (subseq directive non-space) string (+ offset non-space)) (add-fill-style-newlines (cdr list) string (+ offset (length directive))))) (newlinep (cons directive (add-fill-style-newlines (cdr list) string (+ offset (length directive))))) (t (nconc (add-fill-style-newlines-aux directive string offset) (add-fill-style-newlines (cdr list) string (+ offset (length directive)))))))) (t (cons directive (add-fill-style-newlines (cdr list) string (format-directive-end directive) directive)))))) (t nil))) (defun add-fill-style-newlines-aux (literal string offset) (let ((end (length literal)) (posn 0)) (collect ((results)) (loop (let ((blank (position #\space literal :start posn))) (when (null blank) (results (subseq literal posn)) (return)) (let ((non-blank (or (position #\space literal :start blank :test #'char/=) end))) (results (subseq literal posn non-blank)) (results (make-format-directive :string string :character #\_ :start (+ offset non-blank) :end (+ offset non-blank) :colonp t :atsignp nil :params nil)) (setf posn non-blank)) (when (= posn end) (return)))) (results)))) (defun parse-format-justification (directives) (let ((first-semi nil) (close nil) (remaining directives)) (collect ((segments)) (loop (let ((close-or-semi (find-directive remaining #\> t))) (unless close-or-semi (error 'format-error :complaint "no corresponding close bracket")) (let ((posn (position close-or-semi remaining))) (segments (subseq remaining 0 posn)) (setf remaining (nthcdr (1+ posn) remaining))) (when (char= (format-directive-character close-or-semi) #\>) (setf close close-or-semi) (return)) (unless first-semi (setf first-semi close-or-semi)))) (values (segments) first-semi close remaining)))) (defmacro expander-pprint-next-arg (string offset) `(progn (when (null args) (error 'format-error :complaint "no more arguments" :control-string ,string :offset ,offset)) (pprint-pop) (pop args))) (defun expand-format-logical-block (prefix per-line-p insides suffix atsignp) `(let ((arg ,(if atsignp 'args (expand-next-arg)))) ,@(when atsignp (setf *only-simple-args* nil) '((setf args nil))) (pprint-logical-block (stream arg ,(if per-line-p :per-line-prefix :prefix) ,prefix :suffix ,suffix) (let ((args arg) ,@(unless atsignp `((orig-args arg)))) (declare (ignorable args ,@(unless atsignp '(orig-args)))) (block nil ,@(let ((*expander-next-arg-macro* 'expander-pprint-next-arg) (*only-simple-args* nil) (*orig-args-available* (if atsignp *orig-args-available* t))) (expand-directive-list insides))))))) (defun expand-format-justification (segments colonp atsignp first-semi params) (let ((newline-segment-p (and first-semi (format-directive-colonp first-semi)))) (expand-bind-defaults ((mincol 0) (colinc 1) (minpad 0) (padchar #\space)) params `(let ((segments nil) ,@(when newline-segment-p '((newline-segment nil) (extra-space 0) (line-len 72)))) (block nil ,@(when newline-segment-p `((setf newline-segment (with-output-to-string (stream) ,@(expand-directive-list (pop segments)))) ,(expand-bind-defaults ((extra 0) (line-len '(or #-abcl(sb!impl::line-length stream) 72))) (format-directive-params first-semi) `(setf extra-space ,extra line-len ,line-len)))) ,@(mapcar (lambda (segment) `(push (with-output-to-string (stream) ,@(expand-directive-list segment)) segments)) segments)) (format-justification stream ,@(if newline-segment-p '(newline-segment extra-space line-len) '(nil 0 0)) segments ,colonp ,atsignp ,mincol ,colinc ,minpad ,padchar))))) ;;;; format directive and support function for user-defined method (def-format-directive #\/ (string start end colonp atsignp params) (let ((symbol (extract-user-fun-name string start end))) (collect ((param-names) (bindings)) (dolist (param-and-offset params) (let ((param (cdr param-and-offset))) (let ((param-name (gensym))) (param-names param-name) (bindings `(,param-name ,(case param (:arg (expand-next-arg)) (:remaining '(length args)) (t param))))))) `(let ,(bindings) (,symbol stream ,(expand-next-arg) ,colonp ,atsignp ,@(param-names)))))) (defun extract-user-fun-name (string start end) (let ((slash (position #\/ string :start start :end (1- end) :from-end t))) (unless slash (error 'format-error :complaint "malformed ~~/ directive")) (let* ((name (string-upcase (let ((foo string)) ;; Hack alert: This is to keep the compiler ;; quiet about deleting code inside the ;; subseq expansion. (subseq foo (1+ slash) (1- end))))) (first-colon (position #\: name)) (second-colon (if first-colon (position #\: name :start (1+ first-colon)))) (package-name (if first-colon (subseq name 0 first-colon) "COMMON-LISP-USER")) (package (find-package package-name))) (unless package ;; FIXME: should be PACKAGE-ERROR? Could we just use ;; FIND-UNDELETED-PACKAGE-OR-LOSE? (error 'format-error :complaint "no package named ~S" :args (list package-name))) (intern (cond ((and second-colon (= second-colon (1+ first-colon))) (subseq name (1+ second-colon))) (first-colon (subseq name (1+ first-colon))) (t name)) package)))) ;;; compile-time checking for argument mismatch. This code is ;;; inspired by that of Gerd Moellmann, and comes decorated with ;;; FIXMEs: (defun %compiler-walk-format-string (string args) (declare (type simple-string string)) (let ((*default-format-error-control-string* string)) (macrolet ((incf-both (&optional (increment 1)) `(progn (incf min ,increment) (incf max ,increment))) (walk-complex-directive (function) `(multiple-value-bind (min-inc max-inc remaining) (,function directive directives args) (incf min min-inc) (incf max max-inc) (setq directives remaining)))) ;; FIXME: these functions take a list of arguments as well as ;; the directive stream. This is to enable possibly some ;; limited type checking on FORMAT's arguments, as well as ;; simple argument count mismatch checking: when the minimum and ;; maximum argument counts are the same at a given point, we ;; know which argument is going to be used for a given ;; directive, and some (annotated below) require arguments of ;; particular types. (labels ((walk-justification (justification directives args) (declare (ignore args)) (let ((*default-format-error-offset* (1- (format-directive-end justification)))) (multiple-value-bind (segments first-semi close remaining) (parse-format-justification directives) (declare (ignore segments first-semi)) (cond ((not (format-directive-colonp close)) (values 0 0 directives)) ((format-directive-atsignp justification) (values 0 call-arguments-limit directives)) ;; FIXME: here we could assert that the ;; corresponding argument was a list. (t (values 1 1 remaining)))))) (walk-conditional (conditional directives args) (let ((*default-format-error-offset* (1- (format-directive-end conditional)))) (multiple-value-bind (sublists last-semi-with-colon-p remaining) (parse-conditional-directive directives) (declare (ignore last-semi-with-colon-p)) (let ((sub-max (loop for s in sublists maximize (nth-value 1 (walk-directive-list s args))))) (cond ((format-directive-atsignp conditional) (values 1 (max 1 sub-max) remaining)) ((loop for p in (format-directive-params conditional) thereis (or (integerp (cdr p)) (memq (cdr p) '(:remaining :arg)))) (values 0 sub-max remaining)) ;; FIXME: if not COLONP, then the next argument ;; must be a number. (t (values 1 (1+ sub-max) remaining))))))) (walk-iteration (iteration directives args) (declare (ignore args)) (let ((*default-format-error-offset* (1- (format-directive-end iteration)))) (let* ((close (find-directive directives #\} nil)) (posn (or (position close directives) (error 'format-error :complaint "no corresponding close brace"))) (remaining (nthcdr (1+ posn) directives))) ;; FIXME: if POSN is zero, the next argument must be ;; a format control (either a function or a string). (if (format-directive-atsignp iteration) (values (if (zerop posn) 1 0) call-arguments-limit remaining) ;; FIXME: the argument corresponding to this ;; directive must be a list. (let ((nreq (if (zerop posn) 2 1))) (values nreq nreq remaining)))))) (walk-directive-list (directives args) (let ((min 0) (max 0)) (loop (let ((directive (pop directives))) (when (null directive) (return (values min (min max call-arguments-limit)))) (when (format-directive-p directive) (incf-both (count :arg (format-directive-params directive) :key #'cdr)) (let ((c (format-directive-character directive))) (cond ((find c "ABCDEFGORSWX$/") (incf-both)) ((char= c #\P) (unless (format-directive-colonp directive) (incf-both))) ((or (find c "IT%&|_();>") (char= c #\Newline))) ;; FIXME: check correspondence of ~( and ~) ((char= c #\<) (walk-complex-directive walk-justification)) ((char= c #\[) (walk-complex-directive walk-conditional)) ((char= c #\{) (walk-complex-directive walk-iteration)) ((char= c #\?) ;; FIXME: the argument corresponding to this ;; directive must be a format control. (cond ((format-directive-atsignp directive) (incf min) (setq max call-arguments-limit)) (t (incf-both 2)))) (t (throw 'give-up-format-string-walk nil)))))))))) (catch 'give-up-format-string-walk (let ((directives (tokenize-control-string string))) (walk-directive-list directives args))))))) ;;; From target-format.lisp. (in-package #:format) (defun format (destination control-string &rest format-arguments) (etypecase destination (null (with-output-to-string (stream) (%format stream control-string format-arguments))) (string (with-output-to-string (stream destination) (%format stream control-string format-arguments))) ((member t) (%format *standard-output* control-string format-arguments) nil) ((or stream xp::xp-structure) (%format destination control-string format-arguments) nil))) (defun %format (stream string-or-fun orig-args &optional (args orig-args)) (if (functionp string-or-fun) (apply string-or-fun stream args) (catch 'up-and-out (let* ((string (etypecase string-or-fun (simple-string string-or-fun) (string (coerce string-or-fun 'simple-string)))) (*default-format-error-control-string* string) (*logical-block-popper* nil)) (interpret-directive-list stream (tokenize-control-string string) orig-args args))))) (defun interpret-directive-list (stream directives orig-args args) (if directives (let ((directive (car directives))) (etypecase directive (simple-string (write-string directive stream) (interpret-directive-list stream (cdr directives) orig-args args)) (format-directive (multiple-value-bind (new-directives new-args) (let* ((character (format-directive-character directive)) (function (gethash character *format-directive-interpreters*)) (*default-format-error-offset* (1- (format-directive-end directive)))) (unless function (error 'format-error :complaint "unknown format directive ~@[(character: ~A)~]" :args (list (char-name character)))) (multiple-value-bind (new-directives new-args) (funcall function stream directive (cdr directives) orig-args args) (values new-directives new-args))) (interpret-directive-list stream new-directives orig-args new-args))))) args)) ;;;; FORMAT directive definition macros and runtime support (eval-when (:compile-toplevel :execute) ;;; This macro is used to extract the next argument from the current arg list. ;;; This is the version used by format directive interpreters. (defmacro next-arg (&optional offset) `(progn (when (null args) (error 'format-error :complaint "no more arguments" ,@(when offset `(:offset ,offset)))) (when *logical-block-popper* (funcall *logical-block-popper*)) (pop args))) (defmacro def-complex-format-interpreter (char lambda-list &body body) (let ((defun-name (intern (concatenate 'string (let ((name (char-name char))) (cond (name (string-capitalize name)) (t (string char)))) "-FORMAT-DIRECTIVE-INTERPRETER"))) (directive (gensym)) (directives (if lambda-list (car (last lambda-list)) (gensym)))) `(progn (defun ,defun-name (stream ,directive ,directives orig-args args) (declare (ignorable stream orig-args args)) ,@(if lambda-list `((let ,(mapcar (lambda (var) `(,var (,(sys::symbolicate "FORMAT-DIRECTIVE-" var) ,directive))) (butlast lambda-list)) (values (progn ,@body) args))) `((declare (ignore ,directive ,directives)) ,@body))) (%set-format-directive-interpreter ,char #',defun-name)))) (defmacro def-format-interpreter (char lambda-list &body body) (let ((directives (gensym))) `(def-complex-format-interpreter ,char (,@lambda-list ,directives) ,@body ,directives))) (defmacro interpret-bind-defaults (specs params &body body) (sys::once-only ((params params)) (collect ((bindings)) (dolist (spec specs) (destructuring-bind (var default) spec (bindings `(,var (let* ((param-and-offset (pop ,params)) (offset (car param-and-offset)) (param (cdr param-and-offset))) (case param (:arg (or (next-arg offset) ,default)) (:remaining (length args)) ((nil) ,default) (t param))))))) `(let* ,(bindings) (when ,params (error 'format-error :complaint "too many parameters, expected no more than ~W" :args (list ,(length specs)) :offset (caar ,params))) ,@body)))) ) ; EVAL-WHEN ;;;; format interpreters and support functions for simple output (defun format-write-field (stream string mincol colinc minpad padchar padleft) (unless padleft (write-string string stream)) (dotimes (i minpad) (write-char padchar stream)) ;; As of sbcl-0.6.12.34, we could end up here when someone tries to ;; print e.g. (FORMAT T "~F" "NOTFLOAT"), in which case ANSI says ;; we're supposed to soldier on bravely, and so we have to deal with ;; the unsupplied-MINCOL-and-COLINC case without blowing up. (when (and mincol colinc) (do ((chars (+ (length string) (max minpad 0)) (+ chars colinc))) ((>= chars mincol)) (dotimes (i colinc) (write-char padchar stream)))) (when padleft (write-string string stream))) (defun format-princ (stream arg colonp atsignp mincol colinc minpad padchar) (format-write-field stream (if (or arg (not colonp)) (princ-to-string arg) "()") mincol colinc minpad padchar atsignp)) (def-format-interpreter #\A (colonp atsignp params) (if params (interpret-bind-defaults ((mincol 0) (colinc 1) (minpad 0) (padchar #\space)) params (format-princ stream (next-arg) colonp atsignp mincol colinc minpad padchar)) (princ (if colonp (or (next-arg) "()") (next-arg)) stream))) (defun format-prin1 (stream arg colonp atsignp mincol colinc minpad padchar) (format-write-field stream (if (or arg (not colonp)) (prin1-to-string arg) "()") mincol colinc minpad padchar atsignp)) (def-format-interpreter #\S (colonp atsignp params) (cond (params (interpret-bind-defaults ((mincol 0) (colinc 1) (minpad 0) (padchar #\space)) params (format-prin1 stream (next-arg) colonp atsignp mincol colinc minpad padchar))) (colonp (let ((arg (next-arg))) (if arg (prin1 arg stream) (princ "()" stream)))) (t (prin1 (next-arg) stream)))) (def-format-interpreter #\C (colonp atsignp params) (interpret-bind-defaults () params (if colonp (format-print-named-character (next-arg) stream) (if atsignp (prin1 (next-arg) stream) (write-char (next-arg) stream))))) (defun format-print-named-character (char stream) (let* ((name (char-name char))) (cond ((and name ;;; Fixes ANSI-TEST FORMATTER.C.2A and FORMAT.C.2A (not (eq 160 (char-code char)))) (write-string (string-capitalize name) stream)) (t (write-char char stream))))) (def-format-interpreter #\W (colonp atsignp params) (interpret-bind-defaults () params (let ((*print-pretty* (or colonp *print-pretty*)) (*print-level* (unless atsignp *print-level*)) (*print-length* (unless atsignp *print-length*))) (sys::output-object (next-arg) stream)))) ;;;; format interpreters and support functions for integer output ;;; FORMAT-PRINT-NUMBER does most of the work for the numeric printing ;;; directives. The parameters are interpreted as defined for ~D. (defun format-print-integer (stream number print-commas-p print-sign-p radix mincol padchar commachar commainterval) (let ((*print-base* radix) (*print-radix* nil)) (if (integerp number) (let* ((text (princ-to-string (abs number))) (commaed (if print-commas-p (format-add-commas text commachar commainterval) text)) (signed (cond ((minusp number) (concatenate 'string "-" commaed)) (print-sign-p (concatenate 'string "+" commaed)) (t commaed)))) ;; colinc = 1, minpad = 0, padleft = t (format-write-field stream signed mincol 1 0 padchar t)) (princ number stream)))) (defun format-add-commas (string commachar commainterval) (let ((length (length string))) (multiple-value-bind (commas extra) (truncate (1- length) commainterval) (let ((new-string (make-string (+ length commas))) (first-comma (1+ extra))) (replace new-string string :end1 first-comma :end2 first-comma) (do ((src first-comma (+ src commainterval)) (dst first-comma (+ dst commainterval 1))) ((= src length)) (setf (schar new-string dst) commachar) (replace new-string string :start1 (1+ dst) :start2 src :end2 (+ src commainterval))) new-string)))) ;;; FIXME: This is only needed in this file, could be defined with ;;; SB!XC:DEFMACRO inside EVAL-WHEN (defmacro interpret-format-integer (base) `(if (or colonp atsignp params) (interpret-bind-defaults ((mincol 0) (padchar #\space) (commachar #\,) (commainterval 3)) params (format-print-integer stream (next-arg) colonp atsignp ,base mincol padchar commachar commainterval)) (write (next-arg) :stream stream :base ,base :radix nil :escape nil))) (def-format-interpreter #\D (colonp atsignp params) (interpret-format-integer 10)) (def-format-interpreter #\B (colonp atsignp params) (interpret-format-integer 2)) (def-format-interpreter #\O (colonp atsignp params) (interpret-format-integer 8)) (def-format-interpreter #\X (colonp atsignp params) (interpret-format-integer 16)) (def-format-interpreter #\R (colonp atsignp params) (interpret-bind-defaults ((base nil) (mincol 0) (padchar #\space) (commachar #\,) (commainterval 3)) params (let ((arg (next-arg))) (if base (format-print-integer stream arg colonp atsignp base mincol padchar commachar commainterval) (if atsignp (if colonp (format-print-old-roman stream arg) (format-print-roman stream arg)) (if colonp (format-print-ordinal stream arg) (format-print-cardinal stream arg))))))) (defparameter *cardinal-ones* #(nil "one" "two" "three" "four" "five" "six" "seven" "eight" "nine")) (defparameter *cardinal-tens* #(nil nil "twenty" "thirty" "forty" "fifty" "sixty" "seventy" "eighty" "ninety")) (defparameter *cardinal-teens* #("ten" "eleven" "twelve" "thirteen" "fourteen" ;;; RAD "fifteen" "sixteen" "seventeen" "eighteen" "nineteen")) (defparameter *cardinal-periods* #("" " thousand" " million" " billion" " trillion" " quadrillion" " quintillion" " sextillion" " septillion" " octillion" " nonillion" " decillion" " undecillion" " duodecillion" " tredecillion" " quattuordecillion" " quindecillion" " sexdecillion" " septendecillion" " octodecillion" " novemdecillion" " vigintillion")) (defparameter *ordinal-ones* #(nil "first" "second" "third" "fourth" "fifth" "sixth" "seventh" "eighth" "ninth")) (defparameter *ordinal-tens* #(nil "tenth" "twentieth" "thirtieth" "fortieth" "fiftieth" "sixtieth" "seventieth" "eightieth" "ninetieth")) (defun format-print-small-cardinal (stream n) (multiple-value-bind (hundreds rem) (truncate n 100) (when (plusp hundreds) (write-string (svref *cardinal-ones* hundreds) stream) (write-string " hundred" stream) (when (plusp rem) (write-char #\space stream))) (when (plusp rem) (multiple-value-bind (tens ones) (truncate rem 10) (cond ((< 1 tens) (write-string (svref *cardinal-tens* tens) stream) (when (plusp ones) (write-char #\- stream) (write-string (svref *cardinal-ones* ones) stream))) ((= tens 1) (write-string (svref *cardinal-teens* ones) stream)) ((plusp ones) (write-string (svref *cardinal-ones* ones) stream))))))) (defun format-print-cardinal (stream n) (cond ((minusp n) (write-string "negative " stream) (format-print-cardinal-aux stream (- n) 0 n)) ((zerop n) (write-string "zero" stream)) (t (format-print-cardinal-aux stream n 0 n)))) (defun format-print-cardinal-aux (stream n period err) (multiple-value-bind (beyond here) (truncate n 1000) (unless (<= period 20) (error "number too large to print in English: ~:D" err)) (unless (zerop beyond) (format-print-cardinal-aux stream beyond (1+ period) err)) (unless (zerop here) (unless (zerop beyond) (write-char #\space stream)) (format-print-small-cardinal stream here) (write-string (svref *cardinal-periods* period) stream)))) (defun format-print-ordinal (stream n) (when (minusp n) (write-string "negative " stream)) (let ((number (abs n))) (multiple-value-bind (top bot) (truncate number 100) (unless (zerop top) (format-print-cardinal stream (- number bot))) (when (and (plusp top) (plusp bot)) (write-char #\space stream)) (multiple-value-bind (tens ones) (truncate bot 10) (cond ((= bot 12) (write-string "twelfth" stream)) ((= tens 1) (write-string (svref *cardinal-teens* ones) stream);;;RAD (write-string "th" stream)) ((and (zerop tens) (plusp ones)) (write-string (svref *ordinal-ones* ones) stream)) ((and (zerop ones)(plusp tens)) (write-string (svref *ordinal-tens* tens) stream)) ((plusp bot) (write-string (svref *cardinal-tens* tens) stream) (write-char #\- stream) (write-string (svref *ordinal-ones* ones) stream)) ((plusp number) (write-string "th" stream)) (t (write-string "zeroth" stream))))))) ;;; Print Roman numerals (defun format-print-old-roman (stream n) (unless (< 0 n 5000) (error "Number too large to print in old Roman numerals: ~:D" n)) (do ((char-list '(#\D #\C #\L #\X #\V #\I) (cdr char-list)) (val-list '(500 100 50 10 5 1) (cdr val-list)) (cur-char #\M (car char-list)) (cur-val 1000 (car val-list)) (start n (do ((i start (progn (write-char cur-char stream) (- i cur-val)))) ((< i cur-val) i)))) ((zerop start)))) (defun format-print-roman (stream n) (unless (< 0 n 4000) (error "Number too large to print in Roman numerals: ~:D" n)) (do ((char-list '(#\D #\C #\L #\X #\V #\I) (cdr char-list)) (val-list '(500 100 50 10 5 1) (cdr val-list)) (sub-chars '(#\C #\X #\X #\I #\I) (cdr sub-chars)) (sub-val '(100 10 10 1 1 0) (cdr sub-val)) (cur-char #\M (car char-list)) (cur-val 1000 (car val-list)) (cur-sub-char #\C (car sub-chars)) (cur-sub-val 100 (car sub-val)) (start n (do ((i start (progn (write-char cur-char stream) (- i cur-val)))) ((< i cur-val) (cond ((<= (- cur-val cur-sub-val) i) (write-char cur-sub-char stream) (write-char cur-char stream) (- i (- cur-val cur-sub-val))) (t i)))))) ((zerop start)))) ;;;; plural (def-format-interpreter #\P (colonp atsignp params) (interpret-bind-defaults () params (let ((arg (if colonp (if (eq orig-args args) (error 'format-error :complaint "no previous argument") (do ((arg-ptr orig-args (cdr arg-ptr))) ((eq (cdr arg-ptr) args) (car arg-ptr)))) (next-arg)))) (if atsignp (write-string (if (eql arg 1) "y" "ies") stream) (unless (eql arg 1) (write-char #\s stream)))))) ;;;; format interpreters and support functions for floating point output (defun decimal-string (n) (write-to-string n :base 10 :radix nil :escape nil)) (def-format-interpreter #\F (colonp atsignp params) (when colonp (error 'format-error :complaint "cannot specify the colon modifier with this directive")) (interpret-bind-defaults ((w nil) (d nil) (k nil) (ovf nil) (pad #\space)) params (format-fixed stream (next-arg) w d k ovf pad atsignp))) (defun format-fixed (stream number w d k ovf pad atsign) (if (numberp number) (if (floatp number) (format-fixed-aux stream number w d k ovf pad atsign) (if (rationalp number) (format-fixed-aux stream (coerce number 'single-float) w d k ovf pad atsign) (format-write-field stream (decimal-string number) w 1 0 #\space t))) (format-princ stream number nil nil w 1 0 pad))) ;;; We return true if we overflowed, so that ~G can output the overflow char ;;; instead of spaces. (defun format-fixed-aux (stream number w d k ovf pad atsign) (cond ((and (floatp number) (or (sys:float-infinity-p number) (sys:float-nan-p number))) (prin1 number stream) nil) (t (let ((spaceleft w)) (when (and w (or atsign (minusp (float-sign number)))) (decf spaceleft)) (multiple-value-bind (str len lpoint tpoint) (sys::flonum-to-string (abs number) spaceleft d k) ;;if caller specifically requested no fraction digits, suppress the ;;optional trailing zero (when (and d (zerop d)) (setf tpoint nil)) (when w (decf spaceleft len) ;;optional leading zero (when lpoint (if (or (> spaceleft 0) tpoint) ;force at least one digit (decf spaceleft) (setq lpoint nil))) ;;optional trailing zero (when tpoint (if (> spaceleft 0) (decf spaceleft) (setq tpoint nil)))) (cond ((and w (< spaceleft 0) ovf) ;;field width overflow (dotimes (i w) (write-char ovf stream)) t) (t (when w (dotimes (i spaceleft) (write-char pad stream))) (cond ((minusp (float-sign number)) (write-char #\- stream)) (atsign (write-char #\+ stream))) (when lpoint (write-char #\0 stream)) (write-string str stream) (when tpoint (write-char #\0 stream)) nil))))))) (def-format-interpreter #\E (colonp atsignp params) (when colonp (error 'format-error :complaint "cannot specify the colon modifier with this directive")) (interpret-bind-defaults ((w nil) (d nil) (e nil) (k 1) (ovf nil) (pad #\space) (mark nil)) params (format-exponential stream (next-arg) w d e k ovf pad mark atsignp))) (defun format-exponential (stream number w d e k ovf pad marker atsign) (if (numberp number) (if (floatp number) (format-exp-aux stream number w d e k ovf pad marker atsign) (if (rationalp number) (format-exp-aux stream (coerce number 'single-float) w d e k ovf pad marker atsign) (format-write-field stream (decimal-string number) w 1 0 #\space t))) (format-princ stream number nil nil w 1 0 pad))) (defun format-exponent-marker (number) (if (typep number *read-default-float-format*) #\e (typecase number (single-float #\f) (double-float #\d) (short-float #\s) (long-float #\l)))) ;;; Here we prevent the scale factor from shifting all significance out of ;;; a number to the right. We allow insignificant zeroes to be shifted in ;;; to the left right, athough it is an error to specify k and d such that this ;;; occurs. Perhaps we should detect both these condtions and flag them as ;;; errors. As for now, we let the user get away with it, and merely guarantee ;;; that at least one significant digit will appear. ;;; Raymond Toy writes: The Hyperspec seems to say that the exponent ;;; marker is always printed. Make it so. Also, the original version ;;; causes errors when printing infinities or NaN's. The Hyperspec is ;;; silent here, so let's just print out infinities and NaN's instead ;;; of causing an error. (defun format-exp-aux (stream number w d e k ovf pad marker atsign) (if (and (floatp number) (or (sys::float-infinity-p number) (sys::float-nan-p number))) (prin1 number stream) (multiple-value-bind (num expt) (sys::scale-exponent (abs number)) (let* ((expt (- expt k)) (estr (decimal-string (abs expt))) (elen (if e (max (length estr) e) (length estr))) (fdig (if d (if (plusp k) (1+ (- d k)) d) nil)) (fmin (if (minusp k) (- 1 k) nil)) (spaceleft (if w (- w 2 elen (if (or atsign (minusp number)) 1 0)) nil))) (if (and w ovf e (> elen e)) ;exponent overflow (dotimes (i w) (write-char ovf stream)) (multiple-value-bind (fstr flen lpoint) (sys::flonum-to-string num spaceleft fdig k fmin) (when w (decf spaceleft flen) (when lpoint (if (> spaceleft 0) (decf spaceleft) (setq lpoint nil)))) (cond ((and w (< spaceleft 0) ovf) ;;significand overflow (dotimes (i w) (write-char ovf stream))) (t (when w (dotimes (i spaceleft) (write-char pad stream))) (if (minusp number) (write-char #\- stream) (if atsign (write-char #\+ stream))) (when lpoint (write-char #\0 stream)) (write-string fstr stream) (write-char (if marker marker (format-exponent-marker number)) stream) (write-char (if (minusp expt) #\- #\+) stream) (when e ;;zero-fill before exponent if necessary (dotimes (i (- e (length estr))) (write-char #\0 stream))) (write-string estr stream))))))))) (def-format-interpreter #\G (colonp atsignp params) (when colonp (error 'format-error :complaint "cannot specify the colon modifier with this directive")) (interpret-bind-defaults ((w nil) (d nil) (e nil) (k nil) (ovf nil) (pad #\space) (mark nil)) params (format-general stream (next-arg) w d e k ovf pad mark atsignp))) (defun format-general (stream number w d e k ovf pad marker atsign) (if (numberp number) (if (floatp number) (format-general-aux stream number w d e k ovf pad marker atsign) (if (rationalp number) (format-general-aux stream (coerce number 'single-float) w d e k ovf pad marker atsign) (format-write-field stream (decimal-string number) w 1 0 #\space t))) (format-princ stream number nil nil w 1 0 pad))) ;;; Raymond Toy writes: same change as for format-exp-aux (defun format-general-aux (stream number w d e k ovf pad marker atsign) (if (and (floatp number) (or (sys::float-infinity-p number) (sys::float-nan-p number))) (prin1 number stream) (multiple-value-bind (ignore n) (sys::scale-exponent (abs number)) (declare (ignore ignore)) ;; KLUDGE: Default d if omitted. The procedure is taken directly from ;; the definition given in the manual, and is not very efficient, since ;; we generate the digits twice. Future maintainers are encouraged to ;; improve on this. -- rtoy?? 1998?? (unless d (multiple-value-bind (str len) (sys::flonum-to-string (abs number)) (declare (ignore str)) (let ((q (if (= len 1) 1 (1- len)))) (setq d (max q (min n 7)))))) (let* ((ee (if e (+ e 2) 4)) (ww (if w (- w ee) nil)) (dd (- d n))) (cond ((<= 0 dd d) (let ((char (if (format-fixed-aux stream number ww dd nil ovf pad atsign) ovf #\space))) (dotimes (i ee) (write-char char stream)))) (t (format-exp-aux stream number w d e (or k 1) ovf pad marker atsign))))))) (def-format-interpreter #\$ (colonp atsignp params) (interpret-bind-defaults ((d 2) (n 1) (w 0) (pad #\space)) params (format-dollars stream (next-arg) d n w pad colonp atsignp))) (defun format-dollars (stream number d n w pad colon atsign) (when (rationalp number) ;; This coercion to SINGLE-FLOAT seems as though it gratuitously ;; loses precision (why not LONG-FLOAT?) but it's the default ;; behavior in the ANSI spec, so in some sense it's the right ;; thing, and at least the user shouldn't be surprised. (setq number (coerce number 'single-float))) (if (floatp number) (let* ((signstr (if (minusp number) "-" (if atsign "+" ""))) (signlen (length signstr))) (multiple-value-bind (str strlen ig2 ig3 pointplace) (sys::flonum-to-string (abs number) nil d nil) (declare (ignore ig2 ig3 strlen)) (when colon (write-string signstr stream)) (dotimes (i (- w signlen (max n pointplace) 1 d)) (write-char pad stream)) (unless colon (write-string signstr stream)) (dotimes (i (- n pointplace)) (write-char #\0 stream)) (write-string str stream))) (format-write-field stream (decimal-string number) w 1 0 #\space t))) ;;;; FORMAT interpreters and support functions for line/page breaks etc. (def-format-interpreter #\% (colonp atsignp params) (when (or colonp atsignp) (error 'format-error :complaint "cannot specify either colon or atsign for this directive")) (interpret-bind-defaults ((count 1)) params (dotimes (i count) (terpri stream)))) (def-format-interpreter #\& (colonp atsignp params) (when (or colonp atsignp) (error 'format-error :complaint "cannot specify either colon or atsign for this directive")) (interpret-bind-defaults ((count 1)) params (fresh-line stream) (dotimes (i (1- count)) (terpri stream)))) (def-format-interpreter #\| (colonp atsignp params) (when (or colonp atsignp) (error 'format-error :complaint "cannot specify either colon or atsign for this directive")) (interpret-bind-defaults ((count 1)) params (dotimes (i count) (write-char (code-char sys::form-feed-char-code) stream)))) (def-format-interpreter #\~ (colonp atsignp params) (when (or colonp atsignp) (error 'format-error :complaint "cannot specify either colon or atsign for this directive")) (interpret-bind-defaults ((count 1)) params (dotimes (i count) (write-char #\~ stream)))) (def-complex-format-interpreter #\newline (colonp atsignp params directives) (when (and colonp atsignp) (error 'format-error :complaint "cannot specify both colon and atsign for this directive")) (interpret-bind-defaults () params (when atsignp (write-char #\newline stream))) (if (and (not colonp) directives (simple-string-p (car directives))) (cons (string-left-trim *format-whitespace-chars* (car directives)) (cdr directives)) directives)) ;;;; format interpreters and support functions for tabs and simple pretty ;;;; printing (def-format-interpreter #\T (colonp atsignp params) (if colonp (interpret-bind-defaults ((n 1) (m 1)) params (pprint-tab (if atsignp :section-relative :section) n m stream)) (if atsignp (interpret-bind-defaults ((colrel 1) (colinc 1)) params (format-relative-tab stream colrel colinc)) (interpret-bind-defaults ((colnum 1) (colinc 1)) params (format-absolute-tab stream colnum colinc))))) (defun output-spaces (stream n) (let ((spaces #.(make-string 100 :initial-element #\space))) (loop (when (< n (length spaces)) (return)) (write-string spaces stream) (decf n (length spaces))) (write-string spaces stream :end n))) (defun format-relative-tab (stream colrel colinc) (if (xp::xp-structure-p stream) (pprint-tab :line-relative colrel colinc stream) (let* ((cur (charpos stream)) (spaces (if (and cur (plusp colinc)) (- (* (ceiling (+ cur colrel) colinc) colinc) cur) colrel))) (output-spaces stream spaces)))) (defun format-absolute-tab (stream colnum colinc) (if (xp::xp-structure-p stream) (pprint-tab :line colnum colinc stream) (let ((cur (charpos stream))) (cond ((null cur) (write-string " " stream)) ((< cur colnum) (output-spaces stream (- colnum cur))) (t (unless (zerop colinc) (output-spaces stream (- colinc (rem (- cur colnum) colinc))))))))) (def-format-interpreter #\_ (colonp atsignp params) (interpret-bind-defaults () params (pprint-newline (if colonp (if atsignp :mandatory :fill) (if atsignp :miser :linear)) stream))) (def-format-interpreter #\I (colonp atsignp params) (when atsignp (error 'format-error :complaint "cannot specify the at-sign modifier")) (interpret-bind-defaults ((n 0)) params (pprint-indent (if colonp :current :block) n stream))) ;;;; format interpreter for ~* (def-format-interpreter #\* (colonp atsignp params) (if atsignp (if colonp (error 'format-error :complaint "cannot specify both colon and at-sign") (interpret-bind-defaults ((posn 0)) params (if (<= 0 posn (length orig-args)) (setf args (nthcdr posn orig-args)) (error 'format-error :complaint "Index ~W is out of bounds. (It should ~ have been between 0 and ~W.)" :args (list posn (length orig-args)))))) (if colonp (interpret-bind-defaults ((n 1)) params (do ((cur-posn 0 (1+ cur-posn)) (arg-ptr orig-args (cdr arg-ptr))) ((eq arg-ptr args) (let ((new-posn (- cur-posn n))) (if (<= 0 new-posn (length orig-args)) (setf args (nthcdr new-posn orig-args)) (error 'format-error :complaint "Index ~W is out of bounds. (It should have been between 0 and ~W.)" :args (list new-posn (length orig-args)))))))) (interpret-bind-defaults ((n 1)) params (dotimes (i n) (next-arg)))))) ;;;; format interpreter for indirection (def-format-interpreter #\? (colonp atsignp params string end) (when colonp (error 'format-error :complaint "cannot specify the colon modifier")) (interpret-bind-defaults () params (handler-bind ((format-error (lambda (condition) (error 'format-error :complaint "~A~%while processing indirect format string:" :args (list condition) :print-banner nil :control-string string :offset (1- end))))) (if atsignp (setf args (%format stream (next-arg) orig-args args)) (%format stream (next-arg) (next-arg)))))) ;;;; format interpreters for capitalization (def-complex-format-interpreter #\( (colonp atsignp params directives) (let ((close (find-directive directives #\) nil))) (unless close (error 'format-error :complaint "no corresponding close paren")) (interpret-bind-defaults () params (let* ((posn (position close directives)) (before (subseq directives 0 posn)) (after (nthcdr (1+ posn) directives)) (stream (sys::make-case-frob-stream (if (typep stream 'xp::xp-structure) (xp::base-stream stream) stream) (if colonp (if atsignp :upcase :capitalize) (if atsignp :capitalize-first :downcase))))) (setf args (interpret-directive-list stream before orig-args args)) after)))) (def-complex-format-interpreter #\) () (error 'format-error :complaint "no corresponding open paren")) ;;;; format interpreters and support functions for conditionalization (def-complex-format-interpreter #\[ (colonp atsignp params directives) (multiple-value-bind (sublists last-semi-with-colon-p remaining) (parse-conditional-directive directives) (setf args (if atsignp (if colonp (error 'format-error :complaint "cannot specify both the colon and at-sign modifiers") (if (cdr sublists) (error 'format-error :complaint "can only specify one section") (interpret-bind-defaults () params (let ((prev-args args) (arg (next-arg))) (if arg (interpret-directive-list stream (car sublists) orig-args prev-args) args))))) (if colonp (if (= (length sublists) 2) (interpret-bind-defaults () params (if (next-arg) (interpret-directive-list stream (car sublists) orig-args args) (interpret-directive-list stream (cadr sublists) orig-args args))) (error 'format-error :complaint "must specify exactly two sections")) (interpret-bind-defaults ((index (next-arg))) params (let* ((default (and last-semi-with-colon-p (pop sublists))) (last (1- (length sublists))) (sublist (if (<= 0 index last) (nth (- last index) sublists) default))) (interpret-directive-list stream sublist orig-args args)))))) remaining)) (def-complex-format-interpreter #\; () (error 'format-error :complaint "~~; not contained within either ~~[...~~] or ~~<...~~>")) (def-complex-format-interpreter #\] () (error 'format-error :complaint "no corresponding open bracket")) ;;;; format interpreter for up-and-out (defvar *outside-args*) (def-format-interpreter #\^ (colonp atsignp params) (when atsignp (error 'format-error :complaint "cannot specify the at-sign modifier")) (when (and colonp (not *up-up-and-out-allowed*)) (error 'format-error :complaint "attempt to use ~~:^ outside a ~~:{...~~} construct")) (when (interpret-bind-defaults ((arg1 nil) (arg2 nil) (arg3 nil)) params (cond (arg3 (<= arg1 arg2 arg3)) (arg2 (eql arg1 arg2)) (arg1 (eql arg1 0)) (t (if colonp (null *outside-args*) (null args))))) (throw (if colonp 'up-up-and-out 'up-and-out) args))) ;;;; format interpreters for iteration (def-complex-format-interpreter #\{ (colonp atsignp params string end directives) (let ((close (find-directive directives #\} nil))) (unless close (error 'format-error :complaint "no corresponding close brace")) (interpret-bind-defaults ((max-count nil)) params (let* ((closed-with-colon (format-directive-colonp close)) (posn (position close directives)) (insides (if (zerop posn) (next-arg) (subseq directives 0 posn))) (*up-up-and-out-allowed* colonp)) (labels ((do-guts (orig-args args) (if (zerop posn) (handler-bind ((format-error (lambda (condition) (error 'format-error :complaint "~A~%while processing indirect format string:" :args (list condition) :print-banner nil :control-string string :offset (1- end))))) (%format stream insides orig-args args)) (interpret-directive-list stream insides orig-args args))) (bind-args (orig-args args) (if colonp (let* ((arg (next-arg)) (*logical-block-popper* nil) (*outside-args* args)) (catch 'up-and-out (do-guts arg arg)) args) (do-guts orig-args args))) (do-loop (orig-args args) (catch (if colonp 'up-up-and-out 'up-and-out) (loop (when (and (not closed-with-colon) (null args)) (return)) (when (and max-count (minusp (decf max-count))) (return)) (setf args (bind-args orig-args args)) (when (and closed-with-colon (null args)) (return))) args))) (if atsignp (setf args (do-loop orig-args args)) (let ((arg (next-arg)) (*logical-block-popper* nil)) (do-loop arg arg))) (nthcdr (1+ posn) directives)))))) (def-complex-format-interpreter #\} () (error 'format-error :complaint "no corresponding open brace")) ;;;; format interpreters and support functions for justification (def-complex-format-interpreter #\< (colonp atsignp params string end directives) (multiple-value-bind (segments first-semi close remaining) (parse-format-justification directives) (setf args (if (format-directive-colonp close) (multiple-value-bind (prefix per-line-p insides suffix) (parse-format-logical-block segments colonp first-semi close params string end) (interpret-format-logical-block stream orig-args args prefix per-line-p insides suffix atsignp)) (let ((count (reduce #'+ (mapcar (lambda (x) (count-if #'illegal-inside-justification-p x)) segments)))) (when (> count 0) ;; ANSI specifies that "an error is signalled" in this ;; situation. (error 'format-error :complaint "~D illegal directive~:P found inside justification block" :args (list count))) (interpret-format-justification stream orig-args args segments colonp atsignp first-semi params)))) remaining)) (defun interpret-format-justification (stream orig-args args segments colonp atsignp first-semi params) (interpret-bind-defaults ((mincol 0) (colinc 1) (minpad 0) (padchar #\space)) params (let ((newline-string nil) (strings nil) (extra-space 0) (line-len 0)) (setf args (catch 'up-and-out (when (and first-semi (format-directive-colonp first-semi)) (interpret-bind-defaults ((extra 0) (len (or #-abcl(sb!impl::line-length stream) 72))) (format-directive-params first-semi) (setf newline-string (with-output-to-string (stream) (setf args (interpret-directive-list stream (pop segments) orig-args args)))) (setf extra-space extra) (setf line-len len))) (dolist (segment segments) (push (with-output-to-string (stream) (setf args (interpret-directive-list stream segment orig-args args))) strings)) args)) (format-justification stream newline-string extra-space line-len strings colonp atsignp mincol colinc minpad padchar))) args) (defun format-justification (stream newline-prefix extra-space line-len strings pad-left pad-right mincol colinc minpad padchar) (setf strings (reverse strings)) (let* ((num-gaps (+ (1- (length strings)) (if pad-left 1 0) (if pad-right 1 0))) (chars (+ (* num-gaps minpad) (loop for string in strings summing (length string)))) (length (if (> chars mincol) (+ mincol (* (ceiling (- chars mincol) colinc) colinc)) mincol)) (padding (+ (- length chars) (* num-gaps minpad)))) (when (and newline-prefix (> (+ (or (charpos stream) 0) length extra-space) line-len)) (write-string newline-prefix stream)) (flet ((do-padding () (let ((pad-len (if (zerop num-gaps) padding (truncate padding num-gaps)))) (decf padding pad-len) (decf num-gaps) (dotimes (i pad-len) (write-char padchar stream))))) (when (or pad-left (and (not pad-right) (null (cdr strings)))) (do-padding)) (when strings (write-string (car strings) stream) (dolist (string (cdr strings)) (do-padding) (write-string string stream))) (when pad-right (do-padding))))) (defun interpret-format-logical-block (stream orig-args args prefix per-line-p insides suffix atsignp) (let ((arg (if atsignp args (next-arg)))) (if per-line-p (pprint-logical-block (stream arg :per-line-prefix prefix :suffix suffix) (let ((*logical-block-popper* (lambda () (pprint-pop)))) (catch 'up-and-out (interpret-directive-list stream insides (if atsignp orig-args arg) arg)))) (pprint-logical-block (stream arg :prefix prefix :suffix suffix) (let ((*logical-block-popper* (lambda () (pprint-pop)))) (catch 'up-and-out (interpret-directive-list stream insides (if atsignp orig-args arg) arg)))))) (if atsignp nil args)) ;;;; format interpreter and support functions for user-defined method (def-format-interpreter #\/ (string start end colonp atsignp params) (let ((symbol (extract-user-fun-name string start end))) (collect ((args)) (dolist (param-and-offset params) (let ((param (cdr param-and-offset))) (case param (:arg (args (next-arg))) (:remaining (args (length args))) (t (args param))))) (apply (fdefinition symbol) stream (next-arg) colonp atsignp (args))))) (setf (symbol-function 'sys::simple-format) #'format) (provide 'format) abcl-src-1.9.0/src/org/armedbear/lisp/ftruncate.java0100644 0000000 0000000 00000014315 14202767264 021061 0ustar000000000 0000000 /* * ftruncate.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### ftruncate number &optional divisor => quotient, remainder // (defun ftruncate (number &optional (divisor 1)) // (multiple-value-bind (tru rem) (truncate number divisor) // (values (float tru) rem))) // "FFLOOR, FCEILING, FTRUNCATE, and FROUND handle arguments of different types // in the following way: If number is a float, and divisor is not a float of // longer format, then the first result is a float of the same type as number. // Otherwise, the first result is of the type determined by contagion rules." public final class ftruncate extends Primitive { private ftruncate() { super("ftruncate", "number &optional divisor"); } @Override public LispObject execute(LispObject arg) { final LispThread thread = LispThread.currentThread(); if (arg.zerop()) { LispObject q = arg; LispObject r; if (arg instanceof DoubleFloat) r = DoubleFloat.ZERO; else r = SingleFloat.ZERO; return thread.setValues(q, r); } if (arg instanceof DoubleFloat) { double d = ((DoubleFloat)arg).value; if (Double.isInfinite(d) || Double.isNaN(d)) return thread.setValues(arg, new DoubleFloat(Double.NaN)); } else if (arg instanceof SingleFloat) { float f = ((SingleFloat)arg).value; if (Float.isInfinite(f) || Float.isNaN(f)) return thread.setValues(arg, new SingleFloat(Float.NaN)); } LispObject q = arg.truncate(Fixnum.ONE); // an integer if (arg instanceof DoubleFloat) { if (q.zerop()) { if (arg.minusp()) q = new DoubleFloat(-0.0); else q = new DoubleFloat(0.0); } else if (q instanceof Fixnum) q = new DoubleFloat(((Fixnum)q).value); else q = new DoubleFloat(((Bignum)q).doubleValue()); } else { if (q.zerop()) { if (arg.minusp()) q = new SingleFloat(-0.0f); else q = new SingleFloat(0.0f); } else if (q instanceof Fixnum) q = new SingleFloat(((Fixnum)q).value); else q = new SingleFloat(((Bignum)q).floatValue()); } thread._values[0] = q; return q; } @Override public LispObject execute(LispObject first, LispObject second) { final LispThread thread = LispThread.currentThread(); if (first.zerop()) { LispObject q = first; LispObject r; if (first instanceof DoubleFloat) r = DoubleFloat.ZERO; else r = SingleFloat.ZERO; return thread.setValues(q, r); } if (first instanceof DoubleFloat) { double d1 = ((DoubleFloat)first).value; if (Double.isInfinite(d1) || Double.isNaN(d1)) return thread.setValues(first, new DoubleFloat(Double.NaN)); } else if (first instanceof SingleFloat) { float f1 = ((SingleFloat)first).value; if (Float.isInfinite(f1) || Float.isNaN(f1)) return thread.setValues(first, new SingleFloat(Float.NaN)); } LispObject q = first.truncate(second); // an integer if (first instanceof DoubleFloat || second instanceof DoubleFloat) { if (q.zerop()) { if (first.minusp()) { if (second.minusp()) q = new DoubleFloat(0.0); else q = new DoubleFloat(-0.0); } else if (second.minusp()) q = new DoubleFloat(-0.0); else q = new DoubleFloat(0.0); } else if (q instanceof Fixnum) q = new DoubleFloat(((Fixnum)q).value); else q = new DoubleFloat(((Bignum)q).doubleValue()); } else { if (q.zerop()) { if (first.minusp()) { if (second.minusp()) q = new SingleFloat(0.0f); else q = new SingleFloat(-0.0f); } else if (second.minusp()) q = new SingleFloat(-0.0f); else q = new SingleFloat(0.0f); } else if (q instanceof Fixnum) q = new SingleFloat(((Fixnum)q).value); else q = new SingleFloat(((Bignum)q).floatValue()); } thread._values[0] = q; return q; } private static final Primitive FTRUNCATE = new ftruncate(); } abcl-src-1.9.0/src/org/armedbear/lisp/function_info.java0100644 0000000 0000000 00000011614 14202767264 021725 0ustar000000000 0000000 /* * function_info.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.util.Map; import java.util.Collections; import java.util.WeakHashMap; import static org.armedbear.lisp.Lisp.*; public final class function_info { // ### TODO: Replace by a concurrent hashmap, with weak keys, ofcourse. final static Map symbolToFunctionMap = Collections.synchronizedMap(new WeakHashMap()); // ### function-info name private static final Primitive FUNCTION_INFO = new Primitive("function-info", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject arg) { LispObject info = symbolToFunctionMap.get(arg); return info != null ? info : NIL; } }; // ### %set-function-info name info private static final Primitive _SET_FUNCTION_INFO = new Primitive("%set-function-info", PACKAGE_SYS, false) { @Override public LispObject execute(LispObject name, LispObject info) { if (info == NIL) symbolToFunctionMap.remove(name); else symbolToFunctionMap.put(name, info); return info; } }; // ### get-function-info-value name indicator => value private static final Primitive GET_FUNCTION_INFO_VALUE = new Primitive("get-function-info-value", PACKAGE_SYS, true, "name indicator") { @Override public LispObject execute(LispObject name, LispObject indicator) { // info is an alist LispObject info = symbolToFunctionMap.get(name); if (info != null) { while (info != NIL) { LispObject cons = info.car(); if (cons instanceof Cons) { if (cons.car().eql(indicator)) { // Found it. return LispThread.currentThread().setValues(cons.cdr(), T); } } else if (cons != NIL) type_error(cons, Symbol.LIST); info = info.cdr(); } } return LispThread.currentThread().setValues(NIL, NIL); } }; // ### set-function-info-value name indicator value => value private static final Primitive SET_FUNCTION_INFO_VALUE = new Primitive("set-function-info-value", PACKAGE_SYS, true, "name indicator value") { @Override public LispObject execute(LispObject name, LispObject indicator, LispObject value) { // info is an alist LispObject info = symbolToFunctionMap.get(name); if (info == null) info = NIL; LispObject alist = info; while (alist != NIL) { LispObject cons = alist.car(); if (cons instanceof Cons) { if (cons.car().eql(indicator)) { // Found it. cons.setCdr(value); return value; } } else if (cons != NIL) type_error(cons, Symbol.LIST); alist = alist.cdr(); } // Not found. symbolToFunctionMap.put(name, info.push(new Cons(indicator, value))); return value; } }; } abcl-src-1.9.0/src/org/armedbear/lisp/gc.java0100644 0000000 0000000 00000004570 14202767264 017461 0ustar000000000 0000000 /* * gc.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### gc public final class gc extends Primitive { private gc() { super("gc", PACKAGE_EXT); } @Override public LispObject execute() { Runtime runtime = Runtime.getRuntime(); long free = 0; long maxFree = 0; while (true) { try { runtime.gc(); Thread.sleep(100); runtime.runFinalization(); Thread.sleep(100); runtime.gc(); Thread.sleep(100); } catch (InterruptedException e) {} free = runtime.freeMemory(); if (free > maxFree) maxFree = free; else break; } return number(free); } private static final Primitive GC = new gc(); } abcl-src-1.9.0/src/org/armedbear/lisp/gentemp.lisp0100644 0000000 0000000 00000003753 14223403213 020537 0ustar000000000 0000000 ;;; gentemp.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package #:system) (defvar *gentemp-counter* 0) (defun gentemp (&optional (prefix "T") (package *package*)) (require-type prefix 'string) (require-type package '(or package string symbol character)) (loop (let ((name (format nil "~A~D" prefix (incf *gentemp-counter*)))) (multiple-value-bind (symbol exists-p) (find-symbol name package) (unless exists-p (return (values (intern name package)))))))) abcl-src-1.9.0/src/org/armedbear/lisp/get-pid.lisp0100644 0000000 0000000 00000003166 14223403213 020427 0ustar000000000 0000000 (in-package :extensions) (export '(get-pid) :extensions) (defun get-pid () "Get the process identifier of this lisp process. Used to be in SLIME but generally useful, so now back in ABCL proper." (handler-case (let* ((runtime (java::jstatic "getRuntime" "java.lang.Runtime")) (command (java::jnew-array-from-array "java.lang.String" #("sh" "-c" "echo $PPID"))) (runtime-exec-jmethod ;; Complicated because java.lang.Runtime.exec() is ;; overloaded on a non-primitive type (array of ;; java.lang.String), so we have to use the actual ;; parameter instance to get java.lang.Class (java::jmethod "java.lang.Runtime" "exec" (java::jcall (java::jmethod "java.lang.Object" "getClass") command))) (process (java::jcall runtime-exec-jmethod runtime command)) (output (java::jcall (java::jmethod "java.lang.Process" "getInputStream") process))) (java::jcall (java::jmethod "java.lang.Process" "waitFor") process) (loop :with b :do (setq b (java::jcall (java::jmethod "java.io.InputStream" "read") output)) :until (member b '(-1 #x0a)) ; Either EOF or LF :collecting (code-char b) :into result :finally (return (parse-integer (coerce result 'string))))) (t () 0))) abcl-src-1.9.0/src/org/armedbear/lisp/get_properties.java0100644 0000000 0000000 00000005271 14202767264 022122 0ustar000000000 0000000 /* * get_properties.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### get-properties public final class get_properties extends Primitive { private get_properties() { super(Symbol.GET_PROPERTIES, "plist indicator-list"); } @Override public LispObject execute(LispObject first, LispObject second) { final LispThread thread = LispThread.currentThread(); LispObject plist = first; while (plist != NIL) { if (plist.cdr() instanceof Cons) { LispObject indicator = ((Cons)plist).car; LispObject indicators = second; while (indicators instanceof Cons) { if (indicator == ((Cons)indicators).car) return thread.setValues(indicator, plist.cadr(), plist); indicators = ((Cons)indicators).cdr; } if (indicators != NIL) return type_error(indicators, Symbol.LIST); plist = plist.cddr(); } else return type_error(plist.cdr(), Symbol.CONS); } return thread.setValues(NIL, NIL, NIL); } private static final Primitive GET_PROPERTIES = new get_properties(); } abcl-src-1.9.0/src/org/armedbear/lisp/gray-streams.lisp0100644 0000000 0000000 00000070335 14223403213 021516 0ustar000000000 0000000 ;;; gray-streams.lisp ;;; ;;; Copyright (C) 2004-2007 Peter Graves, Andras Simon ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from: ;;;; Gray Streams Implementation for Corman Lisp - Version 1.3 ;;;; ;;;; Copyright (C) 2000 Christopher Double. All Rights Reserved. ;;;; ;;;; License ;;;; ======= ;;;; This software is provided 'as-is', without any express or implied ;;;; warranty. In no event will the author be held liable for any damages ;;;; arising from the use of this software. ;;;; ;;;; Permission is granted to anyone to use this software for any purpose, ;;;; including commercial applications, and to alter it and redistribute ;;;; it freely, subject to the following restrictions: ;;;; ;;;; 1. The origin of this software must not be misrepresented; you must ;;;; not claim that you wrote the original software. If you use this ;;;; software in a product, an acknowledgment in the product documentation ;;;; would be appreciated but is not required. ;;;; ;;;; 2. Altered source versions must be plainly marked as such, and must ;;;; not be misrepresented as being the original software. ;;;; ;;;; 3. This notice may not be removed or altered from any source ;;;; distribution. ;;;; ;;;; Notes ;;;; ===== ;;;; ;;;; NB: The ABCL implementation has been extensively reworked since these ;;;; notes were included. Please see the ABCL revision history via ;;;; the interface at ;;;; ;;;; http://trac.common-lisp.net/armedbear/browser/trunk/abcl/src/org/armedbear/lisp/gray-streams.lisp ;;;; ;;;; for a more relevant history vis a vis the ABCL implementation. ;;;; ;;;; A simple implementation of Gray streams for Corman Lisp 1.42. ;;;; Gray streams are 'clos' based streams as described at: ;;;; ;;;; ftp://parcftp.xerox.com/pub/cl/cleanup/mail/stream-definition-by-user.mail ;;;; ;;;; 20110319 ;;;; The xerox.com ftp URI doesn't resolve. Instead see Kent Pitman's ;;;; archival copy at ;;;; ;;;; http://www.nhplace.com/kent/CL/Issues/stream-definition-by-user.html ;;;; ;;;; Some differences exist between this implementation and the ;;;; specification above. See notes below for details. ;;;; ;;;; More recent versions of this software may be available at: ;;;; http://www.double.co.nz/cl ;;;; ;;;; Comments, suggestions and bug reports to the author, ;;;; Christopher Double, at: chris@double.co.nz ;;;; ;;;; 03/03/2001 - 1.0 ;;;; Initial release. ;;;; ;;;; 20/08/2001 - 1.1 ;;;; Small modifications by Frederic Bastenaire (fba@free.fr) ;;;; (lines flagged by ;; # fb 1.01) ;;;; - Make it work with the READ function by ;;;; defining %read-char, %read-char-with-error ;;;; and input-character-stream-p ;;;; - Add nickname GS to package "GRAY-STREAMS" for ease of use ;;;; - added missing '*' to *old-write-byte* in gray-write-byte ;;;; ;;;; 03/01/2002 - 1.2 ;;;; Fixed bug with GRAY-WRITE-LINE and GRAY-WRITE-STRING ;;;; that appeared in Corman Lisp 2.0 due to changes to ;;;; WRITE-LINE and WRITE-STRING. ;;;; ;;;; 04/01/2002 - 1.3 ;;;; Added support for STREAM-READ-SEQUENCE and STREAM-WRITE-SEQUENCE. ;;;; Fixed STREAM-WRITE-STRING bug. ;;;; ;;;; Notes ;;;; ===== ;;;; ;;;; ;;;; Much of the implementation of the Gray streams below is from the ;;;; document referenced earlier. ;;;; (require "PPRINT") (defpackage "GRAY-STREAMS" (:use "COMMON-LISP") (:nicknames "GS") ;; # fb 1.01 (:export "FUNDAMENTAL-STREAM" "FUNDAMENTAL-OUTPUT-STREAM" "FUNDAMENTAL-INPUT-STREAM" "FUNDAMENTAL-CHARACTER-STREAM" "FUNDAMENTAL-BINARY-STREAM" "STREAM-READ-BYTE" "STREAM-WRITE-BYTE" "FUNDAMENTAL-CHARACTER-INPUT-STREAM" "STREAM-READ-CHAR" "STREAM-UNREAD-CHAR" "STREAM-READ-CHAR-NO-HANG" "STREAM-PEEK-CHAR" "STREAM-LISTEN" "STREAM-READ-LINE" "STREAM-CLEAR-INPUT" "FUNDAMENTAL-CHARACTER-OUTPUT-STREAM" "STREAM-WRITE-CHAR" "STREAM-LINE-COLUMN" "STREAM-START-LINE-P" "STREAM-WRITE-STRING" "STREAM-TERPRI" "STREAM-FRESH-LINE" "STREAM-FINISH-OUTPUT" "STREAM-FORCE-OUTPUT" "STREAM-CLEAR-OUTPUT" "STREAM-ADVANCE-TO-COLUMN" "STREAM-READ-SEQUENCE" "STREAM-WRITE-SEQUENCE" "STREAM-FILE-POSITION" "FUNDAMENTAL-BINARY-INPUT-STREAM" "FUNDAMENTAL-BINARY-OUTPUT-STREAM")) (in-package :gray-streams) (defvar *ansi-read-char* #'read-char) (defvar *ansi-peek-char* #'peek-char) (defvar *ansi-unread-char* #'unread-char) (defvar *ansi-listen* #'listen) (defvar *ansi-read-line* #'read-line) (defvar *ansi-read-char-no-hang* #'read-char-no-hang) (defvar *ansi-write-char* #'write-char) (defvar *ansi-fresh-line* #'fresh-line) (defvar *ansi-terpri* #'terpri) (defvar *ansi-write-string* #'write-string) (defvar *ansi-write-line* #'write-line) (defvar *sys-%force-output* #'sys::%force-output) (defvar *sys-%finish-output* #'sys::%finish-output) (defvar *sys-%clear-output* #'sys::%clear-output) (defvar *sys-%output-object* #'sys::%output-object) (defvar *ansi-clear-input* #'clear-input) (defvar *ansi-read-byte* #'read-byte) (defvar *ansi-write-byte* #'write-byte) (defvar *ansi-stream-element-type* #'cl::stream-element-type) (defvar *ansi-close* #'cl::close) (defvar *ansi-input-character-stream-p* #'(lambda (s) (and (input-stream-p s) (eql (stream-element-type s) 'character)))) (defvar *ansi-input-stream-p* #'cl::input-stream-p) (defvar *ansi-output-stream-p* #'cl::output-stream-p) (defvar *ansi-open-stream-p* #'cl::open-stream-p) (defvar *ansi-streamp* #'cl::streamp) (defvar *ansi-read-sequence* #'cl::read-sequence) (defvar *ansi-write-sequence* #'cl::write-sequence) (defvar *ansi-make-two-way-stream* #'cl:make-two-way-stream) (defvar *ansi-two-way-stream-input-stream* #'cl:two-way-stream-input-stream) (defvar *ansi-two-way-stream-output-stream* #'cl:two-way-stream-output-stream) (defvar *ansi-file-position* #'cl:file-position) (defun ansi-streamp (stream) (or (xp::xp-structure-p stream) (funcall *ansi-streamp* stream))) (defclass fundamental-stream (standard-object stream) ((open-p :initform t :accessor stream-open-p)) (:documentation "The base class of all Gray streams")) (defgeneric gray-close (stream &key abort)) (defgeneric gray-open-stream-p (stream)) (defgeneric gray-streamp (stream)) (defgeneric gray-input-stream-p (stream)) (defgeneric gray-input-character-stream-p (stream)) ;; # fb 1.01 (defgeneric gray-output-stream-p (stream)) (defgeneric gray-stream-element-type (stream)) (defmethod gray-close ((stream fundamental-stream) &key abort) (declare (ignore abort)) (setf (stream-open-p stream) nil) t) (defmethod gray-open-stream-p ((stream fundamental-stream)) (stream-open-p stream)) (defmethod gray-streamp ((s fundamental-stream)) s) (defclass fundamental-input-stream (fundamental-stream) ()) (defmethod gray-input-character-stream-p (s) ;; # fb 1.01 (and (gray-input-stream-p s) (eq (gray-stream-element-type s) 'character))) (defmethod gray-input-stream-p ((s fundamental-input-stream)) (declare (ignore s)) t) (defclass fundamental-output-stream (fundamental-stream) ()) (defmethod gray-input-stream-p ((s fundamental-output-stream)) (typep s 'fundamental-input-stream)) (defmethod gray-output-stream-p ((s fundamental-output-stream)) (declare (ignore s)) t) (defmethod gray-output-stream-p ((s fundamental-input-stream)) (typep s 'fundamental-output-stream)) (defclass fundamental-character-stream (fundamental-stream) ()) (defmethod gray-stream-element-type ((s fundamental-character-stream)) (declare (ignore s)) 'character) (defclass fundamental-binary-stream (fundamental-stream) ()) (defgeneric stream-read-byte (stream)) (defgeneric stream-write-byte (stream integer)) (defclass fundamental-character-input-stream (fundamental-input-stream fundamental-character-stream) ()) (defgeneric stream-read-char (stream)) (defgeneric stream-unread-char (stream character)) (defgeneric stream-read-char-no-hang (stream)) (defgeneric stream-peek-char (stream)) (defgeneric stream-listen (stream)) (defgeneric stream-read-line (stream)) (defgeneric stream-clear-input (stream)) (defmethod stream-peek-char ((stream fundamental-character-input-stream)) (let ((character (stream-read-char stream))) (unless (eq character :eof) (stream-unread-char stream character)) character)) (defmethod stream-listen ((stream fundamental-character-input-stream)) (let ((char (stream-read-char-no-hang stream))) (and (not (null char)) (not (eq char :eof)) (progn (stream-unread-char stream char) t)))) (defmethod stream-read-line ((stream fundamental-character-input-stream)) (let ((line (make-array 64 :element-type 'character :fill-pointer 0 :adjustable t))) (loop (let ((character (stream-read-char stream))) (if (eq character :eof) (return (values line t)) (if (eql character #\Newline) (return (values line nil)) (vector-push-extend character line))))))) (defmethod stream-clear-input (stream) (declare (ignore stream)) nil) (defclass fundamental-character-output-stream (fundamental-output-stream fundamental-character-stream) ()) (defgeneric stream-write-char (stream character)) (defgeneric stream-line-column (stream)) (defgeneric stream-start-line-p (stream)) (defgeneric stream-write-string (stream string &optional start end)) (defgeneric stream-terpri (stream)) (defmethod stream-terpri (stream) (stream-write-char stream #\Newline)) (defgeneric stream-fresh-line (stream)) (defgeneric stream-finish-output (stream)) (defgeneric stream-force-output (stream)) (defgeneric stream-clear-output (stream)) (defgeneric stream-advance-to-column (stream column)) (defgeneric stream-read-sequence (stream sequence &optional start end)) (defgeneric stream-write-sequence (stream sequence &optional start end)) (defmethod stream-force-output (stream) (declare (ignore stream)) nil) (defmethod stream-finish-output (stream) (declare (ignore stream)) nil) (defmethod stream-clear-output (stream) (declare (ignore stream)) nil) (defmethod stream-start-line-p ((stream fundamental-character-output-stream)) (equal (stream-line-column stream) 0)) (defmethod stream-write-string ((stream fundamental-character-output-stream) string &optional (start 0) end) (let ((end (or end (length string)))) (do ((i start (1+ i))) ((>= i end) string) (stream-write-char stream (char string i))))) (defmethod stream-fresh-line ((stream fundamental-character-output-stream)) (if (stream-start-line-p stream) nil (progn (stream-terpri stream) t))) (defmethod stream-advance-to-column ((stream fundamental-character-output-stream) column) (let ((current (stream-line-column stream))) (unless (null current) (dotimes (i (- current column) t) (stream-write-char stream #\Space))))) (defun basic-read-sequence (stream sequence start end expected-element-type read-fun) (let ((element-type (stream-element-type stream))) (if (subtypep element-type expected-element-type) (dotimes (count (- end start) ;; If (< end start), skip the dotimes body but ;; return start (max start end)) (let ((el (funcall read-fun stream))) (when (eq el :eof) (return (+ count start))) (setf (elt sequence (+ count start)) el))) (error "Cannot READ-SEQUENCE on stream of :ELEMENT-TYPE ~A" element-type)))) (defun basic-write-sequence (stream sequence start end expected-element-type write-fun) (let ((element-type (stream-element-type stream))) (if (subtypep element-type expected-element-type) ;; Avoid LOOP because it isn't loaded yet (do ((n start (+ n 1))) ((= n end)) (funcall write-fun stream (elt sequence n))) (error "Cannot WRITE-SEQUENCE on stream of :ELEMENT-TYPE ~A" element-type))) (stream-force-output stream) sequence) (defmethod stream-read-sequence ((stream fundamental-character-input-stream) sequence &optional (start 0) end) (basic-read-sequence stream sequence start (or end (length sequence)) 'character #'stream-read-char)) (defmethod stream-write-sequence ((stream fundamental-character-output-stream) sequence &optional (start 0) end) (basic-write-sequence stream sequence start (or end (length sequence)) 'character #'stream-write-char)) (defclass fundamental-binary-input-stream (fundamental-input-stream fundamental-binary-stream) ()) (defclass fundamental-binary-output-stream (fundamental-output-stream fundamental-binary-stream) ()) (defmethod stream-read-sequence ((stream fundamental-binary-input-stream) sequence &optional (start 0) end) (basic-read-sequence stream sequence start (or end (length sequence)) 'signed-byte #'stream-read-byte)) (defmethod stream-write-sequence ((stream fundamental-binary-output-stream) sequence &optional (start 0) end) (basic-write-sequence stream sequence start (or end (length sequence)) 'signed-byte #'stream-write-byte)) (defun decode-read-arg (arg) (cond ((null arg) *standard-input*) ((eq arg t) *terminal-io*) (t arg))) (defun decode-print-arg (arg) (cond ((null arg) *standard-output*) ((eq arg t) *terminal-io*) (t arg))) (defun report-eof (stream eof-errorp eof-value) (if eof-errorp (error 'end-of-file :stream stream) eof-value)) (defun check-for-eof (value stream eof-errorp eof-value) (if (eq value :eof) (report-eof stream eof-errorp eof-value) value)) (defun gray-read-char (&optional input-stream (eof-errorp t) eof-value recursive-p) (let ((stream (decode-read-arg input-stream))) (if (ansi-streamp stream) (funcall *ansi-read-char* stream eof-errorp eof-value recursive-p) (check-for-eof (stream-read-char stream) stream eof-errorp eof-value)))) (defun gray-peek-char (&optional peek-type input-stream (eof-errorp t) eof-value recursive-p) (let ((stream (decode-read-arg input-stream))) (if (ansi-streamp stream) (funcall *ansi-peek-char* peek-type stream eof-errorp eof-value recursive-p) (if (null peek-type) (check-for-eof (stream-peek-char stream) stream eof-errorp eof-value) (loop (let ((value (stream-peek-char stream))) (if (eq value :eof) (return (report-eof stream eof-errorp eof-value)) (if (if (eq peek-type t) (not (member value '(#\space #\tab #\newline #\return))) (char= peek-type value)) (return value) (stream-read-char stream))))))))) (defun gray-unread-char (character &optional input-stream) (let ((stream (decode-read-arg input-stream))) (if (ansi-streamp stream) (funcall *ansi-unread-char* character stream) (stream-unread-char stream character)))) (defun gray-listen (&optional input-stream) (let ((stream (decode-read-arg input-stream))) (if (ansi-streamp stream) (funcall *ansi-listen* stream) (stream-listen stream)))) (defun gray-read-line (&optional input-stream (eof-error-p t) eof-value recursive-p) (let ((stream (decode-read-arg input-stream))) (if (ansi-streamp stream) (funcall *ansi-read-line* stream eof-error-p eof-value recursive-p) (multiple-value-bind (string eofp) (stream-read-line stream) (if eofp (if (= (length string) 0) (report-eof stream eof-error-p eof-value) (values string t)) (values string nil)))))) (defun gray-clear-input (&optional input-stream) (let ((stream (decode-read-arg input-stream))) (if (ansi-streamp stream) (funcall *ansi-clear-input* stream) (stream-clear-input stream)))) (defun gray-output-object (object stream) (if (ansi-streamp stream) (funcall *sys-%output-object* object stream) (stream-write-string stream (with-output-to-string (s) (funcall *sys-%output-object* object s))))) (defun gray-read-char-no-hang (&optional input-stream (eof-errorp t) eof-value recursive-p) (let ((stream (decode-read-arg input-stream))) (if (ansi-streamp stream) (funcall *ansi-read-char-no-hang* stream eof-errorp eof-value recursive-p) (check-for-eof (stream-read-char-no-hang stream) stream eof-errorp eof-value)))) (defun gray-write-char (character &optional output-stream) (let ((stream (decode-print-arg output-stream))) (if (ansi-streamp stream) (funcall *ansi-write-char* character stream) (stream-write-char stream character)))) (defun gray-fresh-line (&optional output-stream) (let ((stream (decode-print-arg output-stream))) (if (ansi-streamp stream) (funcall *ansi-fresh-line* stream) (stream-fresh-line stream)))) (defun gray-terpri (&optional output-stream) (let ((stream (decode-print-arg output-stream))) (if (ansi-streamp stream) (funcall *ansi-terpri* stream) (stream-terpri stream)))) (defun gray-write-string (string &optional output-stream &key (start 0) end) (let ((stream (decode-print-arg output-stream))) (if (ansi-streamp stream) (funcall *ansi-write-string* string stream :start start :end end) (stream-write-string stream string start end)))) (defun gray-write-line (string &optional output-stream &key (start 0) end) (let ((stream (decode-print-arg output-stream))) (if (ansi-streamp stream) (funcall *ansi-write-line* string stream :start start :end end) (progn (stream-write-string stream string start end) (stream-terpri stream) string)))) (defun gray-force-output (&optional output-stream) (let ((stream (decode-print-arg output-stream))) (if (ansi-streamp stream) (funcall *sys-%force-output* stream) (stream-force-output stream)))) (defun gray-finish-output (&optional output-stream) (let ((stream (decode-print-arg output-stream))) (if (ansi-streamp stream) (funcall *sys-%finish-output* stream) (stream-finish-output stream)))) (defun gray-clear-output (&optional output-stream) (let ((stream (decode-print-arg output-stream))) (if (ansi-streamp stream) (funcall *sys-%clear-output* stream) (stream-clear-output stream)))) (defun gray-read-byte (binary-input-stream &optional (eof-errorp t) eof-value) (if (ansi-streamp binary-input-stream) (funcall *ansi-read-byte* binary-input-stream eof-errorp eof-value) (check-for-eof (stream-read-byte binary-input-stream) binary-input-stream eof-errorp eof-value))) (defun gray-write-byte (integer binary-output-stream) (if (ansi-streamp binary-output-stream) (funcall *ansi-write-byte* integer binary-output-stream) (stream-write-byte binary-output-stream integer))) (defmethod stream-line-column ((stream stream)) nil) (defun gray-stream-column (&optional input-stream) (let ((stream (decode-read-arg input-stream))) (if (ansi-streamp stream) nil ;(funcall *ansi-stream-column* stream) (stream-line-column stream)))) (defmethod gray-stream-element-type (stream) (funcall *ansi-stream-element-type* stream)) (defmethod gray-close (stream &key abort) (funcall *ansi-close* stream :abort abort)) (defmethod gray-input-stream-p (stream) (funcall *ansi-input-stream-p* stream)) (defmethod gray-input-character-stream-p (stream) (funcall *ansi-input-character-stream-p* stream)) (defmethod gray-output-stream-p (stream) (funcall *ansi-output-stream-p* stream)) (defmethod gray-open-stream-p (stream) (funcall *ansi-open-stream-p* stream)) (defmethod gray-streamp (stream) (funcall *ansi-streamp* stream)) (defun gray-write-sequence (sequence stream &key (start 0) end) (if (ansi-streamp stream) (funcall *ansi-write-sequence* sequence stream :start start :end end) (stream-write-sequence stream sequence start end))) (defun gray-read-sequence (sequence stream &key (start 0) end) (if (ansi-streamp stream) (funcall *ansi-read-sequence* sequence stream :start start :end end) (stream-read-sequence stream sequence start end))) (defgeneric stream-file-position (stream &optional position-spec)) (defun gray-file-position (stream &optional position-spec) (if position-spec (if (ansi-streamp stream) (funcall *ansi-file-position* stream position-spec) (stream-file-position stream position-spec)) (if (ansi-streamp stream) (funcall *ansi-file-position* stream) (stream-file-position stream)))) #| (defstruct (two-way-stream-g (:include stream)) input-stream output-stream) (defun gray-make-two-way-stream (in out) (if (and (ansi-streamp in) (ansi-streamp out)) (funcall *ansi-make-two-way-stream* in out) (make-two-way-stream-g :input-stream in :output-stream out))) (defun gray-two-way-stream-input-stream (stream) (if (ansi-streamp stream) (funcall *ansi-two-way-stream-input-stream* stream) (two-way-stream-g-input-stream stream))) (defun gray-two-way-stream-output-stream (stream) (if (ansi-streamp stream) (funcall *ansi-two-way-stream-output-stream* stream) (two-way-stream-g-output-stream stream))) |# (setf (symbol-function 'common-lisp::read-char) #'gray-read-char) (setf (symbol-function 'common-lisp::peek-char) #'gray-peek-char) (setf (symbol-function 'common-lisp::unread-char) #'gray-unread-char) (setf (symbol-function 'common-lisp::read-line) #'gray-read-line) (setf (symbol-function 'common-lisp::clear-input) #'gray-clear-input) (setf (symbol-function 'common-lisp::read-char-no-hang) #'gray-read-char-no-hang) (setf (symbol-function 'common-lisp::write-char) #'gray-write-char) (setf (symbol-function 'common-lisp::fresh-line) #'gray-fresh-line) (setf (symbol-function 'common-lisp::terpri) #'gray-terpri) (setf (symbol-function 'common-lisp::write-string) #'gray-write-string) (setf (symbol-function 'common-lisp::write-line) #'gray-write-line) (setf (symbol-function 'sys::%force-output) #'gray-force-output) (setf (symbol-function 'sys::%finish-output) #'gray-finish-output) (setf (symbol-function 'sys::%clear-output) #'gray-clear-output) (setf (symbol-function 'sys::%output-object) #'gray-output-object) (setf (symbol-function 'common-lisp::read-byte) #'gray-read-byte) (setf (symbol-function 'common-lisp::write-byte) #'gray-write-byte) (setf (symbol-function 'common-lisp::stream-column) #'gray-stream-column) (setf (symbol-function 'common-lisp::stream-element-type) #'gray-stream-element-type) (setf (symbol-function 'common-lisp::close) #'gray-close) (setf (symbol-function 'common-lisp::input-stream-p) #'gray-input-stream-p) (setf (symbol-function 'common-lisp::input-character-stream-p) #'gray-input-character-stream-p) ;; # fb 1.01 (setf (symbol-function 'common-lisp::output-stream-p) #'gray-output-stream-p) (setf (symbol-function 'common-lisp::open-stream-p) #'gray-open-stream-p) (setf (symbol-function 'common-lisp::streamp) #'gray-streamp) (setf (symbol-function 'common-lisp::read-sequence) #'gray-read-sequence) (setf (symbol-function 'common-lisp::write-sequence) #'gray-write-sequence) (setf (symbol-function 'common-lisp::file-position) #'gray-file-position) (setf (symbol-function 'common-lisp::listen) #'gray-listen) (dolist (e '((common-lisp::read-char gray-read-char) (common-lisp::peek-char gray-peek-char) (common-lisp::unread-char gray-unread-char) (common-lisp::read-line gray-read-line) (common-lisp::clear-input gray-clear-input) (common-lisp::read-char-no-hang gray-read-char-no-hang) (common-lisp::write-char gray-write-char) (common-lisp::fresh-line gray-fresh-line) (common-lisp::terpri gray-terpri) (common-lisp::write-string gray-write-string) (common-lisp::write-line gray-write-line) (sys::%force-output gray-force-output) (sys::%finish-output gray-finish-output) (sys::%clear-output gray-clear-output) (sys::%output-object gray-output-object) (common-lisp::read-byte gray-read-byte) (common-lisp::write-byte gray-write-byte) (common-lisp::stream-column gray-stream-column) (common-lisp::stream-element-type gray-stream-element-type) (common-lisp::close gray-close) (common-lisp::input-stream-p gray-input-stream-p) (common-lisp::input-character-stream-p gray-input-character-stream-p) ;; # fb 1.01 (common-lisp::output-stream-p gray-output-stream-p) (common-lisp::open-stream-p gray-open-stream-p) (common-lisp::streamp gray-streamp) (common-lisp::read-sequence gray-read-sequence) (common-lisp::write-sequence gray-write-sequence) (common-lisp::file-position gray-file-position) (common-lisp::listen gray-listen))) (sys::put (car e) 'sys::source (cl:get (second e) 'sys::source))) #| (setf (symbol-function 'common-lisp::make-two-way-stream) #'gray-make-two-way-stream) (setf (symbol-function 'common-lisp::two-way-stream-input-stream) #'gray-two-way-stream-input-stream) (setf (symbol-function 'common-lisp::two-way-stream-output-stream) #'gray-two-way-stream-output-stream) |# (eval-when (:load-toplevel) (mapcar (lambda (o) (mop:finalize-inheritance (find-class o))) '(fundamental-stream fundamental-input-stream fundamental-output-stream fundamental-character-stream fundamental-character-input-stream fundamental-character-output-stream fundamental-binary-stream fundamental-binary-input-stream fundamental-binary-output-stream))) (provide 'gray-streams) ;;; Fixup Gray/ANSI stream relations (defparameter *sys--stream-charpos* #'sys::stream-charpos) (defun sys::stream-charpos (stream) (cond ((subtypep (type-of stream) 'gray-streams:fundamental-stream) (stream-line-column stream)) ((streamp stream) (funcall *sys--stream-charpos* stream)))) (defparameter *sys--stream-%set-charpos* #'sys::stream-%set-charpos) (defun sys::stream-%set-charpos (new-value stream) (cond ((subtypep (type-of stream) 'gray-streams:fundamental-stream) (setf (stream-line-column stream) new-value)) ((streamp stream) (funcall *sys--stream-%set-charpos* stream new-value)))) abcl-src-1.9.0/src/org/armedbear/lisp/gui.lisp0100644 0000000 0000000 00000001255 14202767264 017677 0ustar000000000 0000000 (in-package :extensions) (require :java) (export '(*gui-backend* init-gui make-dialog-prompt-stream)) (defvar *gui-backend* :swing) (defun init-gui () "Dummy function used to autoload this file" t) (defun make-dialog-prompt-stream () (%make-dialog-prompt-stream *gui-backend*)) (defgeneric %make-dialog-prompt-stream (gui-backend)) (defmethod %make-dialog-prompt-stream ((gui-backend (eql :swing))) (java:jnew (java:jconstructor "org.armedbear.lisp.java.swing.SwingDialogPromptStream"))) (defmethod %make-dialog-prompt-stream ((gui-backend (eql :awt))) (java:jnew (java:jconstructor "org.armedbear.lisp.java.awt.AwtDialogPromptStream"))) abcl-src-1.9.0/src/org/armedbear/lisp/inline.lisp0100644 0000000 0000000 00000003441 14202767264 020370 0ustar000000000 0000000 ;;; precompiler.lisp ;;; ;;; Copyright (C) 2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :system) (defun inline-expansion (name) (get-function-info-value name :inline-expansion)) (defun set-inline-expansion (name expansion) (set-function-info-value name :inline-expansion expansion)) (defsetf inline-expansion set-inline-expansion) abcl-src-1.9.0/src/org/armedbear/lisp/input_stream_p.java0100644 0000000 0000000 00000003671 14202767264 022122 0ustar000000000 0000000 /* * input_stream_p.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### input-stream-p public final class input_stream_p extends Primitive { private input_stream_p() { super("input-stream-p"); } @Override public LispObject execute(LispObject arg) { return checkStream(arg).isInputStream() ? T : NIL; } private static final Primitive INPUT_STREAM_P = new input_stream_p(); } abcl-src-1.9.0/src/org/armedbear/lisp/inspect.lisp0100644 0000000 0000000 00000017657 14202767264 020575 0ustar000000000 0000000 ;;; inspect.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require 'clos) (require 'format) (defvar *inspect-break* nil) (defvar *inspected-object-stack* nil) (defvar *inspected-object* nil) (defun leader (name) (let ((size (max 0 (- 16 (length (string name)))))) (concatenate 'string (make-string size :initial-element #\-) "->"))) (defun safe-length (x) (do ((n 0 (+ n 2)) (fast x (cddr fast)) (slow x (cdr slow))) (()) (when (null fast) (return (values n :proper))) (when (atom fast) (return (values n :dotted))) (when (null (cdr fast)) (return (values (+ n 1) :proper))) (when (atom (cdr fast)) (return (values (+ n 1) :dotted))) (when (and (eq fast slow) (> n 0)) (return (values nil :circular))))) (defun display-object (obj) (let ((*print-length* 2) (*print-level* 2)) (cond ((typep obj 'standard-object) (let ((parts (inspected-parts obj)) (i 0)) (dolist (part parts) (let ((name (car part)) (value (cdr part))) (format t "~4D ~A ~A ~S~%" i name (leader name) value) (incf i))))) ((simple-vector-p obj) (format t "~A at #x~X~%" (inspected-description obj) (identity-hash-code obj)) (let ((limit (min (length obj) 25))) (dotimes (i limit) (format t "~4D-> ~A~%" i (aref obj i))))) ((vectorp obj) (format t "~A~%" (inspected-description obj)) (let ((limit (min (length obj) 25))) (dotimes (i limit) (format t "~4D-> ~A~%" i (aref obj i))))) ((consp obj) (multiple-value-bind (len kind) (safe-length obj) (case kind (:proper (format t "A proper list with ~D elements at #x~X~%" len (identity-hash-code obj)) (let ((i 0)) (dolist (item obj) (cond ((< i 25) (format t "~4D-> ~S~%" i item)) ((= i 25) (format t " ...~%")) ((= i (1- len)) (format t "~4D-> ~S~%" i item))) (incf i)))) (:dotted (format t "A dotted list with ~D elements at #x~X~%" len (identity-hash-code obj)) (let* ((rest obj) (item (car rest)) (i 0)) (loop (cond ((< i 25) (format t "~4D-> ~S~%" i item)) ((= i 25) (format t " ...~%"))) (incf i) (setf rest (cdr rest)) (when (atom rest) (return)) (setf item (car rest))) (format t "tail-> ~S~%" rest))) (:circular (format t "A circular list at #x~X~%" (identity-hash-code obj)))))) (t (format t "~A~%" (inspected-description obj)) (let ((parts (inspected-parts obj)) (i 0) (limit 25)) (dolist (part parts) (let ((name (string (car part))) (value (cdr part))) (format t "~4D ~A ~A ~S~%" i name (leader name) value) (incf i) (when (> i limit) (return)))))))) (values)) (defun display-current () (if *inspect-break* (display-object *inspected-object*) (format t "No object is being inspected."))) (defun inspect (obj) (when ext:*inspector-hook* (funcall ext:*inspector-hook* obj)) (when *inspected-object* (push *inspected-object* *inspected-object-stack*)) (setf *inspected-object* obj) (let* ((*inspect-break* t) (*debug-level* (1+ *debug-level*))) (setf *** ** ** * * obj) (display-current) (catch 'inspect-exit (tpl::repl))) (setf *** ** ** * * obj) (values)) (defun istep (args) (if (null args) (display-current) (let* ((pos (position #\space args)) (option-string (if pos (subseq args 0 pos) args)) (option (read-from-string option-string))) (cond ((string= option-string "-") (if *inspected-object-stack* (progn (setf *inspected-object* (pop *inspected-object-stack*)) (setf *** ** ** * * *inspected-object*) (display-current)) (format t "Object has no parent."))) ((string= option-string "q") (setf *inspected-object* nil *inspected-object-stack* nil *inspect-break* nil) (throw 'inspect-exit nil)) ((fixnump option) (let* ((index option) (parts (inspected-parts *inspected-object*))) (cond ((null parts) (if (typep *inspected-object* 'sequence) (if (or (minusp index) (>= index (length *inspected-object*))) (format t "Invalid index (~D)." index) (progn (push *inspected-object* *inspected-object-stack*) (setf *inspected-object* (elt *inspected-object* index)) (setf * *inspected-object*) (display-current))) (format t "Object has no selectable components."))) ((or (minusp index) (>= index (length parts))) (format t "Invalid index (~D)." index)) (t (push *inspected-object* *inspected-object-stack*) (setf *inspected-object* (cdr (elt parts index))) (setf * *inspected-object*) (display-current))))))))) abcl-src-1.9.0/src/org/armedbear/lisp/interactive_stream_p.java0100644 0000000 0000000 00000004074 14202767264 023276 0ustar000000000 0000000 /* * interactive_stream_p.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### interactive-stream-p public final class interactive_stream_p extends Primitive { private interactive_stream_p() { super("interactive-stream-p", "stream"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof Stream) return ((Stream)arg).isInteractive() ? T : NIL; return type_error(arg, Symbol.STREAM); } private static final Primitive INTERACTIVE_STREAM_P = new interactive_stream_p(); } abcl-src-1.9.0/src/org/armedbear/lisp/java-collections.lisp0100644 0000000 0000000 00000014711 14223403213 022331 0ustar000000000 0000000 (require "CLOS") (require "JAVA") (require "EXTENSIBLE-SEQUENCES") (require "PRINT-OBJECT") (in-package :java) (let* ((jclass (jclass "java.util.List")) (class (%find-java-class jclass))) (if class (error "java.util.List is already registered as a Lisp class; since JAVA-CLASSes can't be redefined, I can't inject SEQUENCE in its class precedence list. Ensure that you require :java-collections before specializing any method on java.util.List and in general before using java.util.List as a CLOS class.") ;;The code below is adapted from ensure-java-class in java.lisp (%register-java-class jclass (mop::ensure-class (make-symbol (jclass-name jclass)) :metaclass (find-class 'java-class) :direct-superclasses (let ((supers (mapcar #'ensure-java-class (delete nil (concatenate 'list (list (jclass-superclass jclass)) (jclass-interfaces jclass)))))) (append supers (list (find-class 'sequence)) (jclass-additional-superclasses jclass))) :java-class jclass)))) (defmethod print-object ((coll (jclass "java.util.Collection")) stream) (print-unreadable-object (coll stream :type t :identity t) (format stream "~A ~A" (jclass-of coll) (jcall "toString" coll)))) ;;Lists (java.util.List) are the Java counterpart to Lisp SEQUENCEs. (defun jlist-add (list item) (jcall (jmethod "java.util.List" "add" "java.lang.Object") list item)) (defun jlist-set (list index item) (jcall (jmethod "java.util.List" "set" "int" "java.lang.Object") list index item)) (defun jlist-get (list index) (jcall (jmethod "java.util.List" "get" "int") list index)) (defmethod sequence:length ((s (jclass "java.util.List"))) (jcall (jmethod "java.util.Collection" "size") s)) (defmethod sequence:elt ((s (jclass "java.util.List")) index) (jlist-get s index)) (defmethod (setf sequence:elt) (value (list (jclass "java.util.List")) index) (jlist-set list index value) value) (defmethod sequence:make-sequence-like ((s (jclass "java.util.List")) length &rest args &key initial-element initial-contents) (declare (ignorable initial-element initial-contents)) (apply #'make-jsequence-like s length #'jlist-add args)) (defun make-jsequence-like (s length add-fn &key (initial-element nil iep) (initial-contents nil icp)) (let ((seq (jnew (jclass-of s)))) (cond ((and icp iep) (error "Can't specify both :initial-element and :initial-contents")) (icp (dotimes (i length) (funcall add-fn seq (elt initial-contents i)))) ;;TODO inefficient, use iterator (t (dotimes (i length) (funcall add-fn seq initial-element)))) seq)) ;;TODO: destruct doesn't signal an error for too-many-args for its options ;;e.g. this didn't complain: ;;(defstruct (jlist-iterator (:type list :conc-name #:jlist-it-)) (defstruct (jlist-iterator (:type list) (:conc-name #:jlist-it-)) (native-iterator (error "Native iterator required") :read-only t) element index) (defmethod sequence:make-simple-sequence-iterator ((s (jclass "java.util.List")) &key from-end (start 0) end) (let* ((end (or end (length s))) (index (if from-end end start)) (it (jcall "listIterator" s index)) (iter (make-jlist-iterator :native-iterator it :index (if from-end (1+ index) (1- index)))) (limit (if from-end (1+ start) (1- end)))) ;;CL iterator semantics are that first element is present from the start (unless (sequence:iterator-endp s iter limit from-end) (sequence:iterator-step s iter from-end)) (values iter limit from-end))) ;;Collection, and not List, because we want to reuse this for Set when applicable (defmethod sequence:iterator-step ((s (jclass "java.util.Collection")) it from-end) (let ((native-it (jlist-it-native-iterator it))) (if from-end (progn (setf (jlist-it-element it) (when (jcall "hasPrevious" native-it) (jcall "previous" native-it))) (decf (jlist-it-index it))) (progn (setf (jlist-it-element it) (when (jcall "hasNext" native-it) (jcall "next" native-it))) (incf (jlist-it-index it))))) it) (defmethod sequence:iterator-endp ((s (jclass "java.util.Collection")) it limit from-end) (if from-end (< (jlist-it-index it) limit) (> (jlist-it-index it) limit))) (defmethod sequence:iterator-element ((s (jclass "java.util.Collection")) iterator) (declare (ignore s)) (jlist-it-element iterator)) (defmethod (setf sequence:iterator-element) (new-value (s (jclass "java.util.Collection")) it) (jcall "set" (jlist-it-native-iterator it) new-value)) (defmethod sequence:iterator-index ((s (jclass "java.util.Collection")) iterator) (declare (ignore s)) (jlist-it-index iterator)) (defmethod sequence:iterator-copy ((s (jclass "java.util.Collection")) iterator) (declare (ignore s iterator)) (error "iterator-copy not supported for Java iterators.")) ;;It makes sense to have some sequence functions available for Sets ;;(java.util.Set) too, even if they're not sequences. (defun jset-add (set item) (jcall (jmethod "java.util.Set" "add" "java.lang.Object") set item)) (defmethod sequence:length ((s (jclass "java.util.Set"))) (jcall (jmethod "java.util.Collection" "size") s)) (defmethod sequence:make-sequence-like ((s (jclass "java.util.Set")) length &rest args &key initial-element initial-contents) (declare (ignorable initial-element initial-contents)) (apply #'make-jsequence-like s length #'jset-add args)) (defmethod sequence:make-simple-sequence-iterator ((s (jclass "java.util.Set")) &key from-end (start 0) end) (when (or from-end (not (= start 0))) (error "Java Sets can only be iterated from the start.")) (let* ((end (or end (length s))) (it (jcall "iterator" s)) (iter (make-jlist-iterator :native-iterator it :index -1)) (limit (1- end))) ;;CL iterator semantics are that first element is present from the start (unless (sequence:iterator-endp s iter limit nil) (sequence:iterator-step s iter nil)) (values iter limit nil))) (provide :java-collections) abcl-src-1.9.0/src/org/armedbear/lisp/java.lisp0100644 0000000 0000000 00000065320 14223403213 020017 0ustar000000000 0000000 ;;; java.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves, Andras Simon ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "JAVA") (require "CLOS") (require "PRINT-OBJECT") (defvar *classloader* (get-default-classloader)) (EXPORT '(JREGISTER-HANDLER JINTERFACE-IMPLEMENTATION JMAKE-INVOCATION-HANDLER JMAKE-PROXY JPROPERTY-VALUE JOBJECT-CLASS JCLASS-SUPERCLASS JCLASS-INTERFACES JCLASS-INTERFACE-P JCLASS-SUPERCLASS-P JCLASS-ARRAY-P JARRAY-COMPONENT-TYPE JARRAY-LENGTH JNEW-ARRAY-FROM-ARRAY JNEW-ARRAY-FROM-LIST JARRAY-FROM-LIST JCLASS-CONSTRUCTORS JCONSTRUCTOR-PARAMS JCLASS-FIELD JCLASS-FIELDS JFIELD-TYPE JFIELD-NAME JCLASS-METHODS JMETHOD-PARAMS JMETHOD-NAME JINSTANCE-OF-P JMEMBER-STATIC-P JMEMBER-PUBLIC-P JMEMBER-PROTECTED-P JNEW-RUNTIME-CLASS DEFINE-JAVA-CLASS ENSURE-JAVA-CLASS CHAIN JMETHOD-LET JEQUAL)) (defun add-url-to-classpath (url &optional (classloader *classloader*)) (jcall "addUrl" classloader url)) (defun add-urls-to-classpath (&rest urls) (dolist (url urls) (add-url-to-classpath url))) (defgeneric add-to-classpath (jar-or-jars &optional classloader) (:documentation "Add JAR-OR-JARS to the JVM classpath optionally specifying the CLASSLOADER to add. JAR-OR-JARS is either a pathname designating a jar archive or the root directory to search for classes or a list of such values.")) (defmethod add-to-classpath (jar-or-jars &optional (classloader (get-current-classloader))) (%add-to-classpath jar-or-jars classloader)) (defun jregister-handler (object event handler &key data count) (%jregister-handler object event handler data count)) (defun jinterface-implementation (interface &rest method-names-and-defs) "Creates and returns an implementation of a Java interface with methods calling Lisp closures as given in METHOD-NAMES-AND-DEFS. INTERFACE is either a Java interface or a string naming one. METHOD-NAMES-AND-DEFS is an alternating list of method names (strings) and method definitions (closures). For missing methods, a dummy implementation is provided that returns nothing or null depending on whether the return type is void or not. This is for convenience only, and a warning is issued for each undefined method." (let ((interface (jclass interface)) (implemented-methods (loop for m in method-names-and-defs for i from 0 if (evenp i) do (assert (stringp m) (m) "Method names must be strings: ~s" m) and collect m else do (assert (or (symbolp m) (functionp m)) (m) "Methods must be function designators: ~s" m)))) (loop for method across (jclass-methods interface :declared nil :public t) for method-name = (jmethod-name method) when (not (member method-name implemented-methods :test #'string=)) do (let* ((void-p (string= (jclass-name (jmethod-return-type method)) "void")) (arglist (when (plusp (length (jmethod-params method))) '(&rest ignore))) (def `(lambda ,arglist ,(when arglist '(declare (ignore ignore))) ,(if void-p '(values) java:+null+)))) (warn "Implementing dummy method ~a for interface ~a" method-name (jclass-name interface)) (push (coerce def 'function) method-names-and-defs) (push method-name method-names-and-defs))) (apply #'%jnew-proxy interface method-names-and-defs))) (defun jmake-invocation-handler (function) (%jmake-invocation-handler function)) (when (autoloadp 'jmake-proxy) (fmakunbound 'jmake-proxy)) (defgeneric jmake-proxy (interface implementation &optional lisp-this) (:documentation "Returns a proxy Java object implementing the provided interface(s) using methods implemented in Lisp - typically closures, but implementations are free to provide other mechanisms. You can pass an optional 'lisp-this' object that will be passed to the implementing methods as their first argument. If you don't provide this object, NIL will be used. The second argument of the Lisp methods is the name of the Java method being implemented. This has the implication that overloaded methods are merged, so you have to manually discriminate them if you want to. The remaining arguments are java-objects wrapping the method's parameters.")) (defun canonicalize-jproxy-interfaces (ifaces) (if (listp ifaces) (mapcar #'jclass ifaces) (list (jclass ifaces)))) (defmethod jmake-proxy (interface invocation-handler &optional lisp-this) "Basic implementation that directly uses an invocation handler." (%jmake-proxy (canonicalize-jproxy-interfaces interface) invocation-handler lisp-this)) (defmethod jmake-proxy (interface (implementation function) &optional lisp-this) "Implements a Java interface forwarding method calls to a Lisp function." (%jmake-proxy (canonicalize-jproxy-interfaces interface) (jmake-invocation-handler implementation) lisp-this)) (defmethod jmake-proxy (interface (implementation package) &optional lisp-this) "Implements a Java interface mapping Java method names to symbols in a given package. javaMethodName is mapped to a JAVA-METHOD-NAME symbol. An error is signaled if no such symbol exists in the package, or if the symbol exists but does not name a function." (flet ((java->lisp (name) (with-output-to-string (str) (let ((last-lower-p nil)) (map nil (lambda (char) (let ((upper-p (char= (char-upcase char) char))) (when (and last-lower-p upper-p) (princ "-" str)) (setf last-lower-p (not upper-p)) (princ (char-upcase char) str))) name))))) (%jmake-proxy (canonicalize-jproxy-interfaces interface) (jmake-invocation-handler (lambda (obj method &rest args) (let ((sym (find-symbol (java->lisp method) implementation))) (unless sym (error "Symbol ~A, implementation of method ~A, not found in ~A" (java->lisp method) method implementation)) (if (fboundp sym) (apply (symbol-function sym) obj method args) (error "Function ~A, implementation of method ~A, not found in ~A" sym method implementation))))) lisp-this))) (defmethod jmake-proxy (interface (implementation hash-table) &optional lisp-this) "Implements a Java interface using closures in an hash-table keyed by Java method name." (%jmake-proxy (canonicalize-jproxy-interfaces interface) (jmake-invocation-handler (lambda (obj method &rest args) (let ((fn (gethash method implementation))) (if fn (apply fn obj args) (error "Implementation for method ~A not found in ~A" method implementation))))) lisp-this)) (defun jequal (obj1 obj2) "Compares obj1 with obj2 using java.lang.Object.equals()" (jcall (jmethod "java.lang.Object" "equals" "java.lang.Object") obj1 obj2)) (defun jobject-class (obj) "Returns the Java class that OBJ belongs to" (jcall (jmethod "java.lang.Object" "getClass") obj)) (defun jclass-superclass (class) "Returns the superclass of CLASS, or NIL if it hasn't got one" (jcall (jmethod "java.lang.Class" "getSuperclass") (jclass class))) (defun jclass-interfaces (class) "Returns the vector of interfaces of CLASS" (jcall (jmethod "java.lang.Class" "getInterfaces") (jclass class))) (defun jclass-interface-p (class) "Returns T if CLASS is an interface" (jcall (jmethod "java.lang.Class" "isInterface") (jclass class))) (defun jclass-superclass-p (class-1 class-2) "Returns T if CLASS-1 is a superclass or interface of CLASS-2" (jcall (jmethod "java.lang.Class" "isAssignableFrom" "java.lang.Class") (jclass class-1) (jclass class-2))) (defun jclass-array-p (class) "Returns T if CLASS is an array class" (jcall (jmethod "java.lang.Class" "isArray") (jclass class))) (defun jarray-component-type (atype) "Returns the component type of the array type ATYPE" (assert (jclass-array-p atype)) (jcall (jmethod "java.lang.Class" "getComponentType") atype)) (defun jarray-length (java-array) "Returns the length of a Java primitive array." (jstatic "getLength" "java.lang.reflect.Array" java-array) ) (defun (setf jarray-ref) (new-value java-array &rest indices) (apply #'jarray-set java-array new-value indices)) (defun jnew-array-from-array (element-type array) "Returns a new Java array with base type ELEMENT-TYPE (a string or a class-ref) initialized from ARRAY." (flet ((row-major-to-index (dimensions n) (loop for dims on dimensions with indices do (multiple-value-bind (m r) (floor n (apply #'* (cdr dims))) (push m indices) (setq n r)) finally (return (nreverse indices))))) (let* ((fill-pointer (when (array-has-fill-pointer-p array) (fill-pointer array))) (dimensions (if fill-pointer (list fill-pointer) (array-dimensions array))) (jarray (apply #'jnew-array element-type dimensions))) (dotimes (i (if fill-pointer fill-pointer (array-total-size array)) jarray) #+maybe_one_day (setf (apply #'jarray-ref jarray (row-major-to-index dimensions i)) (row-major-aref array i)) (apply #'(setf jarray-ref) (row-major-aref array i) jarray (row-major-to-index dimensions i)))))) (defun jnew-array-from-list (element-type list) "Returns a new Java array with base type ELEMENT-TYPE (a string or a class-ref) initialized from a Lisp list." (let ((jarray (jnew-array element-type (length list))) (i 0)) (dolist (x list) (setf (jarray-ref jarray i) x i (1+ i))) jarray)) (defun jarray-from-list (list) "Return a Java array from LIST whose type is inferred from the first element. For more control over the type of the array, use JNEW-ARRAY-FROM-LIST." (jnew-array-from-list (jobject-class (first list)) list)) (defun list-from-jarray (jarray) "Returns a list with the elements of `jarray`." (loop for i from 0 below (jarray-length jarray) collect (jarray-ref jarray i))) (defun vector-from-jarray (jarray) "Returns a vector with the elements of `jarray`." (loop with vec = (make-array (jarray-length jarray)) for i from 0 below (jarray-length jarray) do (setf (aref vec i) (jarray-ref jarray i)) finally (return vec))) (defun list-from-jenumeration (jenumeration) "Returns a list with the elements returned by successive `nextElement` calls on the java.util.Enumeration `jenumeration`." (loop while (jcall jenumeration (jmethod "java.util.Enumeration" "hasMoreElements")) collect (jcall jenumeration (jmethod "java.util.Enumeration" "nextElement")))) (defun jclass-constructors (class) "Returns a vector of constructors for CLASS" (jcall (jmethod "java.lang.Class" "getConstructors") (jclass class))) (defun jconstructor-params (constructor) "Returns a vector of parameter types (Java classes) for CONSTRUCTOR" (jcall (jmethod "java.lang.reflect.Constructor" "getParameterTypes") constructor)) (defun jclass-fields (class &key declared public) "Returns a vector of all (or just the declared/public, if DECLARED/PUBLIC is true) fields of CLASS" (let* ((getter (if declared "getDeclaredFields" "getFields")) (fields (jcall (jmethod "java.lang.Class" getter) (jclass class)))) (if public (delete-if-not #'jmember-public-p fields) fields))) (defun jclass-field (class field-name) "Returns the field named FIELD-NAME of CLASS" (jcall (jmethod "java.lang.Class" "getField" "java.lang.String") (jclass class) field-name)) (defun jfield-type (field) "Returns the type (Java class) of FIELD" (jcall (jmethod "java.lang.reflect.Field" "getType") field)) (defun jfield-name (field) "Returns the name of FIELD as a Lisp string" (jcall (jmethod "java.lang.reflect.Field" "getName") field)) (defun (setf jfield) (newvalue class-ref-or-field field-or-instance &optional (instance nil instance-supplied-p) unused-value) (declare (ignore unused-value)) (if instance-supplied-p (jfield class-ref-or-field field-or-instance instance newvalue) (jfield class-ref-or-field field-or-instance nil newvalue))) (defun jclass-methods (class &key declared public) "Return a vector of all (or just the declared/public, if DECLARED/PUBLIC is true) methods of CLASS" (let* ((getter (if declared "getDeclaredMethods" "getMethods")) (methods (jcall (jmethod "java.lang.Class" getter) (jclass class)))) (if public (delete-if-not #'jmember-public-p methods) methods))) (defun jmethod-params (method) "Returns a vector of parameter types (Java classes) for METHOD" (jcall (jmethod "java.lang.reflect.Method" "getParameterTypes") method)) (defun jmethod-return-type (method) "Returns the result type (Java class) of the METHOD" (jcall (jmethod "java.lang.reflect.Method" "getReturnType") method)) (defun jmethod-declaring-class (method) "Returns the Java class declaring METHOD" (jcall (jmethod "java.lang.reflect.Method" "getDeclaringClass") method)) (defun jmethod-name (method) "Returns the name of METHOD as a Lisp string" (jcall (jmethod "java.lang.reflect.Method" "getName") method)) (defun jinstance-of-p (obj class) "OBJ is an instance of CLASS (or one of its subclasses)" (and (java-object-p obj) (jcall (jmethod "java.lang.Class" "isInstance" "java.lang.Object") (jclass class) obj))) (defun jmember-static-p (member) "MEMBER is a static member of its declaring class" (jstatic (jmethod "java.lang.reflect.Modifier" "isStatic" "int") "java.lang.reflect.Modifier" (jcall (jmethod "java.lang.reflect.Member" "getModifiers") member))) (defun jmember-public-p (member) "MEMBER is a public member of its declaring class" (jstatic (jmethod "java.lang.reflect.Modifier" "isPublic" "int") "java.lang.reflect.Modifier" (jcall (jmethod "java.lang.reflect.Member" "getModifiers") member))) (defun jmember-protected-p (member) "MEMBER is a protected member of its declaring class" (jstatic (jmethod "java.lang.reflect.Modifier" "isProtected" "int") "java.lang.reflect.Modifier" (jcall (jmethod "java.lang.reflect.Member" "getModifiers") member))) (defmethod make-load-form ((object java-object) &optional environment) (declare (ignore environment)) (let ((class-name (jclass-name (jclass-of object)))) (cond ((string= class-name "java.lang.reflect.Constructor") `(java:jconstructor ,(jclass-name (jcall (jmethod "java.lang.reflect.Constructor" "getDeclaringClass") object)) ,@(loop for arg-type across (jcall (jmethod "java.lang.reflect.Constructor" "getParameterTypes") object) collecting (jclass-name arg-type)))) ((string= class-name "java.lang.reflect.Method") `(java:jmethod ,(jclass-name (jcall (jmethod "java.lang.reflect.Method" "getDeclaringClass") object)) ,(jmethod-name object) ,@(loop for arg-type across (jcall (jmethod "java.lang.reflect.Method" "getParameterTypes") object) collecting (jclass-name arg-type)))) ((string= class-name "java.lang.reflect.Field") `(let ((field (find ,(jcall "getName" object) (jcall "getDeclaredFields" ,(jcall "getDeclaringClass" object)) :key (lambda(el) (jcall "getName" el)) :test 'equal))) (jcall "setAccessible" field t) field)) ((jinstance-of-p object "java.lang.Class") `(java:jclass ,(jcall (jmethod "java.lang.Class" "getName") object))) (t (error "Unknown load-form for ~A" class-name))))) (defun jproperty-value (object property) "setf-able access on the Java Beans notion of property named PROPETRY on OBJECT." (%jget-property-value object property)) (defun (setf jproperty-value) (value obj prop) (%jset-property-value obj prop value)) ;;; higher-level operators (defmacro chain (target op &rest ops) "Performs chained method invocations. TARGET is either the receiver object when the first call is a virtual method call or a list in the form (:static ) when the first method call is a static method call. OP and each of the OPS are either method designators or lists in the form ( &rest args), where a method designator is either a string naming a method, or a jmethod object. CHAIN will perform the method call specified by OP on TARGET; then, for each of the OPS, CHAIN will perform the specified method call using the object returned by the previous method call as the receiver, and will ultimately return the result of the last method call. For example, the form: (chain (:static \"java.lang.Runtime\") \"getRuntime\" (\"exec\" \"ls\")) is equivalent to the following Java code: java.lang.Runtime.getRuntime().exec(\"ls\");" (labels ((canonicalize-op (op) (if (listp op) op (list op))) (compose-arglist (target op) `(,(car op) ,target ,@(cdr op))) (make-binding-for (form) `(,(gensym) ,form)) (make-binding (bindings next-op &aux (target (caar bindings))) (cons (make-binding-for `(jcall ,@(compose-arglist target (canonicalize-op next-op)))) bindings))) (let* ((first (if (and (consp target) (eq (first target) :static)) `(jstatic ,@(compose-arglist (cadr target) (canonicalize-op op))) `(jcall ,@(compose-arglist target (canonicalize-op op))))) (bindings (nreverse (reduce #'make-binding ops :initial-value (list (make-binding-for first)))))) `(let* ,bindings (declare (ignore ,@(butlast (mapcar #'car bindings)))) ,(caar (last bindings)))))) (defmacro jmethod-let (bindings &body body) (let ((args (gensym))) `(let ,(mapcar (lambda (binding) `(,(car binding) (jmethod ,@(cdr binding)))) bindings) (macrolet ,(mapcar (lambda (binding) `(,(car binding) (&rest ,args) `(jcall ,,(car binding) ,@,args))) bindings) ,@body)))) ;;; print-object (defmethod print-object ((obj java:java-object) stream) (if (jnull-ref-p obj) (write-string "#" stream) (print-java-object-by-class (jobject-class obj) obj stream))) ;;define extensions by eql methods on class name interned in keyword package ;;e.g. (defmethod java::print-java-object-by-class ((class (eql ':|uk.ac.manchester.cs.owl.owlapi.concurrent.ConcurrentOWLOntologyImpl|)) obj stream) ;; (print 'hi) ;; (call-next-method)) (defmethod print-java-object-by-class :around (class obj stream) (handler-bind ((java-exception #'(lambda(c) (format stream "#<~a, while printing a ~a>" (jcall "toString" (java-exception-cause c)) (jcall "getName" (jcall "getClass" obj))) (return-from print-java-object-by-class)))) (call-next-method))) ;; we have to do our own inheritence for the java class (defmethod print-java-object-by-class (class obj stream) (loop for super = class then (jclass-superclass super) for keyword = (intern (jcall "getName" super) 'keyword) for method = (find-method #'print-java-object-by-class nil (list `(eql ,keyword) t t) nil) while (jclass-superclass super) when method do (return-from print-java-object-by-class (print-java-object-by-class keyword obj stream))) (write-string (sys::%write-to-string obj) stream)) (defmethod print-object ((e java:java-exception) stream) (handler-bind ((java-exception #'(lambda(c) (format stream "#<~a,while printing a ~a>" (jcall "toString" (java-exception-cause c)) (jcall "getName" (jcall "getClass" e))) (return-from print-object)))) (if *print-escape* (print-unreadable-object (e stream :type t :identity t) (format stream "~A" (java:jcall (java:jmethod "java.lang.Object" "toString") (java:java-exception-cause e)))) (format stream "Java exception '~A'." (java:jcall (java:jmethod "java.lang.Object" "toString") (java:java-exception-cause e)))))) ;;; JAVA-CLASS support (defconstant +java-lang-object+ (jclass "java.lang.Object")) (defclass java-class (standard-class) ((jclass :initarg :java-class :initform (error "class is required") :reader java-class-jclass))) ;;; FIXME (rudi 2012-05-02): consider replacing the metaclass of class ;;; java-object to be java-class here instead of allowing this subclass ;;; relationship. On the other hand, abcl ran for the longest time ;;; without an implementation of validate-superclass, so this doesn't ;;; introduce new sources for bugs. (defmethod mop:validate-superclass ((class java-class) (superclass built-in-class)) t) ;;init java.lang.Object class (defconstant +java-lang-object-class+ (%register-java-class +java-lang-object+ (mop::ensure-class (make-symbol "java.lang.Object") :metaclass (find-class 'java-class) :direct-superclasses (list (find-class 'java-object)) :java-class +java-lang-object+))) (defun jclass-additional-superclasses (jclass) "Extension point to put additional CLOS classes on the CPL of a CLOS Java class." (let ((supers nil)) (when (jclass-interface-p jclass) (push (find-class 'java-object) supers)) supers)) (defun ensure-java-class (jclass) "Attempt to ensure that the Java class referenced by JCLASS exists in the current process of the implementation." (let ((class (%find-java-class jclass))) (if class class (%register-java-class jclass (mop::ensure-class (make-symbol (jclass-name jclass)) :metaclass (find-class 'java-class) :direct-superclasses (let ((supers (mapcar #'ensure-java-class (delete nil (concatenate 'list (list (jclass-superclass jclass)) (jclass-interfaces jclass)))))) (append supers (jclass-additional-superclasses jclass))) :java-class jclass))))) (defmethod mop::compute-class-precedence-list ((class java-class)) "Sort classes this way: 1. Java classes (but not java.lang.Object) 2. Java interfaces 3. java.lang.Object 4. other classes Rationale: 1. Concrete classes are the most specific. 2. Then come interfaces. So if a generic function is specialized both on an interface and a concrete class, the concrete class comes first. 3. because everything is an Object. 4. to handle base CLOS classes. Note: Java interfaces are not sorted among themselves in any way, so if a gf is specialized on two different interfaces and you apply it to an object that implements both, it is unspecified which method will be called." (let ((cpl (nreverse (mop::collect-superclasses* class)))) (flet ((score (class) (if (not (typep class 'java-class)) 4 (cond ((jcall (jmethod "java.lang.Object" "equals" "java.lang.Object") (java-class-jclass class) +java-lang-object+) 3) ((jclass-interface-p (java-class-jclass class)) 2) (t 1))))) (stable-sort cpl #'(lambda (x y) (< (score x) (score y))))))) (defmethod make-instance ((class java-class) &rest initargs &key &allow-other-keys) (declare (ignore initargs)) (error "make-instance not supported for ~S" class)) (defun jinput-stream (pathname) "Returns a java.io.InputStream for resource denoted by PATHNAME." (sys:get-input-stream pathname)) (provide "JAVA") abcl-src-1.9.0/src/org/armedbear/lisp/java/swing/REPLConsole.java0100644 0000000 0000000 00000024040 14202767264 023217 0ustar000000000 0000000 /* * ConsoleDocument.java * * Copyright (C) 2008-2009 Alessio Stalla * * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp.java.swing; import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedReader; import java.io.BufferedWriter; import java.lang.RuntimeException; import java.io.Reader; import java.io.Writer; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.JTextComponent; import org.armedbear.lisp.Function; import org.armedbear.lisp.Interpreter; import org.armedbear.lisp.LispObject; import org.armedbear.lisp.LispThread; import org.armedbear.lisp.SpecialBindingsMark; import org.armedbear.lisp.Stream; import org.armedbear.lisp.Symbol; import org.armedbear.lisp.TwoWayStream; import static org.armedbear.lisp.Lisp.*; public class REPLConsole extends DefaultStyledDocument { private StringBuffer inputBuffer = new StringBuffer(); private Reader reader = new Reader() { @Override public void close() throws RuntimeException {} @Override public synchronized int read(char[] cbuf, int off, int len) throws RuntimeException { try { int length = Math.min(inputBuffer.length(), len); while(length <= 0) { wait(); length = Math.min(inputBuffer.length(), len); } inputBuffer.getChars(0, length, cbuf, off); inputBuffer.delete(0, length); return length; } catch (InterruptedException e) { throw new RuntimeException(e); } } }; private Writer writer = new Writer() { @Override public void close() throws RuntimeException {} @Override public void flush() throws RuntimeException {} @Override public void write(final char[] cbuf, final int off, final int len) throws RuntimeException { try { final int insertOffs; synchronized(reader) { if(inputBuffer.toString().matches("^\\s*$")) { int length = inputBuffer.length(); inputBuffer.delete(0, length); } insertOffs = getLength() - inputBuffer.length(); reader.notifyAll(); } Runnable r = new Runnable() { public void run() { synchronized(reader) { try { superInsertString(insertOffs, new String(cbuf, off, len), null); } catch(Exception e) { assert(false); //BadLocationException should not happen here } } } }; SwingUtilities.invokeAndWait(r); } catch (Exception e) { throw new RuntimeException(e); } } }; private boolean disposed = false; private final Thread replThread; public REPLConsole(LispObject replFunction) { final LispObject replWrapper = makeReplWrapper(new Stream(Symbol.SYSTEM_STREAM, new BufferedReader(reader)), new Stream(Symbol.SYSTEM_STREAM, new BufferedWriter(writer)), replFunction); replThread = new Thread("REPL-thread-" + System.identityHashCode(this)) { public void run() { while(true) { replWrapper.execute(); java.lang.Thread.yield(); } } }; replThread.start(); } @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { synchronized(reader) { int bufferStart = getLength() - inputBuffer.length(); if(offs < bufferStart) { throw new BadLocationException("Can only insert after " + bufferStart, offs); } superInsertString(offs, str, a); inputBuffer.insert(offs - bufferStart, str); if(processInputP(inputBuffer, str)) { reader.notifyAll(); } } } protected void superInsertString(int offs, String str, AttributeSet a) throws BadLocationException { super.insertString(offs, str, a); } /** * Guaranteed to run with exclusive access to the buffer. * @param sb NB sb MUST NOT be destructively modified!! * @return */ protected boolean processInputP(StringBuffer sb, String str) { if(str.indexOf("\n") == -1) { return false; } int parenCount = 0; int len = sb.length(); for(int i = 0; i < len; i++) { char c = sb.charAt(i); if(c == '(') { parenCount++; } else if(c == ')') { parenCount--; if(parenCount == 0) { return true; } } } return parenCount <= 0; } @Override public void remove(int offs, int len) throws BadLocationException { synchronized(reader) { int bufferStart = getLength() - inputBuffer.length(); if(offs < bufferStart) { throw new BadLocationException("Can only remove after " + bufferStart, offs); } super.remove(offs, len); inputBuffer.delete(offs - bufferStart, offs - bufferStart + len); } } public Reader getReader() { return reader; } public Writer getWriter() { return writer; } public void setupTextComponent(final JTextComponent txt) { addDocumentListener(new DocumentListener() { // @Override public void changedUpdate(DocumentEvent e) { } // @Override public void insertUpdate(DocumentEvent e) { int len = getLength(); if(len - e.getLength() == e.getOffset()) { //The insert was at the end of the document txt.setCaretPosition(getLength()); } } // @Override public void removeUpdate(DocumentEvent e) { } }); txt.setCaretPosition(getLength()); } public void dispose() { disposed = true; for(DocumentListener listener : getDocumentListeners()) { removeDocumentListener(listener); } try { reader.close(); writer.close(); } catch (Exception e) { throw new RuntimeException(e); } replThread.interrupt(); //really? } private final LispObject debuggerHook = new Function() { @Override public LispObject execute(LispObject condition, LispObject debuggerHook) { if(disposed) { return PACKAGE_SYS.findSymbol("%DEBUGGER-HOOK-FUNCTION").execute(condition, debuggerHook); } else { return NIL; } } }; public LispObject makeReplWrapper(final Stream in, final Stream out, final LispObject fn) { return new Function() { @Override public LispObject execute() { SpecialBindingsMark lastSpecialBinding = LispThread.currentThread().markSpecialBindings(); try { TwoWayStream ioStream = new TwoWayStream(in, out); LispThread.currentThread().bindSpecial(Symbol.DEBUGGER_HOOK, debuggerHook); LispThread.currentThread().bindSpecial(Symbol.STANDARD_INPUT, in); LispThread.currentThread().bindSpecial(Symbol.STANDARD_OUTPUT, out); LispThread.currentThread().bindSpecial(Symbol.ERROR_OUTPUT, out); LispThread.currentThread().bindSpecial(Symbol.TERMINAL_IO, ioStream); LispThread.currentThread().bindSpecial(Symbol.DEBUG_IO, ioStream); LispThread.currentThread().bindSpecial(Symbol.QUERY_IO, ioStream); return fn.execute(); } finally { LispThread.currentThread().resetSpecialBindings(lastSpecialBinding); } } }; } public void disposeOnClose(final Window parent) { parent.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { dispose(); parent.removeWindowListener(this); } }); } public static void main(String[] args) { LispObject repl = null; try { repl = Interpreter.createInstance().eval("#'top-level::top-level-loop"); } catch (Throwable e) { e.printStackTrace(); System.exit(1); // Ok. We haven't done anything useful yet. } final REPLConsole d = new REPLConsole(repl); final JTextComponent txt = new JTextArea(d); d.setupTextComponent(txt); JFrame f = new JFrame(); f.add(new JScrollPane(txt)); d.disposeOnClose(f); f.setDefaultCloseOperation(f.EXIT_ON_CLOSE); f.pack(); f.setVisible(true); } } abcl-src-1.9.0/src/org/armedbear/lisp/jclass_name.java0100644 0000000 0000000 00000007510 14202767264 021344 0ustar000000000 0000000 /* * jclass_name.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### jclass-name class-ref &optional name public final class jclass_name extends Primitive { private jclass_name() { super(Symbol.JCLASS_NAME, "class-ref &optional name", "When called with one argument, returns the name of the Java class\n" + " designated by CLASS-REF. When called with two arguments, tests\n" + " whether CLASS-REF matches NAME."); } // When called with one argument, JCLASS-NAME returns the name of the class // referenced by CLASS-REF. @Override public LispObject execute(LispObject arg) { if (arg instanceof AbstractString) { String s = arg.getStringValue(); try { return new SimpleString((Class.forName(s)).getName()); } catch (ClassNotFoundException e) { // Fall through. } } else if (arg instanceof JavaObject) { Object obj = ((JavaObject)arg).getObject(); if (obj instanceof Class) return new SimpleString(((Class)obj).getName()); // Fall through. } return error(new LispError(arg.princToString() + " does not designate a Java class.")); } // When called with two arguments, JCLASS-NAME tests whether CLASS-REF // matches NAME. @Override public LispObject execute(LispObject first, LispObject second) { String className = null; if (first instanceof AbstractString) { String s = first.getStringValue(); try { className = (Class.forName(s)).getName(); } catch (ClassNotFoundException e) {} } else if (first instanceof JavaObject) { Object obj = ((JavaObject)first).getObject(); if (obj instanceof Class) className = ((Class)obj).getName(); } if (className == null) return error(new LispError(first.princToString() + " does not designate a Java class.")); final AbstractString name = checkString(second); return LispThread.currentThread().setValues(name.getStringValue().equals(className) ? T : NIL, new SimpleString(className)); } private static final Primitive JCLASS_NAME = new jclass_name(); } abcl-src-1.9.0/src/org/armedbear/lisp/jclass_of.java0100644 0000000 0000000 00000006176 14202767264 021037 0ustar000000000 0000000 /* * jclass_of.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### jclass-of object &optional name public final class jclass_of extends Primitive { private jclass_of() { super(Symbol.JCLASS_OF, "object &optional name", "Returns the name of the Java class of OBJECT. If the NAME argument is\n" + " supplied, verifies that OBJECT is an instance of the named class. The name\n" + " of the class or nil is always returned as a second value."); } @Override public LispObject execute(LispObject arg) { final String className; if (arg instanceof AbstractString) className = "java.lang.String"; else if (arg instanceof JavaObject) className = ((JavaObject)arg).getObject().getClass().getName(); else className = null; final LispObject value = (className != null) ? new SimpleString(className) : NIL; return LispThread.currentThread().setValues(value, value); } @Override public LispObject execute(LispObject first, LispObject second) { final String className; if (first instanceof AbstractString) className = "java.lang.String"; else if (first instanceof JavaObject) className = ((JavaObject)first).getObject().getClass().getName(); else className = null; String name = javaString(second); return LispThread.currentThread().setValues(name.equals(className) ? T : NIL, new SimpleString(className)); } private static final Primitive JCLASS_OF = new jclass_of(); } abcl-src-1.9.0/src/org/armedbear/lisp/jmethod_return_type.java0100644 0000000 0000000 00000004572 14202767264 023164 0ustar000000000 0000000 /* * jmethod_return_type.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.lang.reflect.Method; // ### jmethod-return-type method => class public final class jmethod_return_type extends Primitive { private jmethod_return_type() { super(Symbol.JMETHOD_RETURN_TYPE, "method", "Returns a reference to the Class object that represents the formal return type of METHOD."); } @Override public LispObject execute(LispObject arg) { if (arg instanceof JavaObject) { Object method = ((JavaObject)arg).getObject(); if (method instanceof Method) return new JavaObject(((Method)method).getReturnType()); } return error(new LispError(arg.princToString() + " does not designate a Java method.")); } private static final Primitive JMETHOD_RETURN_TYPE = new jmethod_return_type(); } abcl-src-1.9.0/src/org/armedbear/lisp/jvm-class-file.lisp0100644 0000000 0000000 00000212620 14232261063 021714 0ustar000000000 0000000 ;;; jvm-class-file.lisp ;;; ;;; Copyright (C) 2010 Erik Huelsmann ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :jvm) (require '#:compiler-types) #| The general design of the class-file writer is to have generic - human readable - representations of the class being generated during the construction and manipulation phases. After completing the creation/manipulation of the class, all its components will be finalized. This process translates readable (e.g. string) representations to indices to be stored on disc. The only thing to be done after finalization is sending the output to a stream ("writing"). Finalization happens highest-level first. As an example, take a method with exception handlers. The exception handlers are stored as attributes in the class file structure. They are children of the method's Code attribute. In this example, the body of the Code attribute (the higher level) gets finalized before the attributes. The reason to do so is that the exceptions need to refer to labels (offsets) in the Code segment. |# (defun map-primitive-type (type) "Maps a symbolic primitive type name to its Java string representation." (case type (:int "I") (:long "J") (:float "F") (:double "D") (:boolean "Z") (:char "C") (:byte "B") (:short "S") ((nil :void) "V"))) (defun pretty-class (type &optional (default-package "")) (let* ((p-len (1+ (length default-package))) (len (length type)) (cnt (when (< p-len len) (count #\/ type :start p-len))) (type (if (and cnt (= 0 cnt)) (subseq type p-len len) (substitute #\. #\/ type)))) type)) (defun pretty-type (type &optional (default-package "")) (cond ((eql #\I type) "int") ((eql #\J type) "long") ((eql #\F type) "float") ((eql #\D type) "double") ((eql #\Z type) "boolean") ((eql #\C type) "char") ((eql #\B type) "byte") ((eql #\S type) "short") ((eql #\V type) "void") ((stringp type) (pretty-class (subseq type 1 (1- (length type))) default-package)))) #| The `class-name' facility helps to abstract from "this instruction takes a reference" and "this instruction takes a class name". We simply pass the class name around and the instructions themselves know which representation to use. |# (defstruct (jvm-class-name (:conc-name class-) (:constructor %make-jvm-class-name) (:print-object %print-jvm-class-name)) "Used for class identification. The caller should instantiate only one `class-name' per class, as they are used as class identifiers and compared using EQ. Some instructions need a class argument, others need a reference identifier. This class is used to abstract from the difference." name-internal ref array-class ;; cached array class reference ;; keeping a reference to the associated array class allows class ;; name comparisons to be EQ: all classes should exist only once, ) (defun %print-jvm-class-name (name stream) (print-unreadable-object (name stream :type t) (write-string (class-name-internal name) stream))) (defun make-jvm-class-name (name) "Creates a `class-name' structure for the class or interface `name'. `name' should be specified using Java representation, which is converted to 'internal' (JVM) representation by this function." (setf name (substitute #\/ #\. name)) (%make-jvm-class-name :name-internal name :ref (concatenate 'string "L" name ";"))) (defun class-array (class-name) "Returns a class-name representing an array of `class-name'. For multi-dimensional arrays, call this function multiple times, using its own result. This function can be called multiple times on the same `class-name' without violating the 'only one instance' requirement: the returned value is cached and used on successive calls." (unless (class-array-class class-name) ;; Alessio Stalla found by dumping a class file that the JVM uses ;; the same representation (ie '[L;') in CHECKCAST as ;; it does in field references, meaning the class name and class ref ;; are identified by the same string (let ((name-and-ref (concatenate 'string "[" (class-ref class-name)))) (setf (class-array-class class-name) (%make-jvm-class-name :name-internal name-and-ref :ref name-and-ref)))) (class-array-class class-name)) (defmacro define-class-name (symbol java-dotted-name &optional documentation) "Convenience macro to define constants for `class-name' structures, initialized from the `java-dotted-name'." `(defconstant ,symbol (make-jvm-class-name ,java-dotted-name) ,documentation)) (define-class-name +java-class+ "java.lang.Class") (define-class-name +java-object+ "java.lang.Object") (define-class-name +java-string+ "java.lang.String") (define-class-name +java-system+ "java.lang.System") (define-class-name +java-stack-overflow+ "java.lang.StackOverflowError") (define-class-name +java-out-of-memory+ "java.lang.OutOfMemoryError") (define-class-name +java-io-input-stream+ "java.io.InputStream") (define-class-name +java-util-collection+ "java.util.Collection") (define-class-name +lisp-object+ "org.armedbear.lisp.LispObject") (defconstant +lisp-object-array+ (class-array +lisp-object+)) (define-class-name +lisp-simple-string+ "org.armedbear.lisp.SimpleString") (define-class-name +lisp+ "org.armedbear.lisp.Lisp") (define-class-name +lisp-nil+ "org.armedbear.lisp.Nil") (define-class-name +lisp-class+ "org.armedbear.lisp.LispClass") (define-class-name +lisp-symbol+ "org.armedbear.lisp.Symbol") (define-class-name +lisp-thread+ "org.armedbear.lisp.LispThread") (define-class-name +lisp-closure-binding+ "org.armedbear.lisp.ClosureBinding") (defconstant +closure-binding-array+ (class-array +lisp-closure-binding+)) (define-class-name +lisp-integer+ "org.armedbear.lisp.LispInteger") (define-class-name +lisp-fixnum+ "org.armedbear.lisp.Fixnum") (defconstant +lisp-fixnum-array+ (class-array +lisp-fixnum+)) (define-class-name +lisp-bignum+ "org.armedbear.lisp.Bignum") (define-class-name +lisp-single-float+ "org.armedbear.lisp.SingleFloat") (define-class-name +lisp-double-float+ "org.armedbear.lisp.DoubleFloat") (define-class-name +lisp-cons+ "org.armedbear.lisp.Cons") (define-class-name +lisp-load+ "org.armedbear.lisp.Load") (define-class-name +lisp-character+ "org.armedbear.lisp.LispCharacter") (defconstant +lisp-character-array+ (class-array +lisp-character+)) (define-class-name +lisp-structure-object+ "org.armedbear.lisp.StructureObject") (define-class-name +lisp-simple-vector+ "org.armedbear.lisp.SimpleVector") (define-class-name +lisp-abstract-string+ "org.armedbear.lisp.AbstractString") (define-class-name +lisp-abstract-vector+ "org.armedbear.lisp.AbstractVector") (define-class-name +lisp-abstract-bit-vector+ "org.armedbear.lisp.AbstractBitVector") (define-class-name +lisp-environment+ "org.armedbear.lisp.Environment") (define-class-name +lisp-special-binding+ "org.armedbear.lisp.SpecialBinding") (define-class-name +lisp-special-bindings-mark+ "org.armedbear.lisp.SpecialBindingsMark") (define-class-name +lisp-throw+ "org.armedbear.lisp.Throw") (define-class-name +lisp-return+ "org.armedbear.lisp.Return") (define-class-name +lisp-go+ "org.armedbear.lisp.Go") (define-class-name +lisp-primitive+ "org.armedbear.lisp.Primitive") (define-class-name +lisp-compiled-primitive+ "org.armedbear.lisp.CompiledPrimitive") (define-class-name +lisp-eql-hash-table+ "org.armedbear.lisp.EqlHashTable") (define-class-name +lisp-hash-table+ "org.armedbear.lisp.HashTable") (define-class-name +lisp-package+ "org.armedbear.lisp.Package") (define-class-name +lisp-readtable+ "org.armedbear.lisp.Readtable") (define-class-name +lisp-stream+ "org.armedbear.lisp.Stream") (define-class-name +lisp-operator+ "org.armedbear.lisp.Operator") (define-class-name +lisp-closure+ "org.armedbear.lisp.Closure") (define-class-name +lisp-compiled-closure+ "org.armedbear.lisp.CompiledClosure") (define-class-name +argument-list-processor+ "org.armedbear.lisp.ArgumentListProcessor") (define-class-name +alp-required-parameter+ "org.armedbear.lisp.ArgumentListProcessor$RequiredParam") (define-class-name +alp-optional-parameter+ "org.armedbear.lisp.ArgumentListProcessor$OptionalParam") (define-class-name +alp-keyword-parameter+ "org.armedbear.lisp.ArgumentListProcessor$KeywordParam") #| Lisp-side descriptor representation: - list: a list starting with a method return value, followed by the argument types - keyword: the primitive type associated with that keyword - class-name structure instance: the class-ref value The latter two can be converted to a Java representation using the `internal-field-ref' function, the former is to be fed to `descriptor'. |# (defun internal-field-type (field-type) "Returns a string containing the JVM-internal representation of `field-type', which should either be a symbol identifying a primitive type, or a `class-name' structure identifying a class or interface." (if (symbolp field-type) (map-primitive-type field-type) (class-name-internal field-type))) (defun internal-field-ref (field-type) "Returns a string containing the JVM-internal representation of a reference to `field-type', which should either be a symbol identifying a primitive type, or a `class-name' structure identifying a class or interface." (if (symbolp field-type) (map-primitive-type field-type) (class-ref field-type))) (defun descriptor (return-type &rest argument-types) "Returns a string describing the `return-type' and `argument-types' in JVM-internal representation." (let* ((arg-strings (mapcar #'internal-field-ref argument-types)) (ret-string (internal-field-ref return-type)) (size (+ 2 (reduce #'+ arg-strings :key #'length :initial-value (length ret-string)))) (str (make-array size :fill-pointer 0 :element-type 'character))) (with-output-to-string (s str) (princ #\( s) (dolist (arg-string arg-strings) (princ arg-string s)) (princ #\) s) (princ ret-string s)) str) ;; (format nil "(~{~A~})~A" ;; (internal-field-ref return-type)) ) (defun descriptor-stack-effect (return-type &rest argument-types) "Returns the effect on the stack position of the `argument-types' and `return-type' of a method call. If the method consumes an implicit `this' argument, this function does not take that effect into account." (flet ((type-stack-effect (arg) (case arg ((:long :double) 2) ((nil :void) 0) (otherwise 1)))) (+ (reduce #'- argument-types :key #'type-stack-effect :initial-value 0) (type-stack-effect return-type)))) (defstruct pool ;; `index' contains the index of the last allocated slot (0 == empty) ;; "A constant pool entry is considered valid if it has ;; an index greater than 0 (zero) and less than pool-count" (index 0) entries-list ;; the entries hash stores raw values, except in case of string and ;; utf8, because both are string values in which case a two-element ;; list - containing the tag and the value - is used (entries (make-hash-table :test #'equal :size 2048 :rehash-size 2.0))) (defun matching-index-p (entry index) (eql (constant-index entry) index)) (defun find-pool-entry (pool item &key (test #'matching-index-p)) (find-if (lambda (x) (funcall test x item)) (pool-entries-list pool))) (defstruct constant "Structure to be included in all constant sub-types." tag index) (defgeneric print-pool-constant (pool entry stream &key &allow-other-keys) (:method (pool (entry t) stream &key) (print-object entry stream))) (defmethod print-pool-constant :around (pool entry stream &key recursive) (cond ((and (null *print-readably*) (null *print-escape*) (null recursive)) (princ #\# stream) (princ (constant-index entry) stream) (princ #\Space stream) (princ #\< stream) (call-next-method) (princ #\> stream)) (t (call-next-method)))) (defparameter +constant-type-map+ '((:class 7 1) (:field-ref 9 1) (:method-ref 10 1) ;; (:interface-method-ref 11) (:string 8 1) (:integer 3 1) (:float 4 1) (:long 5 2) (:double 6 2) (:name-and-type 12 1) (:utf8 1 1))) (defstruct (constant-class (:constructor make-constant-class (index name-index)) (:include constant (tag 7))) "Structure holding information on a 'class' type item in the constant pool." name-index) (defmethod print-pool-constant (pool (entry constant-class) stream &key recursive package) (cond ((and (null *print-escape*) (null *print-readably*)) ;; human readable (unless recursive (princ "Class " stream)) (princ (pretty-class (constant-utf8-value (find-pool-entry pool (constant-class-name-index entry))) package) stream)) (t ;; READable (call-next-method)))) (defstruct (constant-member-ref (:constructor %make-constant-member-ref (tag index class-index name/type-index)) (:include constant)) "Structure holding information on a member reference type item (a field, method or interface method reference) in the constant pool." class-index name/type-index) (defmethod print-pool-constant (pool (entry constant-member-ref) stream &key recursive package) (cond ((and (null *print-escape*) (null *print-readably*)) ;; human readable (unless recursive (princ (case (constant-member-ref-tag entry) (9 "Field ") (10 "Method ") (11 "Interface method ")) stream)) (let ((name-prefix (with-output-to-string (s) (print-pool-constant pool (find-pool-entry pool (constant-member-ref-class-index entry)) s :recursive t :package package) (princ #\. s)))) (print-pool-constant pool (find-pool-entry pool (constant-member-ref-name/type-index entry)) stream :name-prefix name-prefix :recursive t :package package))) (t ;; READable (call-next-method)))) (declaim (inline make-constant-field-ref make-constant-method-ref make-constant-interface-method-ref)) (defun make-constant-field-ref (index class-index name/type-index) "Creates a `constant-member-ref' instance containing a field reference." (%make-constant-member-ref 9 index class-index name/type-index)) (defun make-constant-method-ref (index class-index name/type-index) "Creates a `constant-member-ref' instance containing a method reference." (%make-constant-member-ref 10 index class-index name/type-index)) (defun make-constant-interface-method-ref (index class-index name/type-index) "Creates a `constant-member-ref' instance containing an interface-method reference." (%make-constant-member-ref 11 index class-index name/type-index)) (defstruct (constant-string (:constructor make-constant-string (index value-index)) (:include constant (tag 8))) "Structure holding information on a 'string' type item in the constant pool." value-index) (defmethod print-pool-constant (pool (entry constant-string) stream &key recursive) (cond ((and (null *print-readably*) (null *print-escape*)) (unless recursive (princ "String " stream)) (princ #\" stream) (print-pool-constant pool (find-pool-entry pool (constant-string-value-index entry)) stream :recursive t) (princ #\" stream)) (t (call-next-method)))) (defstruct (constant-float/int (:constructor %make-constant-float/int (tag index value)) (:include constant)) "Structure holding information on a 'float' or 'integer' type item in the constant pool." value) (defmethod print-pool-constant (pool (entry constant-float/int) stream &key recursive) (cond ((and (null *print-escape*) (null *print-readably*)) (unless recursive (princ (case (constant-tag entry) (3 "int ") (4 "float ")) stream)) (princ (constant-float/int-value entry) stream)) (t (call-next-method)))) (declaim (inline make-constant-float make-constant-int)) (defun make-constant-float (index value) "Creates a `constant-float/int' structure instance containing a float." (%make-constant-float/int 4 index value)) (defun make-constant-int (index value) "Creates a `constant-float/int' structure instance containing an int." (%make-constant-float/int 3 index value)) (defstruct (constant-double/long (:constructor %make-constant-double/long (tag index value)) (:include constant)) "Structure holding information on a 'double' or 'long' type item in the constant pool." value) (defmethod print-pool-constant (pool (entry constant-double/long) stream &key recursive) (cond ((and (null *print-escape*) (null *print-readably*)) (unless recursive (princ (case (constant-tag entry) (5 "long ") (6 "double ")) stream)) (princ (constant-double/long-value entry) stream)) (t (call-next-method)))) (declaim (inline make-constant-double make-constant-float)) (defun make-constant-double (index value) "Creates a `constant-double/long' structure instance containing a double." (%make-constant-double/long 6 index value)) (defun make-constant-long (index value) "Creates a `constant-double/long' structure instance containing a long." (%make-constant-double/long 5 index value)) (defstruct (constant-name/type (:constructor make-constant-name/type (index name-index descriptor-index)) (:include constant (tag 12))) "Structure holding information on a 'name-and-type' type item in the constant pool; this type of element is used by 'member-ref' type items." name-index descriptor-index) (defun parse-descriptor (descriptor) (let (arguments method-descriptor-p (index 0)) (when (eql (aref descriptor 0) #\() ;; parse the arguments here... (assert (find #\) descriptor)) (setf method-descriptor-p t) (loop until (eql (aref descriptor index) #\)) do (incf index) if (find (aref descriptor index) "IJFDZCBSV") do (push (aref descriptor index) arguments) if (eql (aref descriptor index) #\L) do (loop for i upfrom index until (eql (aref descriptor i) #\;) finally (push (subseq descriptor index (1+ i)) arguments) finally (setf index i)) finally (incf index))) (values (let ((return-value (subseq descriptor index))) (if (= (length return-value) 1) (aref return-value 0) return-value)) (nreverse arguments) method-descriptor-p))) (defmethod print-pool-constant (pool (entry constant-name/type) stream &key name-prefix package) (cond ((and (null *print-readably*) (null *print-escape*)) (multiple-value-bind (type arguments method-descriptor-p) (let ((entry (find-pool-entry pool (constant-name/type-descriptor-index entry)))) (if (constant-utf8-p entry) (parse-descriptor (constant-utf8-value entry)) (class-ref entry))) (princ (pretty-type type package) stream) (princ #\Space stream) (when name-prefix (princ name-prefix stream)) (print-pool-constant pool (find-pool-entry pool (constant-name/type-name-index entry)) stream :recursive t) (when method-descriptor-p (format stream "(~{~A~^,~})" (mapcar (lambda (x) (pretty-type x package)) arguments))))) (t (call-next-method)))) (defstruct (constant-utf8 (:constructor make-constant-utf8 (index value)) (:include constant (tag 1))) "Structure holding information on a 'utf8' type item in the constant pool; This type of item is used for text representation of identifiers and string contents." value) (defun pool-add-class (pool class) "Returns the index of the constant-pool class item for `class'. `class' must be an instance of `class-name' or a string (which will be converted to a `class-name')." (let ((class (if (jvm-class-name-p class) class (make-jvm-class-name class)))) (let ((entry (gethash class (pool-entries pool)))) (unless entry (let ((utf8 (pool-add-utf8 pool (class-name-internal class)))) (setf entry (make-constant-class (incf (pool-index pool)) utf8) (gethash class (pool-entries pool)) entry)) (push entry (pool-entries-list pool))) (constant-index entry)))) (defun pool-add-field-ref (pool class name type) "Returns the index of the constant-pool item which denotes a reference to the `name' field of the `class', being of `type'. `class' should be an instance of `class-name'. `name' is a string. `type' is a field-type (see `internal-field-type')" (let ((entry (gethash (acons name type class) (pool-entries pool)))) (unless entry (let ((c (pool-add-class pool class)) (n/t (pool-add-name/type pool name type))) (setf entry (make-constant-field-ref (incf (pool-index pool)) c n/t) (gethash (acons name type class) (pool-entries pool)) entry)) (push entry (pool-entries-list pool))) (constant-index entry))) (defun pool-add-method-ref (pool class name type) "Returns the index of the constant-pool item which denotes a reference to the method with `name' in `class', which is of `type'. Here, `type' is a method descriptor, which defines the argument types and return type. `class' is an instance of `class-name'." (let ((entry (gethash (acons name type class) (pool-entries pool)))) (unless entry (let ((c (pool-add-class pool class)) (n/t (pool-add-name/type pool name type))) (setf entry (make-constant-method-ref (incf (pool-index pool)) c n/t) (gethash (acons name type class) (pool-entries pool)) entry)) (push entry (pool-entries-list pool))) (constant-index entry))) (defun pool-add-interface-method-ref (pool class name type) "Returns the index of the constant-pool item which denotes a reference to the method `name' in the interface `class', which is of `type'. See `pool-add-method-ref' for remarks." (let ((entry (gethash (acons name type class) (pool-entries pool)))) (unless entry (let ((c (pool-add-class pool class)) (n/t (pool-add-name/type pool name type))) (setf entry (make-constant-interface-method-ref (incf (pool-index pool)) c n/t) (gethash (acons name type class) (pool-entries pool)) entry)) (push entry (pool-entries-list pool))) (constant-index entry))) (defun pool-add-string (pool string) "Returns the index of the constant-pool item denoting the string." (let ((entry (gethash (cons 8 string) ;; 8 == string-tag (pool-entries pool)))) (unless entry (let ((utf8 (pool-add-utf8 pool string))) (setf entry (make-constant-string (incf (pool-index pool)) utf8) (gethash (cons 8 string) (pool-entries pool)) entry)) (push entry (pool-entries-list pool))) (constant-index entry))) (defun pool-add-int (pool int) "Returns the index of the constant-pool item denoting the int." (let ((entry (gethash (cons 3 int) (pool-entries pool)))) (unless entry (setf entry (make-constant-int (incf (pool-index pool)) int) (gethash (cons 3 int) (pool-entries pool)) entry) (push entry (pool-entries-list pool))) (constant-index entry))) (defun pool-add-float (pool float) "Returns the index of the constant-pool item denoting the float." (let ((entry (gethash (cons 4 float) (pool-entries pool)))) (unless entry (setf entry (make-constant-float (incf (pool-index pool)) (sys::%float-bits float)) (gethash (cons 4 float) (pool-entries pool)) entry) (push entry (pool-entries-list pool))) (constant-index entry))) (defun pool-add-long (pool long) "Returns the index of the constant-pool item denoting the long." (let ((entry (gethash (cons 5 long) (pool-entries pool)))) (unless entry (setf entry (make-constant-long (incf (pool-index pool)) long) (gethash (cons 5 long) (pool-entries pool)) entry) (push entry (pool-entries-list pool)) (incf (pool-index pool))) ;; double index increase; long takes 2 slots (constant-index entry))) (defun pool-add-double (pool double) "Returns the index of the constant-pool item denoting the double." (let ((entry (gethash (cons 6 double) (pool-entries pool)))) (unless entry (setf entry (make-constant-double (incf (pool-index pool)) (sys::%float-bits double)) (gethash (cons 6 double) (pool-entries pool)) entry) (push entry (pool-entries-list pool)) (incf (pool-index pool))) ;; double index increase; 'double' takes 2 slots (constant-index entry))) (defun pool-add-name/type (pool name type) "Returns the index of the constant-pool item denoting the name/type identifier." (let ((entry (gethash (cons name type) (pool-entries pool))) (internal-type (if (listp type) (apply #'descriptor type) (internal-field-ref type)))) (unless entry (let ((n (pool-add-utf8 pool name)) (i-t (pool-add-utf8 pool internal-type))) (setf entry (make-constant-name/type (incf (pool-index pool)) n i-t) (gethash (cons name type) (pool-entries pool)) entry)) (push entry (pool-entries-list pool))) (constant-index entry))) (defun pool-add-utf8 (pool utf8-as-string) "Returns the index of the textual value that will be stored in the class file as UTF-8 encoded data." (let ((entry (gethash (cons 11 utf8-as-string) ;; 11 == utf8 (pool-entries pool)))) (unless entry (setf entry (make-constant-utf8 (incf (pool-index pool)) utf8-as-string) (gethash (cons 11 utf8-as-string) (pool-entries pool)) entry) (push entry (pool-entries-list pool))) (constant-index entry))) (defstruct (class-file (:constructor make-class-file (class superclass access-flags))) "Holds the components of a class file." (constants (make-pool)) access-flags class superclass interfaces fields methods attributes) (defun make-class-interface-file (class) "Create the components of a class file representing a public Java interface." (make-class-file class +java-object+ '(:public :abstract :interface))) (defun class-add-field (class field) "Adds a `field' created by `make-field'." (push field (class-file-fields class))) (defun class-field (class name) "Finds a field by name." ;; ### strictly speaking, a field is uniquely ;; identified by its name and type, not by the name alone. (find name (class-file-fields class) :test #'string= :key #'field-name)) (defun class-add-method (class method) "Adds a `method' to `class'; the method must have been created using `make-jvm-method'." (push method (class-file-methods class))) (defun class-methods-by-name (class name) "Returns all methods which have `name'." (remove (map-method-name name) (class-file-methods class) :test-not #'string= :key #'method-name)) (defun class-method (class name return &rest args) "Return the method which is (uniquely) identified by its name AND descriptor." (let ((return-and-args (cons return args)) (name (map-method-name name))) (find-if #'(lambda (c) (and (string= (method-name c) name) (equal (method-descriptor c) return-and-args))) (class-file-methods class)))) (defun class-remove-method (class method) (setf (class-file-methods class) (remove method (class-file-methods class))) method) (defun class-add-attribute (class attribute) "Adds `attribute' to the class; attributes must be instances of structure classes which include the `attribute' structure class." (push attribute (class-file-attributes class))) (defun class-add-superinterface (class interface) "Adds the java-class-name contained in `interface' as a superinterface of the `class'. For a class that represents an object, the requirements in `interface' must then be implemented in the class. For a class that represents an interface, the `interface' imposes additional requirements to the classes which implement this class." (push interface (class-file-interfaces class))) (defun class-attribute (class name) "Returns the attribute which is named `name'." (find name (class-file-attributes class) :test #'string= :key #'attribute-name)) (defun finalize-interfaces (class) "Finalize the interfaces for `class'. Interface finalization first ensures that all the classes referenced by the interfaces members exist in the pool. Then, it destructively modfies the interfaces members with a list of the references to the corresponding pool indices." (let ((interface-refs nil)) (dolist (interface (class-file-interfaces class)) (push (pool-add-class (class-file-constants class) interface) interface-refs)) (setf (class-file-interfaces class) interface-refs))) (defun finalize-class-file (class) "Transforms the representation of the class-file from one which allows easy modification to one which works best for serialization. The class can't be modified after finalization." ;; constant pool contains constants finalized on addition; ;; no need for additional finalization (setf (class-file-access-flags class) (map-flags (class-file-access-flags class))) (setf (class-file-superclass class) (pool-add-class (class-file-constants class) (class-file-superclass class)) (class-file-class class) (pool-add-class (class-file-constants class) (class-file-class class))) (finalize-interfaces class) (dolist (field (class-file-fields class)) (finalize-field field class)) (dolist (method (class-file-methods class)) (finalize-method method class)) ;; top-level attributes (no parent attributes to refer to) (finalize-attributes (class-file-attributes class) nil class)) (declaim (inline write-u1 write-u2 write-u4 write-s4)) (defun write-u1 (n stream) (declare (optimize speed)) (declare (type (unsigned-byte 8) n)) (declare (type stream stream)) (write-8-bits n stream)) (defknown write-u2 (t t) t) (defun write-u2 (n stream) (declare (optimize speed)) (declare (type (unsigned-byte 16) n)) (declare (type stream stream)) (write-8-bits (logand (ash n -8) #xFF) stream) (write-8-bits (logand n #xFF) stream)) (defknown write-u4 (integer stream) t) (defun write-u4 (n stream) (declare (optimize speed)) (declare (type (unsigned-byte 32) n)) (write-u2 (logand (ash n -16) #xFFFF) stream) (write-u2 (logand n #xFFFF) stream)) (declaim (ftype (function (t t) t) write-s4)) (defun write-s4 (n stream) (declare (optimize speed)) (cond ((minusp n) (write-u4 (1+ (logxor (- n) #xFFFFFFFF)) stream)) (t (write-u4 n stream)))) (declaim (ftype (function (t t t) t) write-ascii)) (defun write-ascii (string length stream) (declare (type string string)) (declare (type (unsigned-byte 16) length)) (declare (type stream stream)) (write-u2 length stream) (dotimes (i length) (declare (type (unsigned-byte 16) i)) (write-8-bits (char-code (char string i)) stream))) (declaim (ftype (function (t t) t) write-utf8)) (defun write-utf8 (string stream) (declare (optimize speed)) (declare (type string string)) (declare (type stream stream)) (let ((length (length string)) (must-convert nil)) (declare (type fixnum length)) (dotimes (i length) (declare (type fixnum i)) (unless (< 0 (char-code (char string i)) #x80) (setf must-convert t) (return))) (if must-convert (let ((octets (make-array (* length 2) :element-type '(unsigned-byte 8) :adjustable t :fill-pointer 0))) (declare (type (vector (unsigned-byte 8)) octets)) (dotimes (i length) (declare (type fixnum i)) (let* ((c (char string i)) (n (char-code c))) (cond ((zerop n) (vector-push-extend #xC0 octets) (vector-push-extend #x80 octets)) ((< 0 n #x80) (vector-push-extend n octets)) (t (let ((char-octets (char-to-utf8 c))) (dotimes (j (length char-octets)) (declare (type fixnum j)) (vector-push-extend (svref char-octets j) octets))))))) (write-u2 (length octets) stream) (dotimes (i (length octets)) (declare (type fixnum i)) (write-8-bits (aref octets i) stream))) (write-ascii string length stream)))) (defun write-class-file (class stream) "Serializes `class' to `stream', after it has been finalized." ;; header (write-u4 #xCAFEBABE stream) (write-u2 0 stream) (write-u2 49 stream) ;; our methods use class literals ;; which require a high enough class file format ;; we used to have 45, but the LDC instruction doesn't support ;; class literals in that version... (49 == Java 1.5) ;; constants pool (write-constants (class-file-constants class) stream) ;; flags (write-u2 (class-file-access-flags class) stream) ;; class name (write-u2 (class-file-class class) stream) ;; superclass (write-u2 (class-file-superclass class) stream) ;; interfaces (if (class-file-interfaces class) (progn (write-u2 (length (class-file-interfaces class)) stream) (dolist (interface-ref (class-file-interfaces class)) (write-u2 interface-ref stream))) (write-u2 0 stream)) ;; fields (write-u2 (length (class-file-fields class)) stream) (dolist (field (class-file-fields class)) (write-field field stream)) ;; methods (write-u2 (length (class-file-methods class)) stream) (dolist (method (class-file-methods class)) (write-method method stream)) ;; attributes (write-attributes (class-file-attributes class) stream)) (defvar *jvm-class-debug-pool* nil "When bound to a non-NIL value, enables output to *standard-output* to allow debugging output of the constant section of the class file.") (defun write-constants (constants stream) "Writes the constant section given in `constants' to the class file `stream'." (let ((pool-index 0)) (write-u2 (1+ (pool-index constants)) stream) (when *jvm-class-debug-pool* (sys::%format t "pool count ~A~%" (pool-index constants))) (dolist (entry (reverse (pool-entries-list constants))) (incf pool-index) (let ((tag (constant-tag entry))) (when *jvm-class-debug-pool* (print-entry entry t)) (write-u1 tag stream) (case tag (1 ; UTF8 (write-utf8 (constant-utf8-value entry) stream)) ((3 4) ; float int (write-u4 (constant-float/int-value entry) stream)) ((5 6) ; long double (write-u4 (logand (ash (constant-double/long-value entry) -32) #xFFFFffff) stream) (write-u4 (logand (constant-double/long-value entry) #xFFFFffff) stream)) ((9 10 11) ; fieldref methodref InterfaceMethodref (write-u2 (constant-member-ref-class-index entry) stream) (write-u2 (constant-member-ref-name/type-index entry) stream)) (12 ; nameAndType (write-u2 (constant-name/type-name-index entry) stream) (write-u2 (constant-name/type-descriptor-index entry) stream)) (7 ; class (write-u2 (constant-class-name-index entry) stream)) (8 ; string (write-u2 (constant-string-value-index entry) stream)) (t (error "write-constant-pool-entry unhandled tag ~D~%" tag))))))) (defun print-entry (entry stream) "Debugging helper to print the content of a constant-pool entry." (let ((tag (constant-tag entry)) (index (constant-index entry))) (sys::%format stream "pool element ~a, tag ~a, " index tag) (case tag (1 (sys::%format t "utf8: ~a~%" (constant-utf8-value entry))) ((3 4) (sys::%format t "f/i: ~a~%" (constant-float/int-value entry))) ((5 6) (sys::%format t "d/l: ~a~%" (constant-double/long-value entry))) ((9 10 11) (sys::%format t "ref: ~a,~a~%" (constant-member-ref-class-index entry) (constant-member-ref-name/type-index entry))) (12 (sys::%format t "n/t: ~a,~a~%" (constant-name/type-name-index entry) (constant-name/type-descriptor-index entry))) (7 (sys::%format t "cls: ~a~%" (constant-class-name-index entry))) (8 (sys::%format t "str: ~a~%" (constant-string-value-index entry)))))) (defmethod print-pool-constant (pool (entry constant-utf8) stream &key) (if (and (null *print-escape*) (null *print-readably*)) (princ (constant-utf8-value entry) stream) (call-next-method))) #| ABCL doesn't use interfaces, so don't implement it here at this time (defstruct interface) |# (defparameter +access-flags-map+ '((:public #x0001) (:private #x0002) (:protected #x0004) (:static #x0008) (:final #x0010) (:volatile #x0040) (:synchronized #x0020) (:transient #x0080) (:native #x0100) (:interface #x0200) (:abstract #x0400) (:strict #x0800)) "List of keyword symbols used for human readable representation of (access) flags and their binary values.") (defun map-flags (flags) "Calculates the bitmap of the flags from a list of symbols." (reduce #'(lambda (y x) (logior (or (when (member (car x) flags) (second x)) 0) y)) +access-flags-map+ :initial-value 0)) (defstruct (field (:constructor %make-field)) "Holds information on the properties of fields in the class(-file)." access-flags name descriptor attributes) (defun make-field (name type &key (flags '(:public))) "Creates a field for addition to a class file." (%make-field :access-flags flags :name name :descriptor type)) (defun field-add-attribute (field attribute) "Adds an attribute to a field." (push attribute (field-attributes field))) (defun field-attribute (field name) "Retrieves an attribute named `name' of `field'. Returns NIL if the attribute isn't found." (find name (field-attributes field) :test #'string= :key #'attribute-name)) (defun finalize-field (field class) "Prepares `field' for serialization." (let ((pool (class-file-constants class))) (setf (field-access-flags field) (map-flags (field-access-flags field)) (field-descriptor field) (pool-add-utf8 pool (internal-field-ref (field-descriptor field))) (field-name field) (pool-add-utf8 pool (field-name field)))) (finalize-attributes (field-attributes field) nil class)) (defun write-field (field stream) "Writes classfile representation of `field' to `stream'." (write-u2 (field-access-flags field) stream) (write-u2 (field-name field) stream) (write-u2 (field-descriptor field) stream) (write-attributes (field-attributes field) stream)) (defstruct (jvm-method (:constructor %make-jvm-method) (:conc-name method-)) "Holds information on the properties of methods in the class(-file)." access-flags name descriptor attributes) (defun map-method-name (name) "Methods should be identified by strings containing their names, or, be one of two keyword identifiers to identify special methods: * :static-initializer * :constructor " (cond ((eq name :static-initializer) "") ((eq name :constructor) "") (t name))) (defun make-jvm-method (name return args &key (flags '(:public))) "Creates a method for addition to a class file." (%make-jvm-method :descriptor (cons return args) :access-flags flags :name (map-method-name name))) (defun method-add-attribute (method attribute) "Add `attribute' to the list of attributes of `method', returning `attribute'." (push attribute (method-attributes method)) attribute) (defun method-add-code (method &optional (optimize t)) "Creates an (empty) 'Code' attribute for the method, returning the created attribute." (method-add-attribute method (make-code-attribute (+ (length (cdr (method-descriptor method))) (if (member :static (method-access-flags method)) 0 1)) ;; 1 == implicit 'this' optimize))) (defun method-ensure-code (method &optional (optimize t)) "Ensures the existence of a 'Code' attribute for the method, returning the attribute." (let ((code (method-attribute method "Code"))) (if (null code) (method-add-code method optimize) code))) (defun method-attribute (method name) "Returns the first attribute of `method' with `name'." (find name (method-attributes method) :test #'string= :key #'attribute-name)) (defun finalize-method (method class) "Prepares `method' for serialization." (let ((pool (class-file-constants class))) (setf (method-access-flags method) (map-flags (method-access-flags method)) (method-descriptor method) (pool-add-utf8 pool (apply #'descriptor (method-descriptor method))) (method-name method) (pool-add-utf8 pool (method-name method)))) (finalize-attributes (method-attributes method) nil class)) (defun write-method (method stream) "Write class file representation of `method' to `stream'." (write-u2 (method-access-flags method) stream) (write-u2 (method-name method) stream) ;;(sys::%format t "method-name: ~a~%" (method-name method)) (write-u2 (method-descriptor method) stream) (write-attributes (method-attributes method) stream)) (defstruct attribute "Parent attribute structure to be included into other attributes, mainly to define common fields. Having common fields allows common driver code for finalizing and serializing attributes." name ;; not in the class file: finalizer ;; function of 3 arguments: the attribute, parent and class-file writer ;; function of 2 arguments: the attribute and the output stream ) (defun finalize-attributes (attributes att class) "Prepare `attributes' (a list) of attribute `att' list for serialization." (dolist (attribute attributes) ;; assure header: make sure 'name' is in the pool (setf (attribute-name attribute) (pool-add-utf8 (class-file-constants class) (attribute-name attribute))) ;; we're saving "root" attributes: attributes which have no parent (funcall (attribute-finalizer attribute) attribute att class))) (defun write-attributes (attributes stream) "Writes the `attributes' to `stream'." (write-u2 (length attributes) stream) (dolist (attribute attributes) (write-u2 (attribute-name attribute) stream) ;; set up a bulk catcher for (UNSIGNED-BYTE 8) ;; since we need to know the attribute length (excluding the header) (let ((local-stream (sys::%make-byte-array-output-stream))) (funcall (attribute-writer attribute) attribute local-stream) (let ((array (sys::%get-output-stream-array local-stream))) (write-u4 (length array) stream) (write-sequence array stream))))) (defstruct (code-attribute (:conc-name code-) (:include attribute (name "Code") (finalizer #'finalize-code-attribute) (writer #'write-code-attribute)) (:constructor %make-code-attribute)) "The attribute containing the actual JVM byte code; an attribute of a method." max-stack max-locals code exception-handlers attributes ;; fields not in the class file start here ;; labels contains offsets into the code array after it's finalized labels ;; an alist optimize (current-local 0)) ;; used for handling nested WITH-CODE-TO-METHOD blocks (defun code-label-offset (code label) "Retrieves the `label' offset within a `code' attribute after the attribute has been finalized." (cdr (assoc label (code-labels code)))) (defun (setf code-label-offset) (offset code label) "Sets the `label' offset within a `code' attribute after the attribute has been finalized." (setf (code-labels code) (acons label offset (code-labels code)))) (defun finalize-code-attribute (code parent class) "Prepares the `code' attribute for serialization, within method `parent'." (let* ((handlers (code-exception-handlers code)) (c (finalize-code (code-code code) (nconc (mapcar #'exception-start-pc handlers) (mapcar #'exception-end-pc handlers) (mapcar #'exception-handler-pc handlers)) (code-optimize code) (class-file-constants class)))) (invoke-callbacks :code-finalized class parent (coerce c 'list) handlers) (unless (code-max-stack code) (setf (code-max-stack code) (analyze-stack c (mapcar #'exception-handler-pc handlers)))) (unless (code-max-locals code) (setf (code-max-locals code) (analyze-locals code))) (multiple-value-bind (c labels) (code-bytes c) (assert (< 0 (length c) 65536)) (setf (code-code code) c (code-labels code) labels))) (setf (code-exception-handlers code) (remove-if #'(lambda (h) (eql (code-label-offset code (exception-start-pc h)) (code-label-offset code (exception-end-pc h)))) (code-exception-handlers code))) (dolist (exception (code-exception-handlers code)) (setf (exception-start-pc exception) (code-label-offset code (exception-start-pc exception)) (exception-end-pc exception) (code-label-offset code (exception-end-pc exception)) (exception-handler-pc exception) (code-label-offset code (exception-handler-pc exception)) (exception-catch-type exception) (if (null (exception-catch-type exception)) 0 ;; generic 'catch all' class index number (pool-add-class (class-file-constants class) (exception-catch-type exception))))) (finalize-attributes (code-attributes code) code class)) (defun write-code-attribute (code stream) "Writes the attribute `code' to `stream'." ;;(sys::%format t "max-stack: ~a~%" (code-max-stack code)) (write-u2 (code-max-stack code) stream) ;;(sys::%format t "max-locals: ~a~%" (code-max-locals code)) (write-u2 (code-max-locals code) stream) (let ((code-array (code-code code))) ;;(sys::%format t "length: ~a~%" (length code-array)) (write-u4 (length code-array) stream) (dotimes (i (length code-array)) (write-u1 (svref code-array i) stream))) (write-u2 (length (code-exception-handlers code)) stream) (dolist (exception (reverse (code-exception-handlers code))) ;;(sys::%format t "start-pc: ~a~%" (exception-start-pc exception)) (write-u2 (exception-start-pc exception) stream) ;;(sys::%format t "end-pc: ~a~%" (exception-end-pc exception)) (write-u2 (exception-end-pc exception) stream) ;;(sys::%format t "handler-pc: ~a~%" (exception-handler-pc exception)) (write-u2 (exception-handler-pc exception) stream) (write-u2 (exception-catch-type exception) stream)) (write-attributes (code-attributes code) stream)) (defun make-code-attribute (arg-count &optional optimize) "Creates an empty 'Code' attribute for a method which takes `arg-count` parameters, including the implicit `this` parameter." (%make-code-attribute :max-locals arg-count :optimize optimize)) (defun code-add-attribute (code attribute) "Adds `attribute' to `code', returning `attribute'." (push attribute (code-attributes code)) attribute) (defun code-attribute (code name) "Returns an attribute of `code' identified by `name'." (find name (code-attributes code) :test #'string= :key #'attribute-name)) (defun code-add-exception-handler (code start end handler type) "Adds an exception handler to `code' protecting the region from labels `start' to `end' (inclusive) from exception `type' - where a value of NIL indicates all types. Upon an exception of the given type, control is transferred to label `handler'." (push (make-exception :start-pc start :end-pc end :handler-pc handler :catch-type type) (code-exception-handlers code))) (defstruct exception "Exception handler information. After finalization, the fields contain offsets instead of labels." start-pc ;; label target end-pc ;; label target handler-pc ;; label target catch-type ;; a string for a specific type, or NIL for all ) (defstruct (constant-value-attribute (:conc-name constant-value-) (:include attribute (name "ConstantValue") ;; finalizer ;; writer )) "An attribute of a field of primitive type. " ;;; ### TODO ) (defstruct (checked-exceptions-attribute (:conc-name checked-) (:include attribute (name "Exceptions") (finalizer #'finalize-checked-exceptions) (writer #'write-checked-exceptions))) "An attribute of `code-attribute', " table ;; a list of checked classes corresponding to Java's 'throws' ) (defun finalize-checked-exceptions (checked-exceptions code class) (declare (ignorable code class)) "Prepare `checked-exceptions' for serialization." (setf (checked-table checked-exceptions) (mapcar #'(lambda (exception) (pool-add-class (class-file-constants class) exception)) (checked-table checked-exceptions)))) (defun write-checked-exceptions (checked-exceptions stream) "Write `checked-exceptions' to `stream' in class file representation." (write-u2 (length (checked-table checked-exceptions)) stream) (dolist (exception (reverse (checked-table checked-exceptions))) (write-u2 exception stream))) ;; Can't be used yet: serialization missing (defstruct (deprecated-attribute (:include attribute (name "Deprecated") (finalizer (constantly nil)) (writer (constantly nil)))) ;; finalizer and writer need to do nothing: Deprecated attributes are empty "An attribute of a class file, field or method, indicating the element to which it has been attached has been superseded.") (defvar *current-code-attribute* nil) (defvar *method*) (defun save-code-specials (code) (setf (code-code code) *code* (code-max-locals code) *registers-allocated* (code-current-local code) *register*)) (defun restore-code-specials (code) (setf *code* (code-code code) *registers-allocated* (code-max-locals code) *register* (code-current-local code))) (defmacro with-code-to-method ((class-file method) &body body) (let ((m (gensym)) (c (gensym))) `(progn (when *current-code-attribute* (save-code-specials *current-code-attribute*)) (unwind-protect (let* ((,m ,method) (*method* ,m) (,c (method-ensure-code ,method)) (*pool* (class-file-constants ,class-file)) (*code* (code-code ,c)) (*registers-allocated* (code-max-locals ,c)) (*register* (code-current-local ,c)) (*current-code-attribute* ,c)) (unwind-protect ,@body ;; in case of a RETURN-FROM or GO, save the current state (setf (code-code ,c) *code* (code-current-local ,c) *register* (code-max-locals ,c) *registers-allocated*))) ;; using the same line of reasoning, restore the outer-scope state (when *current-code-attribute* (restore-code-specials *current-code-attribute*)))))) (defstruct (source-file-attribute (:conc-name source-) (:include attribute (name "SourceFile") (finalizer #'finalize-source-file) (writer #'write-source-file))) "An attribute of the class file indicating which source file it was compiled from." filename) (defun finalize-source-file (source-file code class) (declare (ignorable code class)) (setf (source-filename source-file) (pool-add-utf8 (class-file-constants class) (source-filename source-file)))) (defun write-source-file (source-file stream) (write-u2 (source-filename source-file) stream)) (defstruct (synthetic-attribute (:include attribute (name "Synthetic") (finalizer (constantly nil)) (writer (constantly nil)))) ;; finalizer and writer need to do nothing: Synthetic attributes are empty "An attribute of a class file, field or method to mark that it wasn't included in the sources - but was generated artificially.") (defstruct (line-numbers-attribute (:conc-name line-numbers-) (:include attribute (name "LineNumberTable") (finalizer #'finalize-line-numbers) (writer #'write-line-numbers))) "An attribute of `code-attribute', containing a mapping of offsets within the code section to the line numbers in the source file." table ;; a list of line-number structures, in reverse order ) (defstruct line-number start-pc ;; a label, before finalization, or 0 for "start of function" line) (defun finalize-line-numbers (line-numbers code class) (declare (ignorable code class)) (dolist (line-number (line-numbers-table line-numbers)) (unless (zerop (line-number-start-pc line-number)) (setf (line-number-start-pc line-number) (code-label-offset code (line-number-start-pc line-number)))))) (defun write-line-numbers (line-numbers stream) (write-u2 (length (line-numbers-table line-numbers)) stream) (dolist (line-number (reverse (line-numbers-table line-numbers))) (write-u2 (line-number-start-pc line-number) stream) (write-u2 (line-number-line line-number) stream))) (defun line-numbers-add-line (line-numbers start-pc line) (push (make-line-number :start-pc start-pc :line line) (line-numbers-table line-numbers))) (defstruct (local-variables-attribute (:conc-name local-var-) (:include attribute (name "LocalVariableTable") (finalizer #'finalize-local-variables) (writer #'write-local-variables))) "An attribute of the `code-attribute', containing a table of local variable names, their type and their scope of validity." table ;; a list of local-variable structures, in reverse order ) (defstruct (local-variable (:conc-name local-)) start-pc ;; a label, before finalization length ;; a label (at the ending position) before finalization name descriptor index ;; The index of the variable inside the block of locals ) (defun finalize-local-variables (local-variables code class) (dolist (local-variable (local-var-table local-variables)) (setf (local-start-pc local-variable) (code-label-offset code (local-start-pc local-variable)) (local-length local-variable) ;; calculate 'length' from the distance between 2 labels (- (code-label-offset code (local-length local-variable)) (local-start-pc local-variable)) (local-name local-variable) (pool-add-utf8 (class-file-constants class) (local-name local-variable)) (local-descriptor local-variable) (pool-add-utf8 (class-file-constants class) (local-descriptor local-variable))))) (defun write-local-variables (local-variables stream) (write-u2 (length (local-var-table local-variables)) stream) (dolist (local-variable (reverse (local-var-table local-variables))) (write-u2 (local-start-pc local-variable) stream) (write-u2 (local-length local-variable) stream) (write-u2 (local-name local-variable) stream) (write-u2 (local-descriptor local-variable) stream) (write-u2 (local-index local-variable) stream))) ;;Annotations (defstruct (annotations-attribute (:conc-name annotations-) (:include attribute ;;Name is to be provided by subtypes (finalizer #'finalize-annotations) (writer #'write-annotations))) "An attribute of a class, method or field, containing a list of annotations. This structure serves as the abstract supertype of concrete annotations types." list ;; a list of annotation structures, in reverse order ) (defstruct annotation "Each value of the annotations table represents a single runtime-visible annotation on a program element. The annotation structure has the following format: annotation { u2 type_index; u2 num_element_value_pairs; { u2 element_name_index; element_value value; } element_value_pairs[num_element_value_pairs] }" type elements) (defstruct annotation-element (name "value") tag finalizer writer) (defstruct (primitive-or-string-annotation-element (:include annotation-element (finalizer (lambda (self class) (let ((value (primitive-or-string-annotation-element-value self))) (etypecase value (boolean (setf (annotation-element-tag self) (char-code #\Z) (primitive-or-string-annotation-element-value self) (pool-add-int (class-file-constants class) (if value 1 0)))) (character (setf (annotation-element-tag self) (char-code #\C) (primitive-or-string-annotation-element-value self) (pool-add-int (class-file-constants class) (char-code value)))) (fixnum (setf (annotation-element-tag self) (char-code #\I) (primitive-or-string-annotation-element-value self) (pool-add-int (class-file-constants class) value))) (integer (setf (annotation-element-tag self) (char-code #\J) (primitive-or-string-annotation-element-value self) (pool-add-long (class-file-constants class) value))) (double-float (setf (annotation-element-tag self) (char-code #\D) (primitive-or-string-annotation-element-value self) (pool-add-double (class-file-constants class) value))) (single-float (setf (annotation-element-tag self) (char-code #\F) (primitive-or-string-annotation-element-value self) (pool-add-float (class-file-constants class) value))) (string (setf (annotation-element-tag self) (char-code #\s) (primitive-or-string-annotation-element-value self) (pool-add-utf8 (class-file-constants class) value))))))) (writer (lambda (self stream) (write-u1 (annotation-element-tag self) stream) (write-u2 (primitive-or-string-annotation-element-value self) stream))))) value) (defstruct (enum-value-annotation-element (:include annotation-element (tag (char-code #\e)) (finalizer (lambda (self class) (setf (enum-value-annotation-element-type self) (pool-add-utf8 (class-file-constants class) (enum-value-annotation-element-type self)) ;;Binary name as string (enum-value-annotation-element-value self) (pool-add-utf8 (class-file-constants class) (enum-value-annotation-element-value self))))) (writer (lambda (self stream) (write-u1 (annotation-element-tag self) stream) (write-u2 (enum-value-annotation-element-type self) stream) (write-u2 (enum-value-annotation-element-value self) stream))))) type value) (defstruct (annotation-value-annotation-element (:include annotation-element (tag (char-code #\@)) (finalizer (lambda (self class) (finalize-annotation (annotation-value-annotation-element-value self) class))) (writer (lambda (self stream) (write-u1 (annotation-element-tag self) stream) (write-annotation (annotation-value-annotation-element-value self) stream))))) value) (defstruct (array-annotation-element (:include annotation-element (tag (char-code #\[)) (finalizer (lambda (self class) (dolist (elem (array-annotation-element-values self)) (finalize-annotation-element elem class)))) (writer (lambda (self stream) (write-u1 (annotation-element-tag self) stream) (write-u2 (length (array-annotation-element-values self)) stream) (dolist (elem (array-annotation-element-values self)) (write-annotation-element elem stream)))))) values) ;;In proper order (defstruct (runtime-visible-annotations-attribute (:include annotations-attribute (name "RuntimeVisibleAnnotations"))) "4.8.15 The RuntimeVisibleAnnotations attribute The RuntimeVisibleAnnotations attribute is a variable length attribute in the attributes table of the ClassFile, field_info, and method_info structures. The RuntimeVisibleAnnotations attribute records runtime-visible Java program- ming language annotations on the corresponding class, method, or field. Each ClassFile, field_info, and method_info structure may contain at most one RuntimeVisibleAnnotations attribute, which records all the runtime-visible Java programming language annotations on the corresponding program element. The JVM must make these annotations available so they can be returned by the appropriate reflective APIs.") (defun finalize-annotations (annotations code class) (declare (ignore code)) (dolist (ann (annotations-list annotations)) (finalize-annotation ann class))) (defun finalize-annotation (ann class) (setf (annotation-type ann) (pool-add-class (class-file-constants class) (annotation-type ann))) (dolist (elem (annotation-elements ann)) (finalize-annotation-element elem class))) (defun finalize-annotation-element (elem class) (when (annotation-element-name elem) (setf (annotation-element-name elem) (pool-add-utf8 (class-file-constants class) (annotation-element-name elem)))) (funcall (annotation-element-finalizer elem) elem class)) (defun write-annotations (annotations stream) (write-u2 (length (annotations-list annotations)) stream) (dolist (annotation (reverse (annotations-list annotations))) (write-annotation annotation stream))) (defun write-annotation (annotation stream) (write-u2 (annotation-type annotation) stream) (write-u2 (length (annotation-elements annotation)) stream) (dolist (elem (reverse (annotation-elements annotation))) (write-annotation-element elem stream))) (defun write-annotation-element (elem stream) (when (annotation-element-name elem) (write-u2 (annotation-element-name elem) stream)) (funcall (annotation-element-writer elem) elem stream)) #| ;; this is the minimal sequence we need to support: ;; create a class file structure ;; add methods ;; add code to the methods, switching from one method to the other ;; finalize the methods, one by one ;; write the class file to support the sequence above, we probably need to be able to - find methods by signature - find the method's code attribute - add code to the code attribute - finalize the code attribute contents (blocking it for further addition) - |# (provide '#:jvm-class-file) abcl-src-1.9.0/src/org/armedbear/lisp/jvm-instructions.lisp0100644 0000000 0000000 00000117322 14202767264 022454 0ustar000000000 0000000 ;;; jvm-instructions.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; Copyright (C) 2010 Erik Huelsmann ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:jvm) (require "COMPILER-ERROR") (declaim (inline u2 s1 s2)) (defknown u2 (fixnum) cons) (defun u2 (n) (declare (optimize speed)) (declare (type (unsigned-byte 16) n)) (when (not (<= 0 n 65535)) (error "u2 argument ~A out of 65k range." n)) (list (logand (ash n -8) #xff) (logand n #xff))) (defknown s1 (fixnum) fixnum) (defun s1 (n) (declare (optimize speed)) (declare (type (signed-byte 8) n)) (when (not (<= -128 n 127)) (error "s1 argument ~A out of 8-bit signed range." n)) (if (< n 0) (1+ (logxor (- n) #xFF)) n)) (defknown s2 (fixnum) cons) (defun s2 (n) (declare (optimize speed)) (declare (type (signed-byte 16) n)) (when (not (<= -32768 n 32767)) (error "s2 argument ~A out of 16-bit signed range." n)) (u2 (if (< n 0) (1+ (logxor (- n) #xFFFF)) n))) ;; OPCODES (defconst *opcode-table* (make-array 256)) (defconst *opcodes* (make-hash-table :test 'equalp)) ;; instruction arguments are encoded as part of the instruction, ;; we're not talking stack values here. ;; b = signed byte (8-bit) ;; B = unsigned byte (8-bit) ;; w = signed word (16-bit) ;; W = unsigned word (16-bit) ;; i = signed int (32-bit) ;; I = unsigend int (32-bit) ;; o = signed offset (relative code pointer) (16-bit) ;; p = pool index (unsigned 8-bit) ;; P = pool index (unsigned 16-bit) ;; l = local variable (8-bit) ;; L = local variable (16-bit) ;; z = zero padding (1 to 3 bytes) to guarantee 4-byte alignment ;; of the following arguments ;; q = lookupswitch variable length instruction arguments ;; Q = tableswitch variable length instruction arguments ;; t = 8-bit java builtin type designator (in {4,5,6,7,8,9,10,11}) (defstruct jvm-opcode name number size stack-effect register-used (args-spec "")) (defun %define-opcode (name number size stack-effect register &optional args-spec) (declare (type fixnum number size)) (let* ((name (string name)) (opcode (make-jvm-opcode :name name :number number :size size :stack-effect stack-effect :register-used register :args-spec args-spec))) (setf (svref *opcode-table* number) opcode) (setf (gethash name *opcodes*) opcode) (setf (gethash number *opcodes*) opcode))) (defmacro define-opcode (name number size stack-effect register &optional args-spec) `(%define-opcode ',name ,number ,size ,stack-effect ,register ,@(when args-spec (list args-spec)))) ;; name number size stack-effect register-used (define-opcode nop 0 1 0 nil) (define-opcode aconst_null 1 1 1 nil) (define-opcode iconst_m1 2 1 1 nil) (define-opcode iconst_0 3 1 1 nil) (define-opcode iconst_1 4 1 1 nil) (define-opcode iconst_2 5 1 1 nil) (define-opcode iconst_3 6 1 1 nil) (define-opcode iconst_4 7 1 1 nil) (define-opcode iconst_5 8 1 1 nil) (define-opcode lconst_0 9 1 2 nil) (define-opcode lconst_1 10 1 2 nil) (define-opcode fconst_0 11 1 1 nil) (define-opcode fconst_1 12 1 1 nil) (define-opcode fconst_2 13 1 1 nil) (define-opcode dconst_0 14 1 2 nil) (define-opcode dconst_1 15 1 2 nil) (define-opcode bipush 16 2 1 nil) (define-opcode sipush 17 3 1 nil) (define-opcode ldc 18 2 1 nil "p") (define-opcode ldc_w 19 3 1 nil "P") (define-opcode ldc2_w 20 3 2 nil "P") (define-opcode iload 21 2 1 t) (define-opcode lload 22 2 2 t) (define-opcode fload 23 2 nil t) (define-opcode dload 24 2 nil t) (define-opcode aload 25 2 1 t) (define-opcode iload_0 26 1 1 0) (define-opcode iload_1 27 1 1 1) (define-opcode iload_2 28 1 1 2) (define-opcode iload_3 29 1 1 3) (define-opcode lload_0 30 1 2 0) (define-opcode lload_1 31 1 2 1) (define-opcode lload_2 32 1 2 2) (define-opcode lload_3 33 1 2 3) (define-opcode fload_0 34 1 nil 0) (define-opcode fload_1 35 1 nil 1) (define-opcode fload_2 36 1 nil 2) (define-opcode fload_3 37 1 nil 3) (define-opcode dload_0 38 1 nil 0) (define-opcode dload_1 39 1 nil 1) (define-opcode dload_2 40 1 nil 2) (define-opcode dload_3 41 1 nil 3) (define-opcode aload_0 42 1 1 0) (define-opcode aload_1 43 1 1 1) (define-opcode aload_2 44 1 1 2) (define-opcode aload_3 45 1 1 3) (define-opcode iaload 46 1 -1 nil) (define-opcode laload 47 1 0 nil) (define-opcode faload 48 1 -1 nil) (define-opcode daload 49 1 0 nil) (define-opcode aaload 50 1 -1 nil) (define-opcode baload 51 1 nil nil) (define-opcode caload 52 1 nil nil) (define-opcode saload 53 1 nil nil) (define-opcode istore 54 2 -1 t) (define-opcode lstore 55 2 -2 t) (define-opcode fstore 56 2 nil t) (define-opcode dstore 57 2 nil t) (define-opcode astore 58 2 -1 t) (define-opcode istore_0 59 1 -1 0) (define-opcode istore_1 60 1 -1 1) (define-opcode istore_2 61 1 -1 2) (define-opcode istore_3 62 1 -1 3) (define-opcode lstore_0 63 1 -2 0) (define-opcode lstore_1 64 1 -2 1) (define-opcode lstore_2 65 1 -2 2) (define-opcode lstore_3 66 1 -2 3) (define-opcode fstore_0 67 1 nil 0) (define-opcode fstore_1 68 1 nil 1) (define-opcode fstore_2 69 1 nil 2) (define-opcode fstore_3 70 1 nil 3) (define-opcode dstore_0 71 1 nil 0) (define-opcode dstore_1 72 1 nil 1) (define-opcode dstore_2 73 1 nil 2) (define-opcode dstore_3 74 1 nil 3) (define-opcode astore_0 75 1 -1 0) (define-opcode astore_1 76 1 -1 1) (define-opcode astore_2 77 1 -1 2) (define-opcode astore_3 78 1 -1 3) (define-opcode iastore 79 1 -3 nil) (define-opcode lastore 80 1 -4 nil) (define-opcode fastore 81 1 -3 nil) (define-opcode dastore 82 1 -4 nil) (define-opcode aastore 83 1 -3 nil) (define-opcode bastore 84 1 nil nil) (define-opcode castore 85 1 nil nil) (define-opcode sastore 86 1 nil nil) (define-opcode pop 87 1 -1 nil) (define-opcode pop2 88 1 -2 nil) (define-opcode dup 89 1 1 nil) (define-opcode dup_x1 90 1 1 nil) (define-opcode dup_x2 91 1 1 nil) (define-opcode dup2 92 1 2 nil) (define-opcode dup2_x1 93 1 2 nil) (define-opcode dup2_x2 94 1 2 nil) (define-opcode swap 95 1 0 nil) (define-opcode iadd 96 1 -1 nil) (define-opcode ladd 97 1 -2 nil) (define-opcode fadd 98 1 -1 nil) (define-opcode dadd 99 1 -2 nil) (define-opcode isub 100 1 -1 nil) (define-opcode lsub 101 1 -2 nil) (define-opcode fsub 102 1 -1 nil) (define-opcode dsub 103 1 -2 nil) (define-opcode imul 104 1 -1 nil) (define-opcode lmul 105 1 -2 nil) (define-opcode fmul 106 1 -1 nil) (define-opcode dmul 107 1 -2 nil) (define-opcode idiv 108 1 nil nil) (define-opcode ldiv 109 1 nil nil) (define-opcode fdiv 110 1 nil nil) (define-opcode ddiv 111 1 nil nil) (define-opcode irem 112 1 nil nil) (define-opcode lrem 113 1 nil nil) (define-opcode frem 114 1 nil nil) (define-opcode drem 115 1 nil nil) (define-opcode ineg 116 1 0 nil) (define-opcode lneg 117 1 0 nil) (define-opcode fneg 118 1 0 nil) (define-opcode dneg 119 1 0 nil) (define-opcode ishl 120 1 -1 nil) (define-opcode lshl 121 1 -1 nil) (define-opcode ishr 122 1 -1 nil) (define-opcode lshr 123 1 -1 nil) (define-opcode iushr 124 1 nil nil) (define-opcode lushr 125 1 nil nil) (define-opcode iand 126 1 -1 nil) (define-opcode land 127 1 -2 nil) (define-opcode ior 128 1 -1 nil) (define-opcode lor 129 1 -2 nil) (define-opcode ixor 130 1 -1 nil) (define-opcode lxor 131 1 -2 nil) (define-opcode iinc 132 3 0 t) (define-opcode i2l 133 1 1 nil) (define-opcode i2f 134 1 0 nil) (define-opcode i2d 135 1 1 nil) (define-opcode l2i 136 1 -1 nil) (define-opcode l2f 137 1 -1 nil) (define-opcode l2d 138 1 0 nil) (define-opcode f2i 139 1 nil nil) (define-opcode f2l 140 1 nil nil) (define-opcode f2d 141 1 1 nil) (define-opcode d2i 142 1 nil nil) (define-opcode d2l 143 1 nil nil) (define-opcode d2f 144 1 -1 nil) (define-opcode i2b 145 1 nil nil) (define-opcode i2c 146 1 nil nil) (define-opcode i2s 147 1 nil nil) (define-opcode lcmp 148 1 -3 nil) (define-opcode fcmpl 149 1 -1 nil) (define-opcode fcmpg 150 1 -1 nil) (define-opcode dcmpl 151 1 -3 nil) (define-opcode dcmpg 152 1 -3 nil) (define-opcode ifeq 153 3 -1 nil) (define-opcode ifne 154 3 -1 nil) (define-opcode iflt 155 3 -1 nil) (define-opcode ifge 156 3 -1 nil) (define-opcode ifgt 157 3 -1 nil) (define-opcode ifle 158 3 -1 nil) (define-opcode if_icmpeq 159 3 -2 nil) (define-opcode if_icmpne 160 3 -2 nil) (define-opcode if_icmplt 161 3 -2 nil) (define-opcode if_icmpge 162 3 -2 nil) (define-opcode if_icmpgt 163 3 -2 nil) (define-opcode if_icmple 164 3 -2 nil) (define-opcode if_acmpeq 165 3 -2 nil) (define-opcode if_acmpne 166 3 -2 nil) (define-opcode goto 167 3 0 nil) ;;(define-opcode jsr 168 3 1) Don't use these 2 opcodes: deprecated ;;(define-opcode ret 169 2 0) their use results in JVM verifier errors (define-opcode tableswitch 170 0 nil nil) (define-opcode lookupswitch 171 0 nil nil) (define-opcode ireturn 172 1 nil nil) (define-opcode lreturn 173 1 nil nil) (define-opcode freturn 174 1 nil nil) (define-opcode dreturn 175 1 nil nil) (define-opcode ireturn 172 1 -1 nil) (define-opcode areturn 176 1 -1 nil) (define-opcode return 177 1 0 nil) (define-opcode getstatic 178 3 1 nil "P") (define-opcode putstatic 179 3 -1 nil "P") (define-opcode getfield 180 3 0 nil "P") (define-opcode putfield 181 3 -2 nil "P") (define-opcode invokevirtual 182 3 nil nil "P") (define-opcode invokespecial 183 3 nil nil "P") (define-opcode invokestatic 184 3 nil nil "P") (define-opcode invokeinterface 185 5 nil nil "P") (define-opcode unused 186 0 nil nil) (define-opcode new 187 3 1 nil "P") (define-opcode newarray 188 2 nil nil) (define-opcode anewarray 189 3 0 nil) (define-opcode arraylength 190 1 0 nil) (define-opcode athrow 191 1 0 nil) (define-opcode checkcast 192 3 0 nil "P") (define-opcode instanceof 193 3 0 nil "P") (define-opcode monitorenter 194 1 -1 nil) (define-opcode monitorexit 195 1 -1 nil) (define-opcode wide 196 0 nil nil) (define-opcode multianewarray 197 4 nil nil) (define-opcode ifnull 198 3 -1 nil) (define-opcode ifnonnull 199 3 nil nil) (define-opcode goto_w 200 5 nil nil) ;; (define-opcode jsr_w 201 5 nil) Don't use: deprecated (define-opcode label 202 0 0 nil) ;; virtual: does not exist in the JVM ;; (define-opcode push-value 203 nil 1) ;; (define-opcode store-value 204 nil -1) (define-opcode clear-values 205 0 0 t) ;; virtual: does not exist in the JVM ;;(define-opcode var-ref 206 0 0) (defparameter *last-opcode* 206) (declaim (ftype (function (t) t) opcode-name)) (defun opcode-name (opcode-number) (let ((opcode (gethash opcode-number *opcodes*))) (and opcode (jvm-opcode-name opcode)))) (declaim (ftype (function (t) (integer 0 255)) opcode-number)) (defun opcode-number (opcode-name) (declare (optimize speed)) (let ((opcode (gethash (string opcode-name) *opcodes*))) (if opcode (jvm-opcode-number opcode) (error "Unknown opcode ~S." opcode-name)))) (declaim (ftype (function (t) fixnum) opcode-size)) (defun opcode-size (opcode-number) (declare (optimize speed (safety 0))) (declare (type (integer 0 255) opcode-number)) (jvm-opcode-size (svref *opcode-table* opcode-number))) (declaim (ftype (function (t) t) opcode-stack-effect)) (defun opcode-stack-effect (opcode-number) (declare (optimize speed)) (jvm-opcode-stack-effect (svref *opcode-table* opcode-number))) (defun opcode-args-spec (opcode-number) (let ((opcode (gethash opcode-number *opcodes*))) (and opcode (jvm-opcode-args-spec)))) ;; INSTRUCTION (defstruct (instruction (:constructor %make-instruction (opcode args))) (opcode 0 :type (integer 0 255)) args stack depth wide) (defun make-instruction (opcode args) (let ((inst (apply #'%make-instruction (list opcode (remove :wide-prefix args))))) (when (memq :wide-prefix args) (setf (inst-wide inst) t)) inst)) (defun print-instruction (instruction) (sys::%format nil "~A ~A stack = ~S depth = ~S" (opcode-name (instruction-opcode instruction)) (instruction-args instruction) (instruction-stack instruction) (instruction-depth instruction))) (declaim (ftype (function (t) t) instruction-label)) (defun instruction-label (instruction) (and instruction (= (instruction-opcode (the instruction instruction)) 202) (car (instruction-args instruction)))) (defknown inst * t) (defun inst (instr &optional args) (declare (optimize speed)) (let ((opcode (if (fixnump instr) instr (opcode-number instr)))) (unless (listp args) (setf args (list args))) (make-instruction opcode args))) ;; Having %emit and %%emit output their code to *code* ;; is currently an implementation detail exposed to all users. ;; We need to have APIs to address this, but for now pass2 is ;; our only user and we'll hard-code the use of *code*. (defvar *code* nil) (defknown %%emit * t) (defun %%emit (instr &rest args) (declare (optimize speed)) (let ((instruction (make-instruction instr args))) (push instruction *code*) instruction)) (defknown %emit * t) (defun %emit (instr &rest args) (declare (optimize speed)) (let ((instruction (inst instr args))) (push instruction *code*) instruction)) (defmacro emit (instr &rest args) (when (and (consp instr) (eq (car instr) 'QUOTE) (symbolp (cadr instr))) (setf instr (opcode-number (cadr instr)))) (if (fixnump instr) `(%%emit ,instr ,@args) `(%emit ,instr ,@args))) ;; Helper routines (defknown label (symbol) t) (defun label (symbol) (declare (type symbol symbol)) (declare (optimize speed)) (emit 'label symbol) (setf (symbol-value symbol) nil)) (defknown aload (fixnum) t) (defun aload (index) (case index (0 (emit 'aload_0)) (1 (emit 'aload_1)) (2 (emit 'aload_2)) (3 (emit 'aload_3)) (t (emit 'aload index)))) (defknown astore (fixnum) t) (defun astore (index) (case index (0 (emit 'astore_0)) (1 (emit 'astore_1)) (2 (emit 'astore_2)) (3 (emit 'astore_3)) (t (emit 'astore index)))) (defknown iload (fixnum) t) (defun iload (index) (case index (0 (emit 'iload_0)) (1 (emit 'iload_1)) (2 (emit 'iload_2)) (3 (emit 'iload_3)) (t (emit 'iload index)))) (defknown istore (fixnum) t) (defun istore (index) (case index (0 (emit 'istore_0)) (1 (emit 'istore_1)) (2 (emit 'istore_2)) (3 (emit 'istore_3)) (t (emit 'istore index)))) (declaim (ftype (function (t) t) branch-p) (inline branch-p)) (defun branch-p (opcode) ;; (declare (optimize speed)) ;; (declare (type '(integer 0 255) opcode)) (or (<= 153 opcode 167) (<= 198 opcode 200))) ;; ifnull / ifnonnull / goto_w (declaim (ftype (function (t) t) unconditional-control-transfer-p) (inline unconditional-control-transfer-p)) (defun unconditional-control-transfer-p (opcode) (or (= 167 opcode) ;; goto (= 200 opcode) ;; goto_w (<= 172 opcode 177) ;; ?return (= 191 opcode) ;; athrow )) (declaim (ftype (function (t) boolean) label-p) (inline label-p)) (defun label-p (instruction) (and instruction (= (the fixnum (instruction-opcode (the instruction instruction))) 202))) (defun constant-pool-index (instruction) "If an instruction references an item in the constant pool, return the index, otherwise return nil." ;; 1 byte index ;; 18 ldc ;; ;; 2 byte index ;; 178 getstatic ;; 179 putstatic ;; 180 getfield ;; 181 putfield ;; 182 invokevirtual ;; 183 invokespecial ;; 184 invokestatic ;; 185 invokeinterface ;; 187 new ;; 192 checkcast ;; 193 instanceof (when instruction (case (instruction-opcode instruction) (18 (first (instruction-args instruction))) ((19 20 178 179 180 181 182 183 184 185 187 192 193) (logior (ash (first (instruction-args instruction)) 8) (second (instruction-args instruction))))))) (defun format-instruction-args (instruction pool) (let* ((*print-readably* nil) (*print-escape* nil) (pool-index (constant-pool-index instruction)) (entry (when pool-index (find-pool-entry pool pool-index)))) (when entry (return-from format-instruction-args (with-output-to-string (s) (print-pool-constant pool entry s :package "org/armedbear/lisp"))))) (when (instruction-args instruction) (format nil "~S" (instruction-args instruction)))) (defun print-code (code pool) (declare (ignorable pool)) (dotimes (i (length code)) (let ((instruction (elt code i))) (format t "~3D ~A ~19T~A ~@[IStack: ~A~] ~@[IDepth: ~A~]~%" i (opcode-name (instruction-opcode instruction)) (or (format-instruction-args instruction pool) "") (instruction-stack instruction) (instruction-depth instruction))))) (defun print-code2 (code pool) (declare (ignorable pool)) (dotimes (i (length code)) (let ((instruction (elt code i))) (case (instruction-opcode instruction) (202 ; LABEL (format t "~A:~%" (car (instruction-args instruction)))) (t (format t "~8D: ~A ~S~%" i (opcode-name (instruction-opcode instruction)) (instruction-args instruction))))))) (defun expand-virtual-instructions (code) (let* ((len (length code)) (vector (make-array (ash len 1) :fill-pointer 0 :adjustable t))) (dotimes (index len vector) (declare (type (unsigned-byte 16) index)) (let ((instruction (svref code index))) (case (instruction-opcode instruction) (205 ; CLEAR-VALUES (dolist (instruction (list (inst 'aload (car (instruction-args instruction))) (inst 'aconst_null) (inst 'putfield (list (pool-field +lisp-thread+ "_values" +lisp-object-array+))))) (vector-push-extend instruction vector))) (t (vector-push-extend instruction vector))))))) ;; RESOLVERS (defun unsupported-opcode (instruction) (error "Unsupported opcode ~D." (instruction-opcode instruction))) (declaim (type hash-table +resolvers+)) (defconst +resolvers+ (make-hash-table)) (defun initialize-resolvers () (let ((ht +resolvers+)) (dotimes (n (1+ *last-opcode*)) (setf (gethash n ht) #'unsupported-opcode)) ;; The following opcodes resolve to themselves. (dolist (n '(0 ; nop 1 ; aconst_null 2 ; iconst_m1 3 ; iconst_0 4 ; iconst_1 5 ; iconst_2 6 ; iconst_3 7 ; iconst_4 8 ; iconst_5 9 ; lconst_0 10 ; lconst_1 11 ; fconst_0 12 ; fconst_1 13 ; fconst_2 14 ; dconst_0 15 ; dconst_1 26 ; iload_0 27 ; iload_1 28 ; iload_2 29 ; iload_3 42 ; aload_0 43 ; aload_1 44 ; aload_2 45 ; aload_3 46 ; iaload 47 ; laload 48 ; faload 49 ; daload 50 ; aaload 54 ; istore 59 ; istore_0 60 ; istore_1 61 ; istore_2 62 ; istore_3 75 ; astore_0 76 ; astore_1 77 ; astore_2 78 ; astore_3 79 ; iastore 80 ; lastore 81 ; fastore 82 ; dastore 83 ; aastore 87 ; pop 88 ; pop2 89 ; dup 90 ; dup_x1 91 ; dup_x2 92 ; dup2 93 ; dup2_x1 94 ; dup2_x2 95 ; swap 96 ; iadd 97 ; ladd 98 ; fadd 99 ; dadd 100 ; isub 101 ; lsub 102 ; fsub 103 ; dsub 104 ; imul 105 ; lmul 106 ; fmul 107 ; dmul 116 ; ineg 117 ; lneg 118 ; fneg 119 ; dneg 120 ; ishl 121 ; lshl 122 ; ishr 123 ; lshr 126 ; iand 127 ; land 128 ; ior 129 ; lor 130 ; ixor 131 ; lxor 133 ; i2l 134 ; i2f 135 ; i2d 136 ; l2i 137 ; l2f 138 ; l2d 141 ; f2d 144 ; d2f 148 ; lcmp 149 ; fcmpd 150 ; fcmpg 151 ; dcmpd 152 ; dcmpg 153 ; ifeq 154 ; ifne 155 ; ifge 156 ; ifgt 157 ; ifgt 158 ; ifle 159 ; if_icmpeq 160 ; if_icmpne 161 ; if_icmplt 162 ; if_icmpge 163 ; if_icmpgt 164 ; if_icmple 165 ; if_acmpeq 166 ; if_acmpne 167 ; goto 172 ; ireturn 176 ; areturn 177 ; return 189 ; anewarray 190 ; arraylength 191 ; athrow 194 ; monitorenter 195 ; monitorexit 198 ; ifnull 202 ; label )) (setf (gethash n ht) nil)))) (initialize-resolvers) (defmacro define-resolver (opcodes args &body body) (let ((name (gensym))) `(progn (defun ,name ,args ,@body) (eval-when (:load-toplevel :execute) ,(if (listp opcodes) `(dolist (op ',opcodes) (setf (gethash op +resolvers+) (symbol-function ',name))) `(setf (gethash ,opcodes +resolvers+) (symbol-function ',name))))))) (defun load/store-resolver (instruction inst-index inst-index2 error-text) (let* ((args (instruction-args instruction)) (index (car args))) (declare (type (unsigned-byte 16) index)) (cond ((<= 0 index 3) (inst (+ index inst-index))) ((<= 0 index 255) (inst inst-index2 index)) (t (error error-text))))) ;; aload (define-resolver 25 (instruction) (load/store-resolver instruction 42 25 "ALOAD unsupported case")) ;; astore (define-resolver 58 (instruction) (load/store-resolver instruction 75 58 "ASTORE unsupported case")) ;; iload (define-resolver 21 (instruction) (load/store-resolver instruction 26 21 "ILOAD unsupported case")) ;; istore (define-resolver 54 (instruction) (load/store-resolver instruction 59 54 "ISTORE unsupported case")) ;; lload (define-resolver 22 (instruction) (load/store-resolver instruction 30 22 "LLOAD unsupported case")) ;; lstore (define-resolver 55 (instruction) (load/store-resolver instruction 63 55 "LSTORE unsupported case")) ;; bipush, sipush (define-resolver (16 17) (instruction) (let* ((args (instruction-args instruction)) (n (first args))) (declare (type fixnum n)) (cond ((<= 0 n 5) (inst (+ n 3))) ((<= -128 n 127) (inst 16 (logand n #xff))) ; BIPUSH (t ; SIPUSH (inst 17 (s2 n)))))) ;; ldc (define-resolver 18 (instruction) (let* ((args (instruction-args instruction))) (unless (= (length args) 1) (error "Wrong number of args for LDC.")) (if (> (car args) 255) (inst 19 (u2 (car args))) ; LDC_W (inst 18 args)))) ;; ldc_w (define-resolver 19 (instruction) (let* ((args (instruction-args instruction))) (unless (= (length args) 1) (error "Wrong number of args for LDC_W.")) (inst 19 (u2 (car args))))) ;; ldc2_w (define-resolver 20 (instruction) (let* ((args (instruction-args instruction))) (unless (= (length args) 1) (error "Wrong number of args for LDC2_W.")) (inst 20 (u2 (car args))))) ;; iinc (define-resolver 132 (instruction) (let* ((args (instruction-args instruction)) (register (first args)) (n (second args))) (when (not (<= -128 n 127)) (error "IINC argument ~A out of bounds." n)) (inst 132 (list register (s1 n))))) (define-resolver (178 179 180 181 182 183 184 185 192 193 187) (instruction) (let* ((arg (car (instruction-args instruction)))) (setf (instruction-args instruction) (u2 arg)) instruction)) (defknown resolve-instruction (t) t) (defun resolve-instruction (instruction) (declare (optimize speed)) (let ((resolver (gethash1 (instruction-opcode instruction) +resolvers+))) (if resolver (funcall resolver instruction) instruction))) (defun resolve-instructions (code) (let* ((len (length code)) (vector (make-array len :fill-pointer 0 :adjustable t))) (dotimes (index len vector) (declare (type (unsigned-byte 16) index)) (let ((instruction (aref code index))) (vector-push-extend (resolve-instruction instruction) vector))))) ;; BYTE CODE ANALYSIS AND OPTIMIZATION (declaim (ftype (function (t t t) t) analyze-stack-path)) (defun analyze-stack-path (code start-index depth) (declare (optimize speed)) (declare (type fixnum start-index depth)) (do* ((i start-index (1+ i)) (limit (length code))) ((>= i limit)) (declare (type fixnum i limit)) (let* ((instruction (aref code i)) (instruction-depth (instruction-depth instruction)) (instruction-stack (instruction-stack instruction))) (declare (type fixnum instruction-stack)) (when instruction-depth (unless (= (the fixnum instruction-depth) (the fixnum (+ depth instruction-stack))) (internal-compiler-error "Stack inconsistency detected ~ in ~A at index ~D: ~ found ~S, expected ~S." (if *current-compiland* (compiland-name *current-compiland*) "") i instruction-depth (+ depth instruction-stack))) (return-from analyze-stack-path)) (let ((opcode (instruction-opcode instruction))) (setf depth (+ depth instruction-stack)) (setf (instruction-depth instruction) depth) (unless (<= 0 depth) (internal-compiler-error "Stack inconsistency detected ~ in ~A at index ~D: ~ negative depth ~S." (if *current-compiland* (compiland-name *current-compiland*) "") i depth)) (when (branch-p opcode) (let ((label (car (instruction-args instruction)))) (declare (type symbol label)) (analyze-stack-path code (symbol-value label) depth))) (when (unconditional-control-transfer-p opcode) ;; Current path ends. (return-from analyze-stack-path)))))) (declaim (ftype (function (t) t) analyze-stack)) (defun analyze-stack (code exception-entry-points) (declare (optimize speed)) ;;(print-code code *pool*) (let* ((code-length (length code))) (declare (type vector code)) (dotimes (i code-length) (let* ((instruction (aref code i)) (opcode (instruction-opcode instruction))) (when (eql opcode 202) ; LABEL (let ((label (car (instruction-args instruction)))) (set label i))) (unless (instruction-stack instruction) (setf (instruction-stack instruction) (opcode-stack-effect opcode)) (unless (instruction-stack instruction) (sys::%format t "no stack information for instruction ~D~%" (instruction-opcode instruction)) (aver nil))))) (analyze-stack-path code 0 0) (dolist (entry-point exception-entry-points) ;; Stack depth is always 1 when handler is called. (analyze-stack-path code (symbol-value entry-point) 1)) (let ((max-stack 0)) (declare (type fixnum max-stack)) (dotimes (i code-length) (let* ((instruction (aref code i)) (instruction-depth (instruction-depth instruction))) (when instruction-depth (setf max-stack (max max-stack (the fixnum instruction-depth)))))) max-stack))) (defun analyze-locals (code) (let ((code-length (length code)) (max-local 0)) (dotimes (i code-length max-local) (let* ((instruction (aref code i)) (opcode (instruction-opcode instruction))) (setf max-local (max max-local (or (let ((opcode-register (jvm-opcode-register-used opcode))) (if (eq t opcode-register) (car (instruction-args instruction)) opcode-register)) 0))))))) (defun delete-unused-labels (code handler-labels) (declare (optimize speed)) (let ((code (coerce code 'vector)) (changed nil) (marker (gensym))) ;; Mark the labels that are actually branched to. (dotimes (i (length code)) (let ((instruction (aref code i))) (when (branch-p (instruction-opcode instruction)) (let ((label (car (instruction-args instruction)))) (set label marker))))) ;; Add labels used for exception handlers. (dolist (label handler-labels) (set label marker)) ;; Remove labels that are not used as branch targets. (dotimes (i (length code)) (let ((instruction (aref code i))) (when (= (instruction-opcode instruction) 202) ; LABEL (let ((label (car (instruction-args instruction)))) (declare (type symbol label)) (unless (eq (symbol-value label) marker) (setf (aref code i) nil) (setf changed t)))))) (values (if changed (delete nil code) code) changed))) (defun delete-unreachable-code (code) ;; Look for unreachable code after GOTO. (declare (optimize speed)) (let* ((code (coerce code 'vector)) (changed nil) (after-goto/areturn nil)) (dotimes (i (length code)) (declare (type (unsigned-byte 16) i)) (let* ((instruction (aref code i)) (opcode (instruction-opcode instruction))) (cond (after-goto/areturn (if (= opcode 202) ; LABEL (setf after-goto/areturn nil) ;; Unreachable. (progn (setf (aref code i) nil) (setf changed t)))) ((unconditional-control-transfer-p opcode) (setf after-goto/areturn t))))) (values (if changed (delete nil code) code) changed))) (declaim (ftype (function (t) label-target-instructions) hash-labels)) (defun label-target-instructions (code) (let ((ht (make-hash-table :test 'eq)) (code (coerce code 'vector)) (pending-labels '())) (dotimes (i (length code)) (let ((instruction (aref code i))) (cond ((label-p instruction) (push (instruction-label instruction) pending-labels)) (t ;; Not a label. (when pending-labels (dolist (label pending-labels) (setf (gethash label ht) instruction)) (setf pending-labels nil)))))) ht)) (defun optimize-jumps (code) (declare (optimize speed)) (let* ((code (coerce code 'vector)) (ht (label-target-instructions code)) (changed nil)) (dotimes (i (length code)) (let* ((instruction (aref code i)) (opcode (and instruction (instruction-opcode instruction)))) (when (and opcode (branch-p opcode)) (let* ((target-label (car (instruction-args instruction))) (next-instruction (gethash1 target-label ht))) (when next-instruction (case (instruction-opcode next-instruction) ((167 200) ;; GOTO (setf (instruction-args instruction) (instruction-args next-instruction) changed t)) (176 ; ARETURN (when (unconditional-control-transfer-p opcode) (setf (instruction-opcode instruction) 176 (instruction-args instruction) nil changed t))))))))) (values code changed))) (defun optimize-instruction-sequences (code) (let* ((code (coerce code 'vector)) (changed nil)) (dotimes (i (1- (length code))) (let* ((this-instruction (aref code i)) (this-opcode (and this-instruction (instruction-opcode this-instruction))) (labels-skipped-p nil) (next-instruction (do ((j (1+ i) (1+ j))) ((or (>= j (length code)) (/= 202 ; LABEL (instruction-opcode (aref code j)))) (when (< j (length code)) (aref code j))) (setf labels-skipped-p t))) (next-opcode (and next-instruction (instruction-opcode next-instruction)))) (case this-opcode (205 ; CLEAR-VALUES (when (eql next-opcode 205) ; CLEAR-VALUES (setf (aref code i) nil) (setf changed t))) (178 ; GETSTATIC (when (and (eql next-opcode 87) ; POP (not labels-skipped-p)) (setf (aref code i) nil) (setf (aref code (1+ i)) nil) (setf changed t))) (176 ; ARETURN (when (eql next-opcode 176) ; ARETURN (setf (aref code i) nil) (setf changed t))) ((200 167) ; GOTO GOTO_W (when (and (or (eql next-opcode 202) ; LABEL (eql next-opcode 200) ; GOTO_W (eql next-opcode 167)) ; GOTO (eq (car (instruction-args this-instruction)) (car (instruction-args next-instruction)))) (setf (aref code i) nil) (setf changed t)))))) (values (if changed (delete nil code) code) changed))) (defvar *enable-optimization* t) (defknown optimize-code (t t) t) (defun optimize-code (code handler-labels pool) (unless *enable-optimization* (format t "optimizations are disabled~%")) (when *enable-optimization* (when *compiler-debug* (format t "----- before optimization -----~%") (print-code code pool)) (loop (let ((changed-p nil)) (multiple-value-setq (code changed-p) (delete-unused-labels code handler-labels)) (if changed-p (setf code (optimize-instruction-sequences code)) (multiple-value-setq (code changed-p) (optimize-instruction-sequences code))) (if changed-p (setf code (optimize-jumps code)) (multiple-value-setq (code changed-p) (optimize-jumps code))) (if changed-p (setf code (delete-unreachable-code code)) (multiple-value-setq (code changed-p) (delete-unreachable-code code))) (unless changed-p (return)))) (unless (vectorp code) (setf code (coerce code 'vector))) (when *compiler-debug* (sys::%format t "----- after optimization -----~%") (print-code code pool))) code) (defun code-bytes (code) (let ((length 0) labels ;; alist ) (declare (type (unsigned-byte 16) length)) ;; Pass 1: calculate label offsets and overall length. (dotimes (i (length code)) (declare (type (unsigned-byte 16) i)) (let* ((instruction (aref code i)) (opcode (instruction-opcode instruction))) (if (= opcode 202) ; LABEL (let ((label (car (instruction-args instruction)))) (set label length) (setf labels (acons label length labels))) (incf length (opcode-size opcode))))) ;; Pass 2: replace labels with calculated offsets. (let ((index 0)) (declare (type (unsigned-byte 16) index)) (dotimes (i (length code)) (declare (type (unsigned-byte 16) i)) (let ((instruction (aref code i))) (when (branch-p (instruction-opcode instruction)) (let* ((label (car (instruction-args instruction))) (offset (- (the (unsigned-byte 16) (symbol-value (the symbol label))) index))) (assert (<= -32768 offset 32767)) (setf (instruction-args instruction) (s2 offset)))) (unless (= (instruction-opcode instruction) 202) ; LABEL (incf index (opcode-size (instruction-opcode instruction))))))) ;; Expand instructions into bytes, skipping LABEL pseudo-instructions. (let ((bytes (make-array length)) (index 0)) (declare (type (unsigned-byte 16) index)) (dotimes (i (length code)) (declare (type (unsigned-byte 16) i)) (let ((instruction (aref code i))) (unless (= (instruction-opcode instruction) 202) ; LABEL (setf (svref bytes index) (instruction-opcode instruction)) (incf index) (dolist (byte (instruction-args instruction)) (setf (svref bytes index) byte) (incf index))))) (values bytes labels)))) (defun finalize-code (code handler-labels optimize pool) (setf code (coerce (nreverse code) 'vector)) (when optimize (setf code (optimize-code code handler-labels pool))) (resolve-instructions (expand-virtual-instructions code))) (provide '#:jvm-instructions) abcl-src-1.9.0/src/org/armedbear/lisp/jvm.lisp0100644 0000000 0000000 00000070430 14202767264 017710 0ustar000000000 0000000 ;;; jvm.lisp ;;; ;;; Copyright (C) 2003-2008 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :jvm) (export '(compile-defun *catch-errors* derive-compiler-type)) (require "JVM-CLASS-FILE") (defvar *closure-variables* nil) (defvar *enable-dformat* nil) (defvar *callbacks* nil "A list of functions to be called by the compiler and code generator in order to generate 'compilation events'. A callback function takes five arguments: CALLBACK-TYPE CLASS PARENT CONTENT EXCEPTION-HANDLERS.") (declaim (inline invoke-callbacks)) (defun invoke-callbacks (&rest args) (dolist (cb *callbacks*) (apply cb args))) #+nil (defun dformat (destination control-string &rest args) (when *enable-dformat* (apply #'sys::%format destination control-string args))) (defmacro dformat (&rest ignored) (declare (ignore ignored))) (defmacro with-saved-compiler-policy (&body body) "Saves compiler policy variables, restoring them after evaluating `body'." `(let ((*speed* *speed*) (*space* *space*) (*safety* *safety*) (*debug* *debug*) (*explain* *explain*) (*inline-declarations* *inline-declarations*)) ,@body)) (defvar *compiler-debug* nil) (defvar *pool* nil) (defvar *static-code* ()) (defvar *class-file* nil) (defvar *externalized-objects* nil) (defvar *declared-functions* nil) (defstruct (abcl-class-file (:include class-file) (:constructor %make-abcl-class-file)) pathname ; pathname of output file class-name static-initializer constructor objects ;; an alist of externalized objects and their field names (functions (make-hash-table :test 'equal)) ;; because of (SETF ...) functions ) (defun class-name-from-filespec (filespec) (let* ((name (pathname-name filespec))) (declare (type string name)) (dotimes (i (length name)) (declare (type fixnum i)) (when (or (char= (char name i) #\-) (char= (char name i) #\Space)) (setf (char name i) #\_))) (make-jvm-class-name (concatenate 'string "org.armedbear.lisp." name)))) (defun make-unique-class-name () "Creates a random class name for use with a `class-file' structure's `class' slot." (make-jvm-class-name (concatenate 'string "abcl_" (substitute #\_ #\- (java:jcall (java:jmethod "java.util.UUID" "toString") (java:jstatic "randomUUID" "java.util.UUID")))))) (defun make-abcl-class-file (&key pathname) "Creates a `class-file' structure. If `pathname' is non-NIL, it's used to derive a class name. If it is NIL, a random one created using `make-unique-class-name'." (let* ((class-name (if pathname (class-name-from-filespec pathname) (make-unique-class-name))) (class-file (%make-abcl-class-file :pathname pathname :class class-name ; to be finalized :class-name class-name :access-flags '(:public :final)))) (when *file-compilation* (let ((source-attribute (make-source-file-attribute :filename (file-namestring *compile-file-truename*)))) (class-add-attribute class-file source-attribute))) class-file)) (defmacro with-class-file (class-file &body body) (let ((var (gensym))) `(let* ((,var ,class-file) (*class-file* ,var) (*pool* (abcl-class-file-constants ,var)) (*externalized-objects* (abcl-class-file-objects ,var)) (*declared-functions* (abcl-class-file-functions ,var))) (progn ,@body) (setf (abcl-class-file-objects ,var) *externalized-objects* (abcl-class-file-functions ,var) *declared-functions*)))) (defstruct compiland name lambda-expression arg-vars ; variables for lambda arguments free-specials ; arity ; number of args, or NIL if the number of args can vary. p1-result ; the parse tree as created in pass 1 parent ; the parent for compilands which defined within another children ; List of local functions ; defined with FLET, LABELS or LAMBDA blocks ; TAGBODY, PROGV, BLOCK, etc. blocks (next-resource 0) argument-register closure-register environment-register class-file ; class-file object (%single-valued-p t)) (defknown compiland-single-valued-p (t) t) (defun compiland-single-valued-p (compiland) (unless (compiland-parent compiland) (let ((name (compiland-name compiland))) (when name (let ((result-type (or (function-result-type name) (and (proclaimed-ftype name) (ftype-result-type (proclaimed-ftype name)))))) (when result-type (return-from compiland-single-valued-p (cond ((eq result-type '*) nil) ((atom result-type) t) ((eq (%car result-type) 'VALUES) (= (length result-type) 2)) (t t)))))))) ;; Otherwise... (compiland-%single-valued-p compiland)) (defvar *current-compiland* nil) (defvar *this-class* nil) ;; All tags visible at the current point of compilation, some of which may not ;; be in the current compiland. (defvar *visible-tags* ()) ;; The next available register. (defvar *register* 0) ;; Total number of registers allocated. (defvar *registers-allocated* 0) ;; Variables visible at the current point of compilation. (defvar *visible-variables* nil "All variables visible to the form currently being processed, including free specials.") ;; All variables seen so far. (defvar *all-variables* nil "All variables in the lexical scope (thus excluding free specials) of the compilands being processed (p1: so far; p2: in total).") ;; Undefined variables that we've already warned about. (defvar *undefined-variables* nil) (defvar *dump-variables* nil) (defun dump-1-variable (variable) (sys::%format t " ~S special-p = ~S register = ~S binding-reg = ~S index = ~S declared-type = ~S~%" (variable-name variable) (variable-special-p variable) (variable-register variable) (variable-binding-register variable) (variable-index variable) (variable-declared-type variable))) (defun dump-variables (list caption &optional (force nil)) (when (or force *dump-variables*) (write-string caption) (if list (dolist (variable list) (dump-1-variable variable)) (sys::%format t " None.~%")))) (defstruct (variable-info (:conc-name variable-) (:constructor make-variable) (:predicate variable-p)) name initform (declared-type :none) (derived-type :none) ignore-p ignorable-p representation special-p ; indicates whether a variable is special ;; A variable can be stored in a number of locations. ;; 1. if it's passed as a normal argument, it'll be in a register (max 8) ;; the same is true if the variable is a local variable (at any index) ;; 2. if it's passed in the argument array, it'll be in the array in ;; register 1 (register 0 contains the function object) ;; 3. if the variable is part of a closure, it'll be in the closure array ;; 4. if the variable is part of the outer scope of a function with a ;; non-null lexical environment, the variable is to be looked up ;; from a lexical environment object ;; 5. the variable is a special variable and its binding has been looked ;; up and cached in a local register (binding-register) ;; a variable can be either special-p *or* have a register *or* ;; have an index *or* a closure-index *or* an environment register ; register number for a local variable binding-register ; register number containing the binding reference index ; index number for a variable in the argument array closure-index ; index number for a variable in the closure context array environment ; the environment for the variable, if we're compiling in ; a non-null lexical environment with variables (reads 0 :type fixnum) (writes 0 :type fixnum) references (references-allowed-p t) ; NIL if this is a symbol macro in the enclosing ; lexical environment used-non-locally-p (compiland *current-compiland*) block) (defmethod print-object ((object jvm::variable-info) stream) (print-unreadable-object (object stream :type t :identity t) (princ (jvm::variable-name object) stream) (princ " in " stream) (princ (jvm::compiland-name (jvm::variable-compiland object)) stream))) (defstruct (var-ref (:constructor make-var-ref (variable))) ;; The variable this reference refers to. Will be NIL if the VAR-REF has been ;; rewritten to reference a constant value. variable ;; True if the VAR-REF has been rewritten to reference a constant value. constant-p ;; The constant value of this VAR-REF. constant-value) (defmethod print-object ((object jvm::var-ref) stream) (print-unreadable-object (object stream :type t :identity t) (princ "ref ") (print-object (jvm::var-ref-variable object) stream))) ;; obj can be a symbol or variable ;; returns variable or nil (declaim (ftype (function (t) t) unboxed-fixnum-variable)) (defun unboxed-fixnum-variable (obj) (cond ((symbolp obj) (let ((variable (find-visible-variable obj))) (if (and variable (eq (variable-representation variable) :int)) variable nil))) ((variable-p obj) (if (eq (variable-representation obj) :int) obj nil)) (t nil))) (defvar *child-p* nil "True for local functions created by FLET, LABELS and (NAMED-)LAMBDA") (defknown find-variable (symbol list) t) (defun find-variable (name variables) (dolist (variable variables) (when (eq name (variable-name variable)) (return variable)))) (defknown find-visible-variable (t) t) (defun find-visible-variable (name) (dolist (variable *visible-variables*) (when (eq name (variable-name variable)) (return variable)))) (defknown representation-size (t) (integer 0 65535)) (defun representation-size (representation) (ecase representation ((NIL :int :boolean :float :char) 1) ((:long :double) 2))) (defknown allocate-register (t) (integer 0 65535)) (defun allocate-register (representation) (let ((register *register*)) (incf *register* (representation-size representation)) (setf *registers-allocated* (max *registers-allocated* *register*)) register)) (defstruct local-function name definition compiland field inline-expansion environment ;; the environment in which the function is stored in ;; case of a function from an enclosing lexical environment ;; which itself isn't being compiled (references-allowed-p t) ;;whether a reference to the function CAN be captured (references-needed-p nil) ;;whether a reference to the function NEEDS to be ;;captured, because the function name is used in a ;;(function ...) form. Obviously implies ;;references-allowed-p. ) (defvar *local-functions* ()) (defknown find-local-function (t) t) (defun find-local-function (name) (dolist (local-function *local-functions* nil) (when (equal name (local-function-name local-function)) (return local-function)))) (defvar *using-arg-array* nil) (defvar *hairy-arglist-p* nil) (defvar *block* nil "The innermost block applicable to the current lexical environment.") (defvar *blocks* () "The list of blocks in effect in the current lexical environment. The top node does not need to be equal to the value of `*block*`. E.g. when processing the bindings of a LET form, `*block*` is bound to the node of that LET, while the block is not considered 'in effect': that only happens until the body is being processed.") (defstruct node form children (compiland *current-compiland*)) ;; No need for a special constructor: nobody instantiates ;; nodes directly (declaim (inline add-node-child)) (defun add-node-child (parent child) "Add a child node to the `children` list of a parent node, if that parent belongs to the same compiland." (when parent (when (eq (node-compiland parent) *current-compiland*) (push child (node-children parent))))) ;; control-transferring blocks: TAGBODY, CATCH, to do: BLOCK (defstruct (control-transferring-node (:include node)) ;; If non-nil, the TAGBODY contains local blocks which "contaminate" the ;; environment, with GO forms in them which target tags in this TAGBODY ;; Non-nil if and only if the block doesn't modify the environment needs-environment-restoration ) ;; No need for a special constructor: nobody instantiates ;; control-transferring-nodes directly (defstruct (tagbody-node (:conc-name tagbody-) (:include control-transferring-node) (:constructor %make-tagbody-node ())) ;; True if a tag in this tagbody is the target of a non-local GO. non-local-go-p ;; Tags in the tagbody form; a list of tag structures tags ;; Contains a variable whose value uniquely identifies the ;; lexical scope from this block, to be used by GO id-variable) (defknown make-tagbody-node () t) (defun make-tagbody-node () (let ((block (%make-tagbody-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (catch-node (:conc-name catch-) (:include control-transferring-node) (:constructor %make-catch-node ())) ;; The catch tag-form is evaluated, meaning we ;; have no predefined value to store here ) (defknown make-catch-node () t) (defun make-catch-node () (let ((block (%make-catch-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (block-node (:conc-name block-) (:include control-transferring-node) (:constructor %make-block-node (name))) name ;; Block name (exit (gensym)) target ;; True if there is a non-local RETURN from this block. non-local-return-p ;; Contains a variable whose value uniquely identifies the ;; lexical scope from this block, to be used by RETURN-FROM id-variable ;; A list of all RETURN-FROM value forms associated with this block return-value-forms) (defknown make-block-node (t) t) (defun make-block-node (name) (let ((block (%make-block-node name))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (jump-node (:conc-name jump-) (:include node) (:constructor %make-jump-node (non-local-p target-block target-tag))) non-local-p target-block target-tag) (defun make-jump-node (form non-local-p target-block &optional target-tag) (let ((node (%make-jump-node non-local-p target-block target-tag))) ;; Don't push into compiland blocks, as this as a node rather than a block (setf (node-form node) form) (add-node-child *block* node) node)) ;; binding blocks: LET, LET*, FLET, LABELS, M-V-B, PROGV, LOCALLY ;; ;; Binding blocks can carry references to local (optionally special) variable bindings, ;; contain free special bindings or both (defstruct (binding-node (:include node)) ;; number of the register of the saved dynamic env, or NIL if none environment-register ;; Not used for LOCALLY and FLET; LABELS uses vars to store its functions vars free-specials) ;; nobody instantiates any binding nodes directly, so there's no reason ;; to create a constructor with the approprate administration code (defstruct (let/let*-node (:conc-name let-) (:include binding-node) (:constructor %make-let/let*-node ()))) (defknown make-let/let*-node () t) (defun make-let/let*-node () (let ((block (%make-let/let*-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (flet-node (:conc-name flet-) (:include binding-node) (:constructor %make-flet-node ()))) (defknown make-flet-node () t) (defun make-flet-node () (let ((block (%make-flet-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (labels-node (:conc-name labels-) (:include binding-node) (:constructor %make-labels-node ()))) (defknown make-labels-node () t) (defun make-labels-node () (let ((block (%make-labels-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (m-v-b-node (:conc-name m-v-b-) (:include binding-node) (:constructor %make-m-v-b-node ()))) (defknown make-m-v-b-node () t) (defun make-m-v-b-node () (let ((block (%make-m-v-b-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (progv-node (:conc-name progv-) (:include binding-node) (:constructor %make-progv-node ()))) (defknown make-progv-node () t) (defun make-progv-node () (let ((block (%make-progv-node))) (push block (compiland-blocks *current-compiland*)) block)) (defstruct (locally-node (:conc-name locally-) (:include binding-node) (:constructor %make-locally-node ()))) (defknown make-locally-node () t) (defun make-locally-node () (let ((block (%make-locally-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) ;; blocks requiring non-local exits: UNWIND-PROTECT, SYS:SYNCHRONIZED-ON (defstruct (protected-node (:include node) (:constructor %make-protected-node ()))) (defknown make-protected-node () t) (defun make-protected-node () (let ((block (%make-protected-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (unwind-protect-node (:conc-name unwind-protect-) (:include protected-node) (:constructor %make-unwind-protect-node ()))) (defknown make-unwind-protect-node () t) (defun make-unwind-protect-node () (let ((block (%make-unwind-protect-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (synchronized-node (:conc-name synchronized-) (:include protected-node) (:constructor %make-synchronized-node ()))) (defknown make-synchronized-node () t) (defun make-synchronized-node () (let ((block (%make-synchronized-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defstruct (exception-protected-node (:conc-name exception-protected-) (:include protected-node) (:constructor %make-exception-protected-node ()))) (defknown make-exception-protected-node () t) (defun make-exception-protected-node () (let ((block (%make-exception-protected-node))) (push block (compiland-blocks *current-compiland*)) (add-node-child *block* block) block)) (defun find-block (name) (dolist (block *blocks*) (when (and (block-node-p block) (eq name (block-name block))) (return block)))) (defun %find-enclosed-blocks (form traversed-blocks) "Helper function for `find-enclosed-blocks`, implementing the actual algorithm specified there. `traversed-blocks' prevents traversal of recursive structures." (cond ((node-p form) (list form)) ((atom form) nil) (t ;; We can't use MAPCAN or DOLIST here: they'll choke on dotted lists (do* ((tail form (cdr tail)) (current-block (if (consp tail) (car tail) tail) (if (consp tail) (car tail) tail)) blocks) ((null tail) blocks) (unless (gethash current-block traversed-blocks) (setf (gethash current-block traversed-blocks) t) (setf blocks (nconc (%find-enclosed-blocks current-block traversed-blocks) blocks))) (when (not (listp tail)) (return blocks)))))) (defun find-enclosed-blocks (form) "Returns the immediate enclosed blocks by searching the form's subforms. More deeply nested blocks can be reached through the `node-children` field of the immediate enclosed blocks." (when *blocks* ;; when the innermost enclosing block doesn't have node-children, ;; there's really nothing to search for. (let ((first-enclosing-block (car *blocks*))) (when (and (eq *current-compiland* (node-compiland first-enclosing-block)) (null (node-children first-enclosing-block))) (return-from find-enclosed-blocks)))) (%find-enclosed-blocks form (make-hash-table :test 'eq))) (defun some-nested-block (predicate blocks) "Applies `predicate` recursively to the `blocks` and its children, until predicate returns non-NIL, returning that value. `blocks` may be a single block or a list of blocks." (when blocks (some #'(lambda (b) (or (funcall predicate b) (some-nested-block predicate (node-children b)))) (if (listp blocks) blocks (list blocks))))) (defknown node-constant-p (t) boolean) (defun node-constant-p (object) (cond ((node-p object) nil) ((var-ref-p object) nil) ((constantp object) t) (t nil))) (defknown block-requires-non-local-exit-p (t) boolean) (defun block-requires-non-local-exit-p (object) "A block which *always* requires a 'non-local-exit' is a block which requires a transfer control exception to be thrown: e.g. Go and Return. Non-local exits are required by blocks which do more in their cleanup than just restore the lastSpecialBinding (= dynamic environment). " (or (unwind-protect-node-p object) (catch-node-p object) (synchronized-node-p object))) (defun node-opstack-unsafe-p (node) (or (when (jump-node-p node) (let ((target-block (jump-target-block node))) (and (null (jump-non-local-p node)) (member target-block *blocks*)))) (when (tagbody-node-p node) (tagbody-non-local-go-p node)) (when (block-node-p node) (block-non-local-return-p node)) (catch-node-p node))) (defknown block-creates-runtime-bindings-p (t) boolean) (defun block-creates-runtime-bindings-p (block) ;; FIXME: This may be false, if the bindings to be ;; created are a quoted list (progv-node-p block)) (defknown enclosed-by-runtime-bindings-creating-block-p (t) boolean) (defun enclosed-by-runtime-bindings-creating-block-p (outermost-block) "Indicates whether the code being compiled/analyzed is enclosed in a block which creates special bindings at runtime." (dolist (enclosing-block *blocks*) (when (eq enclosing-block outermost-block) (return-from enclosed-by-runtime-bindings-creating-block-p nil)) (when (block-creates-runtime-bindings-p enclosing-block) (return-from enclosed-by-runtime-bindings-creating-block-p t)))) (defknown enclosed-by-protected-block-p (&optional t) boolean) (defun enclosed-by-protected-block-p (&optional outermost-block) "Indicates whether the code being compiled/analyzed is enclosed in a block which requires a non-local transfer of control exception to be generated. " (dolist (enclosing-block *blocks*) (when (eq enclosing-block outermost-block) (return-from enclosed-by-protected-block-p nil)) (when (block-requires-non-local-exit-p enclosing-block) (return-from enclosed-by-protected-block-p t)))) (defknown enclosed-by-environment-setting-block-p (&optional t) boolean) (defun enclosed-by-environment-setting-block-p (&optional outermost-block) (dolist (enclosing-block *blocks*) (when (eq enclosing-block outermost-block) (return nil)) (when (and (binding-node-p enclosing-block) (binding-node-environment-register enclosing-block)) (return t)))) (defknown environment-register-to-restore (&optional t) t) (defun environment-register-to-restore (&optional outermost-block) "Returns the environment register which contains the saved environment from the outermost enclosing block: That's the one which contains the environment used in the outermost block." (flet ((outermost-register (last-register block) (when (eq block outermost-block) (return-from environment-register-to-restore last-register)) (or (and (binding-node-p block) (binding-node-environment-register block)) last-register))) (reduce #'outermost-register *blocks* :initial-value nil))) (defstruct tag ;; The symbol (or integer) naming the tag name ;; The symbol which is the jump target in JVM byte code label ;; The associated TAGBODY block (compiland *current-compiland*) used used-non-locally) (defknown find-tag (t) t) (defun find-tag (name) (dolist (tag *visible-tags*) (when (eql name (tag-name tag)) (return tag)))) (defun process-ignore/ignorable (declaration names variables) (when (memq declaration '(IGNORE IGNORABLE)) (let ((what (if (eq declaration 'IGNORE) "ignored" "ignorable"))) (dolist (name names) (unless (and (consp name) (eq (car name) 'FUNCTION)) (let ((variable (find-variable name variables))) (cond ((null variable) (compiler-style-warn "Declaring unknown variable ~S to be ~A." name what)) ((variable-special-p variable) (compiler-style-warn "Declaring special variable ~S to be ~A." name what)) ((eq declaration 'IGNORE) (setf (variable-ignore-p variable) t)) (t (setf (variable-ignorable-p variable) t))))))))) (defun finalize-generic-functions () (dolist (sym '(make-instance initialize-instance shared-initialize)) (let ((gf (and (fboundp sym) (fdefinition sym)))) (when (typep gf 'standard-generic-function) (unless (compiled-function-p gf) (mop::finalize-standard-generic-function gf)))))) (finalize-generic-functions) (provide 'jvm) abcl-src-1.9.0/src/org/armedbear/lisp/known-functions.lisp0100644 0000000 0000000 00000031727 14223403213 022244 0ustar000000000 0000000 ;;; known-functions.lisp ;;; ;;; Copyright (C) 2005-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require '#:compiler-types) ;; (declaim (ftype (function * symbol) copy-symbol gensym)) ;; (declaim (ftype (function * symbol) fdefinition-block-name)) (defknown (copy-symbol gensym fdefinition-block-name) * symbol) ;; (declaim (ftype (function (t t) t) gethash1)) (defknown gethash1 (t t) t) ;; (declaim (ftype (function (t) symbol) make-keyword)) (defknown make-keyword (t) symbol) ;; (declaim (ftype (function * list) ;; backq-list backq-list* backq-append backq-nconc ;; %class-precedence-list)) (defknown (backq-list backq-list* backq-append backq-nconc %class-precedence-list) * list) ;; (declaim (ftype (function * cons) backq-cons)) (defknown backq-cons * cons) ;; (declaim (ftype (function (character) character) char-downcase char-upcase)) (defknown (char-downcase char-upcase) (character) character) ;; (declaim (ftype (function * t) finish-output force-output clear-output terpri fresh-line)) (defknown (finish-output force-output clear-output terpri fresh-line) * t) ;; (declaim (ftype (function (symbol) string) symbol-name)) (defknown symbol-name (symbol) string) ;; (declaim ;; (ftype (function * string) ;; get-output-stream-string ;; nstring-capitalize ;; nstring-downcase ;; nstring-upcase ;; string-capitalize ;; string-downcase ;; string-upcase ;; write-line ;; write-string ;; )) (defknown (get-output-stream-string nstring-capitalize nstring-downcase nstring-upcase string-capitalize string-downcase string-upcase write-line write-string) * string) (defknown (%failed-aver %ldb %make-structure %method-function put %set-cddr %stream-terpri %stream-write-char alphanumericp array-has-fill-pointer-p aset bit-and bit-andc1 bit-andc2 bit-eqv bit-ior bit-nand bit-nor bit-not bit-orc1 bit-orc2 bit-xor both-case-p built-in-function-p caadr char-equal characterp charpos close coerce coerce-to-function compile-file-pathname complex conjugate count count-if count-if-not delete-file directory-namestring eighth enough-namestring every fifth file-directory-p file-namestring file-position fill first float fmakunbound fourth fset ftype-result-type get-internal-real-time getf hash-table-count hash-table-p host-namestring intersection ldb ldb-test list-all-packages list-find* load-compiled-function lower-case-p make-string-output-stream make-structure map merge-pathnames namestring neq nintersection ninth normalize-type nsubst nsubst-if nsubst-if-not nth pathname-type pathname-type pathnamep phase probe-file proclaimed-ftype random read read-char read-sequence reduce replace rest scale-float search second set set-char set-schar set-std-slot-value setf-function-name-p seventh simple-condition-format-arguments simple-condition-format-control simple-search sixth some sort stable-sort standard-object-p std-instance-layout std-slot-value stream-element-type stream-line-number string-find string<= structure-object-p structure-ref structure-set subst subst-if subst-if-not svref svset tenth third truename upper-case-p vector vector-find* vectorp write-byte write-sequence zerop) * t) (defknown length (sequence) (integer 0 #.(1- most-positive-fixnum))) (defknown (deposit-field dpb logand logcount lognor mask-field numerator denominator boole array-dimension array-row-major-index array-rank array-total-size %dpb ash) * integer) ;; (declaim (ftype (function (t) (integer 0 2147483647)) sxhash)) (defknown sxhash (t) (integer 0 2147483647)) ;; (declaim (ftype (function (character) (unsigned-byte 16)) char-code)) (defknown char-code (character) (unsigned-byte 16)) ;; (declaim (ftype (function (simple-string index) character) schar)) (defknown schar (simple-string index) character) ;; (declaim (ftype (function * character) char write-char)) (defknown (char write-char) * character) (defknown (char= char/= char< char> char<= char>= char-equal char-not-equal char-lessp char-greaterp char-not-greaterp char-not-lessp) * t) ;; (declaim ;; (ftype (function (real real) real) ;; mod rem)) (defknown (mod rem) (real real) real) ;; (declaim (ftype (function (number) rational) rational rationalize)) (defknown (rational rationalize) (number) rational) ;; (declaim (ftype (function * bit) bit sbit)) (defknown (bit sbit) * bit) ;; (declaim (ftype (function * function) make-macro)) (defknown make-macro * function) ;; (declaim (ftype (function * t) %set-arglist)) (defknown %set-arglist * t) ;; (declaim (ftype (function * t) %type-error check-sequence-bounds)) (defknown (%type-error check-sequence-bounds) * t) ;; (declaim (ftype (function * t) out-synonym-of)) (defknown out-synonym-of * t) (defknown (error compiler-style-warn compiler-warn compiler-error compiler-unsupported) * t) ;; (declaim (ftype (function (symbol) function) resolve)) (defknown resolve (symbol) function) ;; (declaim (ftype (function (string fixnum character) character) %set-char)) (defknown %set-char (string index character) character) ;; (declaim (ftype (function (t t t) t) set-function-info-value)) (defknown set-function-info-value (t t t) t) ;; (declaim (ftype (function * hash-table) make-hash-table)) (defknown make-hash-table * hash-table) (defknown %class-slots (class) t) (defknown set-class-slots (class list) t) (defknown %slot-definition-initfunction * t) (defknown std-slot-boundp * t) (defknown std-slot-value * t) (defknown set-std-slot-value * t) (defknown open * (or stream null)) (defknown make-string-input-stream * stream) ;; Boolean predicates that can return unboxed Java booleans. (defknown (arrayp atom consp endp evenp floatp integerp listp minusp numberp oddp packagep plusp rationalp readtablep realp simple-bit-vector-p simple-vector-p stringp symbolp zerop) (t) boolean) (defknown (constantp simple-typep typep sys::%typep) * boolean) ;; Boolean comparison operators. (defknown (/= < <= = > >= eq eql equal equalp) * boolean) ;; Boolean predicates that can not (currently) return unboxed Java booleans. (defknown (bit-vector-p compiled-function-p complexp fboundp functionp keywordp simple-string-p typep) (t) t) (defknown (boundp special-operator-p special-variable-p) (symbol) t) ;; Moved here from jvm.lisp. (defknown (+ - * / 1+ 1- car cdr caar cadr cdar cddr cadar caddr cdddr cddddr first second third list list* macro-function compiler-macro-function sys::%defun get fdefinition array-dimensions array-rank array-total-size array-element-type upgraded-array-element-type row-major-aref quote function map mapcar find position append nconc subseq adjoin revappend nreconc copy-seq assoc assoc-if assoc-if-not acons assq assql char-int digit-char-p member ext:memq remove remove-if remove-if-not delete delete-if delete-if-not symbol-function coerce reverse nreverse last cons rplaca rplacd set-car set-cdr copy-list copy-tree make-sequence make-list make-array make-package find-package pathname make-pathname pathname-name directory package-used-by-list package-shadowing-symbols nthcdr aref elt not null concatenate format sys::%format prin1 princ print write compute-restarts find-restart restart-name string string= setq multiple-value-list push pop type-of class-of abs float-radix logand logandc1 logandc2 logeqv logior lognand lognot logorc1 logorc2 logxor logbitp slot-boundp slot-value slot-exists-p allocate-instance find-class class-name constantly exp expt log min max realpart imagpart integer-length sqrt isqrt gcd lcm signum open svref fill-pointer symbol-value symbol-package package-name fourth vector-push vector-push-extend union nunion remove-duplicates delete-duplicates read-byte fresh-line terpri lambda ext:classp ext:fixnump ext:memql sys::puthash precompiler::precompile1 declare go inst emit label maybe-emit-clear-values single-valued-p sys:read-8-bits sys:write-8-bits sys::require-type sys::arg-count-error sys:subclassp sys:cache-emf sys:get-cached-emf ext:autoloadp sys::proclaim-ftype-1 sys::proclaim-ftype ) * t) (defknown make-string * simple-string) (defknown concatenate-to-string * simple-string) (defknown code-char * (or character null)) (defknown lookup-known-symbol (symbol) t) (defknown %class-name (class) symbol) (defknown adjoin-eql (t t) list) (provide '#:known-functions) abcl-src-1.9.0/src/org/armedbear/lisp/known-symbols.lisp0100644 0000000 0000000 00000005462 14202767264 021741 0ustar000000000 0000000 ;;; known-symbols.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require "JVM-CLASS-FILE") (require "JAVA") (export '(lookup-known-symbol)) (let ((symbols (make-hash-table :test 'eq :size 2048))) (defun initialize-known-symbols (source ht) (let* ((source-class (java:jclass source)) (class-designator (jvm::make-jvm-class-name source)) (symbol-class (java:jclass "org.armedbear.lisp.Symbol")) (fields (java:jclass-fields source-class :declared t :public t))) (dotimes (i (length fields)) (let* ((field (aref fields i)) (type (java:jfield-type field))) (when (equal type symbol-class) (let* ((name (java:jfield-name field)) (symbol (java:jfield source-class name))) (puthash symbol ht (list name class-designator))))))) (hash-table-count ht)) (initialize-known-symbols "org.armedbear.lisp.Symbol" symbols) (initialize-known-symbols "org.armedbear.lisp.Keyword" symbols) (initialize-known-symbols "org.armedbear.lisp.Lisp" symbols) (initialize-known-symbols "org.armedbear.lisp.Nil" symbols) (defun lookup-known-symbol (symbol) "Returns the name of the field and its class designator which stores the Java object `symbol'." (values-list (gethash1 symbol symbols)))) (provide '#:known-symbols) abcl-src-1.9.0/src/org/armedbear/lisp/last.java0100644 0000000 0000000 00000006106 14202767264 020030 0ustar000000000 0000000 /* * last.java * * Copyright (C) 2003-2006 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### last list &optional n => tail public final class last extends Primitive { public last() { super("last", "list &optional n"); } @Override public LispObject execute(LispObject arg) { if (arg == NIL) return NIL; if (arg instanceof Cons) { while (true) { LispObject cdr = ((Cons)arg).cdr; if (!(cdr instanceof Cons)) return arg; arg = cdr; } } else return type_error(arg, Symbol.LIST); } @Override public LispObject execute(LispObject first, LispObject second) { LispObject list = checkList(first); if (second instanceof Fixnum) { int n = ((Fixnum)second).value; if (n >= 0) { if (list == NIL) return NIL; LispObject result = list; while (list instanceof Cons) { list = list.cdr(); if (n-- <= 0) result = result.cdr(); } return result; } } else if (second instanceof Bignum) { if (list == NIL) return NIL; LispObject n = second; LispObject result = list; while (list instanceof Cons) { list = list.cdr(); if (!n.plusp()) result = result.cdr(); n = n.decr(); } return result; } return type_error(second, Symbol.UNSIGNED_BYTE); } private static final Primitive LAST = new last(); } abcl-src-1.9.0/src/org/armedbear/lisp/late-setf.lisp0100644 0000000 0000000 00000011321 14223403213 020752 0ustar000000000 0000000 ;;; late-setf.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From CMUCL/SBCL. (in-package #:system) (defmacro define-setf-expander (access-fn lambda-list &body body) (require-type access-fn 'symbol) (let ((whole (gensym "WHOLE-")) (environment (gensym "ENV-"))) (multiple-value-bind (body local-decs doc) (parse-defmacro lambda-list whole body access-fn 'define-setf-expander :environment environment) `(progn (record-source-information-for-type ',access-fn :setf-expander) (eval-when (:compile-toplevel :load-toplevel :execute) ,@(when doc `((%set-documentation ',access-fn 'setf ,doc))) (setf (get ',access-fn 'setf-expander) #'(lambda (,whole ,environment) ,@local-decs (block ,access-fn ,body))) ',access-fn))))) (define-setf-expander values (&rest places &environment env) (let ((setters ()) (getters ()) (all-dummies ()) (all-vals ()) (newvals ())) (dolist (place places) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion place env) (setf all-dummies (append all-dummies dummies (cdr newval)) all-vals (append all-vals vals (mapcar (constantly nil) (cdr newval))) newvals (append newvals (list (car newval)))) (push setter setters) (push getter getters))) (values all-dummies all-vals newvals `(values ,@(reverse setters)) `(values ,@(reverse getters))))) (defun make-gensym-list (n) (let ((list ())) (dotimes (i n list) (push (gensym) list)))) (define-setf-expander getf (place prop &optional default &environment env) (multiple-value-bind (temps values stores set get) (get-setf-expansion place env) (let ((newval (gensym)) (ptemp (gensym)) (def-temp (if default (gensym)))) (values `(,@temps ,ptemp ,@(if default `(,def-temp))) `(,@values ,prop ,@(if default `(,default))) `(,newval) `(let ((,(car stores) (%putf ,get ,ptemp ,newval))) ,set ,newval) `(getf ,get ,ptemp ,@(if default `(,def-temp))))))) (define-setf-expander apply (functionoid &rest args) (let ((function (second functionoid)) (new-var (gensym)) (vars (make-gensym-list (length args)))) (values vars args (list new-var) `(apply #'(setf ,function) ,new-var ,@vars) `(apply #',function ,@vars)))) (define-setf-expander the (type place &environment env) (multiple-value-bind (temps subforms store-vars setter getter) (get-setf-expansion place env) (values temps subforms store-vars `(multiple-value-bind ,store-vars (the ,type (values ,@store-vars)) ,setter) `(the ,type ,getter)))) (defun (setf macro-function) (new-function symbol &optional environment) (declare (ignore environment)) (let ((macro (make-macro symbol (or (precompile nil new-function) new-function)))) (fset symbol macro) macro)) abcl-src-1.9.0/src/org/armedbear/lisp/lcm.lisp0100644 0000000 0000000 00000004114 14202767264 017663 0ustar000000000 0000000 ;;; lcm.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun two-arg-lcm (n m) (cond ((zerop n) 0) ((zerop m) 0) (t (/ (abs (* n m)) (gcd n m))))) (defun lcm (&rest integers) (unless (every #'integerp integers) (error 'type-error :datum (find-if-not #'integerp integers) :expected-type 'integer)) (case (length integers) (0 1) (1 (abs (car integers))) (2 (two-arg-lcm (car integers) (cadr integers))) (t (do ((result (car integers) (two-arg-lcm result (car rest))) (rest (cdr integers) (cdr rest))) ((null rest) result))))) abcl-src-1.9.0/src/org/armedbear/lisp/ldb.lisp0100644 0000000 0000000 00000007625 14223403213 017643 0ustar000000000 0000000 ;;; ldb.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun byte (size position) (cons size position)) (defun byte-size (bytespec) (car bytespec)) (defun byte-position (bytespec) (cdr bytespec)) (defun ldb (bytespec integer) (logand (ash integer (- (byte-position bytespec))) (1- (ash 1 (byte-size bytespec))))) (defun ldb-test (bytespec integer) (not (zerop (ldb bytespec integer)))) (defun dpb (newbyte bytespec integer) (let* ((size (byte-size bytespec)) (position (byte-position bytespec)) (mask (1- (ash 1 size)))) (logior (logand integer (lognot (ash mask position))) (ash (logand newbyte mask) position)))) ;; From SBCL. (define-setf-expander ldb (bytespec place &environment env) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion place env) (if (and (consp bytespec) (eq (car bytespec) 'byte)) (let ((n-size (gensym)) (n-pos (gensym)) (n-new (gensym))) (values (list* n-size n-pos dummies) (list* (second bytespec) (third bytespec) vals) (list n-new) `(let ((,(car newval) (dpb ,n-new (byte ,n-size ,n-pos) ,getter))) ,setter ,n-new) `(ldb (byte ,n-size ,n-pos) ,getter))) (let ((btemp (gensym)) (gnuval (gensym))) (values (cons btemp dummies) (cons bytespec vals) (list gnuval) `(let ((,(car newval) (dpb ,gnuval ,btemp ,getter))) ,setter ,gnuval) `(ldb ,btemp ,getter)))))) ;; Used by the LDB source transform. (defun %ldb (size position integer) (logand (ash integer (- position)) (1- (ash 1 size)))) (define-setf-expander %ldb (size position place &environment env) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion place env) (let ((n-size (gensym)) (n-pos (gensym)) (n-new (gensym))) (values (list* n-size n-pos dummies) (list* size position vals) (list n-new) `(let ((,(car newval) (dpb ,n-new (byte ,n-size ,n-pos) ,getter))) ,setter ,n-new) `(ldb (byte ,n-size ,n-pos) ,getter))))) abcl-src-1.9.0/src/org/armedbear/lisp/ldiff.lisp0100644 0000000 0000000 00000003717 14223403213 020164 0ustar000000000 0000000 ;;; ldiff.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (defun ldiff (list object) (require-type list 'list) (do* ((list list (cdr list)) (result (list ())) (splice result)) ((atom list) (if (eql list object) (cdr result) (progn (rplacd splice list) (cdr result)))) (if (eql list object) (return (cdr result)) (setq splice (cdr (rplacd splice (list (car list)))))))) abcl-src-1.9.0/src/org/armedbear/lisp/lisp_implementation_type.java0100644 0000000 0000000 00000004001 14202767264 024172 0ustar000000000 0000000 /* * lisp_implementation_type.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### lisp-implementation-type => description public final class lisp_implementation_type extends Primitive { private lisp_implementation_type() { super("lisp-implementation-type", ""); } @Override public LispObject execute() { return new SimpleString("Armed Bear Common Lisp"); } private static final lisp_implementation_type LISP_IMPLEMENTATION_TYPE = new lisp_implementation_type(); } abcl-src-1.9.0/src/org/armedbear/lisp/lisp_implementation_version.java0100644 0000000 0000000 00000005721 14202767264 024710 0ustar000000000 0000000 /* * lisp_implementation_version.java * * Copyright (C) 2003 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.math.BigInteger; import java.text.MessageFormat; // ### lisp_implementation_version // lisp_implementation_version => description public final class lisp_implementation_version extends Primitive { private lisp_implementation_version() { super("lisp-implementation-version",""); } @Override public LispObject execute() { String jdkVersion = MessageFormat.format("{0}-{1}-{2}", System.getProperty("java.vm.name"), System.getProperty("java.vm.vendor"), System.getProperty("java.runtime.version")) .replace(" ", "_"); String osVersion = MessageFormat.format("{0}-{1}-{2}", System.getProperty("os.arch"), System.getProperty("os.name"), System.getProperty("os.version")) .replace(" ", "_"); return Primitives.VALUES.execute(new SimpleString(Version.getVersion()), new SimpleString(jdkVersion), new SimpleString(osVersion)); } private static final lisp_implementation_version LISP_IMPLEMENTATION_VERSION = new lisp_implementation_version(); } abcl-src-1.9.0/src/org/armedbear/lisp/list-length.lisp0100644 0000000 0000000 00000003460 14202767264 021345 0ustar000000000 0000000 ;;; list-length.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun list-length (list) (do ((n 0 (+ n 2)) (y list (cddr y)) (z list (cdr z))) (()) (when (endp y) (return n)) (when (endp (cdr y)) (return (+ n 1))) (when (and (eq y z) (> n 0)) (return nil)))) abcl-src-1.9.0/src/org/armedbear/lisp/list.lisp0100644 0000000 0000000 00000004351 14202767264 020066 0ustar000000000 0000000 ;;; list.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun fifth (list) (car (cddddr list))) (defun sixth (list) (cadr (cddddr list))) (defun seventh (list) (caddr (cddddr list))) (defun eighth (list) (cadddr (cddddr list))) (defun ninth (list) (car (cddddr (cddddr list)))) (defun tenth (list) (cadr (cddddr (cddddr list)))) (defun make-list (size &key initial-element) (%make-list size initial-element)) (defmacro apply-key (key element) `(if ,key (funcall ,key ,element) ,element)) (defun complement (f) #'(lambda (&rest x) (not (apply f x)))) (defun constantly (x) #'(lambda (&rest args) (declare (ignore args)) x)) (defun member (item list &key key test test-not) (%member item list key test test-not)) abcl-src-1.9.0/src/org/armedbear/lisp/listen.java0100644 0000000 0000000 00000004112 14202767264 020356 0ustar000000000 0000000 /* * listen.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### listen public final class listen extends Primitive { private listen() { super("listen", "&optional input-stream"); } @Override public LispObject execute() { Stream stream = checkCharacterInputStream(Symbol.STANDARD_INPUT.symbolValue()); return stream.listen(); } @Override public LispObject execute(LispObject arg) { return inSynonymOf(arg).listen(); } private static final Primitive LISTEN = new listen(); } abcl-src-1.9.0/src/org/armedbear/lisp/load.lisp0100644 0000000 0000000 00000004641 14223403213 020014 0ustar000000000 0000000 ;;; load.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun load (filespec &key (verbose *load-verbose*) (print *load-print*) (if-does-not-exist t) (external-format :default)) (let (*fasl-loader*) (%load (if (streamp filespec) filespec (merge-pathnames (pathname filespec))) verbose print if-does-not-exist external-format))) (defun load-returning-last-result (filespec &key (verbose *load-verbose*) (print *load-print*) (if-does-not-exist t) (external-format :default)) (let (*fasl-loader*) (%load-returning-last-result (if (streamp filespec) filespec (merge-pathnames (pathname filespec))) verbose print if-does-not-exist external-format))) abcl-src-1.9.0/src/org/armedbear/lisp/logand.java0100644 0000000 0000000 00000004606 14202767264 020334 0ustar000000000 0000000 /* * logand.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; // ### logand &rest integers => result-integer public final class logand extends Primitive { private logand() { super("logand", "&rest integers"); } @Override public LispObject execute() { return Fixnum.MINUS_ONE; } @Override public LispObject execute(LispObject arg) { return checkInteger(arg); } @Override public LispObject execute(LispObject first, LispObject second) { return first.LOGAND(second); } @Override public LispObject execute(LispObject[] args) { LispObject result = Fixnum.MINUS_ONE; for (int i = 0; i < args.length; i++) result = result.LOGAND(args[i]); return result; } private static final Primitive LOGAND = new logand(); } abcl-src-1.9.0/src/org/armedbear/lisp/logandc1.java0100644 0000000 0000000 00000005641 14202767264 020560 0ustar000000000 0000000 /* * logandc1.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; public final class logandc1 extends Primitive { private logandc1() { super("logandc1", "integer-1 integer-2"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Fixnum) { if (second instanceof Fixnum) return Fixnum.getInstance(~((Fixnum)first).value & ((Fixnum)second).value); if (second instanceof Bignum) { BigInteger n1 = ((Fixnum)first).getBigInteger(); BigInteger n2 = ((Bignum)second).value; return number(n1.not().and(n2)); } return type_error(second, Symbol.INTEGER); } if (first instanceof Bignum) { BigInteger n1 = ((Bignum)first).value; if (second instanceof Fixnum) { BigInteger n2 = ((Fixnum)second).getBigInteger(); return number(n1.not().and(n2)); } if (second instanceof Bignum) { BigInteger n2 = ((Bignum)second).value; return number(n1.not().and(n2)); } return type_error(second, Symbol.INTEGER); } return type_error(first, Symbol.INTEGER); } private static final Primitive LOGANDC1 = new logandc1(); } abcl-src-1.9.0/src/org/armedbear/lisp/logandc2.java0100644 0000000 0000000 00000006021 14202767264 020552 0ustar000000000 0000000 /* * logandc2.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; // ### logandc2 // logandc2 integer-1 integer-2 => result-integer // and integer-1 with complement of integer-2 public final class logandc2 extends Primitive { private logandc2() { super("logandc2", "integer-1 integer-2"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Fixnum) { if (second instanceof Fixnum) return Fixnum.getInstance(((Fixnum)first).value & ~((Fixnum)second).value); if (second instanceof Bignum) { BigInteger n1 = ((Fixnum)first).getBigInteger(); BigInteger n2 = ((Bignum)second).value; return number(n1.and(n2.not())); } return type_error(second, Symbol.INTEGER); } if (first instanceof Bignum) { BigInteger n1 = ((Bignum)first).value; if (second instanceof Fixnum) { BigInteger n2 = ((Fixnum)second).getBigInteger(); return number(n1.and(n2.not())); } if (second instanceof Bignum) { BigInteger n2 = ((Bignum)second).value; return number(n1.and(n2.not())); } return type_error(second, Symbol.INTEGER); } return type_error(first, Symbol.INTEGER); } private static final Primitive LOGANDC2 = new logandc2(); } abcl-src-1.9.0/src/org/armedbear/lisp/logbitp.java0100644 0000000 0000000 00000005422 14202767264 020525 0ustar000000000 0000000 /* * logbitp.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; // ### logbitp index integer => generalized-boolean public final class logbitp extends Primitive { private logbitp() { super("logbitp", "index integer"); } @Override public LispObject execute(LispObject first, LispObject second) { int index = -1; if (first instanceof Fixnum) { index = ((Fixnum)first).value; } else if (first instanceof Bignum) { // FIXME If the number is really big, we're not checking the right // bit... if (((Bignum)first).value.signum() > 0) index = Integer.MAX_VALUE; } if (index < 0) return type_error(first, Symbol.UNSIGNED_BYTE); BigInteger n; if (second instanceof Fixnum) n = ((Fixnum)second).getBigInteger(); else if (second instanceof Bignum) n = ((Bignum)second).value; else return type_error(second, Symbol.INTEGER); // FIXME See above. if (index == Integer.MAX_VALUE) return n.signum() < 0 ? T : NIL; return n.testBit(index) ? T : NIL; } private static final Primitive LOGBITP = new logbitp(); } abcl-src-1.9.0/src/org/armedbear/lisp/logcount.java0100644 0000000 0000000 00000004372 14202767264 020722 0ustar000000000 0000000 /* * logcount.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; // ### logcount integer => number-of-on-bits public final class logcount extends Primitive { private logcount() { super("logcount","integer"); } @Override public LispObject execute(LispObject arg) { int n; if (arg instanceof Fixnum) { int value = ((Fixnum)arg).value; n = Integer.bitCount(value < 0 ? ~value : value); } else if (arg instanceof Bignum) n = ((Bignum)arg).value.bitCount(); else return type_error(arg, Symbol.INTEGER); return Fixnum.getInstance(n); } private static final Primitive LOGCOUNT = new logcount(); } abcl-src-1.9.0/src/org/armedbear/lisp/logeqv.java0100644 0000000 0000000 00000005271 14202767264 020364 0ustar000000000 0000000 /* * logeqv.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; // ### logeqv // logeqv &rest integers => result-integer // equivalence (exclusive nor) public final class logeqv extends Primitive { private logeqv() { super("logeqv", "&rest integers"); } @Override public LispObject execute() { return Fixnum.MINUS_ONE; } @Override public LispObject execute(LispObject arg) { return checkInteger(arg); } @Override public LispObject execute(LispObject[] args) { BigInteger result = null; for (int i = 0; i < args.length; i++) { LispObject arg = args[i]; BigInteger n; if (arg instanceof Fixnum) n = ((Fixnum)arg).getBigInteger(); else if (arg instanceof Bignum) n = ((Bignum)arg).value; else return type_error(arg, Symbol.INTEGER); if (result == null) result = n; else result = result.xor(n).not(); } return number(result); } private static final Primitive LOGEQV = new logeqv(); } abcl-src-1.9.0/src/org/armedbear/lisp/logior.java0100644 0000000 0000000 00000004536 14202767264 020365 0ustar000000000 0000000 /* * logior.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### logior &rest integers => result-integer public final class logior extends Primitive { private logior() { super("logior", "&rest integers"); } @Override public LispObject execute() { return Fixnum.ZERO; } @Override public LispObject execute(LispObject arg) { return checkInteger(arg); } @Override public LispObject execute(LispObject first, LispObject second) { return first.LOGIOR(second); } @Override public LispObject execute(LispObject[] args) { LispObject result = Fixnum.ZERO; for (int i = 0; i < args.length; i++) result = result.LOGIOR(args[i]); return result; } private static final Primitive LOGIOR = new logior(); } abcl-src-1.9.0/src/org/armedbear/lisp/lognand.java0100644 0000000 0000000 00000005637 14202767264 020517 0ustar000000000 0000000 /* * lognand.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; public final class lognand extends Primitive { private lognand() { super("lognand", "integer-1 integer-2"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Fixnum) { if (second instanceof Fixnum) return Fixnum.getInstance(~(((Fixnum)first).value & ((Fixnum)second).value)); if (second instanceof Bignum) { BigInteger n1 = ((Fixnum)first).getBigInteger(); BigInteger n2 = ((Bignum)second).value; return number(n1.and(n2).not()); } return type_error(second, Symbol.INTEGER); } if (first instanceof Bignum) { BigInteger n1 = ((Bignum)first).value; if (second instanceof Fixnum) { BigInteger n2 = ((Fixnum)second).getBigInteger(); return number(n1.and(n2).not()); } if (second instanceof Bignum) { BigInteger n2 = ((Bignum)second).value; return number(n1.and(n2).not()); } return type_error(second, Symbol.INTEGER); } return type_error(first, Symbol.INTEGER); } private static final Primitive LOGNAND = new lognand(); } abcl-src-1.9.0/src/org/armedbear/lisp/lognor.java0100644 0000000 0000000 00000005626 14202767264 020373 0ustar000000000 0000000 /* * lognor.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; public final class lognor extends Primitive { private lognor() { super("lognor", "integer-1 integer-2"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Fixnum) { if (second instanceof Fixnum) return Fixnum.getInstance(~(((Fixnum)first).value | ((Fixnum)second).value)); if (second instanceof Bignum) { BigInteger n1 = ((Fixnum)first).getBigInteger(); BigInteger n2 = ((Bignum)second).value; return number(n1.or(n2).not()); } return type_error(second, Symbol.INTEGER); } if (first instanceof Bignum) { BigInteger n1 = ((Bignum)first).value; if (second instanceof Fixnum) { BigInteger n2 = ((Fixnum)second).getBigInteger(); return number(n1.or(n2).not()); } if (second instanceof Bignum) { BigInteger n2 = ((Bignum)second).value; return number(n1.or(n2).not()); } return type_error(second, Symbol.INTEGER); } return type_error(first, Symbol.INTEGER); } private static final Primitive LOGNOR = new lognor(); } abcl-src-1.9.0/src/org/armedbear/lisp/lognot.java0100644 0000000 0000000 00000003613 14202767264 020367 0ustar000000000 0000000 /* * lognot.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import java.math.BigInteger; // ### lognot public final class lognot extends Primitive { private lognot(String name, String arglist) { super(name, arglist); } @Override public LispObject execute(LispObject arg) { return arg.LOGNOT(); } private static final Primitive LOGNOT = new lognot("lognot", "integer"); } abcl-src-1.9.0/src/org/armedbear/lisp/logorc1.java0100644 0000000 0000000 00000006005 14202767264 020431 0ustar000000000 0000000 /* * logorc1.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; // ### logorc1 // logorc1 integer-1 integer-2 => result-integer // or complement of integer-1 with integer-2 public final class logorc1 extends Primitive { private logorc1() { super("logorc1", "integer-1 integer-2"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Fixnum) { if (second instanceof Fixnum) return Fixnum.getInstance(~((Fixnum)first).value | ((Fixnum)second).value); if (second instanceof Bignum) { BigInteger n1 = ((Fixnum)first).getBigInteger(); BigInteger n2 = ((Bignum)second).value; return number(n1.not().or(n2)); } return type_error(second, Symbol.INTEGER); } if (first instanceof Bignum) { BigInteger n1 = ((Bignum)first).value; if (second instanceof Fixnum) { BigInteger n2 = ((Fixnum)second).getBigInteger(); return number(n1.not().or(n2)); } if (second instanceof Bignum) { BigInteger n2 = ((Bignum)second).value; return number(n1.not().or(n2)); } return type_error(second, Symbol.INTEGER); } return type_error(first, Symbol.INTEGER); } private static final Primitive LOGORC1 = new logorc1(); } abcl-src-1.9.0/src/org/armedbear/lisp/logorc2.java0100644 0000000 0000000 00000006055 14202767264 020437 0ustar000000000 0000000 /* * logorc2.java * * Copyright (C) 2003-2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; // logorc2 integer-1 integer-2 => result-integer // or integer-1 with complement of integer-2 @DocString(name="logorc2", args="integer-1 integer-2") public final class logorc2 extends Primitive { private logorc2() { super("logorc2", "integer-1 integer-2"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Fixnum) { if (second instanceof Fixnum) return Fixnum.getInstance(((Fixnum)first).value | ~((Fixnum)second).value); if (second instanceof Bignum) { BigInteger n1 = ((Fixnum)first).getBigInteger(); BigInteger n2 = ((Bignum)second).value; return number(n1.or(n2.not())); } return type_error(second, Symbol.INTEGER); } if (first instanceof Bignum) { BigInteger n1 = ((Bignum)first).value; if (second instanceof Fixnum) { BigInteger n2 = ((Fixnum)second).getBigInteger(); return number(n1.or(n2.not())); } if (second instanceof Bignum) { BigInteger n2 = ((Bignum)second).value; return number(n1.or(n2.not())); } return type_error(second, Symbol.INTEGER); } return type_error(first, Symbol.INTEGER); } private static final Primitive LOGORC2 = new logorc2(); } abcl-src-1.9.0/src/org/armedbear/lisp/logtest.java0100644 0000000 0000000 00000005410 14202767264 020543 0ustar000000000 0000000 /* * logtest.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.math.BigInteger; // ### logtest integer-1 integer-2 => generalized-boolean // (logtest x y) == (not (zerop (logand x y))) public final class logtest extends Primitive { private logtest() { super("logtest", "integer-1 integer-2"); } @Override public LispObject execute(LispObject first, LispObject second) { if (first instanceof Fixnum && second instanceof Fixnum) { return (((Fixnum)first).value & ((Fixnum)second).value) == 0 ? NIL : T; } else { BigInteger n1, n2; if (first instanceof Fixnum) n1 = ((Fixnum)first).getBigInteger(); else if (first instanceof Bignum) n1 = ((Bignum)first).value; else return type_error(first, Symbol.INTEGER); if (second instanceof Fixnum) n2 = ((Fixnum)second).getBigInteger(); else if (second instanceof Bignum) n2 = ((Bignum)second).value; else return type_error(second, Symbol.INTEGER); return n1.and(n2).signum() == 0 ? NIL : T; } } private static final Primitive LOGTEST = new logtest(); } abcl-src-1.9.0/src/org/armedbear/lisp/logxor.java0100644 0000000 0000000 00000004536 14202767264 020404 0ustar000000000 0000000 /* * logxor.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### logxor &rest integers => result-integer public final class logxor extends Primitive { private logxor() { super("logxor", "&rest integers"); } @Override public LispObject execute() { return Fixnum.ZERO; } @Override public LispObject execute(LispObject arg) { return checkInteger(arg); } @Override public LispObject execute(LispObject first, LispObject second) { return first.LOGXOR(second); } @Override public LispObject execute(LispObject[] args) { LispObject result = Fixnum.ZERO; for (int i = 0; i < args.length; i++) result = result.LOGXOR(args[i]); return result; } private static final Primitive LOGXOR = new logxor(); } abcl-src-1.9.0/src/org/armedbear/lisp/loop.lisp0100644 0000000 0000000 00000272120 14223403213 020045 0ustar000000000 0000000 ;;; loop.lisp ;;; ;;; Copyright (C) 2004-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. ;;;; the LOOP iteration macro ;;;; This software is part of the SBCL system. See the README file for ;;;; more information. ;;;; This code was modified by William Harold Newman beginning ;;;; 19981106, originally to conform to the new SBCL bootstrap package ;;;; system and then subsequently to address other cross-compiling ;;;; bootstrap issues, SBCLification (e.g. DECLARE used to check ;;;; argument types), and other maintenance. Whether or not it then ;;;; supported all the environments implied by the reader conditionals ;;;; in the source code (e.g. #!+CLOE-RUNTIME) before that ;;;; modification, it sure doesn't now. It might perhaps, by blind ;;;; luck, be appropriate for some other CMU-CL-derived system, but ;;;; really it only attempts to be appropriate for SBCL. ;;;; This software is derived from software originally released by the ;;;; Massachusetts Institute of Technology and Symbolics, Inc. Copyright and ;;;; release statements follow. Later modifications to the software are in ;;;; the public domain and are provided with absolutely no warranty. See the ;;;; COPYING and CREDITS files for more information. ;;;; Portions of LOOP are Copyright (c) 1986 by the Massachusetts Institute ;;;; of Technology. All Rights Reserved. ;;;; ;;;; Permission to use, copy, modify and distribute this software and its ;;;; documentation for any purpose and without fee is hereby granted, ;;;; provided that the M.I.T. copyright notice appear in all copies and that ;;;; both that copyright notice and this permission notice appear in ;;;; supporting documentation. The names "M.I.T." and "Massachusetts ;;;; Institute of Technology" may not be used in advertising or publicity ;;;; pertaining to distribution of the software without specific, written ;;;; prior permission. Notice must be given in supporting documentation that ;;;; copying distribution is by permission of M.I.T. M.I.T. makes no ;;;; representations about the suitability of this software for any purpose. ;;;; It is provided "as is" without express or implied warranty. ;;;; ;;;; Massachusetts Institute of Technology ;;;; 77 Massachusetts Avenue ;;;; Cambridge, Massachusetts 02139 ;;;; United States of America ;;;; +1-617-253-1000 ;;;; Portions of LOOP are Copyright (c) 1989, 1990, 1991, 1992 by Symbolics, ;;;; Inc. All Rights Reserved. ;;;; ;;;; Permission to use, copy, modify and distribute this software and its ;;;; documentation for any purpose and without fee is hereby granted, ;;;; provided that the Symbolics copyright notice appear in all copies and ;;;; that both that copyright notice and this permission notice appear in ;;;; supporting documentation. The name "Symbolics" may not be used in ;;;; advertising or publicity pertaining to distribution of the software ;;;; without specific, written prior permission. Notice must be given in ;;;; supporting documentation that copying distribution is by permission of ;;;; Symbolics. Symbolics makes no representations about the suitability of ;;;; this software for any purpose. It is provided "as is" without express ;;;; or implied warranty. ;;;; ;;;; Symbolics, CLOE Runtime, and Minima are trademarks, and CLOE, Genera, ;;;; and Zetalisp are registered trademarks of Symbolics, Inc. ;;;; ;;;; Symbolics, Inc. ;;;; 8 New England Executive Park, East ;;;; Burlington, Massachusetts 01803 ;;;; United States of America ;;;; +1-617-221-1000 (in-package #:system) (defpackage "LOOP" (:use "COMMON-LISP")) (in-package "LOOP") ;;;; The design of this LOOP is intended to permit, using mostly the same ;;;; kernel of code, up to three different "loop" macros: ;;;; ;;;; (1) The unextended, unextensible ANSI standard LOOP; ;;;; ;;;; (2) A clean "superset" extension of the ANSI LOOP which provides ;;;; functionality similar to that of the old LOOP, but "in the style of" ;;;; the ANSI LOOP. For instance, user-definable iteration paths, with a ;;;; somewhat cleaned-up interface. ;;;; ;;;; (3) Extensions provided in another file which can make this LOOP ;;;; kernel behave largely compatibly with the Genera-vintage LOOP macro, ;;;; with only a small addition of code (instead of two whole, separate, ;;;; LOOP macros). ;;;; ;;;; Each of the above three LOOP variations can coexist in the same LISP ;;;; environment. ;;;; ;;;; KLUDGE: In SBCL, we only really use variant (1), and any generality ;;;; for the other variants is wasted. -- WHN 20000121 ;;;; FIXME: the STEP-FUNCTION stuff in the code seems to've been ;;;; intended to support code which was conditionalized with ;;;; LOOP-PREFER-POP (not true on CMU CL) and which has since been ;;;; removed. Thus, STEP-FUNCTION stuff could probably be removed too. ;;;; list collection macrology (defmacro with-loop-list-collection-head ((head-var tail-var &optional user-head-var) &body body) (let ((l (and user-head-var (list (list user-head-var nil))))) `(let* ((,head-var (list nil)) (,tail-var ,head-var) ,@l) ,@body))) (defmacro loop-collect-rplacd (&environment env (head-var tail-var &optional user-head-var) form) (setq form (macroexpand form env)) (flet ((cdr-wrap (form n) (declare (fixnum n)) (do () ((<= n 4) (setq form `(,(case n (1 'cdr) (2 'cddr) (3 'cdddr) (4 'cddddr)) ,form))) (setq form `(cddddr ,form) n (- n 4))))) (let ((tail-form form) (ncdrs nil)) ;; Determine whether the form being constructed is a list of known ;; length. (when (consp form) (cond ((eq (car form) 'list) (setq ncdrs (1- (length (cdr form))))) ((member (car form) '(list* cons)) (when (and (cddr form) (member (car (last form)) '(nil 'nil))) (setq ncdrs (- (length (cdr form)) 2)))))) (let ((answer (cond ((null ncdrs) `(when (setf (cdr ,tail-var) ,tail-form) (setq ,tail-var (last (cdr ,tail-var))))) ((< ncdrs 0) (return-from loop-collect-rplacd nil)) ((= ncdrs 0) ;; @@@@ Here we have a choice of two idioms: ;; (RPLACD TAIL (SETQ TAIL TAIL-FORM)) ;; (SETQ TAIL (SETF (CDR TAIL) TAIL-FORM)). ;; Genera and most others I have seen do better with the ;; former. `(rplacd ,tail-var (setq ,tail-var ,tail-form))) (t `(setq ,tail-var ,(cdr-wrap `(setf (cdr ,tail-var) ,tail-form) ncdrs)))))) ;; If not using locatives or something similar to update the ;; user's head variable, we've got to set it... It's harmless ;; to repeatedly set it unconditionally, and probably faster ;; than checking. (when user-head-var (setq answer `(progn ,answer (setq ,user-head-var (cdr ,head-var))))) answer)))) (defmacro loop-collect-answer (head-var &optional user-head-var) (or user-head-var `(cdr ,head-var))) ;;;; maximization technology #| The basic idea of all this minimax randomness here is that we have to have constructed all uses of maximize and minimize to a particular "destination" before we can decide how to code them. The goal is to not have to have any kinds of flags, by knowing both that (1) the type is something which we can provide an initial minimum or maximum value for and (2) know that a MAXIMIZE and MINIMIZE are not being combined. SO, we have a datastructure which we annotate with all sorts of things, incrementally updating it as we generate loop body code, and then use a wrapper and internal macros to do the coding when the loop has been constructed. |# (defstruct (loop-minimax (:constructor make-loop-minimax-internal) (:copier nil) (:predicate nil)) answer-variable type temp-variable flag-variable operations infinity-data) (defvar *loop-minimax-type-infinities-alist* ;; FIXME: Now that SBCL supports floating point infinities again, we ;; should have floating point infinities here, as cmucl-2.4.8 did. '((fixnum most-positive-fixnum most-negative-fixnum))) (defun make-loop-minimax (answer-variable type) (let ((infinity-data (cdr (assoc type *loop-minimax-type-infinities-alist* :test #'subtypep)))) (make-loop-minimax-internal :answer-variable answer-variable :type type :temp-variable (gensym "LOOP-MAXMIN-TEMP-") :flag-variable (and (not infinity-data) (gensym "LOOP-MAXMIN-FLAG-")) :operations nil :infinity-data infinity-data))) (defun loop-note-minimax-operation (operation minimax) (pushnew (the symbol operation) (loop-minimax-operations minimax)) (when (and (cdr (loop-minimax-operations minimax)) (not (loop-minimax-flag-variable minimax))) (setf (loop-minimax-flag-variable minimax) (gensym "LOOP-MAXMIN-FLAG-"))) operation) (defmacro with-minimax-value (lm &body body) (let ((init (loop-typed-init (loop-minimax-type lm))) (which (car (loop-minimax-operations lm))) (infinity-data (loop-minimax-infinity-data lm)) (answer-var (loop-minimax-answer-variable lm)) (temp-var (loop-minimax-temp-variable lm)) (flag-var (loop-minimax-flag-variable lm)) (type (loop-minimax-type lm))) (if flag-var `(let ((,answer-var ,init) (,temp-var ,init) (,flag-var nil)) (declare (type ,type ,answer-var ,temp-var)) ,@body) `(let ((,answer-var ,(if (eq which 'min) (first infinity-data) (second infinity-data))) (,temp-var ,init)) (declare (type ,type ,answer-var ,temp-var)) ,@body)))) (defmacro loop-accumulate-minimax-value (lm operation form) (let* ((answer-var (loop-minimax-answer-variable lm)) (temp-var (loop-minimax-temp-variable lm)) (flag-var (loop-minimax-flag-variable lm)) (test `(,(ecase operation (min '<) (max '>)) ,temp-var ,answer-var))) `(progn (setq ,temp-var ,form) (when ,(if flag-var `(or (not ,flag-var) ,test) test) (setq ,@(and flag-var `(,flag-var t)) ,answer-var ,temp-var))))) ;;;; LOOP keyword tables #| LOOP keyword tables are hash tables string keys and a test of EQUAL. The actual descriptive/dispatch structure used by LOOP is called a "loop universe" contains a few tables and parameterizations. The basic idea is that we can provide a non-extensible ANSI-compatible loop environment, an extensible ANSI-superset loop environment, and (for such environments as CLOE) one which is "sufficiently close" to the old Genera-vintage LOOP for use by old user programs without requiring all of the old LOOP code to be loaded. |# ;;;; token hackery ;;; Compare two "tokens". The first is the frob out of *LOOP-SOURCE-CODE*, ;;; the second a symbol to check against. (defun loop-tequal (x1 x2) (and (symbolp x1) (string= x1 x2))) (defun loop-tassoc (kwd alist) (and (symbolp kwd) (assoc kwd alist :test #'string=))) (defun loop-tmember (kwd list) (and (symbolp kwd) (member kwd list :test #'string=))) (defun loop-lookup-keyword (loop-token table) (and (symbolp loop-token) (values (gethash (symbol-name (the symbol loop-token)) table)))) (defmacro loop-store-table-data (symbol table datum) `(setf (gethash (symbol-name ,symbol) ,table) ,datum)) (defstruct (loop-universe (:copier nil) (:predicate nil)) keywords ; hash table, value = (fn-name . extra-data) iteration-keywords ; hash table, value = (fn-name . extra-data) for-keywords ; hash table, value = (fn-name . extra-data) path-keywords ; hash table, value = (fn-name . extra-data) type-symbols ; hash table of type SYMBOLS, test EQ, ; value = CL type specifier type-keywords ; hash table of type STRINGS, test EQUAL, ; value = CL type spec ansi ; NIL, T, or :EXTENDED implicit-for-required) ; see loop-hack-iteration #+sbcl (sb!int:def!method print-object ((u loop-universe) stream) (let ((string (case (loop-universe-ansi u) ((nil) "non-ANSI") ((t) "ANSI") (:extended "extended-ANSI") (t (loop-universe-ansi u))))) (print-unreadable-object (u stream :type t) (write-string string stream)))) ;;; This is the "current" loop context in use when we are expanding a ;;; loop. It gets bound on each invocation of LOOP. (defvar *loop-universe*) (defun make-standard-loop-universe (&key keywords for-keywords iteration-keywords path-keywords type-keywords type-symbols ansi) (declare (type (member nil t :extended) ansi)) (flet ((maketable (entries) (let* ((size (length entries)) (ht (make-hash-table :size (if (< size 10) 10 size) :test 'equal))) (dolist (x entries) (setf (gethash (symbol-name (car x)) ht) (cadr x))) ht))) (make-loop-universe :keywords (maketable keywords) :for-keywords (maketable for-keywords) :iteration-keywords (maketable iteration-keywords) :path-keywords (maketable path-keywords) :ansi ansi :implicit-for-required (not (null ansi)) :type-keywords (maketable type-keywords) :type-symbols (let* ((size (length type-symbols)) (ht (make-hash-table :size (if (< size 10) 10 size) :test 'eq))) (dolist (x type-symbols) (if (atom x) (setf (gethash x ht) x) (setf (gethash (car x) ht) (cadr x)))) ht)))) ;;;; SETQ hackery, including destructuring ("DESETQ") (defun loop-make-psetq (frobs) (and frobs (loop-make-desetq (list (car frobs) (if (null (cddr frobs)) (cadr frobs) `(prog1 ,(cadr frobs) ,(loop-make-psetq (cddr frobs)))))))) (defun loop-make-desetq (var-val-pairs) (if (null var-val-pairs) nil (cons 'loop-really-desetq var-val-pairs))) (defvar *loop-desetq-temporary* (make-symbol "LOOP-DESETQ-TEMP")) (defmacro loop-really-desetq (&environment env &rest var-val-pairs) (labels ((find-non-null (var) ;; See whether there's any non-null thing here. Recurse ;; if the list element is itself a list. (do ((tail var)) ((not (consp tail)) tail) (when (find-non-null (pop tail)) (return t)))) (loop-desetq-internal (var val &optional temp) ;; returns a list of actions to be performed (typecase var (null (when (consp val) ;; Don't lose possible side effects. (if (eq (car val) 'prog1) ;; These can come from PSETQ or DESETQ below. ;; Throw away the value, keep the side effects. ;; Special case is for handling an expanded POP. (mapcan (lambda (x) (and (consp x) (or (not (eq (car x) 'car)) (not (symbolp (cadr x))) (not (symbolp (setq x (macroexpand x env))))) (cons x nil))) (cdr val)) `(,val)))) (cons (let* ((car (car var)) (cdr (cdr var)) (car-non-null (find-non-null car)) (cdr-non-null (find-non-null cdr))) (when (or car-non-null cdr-non-null) (if cdr-non-null (let* ((temp-p temp) (temp (or temp *loop-desetq-temporary*)) (body `(,@(loop-desetq-internal car `(car ,temp)) (setq ,temp (cdr ,temp)) ,@(loop-desetq-internal cdr temp temp)))) (if temp-p `(,@(unless (eq temp val) `((setq ,temp ,val))) ,@body) `((let ((,temp ,val)) ,@body)))) ;; no CDRing to do (loop-desetq-internal car `(car ,val) temp))))) (otherwise (unless (eq var val) `((setq ,var ,val))))))) (do ((actions)) ((null var-val-pairs) (if (null (cdr actions)) (car actions) `(progn ,@(nreverse actions)))) (setq actions (revappend (loop-desetq-internal (pop var-val-pairs) (pop var-val-pairs)) actions))))) ;;;; LOOP-local variables ;;; This is the "current" pointer into the LOOP source code. (defvar *loop-source-code*) ;;; This is the pointer to the original, for things like NAMED that ;;; insist on being in a particular position (defvar *loop-original-source-code*) ;;; This is *loop-source-code* as of the "last" clause. It is used ;;; primarily for generating error messages (see loop-error, loop-warn). (defvar *loop-source-context*) ;;; list of names for the LOOP, supplied by the NAMED clause (defvar *loop-names*) ;;; The macroexpansion environment given to the macro. (defvar *loop-macro-environment*) ;;; This holds variable names specified with the USING clause. ;;; See LOOP-NAMED-VAR. (defvar *loop-named-vars*) ;;; LETlist-like list being accumulated for one group of parallel bindings. (defvar *loop-vars*) ;;; list of declarations being accumulated in parallel with *LOOP-VARS* (defvar *loop-declarations*) ;;; This is used by LOOP for destructuring binding, if it is doing ;;; that itself. See LOOP-MAKE-VAR. (defvar *loop-desetq-crocks*) ;;; list of wrapping forms, innermost first, which go immediately ;;; inside the current set of parallel bindings being accumulated in ;;; *LOOP-VARS*. The wrappers are appended onto a body. E.g., ;;; this list could conceivably have as its value ;;; ((WITH-OPEN-FILE (G0001 G0002 ...))), ;;; with G0002 being one of the bindings in *LOOP-VARS* (This is ;;; why the wrappers go inside of the variable bindings). (defvar *loop-wrappers*) ;;; This accumulates lists of previous values of *LOOP-VARS* and ;;; the other lists above, for each new nesting of bindings. See ;;; LOOP-BIND-BLOCK. (defvar *loop-bind-stack*) ;;; This is simply a list of LOOP iteration variables, used for ;;; checking for duplications. (defvar *loop-iteration-vars*) ;;; list of prologue forms of the loop, accumulated in reverse order (defvar *loop-prologue*) (defvar *loop-before-loop*) (defvar *loop-body*) (defvar *loop-after-body*) ;;; This is T if we have emitted any body code, so that iteration ;;; driving clauses can be disallowed. This is not strictly the same ;;; as checking *LOOP-BODY*, because we permit some clauses such as ;;; RETURN to not be considered "real" body (so as to permit the user ;;; to "code" an abnormal return value "in loop"). (defvar *loop-emitted-body*) ;;; list of epilogue forms (supplied by FINALLY generally), accumulated ;;; in reverse order (defvar *loop-epilogue*) ;;; list of epilogue forms which are supplied after the above "user" ;;; epilogue. "Normal" termination return values are provide by ;;; putting the return form in here. Normally this is done using ;;; LOOP-EMIT-FINAL-VALUE, q.v. (defvar *loop-after-epilogue*) ;;; the "culprit" responsible for supplying a final value from the ;;; loop. This is so LOOP-EMIT-FINAL-VALUE can moan about multiple ;;; return values being supplied. (defvar *loop-final-value-culprit*) ;;; If this is true, we are in some branch of a conditional. Some ;;; clauses may be disallowed. (defvar *loop-inside-conditional*) ;;; If not NIL, this is a temporary bound around the loop for holding ;;; the temporary value for "it" in things like "when (f) collect it". ;;; It may be used as a supertemporary by some other things. (defvar *loop-when-it-var*) ;;; Sometimes we decide we need to fold together parts of the loop, ;;; but some part of the generated iteration code is different for the ;;; first and remaining iterations. This variable will be the ;;; temporary which is the flag used in the loop to tell whether we ;;; are in the first or remaining iterations. (defvar *loop-never-stepped-var*) ;;; list of all the value-accumulation descriptor structures in the ;;; loop. See LOOP-GET-COLLECTION-INFO. (defvar *loop-collection-cruft*) ; for multiple COLLECTs (etc.) ;;;; code analysis stuff (defun loop-constant-fold-if-possible (form &optional expected-type) (let ((new-form form) (constantp nil) (constant-value nil)) (when (setq constantp (constantp new-form)) (setq constant-value (eval new-form))) (when (and constantp expected-type) (unless (typep constant-value expected-type) (loop-warn "~@" form constant-value expected-type) (setq constantp nil constant-value nil))) (values new-form constantp constant-value))) (defun loop-constantp (form) (constantp form)) ;;;; LOOP iteration optimization (defvar *loop-duplicate-code* nil) (defvar *loop-iteration-flag-var* (make-symbol "LOOP-NOT-FIRST-TIME")) (defun loop-code-duplication-threshold (env) (declare (ignore env)) (let (;; If we could read optimization declaration information (as ;; with the DECLARATION-INFORMATION function (present in ;; CLTL2, removed from ANSI standard) we could set these ;; values flexibly. Without DECLARATION-INFORMATION, we have ;; to set them to constants. ;; ;; except FIXME: we've lost all pretence of portability, ;; considering this instead an internal implementation, so ;; we're free to couple to our own representation of the ;; environment. (speed 1) (space 1)) (+ 40 (* (- speed space) 10)))) (defmacro loop-body (&environment env prologue before-loop main-body after-loop epilogue &aux rbefore rafter flagvar) (unless (= (length before-loop) (length after-loop)) (error "LOOP-BODY called with non-synched before- and after-loop lists")) ;;All our work is done from these copies, working backwards from the end: (setq rbefore (reverse before-loop) rafter (reverse after-loop)) (labels ((psimp (l) (let ((ans nil)) (dolist (x l) (when x (push x ans) (when (and (consp x) (member (car x) '(go return return-from))) (return nil)))) (nreverse ans))) (pify (l) (if (null (cdr l)) (car l) `(progn ,@l))) (makebody () (let ((form `(tagbody ,@(psimp (append prologue (nreverse rbefore))) next-loop ,@(psimp (append main-body (nreconc rafter `((go next-loop))))) end-loop ,@(psimp epilogue)))) (if flagvar `(let ((,flagvar nil)) ,form) form)))) (when (or *loop-duplicate-code* (not rbefore)) (return-from loop-body (makebody))) ;; This outer loop iterates once for each not-first-time flag test ;; generated plus once more for the forms that don't need a flag test. (do ((threshold (loop-code-duplication-threshold env))) (nil) (declare (fixnum threshold)) ;; Go backwards from the ends of before-loop and after-loop ;; merging all the equivalent forms into the body. (do () ((or (null rbefore) (not (equal (car rbefore) (car rafter))))) (push (pop rbefore) main-body) (pop rafter)) (unless rbefore (return (makebody))) ;; The first forms in RBEFORE & RAFTER (which are the ;; chronologically last forms in the list) differ, therefore ;; they cannot be moved into the main body. If everything that ;; chronologically precedes them either differs or is equal but ;; is okay to duplicate, we can just put all of rbefore in the ;; prologue and all of rafter after the body. Otherwise, there ;; is something that is not okay to duplicate, so it and ;; everything chronologically after it in rbefore and rafter ;; must go into the body, with a flag test to distinguish the ;; first time around the loop from later times. What ;; chronologically precedes the non-duplicatable form will be ;; handled the next time around the outer loop. (do ((bb rbefore (cdr bb)) (aa rafter (cdr aa)) (lastdiff nil) (count 0) (inc nil)) ((null bb) (return-from loop-body (makebody))) ; Did it. (cond ((not (equal (car bb) (car aa))) (setq lastdiff bb count 0)) ((or (not (setq inc (estimate-code-size (car bb) env))) (> (incf count inc) threshold)) ;; Ok, we have found a non-duplicatable piece of code. ;; Everything chronologically after it must be in the ;; central body. Everything chronologically at and ;; after LASTDIFF goes into the central body under a ;; flag test. (let ((then nil) (else nil)) (do () (nil) (push (pop rbefore) else) (push (pop rafter) then) (when (eq rbefore (cdr lastdiff)) (return))) (unless flagvar (push `(setq ,(setq flagvar *loop-iteration-flag-var*) t) else)) (push `(if ,flagvar ,(pify (psimp then)) ,(pify (psimp else))) main-body)) ;; Everything chronologically before lastdiff until the ;; non-duplicatable form (CAR BB) is the same in ;; RBEFORE and RAFTER, so just copy it into the body. (do () (nil) (pop rafter) (push (pop rbefore) main-body) (when (eq rbefore (cdr bb)) (return))) (return))))))) (defun duplicatable-code-p (expr env) (if (null expr) 0 (let ((ans (estimate-code-size expr env))) (declare (fixnum ans)) ;; @@@@ Use (DECLARATION-INFORMATION 'OPTIMIZE ENV) here to ;; get an alist of optimize quantities back to help quantify ;; how much code we are willing to duplicate. ans))) (defvar *special-code-sizes* '((return 0) (progn 0) (null 1) (not 1) (eq 1) (car 1) (cdr 1) (when 1) (unless 1) (if 1) (caar 2) (cadr 2) (cdar 2) (cddr 2) (caaar 3) (caadr 3) (cadar 3) (caddr 3) (cdaar 3) (cdadr 3) (cddar 3) (cdddr 3) (caaaar 4) (caaadr 4) (caadar 4) (caaddr 4) (cadaar 4) (cadadr 4) (caddar 4) (cadddr 4) (cdaaar 4) (cdaadr 4) (cdadar 4) (cdaddr 4) (cddaar 4) (cddadr 4) (cdddar 4) (cddddr 4))) (defvar *estimate-code-size-punt* '(block do do* dolist flet labels lambda let let* locally macrolet multiple-value-bind prog prog* symbol-macrolet tagbody unwind-protect with-open-file)) (defun destructuring-size (x) (do ((x x (cdr x)) (n 0 (+ (destructuring-size (car x)) n))) ((atom x) (+ n (if (null x) 0 1))))) (defun estimate-code-size (x env) (catch 'estimate-code-size (estimate-code-size-1 x env))) (defun estimate-code-size-1 (x env) (flet ((list-size (l) (let ((n 0)) (declare (fixnum n)) (dolist (x l n) (incf n (estimate-code-size-1 x env)))))) ;;@@@@ ???? (declare (function list-size (list) fixnum)) (cond ((constantp x) 1) ((symbolp x) (multiple-value-bind (new-form expanded-p) (macroexpand-1 x env) (if expanded-p (estimate-code-size-1 new-form env) 1))) ((atom x) 1) ;; ??? self-evaluating??? ((symbolp (car x)) (let ((fn (car x)) (tem nil) (n 0)) (declare (symbol fn) (fixnum n)) (macrolet ((f (overhead &optional (args nil args-p)) `(the fixnum (+ (the fixnum ,overhead) (the fixnum (list-size ,(if args-p args '(cdr x)))))))) (cond ((setq tem (get fn 'estimate-code-size)) (typecase tem (fixnum (f tem)) (t (funcall tem x env)))) ((setq tem (assoc fn *special-code-sizes*)) (f (second tem))) ((eq fn 'cond) (dolist (clause (cdr x) n) (incf n (list-size clause)) (incf n))) ((eq fn 'desetq) (do ((l (cdr x) (cdr l))) ((null l) n) (setq n (+ n (destructuring-size (car l)) (estimate-code-size-1 (cadr l) env))))) ((member fn '(setq psetq)) (do ((l (cdr x) (cdr l))) ((null l) n) (setq n (+ n (estimate-code-size-1 (cadr l) env) 1)))) ((eq fn 'go) 1) ((eq fn 'function) (if #+sbcl (sb!int:legal-fun-name-p (cadr x)) #+armedbear (or (symbolp (cadr x)) (and (consp (cadr x)) (eq (caadr x) 'setf))) 1 (throw 'estimate-code-size nil))) ((eq fn 'multiple-value-setq) (f (length (second x)) (cddr x))) ((eq fn 'return-from) (1+ (estimate-code-size-1 (third x) env))) ((or (special-operator-p fn) (member fn *estimate-code-size-punt*)) (throw 'estimate-code-size nil)) (t (multiple-value-bind (new-form expanded-p) (macroexpand-1 x env) (if expanded-p (estimate-code-size-1 new-form env) (f 3)))))))) (t (throw 'estimate-code-size nil))))) ;;;; loop errors (defun loop-context () (do ((l *loop-source-context* (cdr l)) (new nil (cons (car l) new))) ((eq l (cdr *loop-source-code*)) (nreverse new)))) (defun loop-error (format-string &rest format-args) (error 'program-error :format-control "~?~%Current LOOP context:~{ ~S~}." :format-arguments (list format-string format-args (loop-context)))) (defun loop-warn (format-string &rest format-args) (warn "~?~%Current LOOP context:~{ ~S~}." format-string format-args (loop-context))) (defun loop-check-data-type (specified-type required-type &optional (default-type required-type)) (if (null specified-type) default-type (multiple-value-bind (a b) (subtypep specified-type required-type) (cond ((not b) (loop-warn "LOOP couldn't verify that ~S is a subtype of the required type ~S." specified-type required-type)) ((not a) (loop-error "The specified data type ~S is not a subtype of ~S." specified-type required-type))) specified-type))) (defun subst-gensyms-for-nil (tree) (declare (special *ignores*)) (cond ((null tree) (car (push (gensym "LOOP-IGNORED-VAR-") *ignores*))) ((atom tree) tree) ((atom (cdr tree)) (cons (subst-gensyms-for-nil (car tree)) (subst-gensyms-for-nil (cdr tree)))) (t (do* ((acc (cons '&optional nil)) (acc-last acc) (elt tree (cdr elt))) ((atom elt) (setf (cdr acc-last) elt) acc) (setf (cdr acc-last) (cons (subst-gensyms-for-nil (car elt)) nil)) (setf acc-last (cdr acc-last)))))) (defmacro loop-destructuring-bind (lambda-list arg-list &rest body) (let ((*ignores* nil)) (declare (special *ignores*)) (let ((d-var-lambda-list (subst-gensyms-for-nil lambda-list))) `(destructuring-bind ,d-var-lambda-list ,arg-list (declare (ignore ,@*ignores*)) ,@body)))) (defun loop-build-destructuring-bindings (crocks forms) (if crocks `((loop-destructuring-bind ,(car crocks) ,(cadr crocks) ,@(loop-build-destructuring-bindings (cddr crocks) forms))) forms)) (defun loop-translate (*loop-source-code* *loop-macro-environment* *loop-universe*) (let ((*loop-original-source-code* *loop-source-code*) (*loop-source-context* nil) (*loop-iteration-vars* nil) (*loop-vars* nil) (*loop-named-vars* nil) (*loop-declarations* nil) (*loop-desetq-crocks* nil) (*loop-bind-stack* nil) (*loop-prologue* nil) (*loop-wrappers* nil) (*loop-before-loop* nil) (*loop-body* nil) (*loop-emitted-body* nil) (*loop-after-body* nil) (*loop-epilogue* nil) (*loop-after-epilogue* nil) (*loop-final-value-culprit* nil) (*loop-inside-conditional* nil) (*loop-when-it-var* nil) (*loop-never-stepped-var* nil) (*loop-names* nil) (*loop-collection-cruft* nil)) (loop-iteration-driver) (loop-bind-block) (let ((answer `(loop-body ,(nreverse *loop-prologue*) ,(nreverse *loop-before-loop*) ,(nreverse *loop-body*) ,(nreverse *loop-after-body*) ,(nreconc *loop-epilogue* (nreverse *loop-after-epilogue*))))) (dolist (entry *loop-bind-stack*) (let ((vars (first entry)) (dcls (second entry)) (crocks (third entry)) (wrappers (fourth entry))) (dolist (w wrappers) (setq answer (append w (list answer)))) (when (or vars dcls crocks) (let ((forms (list answer))) ;;(when crocks (push crocks forms)) (when dcls (push `(declare ,@dcls) forms)) (setq answer `(,(if vars 'let 'locally) ,vars ,@(loop-build-destructuring-bindings crocks forms))))))) (do () (nil) (setq answer `(block ,(pop *loop-names*) ,answer)) (unless *loop-names* (return nil))) answer))) (defun loop-iteration-driver () (do () ((null *loop-source-code*)) (let ((keyword (car *loop-source-code*)) (tem nil)) (cond ((not (symbolp keyword)) (loop-error "~S found where LOOP keyword expected" keyword)) (t (setq *loop-source-context* *loop-source-code*) (loop-pop-source) (cond ((setq tem (loop-lookup-keyword keyword (loop-universe-keywords *loop-universe*))) ;; It's a "miscellaneous" toplevel LOOP keyword (DO, ;; COLLECT, NAMED, etc.) (apply (symbol-function (first tem)) (rest tem))) ((setq tem (loop-lookup-keyword keyword (loop-universe-iteration-keywords *loop-universe*))) (loop-hack-iteration tem)) ((loop-tmember keyword '(and else)) ;; The alternative is to ignore it, i.e. let it go ;; around to the next keyword... (loop-error "secondary clause misplaced at top level in LOOP macro: ~S ~S ~S ..." keyword (car *loop-source-code*) (cadr *loop-source-code*))) (t (loop-error "unknown LOOP keyword: ~S" keyword)))))))) (defun loop-pop-source () (if *loop-source-code* (pop *loop-source-code*) (loop-error "LOOP source code ran out when another token was expected."))) (defun loop-get-form () (if *loop-source-code* (loop-pop-source) (loop-error "LOOP code ran out where a form was expected."))) (defun loop-get-compound-form () (let ((form (loop-get-form))) (unless (consp form) (loop-error "A compound form was expected, but ~S found." form)) form)) (defun loop-get-progn () (do ((forms (list (loop-get-compound-form)) (cons (loop-get-compound-form) forms)) (nextform (car *loop-source-code*) (car *loop-source-code*))) ((atom nextform) (if (null (cdr forms)) (car forms) (cons 'progn (nreverse forms)))))) (defun loop-construct-return (form) `(return-from ,(car *loop-names*) ,form)) (defun loop-pseudo-body (form) (cond ((or *loop-emitted-body* *loop-inside-conditional*) (push form *loop-body*)) (t (push form *loop-before-loop*) (push form *loop-after-body*)))) (defun loop-emit-body (form) (setq *loop-emitted-body* t) (loop-pseudo-body form)) (defun loop-emit-final-value (&optional (form nil form-supplied-p)) (when form-supplied-p (push (loop-construct-return form) *loop-after-epilogue*)) (when *loop-final-value-culprit* (loop-warn "The LOOP clause is providing a value for the iteration;~@ however, one was already established by a ~S clause." *loop-final-value-culprit*)) (setq *loop-final-value-culprit* (car *loop-source-context*))) (defun loop-disallow-conditional (&optional kwd) (when *loop-inside-conditional* (loop-error "~:[This LOOP~;The LOOP ~:*~S~] clause is not permitted inside a conditional." kwd))) (defun loop-disallow-anonymous-collectors () (when (find-if-not 'loop-collector-name *loop-collection-cruft*) (loop-error "This LOOP clause is not permitted with anonymous collectors."))) (defun loop-disallow-aggregate-booleans () (when (loop-tmember *loop-final-value-culprit* '(always never thereis)) (loop-error "This anonymous collection LOOP clause is not permitted with aggregate booleans."))) ;;;; loop types (defun loop-typed-init (data-type &optional step-var-p) (when (and data-type (subtypep data-type 'number)) ;; From SBCL (let ((init (if step-var-p 1 0))) (flet ((like (&rest types) (coerce init (find-if (lambda (type) (subtypep data-type type)) types)))) (cond ((subtypep data-type 'float) (like 'single-float 'double-float 'short-float 'long-float 'float)) ((subtypep data-type '(complex float)) (like '(complex single-float) '(complex double-float) '(complex short-float) '(complex long-float) '(complex float))) (t init)))))) (defun loop-optional-type (&optional variable) ;; No variable specified implies that no destructuring is permissible. (and *loop-source-code* ; Don't get confused by NILs.. (let ((z (car *loop-source-code*))) (cond ((loop-tequal z 'of-type) ;; This is the syntactically unambigous form in that ;; the form of the type specifier does not matter. ;; Also, it is assumed that the type specifier is ;; unambiguously, and without need of translation, a ;; common lisp type specifier or pattern (matching the ;; variable) thereof. (loop-pop-source) (loop-pop-source)) ((symbolp z) ;; This is the (sort of) "old" syntax, even though we ;; didn't used to support all of these type symbols. (let ((type-spec (or (gethash z (loop-universe-type-symbols *loop-universe*)) (gethash (symbol-name z) (loop-universe-type-keywords *loop-universe*))))) (when type-spec (loop-pop-source) type-spec))) (t ;; This is our sort-of old syntax. But this is only ;; valid for when we are destructuring, so we will be ;; compulsive (should we really be?) and require that ;; we in fact be doing variable destructuring here. We ;; must translate the old keyword pattern typespec ;; into a fully-specified pattern of real type ;; specifiers here. (if (consp variable) (unless (consp z) (loop-error "~S found where a LOOP keyword, LOOP type keyword, or LOOP type pattern expected" z)) (loop-error "~S found where a LOOP keyword or LOOP type keyword expected" z)) (loop-pop-source) (labels ((translate (k v) (cond ((null k) nil) ((atom k) (replicate (or (gethash k (loop-universe-type-symbols *loop-universe*)) (gethash (symbol-name k) (loop-universe-type-keywords *loop-universe*)) (loop-error "The destructuring type pattern ~S contains the unrecognized type keyword ~S." z k)) v)) ((atom v) (loop-error "The destructuring type pattern ~S doesn't match the variable pattern ~S." z variable)) (t (cons (translate (car k) (car v)) (translate (cdr k) (cdr v)))))) (replicate (typ v) (if (atom v) typ (cons (replicate typ (car v)) (replicate typ (cdr v)))))) (translate z variable))))))) ;;;; loop variables (defun loop-bind-block () (when (or *loop-vars* *loop-declarations* *loop-wrappers*) (push (list (nreverse *loop-vars*) *loop-declarations* *loop-desetq-crocks* *loop-wrappers*) *loop-bind-stack*) (setq *loop-vars* nil *loop-declarations* nil *loop-desetq-crocks* nil *loop-wrappers* nil))) (defun loop-var-p (name) (do ((entry *loop-bind-stack* (cdr entry))) (nil) (cond ((null entry) (return nil)) ((assoc name (caar entry) :test #'eq) (return t))))) (defun loop-make-var (name initialization dtype &optional iteration-var-p step-var-p) (cond ((null name) (setq name (gensym "LOOP-IGNORE-")) (push (list name initialization) *loop-vars*) (if (null initialization) (push `(ignore ,name) *loop-declarations*) (loop-declare-var name dtype))) ((atom name) (cond (iteration-var-p (if (member name *loop-iteration-vars*) (loop-error "duplicated LOOP iteration variable ~S" name) (push name *loop-iteration-vars*))) ((assoc name *loop-vars*) (loop-error "duplicated variable ~S in LOOP parallel binding" name))) (unless (symbolp name) (loop-error "bad variable ~S somewhere in LOOP" name)) (loop-declare-var name dtype step-var-p) ;; We use ASSOC on this list to check for duplications (above), ;; so don't optimize out this list: (push (list name (or initialization (loop-typed-init dtype step-var-p))) *loop-vars*)) (initialization (let ((newvar (gensym "LOOP-DESTRUCTURE-"))) (loop-declare-var name dtype) (push (list newvar initialization) *loop-vars*) ;; *LOOP-DESETQ-CROCKS* gathered in reverse order. (setq *loop-desetq-crocks* (list* name newvar *loop-desetq-crocks*)))) (t (let ((tcar nil) (tcdr nil)) (if (atom dtype) (setq tcar (setq tcdr dtype)) (setq tcar (car dtype) tcdr (cdr dtype))) (loop-make-var (car name) nil tcar iteration-var-p) (loop-make-var (cdr name) nil tcdr iteration-var-p)))) name) (defun loop-make-iteration-var (name initialization dtype) (when (and name (loop-var-p name)) (loop-error "Variable ~S has already been used." name)) (loop-make-var name initialization dtype t)) (defun loop-declare-var (name dtype &optional step-var-p) (cond ((or (null name) (null dtype) (eq dtype t)) nil) ((symbolp name) (unless (subtypep t dtype) (let ((dtype (let ((init (loop-typed-init dtype step-var-p))) (if (typep init dtype) dtype `(or (member ,init) ,dtype))))) (push `(type ,dtype ,name) *loop-declarations*)))) ((consp name) (cond ((consp dtype) (loop-declare-var (car name) (car dtype)) (loop-declare-var (cdr name) (cdr dtype))) (t (loop-declare-var (car name) dtype) (loop-declare-var (cdr name) dtype)))) (t (error "invalid LOOP variable passed in: ~S" name)))) (defun loop-maybe-bind-form (form data-type) (if (loop-constantp form) form (loop-make-var (gensym "LOOP-BIND-") form data-type))) (defun loop-do-if (for negatep) (let ((form (loop-get-form)) (*loop-inside-conditional* t) (it-p nil) (first-clause-p t)) (flet ((get-clause (for) (do ((body nil)) (nil) (let ((key (car *loop-source-code*)) (*loop-body* nil) data) (cond ((not (symbolp key)) (loop-error "~S found where keyword expected getting LOOP clause after ~S" key for)) (t (setq *loop-source-context* *loop-source-code*) (loop-pop-source) (when (and (loop-tequal (car *loop-source-code*) 'it) first-clause-p) (setq *loop-source-code* (cons (or it-p (setq it-p (loop-when-it-var))) (cdr *loop-source-code*)))) (cond ((or (not (setq data (loop-lookup-keyword key (loop-universe-keywords *loop-universe*)))) (progn (apply (symbol-function (car data)) (cdr data)) (null *loop-body*))) (loop-error "~S does not introduce a LOOP clause that can follow ~S." key for)) (t (setq body (nreconc *loop-body* body))))))) (setq first-clause-p nil) (if (loop-tequal (car *loop-source-code*) :and) (loop-pop-source) (return (if (cdr body) `(progn ,@(nreverse body)) (car body))))))) (let ((then (get-clause for)) (else (when (loop-tequal (car *loop-source-code*) :else) (loop-pop-source) (list (get-clause :else))))) (when (loop-tequal (car *loop-source-code*) :end) (loop-pop-source)) (when it-p (setq form `(setq ,it-p ,form))) (loop-pseudo-body `(if ,(if negatep `(not ,form) form) ,then ,@else)))))) (defun loop-do-initially () (loop-disallow-conditional :initially) (push (loop-get-progn) *loop-prologue*)) (defun loop-do-finally () (loop-disallow-conditional :finally) (push (loop-get-progn) *loop-epilogue*)) (defun loop-do-do () (loop-emit-body (loop-get-progn))) (defun loop-do-named () (let ((name (loop-pop-source))) (unless (symbolp name) (loop-error "~S is an invalid name for your LOOP" name)) (when (or *loop-before-loop* *loop-body* *loop-after-epilogue* *loop-inside-conditional*) (loop-error "The NAMED ~S clause occurs too late." name)) (when *loop-names* (loop-error "You may only use one NAMED clause in your loop: NAMED ~S ... NAMED ~S." (car *loop-names*) name)) (setq *loop-names* (list name)))) (defun loop-do-return () (loop-emit-body (loop-construct-return (loop-get-form)))) ;;;; value accumulation: LIST (defstruct (loop-collector (:copier nil) (:predicate nil)) name class (history nil) (tempvars nil) dtype (data nil)) ;collector-specific data (defun loop-get-collection-info (collector class default-type) (let ((form (loop-get-form)) (dtype (and (not (loop-universe-ansi *loop-universe*)) (loop-optional-type))) (name (when (loop-tequal (car *loop-source-code*) 'into) (loop-pop-source) (loop-pop-source)))) (when (not (symbolp name)) (loop-error "The value accumulation recipient name, ~S, is not a symbol." name)) (unless name (loop-disallow-aggregate-booleans)) (unless dtype (setq dtype (or (loop-optional-type) default-type))) (let ((cruft (find (the symbol name) *loop-collection-cruft* :key #'loop-collector-name))) (cond ((not cruft) (when (and name (loop-var-p name)) (loop-error "Variable ~S in INTO clause is a duplicate" name)) (push (setq cruft (make-loop-collector :name name :class class :history (list collector) :dtype dtype)) *loop-collection-cruft*)) (t (unless (eq (loop-collector-class cruft) class) (loop-error "incompatible kinds of LOOP value accumulation specified for collecting~@ ~:[as the value of the LOOP~;~:*INTO ~S~]: ~S and ~S" name (car (loop-collector-history cruft)) collector)) (unless (equal dtype (loop-collector-dtype cruft)) (loop-warn "unequal datatypes specified in different LOOP value accumulations~@ into ~S: ~S and ~S" name dtype (loop-collector-dtype cruft)) (when (eq (loop-collector-dtype cruft) t) (setf (loop-collector-dtype cruft) dtype))) (push collector (loop-collector-history cruft)))) (values cruft form)))) (defun loop-list-collection (specifically) ; NCONC, LIST, or APPEND (multiple-value-bind (lc form) (loop-get-collection-info specifically 'list 'list) (let ((tempvars (loop-collector-tempvars lc))) (unless tempvars (setf (loop-collector-tempvars lc) (setq tempvars (list* (gensym "LOOP-LIST-HEAD-") (gensym "LOOP-LIST-TAIL-") (and (loop-collector-name lc) (list (loop-collector-name lc)))))) (push `(with-loop-list-collection-head ,tempvars) *loop-wrappers*) (unless (loop-collector-name lc) (loop-emit-final-value `(loop-collect-answer ,(car tempvars) ,@(cddr tempvars))))) (ecase specifically (list (setq form `(list ,form))) (nconc nil) (append (unless (and (consp form) (eq (car form) 'list)) (setq form `(copy-list ,form))))) (loop-emit-body `(loop-collect-rplacd ,tempvars ,form))))) ;;;; value accumulation: MAX, MIN, SUM, COUNT (defun loop-sum-collection (specifically required-type default-type);SUM, COUNT (multiple-value-bind (lc form) (loop-get-collection-info specifically 'sum default-type) (loop-check-data-type (loop-collector-dtype lc) required-type) (let ((tempvars (loop-collector-tempvars lc))) (unless tempvars (setf (loop-collector-tempvars lc) (setq tempvars (list (loop-make-var (or (loop-collector-name lc) (gensym "LOOP-SUM-")) nil (loop-collector-dtype lc))))) (unless (loop-collector-name lc) (loop-emit-final-value (car (loop-collector-tempvars lc))))) (loop-emit-body (if (eq specifically 'count) `(when ,form (setq ,(car tempvars) (1+ ,(car tempvars)))) `(setq ,(car tempvars) (+ ,(car tempvars) ,form))))))) (defun loop-maxmin-collection (specifically) (multiple-value-bind (lc form) (loop-get-collection-info specifically 'maxmin 'real) (loop-check-data-type (loop-collector-dtype lc) 'real) (let ((data (loop-collector-data lc))) (unless data (setf (loop-collector-data lc) (setq data (make-loop-minimax (or (loop-collector-name lc) (gensym "LOOP-MAXMIN-")) (loop-collector-dtype lc)))) (unless (loop-collector-name lc) (loop-emit-final-value (loop-minimax-answer-variable data)))) (loop-note-minimax-operation specifically data) (push `(with-minimax-value ,data) *loop-wrappers*) (loop-emit-body `(loop-accumulate-minimax-value ,data ,specifically ,form))))) ;;;; value accumulation: aggregate booleans ;;; handling the ALWAYS and NEVER loop keywords ;;; ;;; Under ANSI these are not permitted to appear under conditionalization. (defun loop-do-always (restrictive negate) (let ((form (loop-get-form))) (when restrictive (loop-disallow-conditional)) (loop-disallow-anonymous-collectors) (loop-emit-body `(,(if negate 'when 'unless) ,form ,(loop-construct-return nil))) (loop-emit-final-value t))) ;;; handling the THEREIS loop keyword ;;; ;;; Under ANSI this is not permitted to appear under conditionalization. (defun loop-do-thereis (restrictive) (when restrictive (loop-disallow-conditional)) (loop-disallow-anonymous-collectors) (loop-emit-final-value) (loop-emit-body `(when (setq ,(loop-when-it-var) ,(loop-get-form)) ,(loop-construct-return *loop-when-it-var*)))) (defun loop-do-while (negate kwd &aux (form (loop-get-form))) (loop-disallow-conditional kwd) (loop-pseudo-body `(,(if negate 'when 'unless) ,form (go end-loop)))) (defun loop-do-repeat () (loop-disallow-conditional :repeat) (let ((form (loop-get-form)) (type 'integer)) (let ((var (loop-make-var (gensym "LOOP-REPEAT-") `(ceiling ,form) type))) (push `(if (<= ,var 0) (go end-loop) (decf ,var)) *loop-before-loop*) (push `(if (<= ,var 0) (go end-loop) (decf ,var)) *loop-after-body*) ;; FIXME: What should ;; (loop count t into a ;; repeat 3 ;; count t into b ;; finally (return (list a b))) ;; return: (3 3) or (4 3)? PUSHes above are for the former ;; variant, L-P-B below for the latter. #+nil (loop-pseudo-body `(when (minusp (decf ,var)) (go end-loop)))))) (defun loop-do-with () (loop-disallow-conditional :with) (do ((var) (val) (dtype)) (nil) (setq var (loop-pop-source) dtype (loop-optional-type var) val (cond ((loop-tequal (car *loop-source-code*) :=) (loop-pop-source) (loop-get-form)) (t nil))) (when (and var (loop-var-p var)) (loop-error "Variable ~S has already been used" var)) (loop-make-var var val dtype) (if (loop-tequal (car *loop-source-code*) :and) (loop-pop-source) (return (loop-bind-block))))) ;;;; the iteration driver (defun loop-hack-iteration (entry) (flet ((make-endtest (list-of-forms) (cond ((null list-of-forms) nil) ((member t list-of-forms) '(go end-loop)) (t `(when ,(if (null (cdr (setq list-of-forms (nreverse list-of-forms)))) (car list-of-forms) (cons 'or list-of-forms)) (go end-loop)))))) (do ((pre-step-tests nil) (steps nil) (post-step-tests nil) (pseudo-steps nil) (pre-loop-pre-step-tests nil) (pre-loop-steps nil) (pre-loop-post-step-tests nil) (pre-loop-pseudo-steps nil) (tem) (data)) (nil) ;; Note that we collect endtests in reverse order, but steps in correct ;; order. MAKE-ENDTEST does the nreverse for us. (setq tem (setq data (apply (symbol-function (first entry)) (rest entry)))) (and (car tem) (push (car tem) pre-step-tests)) (setq steps (nconc steps (copy-list (car (setq tem (cdr tem)))))) (and (car (setq tem (cdr tem))) (push (car tem) post-step-tests)) (setq pseudo-steps (nconc pseudo-steps (copy-list (car (setq tem (cdr tem)))))) (setq tem (cdr tem)) (when *loop-emitted-body* (loop-error "iteration in LOOP follows body code")) (unless tem (setq tem data)) (when (car tem) (push (car tem) pre-loop-pre-step-tests)) ;; FIXME: This (SETF FOO (NCONC FOO BAR)) idiom appears often enough ;; that it might be worth making it into an NCONCF macro. (setq pre-loop-steps (nconc pre-loop-steps (copy-list (car (setq tem (cdr tem)))))) (when (car (setq tem (cdr tem))) (push (car tem) pre-loop-post-step-tests)) (setq pre-loop-pseudo-steps (nconc pre-loop-pseudo-steps (copy-list (cadr tem)))) (unless (loop-tequal (car *loop-source-code*) :and) (setq *loop-before-loop* (list* (loop-make-desetq pre-loop-pseudo-steps) (make-endtest pre-loop-post-step-tests) (loop-make-psetq pre-loop-steps) (make-endtest pre-loop-pre-step-tests) *loop-before-loop*)) (setq *loop-after-body* (list* (loop-make-desetq pseudo-steps) (make-endtest post-step-tests) (loop-make-psetq steps) (make-endtest pre-step-tests) *loop-after-body*)) (loop-bind-block) (return nil)) (loop-pop-source) ; Flush the "AND". (when (and (not (loop-universe-implicit-for-required *loop-universe*)) (setq tem (loop-lookup-keyword (car *loop-source-code*) (loop-universe-iteration-keywords *loop-universe*)))) ;; The latest ANSI clarification is that the FOR/AS after the AND must ;; NOT be supplied. (loop-pop-source) (setq entry tem))))) ;;;; main iteration drivers ;;; FOR variable keyword ..args.. (defun loop-do-for () (let* ((var (loop-pop-source)) (data-type (loop-optional-type var)) (keyword (loop-pop-source)) (first-arg nil) (tem nil)) (setq first-arg (loop-get-form)) (unless (and (symbolp keyword) (setq tem (loop-lookup-keyword keyword (loop-universe-for-keywords *loop-universe*)))) (loop-error "~S is an unknown keyword in FOR or AS clause in LOOP." keyword)) (apply (car tem) var first-arg data-type (cdr tem)))) (defun loop-when-it-var () (or *loop-when-it-var* (setq *loop-when-it-var* (loop-make-var (gensym "LOOP-IT-") nil nil)))) ;;;; various FOR/AS subdispatches ;;; ANSI "FOR x = y [THEN z]" is sort of like the old Genera one when ;;; the THEN is omitted (other than being more stringent in its ;;; placement), and like the old "FOR x FIRST y THEN z" when the THEN ;;; is present. I.e., the first initialization occurs in the loop body ;;; (first-step), not in the variable binding phase. (defun loop-ansi-for-equals (var val data-type) (loop-make-iteration-var var nil data-type) (cond ((loop-tequal (car *loop-source-code*) :then) ;; Then we are the same as "FOR x FIRST y THEN z". (loop-pop-source) `(() (,var ,(loop-get-form)) () () () (,var ,val) () ())) (t ;; We are the same as "FOR x = y". `(() (,var ,val) () ())))) (defun loop-for-across (var val data-type) (loop-make-iteration-var var nil data-type) (let ((vector-var (gensym "LOOP-ACROSS-VECTOR-")) (index-var (gensym "LOOP-ACROSS-INDEX-"))) (multiple-value-bind (vector-form constantp vector-value) (loop-constant-fold-if-possible val 'vector) (loop-make-var vector-var vector-form (if (and (consp vector-form) (eq (car vector-form) 'the)) (cadr vector-form) 'vector)) (loop-make-var index-var 0 'fixnum) (let* ((length 0) (length-form (cond ((not constantp) (let ((v (gensym "LOOP-ACROSS-LIMIT-"))) (push `(setq ,v (length ,vector-var)) *loop-prologue*) (loop-make-var v 0 'fixnum))) (t (setq length (length vector-value))))) (first-test `(>= ,index-var ,length-form)) (other-test first-test) (step `(,var (aref ,vector-var ,index-var))) (pstep `(,index-var (1+ ,index-var)))) (declare (fixnum length)) (when constantp (setq first-test (= length 0)) (when (<= length 1) (setq other-test t))) `(,other-test ,step () ,pstep ,@(and (not (eq first-test other-test)) `(,first-test ,step () ,pstep))))))) ;;;; list iteration (defun loop-list-step (listvar) ;; We are not equipped to analyze whether 'FOO is the same as #'FOO ;; here in any sensible fashion, so let's give an obnoxious warning ;; whenever 'FOO is used as the stepping function. ;; ;; While a Discerning Compiler may deal intelligently with ;; (FUNCALL 'FOO ...), not recognizing FOO may defeat some LOOP ;; optimizations. (let ((stepper (cond ((loop-tequal (car *loop-source-code*) :by) (loop-pop-source) (loop-get-form)) (t '(function cdr))))) (cond ((and (consp stepper) (eq (car stepper) 'quote)) (loop-warn "Use of QUOTE around stepping function in LOOP will be left verbatim.") `(funcall ,stepper ,listvar)) ((and (consp stepper) (eq (car stepper) 'function)) (list (cadr stepper) listvar)) (t `(funcall ,(loop-make-var (gensym "LOOP-FN-") stepper 'function) ,listvar))))) (defun loop-for-on (var val data-type) (multiple-value-bind (list constantp list-value) (loop-constant-fold-if-possible val) (let ((listvar var)) (cond ((and var (symbolp var)) (loop-make-iteration-var var list data-type)) (t (loop-make-var (setq listvar (gensym)) list 'list) (loop-make-iteration-var var nil data-type))) (let ((list-step (loop-list-step listvar))) (let* ((first-endtest ;; mysterious comment from original CMU CL sources: ;; the following should use `atom' instead of `endp', ;; per [bug2428] `(atom ,listvar)) (other-endtest first-endtest)) (when (and constantp (listp list-value)) (setq first-endtest (null list-value))) (cond ((eq var listvar) ;; The contour of the loop is different because we ;; use the user's variable... `(() (,listvar ,list-step) ,other-endtest () () () ,first-endtest ())) (t (let ((step `(,var ,listvar)) (pseudo `(,listvar ,list-step))) `(,other-endtest ,step () ,pseudo ,@(and (not (eq first-endtest other-endtest)) `(,first-endtest ,step () ,pseudo))))))))))) (defun loop-for-in (var val data-type) (multiple-value-bind (list constantp list-value) (loop-constant-fold-if-possible val) (let ((listvar (gensym "LOOP-LIST-"))) (loop-make-iteration-var var nil data-type) (loop-make-var listvar list 'list) (let ((list-step (loop-list-step listvar))) (let* ((first-endtest `(endp ,listvar)) (other-endtest first-endtest) (step `(,var (car ,listvar))) (pseudo-step `(,listvar ,list-step))) (when (and constantp (listp list-value)) (setq first-endtest (null list-value))) `(,other-endtest ,step () ,pseudo-step ,@(and (not (eq first-endtest other-endtest)) `(,first-endtest ,step () ,pseudo-step)))))))) ;;;; iteration paths (defstruct (loop-path (:copier nil) (:predicate nil)) names preposition-groups inclusive-permitted function user-data) (defun add-loop-path (names function universe &key preposition-groups inclusive-permitted user-data) (declare (type loop-universe universe)) (unless (listp names) (setq names (list names))) (let ((ht (loop-universe-path-keywords universe)) (lp (make-loop-path :names (mapcar #'symbol-name names) :function function :user-data user-data :preposition-groups (mapcar (lambda (x) (if (listp x) x (list x))) preposition-groups) :inclusive-permitted inclusive-permitted))) (dolist (name names) (setf (gethash (symbol-name name) ht) lp)) lp)) ;;; Note: Path functions are allowed to use LOOP-MAKE-VAR, hack ;;; the prologue, etc. (defun loop-for-being (var val data-type) ;; FOR var BEING each/the pathname prep-phrases using-stuff... each/the = ;; EACH or THE. Not clear if it is optional, so I guess we'll warn. (let ((path nil) (data nil) (inclusive nil) (stuff nil) (initial-prepositions nil)) (cond ((loop-tmember val '(:each :the)) (setq path (loop-pop-source))) ((loop-tequal (car *loop-source-code*) :and) (loop-pop-source) (setq inclusive t) (unless (loop-tmember (car *loop-source-code*) '(:its :each :his :her)) (loop-error "~S was found where ITS or EACH expected in LOOP iteration path syntax." (car *loop-source-code*))) (loop-pop-source) (setq path (loop-pop-source)) (setq initial-prepositions `((:in ,val)))) (t (loop-error "unrecognizable LOOP iteration path syntax: missing EACH or THE?"))) (cond ((not (symbolp path)) (loop-error "~S was found where a LOOP iteration path name was expected." path)) ((not (setq data (loop-lookup-keyword path (loop-universe-path-keywords *loop-universe*)))) (loop-error "~S is not the name of a LOOP iteration path." path)) ((and inclusive (not (loop-path-inclusive-permitted data))) (loop-error "\"Inclusive\" iteration is not possible with the ~S LOOP iteration path." path))) (let ((fun (loop-path-function data)) (preps (nconc initial-prepositions (loop-collect-prepositional-phrases (loop-path-preposition-groups data) t))) (user-data (loop-path-user-data data))) (when (symbolp fun) (setq fun (symbol-function fun))) (setq stuff (if inclusive (apply fun var data-type preps :inclusive t user-data) (apply fun var data-type preps user-data)))) (when *loop-named-vars* (loop-error "Unused USING vars: ~S." *loop-named-vars*)) ;; STUFF is now (bindings prologue-forms . stuff-to-pass-back). ;; Protect the system from the user and the user from himself. (unless (member (length stuff) '(6 10)) (loop-error "Value passed back by LOOP iteration path function for path ~S has invalid length." path)) (do ((l (car stuff) (cdr l)) (x)) ((null l)) (if (atom (setq x (car l))) (loop-make-iteration-var x nil nil) (loop-make-iteration-var (car x) (cadr x) (caddr x)))) (setq *loop-prologue* (nconc (reverse (cadr stuff)) *loop-prologue*)) (cddr stuff))) (defun loop-named-var (name) (let ((tem (loop-tassoc name *loop-named-vars*))) (declare (list tem)) (cond ((null tem) (values (gensym) nil)) (t (setq *loop-named-vars* (delete tem *loop-named-vars*)) (values (cdr tem) t))))) (defun loop-collect-prepositional-phrases (preposition-groups &optional using-allowed initial-phrases) (flet ((in-group-p (x group) (car (loop-tmember x group)))) (do ((token nil) (prepositional-phrases initial-phrases) (this-group nil nil) (this-prep nil nil) (disallowed-prepositions (mapcan (lambda (x) (copy-list (find (car x) preposition-groups :test #'in-group-p))) initial-phrases)) (used-prepositions (mapcar #'car initial-phrases))) ((null *loop-source-code*) (nreverse prepositional-phrases)) (declare (symbol this-prep)) (setq token (car *loop-source-code*)) (dolist (group preposition-groups) (when (setq this-prep (in-group-p token group)) (return (setq this-group group)))) (cond (this-group (when (member this-prep disallowed-prepositions) (loop-error (if (member this-prep used-prepositions) "A ~S prepositional phrase occurs multiply for some LOOP clause." "Preposition ~S was used when some other preposition has subsumed it.") token)) (setq used-prepositions (if (listp this-group) (append this-group used-prepositions) (cons this-group used-prepositions))) (loop-pop-source) (push (list this-prep (loop-get-form)) prepositional-phrases)) ((and using-allowed (loop-tequal token 'using)) (loop-pop-source) (do ((z (loop-pop-source) (loop-pop-source)) (tem)) (nil) (when (cadr z) (if (setq tem (loop-tassoc (car z) *loop-named-vars*)) (loop-error "The variable substitution for ~S occurs twice in a USING phrase,~@ with ~S and ~S." (car z) (cadr z) (cadr tem)) (push (cons (car z) (cadr z)) *loop-named-vars*))) (when (or (null *loop-source-code*) (symbolp (car *loop-source-code*))) (return nil)))) (t (return (nreverse prepositional-phrases))))))) ;;;; master sequencer function (defun loop-sequencer (indexv indexv-type variable variable-type sequence-variable sequence-type step-hack default-top prep-phrases) (let ((endform nil) ; form (constant or variable) with limit value (sequencep nil) ; T if sequence arg has been provided (testfn nil) ; endtest function (test nil) ; endtest form (stepby (1+ (or (loop-typed-init indexv-type) 0))) ; our increment (stepby-constantp t) (step nil) ; step form (dir nil) ; direction of stepping: NIL, :UP, :DOWN (inclusive-iteration nil) ; T if include last index (start-given nil) ; T when prep phrase has specified start (start-value nil) (start-constantp nil) (limit-given nil) ; T when prep phrase has specified end (limit-constantp nil) (limit-value nil) ) (flet ((assert-index-for-arithmetic (index) (unless (atom index) (loop-error "Arithmetic index must be an atom.")))) (when variable (loop-make-iteration-var variable nil variable-type)) (do ((l prep-phrases (cdr l)) (prep) (form) (odir)) ((null l)) (setq prep (caar l) form (cadar l)) (case prep ((:of :in) (setq sequencep t) (loop-make-var sequence-variable form sequence-type)) ((:from :downfrom :upfrom) (setq start-given t) (cond ((eq prep :downfrom) (setq dir ':down)) ((eq prep :upfrom) (setq dir ':up))) (multiple-value-setq (form start-constantp start-value) (loop-constant-fold-if-possible form indexv-type)) (assert-index-for-arithmetic indexv) ;; KLUDGE: loop-make-var generates a temporary symbol for ;; indexv if it is NIL. We have to use it to have the index ;; actually count (setq indexv (loop-make-iteration-var indexv form indexv-type))) ((:upto :to :downto :above :below) (cond ((loop-tequal prep :upto) (setq inclusive-iteration (setq dir ':up))) ((loop-tequal prep :to) (setq inclusive-iteration t)) ((loop-tequal prep :downto) (setq inclusive-iteration (setq dir ':down))) ((loop-tequal prep :above) (setq dir ':down)) ((loop-tequal prep :below) (setq dir ':up))) (setq limit-given t) (multiple-value-setq (form limit-constantp limit-value) (loop-constant-fold-if-possible form `(and ,indexv-type real))) (setq endform (if limit-constantp `',limit-value (loop-make-var (gensym "LOOP-LIMIT-") form `(and ,indexv-type real))))) (:by (multiple-value-setq (form stepby-constantp stepby) (loop-constant-fold-if-possible form `(and ,indexv-type (real (0))))) (unless stepby-constantp (loop-make-var (setq stepby (gensym "LOOP-STEP-BY-")) form `(and ,indexv-type (real (0))) nil t))) (t (loop-error "~S invalid preposition in sequencing or sequence path;~@ maybe invalid prepositions were specified in iteration path descriptor?" prep))) (when (and odir dir (not (eq dir odir))) (loop-error "conflicting stepping directions in LOOP sequencing path")) (setq odir dir)) (when (and sequence-variable (not sequencep)) (loop-error "missing OF or IN phrase in sequence path")) ;; Now fill in the defaults. (if start-given (when limit-given ;; if both start and limit are given, they had better both ;; be REAL. We already enforce the REALness of LIMIT, ;; above; here's the KLUDGE to enforce the type of START. (flet ((type-declaration-of (x) (and (eq (car x) 'type) (caddr x)))) (let ((decl (find indexv *loop-declarations* :key #'type-declaration-of)) (%decl (find indexv *loop-declarations* :key #'type-declaration-of :from-end t))) #+sbcl (aver (eq decl %decl)) #-sbcl (declare (ignore %decl)) (setf (cadr decl) `(and real ,(cadr decl)))))) ;; default start ;; DUPLICATE KLUDGE: loop-make-var generates a temporary ;; symbol for indexv if it is NIL. See also the comment in ;; the (:from :downfrom :upfrom) case (progn (assert-index-for-arithmetic indexv) (setq indexv (loop-make-iteration-var indexv (setq start-constantp t start-value (or (loop-typed-init indexv-type) 0)) `(and ,indexv-type real))))) (cond ((member dir '(nil :up)) (when (or limit-given default-top) (unless limit-given (loop-make-var (setq endform (gensym "LOOP-SEQ-LIMIT-")) nil indexv-type) (push `(setq ,endform ,default-top) *loop-prologue*)) (setq testfn (if inclusive-iteration '> '>=))) (setq step (if (eql stepby 1) `(1+ ,indexv) `(+ ,indexv ,stepby)))) (t (unless start-given (unless default-top (loop-error "don't know where to start stepping")) (push `(setq ,indexv (1- ,default-top)) *loop-prologue*)) (when (and default-top (not endform)) (setq endform (loop-typed-init indexv-type) inclusive-iteration t)) (when endform (setq testfn (if inclusive-iteration '< '<=))) (setq step (if (eql stepby 1) `(1- ,indexv) `(- ,indexv ,stepby))))) (when testfn (setq test `(,testfn ,indexv ,endform))) (when step-hack (setq step-hack `(,variable ,step-hack))) (let ((first-test test) (remaining-tests test)) (when (and stepby-constantp start-constantp limit-constantp (realp start-value) (realp limit-value)) (when (setq first-test (funcall (symbol-function testfn) start-value limit-value)) (setq remaining-tests t))) `(() (,indexv ,step) ,remaining-tests ,step-hack () () ,first-test ,step-hack))))) ;;;; interfaces to the master sequencer (defun loop-for-arithmetic (var val data-type kwd) (loop-sequencer var (loop-check-data-type data-type 'number) nil nil nil nil nil nil (loop-collect-prepositional-phrases '((:from :upfrom :downfrom) (:to :upto :downto :above :below) (:by)) nil (list (list kwd val))))) (defun loop-sequence-elements-path (variable data-type prep-phrases &key fetch-function size-function sequence-type element-type) (multiple-value-bind (indexv) (loop-named-var 'index) (let ((sequencev (loop-named-var 'sequence))) (list* nil nil ; dummy bindings and prologue (loop-sequencer indexv 'fixnum variable (or data-type element-type) sequencev sequence-type `(,fetch-function ,sequencev ,indexv) `(,size-function ,sequencev) prep-phrases))))) ;;;; builtin LOOP iteration paths #|| (loop for v being the hash-values of ht do (print v)) (loop for k being the hash-keys of ht do (print k)) (loop for v being the hash-values of ht using (hash-key k) do (print (list k v))) (loop for k being the hash-keys of ht using (hash-value v) do (print (list k v))) ||# (defun loop-hash-table-iteration-path (variable data-type prep-phrases &key which) (declare (type (member :hash-key :hash-value) which)) (cond ((or (cdr prep-phrases) (not (member (caar prep-phrases) '(:in :of)))) (loop-error "too many prepositions!")) ((null prep-phrases) (loop-error "missing OF or IN in ~S iteration path"))) (let ((ht-var (gensym "LOOP-HASHTAB-")) (next-fn (gensym "LOOP-HASHTAB-NEXT-")) (dummy-predicate-var nil) (post-steps nil)) (multiple-value-bind (other-var other-p) (loop-named-var (ecase which (:hash-key 'hash-value) (:hash-value 'hash-key))) ;; @@@@ LOOP-NAMED-VAR returns a second value of T if the name was ;; actually specified, so clever code can throw away the GENSYM'ed-up ;; variable if it isn't really needed. (unless other-p (push `(ignorable ,other-var) *loop-declarations*)) ;; The following is for those implementations in which we cannot put ;; dummy NILs into MULTIPLE-VALUE-SETQ variable lists. (setq other-p t dummy-predicate-var (loop-when-it-var)) (let* ((key-var nil) (val-var nil) (variable (or variable (gensym "LOOP-HASH-VAR-TEMP-"))) (bindings `((,variable nil ,data-type) (,ht-var ,(cadar prep-phrases)) ,@(and other-p other-var `((,other-var nil)))))) (ecase which (:hash-key (setq key-var variable val-var (and other-p other-var))) (:hash-value (setq key-var (and other-p other-var) val-var variable))) (push `(with-hash-table-iterator (,next-fn ,ht-var)) *loop-wrappers*) (when (or (consp key-var) data-type) (setq post-steps `(,key-var ,(setq key-var (gensym "LOOP-HASH-KEY-TEMP-")) ,@post-steps)) (push `(,key-var nil) bindings)) (when (or (consp val-var) data-type) (setq post-steps `(,val-var ,(setq val-var (gensym "LOOP-HASH-VAL-TEMP-")) ,@post-steps)) (push `(,val-var nil) bindings)) (push `(ignorable ,dummy-predicate-var) *loop-declarations*) `(,bindings ;bindings () ;prologue () ;pre-test () ;parallel steps (not (multiple-value-setq (,dummy-predicate-var ,key-var ,val-var) (,next-fn))) ;post-test ,post-steps))))) (defun loop-package-symbols-iteration-path (variable data-type prep-phrases &key symbol-types) (cond ((and prep-phrases (cdr prep-phrases)) (loop-error "Too many prepositions!")) ((and prep-phrases (not (member (caar prep-phrases) '(:in :of)))) (loop-error "Unknown preposition ~S." (caar prep-phrases)))) (unless (symbolp variable) (loop-error "Destructuring is not valid for package symbol iteration.")) (let ((pkg-var (gensym "LOOP-PKGSYM-")) (next-fn (gensym "LOOP-PKGSYM-NEXT-")) (variable (or variable (gensym "LOOP-PKGSYM-VAR-"))) (package (or (cadar prep-phrases) '*package*))) (push `(with-package-iterator (,next-fn ,pkg-var ,@symbol-types)) *loop-wrappers*) (push `(ignorable ,(loop-when-it-var)) *loop-declarations*) `(((,variable nil ,data-type) (,pkg-var ,package)) () () () (not (multiple-value-setq (,(loop-when-it-var) ,variable) (,next-fn))) ()))) ;;;; ANSI LOOP (defun make-ansi-loop-universe (extended-p) (let ((w (make-standard-loop-universe :keywords '((named (loop-do-named)) (initially (loop-do-initially)) (finally (loop-do-finally)) (do (loop-do-do)) (doing (loop-do-do)) (return (loop-do-return)) (collect (loop-list-collection list)) (collecting (loop-list-collection list)) (append (loop-list-collection append)) (appending (loop-list-collection append)) (nconc (loop-list-collection nconc)) (nconcing (loop-list-collection nconc)) (count (loop-sum-collection count real fixnum)) (counting (loop-sum-collection count real fixnum)) (sum (loop-sum-collection sum number number)) (summing (loop-sum-collection sum number number)) (maximize (loop-maxmin-collection max)) (minimize (loop-maxmin-collection min)) (maximizing (loop-maxmin-collection max)) (minimizing (loop-maxmin-collection min)) (always (loop-do-always t nil)) ; Normal, do always (never (loop-do-always t t)) ; Negate test on always. (thereis (loop-do-thereis t)) (while (loop-do-while nil :while)) ; Normal, do while (until (loop-do-while t :until)) ;Negate test on while (when (loop-do-if when nil)) ; Normal, do when (if (loop-do-if if nil)) ; synonymous (unless (loop-do-if unless t)) ; Negate test on when (with (loop-do-with)) (repeat (loop-do-repeat))) :for-keywords '((= (loop-ansi-for-equals)) (across (loop-for-across)) (in (loop-for-in)) (on (loop-for-on)) (from (loop-for-arithmetic :from)) (downfrom (loop-for-arithmetic :downfrom)) (upfrom (loop-for-arithmetic :upfrom)) (below (loop-for-arithmetic :below)) (above (loop-for-arithmetic :above)) (to (loop-for-arithmetic :to)) (upto (loop-for-arithmetic :upto)) (downto (loop-for-arithmetic :downto)) (by (loop-for-arithmetic :by)) (being (loop-for-being))) :iteration-keywords '((for (loop-do-for)) (as (loop-do-for))) :type-symbols '(array atom bignum bit bit-vector character compiled-function complex cons double-float fixnum float function hash-table integer keyword list long-float nil null number package pathname random-state ratio rational readtable sequence short-float simple-array simple-bit-vector simple-string simple-vector single-float standard-char stream string base-char symbol t vector) :type-keywords nil :ansi (if extended-p :extended t)))) (add-loop-path '(hash-key hash-keys) 'loop-hash-table-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:which :hash-key)) (add-loop-path '(hash-value hash-values) 'loop-hash-table-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:which :hash-value)) (add-loop-path '(symbol symbols) 'loop-package-symbols-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:symbol-types (:internal :external :inherited))) (add-loop-path '(external-symbol external-symbols) 'loop-package-symbols-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:symbol-types (:external))) (add-loop-path '(present-symbol present-symbols) 'loop-package-symbols-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:symbol-types (:internal :external))) w)) (defparameter *loop-ansi-universe* (make-ansi-loop-universe nil)) (defun loop-standard-expansion (keywords-and-forms environment universe) (if (and keywords-and-forms (symbolp (car keywords-and-forms))) (loop-translate keywords-and-forms environment universe) (let ((tag (gensym))) `(block nil (tagbody ,tag (progn ,@keywords-and-forms) (go ,tag)))))) (defmacro loop (&environment env &rest keywords-and-forms) (loop-standard-expansion keywords-and-forms env *loop-ansi-universe*)) (defmacro loop-finish () "Cause the iteration to terminate \"normally\", the same as implicit termination by an iteration driving clause, or by use of WHILE or UNTIL -- the epilogue code (if any) will be run, and any implicitly collected result will be returned as the value of the LOOP." '(go end-loop)) (provide "LOOP") abcl-src-1.9.0/src/org/armedbear/lisp/machine_type.java0100644 0000000 0000000 00000003767 14202767264 021544 0ustar000000000 0000000 /* * machine_type.java * * Copyright (C) 2004-2007 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### machine-type public final class machine_type extends Primitive { private machine_type() { super("machine-type"); } @Override public LispObject execute() { String s = System.getProperty("os.arch"); if (s == null) s = "UNKNOWN"; else if (s.equals("amd64")) s = "X86-64"; else s = s.toUpperCase(); return new SimpleString(s); } private static final Primitive MACHINE_TYPE = new machine_type(); } abcl-src-1.9.0/src/org/armedbear/lisp/machine_version.java0100644 0000000 0000000 00000006115 14202767264 022236 0ustar000000000 0000000 /* * machine_version.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; // ### machine-version public final class machine_version extends Primitive { private machine_version() { super("machine-version"); } @Override public LispObject execute() { String osName = System.getProperty("os.name"); if (osName != null && osName.toLowerCase().startsWith("linux")) { try { FileInputStream in = new FileInputStream("/proc/cpuinfo"); if (in != null) { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); try { String s; while ((s = reader.readLine()) != null) { int start = s.indexOf("model name"); if (start >= 0) { start = s.indexOf(':', start); if (start >= 0) { return new SimpleString(s.substring(start + 1).trim()); } } } } finally { reader.close(); } } } catch (IOException e) {} } return NIL; } private static final Primitive MACHINE_VERSION = new machine_version(); } abcl-src-1.9.0/src/org/armedbear/lisp/macros.lisp0100644 0000000 0000000 00000014703 14223403213 020361 0ustar000000000 0000000 ;;; macros.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (export 'defconst) (defmacro in-package (name) `(%in-package ,(string name))) (defmacro when (test-form &rest body) (if (cdr body) `(if ,test-form (progn ,@body)) `(if ,test-form ,(car body)))) (defmacro unless (test-form &rest body) (if (cdr body) `(if (not ,test-form) (progn ,@body)) `(if (not ,test-form) ,(car body)))) (defmacro return (&optional result) `(return-from nil ,result)) (defmacro defconstant (name initial-value &optional docstring) `(progn (record-source-information-for-type ',name :constant) (%defconstant ',name ,initial-value ,docstring))) (defmacro defparameter (name initial-value &optional docstring) `(progn (record-source-information-for-type ',name :variable) (%defparameter ',name ,initial-value ,docstring))) (defmacro truly-the (type value) `(the ,type ,value)) (defmacro %car (x) `(car (truly-the cons ,x))) (defmacro %cdr (x) `(cdr (truly-the cons ,x))) (defmacro %cadr (x) `(%car (%cdr ,x))) (defmacro %caddr (x) `(%car (%cdr (%cdr ,x)))) (defmacro prog1 (first-form &rest forms) (let ((result (gensym))) `(let ((,result ,first-form)) ,@forms ,result))) (defmacro prog2 (first-form second-form &rest forms) `(prog1 (progn ,first-form ,second-form) ,@forms)) ;; Adapted from SBCL. (defmacro push (&environment env item place) (if (and (symbolp place) (eq place (macroexpand place env))) `(setq ,place (cons ,item ,place)) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion place env) (let ((g (gensym))) `(let* ((,g ,item) ,@(mapcar #'list dummies vals) (,(car newval) (cons ,g ,getter))) ,setter))))) ;; Adapted from SBCL. (defmacro pushnew (&environment env item place &rest keys) (if (and (symbolp place) (eq place (macroexpand place env))) `(setq ,place (adjoin ,item ,place ,@keys)) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion place env) (let ((g (gensym))) `(let* ((,g ,item) ,@(mapcar #'list dummies vals) (,(car newval) (adjoin ,g ,getter ,@keys))) ,setter))))) ;; Adapted from SBCL. (defmacro pop (&environment env place) (if (and (symbolp place) (eq place (macroexpand place env))) `(prog1 (car ,place) (setq ,place (cdr ,place))) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion place env) (do* ((d dummies (cdr d)) (v vals (cdr v)) (let-list nil)) ((null d) (push (list (car newval) getter) let-list) `(let* ,(nreverse let-list) (prog1 (car ,(car newval)) (setq ,(car newval) (cdr ,(car newval))) ,setter))) (push (list (car d) (car v)) let-list))))) (defmacro psetq (&environment env &rest args) (do ((l args (cddr l)) (forms nil) (bindings nil)) ((endp l) (list* 'let* (reverse bindings) (reverse (cons nil forms)))) (if (and (symbolp (car l)) (eq (car l) (macroexpand-1 (car l) env))) (let ((sym (gensym))) (push (list sym (cadr l)) bindings) (push (list 'setq (car l) sym) forms)) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion (macroexpand-1 (car l) env) env) (declare (ignore getter)) (do ((d dummies (cdr d)) (v vals (cdr v))) ((null d)) (push (list (car d) (car v)) bindings)) (push (list (car newval) (cadr l)) bindings) (push setter forms))))) (defmacro time (form) `(%time #'(lambda () ,form))) (defmacro with-open-stream (&rest args) (let ((var (caar args)) (stream (cadar args)) (forms (cdr args)) (abortp (gensym))) `(let ((,var ,stream) (,abortp t)) (unwind-protect (multiple-value-prog1 (progn ,@forms) (setq ,abortp nil)) (when ,var (close ,var :abort ,abortp)))))) (defun ansi-loop (exps) (let ((*warn-on-redefinition* nil)) (require 'loop)) (fmakunbound 'ansi-loop) `(loop ,@exps)) (defmacro loop (&rest exps) (dolist (exp exps) (when (atom exp) (return-from loop (ansi-loop exps)))) (let ((tag (gensym))) `(block nil (tagbody ,tag ,@exps (go ,tag))))) (defmacro defvar (var &optional (val nil valp) (doc nil docp)) `(progn (sys::record-source-information-for-type ',var :variable) (%defvar ',var) ,@(when valp `((unless (boundp ',var) (setq ,var ,val)))) ,@(when docp `((%set-documentation ',var 'variable ',doc))) ',var)) (defmacro defconst (name value) `(defconstant ,name (if (boundp ',name) (symbol-value ',name) ,value))) abcl-src-1.9.0/src/org/armedbear/lisp/make-hash-table.lisp0100644 0000000 0000000 00000004722 14223403213 022020 0ustar000000000 0000000 ;;; make-hash-table.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun make-hash-table (&key (test 'eql) (size 11) (rehash-size 1.5) (rehash-threshold 0.75) (weakness nil)) (setf test (coerce-to-function test)) (unless (and (integerp size) (>= size 0)) (error 'type-error :datum size :expected-type '(integer 0))) (let ((size (max 11 (min size array-dimension-limit))) (weakness-types '(or (eql :key) (eql :value) (eql :key-and-value) (eql :key-or-value)))) (if weakness (if (not (typep weakness weakness-types)) (error 'type-error :datum weakness :expected-type weakness-types) (%make-weak-hash-table test size rehash-size rehash-threshold weakness)) (%make-hash-table test size rehash-size rehash-threshold)))) abcl-src-1.9.0/src/org/armedbear/lisp/make-load-form-saving-slots.lisp0100644 0000000 0000000 00000005527 14202767264 024343 0ustar000000000 0000000 ;;; make-load-form-saving-slots.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (resolve 'defstruct) (defun make-load-form-saving-slots (object &key slot-names environment) (declare (ignore environment)) (let ((class (class-of object)) (inits ()) (instance (gensym "INSTANCE-"))) (cond ((typep object 'structure-object) (let ((index 0)) (dolist (slot (mop:class-slots class)) (let ((slot-name (dsd-name slot))) (when (or (memq slot-name slot-names) (null slot-names)) (let ((value (structure-ref object index))) (push `(structure-set ,instance ,index ',value) inits)))) (incf index)))) ((typep object 'standard-object) (dolist (slot (mop:class-slots class)) (let ((slot-name (mop:slot-definition-name slot))) (when (or (memq slot-name slot-names) (null slot-names)) (when (slot-boundp object slot-name) (let ((value (slot-value object slot-name))) (push `(setf (slot-value ,instance ',slot-name) ',value) inits)))))))) (values `(let ((,instance (allocate-instance (find-class ',(%class-name class))))) (progn ,@inits) ,instance) nil))) abcl-src-1.9.0/src/org/armedbear/lisp/make-sequence.lisp0100644 0000000 0000000 00000014731 14223403213 021621 0ustar000000000 0000000 ;;; make-sequence.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) ;;; Adapted from ECL. (defun size-mismatch-error (type size) (error 'simple-type-error :format-control "The requested length (~D) does not match the specified type ~A." :format-arguments (list size type))) (defun make-sequence (type size &key (initial-element nil iesp)) (let (element-type sequence class) (setf type (normalize-type type)) (cond ((atom type) (setf class (if (classp type) type (find-class type nil))) (when (classp type) (let ((class-name (%class-name type))) (when (member class-name '(LIST CONS STRING SIMPLE-STRING BASE-STRING SIMPLE-BASE-STRING NULL BIT-VECTOR SIMPLE-BIT-VECTOR VECTOR SIMPLE-VECTOR)) (setf type class-name)))) ;;Else we suppose it's a user-defined sequence and move on (cond ((memq type '(LIST CONS)) (when (zerop size) (if (eq type 'CONS) (size-mismatch-error type size) (return-from make-sequence nil))) (return-from make-sequence (if iesp (make-list size :initial-element initial-element) (make-list size)))) ((memq type '(STRING SIMPLE-STRING BASE-STRING SIMPLE-BASE-STRING)) (return-from make-sequence (if iesp (make-string size :initial-element initial-element) (make-string size)))) ((eq type 'NULL) (if (zerop size) (return-from make-sequence nil) (size-mismatch-error type size))) (t (setq element-type (cond ((memq type '(BIT-VECTOR SIMPLE-BIT-VECTOR)) 'BIT) ((memq type '(VECTOR SIMPLE-VECTOR)) t) ((null class) (error 'simple-type-error :format-control "~S is not a sequence type." :format-arguments (list type)))))))) (t (let ((name (%car type)) (args (%cdr type))) (when (eq name 'LIST) (return-from make-sequence (if iesp (make-list size :initial-element initial-element) (make-list size)))) (when (eq name 'CONS) (unless (plusp size) (size-mismatch-error name size)) (return-from make-sequence (if iesp (make-list size :initial-element initial-element) (make-list size)))) (unless (memq name '(ARRAY SIMPLE-ARRAY VECTOR SIMPLE-VECTOR BIT-VECTOR SIMPLE-BIT-VECTOR STRING SIMPLE-STRING BASE-STRING SIMPLE-BASE-STRING)) (error 'simple-type-error :format-control "~S is not a sequence type." :format-arguments (list type))) (let ((len nil)) (cond ((memq name '(STRING SIMPLE-STRING BASE-STRING SIMPLE-BASE-STRING)) (setf element-type 'character len (car args))) ((memq name '(ARRAY SIMPLE-ARRAY)) (setf element-type (or (car args) t) len (if (consp (cadr args)) (caadr args) '*))) ((memq name '(BIT-VECTOR SIMPLE-BIT-VECTOR)) (setf element-type 'bit len (car args))) (t (setf element-type (or (car args) t) len (cadr args)))) (unless (or (null len) (eq len '*) (equal len '(*))) (when (/= size len) (size-mismatch-error type size))))))) (setq sequence (cond ((or (not (atom type)) (subtypep type 'array)) (if iesp (make-array size :element-type element-type :initial-element initial-element) (make-array size :element-type element-type))) ((and class (subtypep type 'sequence)) (if iesp (sequence:make-sequence-like (mop::class-prototype class) size :initial-element initial-element) (sequence:make-sequence-like (mop::class-prototype class) size))) (t (error 'simple-type-error :format-control "~S is not a sequence type." :format-arguments (list type))))) sequence)) abcl-src-1.9.0/src/org/armedbear/lisp/make-string-output-stream.lisp0100644 0000000 0000000 00000003257 14202767264 024167 0ustar000000000 0000000 ;;; make-string-output-stream.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun make-string-output-stream (&key (element-type 'character)) (%make-string-output-stream element-type)) abcl-src-1.9.0/src/org/armedbear/lisp/make-string.lisp0100644 0000000 0000000 00000003242 14202767264 021332 0ustar000000000 0000000 ;;; make-string.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun make-string (size &key initial-element element-type) (%make-string size initial-element element-type)) abcl-src-1.9.0/src/org/armedbear/lisp/make_array.java0100644 0000000 0000000 00000042330 14202767264 021177 0ustar000000000 0000000 /* * make_array.java * * Copyright (C) 2003-2005 Peter Graves * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import org.armedbear.lisp.Java.Buffers.AllocationPolicy; import static org.armedbear.lisp.Lisp.*; // ### %make-array dimensions element-type initial-element initial-element-p initial-contents adjustable fill-pointer displaced-to displaced-index-offset nio-buffer nio-buffer-provided-p // => new-array public final class make_array extends Primitive { public make_array() { super("%make-array", PACKAGE_SYS, false); } @Override public LispObject execute(LispObject[] args) { // What a mess without keywords, but it still works… if (args.length != 13) { return error(new WrongNumberOfArgumentsException(this, 13)); } LispObject dimensions = args[0]; LispObject elementType = args[1]; LispObject initialElement = args[2]; LispObject initialElementProvided = args[3]; LispObject initialContents = args[4]; LispObject adjustable = args[5]; LispObject fillPointer = args[6]; LispObject displacedTo = args[7]; LispObject displacedIndexOffset = args[8]; LispObject direct = args[9]; // boolean whether to do a direct allocation for nio capable vectors // LispObject directProvided = args[10]; // UNUSED but included for consistency boolean directAllocation = direct.equals(NIL) ? false : true; LispObject nioBuffer = args[11]; LispObject nioBufferProvided = args[12]; if (initialElementProvided != NIL && initialContents != NIL) { return error(new LispError("MAKE-ARRAY: cannot specify both " + "initial element and initial contents.")); } final int rank = dimensions.listp() ? dimensions.length() : 1; int[] dimv = new int[rank]; if (dimensions.listp()) { for (int i = 0; i < rank; i++) { LispObject dim = dimensions.car(); dimv[i] = Fixnum.getValue(dim); dimensions = dimensions.cdr(); } } else { dimv[0] = Fixnum.getValue(dimensions); } if (displacedTo != NIL) { // FIXME Make sure element type (if specified) is compatible with // displaced-to array. final AbstractArray array = checkArray(displacedTo); if (initialElementProvided != NIL) { return error(new LispError("Initial element must not be specified for a displaced array.")); } if (initialContents != NIL) { return error(new LispError("Initial contents must not be specified for a displaced array.")); } final int displacement; if (displacedIndexOffset != NIL) { displacement = Fixnum.getValue(displacedIndexOffset); } else { displacement = 0; } if (rank == 1) { AbstractVector v = null; // FIXME needed to get the compiler not to warn LispObject arrayElementType = array.getElementType(); if (arrayElementType == Symbol.CHARACTER) { v = new ComplexString(dimv[0], array, displacement); } else if (arrayElementType == Symbol.BIT) { v = new ComplexBitVector(dimv[0], array, displacement); } else if (arrayElementType.equal(UNSIGNED_BYTE_8)) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { // an abstract array doesn't have a directAllocation ??? v = new ComplexVector_ByteBuffer(dimv[0], array, displacement, directAllocation); } else { // if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) v = new ComplexVector_UnsignedByte8(dimv[0], array, displacement); } } else if (arrayElementType.equal(UNSIGNED_BYTE_32)) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { // an abstract array doesn't have a directAllocation ??? v = new ComplexVector_IntBuffer(dimv[0], array, displacement, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) v = new ComplexVector_UnsignedByte32(dimv[0], array, displacement); } } else { v = new ComplexVector(dimv[0], array, displacement); } if (fillPointer != NIL) { v.setFillPointer(fillPointer); } return v; } return new ComplexArray(dimv, array, displacement); } LispObject upgradedType = getUpgradedArrayElementType(elementType); if (rank == 0) { LispObject data; if (initialElementProvided != NIL) { data = initialElement; } else { data = initialContents; } return new ZeroRankArray(upgradedType, data, adjustable != NIL); } else if (rank == 1) { final int size = dimv[0]; if (size < 0 || size >= ARRAY_DIMENSION_MAX) { StringBuilder sb = new StringBuilder(); sb.append("The size specified for this array ("); sb.append(size); sb.append(')'); if (size >= ARRAY_DIMENSION_MAX) { sb.append(" is >= ARRAY-DIMENSION-LIMIT ("); sb.append(ARRAY_DIMENSION_MAX); sb.append(")."); } else { sb.append(" is negative.");} return error(new LispError(sb.toString())); } final AbstractVector v; final LispObject defaultInitialElement; if (upgradedType == Symbol.CHARACTER) { if (fillPointer != NIL || adjustable != NIL) { v = new ComplexString(size); } else { v = new SimpleString(size); } defaultInitialElement = LispCharacter.getInstance('\0'); } else if (upgradedType == Symbol.BIT) { if (fillPointer != NIL || adjustable != NIL) { v = new ComplexBitVector(size); } else { v = new SimpleBitVector(size); } defaultInitialElement = Fixnum.ZERO; } else if (upgradedType.equal(UNSIGNED_BYTE_8)) { if (fillPointer != NIL || adjustable != NIL) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { v = new ComplexVector_ByteBuffer(size, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { v = new ComplexVector_UnsignedByte8(size); } } else { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { if (!nioBuffer.equals(NIL)) { v = new BasicVector_ByteBuffer((java.nio.ByteBuffer)(((JavaObject)nioBuffer).getObject()), directAllocation); } else { v = new BasicVector_ByteBuffer(size, directAllocation); } } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { v = new BasicVector_UnsignedByte8(size); } } defaultInitialElement = Fixnum.ZERO; } else if (upgradedType.equal(UNSIGNED_BYTE_16) && fillPointer == NIL && adjustable == NIL) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { if (!nioBuffer.equals(NIL)) { Object o = ((JavaObject)nioBuffer).getObject(); if (o instanceof java.nio.CharBuffer) { v = new BasicVector_CharBuffer((java.nio.CharBuffer) o, directAllocation); } else if (o instanceof java.nio.ByteBuffer) { v = new BasicVector_CharBuffer((java.nio.ByteBuffer)o, directAllocation); // FIXME warn on coercion? } else { return type_error(nioBuffer, JavaObject.getInstance(java.nio.CharBuffer.class)); } } else { v = new BasicVector_CharBuffer(size, directAllocation); } } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { v = new BasicVector_UnsignedByte16(size); } defaultInitialElement = Fixnum.ZERO; } else if (upgradedType.equal(UNSIGNED_BYTE_32)) { if (fillPointer != NIL || adjustable != NIL) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { v = new ComplexVector_IntBuffer(size); } else { v = new ComplexVector_UnsignedByte32(size); } } else { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { if (!nioBuffer.equals(NIL)) { Object o = ((JavaObject)nioBuffer).getObject(); if (o instanceof java.nio.IntBuffer) { v = new BasicVector_IntBuffer((java.nio.IntBuffer)o, directAllocation); } else if (o instanceof java.nio.ByteBuffer) { v = new BasicVector_IntBuffer((java.nio.ByteBuffer)o, directAllocation); } else { return type_error(nioBuffer, JavaObject.getInstance(java.nio.IntBuffer.class)); } } else { v = new BasicVector_IntBuffer(size, directAllocation); } } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { v = new BasicVector_UnsignedByte32(size); } } defaultInitialElement = Fixnum.ZERO; } else if (upgradedType == NIL) { v = new NilVector(size); defaultInitialElement = null; } else { if (fillPointer != NIL || adjustable != NIL) { v = new ComplexVector(size); } else { v = new SimpleVector(size); } defaultInitialElement = NIL; } if (nioBuffer != NIL) { // v should have been allocated with a nioBuffer reference… ; } else if (initialElementProvided != NIL) { // Initial element was specified. v.fill(initialElement); } else if (initialContents != NIL) { if (initialContents.listp()) { LispObject list = initialContents; for (int i = 0; i < size; i++) { v.aset(i, list.car()); list = list.cdr(); } } else if (initialContents.vectorp()) { for (int i = 0; i < size; i++) { v.aset(i, initialContents.elt(i)); } } else { return type_error(initialContents, Symbol.SEQUENCE); } } else { if (defaultInitialElement != null) { v.fill(defaultInitialElement); } } if (fillPointer != NIL) { v.setFillPointer(fillPointer); } return v; } else { // rank > 1 AbstractArray array; if (adjustable == NIL) { if (upgradedType.equal(UNSIGNED_BYTE_8)) { if (initialContents != NIL) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new SimpleArray_ByteBuffer(dimv, initialContents, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new SimpleArray_UnsignedByte8(dimv, initialContents); } } else { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new SimpleArray_ByteBuffer(dimv, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new SimpleArray_UnsignedByte8(dimv); } if (initialElementProvided != NIL) { array.fill(initialElement); } else { array.fill(Fixnum.ZERO); } } } else if (upgradedType.equal(UNSIGNED_BYTE_16)) { if (initialContents != NIL) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new SimpleArray_CharBuffer(dimv, initialContents, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new SimpleArray_UnsignedByte16(dimv, initialContents); } } else { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new SimpleArray_CharBuffer(dimv, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new SimpleArray_UnsignedByte16(dimv); } if (initialElementProvided != NIL) { array.fill(initialElement); } else { array.fill(Fixnum.ZERO); } } } else if (upgradedType.equal(UNSIGNED_BYTE_32)) { if (initialContents != NIL) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new SimpleArray_IntBuffer(dimv, initialContents, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new SimpleArray_UnsignedByte32(dimv, initialContents); } } else { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new SimpleArray_IntBuffer(dimv, directAllocation); } else { array = new SimpleArray_UnsignedByte32(dimv); } if (initialElementProvided != NIL) { array.fill(initialElement); } else { array.fill(Fixnum.ZERO); } } } else { if (initialContents != NIL) { array = new SimpleArray_T(dimv, upgradedType, initialContents); } else { array = new SimpleArray_T(dimv, upgradedType); if (initialElementProvided != NIL) { array.fill(initialElement); } else { array.fill(NIL); } } } } else { // Adjustable. if (upgradedType.equal(UNSIGNED_BYTE_8)) { if (initialContents != NIL) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new ComplexArray_ByteBuffer(dimv, initialContents); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new ComplexArray_UnsignedByte8(dimv, initialContents); } } else { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new ComplexArray_ByteBuffer(dimv); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new ComplexArray_UnsignedByte8(dimv); } if (initialElementProvided != NIL) { array.fill(initialElement); } else { array.fill(Fixnum.ZERO); } } // FIXME add specialization on (unsigned-byte 16) } else if (upgradedType.equal(UNSIGNED_BYTE_32)) { if (initialContents != NIL) { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new ComplexArray_IntBuffer(dimv, initialContents, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new ComplexArray_UnsignedByte32(dimv, initialContents); } } else { if (Java.Buffers.active.equals(AllocationPolicy.NIO)) { array = new ComplexArray_IntBuffer(dimv, directAllocation); } else { //if (Java.Buffers.active.equals(AllocationPolicy.PRIMITIVE_ARRAY)) { array = new ComplexArray_UnsignedByte32(dimv); } if (initialElementProvided != NIL) { array.fill(initialElement); } else { array.fill(Fixnum.ZERO); } } } else { if (initialContents != NIL) { array = new ComplexArray(dimv, upgradedType, initialContents); } else { array = new ComplexArray(dimv, upgradedType); if (initialElementProvided != NIL) { array.fill(initialElement); } else { array.fill(NIL); } } } } return array; } } private static final Primitive _MAKE_ARRAY = new make_array(); } abcl-src-1.9.0/src/org/armedbear/lisp/make_condition.java0100644 0000000 0000000 00000012116 14202767264 022046 0ustar000000000 0000000 /* * make_condition.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; public final class make_condition extends Primitive { private make_condition() { super("%make-condition", PACKAGE_SYS, true); } // ### %make-condition // %make-condition type slot-initializations => condition @Override public LispObject execute(LispObject type, LispObject initArgs) { final Symbol symbol; if (type instanceof Symbol) symbol = (Symbol) type; else if (type instanceof LispClass) symbol = checkSymbol(((LispClass)type).getName()); else { // This function only works on symbols and classes. return NIL; } if (symbol == Symbol.ARITHMETIC_ERROR) return new ArithmeticError(initArgs); if (symbol == Symbol.CELL_ERROR) return new CellError(initArgs); if (symbol == Symbol.CONDITION) return new Condition(initArgs); if (symbol == Symbol.CONTROL_ERROR) return new ControlError(initArgs); if (symbol == Symbol.DIVISION_BY_ZERO) return new DivisionByZero(initArgs); if (symbol == Symbol.END_OF_FILE) return new EndOfFile(initArgs); if (symbol == Symbol.ERROR) return new LispError(initArgs); if (symbol == Symbol.FILE_ERROR) return new FileError(initArgs); if (symbol == Symbol.FLOATING_POINT_INEXACT) return new FloatingPointInexact(initArgs); if (symbol == Symbol.FLOATING_POINT_INVALID_OPERATION) return new FloatingPointInvalidOperation(initArgs); if (symbol == Symbol.FLOATING_POINT_OVERFLOW) return new FloatingPointOverflow(initArgs); if (symbol == Symbol.FLOATING_POINT_UNDERFLOW) return new FloatingPointUnderflow(initArgs); if (symbol == Symbol.PACKAGE_ERROR) return new PackageError(initArgs); if (symbol == Symbol.PARSE_ERROR) return new ParseError(initArgs); if (symbol == Symbol.PRINT_NOT_READABLE) return new PrintNotReadable(initArgs); if (symbol == Symbol.PROGRAM_ERROR) return new ProgramError(initArgs); if (symbol == Symbol.READER_ERROR) return new ReaderError(initArgs); if (symbol == Symbol.SERIOUS_CONDITION) return new SeriousCondition(initArgs); if (symbol == Symbol.SIMPLE_CONDITION) return new SimpleCondition(initArgs); if (symbol == Symbol.SIMPLE_ERROR) return new SimpleError(initArgs); if (symbol == Symbol.SIMPLE_TYPE_ERROR) return new SimpleTypeError(initArgs); if (symbol == Symbol.SIMPLE_WARNING) return new SimpleWarning(initArgs); if (symbol == Symbol.STORAGE_CONDITION) return new StorageCondition(initArgs); if (symbol == Symbol.STREAM_ERROR) return new StreamError(initArgs); if (symbol == Symbol.STYLE_WARNING) return new StyleWarning(initArgs); if (symbol == Symbol.TYPE_ERROR) return new TypeError(initArgs); if (symbol == Symbol.UNBOUND_SLOT) return new UnboundSlot(initArgs); if (symbol == Symbol.UNBOUND_VARIABLE) return new UnboundVariable(initArgs); if (symbol == Symbol.UNDEFINED_FUNCTION) return new UndefinedFunction(initArgs); if (symbol == Symbol.WARNING) return new Warning(initArgs); return NIL; } private static final Primitive MAKE_CONDITION = new make_condition(); } abcl-src-1.9.0/src/org/armedbear/lisp/make_server_socket.java0100644 0000000 0000000 00000004354 14202767264 022743 0ustar000000000 0000000 /* * make_server_socket.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.ServerSocket; // ### %make-server-socket public final class make_server_socket extends Primitive { private make_server_socket() { super("%make-server-socket", PACKAGE_SYS, false, "port element-type"); } @Override public LispObject execute(LispObject first) { int port = Fixnum.getValue(first); try { ServerSocket socket = new ServerSocket(port); return new JavaObject(socket); } catch (Exception e) { return error(new LispError(e.getMessage())); } } private static final Primitive MAKE_SERVER_SOCKET = new make_server_socket(); } abcl-src-1.9.0/src/org/armedbear/lisp/make_socket.java0100644 0000000 0000000 00000004351 14202767264 021352 0ustar000000000 0000000 /* * make_socket.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.Socket; // ### %make-socket public final class make_socket extends Primitive { private make_socket() { super("%make-socket", PACKAGE_SYS, false, "host port"); } @Override public LispObject execute(LispObject first, LispObject second) { String host = first.getStringValue(); int port = Fixnum.getValue(second); try { Socket socket = new Socket(host, port); return new JavaObject(socket); } catch (Exception e) { return error(new LispError(e.getMessage())); } } private static final Primitive MAKE_SOCKET = new make_socket(); } abcl-src-1.9.0/src/org/armedbear/lisp/map-into.lisp0100644 0000000 0000000 00000004425 14223403213 020621 0ustar000000000 0000000 ;;; map-into.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "COMMON-LISP") (export 'map-into) ;;; MAP-INTO (from CMUCL) (defun map-into (result-sequence function &rest sequences) (let* ((fp-result (and (arrayp result-sequence) (array-has-fill-pointer-p result-sequence))) (len (apply #'min (if fp-result (array-dimension result-sequence 0) (length result-sequence)) (mapcar #'length sequences)))) (when fp-result (setf (fill-pointer result-sequence) len)) (dotimes (index len) (setf (elt result-sequence index) (apply function (mapcar #'(lambda (seq) (elt seq index)) sequences))))) result-sequence) abcl-src-1.9.0/src/org/armedbear/lisp/map.lisp0100644 0000000 0000000 00000005111 14202767264 017663 0ustar000000000 0000000 ;;; map.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun map (result-type function sequence &rest more-sequences) (let* ((sequences (cons sequence more-sequences)) (limit (apply #'min (mapcar #'length sequences)))) (declare (type index limit)) (cond ((null result-type) (dotimes (i limit nil) (apply function (mapcar #'(lambda (z) (elt z i)) sequences)))) ((eq result-type 'LIST) (let (result) (dotimes (i limit (nreverse result)) (push (apply function (mapcar #'(lambda (z) (elt z i)) sequences)) result)))) (t (let ((result (case result-type (STRING (make-string limit)) (VECTOR (make-array limit)) (t (make-sequence result-type limit))))) (dotimes (i limit result) (setf (elt result i) (apply function (mapcar #'(lambda (z) (elt z i)) sequences))))))))) abcl-src-1.9.0/src/org/armedbear/lisp/map1.lisp0100644 0000000 0000000 00000005234 14223403213 017732 0ustar000000000 0000000 ;;; map1.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package #:system) (defun map1 (function original-arglists accumulate take-car) (let* ((arglists (copy-list original-arglists)) (ret-list (list nil)) (temp ret-list)) (do ((res nil) (args '() '())) ((dolist (x arglists nil) (if (null x) (return t))) (if accumulate (cdr ret-list) (car original-arglists))) (do ((l arglists (cdr l))) ((null l)) (push (if take-car (caar l) (car l)) args) (setf (car l) (cdar l))) (setq res (apply function (nreverse args))) (case accumulate (:nconc (setq temp (last (nconc temp res)))) (:list (rplacd temp (list res)) (setq temp (cdr temp))))))) (defun mapcan (function list &rest more-lists) (map1 function (cons list more-lists) :nconc t)) (defun mapl (function list &rest more-lists) (map1 function (cons list more-lists) nil nil)) (defun maplist (function list &rest more-lists) (map1 function (cons list more-lists) :list nil)) (defun mapcon (function list &rest more-lists) (map1 function (cons list more-lists) :nconc nil)) abcl-src-1.9.0/src/org/armedbear/lisp/mask-field.lisp0100644 0000000 0000000 00000004272 14223403213 021111 0ustar000000000 0000000 ;;; mask-field.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From CMUCL. (defun mask-field (bytespec integer) (let ((size (byte-size bytespec)) (pos (byte-position bytespec))) (logand integer (ash (1- (ash 1 size)) pos)))) (define-setf-expander mask-field (bytespec place &environment env) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion place env) (let ((btemp (gensym)) (gnuval (gensym))) (values (cons btemp dummies) (cons bytespec vals) (list gnuval) `(let ((,(car newval) (deposit-field ,gnuval ,btemp ,getter))) ,setter ,gnuval) `(mask-field ,btemp ,getter))))) abcl-src-1.9.0/src/org/armedbear/lisp/member-if.lisp0100644 0000000 0000000 00000003612 14223403213 020735 0ustar000000000 0000000 ;;; member-if.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun member-if (test list &key key) (do ((list list (cdr list))) ((endp list) nil) (if (funcall test (apply-key key (car list))) (return list)))) (defun member-if-not (test list &key key) (do ((list list (cdr list))) ((endp list) ()) (if (not (funcall test (apply-key key (car list)))) (return list)))) abcl-src-1.9.0/src/org/armedbear/lisp/mismatch.lisp0100644 0000000 0000000 00000007472 14223403213 020707 0ustar000000000 0000000 ;;; mismatch.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; MISMATCH (from ECL) (in-package "COMMON-LISP") (require "EXTENSIBLE-SEQUENCES-BASE") (export 'mismatch) ;;; From ECL. (defun bad-seq-limit (x &optional y) (error "bad sequence limit ~a" (if y (list x y) x))) (defun the-end (x y) (cond ((sys::fixnump x) (unless (<= x (length y)) (bad-seq-limit x)) x) ((null x) (length y)) (t (bad-seq-limit x)))) (defun the-start (x) (cond ((sys::fixnump x) (unless (>= x 0) (bad-seq-limit x)) x) ((null x) 0) (t (bad-seq-limit x)))) (defmacro with-start-end (start end seq &body body) `(let* ((,start (if ,start (the-start ,start) 0)) (,end (the-end ,end ,seq))) (unless (<= ,start ,end) (bad-seq-limit ,start ,end)) ,@ body)) (defun call-test (test test-not item keyx) (cond (test (funcall test item keyx)) (test-not (not (funcall test-not item keyx))) (t (eql item keyx)))) (defun test-error() (error "both test and test are supplied")) (defun mismatch (sequence1 sequence2 &rest args &key from-end test test-not (key #'identity) start1 start2 end1 end2) (and test test-not (test-error)) (if (and (or (listp sequence1) (arrayp sequence1)) (or (listp sequence2) (arrayp sequence2))) (with-start-end start1 end1 sequence1 (with-start-end start2 end2 sequence2 (if (not from-end) (do ((i1 start1 (1+ i1)) (i2 start2 (1+ i2))) ((or (>= i1 end1) (>= i2 end2)) (if (and (>= i1 end1) (>= i2 end2)) nil i1)) (unless (call-test test test-not (funcall key (elt sequence1 i1)) (funcall key (elt sequence2 i2))) (return i1))) (do ((i1 (1- end1) (1- i1)) (i2 (1- end2) (1- i2))) ((or (< i1 start1) (< i2 start2)) (if (and (< i1 start1) (< i2 start2)) nil (1+ i1))) (unless (call-test test test-not (funcall key (elt sequence1 i1)) (funcall key (elt sequence2 i2))) (return (1+ i1))))))) (apply #'sequence:mismatch sequence1 sequence2 args))) abcl-src-1.9.0/src/org/armedbear/lisp/mod.java0100644 0000000 0000000 00000003540 14202767264 017643 0ustar000000000 0000000 /* * mod.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### mod number divisor public final class mod extends Primitive { private mod() { super("mod", "number divisor"); } @Override public LispObject execute(LispObject number, LispObject divisor) { return number.MOD(divisor); } private static final Primitive MOD = new mod(); } abcl-src-1.9.0/src/org/armedbear/lisp/mop.lisp0100644 0000000 0000000 00000007754 14202767264 017720 0ustar000000000 0000000 (in-package #:mop) ;;; AMOP pg. 240ff. (defgeneric validate-superclass (class superclass) (:documentation "This generic function is called to determine whether the class superclass is suitable for use as a superclass of class.")) (defmethod validate-superclass ((class class) (superclass class)) (or (eql superclass +the-T-class+) (eql (class-of class) (class-of superclass)) (or (and (eql (class-of class) +the-standard-class+) (eql (class-of superclass) +the-funcallable-standard-class+)) (and (eql (class-of class) +the-funcallable-standard-class+) (eql (class-of superclass) +the-standard-class+))))) ;;; This is against the letter of the MOP, but very much in its spirit. (defmethod validate-superclass ((class class) (superclass forward-referenced-class)) t) (defmethod shared-initialize :before ((instance class) slot-names &key direct-superclasses &allow-other-keys) (declare (ignore slot-names)) (dolist (superclass direct-superclasses) (assert (validate-superclass instance superclass) (instance superclass) "Class ~S is not compatible with superclass ~S" instance superclass))) (export '(;; classes funcallable-standard-object funcallable-standard-class forward-referenced-class slot-definition standard-method standard-accessor-method standard-reader-method standard-writer-method compute-effective-slot-definition compute-class-precedence-list compute-default-initargs compute-effective-slot-definition compute-discriminating-function compute-applicable-methods compute-applicable-methods-using-classes compute-effective-method make-method-lambda compute-slots finalize-inheritance validate-superclass slot-value-using-class slot-boundp-using-class slot-makunbound-using-class ensure-class ensure-class-using-class ensure-generic-function-using-class class-default-initargs class-direct-default-initargs class-direct-slots class-direct-subclasses class-direct-superclasses class-finalized-p class-precedence-list class-prototype class-slots add-direct-subclass remove-direct-subclass generic-function-argument-precedence-order generic-function-declarations generic-function-lambda-list generic-function-method-class generic-function-method-combination generic-function-name method-function method-generic-function method-lambda-list method-specializers method-qualifiers accessor-method-slot-definition reader-method-class writer-method-class direct-slot-definition-class effective-slot-definition-class slot-definition-allocation slot-definition-initargs slot-definition-initform slot-definition-initfunction slot-definition-location slot-definition-name slot-definition-readers slot-definition-type slot-definition-writers slot-definition-documentation standard-instance-access funcallable-standard-instance-access intern-eql-specializer eql-specializer-object specializer-direct-methods specializer-direct-generic-functions add-direct-method remove-direct-method find-method-combination extract-lambda-list extract-specializer-names add-dependent remove-dependent map-dependents update-dependent)) (provide 'mop) abcl-src-1.9.0/src/org/armedbear/lisp/multiple-value-bind.lisp0100644 0000000 0000000 00000004714 14223403213 022755 0ustar000000000 0000000 ;;; multiple-value-bind.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package "SYSTEM") ;; The traditional implementation of M-V-B in terms of M-V-C. ABCL implements ;; M-V-B as a special form in the interpreter, and ABCL's compiler handles it ;; specifically too, so this code is only here to support code walkers and the ;; like, as required by ANSI. (defmacro multiple-value-bind (varlist value-form &body body) (unless (and (listp varlist) (every #'symbolp varlist)) (error 'program-error :format-control "Variable list is not a list of symbols: ~S." :format-arguments (list varlist))) (if (= (length varlist) 1) `(let ((,(car varlist) ,value-form)) ,@body) (let ((ignore (gensym))) `(multiple-value-call #'(lambda (&optional ,@(mapcar #'list varlist) &rest ,ignore) (declare (ignore ,ignore)) ,@body) ,value-form)))) abcl-src-1.9.0/src/org/armedbear/lisp/multiple-value-list.lisp0100644 0000000 0000000 00000003206 14202767264 023027 0ustar000000000 0000000 ;;; multiple-value-list.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defmacro multiple-value-list (form) `(multiple-value-call #'list ,form)) abcl-src-1.9.0/src/org/armedbear/lisp/multiple-value-setq.lisp0100644 0000000 0000000 00000003720 14202767264 023031 0ustar000000000 0000000 ;;; multiple-value-setq.lisp ;;; ;;; Copyright (C) 2004-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;; Adapted from CMUCL. (in-package "SYSTEM") (defmacro multiple-value-setq (varlist value-form) (unless (and (listp varlist) (every #'symbolp varlist)) (error "~S is not a list of symbols." varlist)) ;; MULTIPLE-VALUE-SETQ is required always to return the primary value of the ;; value-form, even if varlist is empty. (if varlist `(values (setf (values ,@varlist) ,value-form)) `(values ,value-form))) abcl-src-1.9.0/src/org/armedbear/lisp/nsubstitute.lisp0100644 0000000 0000000 00000014733 14223403213 021471 0ustar000000000 0000000 ;;; nsubstitute.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; NSUBSTITUTE (from CMUCL) (in-package "SYSTEM") ;;; From CMUCL. (defmacro real-count (count) `(cond ((null ,count) most-positive-fixnum) ((fixnump ,count) (if (minusp ,count) 0 ,count)) ((integerp ,count) (if (minusp ,count) 0 most-positive-fixnum)) (t ,count))) (defun nlist-substitute* (new old sequence test test-not start end count key) (do ((list (nthcdr start sequence) (cdr list)) (index start (1+ index))) ((or (= index end) (null list) (= count 0)) sequence) (when (if test-not (not (funcall test-not old (apply-key key (car list)))) (funcall test old (apply-key key (car list)))) (rplaca list new) (setq count (1- count))))) (defun nvector-substitute* (new old sequence incrementer test test-not start end count key) (do ((index start (+ index incrementer))) ((or (= index end) (= count 0)) sequence) (when (if test-not (not (funcall test-not old (apply-key key (aref sequence index)))) (funcall test old (apply-key key (aref sequence index)))) (setf (aref sequence index) new) (setq count (1- count))))) (defun nsubstitute (new old sequence &key from-end (test #'eql) test-not end count key (start 0)) (let ((end (or end (length sequence))) (count (real-count count))) (if (listp sequence) (if from-end (let ((length (length sequence))) (nreverse (nlist-substitute* new old (nreverse sequence) test test-not (- length end) (- length start) count key))) (nlist-substitute* new old sequence test test-not start end count key)) (if from-end (nvector-substitute* new old sequence -1 test test-not (1- end) (1- start) count key) (nvector-substitute* new old sequence 1 test test-not start end count key))))) (defun nlist-substitute-if* (new test sequence start end count key) (do ((list (nthcdr start sequence) (cdr list)) (index start (1+ index))) ((or (= index end) (null list) (= count 0)) sequence) (when (funcall test (apply-key key (car list))) (rplaca list new) (setq count (1- count))))) (defun nvector-substitute-if* (new test sequence incrementer start end count key) (do ((index start (+ index incrementer))) ((or (= index end) (= count 0)) sequence) (when (funcall test (apply-key key (aref sequence index))) (setf (aref sequence index) new) (setq count (1- count))))) (defun nsubstitute-if (new test sequence &key from-end (start 0) end count key) (let ((end (or end (length sequence))) (count (real-count count))) (if (listp sequence) (if from-end (let ((length (length sequence))) (nreverse (nlist-substitute-if* new test (nreverse sequence) (- length end) (- length start) count key))) (nlist-substitute-if* new test sequence start end count key)) (if from-end (nvector-substitute-if* new test sequence -1 (1- end) (1- start) count key) (nvector-substitute-if* new test sequence 1 start end count key))))) (defun nlist-substitute-if-not* (new test sequence start end count key) (do ((list (nthcdr start sequence) (cdr list)) (index start (1+ index))) ((or (= index end) (null list) (= count 0)) sequence) (when (not (funcall test (apply-key key (car list)))) (rplaca list new) (setq count (1- count))))) (defun nvector-substitute-if-not* (new test sequence incrementer start end count key) (do ((index start (+ index incrementer))) ((or (= index end) (= count 0)) sequence) (when (not (funcall test (apply-key key (aref sequence index)))) (setf (aref sequence index) new) (setq count (1- count))))) (defun nsubstitute-if-not (new test sequence &key from-end (start 0) end count key) (let ((end (or end (length sequence))) (count (real-count count))) (if (listp sequence) (if from-end (let ((length (length sequence))) (nreverse (nlist-substitute-if-not* new test (nreverse sequence) (- length end) (- length start) count key))) (nlist-substitute-if-not* new test sequence start end count key)) (if from-end (nvector-substitute-if-not* new test sequence -1 (1- end) (1- start) count key) (nvector-substitute-if-not* new test sequence 1 start end count key))))) abcl-src-1.9.0/src/org/armedbear/lisp/nth-value.lisp0100644 0000000 0000000 00000003166 14202767264 021021 0ustar000000000 0000000 ;;; nth-value.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defmacro nth-value (n form) `(nth ,n (multiple-value-list ,form))) abcl-src-1.9.0/src/org/armedbear/lisp/numbers.lisp0100644 0000000 0000000 00000020726 14223403213 020552 0ustar000000000 0000000 ;;; numbers.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL/SBCL. (in-package "SYSTEM") (defun signum (number) "If NUMBER is zero, return NUMBER, else return (/ NUMBER (ABS NUMBER))." (if (zerop number) number (if (rationalp number) (if (plusp number) 1 -1) (/ number (abs number))))) (defun round (number &optional (divisor 1)) "Rounds number (or number/divisor) to nearest integer. The second returned value is the remainder." (multiple-value-bind (tru rem) (truncate number divisor) (if (zerop rem) (values tru rem) (let ((thresh (/ (abs divisor) 2))) (cond ((or (> rem thresh) (and (= rem thresh) (oddp tru))) (if (minusp divisor) (values (- tru 1) (+ rem divisor)) (values (+ tru 1) (- rem divisor)))) ((let ((-thresh (- thresh))) (or (< rem -thresh) (and (= rem -thresh) (oddp tru)))) (if (minusp divisor) (values (+ tru 1) (- rem divisor)) (values (- tru 1) (+ rem divisor)))) (t (values tru rem))))))) (defun ffloor (number &optional (divisor 1)) "Same as FLOOR, but returns first value as a float." (multiple-value-bind (tru rem) (ftruncate number divisor) (if (and (not (zerop rem)) (if (minusp divisor) (plusp number) (minusp number))) (values (1- tru) (+ rem divisor)) (values tru rem)))) (defun fceiling (number &optional (divisor 1)) "Same as CEILING, but returns first value as a float." (multiple-value-bind (tru rem) (ftruncate number divisor) (if (and (not (zerop rem)) (if (minusp divisor) (minusp number) (plusp number))) (values (+ tru 1) (- rem divisor)) (values tru rem)))) (defun fround (number &optional (divisor 1)) "Same as ROUND, but returns first value as a float." (multiple-value-bind (res rem) (round number divisor) (values (float res (if (floatp rem) rem 1.0)) rem))) ;;; FIXME (defun rationalize (number) (rational number)) (defun gcd (&rest integers) (cond ((null integers) 0) ((null (cdr integers)) (let ((n (car integers))) (if (integerp n) (abs n) (error 'type-error :datum n :expected-type 'integer)))) (t (do ((gcd (car integers) (gcd-2 gcd (car rest))) (rest (cdr integers) (cdr rest))) ((null rest) gcd))))) ;;; From discussion on comp.lang.lisp and Akira Kurihara. (defun isqrt (natural) "Returns the root of the nearest integer less than natural which is a perfect square." (unless (and (integerp natural) (not (minusp natural))) (error 'simple-type-error :format-control "The value ~A is not a non-negative real number." :format-arguments (list natural))) (if (and (fixnump natural) (<= natural 24)) (cond ((> natural 15) 4) ((> natural 8) 3) ((> natural 3) 2) ((> natural 0) 1) (t 0)) (let* ((n-len-quarter (ash (integer-length natural) -2)) (n-half (ash natural (- (ash n-len-quarter 1)))) (n-half-isqrt (isqrt n-half)) (init-value (ash (1+ n-half-isqrt) n-len-quarter))) (loop (let ((iterated-value (ash (+ init-value (truncate natural init-value)) -1))) (unless (< iterated-value init-value) (return init-value)) (setq init-value iterated-value)))))) ;; FIXME Need to add support for denormalized floats! ;; "FLOAT-PRECISION returns the number of significant radix b digits present in ;; FLOAT; if FLOAT is a float zero, then the result is an integer zero." ;; "For normalized floats, the results of FLOAT-DIGITS and FLOAT-PRECISION are ;; the same, but the precision is less than the number of representation digits ;; for a denormalized or zero number. (defun float-precision (float) (if (floatp float) (cond ((zerop float) 0) ((typep float 'single-float) 24) ((typep float 'double-float) 53) (t ;; Shouldn't get here! (aver nil))) (error 'simple-type-error :format-control "~S is not of type FLOAT." :format-arguments (list float)))) (defun decode-float (float) (cond ((typep float 'single-float) (decode-float-single float)) ((typep float 'double-float) (decode-float-double float)) (t (error 'simple-type-error :format-control "~S is neither SINGLE-FLOAT nor DOUBLE-FLOAT." :format-arguments (list float))))) ;;; From . Thanks Xophe! (defun sane-integer-decode-float (float) (multiple-value-bind (mantissa exp sign) (integer-decode-float float) (let ((fixup (- (integer-length mantissa) (float-precision float)))) (values (ash mantissa (- fixup)) (+ exp fixup) sign)))) (defun decode-float-single (float) ;; TODO memoize (let ((float-precision-single (float-precision 1f0))) (multiple-value-bind (significand exponent sign) (sane-integer-decode-float float) (values (coerce (/ significand (expt 2 float-precision-single)) 'single-float) (+ exponent float-precision-single) (if (minusp sign) -1f0 1f0))))) (defun decode-float-double (float) ;; TODO memoize (let ((float-precision-double (float-precision 1d0))) (multiple-value-bind (significand exponent sign) (sane-integer-decode-float float) (values (coerce (/ significand (expt 2 float-precision-double)) 'double-float) (+ exponent float-precision-double) (if (minusp sign) -1d0 1d0))))) (defun conjugate (number) (etypecase number (complex (complex (realpart number) (- (imagpart number)))) (number number))) (defun phase (number) "Returns the angle part of the polar representation of a complex number. For complex numbers, this is (atan (imagpart number) (realpart number)). For non-complex positive numbers, this is 0. For non-complex negative numbers this is PI." (etypecase number (rational (if (minusp number) (coerce pi 'single-float) 0.0f0)) (single-float (if (minusp (float-sign number)) (coerce pi 'single-float) 0.0f0)) (double-float (if (minusp (float-sign number)) (coerce pi 'double-float) 0.0d0)) (complex (if (zerop (realpart number)) (coerce (* (/ pi 2) (signum (imagpart number))) (if (typep (imagpart number) 'double-float) 'double-float 'single-float)) (atan (imagpart number) (realpart number)))))) abcl-src-1.9.0/src/org/armedbear/lisp/open.lisp0100644 0000000 0000000 00000023150 14223403213 020032 0ustar000000000 0000000 ;;; open.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (defun upgraded-element-type-bits (bits) (if (zerop (mod bits 8)) bits (+ bits (- 8 (mod bits 8))))) (defun upgraded-element-type (element-type) (setf element-type (normalize-type element-type)) (let ((ok nil)) (if (atom element-type) (case element-type ((character base-char) (setf ok t)) ((unsigned-byte signed-byte) (setf element-type (list element-type 8) ok t)) (bit (setf element-type (list 'unsigned-byte (upgraded-element-type-bits 1)) ok t)) (integer (setf element-type '(signed-byte 8) ok t))) (cond ((eq (%car element-type) 'or) (let ((types (mapcar #'upgraded-element-type (%cdr element-type))) (result '(unsigned-byte 8))) (dolist (type types) (when (eq (car type) 'signed-byte) (setf (car result) 'signed-byte)) (setf (cadr result) (max (cadr result) (cadr type)))) (setf element-type result ok t))) ((and (= (length element-type) 2) (memq (%car element-type) '(unsigned-byte signed-byte))) (let ((type (car element-type)) (width (cadr element-type))) (setf element-type (list type (upgraded-element-type-bits width)) ok t))) ((eq (car element-type) 'integer) (case (length element-type) (2 (setf element-type '(signed-byte 8) ok t)) (3 (let ((low (cadr element-type)) (high (caddr element-type))) (when (consp low) (setf low (1+ (%car low)))) (when (consp high) (setf high (1- (%car high)))) (setf element-type (cond ((eq high '*) (if (minusp low) '(signed-byte 8) '(unsigned-byte 8))) ((minusp low) (list 'signed-byte (upgraded-element-type-bits (max (1+ (integer-length low)) (integer-length high))))) (t (list 'unsigned-byte (upgraded-element-type-bits (integer-length high))))) ok t))))))) (if ok element-type (error 'file-error :format-control "Unsupported element type ~S." :format-arguments (list element-type))))) (defun open (filename &key (direction :input) (element-type 'character) (if-exists nil if-exists-given) (if-does-not-exist nil if-does-not-exist-given) (external-format :default)) ; (declare (ignore external-format)) ; FIXME (setf element-type (case element-type ((character base-char) 'character) (:default '(unsigned-byte 8)) (t (upgraded-element-type element-type)))) (let* ((p (merge-pathnames filename)) (pathname (if (typep p 'logical-pathname) (translate-logical-pathname p) p))) (when (wild-pathname-p pathname) (error 'file-error :pathname pathname :format-control "Cannot OPEN a wild pathname.")) (when (memq direction '(:output :io)) (unless if-exists-given (setf if-exists (if (eq (pathname-version pathname) :newest) :new-version :error)))) (unless if-does-not-exist-given (setf if-does-not-exist (cond ((eq direction :input) :error) ((and (memq direction '(:output :io)) (memq if-exists '(:overwrite :append))) :error) ((eq direction :probe) nil) (t :create)))) (case direction (:input (case if-does-not-exist (:error (unless (probe-file pathname) (error 'file-error :pathname pathname :format-control "The file ~S does not exist." :format-arguments (list pathname)))) (:create ;; CREATE-NEW-FILE "atomically creates a new, empty file named by ;; this abstract pathname if and only if a file with this name does ;; not yet exist." See java.io.File.createNewFile(). (create-new-file (namestring pathname)))) (make-file-stream pathname element-type :input nil external-format)) (:probe (case if-does-not-exist (:error (unless (probe-file pathname) (error 'file-error :pathname pathname :format-control "The file ~S does not exist." :format-arguments (list pathname)))) (:create ;; CREATE-NEW-FILE "atomically creates a new, empty file named by ;; this abstract pathname if and only if a file with this name does ;; not yet exist." See java.io.File.createNewFile(). (create-new-file (namestring pathname)))) (let ((stream (make-file-stream pathname element-type :input nil external-format))) (when stream (close stream)) stream)) ((:output :io) (case if-does-not-exist (:error (unless (probe-file pathname) (error 'file-error :pathname pathname :format-control "The file ~S does not exist." :format-arguments (list pathname)))) ((nil) (unless (probe-file pathname) (return-from open nil)))) (case if-exists (:error (when (probe-file pathname) (error 'file-error :pathname pathname :format-control "The file ~S already exists." :format-arguments (list pathname)))) ((nil) (when (probe-file pathname) (return-from open nil))) ((:rename :rename-and-delete) (when (probe-file pathname) ;; Make sure the original file is not a directory. (when (probe-directory pathname) (error 'file-error :pathname pathname :format-control "The file ~S is a directory." :format-arguments (list pathname))) (let ((backup-name (concatenate 'string (namestring pathname) ".bak"))) (when (probe-file backup-name) (when (probe-directory backup-name) (error 'file-error :pathname pathname :format-control "Unable to rename ~S to ~S." :format-arguments (list pathname backup-name))) (delete-file backup-name)) (rename-file pathname backup-name)))) ((:new-version :supersede :overwrite :append)) ; OK to proceed. (t (error 'simple-error :format-control "Option not supported: ~S." :format-arguments (list if-exists)))) (let ((stream (make-file-stream pathname element-type direction if-exists external-format))) (unless stream (error 'file-error :pathname pathname :format-control "Unable to open ~S." :format-arguments (list pathname))) stream)) (t (error 'simple-error :format-control ":DIRECTION ~S not supported." :format-arguments (list direction)))))) abcl-src-1.9.0/src/org/armedbear/lisp/open_stream_p.java0100644 0000000 0000000 00000003647 14202767264 021727 0ustar000000000 0000000 /* * open_stream_p.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### open-stream-p public final class open_stream_p extends Primitive { private open_stream_p() { super("open-stream-p"); } @Override public LispObject execute(LispObject arg) { return checkStream(arg).isOpen() ? T : NIL; } private static final Primitive OPEN_STREAM_P = new open_stream_p(); } abcl-src-1.9.0/src/org/armedbear/lisp/or.lisp0100644 0000000 0000000 00000003545 14223403213 017517 0ustar000000000 0000000 ;;; or.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package "SYSTEM") (defmacro or (&rest forms) (cond ((endp forms) nil) ((endp (rest forms)) (first forms)) (t (let ((n-result (gensym))) `(let ((,n-result ,(first forms))) (if ,n-result ,n-result (or ,@(rest forms)))))))) abcl-src-1.9.0/src/org/armedbear/lisp/output_stream_p.java0100644 0000000 0000000 00000003675 14202767264 022327 0ustar000000000 0000000 /* * output_stream_p.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### output-stream-p public final class output_stream_p extends Primitive { private output_stream_p() { super("output-stream-p"); } @Override public LispObject execute(LispObject arg) { return checkStream(arg).isOutputStream() ? T : NIL; } private static final Primitive OUTPUT_STREAM_P = new output_stream_p(); } abcl-src-1.9.0/src/org/armedbear/lisp/package.lisp0100644 0000000 0000000 00000013147 14202767264 020511 0ustar000000000 0000000 ;;; package.lisp ;;; ;;; Copyright (C) 2008 Erik Huelsmann ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") ;; Redefines make-package from boot.lisp (defun make-package (name &key nicknames use) (restart-case (progn (when (find-package name) (error 'simple-error "Package ~A already exists." name)) (dolist (nick nicknames) (when (find-package nick) (error 'package-error :package nick))) (%make-package name nicknames use)) (use-existing-package () :report "Use existing package" (return-from make-package (find-package name))))) ;; Redefines function from defpackage.lisp, because there it's lacking restart-case (defun ensure-available-symbols (imports) (remove nil (mapcar #'(lambda (package-and-symbols) (let* ((package (find-package (designated-package-name (car package-and-symbols)))) (new-symbols (remove nil (mapcar #'(lambda (sym) (restart-case (progn (unless (nth-value 1 (find-symbol sym package)) (error 'package-error "The symbol ~A is not present in package ~A." sym (package-name package))) sym) (skip () :report "Skip this symbol." nil))) (cdr package-and-symbols))))) (when new-symbols (cons package new-symbols)))) imports))) (defun import (symbols &optional (package *package* package-supplied-p)) (dolist (symbol (if (listp symbols) symbols (list symbols))) (let* ((sym-name (string symbol)) (local-sym (find-symbol sym-name package))) (restart-case (progn (when (and local-sym (not (eql symbol local-sym))) (error 'package-error "Different symbol (~A) with the same name already accessible in package ~A." local-sym (package-name package))) (if package-supplied-p (%import (list symbol) package) ;; in order to pass NIL, wrap in a list (%import (list symbol)))) (unintern-existing () :report (lambda (s) (format s "Unintern ~S and continue" local-sym)) (unintern local-sym) (%import symbol)) (skip () :report "Skip symbol")))) T) (defun delete-package (package) (with-simple-restart (continue "Ignore missing package.") (sys::%delete-package package))) (defun add-package-local-nickname (local-nickname actual-package &optional (package-designator *package*)) (let* ((local-nickname (string local-nickname)) (package-designator (or (find-package package-designator) (error "Package ~A not found" package-designator))) (actual-package (or (find-package actual-package) (error "Package ~A not found" actual-package)))) (when (member local-nickname '("CL" "COMMON-LISP" "KEYWORD") :test #'string=) (cerror "Continue anyway" "Trying to define a local nickname called ~A" local-nickname)) (when (member local-nickname (list* (package-name package-designator) (package-nicknames package-designator)) :test #'string=) (cerror "Continue anyway" "Trying to override the name or nickname ~A for package ~A ~ with a local nickname for another package ~A" local-nickname package-designator actual-package)) (sys::%add-package-local-nickname local-nickname actual-package package-designator))) abcl-src-1.9.0/src/org/armedbear/lisp/parse-integer.lisp0100644 0000000 0000000 00000006222 14202767264 021657 0ustar000000000 0000000 ;;; parse-integer.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") ;;; From OpenMCL. (defun parse-integer-error (string) (error 'parse-error "not an integer string: ~S" string)) (defun parse-integer (string &key (start 0) end (radix 10) junk-allowed) (when (null end) (setq end (length string))) (let ((index (do ((i start (1+ i))) ((= i end) (if junk-allowed (return-from parse-integer (values nil end)) (parse-integer-error string))) (unless (whitespacep (char string i)) (return i)))) (minusp nil) (found-digit nil) (result 0)) (let ((char (char string index))) (cond ((char= char #\-) (setq minusp t) (setq index (1+ index))) ((char= char #\+) (setq index (1+ index))))) (loop (when (= index end) (return nil)) (let* ((char (char string index)) (weight (digit-char-p char radix))) (cond (weight (setq result (+ weight (* result radix)) found-digit t)) (junk-allowed (return nil)) ((whitespacep char) (do () ((= (setq index (1+ index)) end)) (unless (whitespacep (char string index)) (parse-integer-error string))) (return nil)) (t (parse-integer-error string)))) (setq index (1+ index))) (values (if found-digit (if minusp (- result) result) (if junk-allowed nil (parse-integer-error string))) index))) abcl-src-1.9.0/src/org/armedbear/lisp/parse-lambda-list.lisp0100644 0000000 0000000 00000015576 14223403213 022407 0ustar000000000 0000000 ;;; parse-lambda-list.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package "SYSTEM") (require '#:collect) ;;; Break something like a lambda list (but not necessarily actually a ;;; lambda list, e.g. the representation of argument types which is ;;; used within an FTYPE specification) into its component parts. We ;;; return 10 values: ;;; 1. a list of the required args; ;;; 2. a list of the &OPTIONAL arg specs; ;;; 3. true if a &REST arg was specified; ;;; 4. the &REST arg; ;;; 5. true if &KEY args are present; ;;; 6. a list of the &KEY arg specs; ;;; 7. true if &ALLOW-OTHER-KEYS was specified.; ;;; 8. true if any &AUX is present (new in SBCL vs. CMU CL); ;;; 9. a list of the &AUX specifiers; ;;; 10. true if any lambda list keyword is present (only for ;;; PARSE-LAMBDA-LIST-LIKE-THING). ;;; ;;; The top level lambda list syntax is checked for validity, but the ;;; arg specifiers are just passed through untouched. If something is ;;; wrong, we signal an error. (defun parse-lambda-list-like-thing (list) (collect ((required) (optional) (keys) (aux)) (let ((restp nil) (rest nil) (keyp nil) (auxp nil) (allowp nil) (state :required)) (declare (type (member :allow-other-keys :aux :key :optional :post-rest :required :rest) state)) (dolist (arg list) (if (and (symbolp arg) (let ((name (symbol-name (the symbol arg)))) (and (plusp (length name)) (char= (char name 0) #\&)))) (case arg (&optional (unless (eq state :required) (error "misplaced &OPTIONAL in lambda list: ~S" list)) (setq state :optional)) (&rest (unless (member state '(:required :optional)) (error "misplaced &REST in lambda list: ~S" list)) (setq state :rest)) (&key (unless (member state '(:required :optional :post-rest)) (error "misplaced &KEY in lambda list: ~S" list)) (setq keyp t state :key)) (&allow-other-keys (unless (eq state ':key) (error "misplaced &ALLOW-OTHER-KEYS in lambda list: ~S" list)) (setq allowp t state :allow-other-keys)) (&aux (when (eq state :rest) (error "misplaced &AUX in lambda list: ~S" list)) (setq auxp t state :aux)) ;; FIXME: I don't think ANSI says this is an error. (It ;; should certainly be good for a STYLE-WARNING, ;; though.) (t (error "unknown &KEYWORD in lambda list: ~S" arg))) (case state (:required (required arg)) (:optional (optional arg)) (:rest (setq restp t rest arg state :post-rest)) (:key (keys arg)) (:aux (aux arg)) (t (error "found garbage in lambda list when expecting a keyword: ~S" arg))))) (when (eq state :rest) (error "&REST without rest variable")) (values (required) (optional) restp rest keyp (keys) allowp auxp (aux) (neq state :required))))) ;;; like PARSE-LAMBDA-LIST-LIKE-THING, except our LAMBDA-LIST argument ;;; really *is* a lambda list, not just a "lambda-list-like thing", so ;;; can barf on things which're illegal as arguments in lambda lists ;;; even if they could conceivably be legal in not-quite-a-lambda-list ;;; weirdosities (defun parse-lambda-list (lambda-list) ;; Classify parameters without checking their validity individually. (multiple-value-bind (required optional restp rest keyp keys allowp auxp aux) (parse-lambda-list-like-thing lambda-list) ;; Check validity of parameters. (flet ((need-symbol (x why) (unless (symbolp x) (error "~A is not a symbol: ~S" why x)))) (dolist (i required) (need-symbol i "Required argument")) (dolist (i optional) (typecase i (symbol) (cons (destructuring-bind (var &optional init-form supplied-p) i (declare (ignore init-form supplied-p)) (need-symbol var "&OPTIONAL parameter name"))) (t (error "&OPTIONAL parameter is not a symbol or cons: ~S" i)))) (when restp (need-symbol rest "&REST argument")) (when keyp (dolist (i keys) (typecase i (symbol) (cons (destructuring-bind (var-or-kv &optional init-form supplied-p) i (declare (ignore init-form supplied-p)) (if (consp var-or-kv) (destructuring-bind (keyword-name var) var-or-kv (declare (ignore keyword-name)) (need-symbol var "&KEY parameter name")) (need-symbol var-or-kv "&KEY parameter name")))) (t (error "&KEY parameter is not a symbol or cons: ~S" i)))))) ;; Voila. (values required optional restp rest keyp keys allowp auxp aux))) abcl-src-1.9.0/src/org/armedbear/lisp/pathnames.lisp0100644 0000000 0000000 00000047350 14202767264 021101 0ustar000000000 0000000 ;;; pathnames.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (export '(logical-host-p)) (defun pathname-host (pathname &key (case :local)) (%pathname-host pathname case)) (defun pathname-device (pathname &key (case :local)) (%pathname-device pathname case)) (defun pathname-directory (pathname &key (case :local)) (%pathname-directory pathname case)) (defun pathname-name (pathname &key (case :local)) (%pathname-name pathname case)) (defun pathname-type (pathname &key (case :local)) (%pathname-type pathname case)) (defun wild-pathname-p (pathname &optional field-key) (%wild-pathname-p pathname field-key)) (defun component-match-wild-p (thing wild ignore-case) (let ((testfunc (if ignore-case #'equalp #'equal))) (labels ((split-string (delim str) (flet ((finder (char) (find char delim))) (loop :for x = (position-if-not #'finder str) :then (position-if-not #'finder str :start (or y (length str))) :for y = (position-if #'finder str :start (or x (length str))) :then (position-if #'finder str :start (or x (length str))) :while x :collect (subseq str x y)))) (positions-larger (thing substrings previous-pos) (let ((new-pos (search (car substrings) thing :start2 previous-pos :test testfunc))) (or (not substrings) (and new-pos (>= new-pos previous-pos) (positions-larger thing (cdr substrings) new-pos)))))) (let ((split-result (split-string "*" wild))) (and (positions-larger thing split-result 0) (if (eql (elt wild 0) #\*) t (eql (search (first split-result) thing :test testfunc) 0)) (if (eql (elt wild (1- (length wild))) #\*) t (let ((last-split-result (first (last split-result)))) (eql (search last-split-result thing :from-end t :test testfunc) (- (length thing) (length last-split-result)))))))))) (defun component-match-p (thing wild ignore-case) (cond ((eq wild :wild) t) ((null wild) t) ((and (stringp wild) (position #\* wild)) (component-match-wild-p thing wild ignore-case)) (ignore-case (equalp thing wild)) (t (equal thing wild)))) (defun directory-match-components (thing wild ignore-case) (loop (cond ((endp thing) (return (or (endp wild) (equal wild '(:wild-inferiors))))) ((endp wild) (return nil))) (let ((x (car thing)) (y (car wild))) (when (eq y :wild-inferiors) (return t)) (unless (component-match-p x y ignore-case) (return nil)) (setf thing (cdr thing) wild (cdr wild))))) (defun directory-match-p (thing wild ignore-case) (cond ((eq wild :wild) t) ((null wild) t) ((and ignore-case (equalp thing wild)) t) ((equal thing wild) t) ((and (null thing) (equal wild '(:absolute :wild-inferiors))) t) ((and (consp thing) (consp wild)) (if (eq (%car thing) (%car wild)) (directory-match-components (%cdr thing) (%cdr wild) ignore-case) nil)) (t nil))) (defun pathname-match-p (pathname wildcard) (setf pathname (pathname pathname) wildcard (pathname wildcard)) (unless (component-match-p (pathname-host pathname) (pathname-host wildcard) nil) (return-from pathname-match-p nil)) (when (and (pathname-jar-p pathname) (pathname-jar-p wildcard)) (unless (every (lambda (value) (not (null value))) (mapcar #'pathname-match-p (pathname-device pathname) (pathname-device wildcard))) (return-from pathname-match-p nil))) (when (or (and (pathname-jar-p pathname) (not (pathname-jar-p wildcard))) (and (not (pathname-jar-p pathname)) (pathname-jar-p wildcard))) (return-from pathname-match-p nil)) (let* ((windows-p (featurep :windows)) (ignore-case (or windows-p (typep pathname 'logical-pathname)))) (cond ((and windows-p (not (pathname-jar-p pathname)) (not (pathname-jar-p wildcard)) (not (component-match-p (pathname-device pathname) (pathname-device wildcard) ignore-case))) nil) ((not (directory-match-p (pathname-directory pathname) (pathname-directory wildcard) ignore-case)) nil) ((not (component-match-p (pathname-name pathname) (pathname-name wildcard) ignore-case)) nil) ((not (component-match-p (pathname-type pathname) (pathname-type wildcard) ignore-case)) nil) (t t)))) (defun wild-p (component) (or (eq component :wild) (and (stringp component) (position #\* component)))) (defun casify (thing case) (typecase thing (string (case case (:upcase (string-upcase thing)) (:downcase (string-downcase thing)) (t thing))) (list (let (result) (dolist (component thing (nreverse result)) (push (casify component case) result)))) (t thing))) (defun translate-component (source from to &optional case) (declare (ignore from)) (cond ((or (eq to :wild) (null to)) ;; "If the piece in TO-WILDCARD is :WILD or NIL, the piece in source ;; is copied into the result." (casify source case)) ((and to (not (wild-p to))) ;; "If the piece in TO-WILDCARD is present and not wild, it is copied ;; into the result." to) (t ;; "Otherwise, the piece in TO-WILDCARD might be a complex wildcard ;; such as "foo*bar" and the piece in FROM-WILDCARD should be wild; ;; the portion of the piece in SOURCE that matches the wildcard ;; portion of the piece in FROM-WILDCARD replaces the wildcard portion ;; of the piece in TO-WILDCARD and the value produced is used in the ;; result." ;; FIXME (error "Unsupported wildcard pattern: ~S" to)))) (defun translate-jar-device (source from to &optional case) (declare (ignore case)) ; FIXME (unless to (return-from translate-jar-device nil)) (when (not (= (length source) (length from) (length to))) (error "Unsupported pathname translation for unequal jar ~ references: ~S != ~S != ~S" source from to)) (mapcar #'translate-pathname source from to)) (defun translate-directory-components-aux (src from to case) (cond ((and (null src) (null from) (null to)) NIL) ((and to (not (member (car to) '(:wild :wild-inferiors)))) (cons (casify (car to) case) (translate-directory-components-aux src from (cdr to) case))) ((and (not src) (eq (car from) :wild-inferiors) (eq (car to) :wild-inferiors)) (translate-directory-components-aux src (cdr from) (cdr to) case)) ((not (and src from)) ;; both are NIL --> TO is a wildcard which can't be matched ;; either is NIL --> SRC can't be fully matched against FROM, vice versa (throw 'failed-match nil)) ((not (member (car from) '(:wild :wild-inferiors))) (unless (string= (casify (car src) case) (casify (car from) case)) (throw 'failed-match nil)) ;; FROM doesn't match SRC (translate-directory-components-aux (cdr src) (cdr from) to case)) ((not (eq (car from) (car to))) ;; TO is NIL while FROM is not, or (throw 'failed-match nil)) ;; FROM wildcard doesn't match TO wildcard ((eq (car to) :wild) ;; FROM and TO wildcards are :WILD (cons (casify (car src) case) (translate-directory-components-aux (cdr src) (cdr from) (cdr to) case))) ((eq (car to) :wild-inferiors) ;; FROM and TO wildcards are :WILD-INFERIORS (do ((src (cdr src) (cdr src)) (match (list (casify (car src) case)) (cons (casify (car src) case) match))) (NIL) ;; we'll exit the loop in different ways (catch 'failed-match (return-from translate-directory-components-aux (append (reverse match) (translate-directory-components-aux src (cdr from) (cdr to) case)))) (when (and (null src) (eq (car from) :wild-inferiors) (eq (car to) :wild-inferiors)) (return-from translate-directory-components-aux nil)) (when (null src) ;; SRC is NIL and we're still here: error exit (throw 'failed-match nil)))))) (defun translate-directory-components (src from to case) (catch 'failed-match (return-from translate-directory-components (translate-directory-components-aux src from to case))) (error "Unsupported case in TRANSLATE-DIRECTORY-COMPONENTS.")) (defun translate-directory (source from to case) ;; FIXME The IGNORE-CASE argument to DIRECTORY-MATCH-P should not be nil on ;; Windows or if the source pathname is a logical pathname. ;; FIXME We can canonicalize logical pathnames to upper case, so we only need ;; IGNORE-CASE for Windows. (cond ((null source) to) ((equal source '(:absolute)) (remove :wild-inferiors to)) (t (translate-directory-components source from to case)))) ;; "The resulting pathname is TO-WILDCARD with each wildcard or missing field ;; replaced by a portion of SOURCE." (defun translate-pathname (source from-wildcard to-wildcard &key) (unless (pathname-match-p source from-wildcard) (error "~S and ~S do not match." source from-wildcard)) (let* ((source (pathname source)) (from (pathname from-wildcard)) (to (pathname to-wildcard)) (device (if (typep 'to 'logical-pathname) :unspecific (if (pathname-jar-p source) (translate-jar-device (pathname-device source) (pathname-device from) (pathname-device to)) (translate-component (pathname-device source) (pathname-device from) (pathname-device to))))) (case (and (typep source 'logical-pathname) (or (featurep :unix) (featurep :windows)) :downcase))) (make-pathname :host (pathname-host to) :device (cond ((typep to 'logical-pathname) :unspecific) ((eq device :unspecific) nil) (t device)) :directory (translate-directory (pathname-directory source) (pathname-directory from) (pathname-directory to) case) :name (translate-component (pathname-name source) (pathname-name from) (pathname-name to) case) :type (translate-component (pathname-type source) (pathname-type from) (pathname-type to) case) :version (if (null (pathname-host from)) (if (or (eq (pathname-version to) :wild) (eq (pathname-version to) nil)) (pathname-version source) (pathname-version to)) (translate-component (pathname-version source) (pathname-version from) (pathname-version to)))))) (defun logical-host-p (canonical-host) (multiple-value-bind (translations present) (gethash canonical-host *logical-pathname-translations*) (declare (ignore translations)) present)) (defun logical-pathname-translations (host) (multiple-value-bind (translations present) (gethash (canonicalize-logical-host host) *logical-pathname-translations*) (unless present (error 'type-error :datum host :expected-type '(and string (satisfies logical-host-p)))) translations)) (defun canonicalize-logical-pathname-translations (translations host) (let (result) (dolist (translation translations (nreverse result)) (let ((from (car translation)) (to (cadr translation))) (push (list (if (typep from 'logical-pathname) from (parse-namestring from host)) (pathname to)) result))))) (defun %set-logical-pathname-translations (host translations) (setf host (canonicalize-logical-host host)) ;; Avoid undefined host error in CANONICALIZE-LOGICAL-PATHNAME-TRANSLATIONS. (unless (logical-host-p host) (setf (gethash host *logical-pathname-translations*) nil)) (setf (gethash host *logical-pathname-translations*) (canonicalize-logical-pathname-translations translations host))) (defsetf logical-pathname-translations %set-logical-pathname-translations) (defun translate-logical-pathname (pathname &key) (typecase pathname (logical-pathname (let* ((host (pathname-host pathname)) (translations (logical-pathname-translations host))) (dolist (translation translations (error 'file-error :pathname pathname :format-control "No translation for ~S" :format-arguments (list pathname))) (let ((from-wildcard (car translation)) (to-wildcard (cadr translation))) (when (pathname-match-p pathname from-wildcard) (return (translate-logical-pathname (translate-pathname pathname from-wildcard to-wildcard)))))))) (pathname pathname) (t (translate-logical-pathname (pathname pathname))))) (defun load-logical-pathname-translations (host) (declare (type string host)) (multiple-value-bind (ignore found) (gethash (canonicalize-logical-host host) *logical-pathname-translations*) (declare (ignore ignore)) (unless found (error "The logical host ~S was not found." host)))) (defun logical-pathname (pathspec) (typecase pathspec (logical-pathname pathspec) (string (%make-logical-pathname pathspec)) (stream (let ((result (pathname pathspec))) (if (typep result 'logical-pathname) result (error 'simple-type-error :datum result :expected-type 'logical-pathname)))) (t (error 'type-error :datum pathspec :expected-type '(or logical-pathname string stream))))) (defun parse-namestring (thing &optional host (default-pathname *default-pathname-defaults*) &key (start 0) end junk-allowed) (declare (ignore junk-allowed)) ; FIXME (cond ((eq host :unspecific) (setf host nil)) ((consp host)) ;; A URL (host (setf host (canonicalize-logical-host host)))) (typecase thing (stream (values (pathname thing) start)) (pathname (values thing start)) (string (unless end (setf end (length thing))) (%parse-namestring (subseq thing start end) host default-pathname)) (t (error 'type-error :format-control "~S cannot be converted to a pathname." :format-arguments (list thing))))) ;;; Functions for dealing with URL Pathnames (in-package :extensions) (defun url-pathname-scheme (p) (unless (pathname-url-p p) (error "~A is not a URL pathname." p)) (getf (pathname-host p) :scheme)) (defun set-url-pathname-scheme (p v) (unless (pathname-url-p p) (error "~A is not a URL pathname." p)) (let ((host (pathname-host p))) (setf (getf host :scheme) v))) (defsetf url-pathname-scheme set-url-pathname-scheme) (defun url-pathname-authority (p) (unless (pathname-url-p p) (error "~A is not a URL pathname." p)) (getf (pathname-host p) :authority)) (defun set-url-pathname-authority (p v) (unless (pathname-url-p p) (error "~A is not a URL pathname." p)) (let ((host (pathname-host p))) (setf (getf host :authority) v))) (defsetf url-pathname-authority set-url-pathname-authority) (defun url-pathname-query (p) (unless (pathname-url-p p) (error "~A is not a URL pathname." p)) (getf (pathname-host p) :query)) (defun set-url-pathname-query (p v) (unless (pathname-url-p p) (error "~A is not a URL pathname." p)) (let ((host (pathname-host p))) (setf (getf host :query) v))) (defsetf url-pathname-query set-url-pathname-query) (defun url-pathname-fragment (p) (unless (pathname-url-p p) (error "~A is not a URL pathname." p)) (getf (pathname-host p) :fragment)) (defun set-url-pathname-fragment (p v) (unless (pathname-url-p p) (error "~A is not a URL pathname." p)) (let ((host (pathname-host p))) (setf (getf host :fragment) v))) (defsetf url-pathname-fragment set-url-pathname-fragment) (export '(url-pathname-scheme url-pathname-authority url-pathname-query url-pathname-fragment) 'ext) abcl-src-1.9.0/src/org/armedbear/lisp/peek_char.java0100644 0000000 0000000 00000012216 14202767264 021005 0ustar000000000 0000000 /* * peek_char.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### peek-char public final class peek_char extends Primitive { private static LispObject internalEOF = new LispObject(); private peek_char() { super("peek-char", "&optional peek-type input-stream eof-error-p eof-value recursive-p"); } @Override public LispObject execute(LispObject[] args) { int length = args.length; if (length > 5) error(new WrongNumberOfArgumentsException(this, -1, 5)); LispObject peekType = length > 0 ? args[0] : NIL; Stream stream = length > 1 ? inSynonymOf(args[1]) : getStandardInput(); boolean eofError = length > 2 ? (args[2] != NIL) : true; LispObject eofValue = length > 3 ? args[3] : NIL; // recursive-p is ignored // boolean recursive = length > 4 ? (args[4] != NIL) : false; if (peekType == NIL) { // "If PEEK-TYPE is not supplied or NIL, PEEK-CHAR returns the next // character to be read from INPUT-STREAM, without actually // removing it from INPUT-STREAM." final Stream in; if (stream instanceof EchoStream) // "When INPUT-STREAM is an echo stream, characters that are // only peeked at are not echoed." Read from the echo stream's // input stream to bypass the echo. in = ((EchoStream)stream).getInputStream(); else in = stream; final LispObject result = in.readChar(eofError, internalEOF); if (result == internalEOF) return eofValue; if (result instanceof LispCharacter) in.unreadChar((LispCharacter)result); return result; } if (peekType == T) { // "If PEEK-TYPE is T, then PEEK-CHAR skips over whitespace[2] // characters, but not comments, and then performs the peeking // operation on the next character." Readtable rt = currentReadtable(); while (true) { LispObject result = stream.readChar(eofError, internalEOF); if (result == internalEOF) return eofValue; if (result instanceof LispCharacter) { char c = ((LispCharacter)result).value; if (!rt.isWhitespace(c)) { stream.unreadChar((LispCharacter)result); return result; } } else return result; } } if (peekType instanceof LispCharacter) { // "If PEEK-TYPE is a character, then PEEK-CHAR skips over input // characters until a character that is CHAR= to that character is // found; that character is left in INPUT-STREAM." char c = ((LispCharacter)peekType).value; while (true) { LispObject result = stream.readChar(eofError, internalEOF); if (result == internalEOF) return eofValue; if (result instanceof LispCharacter) { if (((LispCharacter)result).value == c) { stream.unreadChar((LispCharacter)result); return result; } } else return result; } } return error(new SimpleError(String.valueOf(peekType) + " is an illegal peek-type.")); } private static final Primitive PEEK_CHAR = new peek_char(); } abcl-src-1.9.0/src/org/armedbear/lisp/pprint-dispatch.lisp0100644 0000000 0000000 00000037556 14223403213 022221 0ustar000000000 0000000 ;;; pprint-dispatch.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from the November, 26 1991 version of Richard C. Waters' XP pretty ;;; printer. ;------------------------------------------------------------------------ ;Copyright Massachusetts Institute of Technology, Cambridge, Massachusetts. ;Permission to use, copy, modify, and distribute this software and its ;documentation for any purpose and without fee is hereby granted, ;provided that this copyright and permission notice appear in all ;copies and supporting documentation, and that the name of M.I.T. not ;be used in advertising or publicity pertaining to distribution of the ;software without specific, written prior permission. M.I.T. makes no ;representations about the suitability of this software for any ;purpose. It is provided "as is" without express or implied warranty. ; M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ; ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ; M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ; ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ; WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ; ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ; SOFTWARE. ;------------------------------------------------------------------------ (in-package #:xp) (require "PPRINT") (defvar *ipd* nil ;see initialization at end of file. "initial print dispatch table.") (defstruct (pprint-dispatch-table (:conc-name nil) (:copier nil)) (conses-with-cars (make-hash-table :test #'eq) :type hash-table) (structures (make-hash-table :test #'eq) :type hash-table) (others nil :type list)) ;The list and the hash-tables contain entries of the ;following form. When stored in the hash tables, the test entry is ;the number of entries in the OTHERS list that have a higher priority. (defstruct (entry (:conc-name nil)) (test nil) ;predicate function or count of higher priority others. (fn nil) ;pprint function (full-spec nil)) ;list of priority and type specifier (defun copy-pprint-dispatch (&optional (table *print-pprint-dispatch*)) (unless table (setf table *ipd*)) (sys::require-type table 'pprint-dispatch-table) (let* ((new-conses-with-cars (make-hash-table :test #'eq :size (max (hash-table-count (conses-with-cars table)) 32))) (new-structures (make-hash-table :test #'eq :size (max (hash-table-count (structures table)) 32)))) (maphash #'(lambda (key value) (setf (gethash key new-conses-with-cars) (copy-entry value))) (conses-with-cars table)) (maphash #'(lambda (key value) (setf (gethash key new-structures) (copy-entry value))) (structures table)) (make-pprint-dispatch-table :conses-with-cars new-conses-with-cars :structures new-structures :others (copy-list (others table))))) (defun set-pprint-dispatch (type-specifier function &optional (priority 0) (table *print-pprint-dispatch*)) (when (or (not (numberp priority)) (complexp priority)) (error "invalid PRIORITY argument ~A to SET-PPRINT-DISPATCH" priority)) (set-pprint-dispatch+ type-specifier function priority table)) (defun set-pprint-dispatch+ (type-specifier function priority table) (let* ((category (specifier-category type-specifier)) (pred (if (not (eq category 'other)) nil (let ((pred (specifier-fn type-specifier))) (if (and (consp (caddr pred)) (symbolp (caaddr pred)) (equal (cdaddr pred) '(x))) (symbol-function (caaddr pred)) ;; (compile nil pred) pred )))) (entry (if function (make-entry :test pred :fn function :full-spec (list priority type-specifier))))) (case category (cons-with-car (cond ((null entry) (remhash (cadadr type-specifier) (conses-with-cars table))) (T (setf (test entry) (count-if #'(lambda (e) (priority-> (car (full-spec e)) priority)) (others table))) (setf (gethash (cadadr type-specifier) (conses-with-cars table)) entry)))) (structure-type (cond ((null entry) (remhash type-specifier (structures table))) (T (setf (test entry) (count-if #'(lambda (e) (priority-> (car (full-spec e)) priority)) (others table))) (setf (gethash type-specifier (structures table)) entry)))) (T ;other (let ((old (car (member type-specifier (others table) :test #'equal :key #'(lambda (e) (cadr (full-spec e))))))) (when old (setf (others table) (delete old (others table))) (adjust-counts table (car (full-spec old)) -1))) (when entry (let ((others (cons nil (others table)))) (do ((l others (cdr l))) ((null (cdr l)) (rplacd l (list entry))) (when (priority-> priority (car (full-spec (cadr l)))) (rplacd l (cons entry (cdr l))) (return nil))) (setf (others table) (cdr others))) (adjust-counts table priority 1))))) nil) (defun priority-> (x y) (if (consp x) (if (consp y) (> (car x) (car y)) nil) (if (consp y) T (> x y)))) (defun adjust-counts (table priority delta) (maphash #'(lambda (key value) (declare (ignore key)) (if (priority-> priority (car (full-spec value))) (incf (test value) delta))) (conses-with-cars table)) (maphash #'(lambda (key value) (declare (ignore key)) (if (priority-> priority (car (full-spec value))) (incf (test value) delta))) (structures table))) (defun pprint-dispatch (object &optional (table *print-pprint-dispatch*)) (unless table (setf table *ipd*)) (let ((fn (get-printer object table))) (values (or fn #'non-pretty-print) (not (null fn))))) (defun get-printer (object table) (let* ((entry (if (consp object) (gethash (car object) (conses-with-cars table)) (gethash (type-of object) (structures table))))) (if (not entry) (setq entry (find object (others table) :test #'fits)) (do ((i (test entry) (1- i)) (l (others table) (cdr l))) ((zerop i)) (when (fits object (car l)) (setq entry (car l)) (return nil)))) (when entry (fn entry)))) (defun fits (obj entry) (funcall (test entry) obj)) (defun specifier-category (spec) (cond ((and (consp spec) (eq (car spec) 'cons) (consp (cdr spec)) (null (cddr spec)) (consp (cadr spec)) (eq (caadr spec) 'member) (consp (cdadr spec)) (null (cddadr spec))) 'cons-with-car) ((and (symbolp spec) ;; (structure-type-p spec) (get spec 'structure-printer) ) 'structure-type) (T 'other))) (defvar *preds-for-specs* '((T always-true) (cons consp) (simple-atom simple-atom-p) (other otherp) (null null) (symbol symbolp) (atom atom) (cons consp) (list listp) (number numberp) (integer integerp) (rational rationalp) (float floatp) (complex complexp) (character characterp) (string stringp) (bit-vector bit-vector-p) (vector vectorp) (simple-vector simple-vector-p) (simple-string simple-string-p) (simple-bit-vector simple-bit-vector-p) (array arrayp) (package packagep) (function functionp) (compiled-function compiled-function-p) (common commonp))) (defun always-true (x) (declare (ignore x)) T) (defun specifier-fn (spec) `(lambda (x) ,(convert-body spec))) (defun convert-body (spec) (cond ((atom spec) (let ((pred (cadr (assoc spec *preds-for-specs*)))) (if pred `(,pred x) `(typep x ',spec)))) ((member (car spec) '(and or not)) (cons (car spec) (mapcar #'convert-body (cdr spec)))) ((eq (car spec) 'member) `(member x ',(copy-list (cdr spec)))) ((eq (car spec) 'cons) `(and (consp x) ,@(if (cdr spec) `((let ((x (car x))) ,(convert-body (cadr spec))))) ,@(if (cddr spec) `((let ((x (cdr x))) ,(convert-body (caddr spec))))))) ((eq (car spec) 'satisfies) `(funcall (function ,(cadr spec)) x)) ((eq (car spec) 'eql) `(eql x ',(cadr spec))) (t `(typep x ',(copy-tree spec))))) (defun function-call-p (x) (and (consp x) (symbolp (car x)) (fboundp (car x)))) (setq *ipd* (make-pprint-dispatch-table)) (set-pprint-dispatch+ '(satisfies function-call-p) 'fn-call '(-5) *ipd*) (set-pprint-dispatch+ 'cons 'pprint-fill '(-10) *ipd*) (set-pprint-dispatch+ '(cons (member block)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member case)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member catch)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member ccase)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member compiler-let)) 'let-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member cond)) 'cond-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member ctypecase)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member defconstant)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member define-setf-method)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member defmacro)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member define-modify-macro)) 'dmm-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member defparameter)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member defsetf)) 'defsetf-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member define-setf-method)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member defstruct)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member deftype)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member defun)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member defvar)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member do)) 'do-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member do*)) 'do-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member do-all-symbols)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member do-external-symbols)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member do-symbols)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member dolist)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member dotimes)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member ecase)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member etypecase)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member eval-when)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member flet)) 'flet-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member function)) 'function-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member labels)) 'flet-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member lambda)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member let)) 'let-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member let*)) 'let-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member locally)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member loop)) 'pretty-loop '(0) *ipd*) (set-pprint-dispatch+ '(cons (member macrolet)) 'flet-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member multiple-value-bind)) 'mvb-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member multiple-value-setq)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member prog)) 'prog-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member prog*)) 'prog-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member progv)) 'defun-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member psetf)) 'setq-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member psetq)) 'setq-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member quote)) 'quote-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member return-from)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member setf)) 'setq-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member setq)) 'setq-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member tagbody)) 'tagbody-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member throw)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member typecase)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member unless)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member unwind-protect)) 'up-print '(0) *ipd*) (set-pprint-dispatch+ '(cons (member when)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member with-input-from-string)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member with-open-file)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member with-open-stream)) 'block-like '(0) *ipd*) (set-pprint-dispatch+ '(cons (member with-output-to-string)) 'block-like '(0) *ipd*) (defun pprint-dispatch-print (xp table) (let ((stuff (copy-list (others table)))) (maphash #'(lambda (key val) (declare (ignore key)) (push val stuff)) (conses-with-cars table)) (maphash #'(lambda (key val) (declare (ignore key)) (push val stuff)) (structures table)) (setq stuff (sort stuff #'priority-> :key #'(lambda (x) (car (full-spec x))))) (pprint-logical-block (xp stuff :prefix "#<" :suffix ">") (format xp (formatter "pprint dispatch table containing ~A entries: ") (length stuff)) (loop (pprint-exit-if-list-exhausted) (let ((entry (pprint-pop))) (format xp (formatter "~{~_P=~4D ~W~} F=~W ") (full-spec entry) (fn entry))))))) (setf (get 'pprint-dispatch-table 'structure-printer) #'pprint-dispatch-print) (set-pprint-dispatch+ 'pprint-dispatch-table #'pprint-dispatch-print '(0) *ipd*) (setf *print-pprint-dispatch* (copy-pprint-dispatch nil)) (provide "PPRINT-DISPATCH") abcl-src-1.9.0/src/org/armedbear/lisp/pprint.lisp0100644 0000000 0000000 00000163220 14223403213 020410 0ustar000000000 0000000 ;;; pprint.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from the November, 26 1991 version of Richard C. Waters' XP pretty ;;; printer. ;------------------------------------------------------------------------ ;Copyright Massachusetts Institute of Technology, Cambridge, Massachusetts. ;Permission to use, copy, modify, and distribute this software and its ;documentation for any purpose and without fee is hereby granted, ;provided that this copyright and permission notice appear in all ;copies and supporting documentation, and that the name of M.I.T. not ;be used in advertising or publicity pertaining to distribution of the ;software without specific, written prior permission. M.I.T. makes no ;representations about the suitability of this software for any ;purpose. It is provided "as is" without express or implied warranty. ; M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ; ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ; M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ; ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ; WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ; ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ; SOFTWARE. ;------------------------------------------------------------------------ (in-package #:xp) ;must do the following in common lisps not supporting *print-shared* (require "PRINT") (defvar *print-shared* nil) (export '(*print-shared*)) (defvar *default-right-margin* 70. "controls default line length; must be a non-negative integer") (defvar *current-level* 0 "current depth in logical blocks.") (defvar *abbreviation-happened* nil "t if current thing being printed has been abbreviated.") (defvar *result* nil "used to pass back a value") ;default (bad) definitions for the non-portable functions #-(or :symbolics :lucid :franz-inc :cmu)(eval-when (eval load compile) (defun structure-type-p (x) (and (symbolp x) (get x 'structure-printer))) (defun output-width (&optional (s *standard-output*)) (declare (ignore s)) nil)) (defvar *locating-circularities* nil "Integer if making a first pass over things to identify circularities. Integer used as counter for #n= syntax.") ; ---- XP STRUCTURES, AND THE INTERNAL ALGORITHM ---- (eval-when (eval load compile) ;not used at run time. (defvar block-stack-entry-size 1) (defvar prefix-stack-entry-size 5) (defvar queue-entry-size 7) (defvar buffer-entry-size 1) (defvar prefix-entry-size 1) (defvar suffix-entry-size 1)) (eval-when (eval load compile) ;used at run time (defvar block-stack-min-size #.(* 35. block-stack-entry-size)) (defvar prefix-stack-min-size #.(* 30. prefix-stack-entry-size)) (defvar queue-min-size #.(* 75. queue-entry-size)) (defvar buffer-min-size 256.) (defvar prefix-min-size 256.) (defvar suffix-min-size 256.) ) (defstruct (xp-structure (:conc-name nil) #+nil (:print-function describe-xp)) (base-stream nil) ;;The stream io eventually goes to. line-length ;;The line length to use for formatting. line-limit ;;If non-NIL the max number of lines to print. line-no ;;number of next line to be printed. depth-in-blocks ;;Number of logical blocks at QRIGHT that are started but not ended. (block-stack (make-array #.block-stack-min-size)) block-stack-ptr ;;This stack is pushed and popped in accordance with the way blocks are ;;nested at the moment they are entered into the queue. It contains the ;;following block specific value. ;;SECTION-START total position where the section (see AIM-1102) ;;that is rightmost in the queue started. (buffer (make-array #.buffer-min-size :element-type 'character)) charpos buffer-ptr buffer-offset ;;This is a vector of characters (eg a string) that builds up the ;;line images that will be printed out. BUFFER-PTR is the ;;buffer position where the next character should be inserted in ;;the string. CHARPOS is the output character position of the ;;first character in the buffer (non-zero only if a partial line ;;has been output). BUFFER-OFFSET is used in computing total lengths. ;;It is changed to reflect all shifting and insertion of prefixes so that ;;total length computes things as they would be if they were ;;all on one line. Positions are kept three different ways ;; Buffer position (eg BUFFER-PTR) ;; Line position (eg (+ BUFFER-PTR CHARPOS)). Indentations are stored in this form. ;; Total position if all on one line (eg (+ BUFFER-PTR BUFFER-OFFSET)) ;; Positions are stored in this form. (queue (make-array #.queue-min-size)) qleft qright ;;This holds a queue of action descriptors. QLEFT and QRIGHT ;;point to the next entry to dequeue and the last entry enqueued ;;respectively. The queue is empty when ;;(> QLEFT QRIGHT). The queue entries have several parts: ;;QTYPE one of :NEWLINE/:IND/:START-BLOCK/:END-BLOCK ;;QKIND :LINEAR/:MISER/:FILL/:MANDATORY or :UNCONDITIONAL/:FRESH ;; or :BLOCK/:CURRENT ;;QPOS total position corresponding to this entry ;;QDEPTH depth in blocks of this entry. ;;QEND offset to entry marking end of section this entry starts. (NIL until known.) ;; Only :start-block and non-literal :newline entries can start sections. ;;QOFFSET offset to :END-BLOCK for :START-BLOCK (NIL until known). ;;QARG for :IND indentation delta ;; for :START-BLOCK suffix in the block if any. ;; or if per-line-prefix then cons of suffix and ;; per-line-prefix. ;; for :END-BLOCK suffix for the block if any. (prefix (make-array #.buffer-min-size :element-type 'character)) ;;this stores the prefix that should be used at the start of the line (prefix-stack (make-array #.prefix-stack-min-size)) prefix-stack-ptr ;;This stack is pushed and popped in accordance with the way blocks ;;are nested at the moment things are taken off the queue and printed. ;;It contains the following block specific values. ;;PREFIX-PTR current length of PREFIX. ;;SUFFIX-PTR current length of pending suffix ;;NON-BLANK-PREFIX-PTR current length of non-blank prefix. ;;INITIAL-PREFIX-PTR prefix-ptr at the start of this block. ;;SECTION-START-LINE line-no value at last non-literal break at this level. (suffix (make-array #.buffer-min-size :element-type 'character)) ;;this stores the suffixes that have to be printed to close of the current ;;open blocks. For convenient in popping, the whole suffix ;;is stored in reverse order. ) (defun ext:charpos (stream) (cond ((xp-structure-p stream) (charpos stream)) ((streamp stream) (sys::stream-charpos stream)))) (defun (setf ext:charpos) (new-value stream) (cond ((xp-structure-p stream) (setf (charpos stream) new-value)) ((streamp stream) (sys::stream-%set-charpos stream new-value)))) (defmacro LP<-BP (xp &optional (ptr nil)) (if (null ptr) (setq ptr `(buffer-ptr ,xp))) `(+ ,ptr (charpos ,xp))) (defmacro TP<-BP (xp) `(+ (buffer-ptr ,xp) (buffer-offset ,xp))) (defmacro BP<-LP (xp ptr) `(- ,ptr (charpos ,xp))) (defmacro BP<-TP (xp ptr) `(- ,ptr (buffer-offset ,xp))) ;This does not tell you the line position you were at when the TP ;was set, unless there have been no newlines or indentation output ;between ptr and the current output point. (defmacro LP<-TP (xp ptr) `(LP<-BP ,xp (BP<-TP ,xp ,ptr))) ;We don't use adjustable vectors or any of that, because we seldom have ;to actually extend and non-adjustable vectors are a lot faster in ;many Common Lisps. (defmacro check-size (xp vect ptr) (let* ((min-size (symbol-value (intern (concatenate 'string (string vect) "-MIN-SIZE") (find-package "XP")))) (entry-size (symbol-value (intern (concatenate 'string (string vect) "-ENTRY-SIZE") (find-package "XP"))))) `(when (and (> ,ptr ,(- min-size entry-size)) ;seldom happens (> ,ptr (- (length (,vect ,xp)) ,entry-size))) (let* ((old (,vect ,xp)) (new (make-array (+ ,ptr ,(if (= entry-size 1) 50 (* 10 entry-size))) :element-type (array-element-type old)))) (replace new old) (setf (,vect ,xp) new))))) (defmacro section-start (xp) `(aref (block-stack ,xp) (block-stack-ptr ,xp))) (defun push-block-stack (xp) (incf (block-stack-ptr xp) #.block-stack-entry-size) (check-size xp block-stack (block-stack-ptr xp))) (defun pop-block-stack (xp) (decf (block-stack-ptr xp) #.block-stack-entry-size)) (defmacro prefix-ptr (xp) `(aref (prefix-stack ,xp) (prefix-stack-ptr ,xp))) (defmacro suffix-ptr (xp) `(aref (prefix-stack ,xp) (+ (prefix-stack-ptr ,xp) 1))) (defmacro non-blank-prefix-ptr (xp) `(aref (prefix-stack ,xp) (+ (prefix-stack-ptr ,xp) 2))) (defmacro initial-prefix-ptr (xp) `(aref (prefix-stack ,xp) (+ (prefix-stack-ptr ,xp) 3))) (defmacro section-start-line (xp) `(aref (prefix-stack ,xp) (+ (prefix-stack-ptr ,xp) 4))) (defun push-prefix-stack (xp) (let ((old-prefix 0) (old-suffix 0) (old-non-blank 0)) (when (not (minusp (prefix-stack-ptr xp))) (setq old-prefix (prefix-ptr xp) old-suffix (suffix-ptr xp) old-non-blank (non-blank-prefix-ptr xp))) (incf (prefix-stack-ptr xp) #.prefix-stack-entry-size) (check-size xp prefix-stack (prefix-stack-ptr xp)) (setf (prefix-ptr xp) old-prefix) (setf (suffix-ptr xp) old-suffix) (setf (non-blank-prefix-ptr xp) old-non-blank))) (defun pop-prefix-stack (xp) (decf (prefix-stack-ptr xp) #.prefix-stack-entry-size)) (defmacro Qtype (xp index) `(aref (queue ,xp) ,index)) (defmacro Qkind (xp index) `(aref (queue ,xp) (1+ ,index))) (defmacro Qpos (xp index) `(aref (queue ,xp) (+ ,index 2))) (defmacro Qdepth (xp index) `(aref (queue ,xp) (+ ,index 3))) (defmacro Qend (xp index) `(aref (queue ,xp) (+ ,index 4))) (defmacro Qoffset (xp index) `(aref (queue ,xp) (+ ,index 5))) (defmacro Qarg (xp index) `(aref (queue ,xp) (+ ,index 6))) ;we shift the queue over rather than using a circular queue because ;that works out to be a lot faster in practice. Note, short printout ;does not ever cause a shift, and even in long printout, the queue is ;shifted left for free every time it happens to empty out. (defun enqueue (xp type kind &optional arg) (incf (Qright xp) #.queue-entry-size) (when (> (Qright xp) #.(- queue-min-size queue-entry-size)) (replace (queue xp) (queue xp) :start2 (Qleft xp) :end2 (Qright xp)) (setf (Qright xp) (- (Qright xp) (Qleft xp))) (setf (Qleft xp) 0)) (check-size xp queue (Qright xp)) (setf (Qtype xp (Qright xp)) type) (setf (Qkind xp (Qright xp)) kind) (setf (Qpos xp (Qright xp)) (TP<-BP xp)) (setf (Qdepth xp (Qright xp)) (depth-in-blocks xp)) (setf (Qend xp (Qright xp)) nil) (setf (Qoffset xp (Qright xp)) nil) (setf (Qarg xp (Qright xp)) arg)) (defmacro Qnext (index) `(+ ,index #.queue-entry-size)) ;This is called to initialize things when you start pretty printing. (defun initialize-xp (xp stream) (setf (base-stream xp) stream) (setf (line-length xp) (max 0 (cond (*print-right-margin*) ((output-width stream)) (t *default-right-margin*)))) (setf (line-limit xp) *print-lines*) (setf (line-no xp) 1) (setf (depth-in-blocks xp) 0) (setf (block-stack-ptr xp) 0) (setf (charpos xp) (cond ((ext:charpos stream)) (t 0))) (setf (section-start xp) 0) (setf (buffer-ptr xp) 0) (setf (buffer-offset xp) (charpos xp)) (setf (Qleft xp) 0) (setf (Qright xp) #.(- queue-entry-size)) (setf (prefix-stack-ptr xp) #.(- prefix-stack-entry-size)) xp) ;This handles the basic outputting of characters. note + suffix means that ;the stream is known to be an XP stream, all inputs are mandatory, and no ;error checking has to be done. Suffix ++ additionally means that the ;output is guaranteed not to contain a newline char. (defun write-char+ (char xp) (if (eql char #\newline) (pprint-newline+ :unconditional xp) (write-char++ char xp))) (defun write-string+ (string xp start end) (let ((sub-end nil) next-newline) (loop (setq next-newline (position #\newline string :test #'char= :start start :end end)) (setq sub-end (if next-newline next-newline end)) (write-string++ string xp start sub-end) (when (null next-newline) (return nil)) (pprint-newline+ :unconditional xp) (setq start (1+ sub-end))))) ;note this checks (> BUFFER-PTR LINE-LENGTH) instead of (> (LP<-BP) LINE-LENGTH) ;this is important so that when things are longer than a line they ;end up getting printed in chunks of size LINE-LENGTH. (defun write-char++ (char xp) (when (> (buffer-ptr xp) (line-length xp)) (force-some-output xp)) (let ((new-buffer-end (1+ (buffer-ptr xp)))) (check-size xp buffer new-buffer-end) (setf (char (buffer xp) (buffer-ptr xp)) char) (setf (buffer-ptr xp) new-buffer-end))) (defun force-some-output (xp) (attempt-to-output xp nil nil) (when (> (buffer-ptr xp) (line-length xp)) ;only if printing off end of line (attempt-to-output xp T T))) (defun write-string++ (string xp start end) (when (> (buffer-ptr xp) (line-length xp)) (force-some-output xp)) (write-string+++ string xp start end)) ;never forces output; therefore safe to call from within output-line. (defun write-string+++ (string xp start end) (let ((new-buffer-end (+ (buffer-ptr xp) (- end start)))) (check-size xp buffer new-buffer-end) (do ((buffer (buffer xp)) (i (buffer-ptr xp) (1+ i)) (j start (1+ j))) ((= j end)) (let ((char (char string j))) (setf (char buffer i) char))) (setf (buffer-ptr xp) new-buffer-end))) (defun pprint-tab+ (kind colnum colinc xp) (let ((indented? nil) (relative? nil)) (case kind (:section (setq indented? t)) (:line-relative (setq relative? t)) (:section-relative (setq indented? t relative? t))) (let* ((current (if (not indented?) (LP<-BP xp) (- (TP<-BP xp) (section-start xp)))) (new (if (zerop colinc) (if relative? (+ current colnum) (max colnum current)) (cond (relative? (* colinc (floor (+ current colnum colinc -1) colinc))) ((> colnum current) colnum) (T (+ colnum (* colinc (floor (+ current (- colnum) colinc) colinc))))))) (length (- new current))) (when (plusp length) (let ((end (+ (buffer-ptr xp) length))) (check-size xp buffer end) (fill (buffer xp) #\space :start (buffer-ptr xp) :end end) (setf (buffer-ptr xp) end)))))) ;note following is smallest number >= x that is a multiple of colinc ; (* colinc (floor (+ x (1- colinc)) colinc)) (defun pprint-newline+ (kind xp) (enqueue xp :newline kind) (do ((ptr (Qleft xp) (Qnext ptr))) ;find sections we are ending ((not (< ptr (Qright xp)))) ;all but last (when (and (null (Qend xp ptr)) (not (> (depth-in-blocks xp) (Qdepth xp ptr))) (member (Qtype xp ptr) '(:newline :start-block))) (setf (Qend xp ptr) (- (Qright xp) ptr)))) (setf (section-start xp) (TP<-BP xp)) (when (member kind '(:fresh :unconditional :mandatory)) (attempt-to-output xp T nil))) (defun start-block (xp prefix on-each-line? suffix) (unless (stringp prefix) (error 'type-error :datum prefix :expected-type 'string)) (unless (stringp suffix) (error 'type-error :datum suffix :expected-type 'string)) (when prefix (write-string++ prefix xp 0 (length prefix))) (push-block-stack xp) (enqueue xp :start-block nil (if on-each-line? (cons suffix prefix) suffix)) (incf (depth-in-blocks xp)) ;must be after enqueue (setf (section-start xp) (TP<-BP xp))) (defun end-block (xp suffix) (unless (eq *abbreviation-happened* '*print-lines*) (when suffix (write-string+ suffix xp 0 (length suffix))) (decf (depth-in-blocks xp)) (enqueue xp :end-block nil suffix) (do ((ptr (Qleft xp) (Qnext ptr))) ;looking for start of block we are ending ((not (< ptr (Qright xp)))) ;all but last (when (and (= (depth-in-blocks xp) (Qdepth xp ptr)) (eq (Qtype xp ptr) :start-block) (null (Qoffset xp ptr))) (setf (Qoffset xp ptr) (- (Qright xp) ptr)) (return nil))) ;can only be 1 (pop-block-stack xp))) (defun pprint-indent+ (kind n xp) (enqueue xp :ind kind n)) ; The next function scans the queue looking for things it can do. ;it keeps outputting things until the queue is empty, or it finds ;a place where it cannot make a decision yet. (defmacro maybe-too-large (xp Qentry) `(let ((limit (line-length ,xp))) (when (eql (line-limit ,xp) (line-no ,xp)) ;prevents suffix overflow (decf limit 2) ;3 for " .." minus 1 for space (heuristic) (when (not (minusp (prefix-stack-ptr ,xp))) (decf limit (suffix-ptr ,xp)))) (cond ((Qend ,xp ,Qentry) (> (LP<-TP ,xp (Qpos ,xp (+ ,Qentry (Qend ,xp ,Qentry)))) limit)) ((or force-newlines? (> (LP<-BP ,xp) limit)) T) (T (return nil))))) ;wait until later to decide. (defmacro misering? (xp) `(and *print-miser-width* (<= (- (line-length ,xp) (initial-prefix-ptr ,xp)) *print-miser-width*))) ;If flush-out? is T and force-newlines? is NIL then the buffer, ;prefix-stack, and queue will be in an inconsistent state after the call. ;You better not call it this way except as the last act of outputting. (defun attempt-to-output (xp force-newlines? flush-out?) (do () ((> (Qleft xp) (Qright xp)) (setf (Qleft xp) 0) (setf (Qright xp) #.(- queue-entry-size))) ;saves shifting (case (Qtype xp (Qleft xp)) (:ind (unless (misering? xp) (set-indentation-prefix xp (case (Qkind xp (Qleft xp)) (:block (+ (initial-prefix-ptr xp) (Qarg xp (Qleft xp)))) (T ; :current (+ (LP<-TP xp (Qpos xp (Qleft xp))) (Qarg xp (Qleft xp))))))) (setf (Qleft xp) (Qnext (Qleft xp)))) (:start-block (cond ((maybe-too-large xp (Qleft xp)) (push-prefix-stack xp) (setf (initial-prefix-ptr xp) (prefix-ptr xp)) (set-indentation-prefix xp (LP<-TP xp (Qpos xp (Qleft xp)))) (let ((arg (Qarg xp (Qleft xp)))) (when (consp arg) (set-prefix xp (cdr arg))) (setf (initial-prefix-ptr xp) (prefix-ptr xp)) (cond ((not (listp arg)) (set-suffix xp arg)) ((car arg) (set-suffix xp (car arg))))) (setf (section-start-line xp) (line-no xp))) (T (incf (Qleft xp) (Qoffset xp (Qleft xp))))) (setf (Qleft xp) (Qnext (Qleft xp)))) (:end-block (pop-prefix-stack xp) (setf (Qleft xp) (Qnext (Qleft xp)))) (T ; :newline (when (case (Qkind xp (Qleft xp)) (:fresh (not (zerop (LP<-BP xp)))) (:miser (misering? xp)) (:fill (or (misering? xp) (> (line-no xp) (section-start-line xp)) (maybe-too-large xp (Qleft xp)))) (T T)) ;(:linear :unconditional :mandatory) (output-line xp (Qleft xp)) (setup-for-next-line xp (Qleft xp))) (setf (Qleft xp) (Qnext (Qleft xp)))))) (when flush-out? (flush xp))) ;this can only be called last! (defun flush (xp) (unless *locating-circularities* (write-string (buffer xp) (base-stream xp) :end (buffer-ptr xp))) (incf (buffer-offset xp) (buffer-ptr xp)) (incf (charpos xp) (buffer-ptr xp)) (setf (buffer-ptr xp) 0)) ;This prints out a line of stuff. (defun output-line (xp Qentry) (let* ((out-point (BP<-TP xp (Qpos xp Qentry))) (last-non-blank (position #\space (buffer xp) :test-not #'char= :from-end T :end out-point)) (end (cond ((member (Qkind xp Qentry) '(:fresh :unconditional)) out-point) (last-non-blank (1+ last-non-blank)) (T 0))) (line-limit-exit (and (line-limit xp) (not *print-readably*) (not (> (line-limit xp) (line-no xp)))))) (when line-limit-exit (setf (buffer-ptr xp) end) ;truncate pending output. (write-string+++ " .." xp 0 3) (reverse-string-in-place (suffix xp) 0 (suffix-ptr xp)) (write-string+++ (suffix xp) xp 0 (suffix-ptr xp)) (setf (Qleft xp) (Qnext (Qright xp))) (setf *abbreviation-happened* '*print-lines*) (throw 'line-limit-abbreviation-exit T)) (incf (line-no xp)) (unless *locating-circularities* (let ((stream (base-stream xp))) (sys::%write-string (buffer xp) stream 0 end) (sys::%terpri stream))))) (defun setup-for-next-line (xp Qentry) (let* ((out-point (BP<-TP xp (Qpos xp Qentry))) (prefix-end (cond ((member (Qkind xp Qentry) '(:unconditional :fresh)) (non-blank-prefix-ptr xp)) (T (prefix-ptr xp)))) (change (- prefix-end out-point))) (setf (charpos xp) 0) (when (plusp change) ;almost never happens (check-size xp buffer (+ (buffer-ptr xp) change))) (replace (buffer xp) (buffer xp) :start1 prefix-end :start2 out-point :end2 (buffer-ptr xp)) (replace (buffer xp) (prefix xp) :end2 prefix-end) (incf (buffer-ptr xp) change) (decf (buffer-offset xp) change) (when (not (member (Qkind xp Qentry) '(:unconditional :fresh))) (setf (section-start-line xp) (line-no xp))))) (defun set-indentation-prefix (xp new-position) (let ((new-ind (max (non-blank-prefix-ptr xp) new-position))) (setf (prefix-ptr xp) (initial-prefix-ptr xp)) (check-size xp prefix new-ind) (when (> new-ind (prefix-ptr xp)) (fill (prefix xp) #\space :start (prefix-ptr xp) :end new-ind)) (setf (prefix-ptr xp) new-ind))) (defun set-prefix (xp prefix-string) (replace (prefix xp) prefix-string :start1 (- (prefix-ptr xp) (length prefix-string))) (setf (non-blank-prefix-ptr xp) (prefix-ptr xp))) (defun set-suffix (xp suffix-string) (let* ((end (length suffix-string)) (new-end (+ (suffix-ptr xp) end))) (check-size xp suffix new-end) (do ((i (1- new-end) (1- i)) (j 0 (1+ j))) ((= j end)) (setf (char (suffix xp) i) (char suffix-string j))) (setf (suffix-ptr xp) new-end))) (defun reverse-string-in-place (string start end) (do ((i start (1+ i)) (j (1- end) (1- j))) ((not (< i j)) string) (let ((c (char string i))) (setf (char string i) (char string j)) (setf (char string j) c)))) ; ---- BASIC INTERFACE FUNCTIONS ---- ;The internal functions in this file, and the (formatter "...") expansions ;use the '+' forms of these functions directly (which is faster) because, ;they do not need error checking of fancy stream coercion. The '++' forms ;additionally assume the thing being output does not contain a newline. (defun write (object &key ((:stream stream) *standard-output*) ((:escape *print-escape*) *print-escape*) ((:radix *print-radix*) *print-radix*) ((:base *print-base*) *print-base*) ((:circle *print-circle*) *print-circle*) ((:pretty *print-pretty*) *print-pretty*) ((:level *print-level*) *print-level*) ((:length *print-length*) *print-length*) ((:case *print-case*) *print-case*) ((:array *print-array*) *print-array*) ((:gensym *print-gensym*) *print-gensym*) ((:readably *print-readably*) *print-readably*) ((:right-margin *print-right-margin*) *print-right-margin*) ((:miser-width *print-miser-width*) *print-miser-width*) ((:lines *print-lines*) *print-lines*) ((:pprint-dispatch *print-pprint-dispatch*) *print-pprint-dispatch*)) (sys:output-object object (sys:out-synonym-of stream)) object) (defun maybe-initiate-xp-printing (object fn stream &rest args) (if (xp-structure-p stream) (apply fn stream args) (let ((*abbreviation-happened* nil) (*result* nil)) (if (and *print-circle* (null sys::*circularity-hash-table*)) (let ((sys::*circularity-hash-table* (make-hash-table :test 'eq))) (setf (gethash object sys::*circularity-hash-table*) t) (xp-print fn (make-broadcast-stream) args) (let ((sys::*circularity-counter* 0)) (when (eql 0 (gethash object sys::*circularity-hash-table*)) (setf (gethash object sys::*circularity-hash-table*) (incf sys::*circularity-counter*)) (sys::print-label (gethash object sys::*circularity-hash-table*) (sys:out-synonym-of stream))) (xp-print fn (sys:out-synonym-of stream) args))) (xp-print fn (sys:out-synonym-of stream) args)) *result*))) (defun xp-print (fn stream args) (setq *result* (do-xp-printing fn stream args)) (when *locating-circularities* (setq *locating-circularities* nil) (setq *abbreviation-happened* nil) ;; (setq *parents* nil) (setq *result* (do-xp-printing fn stream args)))) (defun do-xp-printing (fn stream args) (let ((xp (initialize-xp (make-xp-structure) stream)) (*current-level* 0) (result nil)) (catch 'line-limit-abbreviation-exit (start-block xp "" nil "") (setq result (apply fn xp args)) (end-block xp nil)) (when (and *locating-circularities* (zerop *locating-circularities*) ;No circularities. (= (line-no xp) 1) ;Didn't suppress line. (zerop (buffer-offset xp))) ;Didn't suppress partial line. (setq *locating-circularities* nil)) ;print what you have got. (when (catch 'line-limit-abbreviation-exit (attempt-to-output xp nil t) nil) (attempt-to-output xp t t)) result)) (defun write+ (object xp) ;; (let ((*parents* *parents*)) ;; (unless (and *circularity-hash-table* ;; (eq (circularity-process xp object nil) :subsequent)) ;; (when (and *circularity-hash-table* (consp object)) ;; ;;avoid possible double check in handle-logical-block. ;; (setq object (cons (car object) (cdr object)))) (let ((printer (if *print-pretty* (get-printer object *print-pprint-dispatch*) nil)) type) (cond (printer (funcall printer xp object)) ((maybe-print-fast object xp)) ((and *print-pretty* (symbolp (setq type (type-of object))) (setq printer (get type 'structure-printer)) (not (eq printer :none))) (funcall printer xp object)) ((and *print-pretty* *print-array* (arrayp object) (not (stringp object)) (not (bit-vector-p object)) (not (structure-type-p (type-of object)))) (pretty-array xp object)) (t (let ((stuff (with-output-to-string (s) (non-pretty-print object s)))) (write-string+ stuff xp 0 (length stuff))))))) (defun non-pretty-print (object s) ;; (write object ;; :level (if *print-level* ;; (- *print-level* *current-level*)) ;; :pretty nil ;; :stream s)) (sys::output-ugly-object object s)) ;This prints a few very common, simple atoms very fast. ;Pragmatically, this turns out to be an enormous savings over going to the ;standard printer all the time. There would be diminishing returns from making ;this work with more things, but might be worth it. (defun maybe-print-fast (object xp) (cond ((stringp object) (let ((s (sys::%write-to-string object))) (write-string++ s xp 0 (length s)) t)) ((ext:fixnump object) (print-fixnum xp object) t) ((and (symbolp object) (or (symbol-package object) (null *print-circle*))) (let ((s (sys::%write-to-string object))) (write-string++ s xp 0 (length s)) t) ))) (defun print-fixnum (xp fixnum) (let ((s (sys::%write-to-string fixnum))) (write-string++ s xp 0 (length s)))) (defun print (object &optional (stream *standard-output*)) (setf stream (sys:out-synonym-of stream)) (terpri stream) (let ((*print-escape* t)) (sys:output-object object stream)) (write-char #\space stream) object) (defun prin1 (object &optional (stream *standard-output*)) (let ((*print-escape* t)) (sys:output-object object (sys:out-synonym-of stream))) object) (defun princ (object &optional (stream *standard-output*)) (let ((*print-escape* nil) (*print-readably* nil)) (sys:output-object object (sys:out-synonym-of stream))) object) (defun pprint (object &optional (stream *standard-output*)) (setq stream (sys:out-synonym-of stream)) (terpri stream) (let ((*print-escape* T) (*print-pretty* T)) (sys:output-object object stream)) (values)) (defun write-to-string (object &key ((:escape *print-escape*) *print-escape*) ((:radix *print-radix*) *print-radix*) ((:base *print-base*) *print-base*) ((:circle *print-circle*) *print-circle*) ((:pretty *print-pretty*) *print-pretty*) ((:level *print-level*) *print-level*) ((:length *print-length*) *print-length*) ((:case *print-case*) *print-case*) ((:array *print-array*) *print-array*) ((:gensym *print-gensym*) *print-gensym*) ((:readably *print-readably*) *print-readably*) ((:right-margin *print-right-margin*) *print-right-margin*) ((:miser-width *print-miser-width*) *print-miser-width*) ((:lines *print-lines*) *print-lines*) ((:pprint-dispatch *print-pprint-dispatch*) *print-pprint-dispatch*)) (let ((stream (make-string-output-stream))) (sys:output-object object stream) (get-output-stream-string stream))) (defun prin1-to-string (object) (with-output-to-string (stream) (let ((*print-escape* t)) (sys:output-object object stream)))) (defun princ-to-string (object) (with-output-to-string (stream) (let ((*print-escape* nil) (*print-readably* nil)) (sys:output-object object stream)))) (defun write-char (char &optional (stream *standard-output*)) (setf stream (sys:out-synonym-of stream)) (if (xp-structure-p stream) (write-char+ char stream) (sys:%stream-write-char char stream)) char) (defun write-string (string &optional (stream *standard-output*) &key (start 0) end) (setf stream (sys:out-synonym-of stream)) (setf end (or end (length string))) ;; default value for end is NIL (if (xp-structure-p stream) (write-string+ string stream start end) (progn (unless start (setf start 0)) (if end (setf end (min end (length string))) (setf end (length string))) (sys::%write-string string stream start end))) string) (defun write-line (string &optional (stream *standard-output*) &key (start 0) end) (setf stream (sys:out-synonym-of stream)) (setf end (or end (length string))) (cond ((xp-structure-p stream) (write-string+ string stream start end) (pprint-newline+ :unconditional stream)) (t (sys::%write-string string stream start end) (sys::%terpri stream))) string) (defun terpri (&optional (stream *standard-output*)) (setf stream (sys:out-synonym-of stream)) (if (xp-structure-p stream) (pprint-newline+ :unconditional stream) (sys:%stream-terpri stream)) nil) ;This has to violate the XP data abstraction and fool with internal ;stuff, in order to find out the right info to return as the result. (defun fresh-line (&optional (stream *standard-output*)) (setf stream (sys:out-synonym-of stream)) (cond ((xp-structure-p stream) (attempt-to-output stream t t) ;ok because we want newline (when (not (zerop (LP<-BP stream))) (pprint-newline+ :fresh stream) t)) (t (sys::%fresh-line stream)))) ;Each of these causes the stream to be pessimistic and insert ;newlines wherever it might have to, when forcing the partial output ;out. This is so that things will be in a consistent state if ;output continues to the stream later. (defun finish-output (&optional (stream *standard-output*)) (setf stream (sys:out-synonym-of stream)) (when (xp-structure-p stream) (attempt-to-output stream T T) (setf stream (base-stream stream))) (sys::%finish-output stream) nil) (defun force-output (&optional (stream *standard-output*)) (setf stream (sys:out-synonym-of stream)) (when (xp-structure-p stream) (attempt-to-output stream T T) (setf stream (base-stream stream))) (sys::%force-output stream) nil) (defun clear-output (&optional (stream *standard-output*)) (setf stream (sys:out-synonym-of stream)) (when (xp-structure-p stream) (let ((*locating-circularities* 0)) ;hack to prevent visible output (attempt-to-output stream T T) (setf stream (base-stream stream)))) (sys::%clear-output stream) nil) ;The internal functions in this file, and the (formatter "...") expansions ;use the '+' forms of these functions directly (which is faster) because, ;they do not need error checking or fancy stream coercion. The '++' forms ;additionally assume the thing being output does not contain a newline. (defmacro pprint-logical-block ((stream-symbol object &key (prefix "" prefix-p) (per-line-prefix "" per-line-prefix-p) (suffix "")) &body body) (cond ((eq stream-symbol nil) (setf stream-symbol '*standard-output*)) ((eq stream-symbol t) (setf stream-symbol '*terminal-io*))) (unless (symbolp stream-symbol) (warn "STREAM-SYMBOL arg ~S to PPRINT-LOGICAL-BLOCK is not a bindable symbol." stream-symbol) (setf stream-symbol '*standard-output*)) (when (and prefix-p per-line-prefix-p) (error "Cannot specify values for both PREFIX and PER-LINE-PREFIX.")) `(let ((+l ,object)) (maybe-initiate-xp-printing +l #'(lambda (,stream-symbol) (let ((+l +l) (+p ,(cond (prefix-p prefix) (per-line-prefix-p per-line-prefix) (t ""))) (+s ,suffix)) (pprint-logical-block+ (,stream-symbol +l +p +s ,per-line-prefix-p t nil) ,@ body nil))) (sys:out-synonym-of ,stream-symbol)))) ;Assumes var and args must be variables. Other arguments must be literals or variables. (defmacro pprint-logical-block+ ((var args prefix suffix per-line? circle-check? atsign?) &body body) ;; (when (and circle-check? atsign?) ;; (setf circle-check? 'not-first-p)) (declare (ignore atsign?)) `(let ((*current-level* (1+ *current-level*)) (sys:*current-print-length* -1) ;; ,@(if (and circle-check? atsign?) ;; `((not-first-p (plusp sys:*current-print-length*)))) ) (unless (check-block-abbreviation ,var ,args ,circle-check?) (block logical-block (start-block ,var ,prefix ,per-line? ,suffix) (unwind-protect (macrolet ((pprint-pop () `(pprint-pop+ ,',args ,',var)) (pprint-exit-if-list-exhausted () `(if (null ,',args) (return-from logical-block nil)))) ,@ body) (end-block ,var ,suffix)))))) ;; "If stream is a pretty printing stream and the value of *PRINT-PRETTY* is ;; true, a line break is inserted in the output when the appropriate condition ;; below is satisfied; otherwise, PPRINT-NEWLINE has no effect." (defun pprint-newline (kind &optional (stream *standard-output*)) (sys:require-type kind '(MEMBER :LINEAR :MISER :FILL :MANDATORY)) (setq stream (sys:out-synonym-of stream)) (when (not (member kind '(:linear :miser :fill :mandatory))) (error 'simple-type-error :format-control "Invalid KIND argument ~A to PPRINT-NEWLINE." :format-arguments (list kind))) (when (and (xp-structure-p stream) *print-pretty*) (pprint-newline+ kind stream)) nil) ;; "If stream is a pretty printing stream and the value of *PRINT-PRETTY* is ;; true, PPRINT-INDENT sets the indentation in the innermost dynamically ;; enclosing logical block; otherwise, PPRINT-INDENT has no effect." (defun pprint-indent (relative-to n &optional (stream *standard-output*)) (setq stream (sys:out-synonym-of stream)) (when (not (member relative-to '(:block :current))) (error "Invalid KIND argument ~A to PPRINT-INDENT" relative-to)) (when (and (xp-structure-p stream) *print-pretty*) (pprint-indent+ relative-to (truncate n) stream)) nil) (defun pprint-tab (kind colnum colinc &optional (stream *standard-output*)) (setq stream (sys:out-synonym-of stream)) (when (not (member kind '(:line :section :line-relative :section-relative))) (error "Invalid KIND argument ~A to PPRINT-TAB" kind)) (when (and (xp-structure-p stream) *print-pretty*) (pprint-tab+ kind colnum colinc stream)) nil) (eval-when (:compile-toplevel :load-toplevel :execute) (defmacro pprint-pop+ (args xp) `(if (pprint-pop-check+ ,args ,xp) (return-from logical-block nil) (pop ,args))) (defun pprint-pop-check+ (args xp) (incf sys:*current-print-length*) (cond ((not (listp args)) ;must be first so supersedes length abbrev (write-string++ ". " xp 0 2) (sys:output-object args xp) t) ((and *print-length* ;must supersede circle check (not *print-readably*) (not (< sys:*current-print-length* *print-length*))) (write-string++ "..." xp 0 3) ;; (setq *abbreviation-happened* T) t) ;; ((and *circularity-hash-table* (not (zerop sys:*current-print-length*))) ;; (case (circularity-process xp args T) ;; (:first ;; note must inhibit rechecking of circularity for args. ;; (write+ (cons (car args) (cdr args)) xp) T) ;; (:subsequent t) ;; (t nil))) ((or (not *print-circle*) (sys::uniquely-identified-by-print-p args)) nil) ((and (plusp sys:*current-print-length*) (sys::check-for-circularity args)) (write-string++ ". " xp 0 2) (sys:output-object args xp) t) )) (defun check-block-abbreviation (xp args circle-check?) (declare (ignore circle-check?)) (cond ((not (listp args)) (sys:output-object args xp) T) ((and *print-level* (not *print-readably*) (> *current-level* *print-level*)) (write-char++ #\# xp) (setf *abbreviation-happened* t) t) ;; ((and *circularity-hash-table* ;; circle-check? ;; (eq (circularity-process xp args nil) :subsequent)) T) (t nil))) ) ;; EVAL-WHEN ; ---- PRETTY PRINTING FORMATS ---- (defun pretty-array (xp array) (cond ((vectorp array) (pretty-vector xp array)) ((zerop (array-rank array)) (when *print-readably* (unless (eq (array-element-type array) t) (error 'print-not-readable :object array))) (write-string++ "#0A" xp 0 3) (sys:output-object (aref array) xp)) (t (pretty-non-vector xp array)))) (defun pretty-vector (xp v) (pprint-logical-block (xp nil :prefix "#(" :suffix ")") (let ((end (length v)) (i 0)) (when (plusp end) (loop (pprint-pop) (sys:output-object (aref v i) xp) (when (= (incf i) end) (return nil)) (write-char++ #\space xp) (pprint-newline+ :fill xp)))))) (declaim (special *prefix*)) (defun pretty-non-vector (xp array) (when (and *print-readably* (not (array-readably-printable-p array))) (error 'print-not-readable :object array)) (let* ((bottom (1- (array-rank array))) (indices (make-list (1+ bottom) :initial-element 0)) (dims (array-dimensions array)) (*prefix* (cl:format nil "#~DA(" (1+ bottom)))) (labels ((pretty-slice (slice) (pprint-logical-block (xp nil :prefix *prefix* :suffix ")") (let ((end (nth slice dims)) (spot (nthcdr slice indices)) (i 0) (*prefix* "(")) (when (plusp end) (loop (pprint-pop) (setf (car spot) i) (if (= slice bottom) (sys:output-object (apply #'aref array indices) xp) (pretty-slice (1+ slice))) (if (= (incf i) end) (return nil)) (write-char++ #\space xp) (pprint-newline+ (if (= slice bottom) :fill :linear) xp))))))) (pretty-slice 0)))) (defun array-readably-printable-p (array) (and (eq (array-element-type array) t) (let ((zero (position 0 (array-dimensions array))) (number (position 0 (array-dimensions array) :test (complement #'eql) :from-end t))) (or (null zero) (null number) (> zero number))))) ;Must use pprint-logical-block (no +) in the following three, because they are ;exported functions. (defun pprint-linear (s list &optional (colon? T) atsign?) (declare (ignore atsign?)) (pprint-logical-block (s list :prefix (if colon? "(" "") :suffix (if colon? ")" "")) (pprint-exit-if-list-exhausted) (loop (sys:output-object (pprint-pop) s) (pprint-exit-if-list-exhausted) (write-char++ #\space s) (pprint-newline+ :linear s)))) (defun pprint-fill (stream object &optional (colon-p t) at-sign-p) (declare (ignore at-sign-p)) (pprint-logical-block (stream object :prefix (if colon-p "(" "") :suffix (if colon-p ")" "")) (pprint-exit-if-list-exhausted) (loop (sys:output-object (pprint-pop) stream) (pprint-exit-if-list-exhausted) (write-char++ #\space stream) (pprint-newline+ :fill stream)))) (defun pprint-tabular (stream list &optional (colon-p T) at-sign-p (tabsize nil)) (declare (ignore at-sign-p)) (when (null tabsize) (setq tabsize 16)) (pprint-logical-block (stream list :prefix (if colon-p "(" "") :suffix (if colon-p ")" "")) (pprint-exit-if-list-exhausted) (loop (sys:output-object (pprint-pop) stream) (pprint-exit-if-list-exhausted) (write-char++ #\space stream) (pprint-tab+ :section-relative 0 tabsize stream) (pprint-newline+ :fill stream)))) (defun fn-call (xp list) (funcall (formatter "~:<~W~^ ~:I~@_~@{~W~^ ~_~}~:>") xp list)) ;Although idiosyncratic, I have found this very useful to avoid large ;indentations when printing out code. (defun alternative-fn-call (xp list) (if (> (length (symbol-name (car list))) 12) (funcall (formatter "~:<~1I~@{~W~^ ~_~}~:>") xp list) (funcall (formatter "~:<~W~^ ~:I~@_~@{~W~^ ~_~}~:>") xp list))) (defun bind-list (xp list &rest args) (declare (ignore args)) (if (do ((i 50 (1- i)) (ls list (cdr ls))) ((null ls) t) (when (or (not (consp ls)) (not (symbolp (car ls))) (minusp i)) (return nil))) (pprint-fill xp list) (funcall (formatter "~:<~@{~:/xp:pprint-fill/~^ ~_~}~:>") xp list))) (defun block-like (xp list &rest args) (declare (ignore args)) (funcall (formatter "~:<~1I~^~W~^ ~@_~W~^~@{ ~_~W~^~}~:>") xp list)) (defun defun-like (xp list &rest args) (declare (ignore args)) (funcall (formatter "~:<~1I~W~^ ~@_~W~^ ~@_~:/xp:pprint-fill/~^~@{ ~_~W~^~}~:>") xp list)) (defun print-fancy-fn-call (xp list template) (let ((i 0) (in-first-section t)) (pprint-logical-block+ (xp list "(" ")" nil t nil) (sys:output-object (pprint-pop) xp) (pprint-indent+ :current 1 xp) (loop (pprint-exit-if-list-exhausted) (write-char++ #\space xp) (when (eq i (car template)) (pprint-indent+ :block (cadr template) xp) (setq template (cddr template)) (setq in-first-section nil)) (pprint-newline (cond ((and (zerop i) in-first-section) :miser) (in-first-section :fill) (T :linear)) xp) (sys:output-object (pprint-pop) xp) (incf i))))) ;This is an attempt to specify a correct format for every form in the CL book ;that does not just get printed out like an ordinary function call ;(i.e., most special forms and many macros). This of course does not ;cover anything new you define. (defun let-print (xp obj) (funcall (formatter "~:<~^~W~^ ~@_~:<~@{~:<~^~W~@{ ~_~W~}~:>~^ ~_~}~:>~1I~:@_~@{~W~^ ~_~}~:>") xp obj)) (defun cond-print (xp obj) (funcall (formatter "~:<~W~^ ~:I~@_~@{~:/xp:pprint-linear/~^ ~_~}~:>") xp obj)) (defun dmm-print (xp list) (print-fancy-fn-call xp list '(3 1))) (defun defsetf-print (xp list) (print-fancy-fn-call xp list '(3 1))) (defun do-print (xp obj) (funcall (formatter "~:<~W~^ ~:I~@_~/xp:bind-list/~^ ~_~:/xp:pprint-linear/ ~1I~^~@{ ~_~W~^~}~:>") xp obj)) (defun flet-print (xp obj) (funcall (formatter "~:<~1I~W~^ ~@_~:<~@{~/xp:block-like/~^ ~_~}~:>~^~@{ ~_~W~^~}~:>") xp obj)) (defun function-print (xp list) (if (and (consp (cdr list)) (null (cddr list))) (funcall (formatter "#'~W") xp (cadr list)) (fn-call xp list))) (defun mvb-print (xp list) (print-fancy-fn-call xp list '(1 3 2 1))) ;; Used by PROG-PRINT and TAGBODY-PRINT. (defun maybelab (xp item &rest args) (declare (ignore args) (special need-newline indentation)) (when need-newline (pprint-newline+ :mandatory xp)) (cond ((and item (symbolp item)) (write+ item xp) (setq need-newline nil)) (t (pprint-tab+ :section indentation 0 xp) (write+ item xp) (setq need-newline T)))) (defun prog-print (xp list) (let ((need-newline T) (indentation (1+ (length (symbol-name (car list)))))) (declare (special need-newline indentation)) (funcall (formatter "~:<~W~^ ~:/xp:pprint-fill/~^ ~@{~/xp:maybelab/~^ ~}~:>") xp list))) (defun tagbody-print (xp list) (let ((need-newline (and (consp (cdr list)) (symbolp (cadr list)) (cadr list))) (indentation (1+ (length (symbol-name (car list)))))) (declare (special need-newline indentation)) (funcall (formatter "~:<~W~^ ~@{~/xp:maybelab/~^ ~}~:>") xp list))) (defun setq-print (xp obj) (funcall (formatter "~:<~W~^ ~:I~@_~@{~W~^ ~:_~W~^ ~_~}~:>") xp obj)) (defun quote-print (xp list) (if (and (consp (cdr list)) (null (cddr list))) (funcall (formatter "'~W") xp (cadr list)) (pprint-fill xp list))) (defun up-print (xp list) (print-fancy-fn-call xp list '(0 3 1 1))) ;here is some simple stuff for printing LOOP ;The challange here is that we have to effectively parse the clauses of the ;loop in order to know how to print things. Also you want to do this in a ;purely incremental way so that all of the abbreviation things work, and ;you wont blow up on circular lists or the like. (More aesthic output could ;be produced by really parsing the clauses into nested lists before printing them.) ;The following program assumes the following simplified grammar of the loop ;clauses that explains how to print them. Note that it does not bare much ;resemblence to the right parsing grammar, however, it produces half decent ;output. The way to make the output better is to make the grammar more ;detailed. ; ;loop == (LOOP {clause}*) ;one clause on each line. ;clause == block | linear | cond | finally ;block == block-head {expr}* ;as many exprs as possible on each line. ;linear == linear-head {expr}* ;one expr on each line. ;finally == FINALLY [DO | DOING | RETURN] {expr}* ;one expr on each line. ;cond == cond-head [expr] ; clause ; {AND clause}* ;one AND on each line. ; [ELSE ; clause ; {AND clause}*] ;one AND on each line. ; [END] ;block-head == FOR | AS | WITH | AND ; | REPEAT | NAMED | WHILE | UNTIL | ALWAYS | NEVER | THEREIS | RETURN ; | COLLECT | COLLECTING | APPEND | APPENDING | NCONC | NCONCING | COUNT ; | COUNTING | SUM | SUMMING | MAXIMIZE | MAXIMIZING | MINIMIZE | MINIMIZING ;linear-head == DO | DOING | INITIALLY ;var-head == FOR | AS | WITH ;cond-head == IF | WHEN | UNLESS ;expr == ;Note all the string comparisons below are required to support some ;existing implementations of LOOP. (defun token-type (token &aux string) (cond ((not (symbolp token)) :expr) ((string= (setq string (string token)) "FINALLY") :finally) ((member string '("IF" "WHEN" "UNLESS") :test #'string=) :cond-head) ((member string '("DO" "DOING" "INITIALLY") :test #'string=) :linear-head) ((member string '("FOR" "AS" "WITH" "AND" "END" "ELSE" "REPEAT" "NAMED" "WHILE" "UNTIL" "ALWAYS" "NEVER" "THEREIS" "RETURN" "COLLECT" "COLLECTING" "APPEND" "APPENDING" "NCONC" "NCONCING" "COUNT" "COUNTING" "SUM" "SUMMING" "MAXIMIZE" "MAXIMIZING" "MINIMIZE" "MINIMIZING") :test #'string=) :block-head) (T :expr))) (defun pretty-loop (xp loop) (if (not (and (consp (cdr loop)) (symbolp (cadr loop)))) ; old-style loop (fn-call xp loop) (pprint-logical-block (xp loop :prefix "(" :suffix ")") (let (token type) (labels ((next-token () (pprint-exit-if-list-exhausted) (setq token (pprint-pop)) (setq type (token-type token))) (print-clause (xp) (case type (:linear-head (print-exprs xp nil :mandatory)) (:cond-head (print-cond xp)) (:finally (print-exprs xp T :mandatory)) (otherwise (print-exprs xp nil :fill)))) (print-exprs (xp skip-first-non-expr newline-type) (let ((first token)) (next-token) ;so always happens no matter what (pprint-logical-block (xp nil) (write first :stream xp) (when (and skip-first-non-expr (not (eq type :expr))) (write-char #\space xp) (write token :stream xp) (next-token)) (when (eq type :expr) (write-char #\space xp) (pprint-indent :current 0 xp) (loop (write token :stream xp) (next-token) (when (not (eq type :expr)) (return nil)) (write-char #\space xp) (pprint-newline newline-type xp)))))) (print-cond (xp) (let ((first token)) (next-token) ;so always happens no matter what (pprint-logical-block (xp nil) (write first :stream xp) (when (eq type :expr) (write-char #\space xp) (write token :stream xp) (next-token)) (write-char #\space xp) (pprint-indent :block 2 xp) (pprint-newline :linear xp) (print-clause xp) (print-and-list xp) (when (and (symbolp token) (string= (string token) "ELSE")) (print-else-or-end xp) (write-char #\space xp) (pprint-newline :linear xp) (print-clause xp) (print-and-list xp)) (when (and (symbolp token) (string= (string token) "END")) (print-else-or-end xp))))) (print-and-list (xp) (loop (when (not (and (symbolp token) (string= (string token) "AND"))) (return nil)) (write-char #\space xp) (pprint-newline :mandatory xp) (write token :stream xp) (next-token) (write-char #\space xp) (print-clause xp))) (print-else-or-end (xp) (write-char #\space xp) (pprint-indent :block 0 xp) (pprint-newline :linear xp) (write token :stream xp) (next-token) (pprint-indent :block 2 xp))) (pprint-exit-if-list-exhausted) (write (pprint-pop) :stream xp) (next-token) (write-char #\space xp) (pprint-indent :current 0 xp) (loop (print-clause xp) (write-char #\space xp) (pprint-newline :linear xp))))))) ;; (defun basic-write (object stream) ;; (cond ((xp-structure-p stream) ;; (write+ object stream)) ;; (*print-pretty* ;; (maybe-initiate-xp-printing #'(lambda (s o) (write+ o s)) ;; stream object)) ;; (t ;; (assert nil) ;; (syss:output-object object stream)))) (defun output-pretty-object (object stream) ;; (basic-write object stream)) (cond ((xp-structure-p stream) (write+ object stream)) (*print-pretty* (maybe-initiate-xp-printing object #'(lambda (s o) (write+ o s)) stream object)) (t (assert nil) (sys:output-object object stream)))) (provide "PPRINT") ;------------------------------------------------------------------------ ;Copyright Massachusetts Institute of Technology, Cambridge, Massachusetts. ;Permission to use, copy, modify, and distribute this software and its ;documentation for any purpose and without fee is hereby granted, ;provided that this copyright and permission notice appear in all ;copies and supporting documentation, and that the name of M.I.T. not ;be used in advertising or publicity pertaining to distribution of the ;software without specific, written prior permission. M.I.T. makes no ;representations about the suitability of this software for any ;purpose. It is provided "as is" without express or implied warranty. ; M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ; ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ; M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ; ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ; WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ; ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ; SOFTWARE. ;------------------------------------------------------------------------ abcl-src-1.9.0/src/org/armedbear/lisp/precompiler.lisp0100644 0000000 0000000 00000134474 14212332621 021430 0ustar000000000 0000000 ;;; precompiler.lisp ;;; ;;; Copyright (C) 2003-2008 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (export '(process-optimization-declarations inline-p notinline-p inline-expansion expand-inline *defined-functions* *undefined-functions* note-name-defined)) (declaim (ftype (function (t) t) process-optimization-declarations)) (defun process-optimization-declarations (forms) (dolist (form forms) (unless (and (consp form) (eq (%car form) 'DECLARE)) (return)) (dolist (decl (%cdr form)) (case (car decl) (OPTIMIZE (dolist (spec (%cdr decl)) (let ((val 3) (quality spec)) (when (consp spec) (setf quality (%car spec) val (cadr spec))) (when (and (fixnump val) (<= 0 val 3)) (case quality (speed (setf *speed* val)) (safety (setf *safety* val)) (debug (setf *debug* val)) (space (setf *space* val)) (compilation-speed) ;; Ignored. (t (compiler-warn "Ignoring unknown optimization quality ~S in ~S." quality decl))))))) ((INLINE NOTINLINE) (dolist (symbol (%cdr decl)) (push (cons symbol (%car decl)) *inline-declarations*))) (:explain (dolist (spec (%cdr decl)) (let ((val t) (quality spec)) (when (consp spec) (setf quality (%car spec)) (when (= (length spec) 2) (setf val (%cadr spec)))) (if val (pushnew quality *explain*) (setf *explain* (remove quality *explain*))))))))) t) (declaim (ftype (function (t) t) inline-p)) (defun inline-p (name) (declare (optimize speed)) (let ((entry (assoc name *inline-declarations* :test #'equal))) (if entry (eq (cdr entry) 'INLINE) (and (symbolp name) (eq (get name '%inline) 'INLINE))))) (declaim (ftype (function (t) t) notinline-p)) (defun notinline-p (name) (declare (optimize speed)) (let ((entry (assoc name *inline-declarations* :test #'equal))) (if entry (eq (cdr entry) 'NOTINLINE) (and (symbolp name) (eq (get name '%inline) 'NOTINLINE))))) (defun expand-inline (form expansion) ;; (format t "expand-inline form = ~S~%" form) ;; (format t "expand-inline expansion = ~S~%" expansion) (let* ((op (car form)) (proclaimed-ftype (proclaimed-ftype op)) (args (cdr form)) (vars (cadr expansion)) (varlist ()) new-form) ;; (format t "op = ~S proclaimed-ftype = ~S~%" op (proclaimed-ftype op)) (do ((vars vars (cdr vars)) (args args (cdr args))) ((null vars)) (push (list (car vars) (car args)) varlist)) (setf new-form (list* 'LET (nreverse varlist) (copy-tree (cddr expansion)))) (when proclaimed-ftype (let ((result-type (ftype-result-type proclaimed-ftype))) (when (and result-type (neq result-type t) (neq result-type '*)) (setf new-form (list 'TRULY-THE result-type new-form))))) ;; (format t "expand-inline new form = ~S~%" new-form) new-form)) (define-compiler-macro assoc (&whole form &rest args) (cond ((and (= (length args) 4) (eq (third args) :test) (or (equal (fourth args) '(quote eq)) (equal (fourth args) '(function eq)))) `(assq ,(first args) ,(second args))) ((= (length args) 2) `(assql ,(first args) ,(second args))) (t form))) (define-compiler-macro member (&whole form &rest args) (let ((arg1 (first args)) (arg2 (second args))) (case (length args) (2 `(memql ,arg1 ,arg2)) (4 (let ((arg3 (third args)) (arg4 (fourth args))) (cond ((and (eq arg3 :test) (or (equal arg4 '(quote eq)) (equal arg4 '(function eq)))) `(memq ,arg1 ,arg2)) ((and (eq arg3 :test) (or (equal arg4 '(quote eql)) (equal arg4 '(function eql)) (equal arg4 '(quote char=)) (equal arg4 '(function char=)))) `(memql ,arg1 ,arg2)) (t form)))) (t form)))) (define-compiler-macro search (&whole form &rest args) (if (= (length args) 2) `(simple-search ,@args) form)) (define-compiler-macro identity (&whole form &rest args) (if (= (length args) 1) `(progn ,(car args)) form)) (defun quoted-form-p (form) (and (consp form) (eq (%car form) 'QUOTE) (= (length form) 2))) (define-compiler-macro eql (&whole form &rest args) (let ((first (car args)) (second (cadr args))) (if (or (and (quoted-form-p first) (symbolp (cadr first))) (and (quoted-form-p second) (symbolp (cadr second)))) `(eq ,first ,second) form))) (define-compiler-macro not (&whole form arg) (if (atom arg) form (let ((op (case (car arg) (>= '<) (< '>=) (<= '>) (> '<=) (t nil)))) (if (and op (= (length arg) 3)) (cons op (cdr arg)) form)))) (defun predicate-for-type (type) (cdr (assq type '((ARRAY . arrayp) (ATOM . atom) (BIT-VECTOR . bit-vector-p) (CHARACTER . characterp) (COMPLEX . complexp) (CONS . consp) (FIXNUM . fixnump) (FLOAT . floatp) (FUNCTION . functionp) (HASH-TABLE . hash-table-p) (INTEGER . integerp) (LIST . listp) (NULL . null) (NUMBER . numberp) (NUMBER . numberp) (PACKAGE . packagep) (RATIONAL . rationalp) (REAL . realp) (SIMPLE-BIT-VECTOR . simple-bit-vector-p) (SIMPLE-STRING . simple-string-p) (SIMPLE-VECTOR . simple-vector-p) (STREAM . streamp) (STRING . stringp) (SYMBOL . symbolp))))) (define-compiler-macro typep (&whole form &rest args) (if (= (length args) 2) ; no environment arg (let* ((object (%car args)) (type-specifier (%cadr args)) (type (and (consp type-specifier) (eq (%car type-specifier) 'QUOTE) (%cadr type-specifier))) (predicate (and type (predicate-for-type type)))) (if predicate `(,predicate ,object) `(%typep ,@args))) form)) (define-compiler-macro subtypep (&whole form &rest args) (if (= (length args) 2) `(%subtypep ,@args) form)) (define-compiler-macro funcall (&whole form &environment env &rest args) (let ((callee (car args))) (if (and (>= *speed* *debug*) (consp callee) (eq (%car callee) 'function) (symbolp (cadr callee)) (not (special-operator-p (cadr callee))) (not (macro-function (cadr callee) env)) (memq (symbol-package (cadr callee)) (list (find-package "CL") (find-package "SYS")))) `(,(cadr callee) ,@(cdr args)) form))) (define-compiler-macro byte (size position) `(cons ,size ,position)) (define-compiler-macro byte-size (bytespec) `(car ,bytespec)) (define-compiler-macro byte-position (bytespec) `(cdr ,bytespec)) (define-source-transform concatenate (&whole form result-type &rest sequences) (if (equal result-type '(quote STRING)) `(sys::concatenate-to-string (list ,@sequences)) form)) (define-source-transform ldb (&whole form bytespec integer) (if (and (consp bytespec) (eq (%car bytespec) 'byte) (= (length bytespec) 3)) (let ((size (%cadr bytespec)) (position (%caddr bytespec))) `(%ldb ,size ,position ,integer)) form)) (define-source-transform find (&whole form item sequence &key from-end test test-not start end key) (cond ((and (>= (length form) 3) (null start) (null end)) (cond ((and (stringp sequence) (null from-end) (member test '(#'eql #'char=) :test #'equal) (null test-not) (null key)) `(string-find ,item ,sequence)) (t (let ((item-var (gensym)) (seq-var (gensym))) `(let ((,item-var ,item) (,seq-var ,sequence)) (if (listp ,seq-var) (list-find* ,item-var ,seq-var ,from-end ,test ,test-not 0 (length ,seq-var) ,key) (vector-find* ,item-var ,seq-var ,from-end ,test ,test-not 0 (length ,seq-var) ,key))))))) (t form))) (define-source-transform adjoin (&whole form &rest args) (if (= (length args) 2) `(adjoin-eql ,(first args) ,(second args)) form)) (define-source-transform format (&whole form &rest args) (if (stringp (second args)) `(format ,(pop args) (formatter ,(pop args)) ,@args) form)) (define-compiler-macro catch (&whole form tag &rest args) (declare (ignore tag)) (if (and (null (cdr args)) (constantp (car args))) (car args) form)) (define-compiler-macro string= (&whole form &rest args) (if (= (length args) 2) `(sys::%%string= ,@args) form)) (define-compiler-macro <= (&whole form &rest args) (cond ((and (= (length args) 3) (numberp (first args)) (numberp (third args)) (= (first args) (third args))) `(= ,(second args) ,(first args))) (t form))) (in-package "PRECOMPILER") (export '(precompile-form precompile)) ;; No source-transforms and inlining in precompile-function-call ;; No macro expansion in precompile-dolist and precompile-dotimes ;; No macro expansion in precompile-do/do* ;; No macro expansion in precompile-defun ;; Special precompilation in precompile-case and precompile-cond ;; Special precompilation in precompile-when and precompile-unless ;; No precompilation in precompile-nth-value ;; Special precompilation in precompile-return ;; ;; if *in-jvm-compile* is false (defvar *in-jvm-compile* nil) (defvar *precompile-env* nil) (declaim (inline expand-macro)) (defun expand-macro (form) (macroexpand-1 form *precompile-env*)) (declaim (ftype (function (t) t) precompile1)) (defun precompile1 (form) (cond ((symbolp form) (multiple-value-bind (expansion expanded) (expand-macro form) (if expanded (precompile1 expansion) form))) ((atom form) form) (t (let ((op (%car form)) handler) (when (symbolp op) (cond ((setf handler (get op 'precompile-handler)) (return-from precompile1 (funcall handler form))) ((macro-function op *precompile-env*) (return-from precompile1 (precompile1 (expand-macro form)))) ((special-operator-p op) (error "PRECOMPILE1: unsupported special operator ~S." op)))) (precompile-function-call form))))) (defun precompile-identity (form) (declare (optimize speed)) form) (declaim (ftype (function (t) cons) precompile-cons)) (defun precompile-cons (form) (cons (car form) (mapcar #'precompile1 (cdr form)))) (declaim (ftype (function (t t) t) precompile-function-call)) (defun precompile-function-call (form) (let ((op (car form))) (when (and (consp op) (eq (%car op) 'LAMBDA)) (return-from precompile-function-call (or (precompile-function-position-lambda op (cdr form)) (cons (precompile-lambda op) (mapcar #'precompile1 (cdr form)))))) (when (or (not *in-jvm-compile*) (notinline-p op)) (return-from precompile-function-call (precompile-cons form))) (when (source-transform op) (let ((new-form (expand-source-transform form))) (when (neq new-form form) (return-from precompile-function-call (precompile1 new-form))))) (when *enable-inline-expansion* (let ((expansion (inline-expansion op))) (when expansion (let ((explain *explain*)) (when (and explain (memq :calls explain)) (format t "; inlining call to ~S~%" op))) (return-from precompile-function-call (precompile1 (expand-inline form expansion)))))) (cons op (mapcar #'precompile1 (cdr form))))) (defun precompile-function-position-lambda (lambda args) (let* ((arglist (second lambda)) (body (cddr lambda)) (simple-arglist? (not (or (memq '&KEY arglist) (memq '&OPTIONAL arglist) (memq '&REST arglist))))) (or ;;give a chance for someone to transform single-form function bodies (and (= (length body) 1) (consp (car body)) (symbolp (caar body)) (get (caar body) 'sys::function-position-lambda-transform) (funcall (get (caar body) 'sys::function-position-lambda-transform) (caar body) (car body) (mapcar #'precompile1 args))) (and simple-arglist? (let ((arglist-length (if (memq '&aux arglist) (position '&aux arglist) (length arglist)))) (if (= (length args) arglist-length) ;; simplest case - we have a simple arglist with as many ;; arguments as call args. Transform to let. (return-from precompile-function-position-lambda `(let* ,(append (loop for arg-name in arglist for arg in (mapcar #'precompile1 args) until (eq arg-name '&aux) collect (list arg-name arg)) (subseq arglist (1+ arglist-length))) ,@body)) (error "Argument mismatch for lambda in function position: ~a applied to ~a" `(lambda ,arglist body) args))))))) (defmacro define-function-position-lambda-transform (body-function-name (arglist form args) &body body) `(put ',body-function-name 'sys::function-position-lambda-transform #'(lambda(,arglist ,form ,args) ,@body))) (defun precompile-locally (form) (let ((*inline-declarations* *inline-declarations*)) (process-optimization-declarations (cdr form)) (cons 'LOCALLY (mapcar #'precompile1 (cdr form))))) (defun precompile-block (form) (let ((args (cdr form))) (if (null (cdr args)) nil (list* 'BLOCK (car args) (mapcar #'precompile1 (cdr args)))))) (defun precompile-dolist (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) (cons 'DOLIST (cons (mapcar #'precompile1 (cadr form)) (mapcar #'precompile1 (cddr form)))))) (defun precompile-dotimes (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) (cons 'DOTIMES (cons (mapcar #'precompile1 (cadr form)) (mapcar #'precompile1 (cddr form)))))) (defun precompile-do/do*-vars (varlist) (let ((result nil)) (dolist (varspec varlist) (if (atom varspec) (push varspec result) (case (length varspec) (1 (push (%car varspec) result)) (2 (let* ((var (%car varspec)) (init-form (%cadr varspec))) (unless (symbolp var) (error 'type-error)) (push (list var (precompile1 init-form)) result))) (3 (let* ((var (%car varspec)) (init-form (%cadr varspec)) (step-form (%caddr varspec))) (unless (symbolp var) (error 'type-error)) (push (list var (precompile1 init-form) (precompile1 step-form)) result)))))) (nreverse result))) (defun precompile-do/do*-end-form (end-form) (let ((end-test-form (car end-form)) (result-forms (cdr end-form))) (list* (precompile1 end-test-form) (mapcar #'precompile1 result-forms)))) (defun precompile-do/do* (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) (list* (car form) (precompile-do/do*-vars (cadr form)) (precompile-do/do*-end-form (caddr form)) (mapcar #'precompile1 (cdddr form))))) (defun precompile-do-symbols (form) (list* (car form) (cadr form) (mapcar #'precompile1 (cddr form)))) (defun precompile-load-time-value (form) form) (defun precompile-progn (form) (let ((body (cdr form))) (if (eql (length body) 1) (let ((res (precompile1 (%car body)))) ;; If the result turns out to be a bare symbol, leave it wrapped ;; with PROGN so it won't be mistaken for a tag in an enclosing ;; TAGBODY. (if (symbolp res) (list 'progn res) res)) (cons 'PROGN (mapcar #'precompile1 body))))) (defun precompile-threads-synchronized-on (form) (cons 'threads:synchronized-on (mapcar #'precompile1 (cdr form)))) (defun precompile-progv (form) (if (< (length form) 3) (error "Not enough arguments for ~S." 'progv) (list* 'PROGV (mapcar #'precompile1 (%cdr form))))) (defun precompile-setf (form) (let ((place (second form))) (cond ((and (consp place) (eq (%car place) 'VALUES)) (setf form (list* 'SETF (list* 'VALUES (mapcar #'precompile1 (%cdr place))) (cddr form))) (precompile1 (expand-macro form))) ((symbolp place) (multiple-value-bind (expansion expanded) ;; Expand once in case the form expands ;; into something that needs special ;; SETF treatment (macroexpand-1 place *precompile-env*) (if expanded (precompile1 (list* 'SETF expansion (cddr form))) (precompile1 (expand-macro form))))) (t (precompile1 (expand-macro form)))))) (defun precompile-setq (form) (let* ((args (cdr form)) (len (length args))) (when (oddp len) (error 'compiler-error :format-control "Odd number of arguments to SETQ.")) (if (= len 2) (let* ((sym (%car args)) (val (%cadr args))) (multiple-value-bind (expansion expanded) ;; Expand once in case the form expands ;; into something that needs special ;; SETF treatment (macroexpand-1 sym *precompile-env*) (if expanded (precompile1 (list 'SETF expansion val)) (list 'SETQ sym (precompile1 val))))) (let ((result ())) (loop (when (null args) (return)) (push (precompile-setq (list 'SETQ (car args) (cadr args))) result) (setq args (cddr args))) (setq result (nreverse result)) (push 'PROGN result) result)))) (defun precompile-psetf (form) (setf form (list* 'PSETF (mapcar #'precompile1 (cdr form)))) (precompile1 (expand-macro form))) (defun precompile-psetq (form) ;; Make sure all the vars are symbols. (do* ((rest (cdr form) (cddr rest)) (var (car rest))) ((null rest)) (unless (symbolp var) (error 'simple-error :format-control "~S is not a symbol." :format-arguments (list var)))) ;; Delegate to PRECOMPILE-PSETF so symbol macros are handled correctly. (precompile-psetf form)) (defun precompile-lambda-list (form) (let (new aux-tail) (dolist (arg form (nreverse new)) (if (or (atom arg) (> 2 (length arg))) (progn (when (eq arg '&aux) (setf aux-tail t)) (push arg new)) ;; must be a cons of more than 1 cell (let ((new-arg (copy-list arg))) (unless (<= 1 (length arg) (if aux-tail 2 3)) ;; the aux-vars have a maximum length of 2 conses ;; optional and key vars may have 3 (error 'program-error :format-control "The ~A binding specification ~S is invalid." :format-arguments (list (if aux-tail "&AUX" "&OPTIONAL/&KEY") arg))) (setf (second new-arg) (precompile1 (second arg))) (push new-arg new)))))) (defun extract-lambda-vars (lambda-list) (let ((state :required) vars) (dolist (var/key lambda-list vars) (cond ((eq '&aux var/key) (setf state :aux)) ((eq '&key var/key) (setf state :key)) ((eq '&optional var/key) (setf state :optional)) ((eq '&rest var/key) (setf state :rest)) ((symbolp var/key) (unless (eq var/key '&allow-other-keys) (push var/key vars))) ((and (consp var/key) (member state '(:optional :key))) (setf var/key (car var/key)) (when (and (consp var/key) (eq state :key)) (setf var/key (second var/key))) (if (symbolp var/key) (push var/key vars) (error 'program-error :format-control "Unexpected ~A variable specifier ~A." :format-arguments (list state var/key)))) ((and (consp var/key) (eq state :aux)) (if (symbolp (car var/key)) (push (car var/key) vars) (error 'program-error :format-control "Unexpected &AUX format for ~A." :format-arguments (list var/key)))) (t (error 'program-error :format-control "Unexpected lambda-list format: ~A." :format-arguments (list lambda-list))))))) (defun precompile-lambda (form) (let ((body (cddr form)) (precompiled-lambda-list (precompile-lambda-list (cadr form))) (*inline-declarations* *inline-declarations*) (*precompile-env* (make-environment *precompile-env*))) (process-optimization-declarations body) (dolist (var (extract-lambda-vars precompiled-lambda-list)) (environment-add-symbol-binding *precompile-env* var nil)) (list* 'LAMBDA precompiled-lambda-list (mapcar #'precompile1 body)))) (defun precompile-named-lambda (form) (let ((lambda-form (list* 'LAMBDA (caddr form) (cdddr form)))) (let ((body (cddr lambda-form)) (precompiled-lambda-list (precompile-lambda-list (cadr lambda-form))) (*inline-declarations* *inline-declarations*) (*precompile-env* (make-environment *precompile-env*))) (process-optimization-declarations body) (dolist (var (extract-lambda-vars precompiled-lambda-list)) (environment-add-symbol-binding *precompile-env* var nil)) (list* 'NAMED-LAMBDA (cadr form) precompiled-lambda-list (mapcar #'precompile1 body))))) (defun precompile-defun (form) (if *in-jvm-compile* (precompile1 (expand-macro form)) form)) (defun precompile-macrolet (form) (let ((*precompile-env* (make-environment *precompile-env*))) (dolist (definition (cadr form)) (environment-add-macro-definition *precompile-env* (car definition) (make-macro (car definition) (make-closure (make-macro-expander definition) NIL)))) (multiple-value-bind (body decls) (parse-body (cddr form) nil) `(locally ,@decls ,@(mapcar #'precompile1 body))))) (defun precompile-symbol-macrolet (form) (let ((*precompile-env* (make-environment *precompile-env*)) (defs (cadr form))) (dolist (def defs) (let ((sym (car def)) (expansion (cadr def))) (when (special-variable-p sym) (error 'program-error :format-control "Attempt to bind the special variable ~S with SYMBOL-MACROLET." :format-arguments (list sym))) (environment-add-symbol-binding *precompile-env* sym (sys::make-symbol-macro expansion)))) (multiple-value-bind (body decls) (parse-body (cddr form) nil) (when decls (let ((specials ())) (dolist (decl decls) (when (eq (car decl) 'DECLARE) (dolist (declspec (cdr decl)) (when (eq (car declspec) 'SPECIAL) (setf specials (append specials (cdr declspec))))))) (when specials (let ((syms (mapcar #'car (cadr form)))) (dolist (special specials) (when (memq special syms) (error 'program-error :format-control "~S is a symbol-macro and may not be declared special." :format-arguments (list special)))))))) `(locally ,@decls ,@(mapcar #'precompile1 body))))) (defun precompile-the (form) (list 'THE (second form) (precompile1 (third form)))) (defun precompile-truly-the (form) (list 'TRULY-THE (second form) (precompile1 (third form)))) (defun precompile-let/let*-vars (vars) (let ((result nil)) (dolist (var vars) (cond ((consp var) (unless (<= 1 (length var) 2) (error 'program-error :format-control "The LET/LET* binding specification ~S is invalid." :format-arguments (list var))) (let ((v (%car var)) (expr (cadr var))) (unless (symbolp v) (error 'simple-type-error :format-control "The variable ~S is not a symbol." :format-arguments (list v))) (push (list v (precompile1 expr)) result) (environment-add-symbol-binding *precompile-env* v nil))) ;; any value will do: we just need to shadow any symbol macros (t (push var result) (environment-add-symbol-binding *precompile-env* var nil)))) (nreverse result))) (defun precompile-let (form) (let ((*precompile-env* (make-environment *precompile-env*))) (list* 'LET (precompile-let/let*-vars (cadr form)) (mapcar #'precompile1 (cddr form))))) ;; (LET* ((X 1)) (LET* ((Y 2)) (LET* ((Z 3)) (+ X Y Z)))) => ;; (LET* ((X 1) (Y 2) (Z 3)) (+ X Y Z)) (defun maybe-fold-let* (form) (if (and (= (length form) 3) (consp (%caddr form)) (eq (%car (%caddr form)) 'LET*)) (let ((third (maybe-fold-let* (%caddr form)))) (list* 'LET* (append (%cadr form) (cadr third)) (cddr third))) form)) (defun precompile-let* (form) (setf form (maybe-fold-let* form)) (let ((*precompile-env* (make-environment *precompile-env*))) (list* 'LET* (precompile-let/let*-vars (cadr form)) (mapcar #'precompile1 (cddr form))))) (defun precompile-case (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) (let* ((keyform (cadr form)) (clauses (cddr form)) (result (list (precompile1 keyform)))) (dolist (clause clauses) (push (precompile-case-clause clause) result)) (cons (car form) (nreverse result))))) (defun precompile-case-clause (clause) (let ((keys (car clause)) (forms (cdr clause))) (cons keys (mapcar #'precompile1 forms)))) (defun precompile-cond (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) (let ((clauses (cdr form)) (result nil)) (dolist (clause clauses) (push (precompile-cond-clause clause) result)) (cons 'COND (nreverse result))))) (defun precompile-cond-clause (clause) (let ((test (car clause)) (forms (cdr clause))) (cons (precompile1 test) (mapcar #'precompile1 forms)))) (defun precompile-local-function-def (def) (let ((name (car def)) (body (cddr def))) ;; Macro names are shadowed by local functions. (environment-add-function-definition *precompile-env* name body) (cdr (precompile-named-lambda (list* 'NAMED-LAMBDA def))))) (defun precompile-local-functions (defs) (let ((result nil)) (dolist (def defs (nreverse result)) (push (precompile-local-function-def def) result)))) (defun find-use (name expression) (cond ((atom expression) nil) ((eq (%car expression) name) t) ((consp name) t) ;; FIXME Recognize use of SETF functions! (t (or (find-use name (%car expression)) (find-use name (%cdr expression)))))) (defun precompile-flet/labels (form) (let* ((*precompile-env* (make-environment *precompile-env*)) (operator (car form)) (locals (cadr form)) precompiled-locals applicable-locals body) (when (eq operator 'FLET) ;; FLET functions *don't* shadow within their own FLET form (setf precompiled-locals (precompile-local-functions locals)) (setf applicable-locals precompiled-locals)) ;; augment the environment with the newly-defined local functions ;; to shadow preexisting macro definitions with the same names (dolist (local locals) ;; we can use the non-precompiled locals, because the function body isn't used (environment-add-function-definition *precompile-env* (car local) (cddr local))) (when (eq operator 'LABELS) ;; LABELS functions *do* shadow within their own LABELS form (setf precompiled-locals (precompile-local-functions locals)) (setf applicable-locals precompiled-locals)) ;; then precompile (thus macro-expand) the body before inspecting it ;; for the use of our locals and eliminating dead code (setq body (mapcar #'precompile1 (cddr form))) (dolist (local precompiled-locals) (let* ((name (car local)) (used-p (find-use name body))) (unless used-p (when (eq operator 'LABELS) (dolist (local precompiled-locals) (when (neq name (car local)) (when (find-use name (cddr local)) (setf used-p t) (return)) ;; Scope of defined function names includes ;; &OPTIONAL, &KEY and &AUX parameters ;; (LABELS.7B, LABELS.7C and LABELS.7D). (let ((vars (or (cdr (memq '&optional (cadr local))) (cdr (memq '&key (cadr local))) (cdr (memq '&aux (cadr local)))))) (when (and vars (find-use name vars)) (setf used-p t) (return))) )))) (unless used-p (compiler-style-warn "; Note: deleting unused local function ~A ~S~%" operator name) (setf applicable-locals (remove local applicable-locals))))) (if applicable-locals (list* operator applicable-locals body) (list* 'LOCALLY body)))) (defun precompile-function (form) (if (and (consp (cadr form)) (eq (caadr form) 'LAMBDA)) (list 'FUNCTION (precompile-lambda (%cadr form))) form)) (defun precompile-if (form) (let ((args (cdr form))) (case (length args) (2 (let ((test (precompile1 (%car args)))) (cond ((null test) nil) (;;(constantp test) (eq test t) (precompile1 (%cadr args))) (t (list 'IF test (precompile1 (%cadr args))))))) (3 (let ((test (precompile1 (%car args)))) (cond ((null test) (precompile1 (%caddr args))) (;;(constantp test) (eq test t) (precompile1 (%cadr args))) (t (list 'IF test (precompile1 (%cadr args)) (precompile1 (%caddr args))))))) (t (error "wrong number of arguments for IF"))))) (defun precompile-when (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) (precompile-cons form))) (defun precompile-unless (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) (precompile-cons form))) ;; MULTIPLE-VALUE-BIND is handled explicitly by the JVM compiler. (defun precompile-multiple-value-bind (form) (let ((vars (cadr form)) (values-form (caddr form)) (body (cdddr form)) (*precompile-env* (make-environment *precompile-env*))) (dolist (var vars) (environment-add-symbol-binding *precompile-env* var nil)) (list* 'MULTIPLE-VALUE-BIND vars (precompile1 values-form) (mapcar #'precompile1 body)))) ;; MULTIPLE-VALUE-LIST is handled explicitly by the JVM compiler. (defun precompile-multiple-value-list (form) (list 'MULTIPLE-VALUE-LIST (precompile1 (cadr form)))) (defun precompile-nth-value (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) form)) (defun precompile-return (form) (if *in-jvm-compile* (precompile1 (macroexpand form *precompile-env*)) (list 'RETURN (precompile1 (cadr form))))) (defun precompile-return-from (form) (list 'RETURN-FROM (cadr form) (precompile1 (caddr form)))) (defun precompile-tagbody (form) (do ((body (cdr form) (cdr body)) (result ())) ((null body) (cons 'TAGBODY (nreverse result))) (if (atom (car body)) (push (car body) result) (push (let* ((first-form (car body)) (expanded (precompile1 first-form))) (if (and (symbolp expanded) (neq expanded first-form)) ;; Workaround: ;; Since our expansion/compilation order ;; is out of sync with the definition of ;; TAGBODY (which requires the compiler ;; to look for tags before expanding), ;; we need to disguise anything which might ;; look like a tag. We do this by wrapping ;; it in a PROGN form. (list 'PROGN expanded) expanded)) result)))) (defun precompile-eval-when (form) (list* 'EVAL-WHEN (cadr form) (mapcar #'precompile1 (cddr form)))) (defun precompile-unwind-protect (form) (list* 'UNWIND-PROTECT (precompile1 (cadr form)) (mapcar #'precompile1 (cddr form)))) (declaim (ftype (function (t t) t) precompile-form)) (defun precompile-form (form in-jvm-compile &optional precompile-env) (let ((*in-jvm-compile* in-jvm-compile) (*inline-declarations* *inline-declarations*) (pre::*precompile-env* precompile-env)) (precompile1 form))) (defun install-handler (symbol &optional handler) (declare (type symbol symbol)) (let ((handler (or handler (find-symbol (sys::%format nil "PRECOMPILE-~A" (symbol-name symbol)) 'precompiler)))) (unless (and handler (fboundp handler)) (error "No handler for ~S." (let ((*package* (find-package :keyword))) (format nil "~S" symbol)))) (setf (get symbol 'precompile-handler) handler))) (defun install-handlers () (mapcar #'install-handler '(BLOCK CASE COND DOLIST DOTIMES EVAL-WHEN FUNCTION IF LAMBDA MACROLET MULTIPLE-VALUE-BIND MULTIPLE-VALUE-LIST NAMED-LAMBDA NTH-VALUE PROGN PROGV PSETF PSETQ RETURN RETURN-FROM SETF SETQ SYMBOL-MACROLET TAGBODY UNWIND-PROTECT UNLESS WHEN)) (dolist (pair '((ECASE precompile-case) (AND precompile-cons) (OR precompile-cons) (CATCH precompile-cons) (MULTIPLE-VALUE-CALL precompile-cons) (MULTIPLE-VALUE-PROG1 precompile-cons) (DO precompile-do/do*) (DO* precompile-do/do*) (LET precompile-let) (LET* precompile-let*) (LOCALLY precompile-locally) (FLET precompile-flet/labels) (LABELS precompile-flet/labels) (LOAD-TIME-VALUE precompile-load-time-value) (DECLARE precompile-identity) (DEFUN precompile-defun) (GO precompile-identity) (QUOTE precompile-identity) (THE precompile-the) (THROW precompile-cons) (TRULY-THE precompile-truly-the) (THREADS:SYNCHRONIZED-ON precompile-threads-synchronized-on) (JVM::WITH-INLINE-CODE precompile-identity))) (install-handler (first pair) (second pair)))) (install-handlers) (export '(precompile-form)) (in-package #:ext) (export 'macroexpand-all) (defun macroexpand-all (form &optional env) (precompiler:precompile-form form t env)) (in-package #:lisp) (export '(compiler-let)) (defmacro compiler-let (bindings &body forms &environment env) (let ((bindings (mapcar #'(lambda (binding) (if (atom binding) (list binding) binding)) bindings))) (progv (mapcar #'car bindings) (mapcar #'(lambda (binding) (eval (cadr binding))) bindings) (macroexpand-all `(progn ,@forms) env)))) (in-package #:system) (defun set-function-definition (name new old) (let ((*warn-on-redefinition* nil)) (sys::%set-lambda-name new name) (sys:set-call-count new (sys:call-count old)) (sys::%set-arglist new (sys::arglist old)) (when (macro-function name) (setf new (make-macro name new))) (if (typep old 'mop:funcallable-standard-object) (mop:set-funcallable-instance-function old new) (setf (fdefinition name) new)))) (defun precompile (name &optional definition) (unless definition (setq definition (or (and (symbolp name) (macro-function name)) (fdefinition name)))) (let ((expr definition) env result (pre::*precompile-env* nil)) (when (functionp definition) (multiple-value-bind (form closure-p) (function-lambda-expression definition) (unless form (return-from precompile (values nil t t))) (setq env closure-p) (setq expr form))) (unless (and (consp expr) (eq (car expr) 'lambda)) (format t "Unable to precompile ~S.~%" name) (return-from precompile (values nil t t))) (setf result (sys:make-closure (precompiler:precompile-form expr nil env) env)) (when (and name (functionp result)) (sys::set-function-definition name result definition)) (values (or name result) nil nil))) (defun precompile-package (pkg &key (verbose cl:*compile-verbose*)) (dolist (sym (package-symbols pkg)) (when (fboundp sym) (unless (special-operator-p sym) (let ((f (fdefinition sym))) (unless (compiled-function-p f) (when verbose (format t "~&; precompiler; Precompiling ~S~%" sym) (finish-output)) (precompile sym)))))) t) (defun %compile (name definition) (if (and name (fboundp name) (%typep (symbol-function name) 'generic-function)) (values name nil nil) (precompile name definition))) ;; ;; Redefine EVAL to precompile its argument. ;; (defun eval (form) ;; (%eval (precompile-form form nil))) ;; ;; Redefine DEFMACRO to precompile the expansion function on the fly. ;; (defmacro defmacro (name lambda-list &rest body) ;; (let* ((form (gensym "WHOLE-")) ;; (env (gensym "ENVIRONMENT-"))) ;; (multiple-value-bind (body decls) ;; (parse-defmacro lambda-list form body name 'defmacro :environment env) ;; (let ((expander `(lambda (,form ,env) ,@decls (block ,name ,body)))) ;; `(progn ;; (let ((macro (make-macro ',name ;; (or (precompile nil ,expander) ,expander)))) ;; ,@(if (special-operator-p name) ;; `((put ',name 'macroexpand-macro macro)) ;; `((fset ',name macro))) ;; (%set-arglist macro ',lambda-list) ;; ',name)))))) ;; Make an exception just this one time... (when (get 'defmacro 'macroexpand-macro) (fset 'defmacro (get 'defmacro 'macroexpand-macro)) (remprop 'defmacro 'macroexpand-macro)) (defvar *defined-functions*) (defvar *undefined-functions*) (defun note-name-defined (name) (when (boundp '*defined-functions*) (push name *defined-functions*)) (when (and (boundp '*undefined-functions*) (not (null *undefined-functions*))) (setf *undefined-functions* (remove name *undefined-functions*)))) ;; Redefine DEFUN to precompile the definition on the fly. (defmacro defun (name lambda-list &body body &environment env) (note-name-defined name) (multiple-value-bind (body decls doc) (parse-body body) (let* ((block-name (fdefinition-block-name name)) (lambda-expression `(named-lambda ,name ,lambda-list ,@decls ,@(when doc `(,doc)) (block ,block-name ,@body)))) (cond ((and (boundp 'jvm::*file-compilation*) ;; when JVM.lisp isn't loaded yet, this variable isn't bound ;; meaning that we're not trying to compile to a file: ;; Both COMPILE and COMPILE-FILE bind this variable. ;; This function is also triggered by MACROEXPAND, though. jvm::*file-compilation*) `(progn (fset ',name ,lambda-expression) ;; the below matter, for example when loading a ;; compiled defun that is inside some other form ;; (e.g. flet) (record-source-information-for-type ',(if (consp name) (second name) name) '(:function ,name)) (%set-arglist (fdefinition ',name) ',(third lambda-expression)) ,@(when doc `((%set-documentation ',name 'function ,doc))) ',name)) (t (when (and env (empty-environment-p env)) (setf env nil)) (when (null env) (setf lambda-expression (precompiler:precompile-form lambda-expression nil))) (let ((sym (if (consp name) (second name) name))) `(prog1 (%defun ',name ,lambda-expression) (record-source-information-for-type ',sym '(:function ,name)) (%set-arglist (fdefinition ',name) ',(third lambda-expression)) ;; don't do this. building abcl fails autoloading ;; stuff it shouldn't yet ;;(%set-arglist (symbol-function ',name) ,(format nil "~{~s~^ ;; ~}" (third lambda-expression))) ,@(when doc `((%set-documentation ',name 'function ,doc))) ))))))) (export '(precompile)) ;;(provide "PRECOMPILER") abcl-src-1.9.0/src/org/armedbear/lisp/print-object.lisp0100644 0000000 0000000 00000011631 14202767264 021512 0ustar000000000 0000000 ;;; print-object.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require 'clos) (when (autoloadp 'print-object) (fmakunbound 'print-object)) (defgeneric print-object (object stream)) (defmethod print-object ((object t) stream) (print-unreadable-object (object stream :type t :identity t) (write-string (%write-to-string object) stream))) (defmethod print-object ((object standard-object) stream) (write-string (%write-to-string object) stream)) (defmethod print-object ((object structure-object) stream) (write-string (%write-to-string object) stream)) (defmethod print-object ((class class) stream) (print-unreadable-object (class stream :identity t) ;; Avoid recursive errors for uninitialized class objects, e.g. when ;; validate-superclass fails (format stream "~S ~S" (class-name (class-of class)) (ignore-errors (class-name class)))) class) (defmethod print-object ((gf generic-function) stream) (print-unreadable-object (gf stream :identity t) (format stream "~S ~S" (class-name (class-of gf)) (ignore-errors (mop:generic-function-name gf)))) gf) (defmethod print-object ((method method) stream) (print-unreadable-object (method stream :identity t) (format stream "~S ~S~{ ~S~} ~S" (class-name (class-of method)) (mop:generic-function-name (mop:method-generic-function method)) (method-qualifiers method) (mapcar #'(lambda (c) (if (typep c 'mop:eql-specializer) `(eql ,(mop:eql-specializer-object c)) (class-name c))) (mop:method-specializers method)))) method) (defmethod print-object ((method-combination method-combination) stream) (print-unreadable-object (method-combination stream :identity t) (format stream "~A ~S" (class-name (class-of method-combination)) (ignore-errors (mop::method-combination-name method-combination)))) method-combination) (defmethod print-object ((restart restart) stream) (if *print-escape* (print-unreadable-object (restart stream :type t :identity t) (prin1 (restart-name restart) stream)) (restart-report restart stream))) (defmethod print-object ((c condition) stream) (if *print-escape* (call-next-method) (if (slot-boundp c 'format-control) (apply #'format stream (simple-condition-format-control c) (simple-condition-format-arguments c)) (call-next-method)))) (defmethod print-object ((c type-error) stream) (if *print-escape* (call-next-method) (if (slot-boundp c 'format-control) (apply 'format stream (simple-condition-format-control c) (simple-condition-format-arguments c)) (format stream "The value ~S is not of type ~S." (type-error-datum c) (type-error-expected-type c))))) (defmethod print-object ((x undefined-function) stream) (if *print-escape* (call-next-method) (format stream "The function ~S is undefined." (cell-error-name x)))) (defmethod print-object ((x unbound-variable) stream) (if *print-escape* (print-unreadable-object (x stream :identity t) (format stream "~S ~S" (type-of x) (cell-error-name x))) (format stream "The variable ~S is unbound." (cell-error-name x)))) (provide "PRINT-OBJECT") abcl-src-1.9.0/src/org/armedbear/lisp/print-unreadable-object.lisp0100644 0000000 0000000 00000004517 14223403213 023577 0ustar000000000 0000000 ;;; print-unreadable-object.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (defun %print-unreadable-object (object stream type identity body) (setf stream (out-synonym-of stream)) (when *print-readably* (error 'print-not-readable :object object)) (format stream "#<") (when type (format stream "~S" (type-of object)) (format stream " ")) (when body (funcall body)) (when identity (when (or body (not type)) (format stream " ")) (format stream "{~X}" (identity-hash-code object))) (format stream ">") nil) (defmacro print-unreadable-object ((object stream &key type identity) &body body) `(%print-unreadable-object ,object ,stream ,type ,identity ,(if body `(lambda () ,@body) nil))) abcl-src-1.9.0/src/org/armedbear/lisp/print.lisp0100644 0000000 0000000 00000030476 14223403213 020236 0ustar000000000 0000000 ;;; print.lisp ;;; ;;; Copyright (C) 2004-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) ;;; Can this object contain other objects? (defun compound-object-p (x) (or (consp x) (typep x 'structure-object) (typep x 'standard-object) (typep x '(array t *)))) ;;; Punt if INDEX is equal or larger then *PRINT-LENGTH* (and ;;; *PRINT-READABLY* is NIL) by outputting \"...\" and returning from ;;; the block named NIL. (defmacro punt-print-if-too-long (index stream) `(when (and (not *print-readably*) *print-length* (>= ,index *print-length*)) (write-string "..." ,stream) (return))) (defun output-integer (integer stream) ;; (%output-object integer stream)) (if (xp::xp-structure-p stream) (let ((s (sys::%write-to-string integer))) (xp::write-string++ s stream 0 (length s))) (%output-object integer stream))) (defun output-list (list stream) (cond ((and (null *print-readably*) *print-level* (>= *current-print-level* *print-level*)) (write-char #\# stream)) (t (let ((*current-print-level* (1+ *current-print-level*))) (write-char #\( stream) (let ((*current-print-length* 0) (list list)) (loop (punt-print-if-too-long *current-print-length* stream) (output-object (pop list) stream) (unless list (return)) (when (or (atom list) (check-for-circularity list)) (write-string " . " stream) (output-object list stream) (return)) (write-char #\space stream) (incf *current-print-length*))) (write-char #\) stream)))) list) ;;; Output the abbreviated #< form of an array. (defun output-terse-array (array stream) (let ((*print-level* nil) (*print-length* nil)) (print-unreadable-object (array stream :type t :identity t)))) (defun array-readably-printable-p (array) (and (eq (array-element-type array) t) (let ((zero (position 0 (array-dimensions array))) (number (position 0 (array-dimensions array) :test (complement #'eql) :from-end t))) (or (null zero) (null number) (> zero number))))) (defun output-vector (vector stream) (declare (vector vector)) (cond ((stringp vector) (assert nil) (sys::%output-object vector stream)) ((not (or *print-array* *print-readably*)) (output-terse-array vector stream)) ((bit-vector-p vector) (assert nil) (sys::%output-object vector stream)) (t (when (and *print-readably* (not (array-readably-printable-p vector))) (error 'print-not-readable :object vector)) (cond ((and (null *print-readably*) *print-level* (>= *current-print-level* *print-level*)) (write-char #\# stream)) (t (let ((*current-print-level* (1+ *current-print-level*))) (write-string "#(" stream) (dotimes (i (length vector)) (unless (zerop i) (write-char #\space stream)) (punt-print-if-too-long i stream) (output-object (aref vector i) stream)) (write-string ")" stream)))))) vector) (defun output-ugly-object (object stream) (cond ((consp object) (output-list object stream)) ((and (vectorp object) (not (stringp object)) (not (bit-vector-p object))) (output-vector object stream)) ((structure-object-p object) (cond ((and (null *print-readably*) *print-level* (>= *current-print-level* *print-level*)) (write-char #\# stream)) (t (print-object object stream)))) ((standard-object-p object) (print-object object stream)) ((java::java-object-p object) (print-object object stream)) ((xp::xp-structure-p stream) (let ((s (sys::%write-to-string object))) (xp::write-string++ s stream 0 (length s)))) ((functionp object) (print-object object stream)) (t (%output-object object stream)))) ;;;; circularity detection stuff ;;; When *PRINT-CIRCLE* is T, this gets bound to a hash table that ;;; (eventually) ends up with entries for every object printed. When ;;; we are initially looking for circularities, we enter a T when we ;;; find an object for the first time, and a 0 when we encounter an ;;; object a second time around. When we are actually printing, the 0 ;;; entries get changed to the actual marker value when they are first ;;; printed. (defvar *circularity-hash-table* nil) ;;; When NIL, we are just looking for circularities. After we have ;;; found them all, this gets bound to 0. Then whenever we need a new ;;; marker, it is incremented. (defvar *circularity-counter* nil) ;;; Check to see whether OBJECT is a circular reference, and return ;;; something non-NIL if it is. If ASSIGN is T, then the number to use ;;; in the #n= and #n# noise is assigned at this time. ;;; If ASSIGN is true, reference bookkeeping will only be done for ;;; existing entries, no new references will be recorded! ;;; ;;; Note: CHECK-FOR-CIRCULARITY must be called *exactly* once with ;;; ASSIGN true, or the circularity detection noise will get confused ;;; about when to use #n= and when to use #n#. If this returns non-NIL ;;; when ASSIGN is true, then you must call HANDLE-CIRCULARITY on it. ;;; If CHECK-FOR-CIRCULARITY returns :INITIATE as the second value, ;;; you need to initiate the circularity detection noise, e.g. bind ;;; *CIRCULARITY-HASH-TABLE* and *CIRCULARITY-COUNTER* to suitable values ;;; (see #'OUTPUT-OBJECT for an example). (defun check-for-circularity (object &optional assign) (cond ((null *print-circle*) ;; Don't bother, nobody cares. nil) ((null *circularity-hash-table*) (values nil :initiate)) ((null *circularity-counter*) (ecase (gethash object *circularity-hash-table*) ((nil) ;; first encounter (setf (gethash object *circularity-hash-table*) t) ;; We need to keep looking. nil) ((t) ;; second encounter (setf (gethash object *circularity-hash-table*) 0) ;; It's a circular reference. t) (0 ;; It's a circular reference. t))) (t (let ((value (gethash object *circularity-hash-table*))) (case value ((nil t) ;; If NIL, we found an object that wasn't there the ;; first time around. If T, this object appears exactly ;; once. Either way, just print the thing without any ;; special processing. Note: you might argue that ;; finding a new object means that something is broken, ;; but this can happen. If someone uses the ~@<...~:> ;; format directive, it conses a new list each time ;; though format (i.e. the &REST list), so we will have ;; different cdrs. nil) (0 (if assign (let ((value (incf *circularity-counter*))) ;; first occurrence of this object: Set the counter. (setf (gethash object *circularity-hash-table*) value) value) t)) (t ;; second or later occurrence (- value))))))) ;;; Handle the results of CHECK-FOR-CIRCULARITY. If this returns T then ;;; you should go ahead and print the object. If it returns NIL, then ;;; you should blow it off. (defun handle-circularity (marker stream) (case marker (:initiate ;; Someone forgot to initiate circularity detection. (let ((*print-circle* nil)) (error "trying to use CHECK-FOR-CIRCULARITY when ~ circularity checking isn't initiated"))) ((t) ;; It's a second (or later) reference to the object while we are ;; just looking. So don't bother groveling it again. nil) (t ;; (write-char #\# stream) ;; (let ((*print-base* 10) ;; (*print-radix* nil)) (cond ((minusp marker) ;; (output-integer (- marker) stream) ;; (write-char #\# stream) (print-reference marker stream) nil) (t ;; (output-integer marker stream) ;; (write-char #\= stream) (print-label marker stream) t))))) (defun print-label (marker stream) (write-char #\# stream) (let ((*print-base* 10) (*print-radix* nil)) (output-integer marker stream)) (write-char #\= stream)) (defun print-reference (marker stream) (write-char #\# stream) (let ((*print-base* 10) (*print-radix* nil)) (output-integer (- marker) stream)) (write-char #\# stream)) ;;;; OUTPUT-OBJECT -- the main entry point ;; Objects whose print representation identifies them EQLly don't need to be ;; checked for circularity. (defun uniquely-identified-by-print-p (x) (or (numberp x) (characterp x) (and (symbolp x) (symbol-package x)))) (defun %print-object (object stream) (if *print-pretty* (xp::output-pretty-object object stream) (output-ugly-object object stream))) (defun %check-object (object stream) (multiple-value-bind (marker initiate) (check-for-circularity object t) (if (eq initiate :initiate) ;; Initialize circularity detection. (let ((*circularity-hash-table* (make-hash-table :test 'eq))) (%check-object object (make-broadcast-stream)) (let ((*circularity-counter* 0)) (%check-object object stream))) ;; Otherwise... (if marker (when (handle-circularity marker stream) (%print-object object stream)) (%print-object object stream))))) ;;; Output OBJECT to STREAM observing all printer control variables. (defun output-object (object stream) (cond ((or (not *print-circle*) (uniquely-identified-by-print-p object)) (%print-object object stream)) ;; If we have already started circularity detection, this object might ;; be a shared reference. If we have not, then if it is a compound ;; object, it might contain a circular reference to itself or multiple ;; shared references. ((or *circularity-hash-table* (compound-object-p object)) (%check-object object stream)) (t (%print-object object stream))) object) (provide "PRINT") abcl-src-1.9.0/src/org/armedbear/lisp/probe_file.java0100644 0000000 0000000 00000016605 14223403213 021160 0ustar000000000 0000000 /* * probe_file.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; public final class probe_file { public static final Primitive PROBE_FILE = new pf_probe_file(); @DocString(name="probe-file", args="pathspec", returns="truename") private static final class pf_probe_file extends Primitive { pf_probe_file() { super(Symbol.PROBE_FILE, "pathspec"); } @Override public LispObject execute(LispObject arg) { if (arg == null || arg.equals(NIL)) { return NIL; } Pathname p = coerceToPathname(arg); if (p.isWild()) { return error(new FileError("Cannot find the TRUENAME for a wild pathname.", p)); } // TODO: refactor Pathname{,Jar,URL}.truename() to be non-static? if (p instanceof JarPathname) { return JarPathname.truename(p, false); } else if (p instanceof URLPathname) { return URLPathname.truename((URLPathname)p, false); } else { return Pathname.truename(p, false); } } }; public static final Primitive TRUENAME = new pf_truename(); @DocString(name="truename", args="pathspec", returns="pathname") private static class pf_truename extends Primitive { pf_truename() { super(Symbol.TRUENAME, "filespec"); } @Override public LispObject execute(LispObject arg) { Pathname p = coerceToPathname(arg); if (p.isWild()) { return error(new FileError("Cannot find the TRUENAME for a wild pathname.", p)); } // TODO: refactor Pathname{,Jar,URL}.truename() to be non-static? if (p instanceof JarPathname) { return JarPathname.truename(p, true); } else if (p instanceof URLPathname) { return URLPathname.truename((URLPathname)p, true); } else { return Pathname.truename(p, true); } } }; public static final Primitive PROBE_DIRECTORY = new pf_probe_directory(); @DocString(name="probe-directory", args="pathspec", returns="truename") private static final class pf_probe_directory extends Primitive { pf_probe_directory() { super("probe-directory", PACKAGE_EXT, true); } @Override public LispObject execute(LispObject arg) { Pathname pathname = coerceToPathname(arg); if (pathname.isWild()) { error(new FileError("Cannot probe a wild pathname as a directory.", pathname)); } Pathname defaultedPathname = (Pathname)Pathname.MERGE_PATHNAMES.execute(pathname); if (defaultedPathname instanceof JarPathname) { if (defaultedPathname.getName().equals(NIL) && defaultedPathname.getType().equals(NIL)) { return Symbol.PROBE_FILE.execute(defaultedPathname); } SimpleString lastDirectory = (SimpleString)Symbol.FILE_NAMESTRING.execute(defaultedPathname); LispObject appendedDirectory = defaultedPathname.getDirectory().reverse().push(lastDirectory).reverse(); defaultedPathname.setDirectory(appendedDirectory); return Symbol.PROBE_FILE.execute(defaultedPathname); } File file = defaultedPathname.getFile(); if (file == null || !file.isDirectory()) { return NIL; } if (defaultedPathname.getName().equals(NIL) && defaultedPathname.getType().equals(NIL)) { return Symbol.PROBE_FILE.execute(defaultedPathname); } SimpleString lastDirectory = (SimpleString)Symbol.FILE_NAMESTRING.execute(defaultedPathname); LispObject appendedDirectory = defaultedPathname.getDirectory().reverse().push(lastDirectory).reverse(); defaultedPathname.setDirectory(appendedDirectory); return Symbol.PROBE_FILE.execute(defaultedPathname); } }; public static final Primitive FILE_DIRECTORY_P = new pf_file_directory_p(); @DocString(name="file-directory-p", args="pathspec &key (wild-error-p t)", returns="generalized-boolean") private static final class pf_file_directory_p extends Primitive { pf_file_directory_p() { super("file-directory-p", PACKAGE_EXT, true); } private LispObject isDirectory(Pathname p) { LispObject result = PROBE_DIRECTORY.execute(p); return result.equals(NIL) ? NIL : T; } @Override public LispObject execute(LispObject arg) // XXX Should this merge with defaults? { Pathname pathname = coerceToPathname(arg); if (pathname.isWild()) { error(new FileError("Fundamentally unable to determine whether a wild pathname is a directory.", pathname)); } return isDirectory(pathname); } @Override public LispObject execute(LispObject arg, LispObject wildErrorPKeyword, LispObject wildErrorP) { if (!(wildErrorPKeyword.equals(Keyword.WILD_ERROR_P))) { type_error(wildErrorPKeyword, Keyword.WILD_ERROR_P); } Pathname pathname = coerceToPathname(arg); if (wildErrorP != NIL) { if (pathname.isWild()) { error(new FileError("Fundamentally to determine whether a wild pathname is a directory.", pathname)); } } return isDirectory(pathname); } }; } abcl-src-1.9.0/src/org/armedbear/lisp/proclaim.lisp0100644 0000000 0000000 00000013205 14223403213 020677 0ustar000000000 0000000 ;;; proclaim.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (export '(check-declaration-type proclaimed-type proclaimed-ftype ftype-result-type *inline-declarations*)) (defmacro declaim (&rest decls) `(eval-when (:compile-toplevel :load-toplevel :execute) ,@(mapcar (lambda (decl) `(proclaim ',decl)) decls))) (defun declaration-error (name) (error 'simple-error :format-control "The symbol ~S cannot be both the name of a type and the name of a declaration." :format-arguments (list name))) (defvar *inline-declarations* nil) (defvar *declaration-types* (make-hash-table :test 'eq)) ;; "A symbol cannot be both the name of a type and the name of a declaration. ;; Defining a symbol as the name of a class, structure, condition, or type, ;; when the symbol has been declared as a declaration name, or vice versa, ;; signals an error." (defun check-declaration-type (name) (when (gethash1 name (the hash-table *declaration-types*)) (declaration-error name))) (defun proclaim (declaration-specifier) (unless (symbolp (car declaration-specifier)) (%type-error (car declaration-specifier) 'symbol)) ;; (cdr declaration-specifier) must be a proper list. (unless (listp (cddr declaration-specifier)) (%type-error (cddr declaration-specifier) 'list)) (case (car declaration-specifier) (SPECIAL (dolist (name (cdr declaration-specifier)) (%defvar name))) (OPTIMIZE (dolist (spec (cdr declaration-specifier)) (let ((val 3) (quality spec)) (when (consp spec) (setf quality (%car spec) val (cadr spec))) (when (and (fixnump val) (<= 0 val 3)) (case quality (SPEED (setf *speed* val)) (SPACE (setf *space* val)) (SAFETY (setf *safety* val)) (DEBUG (setf *debug* val))))))) (FTYPE (unless (cdr declaration-specifier) (error "No type specified in FTYPE declaration: ~S" declaration-specifier)) (apply 'proclaim-ftype (cdr declaration-specifier))) (TYPE (unless (cdr declaration-specifier) (error "No type specified in TYPE declaration: ~S" declaration-specifier)) (apply 'proclaim-type (cdr declaration-specifier))) ((INLINE NOTINLINE) (dolist (name (cdr declaration-specifier)) (if (symbolp name) (setf (get name '%inline) (car declaration-specifier)) (push (cons name (car declaration-specifier)) *inline-declarations*)))) (DECLARATION (dolist (name (cdr declaration-specifier)) (when (or (get name 'deftype-definition) (find-class name nil)) (declaration-error name)) (setf (gethash name (the hash-table *declaration-types*)) name))) (:explain (dolist (spec (cdr declaration-specifier)) (let ((val t) (quality spec)) (when (consp spec) (setf quality (%car spec)) (when (= (length spec) 2) (setf val (%cadr spec)))) (if val (pushnew quality *explain*) (setf *explain* (remove quality *explain*)))))))) (defun proclaim-type (type &rest names) (dolist (name names) (setf (get name 'proclaimed-type) type))) (defun proclaimed-type (name) (get name 'proclaimed-type)) (declaim (type hash-table *proclaimed-ftypes*)) (defconst *proclaimed-ftypes* (make-hash-table :test 'equal)) (declaim (inline proclaim-ftype-1)) (defun proclaim-ftype-1 (ftype name) (declare (optimize speed)) (if (symbolp name) (setf (get name 'proclaimed-ftype) ftype) (setf (gethash name *proclaimed-ftypes*) ftype))) (declaim (notinline proclaim-ftype-1)) (defun proclaim-ftype (ftype &rest names) (declare (optimize speed)) (declare (inline proclaim-ftype-1)) (dolist (name names) (proclaim-ftype-1 ftype name))) (defun proclaimed-ftype (name) (if (symbolp name) (get name 'proclaimed-ftype) (gethash1 name *proclaimed-ftypes*))) (defun ftype-result-type (ftype) (if (atom ftype) '* (let ((result-type (third ftype))) (if result-type result-type '*)))) abcl-src-1.9.0/src/org/armedbear/lisp/profiler.lisp0100644 0000000 0000000 00000015417 14202767264 020742 0ustar000000000 0000000 ;;; profiler.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:profiler) (export '(*hidden-functions* *granularity* show-call-counts show-hot-counts with-profiling)) (require '#:clos) (require '#:format) (defvar *type* nil) (defvar *granularity* 1 "Sampling interval (in milliseconds).") (defvar *hidden-functions* '(funcall apply eval sys::%eval sys::interactive-eval tpl::repl tpl::top-level-loop)) (defstruct (profile-info (:constructor make-profile-info (object full-count hot-count))) object full-count hot-count) ;; Returns list of all symbols with non-zero call counts. (defun list-called-objects () (let ((result '())) (dolist (pkg (list-all-packages)) (dolist (sym (sys:package-symbols pkg)) (unless (memq sym *hidden-functions*) (when (fboundp sym) (let* ((definition (fdefinition sym)) (full-count (sys:call-count definition)) (hot-count (sys:hot-count definition))) (unless (zerop full-count) (cond ((typep definition 'generic-function) (push (make-profile-info definition full-count hot-count) result) (dolist (method (mop::generic-function-methods definition)) (let ((function (mop:method-function method))) (setf full-count (sys:call-count function)) (setf hot-count (sys:hot-count function))) (unless (zerop full-count) (push (make-profile-info method full-count hot-count) result)))) (t (push (make-profile-info sym full-count hot-count) result))))))))) (remove-duplicates result :key 'profile-info-object :test 'eq))) (defun object-name (object) (cond ((symbolp object) object) ((typep object 'generic-function) (mop:generic-function-name object)) ((typep object 'method) (list 'METHOD (mop:generic-function-name (mop:method-generic-function object)) (mop:method-specializers object))))) (defun object-compiled-function-p (object) (cond ((symbolp object) (compiled-function-p (fdefinition object))) ((typep object 'method) (compiled-function-p (mop:method-function object))) (t (compiled-function-p object)))) (defun show-call-count (info max-count) (let* ((object (profile-info-object info)) (count (profile-info-full-count info))) (if max-count (format t "~5,1F ~8D ~S~A~%" (/ (* count 100.0) max-count) count (object-name object) (if (object-compiled-function-p object) "" " [interpreted function]")) (format t "~8D ~S~A~%" count (object-name object) (if (object-compiled-function-p object) "" " [interpreted function]"))))) (defun show-hot-count (info max-count) (let* ((object (profile-info-object info)) (count (profile-info-hot-count info))) (if max-count (format t "~5,1F ~8D ~S~A~%" (/ (* count 100.0) max-count) count (object-name object) (if (object-compiled-function-p object) "" " [interpreted function]")) (format t "~8D ~S~A~%" count (object-name object) (if (object-compiled-function-p object) "" " [interpreted function]"))))) (defun show-call-counts () (let ((list (list-called-objects))) (setf list (sort list #'< :key 'profile-info-full-count)) (let ((max-count nil)) (when (eq *type* :time) (let ((last-info (car (last list)))) (setf max-count (if last-info (profile-info-full-count last-info) nil)) (when (eql max-count 0) (setf max-count nil)))) (dolist (info list) (show-call-count info max-count)))) (values)) (defun show-hot-counts () (let ((list (list-called-objects))) (setf list (sort list #'< :key 'profile-info-hot-count)) (let ((max-count nil)) (when (eq *type* :time) (let ((last-info (car (last list)))) (setf max-count (if last-info (profile-info-hot-count last-info) nil)) (when (eql max-count 0) (setf max-count nil)))) (dolist (info list) (show-hot-count info max-count)))) (values)) (defun start-profiler (&key type) "Starts the profiler. :TYPE may be either :TIME (statistical sampling) or :COUNT-ONLY (exact call counts)." (unless type (setf type :time)) (unless (memq type '(:time :count-only)) (error ":TYPE must be :TIME or :COUNT-ONLY")) (setf *type* type) (%start-profiler type *granularity*)) (defmacro with-profiling ((&key type) &body body) `(unwind-protect (progn (start-profiler :type ,type) ,@body) (stop-profiler))) abcl-src-1.9.0/src/org/armedbear/lisp/prog.lisp0100644 0000000 0000000 00000004106 14202767264 020060 0ustar000000000 0000000 ;;; prog.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From GCL. (in-package "COMMON-LISP") (defmacro prog (vl &rest body &aux (decl nil)) (do () ((or (endp body) (not (consp (car body))) (not (eq (caar body) 'declare))) `(block nil (let ,vl ,@decl (tagbody ,@body)))) (push (car body) decl) (pop body))) (defmacro prog* (vl &rest body &aux (decl nil)) (do () ((or (endp body) (not (consp (car body))) (not (eq (caar body) 'declare))) `(block nil (let* ,vl ,@decl (tagbody ,@body)))) (push (car body) decl) (pop body))) abcl-src-1.9.0/src/org/armedbear/lisp/protocol/Hashtable.java0100644 0000000 0000000 00000000462 14202767264 022620 0ustar000000000 0000000 package org.armedbear.lisp.protocol; /** Mark object as implementing the Hashtable protocol. */ public interface Hashtable extends org.armedbear.lisp.protocol.LispObject { public org.armedbear.lisp.LispObject getEntries(); @Deprecated public org.armedbear.lisp.LispObject ENTRIES(); } abcl-src-1.9.0/src/org/armedbear/lisp/protocol/Inspectable.java0100644 0000000 0000000 00000000274 14202767264 023157 0ustar000000000 0000000 package org.armedbear.lisp.protocol; /** Object implements a protocol for dynamic introspection. */ public interface Inspectable { public org.armedbear.lisp.LispObject getParts(); } abcl-src-1.9.0/src/org/armedbear/lisp/protocol/LispObject.java0100644 0000000 0000000 00000000351 14202767264 022760 0ustar000000000 0000000 package org.armedbear.lisp.protocol; /** Mark implementation of the LispObject protocol. */ public interface LispObject { public org.armedbear.lisp.LispObject typeOf(); // TODO fill in with other functions as need arises } abcl-src-1.9.0/src/org/armedbear/lisp/protocol/Pathname.java0100644 0000000 0000000 00000000501 14202767264 022454 0ustar000000000 0000000 package org.armedbear.lisp.protocol; // TODO: transcribe CL:PATHNAME, hook org.armedbear.lisp.Pathname up to use a proxied version of the ANSI contract. /** Mark object as implementing the Hashtable protocol. */ public interface Pathname extends org.armedbear.lisp.protocol.LispObject { public Pathname coerce(); } abcl-src-1.9.0/src/org/armedbear/lisp/psetf.lisp0100644 0000000 0000000 00000005611 14212332621 020216 0ustar000000000 0000000 ;;; psetf.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From CMUCL. (in-package #:system) (require '#:collect) (defmacro psetf (&rest args &environment env) "This is to SETF as PSETQ is to SETQ. Args are alternating place expressions and values to go into those places. All of the subforms and values are determined, left to right, and only then are the locations updated. Returns NIL." (collect ((let*-bindings) (mv-bindings) (setters)) (do ((a args (cddr a))) ((endp a)) (when (endp (cdr a)) (error 'program-error :format-control "Odd number of arguments to PSETF.")) (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion (macroexpand-1 (car a) env) env) (declare (ignore getter)) (let*-bindings (mapcar #'list dummies vals)) (mv-bindings (list newval (cadr a))) (setters setter))) (labels ((thunk (let*-bindings mv-bindings) (if let*-bindings `(let* ,(car let*-bindings) (multiple-value-bind ,@(car mv-bindings) ,(thunk (cdr let*-bindings) (cdr mv-bindings)))) `(progn ,@(setters) nil)))) (thunk (let*-bindings) (mv-bindings))))) abcl-src-1.9.0/src/org/armedbear/lisp/query.lisp0100644 0000000 0000000 00000005610 14223403213 020237 0ustar000000000 0000000 ;;; query.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package "SYSTEM") (defun query-readline () (force-output *query-io*) (string-trim '(#\space #\tab) (read-line *query-io*))) (defun y-or-n-p (&optional format-string &rest arguments) (when format-string (fresh-line *query-io*) (apply #'format *query-io* format-string arguments)) (loop (let* ((line (query-readline)) (ans (if (string= line "") #\? ;Force CASE below to issue instruction. (schar line 0)))) (unless (whitespacep ans) (case ans ((#\y #\Y) (return t)) ((#\n #\N) (return nil)) (t (write-line "Type \"y\" for yes or \"n\" for no. " *query-io*) (when format-string (apply #'format *query-io* format-string arguments)) (force-output *query-io*))))))) (defun yes-or-no-p (&optional format-string &rest arguments) (clear-input *query-io*) (when format-string (fresh-line *query-io*) (apply #'format *query-io* format-string arguments)) (do ((ans (query-readline) (query-readline))) (()) (cond ((string-equal ans "YES") (return t)) ((string-equal ans "NO") (return nil)) (t (write-line "Type \"yes\" for yes or \"no\" for no. " *query-io*) (when format-string (apply #'format *query-io* format-string arguments)))))) abcl-src-1.9.0/src/org/armedbear/lisp/read-circle.lisp0100644 0000000 0000000 00000020355 14202767264 021267 0ustar000000000 0000000 ;;; read-circle.lisp ;;; ;;; Copyright (C) 2009 Erik Huelsmann ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") ;;; Reading circular data: the #= and ## reader macros (from SBCL) ;;; Objects already seen by CIRCLE-SUBST. (defvar *sharp-equal-circle-table*) ;; This function is kind of like NSUBLIS, but checks for circularities and ;; substitutes in arrays and structures as well as lists. The first arg is an ;; alist of the things to be replaced assoc'd with the things to replace them. (defun circle-subst (old-new-alist tree) (macrolet ((recursable-element-p (subtree) `(typep ,subtree '(or cons (array t) structure-object standard-object))) (element-replacement (subtree) `(let ((entry (find ,subtree old-new-alist :key #'second))) (if entry (third entry) ,subtree)))) (cond ((not (recursable-element-p tree)) (element-replacement tree)) ((null (gethash tree *sharp-equal-circle-table*)) (cond ((typep tree 'structure-object) (setf (gethash tree *sharp-equal-circle-table*) t) (do ((i 0 (1+ i)) (end (structure-length tree))) ((= i end)) (let* ((old (structure-ref tree i)) (new (circle-subst old-new-alist old))) (unless (eq old new) (structure-set tree i new))))) ;; ((typep tree 'standard-object) ;; (setf (gethash tree *sharp-equal-circle-table*) t) ;; (do ((i 1 (1+ i)) ;; (end (%instance-length tree))) ;; ((= i end)) ;; (let* ((old (%instance-ref tree i)) ;; (new (circle-subst old-new-alist old))) ;; (unless (eq old new) ;; (setf (%instance-ref tree i) new))))) ((arrayp tree) (setf (gethash tree *sharp-equal-circle-table*) t) (do ((i 0 (1+ i)) (end (array-total-size tree))) ((>= i end)) (let* ((old (row-major-aref tree i)) (new (circle-subst old-new-alist old))) (unless (eq old new) (setf (row-major-aref tree i) new))))) (t ;; being CONSP as all the other cases have been handled (do ((subtree tree (cdr subtree))) ((or (not (consp subtree)) (gethash subtree *sharp-equal-circle-table*))) ;; CDR no longer a CONS; no need to recurse any further: ;; the case where the CDR is a symbol to be replaced ;; has been handled in the last iteration (setf (gethash subtree *sharp-equal-circle-table*) t) (let* ((c (car subtree)) (d (cdr subtree)) (a (if (recursable-element-p c) (circle-subst old-new-alist c) (element-replacement c))) (b (cond ((consp d) d) ;; CONSes handled in the loop ((recursable-element-p d) ;; ARRAY, STRUCTURE-OBJECT and STANDARD-OBJECT ;; handled in recursive calls (circle-subst old-new-alist d)) (t (element-replacement d))))) (unless (eq a c) (rplaca subtree a)) (unless (eq d b) (rplacd subtree b)))))) tree) (t tree)))) ;;; Sharp-equal works as follows. When a label is assigned (i.e. when ;;; #= is called) we GENSYM a symbol is which is used as an ;;; unforgeable tag. *SHARP-SHARP-ALIST* maps the integer tag to this ;;; gensym. ;;; ;;; When SHARP-SHARP encounters a reference to a label, it returns the ;;; symbol assoc'd with the label. Resolution of the reference is ;;; deferred until the read done by #= finishes. Any already resolved ;;; tags (in *SHARP-EQUAL-ALIST*) are simply returned. ;;; ;;; After reading of the #= form is completed, we add an entry to ;;; *SHARP-EQUAL-ALIST* that maps the gensym tag to the resolved ;;; object. Then for each entry in the *SHARP-SHARP-ALIST, the current ;;; object is searched and any uses of the gensysm token are replaced ;;; with the actual value. (defvar *sharp-sharp-alist* ()) (defun sharp-equal (stream label readtable) (when *read-suppress* (return-from sharp-equal (values))) (unless label (error 'reader-error :stream stream :format-control "Missing label for #=")) (when (or (assoc label *sharp-sharp-alist*) (assoc label *sharp-equal-alist*)) (error 'reader-error :stream stream :format-control "Multiply defined label: #~D=" :format-arguments (list label))) (let* ((tag (gensym)) (*sharp-sharp-alist* (cons (list label tag nil) *sharp-sharp-alist*)) (obj (let ((*readtable* readtable)) (read stream t nil t)))) (when (eq obj tag) (error 'reader-error :stream stream :format-control "Must tag something more than just #~D#" :format-arguments (list label))) (push (list label tag obj) *sharp-equal-alist*) (when (third (car *sharp-sharp-alist*)) ;; set to T on circularity (let ((*sharp-equal-circle-table* (make-hash-table :test 'eq :size 20))) (circle-subst *sharp-equal-alist* obj))) obj)) () (defun sharp-sharp (stream ignore label) (declare (ignore ignore)) (when *read-suppress* (return-from sharp-sharp nil)) (unless label (error 'reader-error :stream stream :format-control "Missing label for ##")) (let ((entry (assoc label *sharp-equal-alist*))) (if entry (third entry) (let ((pair (assoc label *sharp-sharp-alist*))) (unless pair (error 'reader-error :stream stream :format-control "Object is not labelled #~S#" :format-arguments (list label))) (setf (third pair) t) (second pair))))) (set-dispatch-macro-character #\# #\= #'(lambda (stream ignore label) (declare (ignore ignore)) (sharp-equal stream label *readtable*)) +standard-readtable+) (set-dispatch-macro-character #\# #\# #'sharp-sharp +standard-readtable+) (set-dispatch-macro-character #\# #\= #'(lambda (stream ignore label) (declare (ignore ignore)) (sharp-equal stream label (get-fasl-readtable))) (get-fasl-readtable)) (set-dispatch-macro-character #\# #\# #'sharp-sharp (get-fasl-readtable)) abcl-src-1.9.0/src/org/armedbear/lisp/read-conditional.lisp0100644 0000000 0000000 00000004133 14202767264 022325 0ustar000000000 0000000 ;;; read-conditional.lisp ;;; ;;; Copyright (C) 2005-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun read-feature (stream) (let* ((*package* +keyword-package+) (*read-suppress* nil)) (if (featurep (read stream t nil t)) #\+ #\-))) (defun read-conditional (stream subchar int) (declare (ignore int)) (if (eql subchar (read-feature stream)) (read stream t nil t) (let ((*read-suppress* t)) (read stream t nil t) (values)))) (set-dispatch-macro-character #\# #\+ #'read-conditional +standard-readtable+) (set-dispatch-macro-character #\# #\- #'read-conditional +standard-readtable+) abcl-src-1.9.0/src/org/armedbear/lisp/read-from-string.lisp0100644 0000000 0000000 00000003437 14202767264 022277 0ustar000000000 0000000 ;;; read-from-string.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun read-from-string (string &optional (eof-error-p t) eof-value &key (start 0) end preserve-whitespace) (sys::%read-from-string string eof-error-p eof-value start end preserve-whitespace)) abcl-src-1.9.0/src/org/armedbear/lisp/read-sequence.lisp0100644 0000000 0000000 00000005611 14202767264 021634 0ustar000000000 0000000 ;;; read-sequence.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun read-sequence (sequence stream &key (start 0) end) (declare (type stream stream)) (require-type start '(integer 0)) (if end (require-type end '(integer 0)) (setf end (length sequence))) (let* ((element-type (expand-deftype (stream-element-type stream)))) (cond ((eq element-type 'character) (do ((pos start (1+ pos))) ((>= pos end) pos) (let ((element (read-char stream nil :eof))) (when (eq element :eof) (return pos)) (setf (elt sequence pos) element)))) ((equal element-type '(unsigned-byte 8)) (if (and (vectorp sequence) (equal (array-element-type sequence) '(unsigned-byte 8))) (read-vector-unsigned-byte-8 sequence stream start end) (do ((pos start (1+ pos))) ((>= pos end) pos) (let ((element (read-8-bits stream nil :eof))) (when (eq element :eof) (return pos)) (setf (elt sequence pos) element))))) (t (do ((pos start (1+ pos))) ((>= pos end) pos) (let ((element (read-byte stream nil :eof))) (when (eq element :eof) (return pos)) (setf (elt sequence pos) element))))))) abcl-src-1.9.0/src/org/armedbear/lisp/reduce.lisp0100644 0000000 0000000 00000007731 14223403213 020347 0ustar000000000 0000000 ;;; reduce.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from OpenMCL. (in-package #:system) (require "EXTENSIBLE-SEQUENCES-BASE") (defmacro list-reduce (function sequence start end initial-value ivp key) (let ((what `(if ,key (funcall ,key (car sequence)) (car sequence)))) `(let ((sequence (nthcdr ,start ,sequence))) (do ((count (if ,ivp ,start (1+ ,start)) (1+ count)) (sequence (if ,ivp sequence (cdr sequence)) (cdr sequence)) (value (if ,ivp ,initial-value ,what) (funcall ,function value ,what))) ((= count ,end) value))))) (defmacro list-reduce-from-end (function sequence start end initial-value ivp key) (let ((what `(if ,key (funcall ,key (car sequence)) (car sequence)))) `(let ((sequence (nthcdr (- (length ,sequence) ,end) (reverse ,sequence)))) (do ((count (if ,ivp ,start (1+ ,start)) (1+ count)) (sequence (if ,ivp sequence (cdr sequence)) (cdr sequence)) (value (if ,ivp ,initial-value ,what) (funcall ,function ,what value))) ((= count ,end) value))))) (defun reduce (function sequence &rest args &key from-end (start 0) end (initial-value nil ivp) key) (unless end (setq end (length sequence))) (if (= end start) (if ivp initial-value (funcall function)) (sequence::seq-dispatch sequence (if from-end (list-reduce-from-end function sequence start end initial-value ivp key) (list-reduce function sequence start end initial-value ivp key)) (let* ((disp (if from-end -1 1)) (index (if from-end (1- end) start)) (terminus (if from-end (1- start) end)) (value (if ivp initial-value (let ((elt (aref sequence index))) (setf index (+ index disp)) (if key (funcall key elt) elt)))) (element nil)) (do* () ((= index terminus) value) (setf element (aref sequence index) index (+ index disp) element (if key (funcall key element) element) value (funcall function (if from-end element value) (if from-end value element))))) (apply #'sequence:reduce function sequence args)))) abcl-src-1.9.0/src/org/armedbear/lisp/rem.java0100644 0000000 0000000 00000004023 14202767264 017644 0ustar000000000 0000000 /* * rem.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### rem number divisor => remainder public final class rem extends Primitive { private rem() { super("rem", "number divisor"); } @Override public LispObject execute(LispObject number, LispObject divisor) { number.truncate(divisor); final LispThread thread = LispThread.currentThread(); LispObject remainder = thread._values[1]; thread.clearValues(); return remainder; } private static final Primitive REM = new rem(); } abcl-src-1.9.0/src/org/armedbear/lisp/remf.lisp0100644 0000000 0000000 00000005731 14223403213 020027 0ustar000000000 0000000 ;;; remf.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (defmacro remf (place indicator &environment env) "Place may be any place expression acceptable to SETF, and is expected to hold a property list or (). This list is destructively altered to remove the property specified by the indicator. Returns T if such a property was present, NIL if not." (multiple-value-bind (dummies vals newval setter getter) (get-setf-expansion place env) (do* ((d dummies (cdr d)) (v vals (cdr v)) (let-list nil) (ind-temp (gensym)) (local1 (gensym)) (local2 (gensym))) ((null d) ;; See ANSI 5.1.3 for why we do out-of-order evaluation (push (list ind-temp indicator) let-list) (push (list (car newval) getter) let-list) `(let* ,(nreverse let-list) (do ((,local1 ,(car newval) (cddr ,local1)) (,local2 nil ,local1)) ((atom ,local1) nil) (cond ((atom (cdr ,local1)) (error "Odd-length property list in REMF.")) ((eq (car ,local1) ,ind-temp) (cond (,local2 (rplacd (cdr ,local2) (cddr ,local1)) (return t)) (t (setq ,(car newval) (cddr ,(car newval))) ,setter (return t)))))))) (push (list (car d) (car v)) let-list)))) abcl-src-1.9.0/src/org/armedbear/lisp/remove-duplicates.lisp0100644 0000000 0000000 00000011536 14223403213 022526 0ustar000000000 0000000 ;;; remove-duplicates.lisp ;;; ;;; Copyright (C) 2003-2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require "EXTENSIBLE-SEQUENCES-BASE") ;;; Adapted from CMUCL. (defun list-remove-duplicates (list test test-not start end key from-end) (let* ((result (list ())) (splice result) (current list)) (do ((index 0 (1+ index))) ((= index start)) (setq splice (cdr (rplacd splice (list (car current))))) (setq current (cdr current))) (do ((index start (1+ index))) ((or (and end (= index end)) (atom current))) (if (or (and from-end (not (member (apply-key key (car current)) (nthcdr (1+ start) result) :test test :test-not test-not :key key))) (and (not from-end) (not (do ((it (apply-key key (car current))) (l (cdr current) (cdr l)) (i (1+ index) (1+ i))) ((or (atom l) (and end (= i end))) ()) (if (if test-not (not (funcall test-not it (apply-key key (car l)))) (funcall test it (apply-key key (car l)))) (return t)))))) (setq splice (cdr (rplacd splice (list (car current)))))) (setq current (cdr current))) (do () ((atom current)) (setq splice (cdr (rplacd splice (list (car current))))) (setq current (cdr current))) (cdr result))) (defun vector-remove-duplicates (vector test test-not start end key from-end &optional (length (length vector))) (when (null end) (setf end (length vector))) (let ((result (make-sequence-like vector length)) (index 0) (jndex start)) (do () ((= index start)) (setf (aref result index) (aref vector index)) (setq index (1+ index))) (do ((elt)) ((= index end)) (setq elt (aref vector index)) (unless (or (and from-end (position (apply-key key elt) result :start start :end jndex :test test :test-not test-not :key key)) (and (not from-end) (position (apply-key key elt) vector :start (1+ index) :end end :test test :test-not test-not :key key))) (setf (aref result jndex) elt) (setq jndex (1+ jndex))) (setq index (1+ index))) (do () ((= index length)) (setf (aref result jndex) (aref vector index)) (setq index (1+ index)) (setq jndex (1+ jndex))) (shrink-vector result jndex))) (defun remove-duplicates (sequence &rest args &key (test #'eql) test-not (start 0) from-end end key) (sequence::seq-dispatch sequence (when sequence (if (and (eq test #'eql) (null test-not) (eql start 0) (null from-end) (null end) (null key)) (simple-list-remove-duplicates sequence) (list-remove-duplicates sequence test test-not start end key from-end))) (vector-remove-duplicates sequence test test-not start end key from-end) (apply #'sequence:remove-duplicates sequence args))) abcl-src-1.9.0/src/org/armedbear/lisp/remove.lisp0100644 0000000 0000000 00000016432 14223403213 020373 0ustar000000000 0000000 ;;; remove.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (require "DELETE") ; MUMBLE-DELETE-FROM-END (require "EXTENSIBLE-SEQUENCES-BASE") ;;; From CMUCL. (defmacro real-count (count) `(cond ((null ,count) most-positive-fixnum) ((fixnump ,count) (if (minusp ,count) 0 ,count)) ((integerp ,count) (if (minusp ,count) 0 most-positive-fixnum)) (t ,count))) (defmacro mumble-remove-macro (bump left begin finish right pred) `(do ((index ,begin (,bump index)) (result (do ((index ,left (,bump index)) (result (make-sequence-like sequence length))) ((= index ,begin) result) (aset result index (aref sequence index)))) (new-index ,begin) (number-zapped 0) (this-element)) ((or (= index ,finish) (= number-zapped count)) (do ((index index (,bump index)) (new-index new-index (,bump new-index))) ((= index ,right) (shrink-vector result new-index)) (aset result new-index (aref sequence index)))) (setq this-element (aref sequence index)) (cond (,pred (setq number-zapped (1+ number-zapped))) (t (aset result new-index this-element) (setq new-index (,bump new-index)))))) (defmacro mumble-remove (pred) `(mumble-remove-macro 1+ 0 start end length ,pred)) (defmacro mumble-remove-from-end (pred) `(let ((sequence (copy-seq sequence))) (mumble-delete-from-end ,pred))) (defmacro normal-mumble-remove () `(mumble-remove (if test-not (not (funcall test-not item (apply-key key this-element))) (funcall test item (apply-key key this-element))))) (defmacro normal-mumble-remove-from-end () `(mumble-remove-from-end (if test-not (not (funcall test-not item (apply-key key this-element))) (funcall test item (apply-key key this-element))))) (defmacro if-mumble-remove () `(mumble-remove (funcall predicate (apply-key key this-element)))) (defmacro if-mumble-remove-from-end () `(mumble-remove-from-end (funcall predicate (apply-key key this-element)))) (defmacro if-not-mumble-remove () `(mumble-remove (not (funcall predicate (apply-key key this-element))))) (defmacro if-not-mumble-remove-from-end () `(mumble-remove-from-end (not (funcall predicate (apply-key key this-element))))) (defmacro list-remove-macro (pred reverse-p) `(let* ((sequence ,(if reverse-p '(reverse sequence) 'sequence)) (%start ,(if reverse-p '(- length end) 'start)) (%end ,(if reverse-p '(- length start) 'end)) (splice (list nil)) (results (do ((index 0 (1+ index)) (before-start splice)) ((= index %start) before-start) (setq splice (cdr (rplacd splice (list (pop sequence)))))))) (do ((index %start (1+ index)) (this-element) (number-zapped 0)) ((or (= index %end) (= number-zapped count)) (do ((index index (1+ index))) ((null sequence) ,(if reverse-p '(nreverse (cdr results)) '(cdr results))) (setq splice (cdr (rplacd splice (list (pop sequence))))))) (setq this-element (pop sequence)) (if ,pred (setq number-zapped (1+ number-zapped)) (setq splice (cdr (rplacd splice (list this-element)))))))) (defmacro list-remove (pred) `(list-remove-macro ,pred nil)) (defmacro list-remove-from-end (pred) `(list-remove-macro ,pred t)) (defmacro normal-list-remove () `(list-remove (if test-not (not (funcall test-not item (apply-key key this-element))) (funcall test item (apply-key key this-element))))) (defmacro normal-list-remove-from-end () `(list-remove-from-end (if test-not (not (funcall test-not item (apply-key key this-element))) (funcall test item (apply-key key this-element))))) (defmacro if-list-remove () `(list-remove (funcall predicate (apply-key key this-element)))) (defmacro if-list-remove-from-end () `(list-remove-from-end (funcall predicate (apply-key key this-element)))) (defmacro if-not-list-remove () `(list-remove (not (funcall predicate (apply-key key this-element))))) (defmacro if-not-list-remove-from-end () `(list-remove-from-end (not (funcall predicate (apply-key key this-element))))) (defun remove (item sequence &rest args &key from-end (test #'eql) test-not (start 0) end count key) (let* ((length (length sequence)) (end (or end length)) (count (real-count count))) (sequence::seq-dispatch sequence (if from-end (normal-list-remove-from-end) (normal-list-remove)) (if from-end (normal-mumble-remove-from-end) (normal-mumble-remove)) (apply #'sequence:remove item sequence args)))) (defun remove-if (predicate sequence &rest args &key from-end (start 0) end count key) (let* ((length (length sequence)) (end (or end length)) (count (real-count count))) (sequence::seq-dispatch sequence (if from-end (if-list-remove-from-end) (if-list-remove)) (if from-end (if-mumble-remove-from-end) (if-mumble-remove)) (apply #'sequence:remove-if predicate sequence args)))) (defun remove-if-not (predicate sequence &rest args &key from-end (start 0) end count key) (let* ((length (length sequence)) (end (or end length)) (count (real-count count))) (sequence::seq-dispatch sequence (if from-end (if-not-list-remove-from-end) (if-not-list-remove)) (if from-end (if-not-mumble-remove-from-end) (if-not-mumble-remove)) (apply #'sequence:remove-if-not predicate sequence args)))) abcl-src-1.9.0/src/org/armedbear/lisp/replace.lisp0100644 0000000 0000000 00000021525 14223403213 020510 0ustar000000000 0000000 ;;; replace.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package #:system) (require "EXTENSIBLE-SEQUENCES-BASE") #|(eval-when (:compile-toplevel :load-toplevel :execute) (defmacro seq-dispatch (sequence list-form array-form) `(if (listp ,sequence) ,list-form ,array-form)))|# (eval-when (:compile-toplevel :execute) ;;; If we are copying around in the same vector, be careful not to copy the ;;; same elements over repeatedly. We do this by copying backwards. (defmacro mumble-replace-from-mumble () `(if (and (eq target-sequence source-sequence) (> target-start source-start)) (let ((nelts (min (- target-end target-start) (- source-end source-start)))) (do ((target-index (+ (the fixnum target-start) (the fixnum nelts) -1) (1- target-index)) (source-index (+ (the fixnum source-start) (the fixnum nelts) -1) (1- source-index))) ((= target-index (the fixnum (1- target-start))) target-sequence) (declare (fixnum target-index source-index)) (setf (aref target-sequence target-index) (aref source-sequence source-index)))) (do ((target-index target-start (1+ target-index)) (source-index source-start (1+ source-index))) ((or (= target-index (the fixnum target-end)) (= source-index (the fixnum source-end))) target-sequence) (declare (fixnum target-index source-index)) (setf (aref target-sequence target-index) (aref source-sequence source-index))))) (defmacro list-replace-from-list () `(if (and (eq target-sequence source-sequence) (> target-start source-start)) (let ((new-elts (subseq source-sequence source-start (+ (the fixnum source-start) (the fixnum (min (- (the fixnum target-end) (the fixnum target-start)) (- (the fixnum source-end) (the fixnum source-start)))))))) (do ((n new-elts (cdr n)) (o (nthcdr target-start target-sequence) (cdr o))) ((null n) target-sequence) (rplaca o (car n)))) (do ((target-index target-start (1+ target-index)) (source-index source-start (1+ source-index)) (target-sequence-ref (nthcdr target-start target-sequence) (cdr target-sequence-ref)) (source-sequence-ref (nthcdr source-start source-sequence) (cdr source-sequence-ref))) ((or (= target-index (the fixnum target-end)) (= source-index (the fixnum source-end)) (null target-sequence-ref) (null source-sequence-ref)) target-sequence) (declare (fixnum target-index source-index)) (rplaca target-sequence-ref (car source-sequence-ref))))) (defmacro list-replace-from-mumble () `(do ((target-index target-start (1+ target-index)) (source-index source-start (1+ source-index)) (target-sequence-ref (nthcdr target-start target-sequence) (cdr target-sequence-ref))) ((or (= target-index (the fixnum target-end)) (= source-index (the fixnum source-end)) (null target-sequence-ref)) target-sequence) (declare (fixnum source-index target-index)) (rplaca target-sequence-ref (aref source-sequence source-index)))) (defmacro mumble-replace-from-list () `(do ((target-index target-start (1+ target-index)) (source-index source-start (1+ source-index)) (source-sequence (nthcdr source-start source-sequence) (cdr source-sequence))) ((or (= target-index (the fixnum target-end)) (= source-index (the fixnum source-end)) (null source-sequence)) target-sequence) (declare (fixnum target-index source-index)) (setf (aref target-sequence target-index) (car source-sequence)))) ) ; eval-when ;;; The support routines for REPLACE are used by compiler transforms, so we ;;; worry about dealing with end being supplied as or defaulting to nil ;;; at this level. (defun list-replace-from-list* (target-sequence source-sequence target-start target-end source-start source-end) (when (null target-end) (setq target-end (length target-sequence))) (when (null source-end) (setq source-end (length source-sequence))) (list-replace-from-list)) (defun list-replace-from-vector* (target-sequence source-sequence target-start target-end source-start source-end) (when (null target-end) (setq target-end (length target-sequence))) (when (null source-end) (setq source-end (length source-sequence))) (list-replace-from-mumble)) (defun vector-replace-from-list* (target-sequence source-sequence target-start target-end source-start source-end) (when (null target-end) (setq target-end (length target-sequence))) (when (null source-end) (setq source-end (length source-sequence))) (mumble-replace-from-list)) (defun vector-replace-from-vector* (target-sequence source-sequence target-start target-end source-start source-end) (when (null target-end) (setq target-end (length target-sequence))) (when (null source-end) (setq source-end (length source-sequence))) (mumble-replace-from-mumble)) ;;; REPLACE cannot default end arguments to the length of sequence since it ;;; is not an error to supply nil for their values. We must test for ends ;;; being nil in the body of the function. (defun replace (target-sequence source-sequence &rest args &key ((:start1 target-start) 0) ((:end1 target-end)) ((:start2 source-start) 0) ((:end2 source-end))) "The target sequence is destructively modified by copying successive elements into it from the source sequence." (check-type target-start (integer 0 #.array-total-size-limit)) (check-type source-start (integer 0 #.array-total-size-limit)) (check-type target-end (or null (integer 0 #.array-total-size-limit))) (check-type source-end (or null (integer 0 #.array-total-size-limit))) (let ((target-end (or target-end (length target-sequence))) (source-end (or source-end (length source-sequence)))) (declare (type (integer 0 #.array-total-size-limit) target-start target-end source-start source-end)) (sequence::seq-dispatch target-sequence (sequence::seq-dispatch source-sequence (list-replace-from-list) (list-replace-from-mumble) (apply #'sequence:replace target-sequence source-sequence args)) (sequence::seq-dispatch source-sequence (mumble-replace-from-list) (mumble-replace-from-mumble) (apply #'sequence:replace target-sequence source-sequence args)) (apply #'sequence:replace target-sequence source-sequence args)))) abcl-src-1.9.0/src/org/armedbear/lisp/require.lisp0100644 0000000 0000000 00000006406 14202767264 020572 0ustar000000000 0000000 ;;; require.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) ;;; PROVIDE, REQUIRE (from SBCL) (defun provide (module-name) (pushnew (string module-name) *modules* :test #'string=) t) (defun module-provide-system (module) (let ((*readtable* (copy-readtable nil))) (handler-case (progn (load-system-file (string-downcase (string module))) (provide module)) (t (e) (unless (and (typep e 'error) (search "Failed to find loadable system file" (format nil "~A" e))) (format *error-output* "Failed to require ~A because '~A'~%" module e)) nil)))) (defvar *module-provider-functions* nil) (defun require (module-name &optional pathnames) (unless (member (string module-name) *modules* :test #'string=) (let ((saved-modules (copy-list *modules*))) (cond ;;; Since these are files packaged with the system we ensure that ;;; PROVIDE has been called unless the module has other dependencies ;;; that must be satisfied to be loaded, which is currently only the ;;; case with 'abcl-contrib'. (pathnames (unless (listp pathnames) (setf pathnames (list pathnames))) (dolist (x pathnames) (load x)) (unless (string-equal module-name "abcl-contrib") (provide module-name))) ;;; Responsibility for actually calling PROVIDE up to module provider ;;; function (t (unless (some (lambda (p) (funcall p module-name)) (append (list #'module-provide-system) sys::*module-provider-functions*)) (error "Don't know how to ~S ~A." 'require module-name)))) (set-difference *modules* saved-modules)))) abcl-src-1.9.0/src/org/armedbear/lisp/restart.lisp0100644 0000000 0000000 00000036715 14212332621 020572 0ustar000000000 0000000 ;;; restart.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL/SBCL. (in-package #:system) (defun read-evaluated-form () (fresh-line *query-io*) (%format *query-io* "Enter a form to be evaluated:~%") (list (eval (read *query-io*)))) (defvar *restart-clusters* ()) (defvar *condition-restarts* ()) (defstruct restart name function report-function interactive-function (test-function #'(lambda (c) (declare (ignore c)) t))) (defmacro restart-bind (bindings &body forms) `(let ((*restart-clusters* (cons (list ,@(mapcar #'(lambda (binding) `(make-restart :name ',(car binding) :function ,(cadr binding) ,@(cddr binding))) bindings)) *restart-clusters*))) ,@forms)) (defun compute-restarts (&optional condition) (let ((res ())) (map-restarts (lambda(restart) (push restart res)) condition t) (nreverse res))) (defun map-restarts (fn condition call-test-p) (let ((associated ()) (other ())) (dolist (alist *condition-restarts*) (if (eq (car alist) condition) (setq associated (cdr alist)) (setq other (append (cdr alist) other)))) (dolist (restart-cluster *restart-clusters*) (dolist (restart restart-cluster) (when (and (or (not condition) (member restart associated) (not (member restart other))) (or (not call-test-p) (funcall (restart-test-function restart) condition))) (funcall fn restart)))))) (defun restart-report (restart stream) (funcall (or (restart-report-function restart) (let ((name (restart-name restart))) (lambda (stream) (if name (%format stream "~S" name) (%format stream "~S" restart))))) stream)) (defun print-restart (restart stream) (if *print-escape* (print-unreadable-object (restart stream :type t :identity t) (prin1 (restart-name restart) stream)) (restart-report restart stream))) (defun find-restart (name &optional condition) (let ((restarts (compute-restarts condition))) (dolist (restart restarts) (when (or (eq restart name) (eq (restart-name restart) name)) (return-from find-restart restart))))) (defun find-restart-or-control-error (identifier &optional condition) (or (find-restart identifier condition) (error 'control-error :format-control "Restart ~S is not active." :format-arguments (list identifier)))) (defun invoke-restart (restart &rest values) (let ((real-restart (if (restart-p restart) (catch 'found (map-restarts (lambda(r) (when (eq r restart) (throw 'found r))) nil nil) (error 'control-error :format-control "Restart ~S is not active." :format-arguments (list restart))) (find-restart-or-control-error restart)))) (apply (restart-function real-restart) values))) (defun interactive-restart-arguments (real-restart) (let ((interactive-function (restart-interactive-function real-restart))) (if interactive-function (funcall interactive-function) '()))) (defun invoke-restart-interactively (restart) (let* ((real-restart (if (restart-p restart) (catch 'found (map-restarts (lambda(r) (when (eq r restart) (throw 'found r))) nil nil) (error 'control-error :format-control "Restart ~S is not active." :format-arguments (list restart))) (find-restart-or-control-error restart))) (args (interactive-restart-arguments real-restart)) ) (apply (restart-function real-restart) args))) (defun parse-keyword-pairs (list keys) (do ((l list (cddr l)) (k '() (list* (cadr l) (car l) k))) ((or (null l) (not (member (car l) keys))) (values (nreverse k) l)))) (defmacro with-keyword-pairs ((names expression &optional keywords-var) &body forms) (let ((temp (member '&rest names))) (unless (= (length temp) 2) (error "&REST keyword is ~:[missing~;misplaced~]." temp)) (let ((key-vars (ldiff names temp)) (key-var (or keywords-var (gensym))) (rest-var (cadr temp))) (let ((keywords (mapcar #'(lambda (x) (intern (string x) (find-package "KEYWORD"))) key-vars))) `(multiple-value-bind (,key-var ,rest-var) (parse-keyword-pairs ,expression ',keywords) (let ,(mapcar #'(lambda (var keyword) `(,var (getf ,key-var ,keyword))) key-vars keywords) ,@forms)))))) (defun transform-keywords (&key report interactive test) (let ((result ())) (when report (setf result (list* (if (stringp report) `#'(lambda (stream) (write-string ,report stream)) `#',report) :report-function result))) (when interactive (setf result (list* `#',interactive :interactive-function result))) (when test (setf result (list* `#',test :test-function result))) (nreverse result))) ;; "If the restartable-form is a list whose car is any of the symbols SIGNAL, ;; ERROR, CERROR, or WARN (or is a macro form which macroexpands into such a ;; list), then WITH-CONDITION-RESTARTS is used implicitly to associate the ;; indicated restarts with the condition to be signaled." (defun munge-restart-case-expression (expression env) (let ((exp (macroexpand expression env))) (if (consp exp) (let* ((name (car exp)) (args (if (eq name 'cerror) (cddr exp) (cdr exp)))) (if (member name '(SIGNAL ERROR CERROR WARN)) (let ((n-cond (gensym))) `(let ((,n-cond (coerce-to-condition ,(first args) (list ,@(rest args)) ',(case name (WARN 'simple-warning) (SIGNAL 'simple-condition) (t 'simple-error)) ',name))) (with-condition-restarts ,n-cond (car *restart-clusters*) ,(if (eq name 'cerror) `(cerror ,(second exp) ,n-cond) `(,name ,n-cond))))) expression)) expression))) (defmacro restart-case (expression &body clauses &environment env) (let ((block-tag (gensym)) (temp-var (gensym)) (data (mapcar #'(lambda (clause) (with-keyword-pairs ((report interactive test &rest forms) (cddr clause)) (list (car clause) (gensym) (transform-keywords :report report :interactive interactive :test test) (cadr clause) forms))) clauses))) `(block ,block-tag (let ((,temp-var nil)) (tagbody (restart-bind ,(mapcar #'(lambda (datum) (let ((name (nth 0 datum)) (tag (nth 1 datum)) (keys (nth 2 datum))) `(,name #'(lambda (&rest temp) (setq ,temp-var temp) (go ,tag)) ,@keys))) data) (return-from ,block-tag ,(munge-restart-case-expression expression env))) ,@(mapcan #'(lambda (datum) (let ((tag (nth 1 datum)) (bvl (nth 3 datum)) (body (nth 4 datum))) (list tag `(return-from ,block-tag (apply #'(lambda ,bvl ,@body) ,temp-var))))) data)))))) (defmacro with-simple-restart ((restart-name format-string &rest format-arguments) &body forms) `(restart-case (progn ,@forms) (,restart-name () :report (lambda (stream) (simple-format stream ,format-string ,@format-arguments)) (values nil t)))) (defmacro with-condition-restarts (condition-form restarts-form &body body) (let ((n-cond (gensym))) `(let ((*condition-restarts* (cons (let ((,n-cond ,condition-form)) (cons ,n-cond (append ,restarts-form (cdr (assoc ,n-cond *condition-restarts*))))) *condition-restarts*))) ,@body))) (defun abort (&optional condition) (invoke-restart (find-restart-or-control-error 'abort condition)) (error 'control-error :format-control "ABORT restart failed to transfer control dynamically.")) (defun muffle-warning (&optional condition) (invoke-restart (find-restart-or-control-error 'muffle-warning condition))) (defun continue (&optional condition) (let ((restart (find-restart 'continue condition))) (when restart (invoke-restart restart)))) (defun store-value (value &optional condition) (let ((restart (find-restart 'store-value condition))) (when restart (invoke-restart restart value)))) (defun use-value (value &optional condition) (let ((restart (find-restart 'use-value condition))) (when restart (invoke-restart restart value)))) (defun warn (datum &rest arguments) (let ((condition (coerce-to-condition datum arguments 'simple-warning 'warn))) (require-type condition 'warning) (restart-case (signal condition) (muffle-warning () :report "Skip warning." (return-from warn nil))) (let ((badness (etypecase condition (style-warning 'style-warning) (warning 'warning)))) (fresh-line *error-output*) (simple-format *error-output* "~S: ~A~%" badness condition))) nil) (defun style-warn (format-control &rest format-arguments) (warn 'style-warning :format-control format-control :format-arguments format-arguments)) (defun cerror (continue-string datum &rest arguments) (with-simple-restart (continue "~A" (apply #'simple-format nil continue-string arguments)) (let ((condition (coerce-to-condition datum arguments 'simple-error 'error))) (with-condition-restarts condition (list (find-restart 'continue)) (signal condition) (invoke-debugger condition)))) nil) (defun query-function () (format *query-io* "~&Enter a form to be evaluated: ") (force-output *query-io*) (multiple-value-list (eval (read *query-io*)))) ;; This modified function offers you a function with the same name in another package. (defun undefined-function-called (name arguments) (finish-output) ;; find all fbound symbols of same name (let ((alternatives (let ((them nil)) (dolist (package (list-all-packages)) (let ((found (find-symbol (string name) package))) (when (and (fboundp found) (not (member found them))) (push found them)))) them))) (let ((sys::*restart-clusters* sys::*restart-clusters*)) ;; Build and add the restarts (dolist (alt alternatives) (let ((package (symbol-package alt))) (let ((alt alt) (package package)) (push (list (system::make-restart :name (intern (concatenate 'string "USE-FROM-" (package-name package))) :function #'(lambda (&rest ignore) (declare (ignore ignore)) (shadowing-import alt) (setq name (symbol-function alt)) (return-from undefined-function-called (apply name arguments))) :report-function #'(lambda (stream) (format stream "Import then use #'~a::~a instead" (string-downcase (package-name package)) alt)))) sys::*restart-clusters*)))) (loop (restart-case (error 'undefined-function :name name) (continue () :report "Try again.") (use-value (value) :report "Specify a function to call instead." :interactive query-function (return-from undefined-function-called (apply value arguments))) (return-value (&rest values) :report (lambda (stream) (format stream "Return one or more values from the call to ~S." name)) :interactive query-function (return-from undefined-function-called (values-list values))))) (when (fboundp name) (return-from undefined-function-called (apply name arguments)))))) abcl-src-1.9.0/src/org/armedbear/lisp/revappend.lisp0100644 0000000 0000000 00000003254 14202767264 021100 0ustar000000000 0000000 ;;; revappend.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun revappend (x y) (do ((top x (cdr top)) (result y (cons (car top) result))) ((endp top) result))) abcl-src-1.9.0/src/org/armedbear/lisp/room.java0100644 0000000 0000000 00000005340 14202767264 020040 0ustar000000000 0000000 /* * room.java * * Copyright (C) 2003-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### room public final class room extends Primitive { private room() { super("room", "&optional x"); } @Override public LispObject execute(LispObject[] args) { if (args.length > 1) return error(new WrongNumberOfArgumentsException(this, -1, 1)); Runtime runtime = Runtime.getRuntime(); long total = runtime.totalMemory(); long free = runtime.freeMemory(); long used = total - free; Stream out = getStandardOutput(); StringBuffer sb = new StringBuffer("Total memory "); sb.append(total); sb.append(" bytes"); sb.append(System.getProperty("line.separator")); sb.append(used); sb.append(" bytes used"); sb.append(System.getProperty("line.separator")); sb.append(free); sb.append(" bytes free"); sb.append(System.getProperty("line.separator")); out._writeString(sb.toString()); out._finishOutput(); return LispThread.currentThread().setValues(number(used), number(total),number(runtime.maxMemory())); } private static final Primitive ROOM = new room(); } abcl-src-1.9.0/src/org/armedbear/lisp/rotatef.lisp0100644 0000000 0000000 00000004762 14223403213 020545 0ustar000000000 0000000 ;;; rotatef.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (eval-when (:compile-toplevel) (require '#:collect)) (defmacro rotatef (&rest args &environment env) (when args (collect ((let*-bindings) (mv-bindings) (setters) (getters)) (dolist (arg args) (multiple-value-bind (temps subforms store-vars setter getter) (get-setf-expansion arg env) (loop for temp in temps for subform in subforms do (let*-bindings `(,temp ,subform))) (mv-bindings store-vars) (setters setter) (getters getter))) (setters nil) (getters (car (getters))) (labels ((thunk (mv-bindings getters) (if mv-bindings `((multiple-value-bind ,(car mv-bindings) ,(car getters) ,@(thunk (cdr mv-bindings) (cdr getters)))) (setters)))) `(let* ,(let*-bindings) ,@(thunk (mv-bindings) (cdr (getters)))))))) abcl-src-1.9.0/src/org/armedbear/lisp/run-benchmarks.lisp0100644 0000000 0000000 00000020266 14202767264 022035 0ustar000000000 0000000 ;; Driver for Eric Marsden's CL-BENCH Lisp performance benchmarks. (in-package :cl-user) #+armedbear (require 'pprint) #+allegro (progn (setq excl:*record-source-file-info* nil) (setq excl:*load-source-file-info* nil) (setq excl:*record-xref-info* nil) (setq excl:*load-xref-info* nil)) (setf *default-pathname-defaults* #p"/home/peter/cl-bench/") (load #p"defpackage.lisp") (compile-file #p"files/arrays.olisp") (compile-file #p"files/bignum.olisp") (compile-file #p"files/boehm-gc.olisp") (compile-file #p"files/clos.olisp") (compile-file #p"files/crc40.olisp") (compile-file #p"files/deflate.olisp") (compile-file #p"files/gabriel.olisp") (compile-file #p"files/hash.olisp") (compile-file #p"files/math.olisp") (compile-file #p"files/ratios.olisp") (compile-file #p"files/richards.olisp") (compile-file #p"files/misc.olisp") (load (compile-file-pathname #p"files/arrays.olisp")) (load (compile-file-pathname #p"files/bignum.olisp")) (load (compile-file-pathname #p"files/boehm-gc.olisp")) (load (compile-file-pathname #p"files/clos.olisp")) (load (compile-file-pathname #p"files/crc40.olisp")) (load (compile-file-pathname #p"files/deflate.olisp")) (load (compile-file-pathname #p"files/gabriel.olisp")) (load (compile-file-pathname #p"files/hash.olisp")) (load (compile-file-pathname #p"files/math.olisp")) (load (compile-file-pathname #p"files/ratios.olisp")) (load (compile-file-pathname #p"files/richards.olisp")) (load (compile-file-pathname #p"files/misc.olisp")) (compile-file #p"support.lisp") (load (compile-file-pathname #p"support.lisp")) (in-package :cl-bench) (export '(run-benchmark run-benchmarks)) (setf *benchmark-output* t) #+(or armedbear clisp) (defun bench-gc () (ext:gc)) #+sbcl (defun bench-gc () (sb-ext:gc #+gencgc :full #+gencgc t)) #+allegro (defun bench-gc () (excl:gc)) (defun report-filename () (let ((impl "")) #+allegro (setf impl "-allegro") #+armedbear (setf impl "-armedbear") #+clisp (setf impl "-clisp") #+sbcl (setf impl "-sbcl") (multiple-value-bind (sec min hour day month year) (get-decoded-time) (format nil "~abenchmark-~d~2,'0d~2,'0dT~2,'0d~2,'0d~a" #+win32 "" #-win32 "/var/tmp/" year month day hour min impl)))) (defun run-benchmark (function &optional args (times 1)) (let ((name (symbol-name function))) (format t "Running benchmark ~A" (symbol-name function)) (when (> times 1) (format t " (~D runs)" times)) (terpri) (force-output) (let (before-real after-real before-user after-user) (setf before-real (get-internal-real-time)) (setf before-user (get-internal-run-time)) (dotimes (i times) (apply function args)) (setf after-user (get-internal-run-time)) (setf after-real (get-internal-real-time)) (let ((real (/ (- after-real before-real) internal-time-units-per-second)) (user (/ (- after-user before-user) internal-time-units-per-second))) (format *benchmark-output* ";; ~25a ~8,2f ~8,2f~%" name real user) (format *trace-output* ";; ~25a ~8,2f ~8,2f~%" name real user)) (force-output *benchmark-output*))) (bench-gc) (values)) (defun run-benchmarks () (with-open-file (f (report-filename) :direction :output :if-exists :supersede) (let ((*benchmark-output* f)) (format *benchmark-output* "~A ~A " (lisp-implementation-type) (lisp-implementation-version)) (multiple-value-bind (second minute hour date month year) (get-decoded-time) (format *benchmark-output* "~d-~2,'0d-~2,'0d ~2,'0d:~2,'0d~%" year month date hour minute)) (format *benchmark-output* "~a~%" (short-site-name)) (force-output *benchmark-output*) (bench-gc) ;; The benchmarks. #+nil (run-benchmark 'cl-bench.misc:run-compiler nil 3) #+nil (run-benchmark 'cl-bench.misc:run-fasload nil 20) #-allegro (run-benchmark 'cl-bench.misc:run-permutations nil 2) #+nil (progn (cl-bench.misc::setup-walk-list/seq) (run-benchmark 'cl-bench.misc:walk-list/seq) (setf cl-bench.misc::*big-seq-list* nil) (bench-gc)) #+nil (progn (cl-bench.misc::setup-walk-list/mess) (run-benchmark 'cl-bench.misc:walk-list/mess) (setf cl-bench.misc::*big-mess-list* nil) (bench-gc)) (run-benchmark 'cl-bench.gabriel:boyer nil 30) (run-benchmark 'cl-bench.gabriel:browse nil 10) (run-benchmark 'cl-bench.gabriel:dderiv-run nil 50) (run-benchmark 'cl-bench.gabriel:deriv-run nil 60) (run-benchmark 'cl-bench.gabriel:run-destructive nil 100) (run-benchmark 'cl-bench.gabriel:run-div2-test1 nil 200) (run-benchmark 'cl-bench.gabriel:run-div2-test2 nil 200) (run-benchmark 'cl-bench.gabriel:run-fft nil 30) (run-benchmark 'cl-bench.gabriel:run-frpoly/fixnum nil 100) (run-benchmark 'cl-bench.gabriel:run-frpoly/bignum nil 30) (run-benchmark 'cl-bench.gabriel:run-frpoly/float nil 100) (run-benchmark 'cl-bench.gabriel:run-puzzle nil 1500) (run-benchmark 'cl-bench.gabriel:run-tak) (run-benchmark 'cl-bench.gabriel:run-ctak) (run-benchmark 'cl-bench.gabriel:run-trtak) (run-benchmark 'cl-bench.gabriel:run-takl) #+nil (run-benchmark 'cl-bench.gabriel:run-stak) (run-benchmark 'cl-bench.gabriel:fprint/ugly nil 200) (run-benchmark 'cl-bench.gabriel:fprint/pretty) (run-benchmark 'cl-bench.gabriel:run-traverse) (run-benchmark 'cl-bench.gabriel:run-triangle) (run-benchmark 'cl-bench.richards:richards) (run-benchmark 'cl-bench.math:run-factorial nil 1000) (run-benchmark 'cl-bench.math:run-fib nil 50) (run-benchmark 'cl-bench.math:run-fib-ratio) #+nil (run-benchmark 'cl-bench.math:run-ackermann) (run-benchmark 'cl-bench.math:run-mandelbrot/complex) (run-benchmark 'cl-bench.math:run-mandelbrot/dfloat) (run-benchmark 'cl-bench.math:run-mrg32k3a) (run-benchmark 'cl-bench.crc:run-crc40) (run-benchmark 'cl-bench.bignum:run-elem-100-1000) (run-benchmark 'cl-bench.bignum:run-elem-1000-100) (run-benchmark 'cl-bench.bignum:run-elem-10000-1) (run-benchmark 'cl-bench.bignum:run-pari-100-10) (run-benchmark 'cl-bench.bignum:run-pari-200-5) (run-benchmark 'cl-bench.bignum:run-pi-decimal/small) #-allegro (run-benchmark 'cl-bench.bignum:run-pi-decimal/big) (run-benchmark 'cl-bench.bignum:run-pi-atan) (run-benchmark 'cl-bench.ratios:run-pi-ratios) #-clisp (run-benchmark 'cl-bench.hash:run-slurp-lines nil 30) #-allegro (run-benchmark 'cl-bench.hash:hash-strings nil 2) (run-benchmark 'cl-bench.hash:hash-integers nil 10) #-allegro (run-benchmark 'cl-bench.boehm-gc:gc-benchmark) (run-benchmark 'cl-bench.deflate:run-deflate-file nil 100) #-allegro (run-benchmark 'cl-bench.arrays:bench-1d-arrays) #-allegro (run-benchmark 'cl-bench.arrays:bench-2d-arrays '(1000 1)) #-allegro (run-benchmark 'cl-bench.arrays:bench-3d-arrays '(100 1)) (run-benchmark 'cl-bench.arrays:bench-bitvectors nil 3) #-allegro (run-benchmark 'cl-bench.arrays:bench-strings) #-allegro (run-benchmark 'cl-bench.arrays:bench-strings/adjustable '(1000000 1)) #-(or allegro clisp) (run-benchmark 'cl-bench.arrays:bench-string-concat '(1000000 1)) #-allegro (run-benchmark 'cl-bench.arrays:bench-search-sequence '(1000000 1)) (return-from run-benchmarks) (run-benchmark 'cl-bench.clos:run-defclass) (run-benchmark 'cl-bench.clos:run-defmethod) (run-benchmark 'cl-bench.clos:make-instances) (run-benchmark 'cl-bench.clos:make-instances/simple) (run-benchmark 'cl-bench.clos:methodcalls/simple) (run-benchmark 'cl-bench.clos:methodcalls/simple+after) #-clisp (run-benchmark 'cl-bench.clos:methodcalls/complex) #+nil (run-benchmark 'cl-bench.clos:run-eql-fib) (run-benchmark 'cl-bench.clos::eql-fib '(16))))) (in-package "CL-USER") (import '(cl-bench:run-benchmark cl-bench:run-benchmarks)) (export '(run-benchmark run-benchmarks)) abcl-src-1.9.0/src/org/armedbear/lisp/run-program.lisp0100644 0000000 0000000 00000041256 14223403213 021351 0ustar000000000 0000000 ;;; run-program.lisp ;;; ;;; Copyright (C) 2011 Alessio Stalla ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :system) (require :java) (defun not-java-6-p () (not (find :java-6 *features*))) (defun pre-java-11-p () (or (find :java-6 *features*) (find :java-7 *features*) (find :java-8 *features*))) (export '(run-program process process-p process-input process-output process-error process-alive-p process-wait process-exit-code process-kill process-pid)) ;;; Vaguely inspired by sb-ext:run-program in SBCL. ;;; ;;; See . ;;; ;;; This implementation uses the JVM facilities for running external ;;; processes. ;;; . (defun run-program (program args &key environment (wait t) clear-environment (input :stream) (output :stream) (error :stream) if-input-does-not-exist (if-output-exists :error) (if-error-exists :error) directory) "Run PROGRAM with ARGS in with ENVIRONMENT variables. Possibly WAIT for subprocess to exit. Optionally CLEAR-ENVIRONMENT of the subprocess of any non specified values. Creates a new process running the the PROGRAM. ARGS are a list of strings to be passed to the program as arguments. For no arguments, use nil which means that just the name of the program is passed as arg 0. Returns a process structure containing the JAVA-OBJECT wrapped Process object, and the PROCESS-INPUT, PROCESS-OUTPUT, and PROCESS-ERROR streams. c.f. http://download.oracle.com/javase/6/docs/api/java/lang/Process.html Notes about Unix environments (as in the :environment): * The ABCL implementation of run-program, like SBCL, Perl and many other programs, copies the Unix environment by default. * Running Unix programs from a setuid process, or in any other situation where the Unix environment is under the control of someone else, is a mother lode of security problems. If you are contemplating doing this, read about it first. (The Perl community has a lot of good documentation about this and other security issues in script-like programs. The &key arguments have the following meanings: :environment An alist of STRINGs (name . value) describing new environment values that replace existing ones. :clear-environment If non-NIL, the current environment is cleared before the values supplied by :environment are inserted. :wait If non-NIL, which is the default, wait until the created process finishes. If NIL, continue running Lisp until the program finishes. :input If T, I/O is inherited from the Java process. If NIL, /dev/null is used (nul on Windows). If a PATHNAME designator other than a stream is supplied, input will be read from that file. If set to :STREAM, a stream will be available via PROCESS-INPUT to read from. Defaults to :STREAM. :if-input-does-not-exist If :input points to a non-existing file, this may be set to :ERROR in order to signal an error, :CREATE to create and read from an empty file, or NIL to immediately NIL instead of creating the process. Defaults to NIL. :output If T, I/O is inherited from the Java process. If NIL, /dev/null is used (nul on Windows). If a PATHNAME designator other than a stream is supplied, output will be redirect to that file. If set to :STREAM, a stream will be available via PROCESS-OUTPUT to write to. Defaults to :STREAM. :if-output-exists If :output points to a non-existing file, this may be set to :ERROR in order to signal an error, :SUPERSEDE to supersede the existing file, :APPEND to append to it instead, or NIL to immediately NIL instead of creating the process. Defaults to :ERROR. :error Same as :output, but can also be :output, in which case the error stream is redirected to wherever the standard output stream goes. Defaults to :STREAM. :if-error-exists Same as :if-output-exists, but for the :error target. :directory If set will become the working directory for the new process, otherwise the working directory will be unchanged from the current Java process. Defaults to NIL. " (let* ((program-namestring (namestring (pathname program))) (process-builder (%make-process-builder program-namestring args))) (let ((env-map (%process-builder-environment process-builder))) (when clear-environment (%process-builder-env-clear env-map)) (when environment (dolist (entry environment) (%process-builder-env-put env-map (princ-to-string (car entry)) (princ-to-string (cdr entry)))))) (let ((input-stream-p (eq input :stream)) (output-stream-p (eq output :stream)) (error-stream-p (eq error :stream)) output-redirection input-redirection error-redirection) (unless output-stream-p (unless (setf output-redirection (setup-output-redirection process-builder output NIL if-output-exists)) (return-from run-program))) (if (eq error :output) (java:jcall "redirectErrorStream" process-builder T) (unless error-stream-p (unless (setf error-redirection (setup-output-redirection process-builder error T if-error-exists)) (return-from run-program)))) (unless input-stream-p (unless (setf input-redirection (setup-input-redirection process-builder input if-input-does-not-exist)) (return-from run-program))) (when directory (java:jcall "directory" process-builder (java:jnew "java.io.File" (namestring directory)))) (let ((process (if (not-java-6-p) (make-process (%process-builder-start process-builder) input-stream-p output-stream-p error-stream-p) (make-process (%process-builder-start process-builder) t t t)))) (when (find :java-1.6 *features*) (when input-redirection (let ((input (process-input process))) (threads:make-thread (lambda () (from-file input-redirection input))))) (when output-redirection (let ((output (process-output process)) (file (first output-redirection)) (appendp (second output-redirection))) (threads:make-thread (lambda () (to-file output file :append appendp))))) (when error-redirection (let ((error (process-error process)) (file (first output-redirection)) (appendp (second output-redirection))) (threads:make-thread (lambda () (to-file error file :append appendp)))))) (when (or wait (not-java-6-p) (process-wait process)) process))))) (defconstant +inherit+ (ignore-errors (java:jfield "java.lang.ProcessBuilder$Redirect" "INHERIT"))) (defun coerce-to-file (value) (java:jnew "java.io.File" (if value (namestring value) (cond ((ext:os-unix-p) "/dev/null") ((ext:os-windows-p) "nul") (t (error "Don't know how to set up null stream on this platform.")))))) (define-condition implementation-not-available (error) ((missing :initarg :missing :reader missing)) (:report (lambda (condition stream) (format stream "This JVM is missing the ~a implementation." (missing condition))))) (defun setup-input-redirection (process-builder value if-does-not-exist) "Returns boolean truth when input redirections has been successfully set up. As a second value, returns either nil if input should inherit from the parent process, or a java.io.File reference to the file to read input from." (let ((redirect (if (eq value T) ;; Either inherit stdio or fail (if (not-java-6-p) +inherit+ (signal 'implementation-not-available :missing "Inheritance for subprocess of standard input")) ;; or read from a file (let ((file (coerce-to-file value))) (when value (if (eq if-does-not-exist :create) (open value :direction :probe :if-does-not-exist :create) (unless (probe-file value) (ecase if-does-not-exist (:error (error "Input file ~S does not already exist." value)) ((NIL) (return-from setup-input-redirection)))))) (if (not-java-6-p) (java:jstatic "from" "java.lang.ProcessBuilder$Redirect" file) file))))) (when (not-java-6-p) (java:jcall "redirectInput" process-builder redirect)) redirect)) #| value t inherit from |# (defun setup-output-redirection (process-builder value errorp if-does-exist) (let ((redirect (if (eq value T) (if (not-java-6-p) +inherit+ (if errorp (signal 'implementation-not-available :missing "Inheritance for subprocess of standard error") (signal 'implementation-not-available :missing "Inheritance for subprocess of standard output"))) (let ((file (coerce-to-file value)) appendp) (when (and value (probe-file value)) (ecase if-does-exist (:error (error "Output file ~S does already exist." value)) (:supersede (with-open-file (f value :direction :output :if-exists if-does-exist))) (:append (setf appendp T)) ((NIL) (return-from setup-output-redirection)))) (if (not-java-6-p) (if appendp (java:jstatic "appendTo" "java.lang.ProcessBuilder$Redirect" file) (java:jstatic "to" "java.lang.ProcessBuilder$Redirect" file)) (list file appendp)))))) (when (not-java-6-p) (if errorp (java:jcall "redirectError" process-builder redirect) (java:jcall "redirectOutput" process-builder redirect))) redirect)) ;;; The process structure. (defstruct (process (:constructor %make-process (jprocess))) jprocess %input %output %error) (defun make-process (proc inputp outputp errorp) (let ((process (%make-process proc))) (when inputp (setf (process-%input process) (%make-process-input-stream proc))) (when outputp (setf (process-%output process) (%make-process-output-stream proc))) (when errorp (setf (process-%error process) (%make-process-error-stream proc))) process)) (defun process-input (process) (process-%input process)) (defun process-output (process) (process-%output process)) (defun process-error (process) (process-%error process)) (defun process-alive-p (process) "Return t if process is still alive, nil otherwise." (%process-alive-p (process-jprocess process))) (defun process-wait (process) "Wait for process to quit running for some reason." (%process-wait (process-jprocess process))) (defun process-exit-code (instance) "The exit code of a process." (%process-exit-code (process-jprocess instance))) (defun process-kill (process) "Kills the process." (%process-kill (process-jprocess process))) (defun process-pid (process) "Return the process ID." (%process-pid (process-jprocess process))) ;;; Low-level functions. For now they're just a refactoring of the ;;; initial implementation with direct jnew & jcall forms in the ;;; code. As per Ville's suggestion, these should really be implemented ;;; as primitives. (defun %make-process-builder (program args) (java:jnew "java.lang.ProcessBuilder" (java:jnew-array-from-list "java.lang.String" (cons program args)))) (defun %process-builder-environment (pb) (java:jcall "environment" pb)) (defun %process-builder-env-put (env-map key value) (java:jcall "put" env-map key value)) (defun %process-builder-env-clear (env-map) (java:jcall "clear" env-map)) (defun %process-builder-start (pb) (java:jcall "start" pb)) (defun %make-process-input-stream (proc) (java:jnew "org.armedbear.lisp.Stream" 'system-stream (java:jcall "getOutputStream" proc) ;;not a typo! 'character)) (defun %make-process-output-stream (proc) (java:jnew "org.armedbear.lisp.Stream" 'system-stream (java:jcall "getInputStream" proc) ;;not a typo| 'character)) (defun %make-process-error-stream (proc) (java:jnew "org.armedbear.lisp.Stream" 'system-stream (java:jcall "getErrorStream" proc) 'character)) (defun %process-alive-p (jprocess) (not (ignore-errors (java:jcall "exitValue" jprocess)))) (defun %process-wait (jprocess) (java:jcall "waitFor" jprocess)) (defun %process-exit-code (jprocess) (ignore-errors (java:jcall "exitValue" jprocess))) (defun %process-pid (jprocess) (if (ext:os-unix-p) (let* ((process-class (java:jclass (if (pre-java-11-p) "java.lang.UNIXProcess" "java.lang.ProcessImpl"))) (field (java:jcall "getDeclaredField" process-class "pid"))) (java:jcall "setAccessible" field java:+true+) (java:jcall "get" field jprocess)) (error "Can't retrieve PID on this platform."))) (defun %process-kill (jprocess) (java:jcall "destroy" jprocess)) (defun to-file (input java.io.file &key (append nil)) (declare (ignore append)) ;; FIXME (let ((file (java:jcall "toString" java.io.file))) (with-open-file (s file :direction :output :element-type (stream-element-type input)) (let ((buffer (make-array 8192 :element-type (stream-element-type input)))) (loop :for bytes-read = (read-sequence buffer input) :while (plusp bytes-read) :do (write-sequence buffer s :end bytes-read))))) (close input)) (defun from-file (java.io.file output) (let ((file (java:jcall "toString" java.io.file))) (with-open-file (s file :direction :input :element-type (stream-element-type output)) (let ((buffer (make-array 8192 :element-type (stream-element-type output)))) (loop :for bytes-read = (read-sequence buffer s) :while (plusp bytes-read) :do (write-sequence buffer output :end bytes-read)))) (close output))) #| tests (uiop:run-program "uname -a" :output :string) (uiop:run-program "cat /etc/passwd" :output :string) |# abcl-src-1.9.0/src/org/armedbear/lisp/run-shell-command.lisp0100644 0000000 0000000 00000003457 14202767264 022446 0ustar000000000 0000000 ;;; run-shell-command.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "EXTENSIONS") (export '(run-shell-command)) ;; Deprecated: use SYS:RUN-PROGRAM ;; XXX (defun run-shell-command (command &key directory (output *standard-output*)) "Deprecated. Use SYS:RUN-PROGRAM." (sys::%run-shell-command command directory output)) abcl-src-1.9.0/src/org/armedbear/lisp/runtime-class.lisp0100644 0000000 0000000 00000043455 14202767264 021711 0ustar000000000 0000000 (require "JVM") ;;The package is set to :jvm for convenience, since most of the symbols used ;;here come from that package. However, the functions we're definining belong ;;to the :java package. (in-package :jvm) (defconstant +abcl-java-object+ (make-jvm-class-name "org.armedbear.lisp.JavaObject")) (defun java::make-memory-class-loader (&optional (parent (java:get-current-classloader))) (java:jnew "org.armedbear.lisp.MemoryClassLoader" parent)) (defun java:jnew-runtime-class (class-name &rest args &key (superclass "java.lang.Object") interfaces constructors methods fields (access-flags '(:public)) annotations (class-loader (java::make-memory-class-loader))) "Creates and loads a Java class with methods calling Lisp closures as given in METHODS. CLASS-NAME and SUPER-NAME are strings, INTERFACES is a list of strings, CONSTRUCTORS, METHODS and FIELDS are lists of constructor, method and field definitions. Constructor definitions - currently NOT supported - are lists of the form (argument-types function &optional super-invocation-arguments) where argument-types is a list of strings and function is a lisp function of (1+ (length argument-types)) arguments; the instance (`this') is passed in as the last argument. The optional super-invocation-arguments is a list of numbers between 1 and (length argument-types), where the number k stands for the kth argument to the just defined constructor. If present, the constructor of the superclass will be called with the appropriate arguments. E.g., if the constructor definition is ((\"java.lang.String\" \"int\") #'(lambda (string i this) ...) (2 1)) then the constructor of the superclass with argument types (int, java.lang.String) will be called with the second and first arguments. Method definitions are lists of the form (METHOD-NAME RETURN-TYPE ARGUMENT-TYPES FUNCTION &key MODIFIERS ANNOTATIONS) where METHOD-NAME is a string RETURN-TYPE denotes the type of the object returned by the method ARGUMENT-TYPES is a list of parameters to the method The types are either strings naming fully qualified java classes or Lisp keywords referring to primitive types (:void, :int, etc.). FUNCTION is a Lisp function of minimum arity (1+ (length argument-types)). The instance (`this') is passed as the first argument. Field definitions are lists of the form (field-name type &key modifiers annotations)." (declare (ignorable superclass interfaces constructors methods fields access-flags annotations)) (let ((stream (sys::%make-byte-array-output-stream))) (multiple-value-bind (class-file method-implementation-fields) (apply #'java::%jnew-runtime-class class-name stream :allow-other-keys T args) (sys::put-memory-function class-loader class-name (sys::%get-output-stream-bytes stream)) (let ((jclass (java:jcall "loadClass" class-loader class-name))) (dolist (method method-implementation-fields) (setf (java:jfield jclass (car method)) (cdr method))) jclass)))) (defconstant +abcl-lisp-integer-object+ (make-jvm-class-name "org.armedbear.lisp.LispInteger")) (defun box-arguments (argument-types offset all-argc) ;;Box each argument (loop :for arg-type :in argument-types :for i :from offset :do (progn (cond ((eq arg-type :int) (iload i) (emit-invokestatic +abcl-lisp-integer-object+ "getInstance" (list :int) +abcl-lisp-integer-object+)) ((keywordp arg-type) (error "Unsupported arg-type: ~A" arg-type)) (t (aload i) (emit 'iconst_1) ;;true (emit-invokestatic +abcl-java-object+ "getInstance" (list +java-object+ :boolean) +lisp-object+))) (astore (+ i all-argc))))) (defun java::%jnew-runtime-class (class-name stream &key (superclass "java.lang.Object") interfaces constructors methods fields (access-flags '(:public)) annotations) "Actual implementation of jnew-runtime-class. Writes the class bytes to a stream. Returns two values: the finalized class-file structure and the alist of method implementation fields." (let* ((jvm-class-name (make-jvm-class-name class-name)) (class-file (make-class-file jvm-class-name (make-jvm-class-name superclass) access-flags)) method-implementation-fields) (setf (class-file-interfaces class-file) (mapcar #'make-jvm-class-name interfaces)) (when annotations (class-add-attribute class-file (make-runtime-visible-annotations-attribute :list (mapcar #'parse-annotation annotations)))) (setf method-implementation-fields (java::runtime-class-add-methods class-file methods)) (java::runtime-class-add-fields class-file fields) (if (null constructors) (let ((ctor (make-jvm-method :constructor :void nil :flags '(:public)))) (class-add-method class-file ctor) (with-code-to-method (class-file ctor) (aload 0) (emit-invokespecial-init (class-file-superclass class-file) nil) (emit 'return))) (dolist (constructor constructors) (destructuring-bind (argument-types function &key (modifiers '(:public))) constructor (let* ((argument-types (mapcar #'java::canonicalize-java-type argument-types)) (argc (length argument-types)) (ctor (make-jvm-method :constructor :void argument-types :flags modifiers)) (field-name (string (gensym "CONSTRUCTOR"))) (all-argc (1+ argc))) (class-add-method class-file ctor) (let ((field (make-field field-name +lisp-object+ :flags '(:public :static)))) (class-add-field class-file field)) (push (cons field-name function) method-implementation-fields) (with-code-to-method (class-file ctor) (dotimes (i (* 2 all-argc)) (allocate-register nil)) (aload 0) (emit-invokespecial-init (class-file-superclass class-file) nil) (aload 0) (emit 'iconst_1) ;;true (emit-invokestatic +abcl-java-object+ "getInstance" (list +java-object+ :boolean) +lisp-object+) (astore all-argc) (box-arguments argument-types 1 all-argc) ;;Load the Lisp function from its static field (emit-getstatic (class-file-class class-file) field-name +lisp-object+) (if (<= all-argc call-registers-limit) (progn ;;Load the boxed this (aload all-argc) ;;Load each boxed argument (dotimes (i argc) (aload (+ i 1 all-argc)))) (error "execute(LispObject[]) is currently not supported")) (emit-call-execute all-argc) (emit 'return)))))) (finalize-class-file class-file) (write-class-file class-file stream) (finish-output stream) #+test-record-generated-class-file (let ((filename (merge-pathnames (format nil "~A.class" class-name)))) (with-open-file (f filename :direction :output :element-type '(signed-byte 8)) (write-sequence (java::list-from-jarray (sys::%get-output-stream-bytes stream)) f)) (format *standard-output* "~&Wrote class file ~A.~%" filename)) (values class-file method-implementation-fields))) (defun java::make-accessor-name (prefix name) (let ((initial (char-upcase (aref name 0))) (rest (subseq name 1))) (format nil "~A~A~A" prefix initial rest))) ;;This is missing from compiler-pass2.lisp. Probably this and similar functions should reside ;;in a dedicated file, independent from both runtime-class and compiler-pass2. (defun emit-invokespecial (class-name method-name arg-types return-type) (let* ((stack-effect (apply #'descriptor-stack-effect return-type arg-types)) (index (pool-add-method-ref *pool* class-name method-name (cons return-type arg-types))) (instruction (apply #'%emit 'invokespecial (u2 index)))) (declare (type (signed-byte 8) stack-effect)) (setf (instruction-stack instruction) (1- stack-effect)))) (defun java::canonicalize-java-type (type) (cond ((stringp type) (make-jvm-class-name type)) ((keywordp type) type) (t (error "Unrecognized Java type: ~A" type)))) (defun java::emit-unbox-and-return (return-type) (cond ((eq return-type :void) (emit 'pop) (emit 'return)) ((eq return-type :int) (emit-invokevirtual +lisp-object+ "intValue" nil :int) (emit 'ireturn)) ((eq return-type :boolean) (emit-invokevirtual +lisp-object+ "getBooleanValue" nil :boolean) (emit 'ireturn)) ((jvm-class-name-p return-type) (emit 'ldc_w (pool-class return-type)) (emit-invokevirtual +lisp-object+ "javaInstance" (list +java-class+) +java-object+) (emit-checkcast return-type) (emit 'areturn)) (t (error "Unsupported return type: ~A" return-type)))) (defun java::runtime-class-add-methods (class-file methods) (let (method-implementation-fields) (dolist (method methods) (destructuring-bind (name return-type argument-types function &key (modifiers '(:public)) annotations override) method (let* ((argument-types (mapcar #'java::canonicalize-java-type argument-types)) (argc (length argument-types)) (return-type (java::canonicalize-java-type return-type)) (jmethod (make-jvm-method name return-type argument-types :flags modifiers)) (field-name (string (gensym name))) (staticp (member :static modifiers)) (offset (if staticp 0 1)) (all-argc (+ argc offset))) (class-add-method class-file jmethod) (let ((field (make-field field-name +lisp-object+ :flags '(:public :static)))) (class-add-field class-file field) (push (cons field-name function) method-implementation-fields)) (when annotations (method-add-attribute jmethod (make-runtime-visible-annotations-attribute :list (mapcar #'parse-annotation annotations)))) (with-code-to-method (class-file jmethod) ;;Allocate registers (2 * argc to load and store arguments + 2 to box "this") (dotimes (i (* 2 all-argc)) (allocate-register nil)) (unless staticp ;;Box "this" (to be passed as the first argument to the Lisp function) (aload 0) (emit 'iconst_1) ;;true (emit-invokestatic +abcl-java-object+ "getInstance" (list +java-object+ :boolean) +lisp-object+) (astore all-argc)) (box-arguments argument-types offset all-argc) ;;Load the Lisp function from its static field (emit-getstatic (class-file-class class-file) field-name +lisp-object+) (if (<= all-argc call-registers-limit) (progn ;;Load the boxed this (unless staticp (aload all-argc)) ;;Load each boxed argument (dotimes (i argc) (aload (+ i 1 all-argc)))) (error "execute(LispObject[]) is currently not supported")) (emit-call-execute all-argc) (java::emit-unbox-and-return return-type)) (cond ((eq override t) (let ((super-method (make-jvm-method (format nil "super$~A" name) return-type argument-types :flags modifiers))) (class-add-method class-file super-method) (with-code-to-method (class-file super-method) (dotimes (i (1+ (length argument-types))) (allocate-register nil)) (aload 0) (loop :for arg-type :in argument-types :for i :from 1 :do (progn (cond ((keywordp arg-type) (error "Unsupported arg-type: ~A" arg-type)) ((eq arg-type :int) :todo) (t (aload i))))) (emit-invokespecial (class-file-superclass class-file) name argument-types return-type) ;(emit 'pop) (cond ((eq return-type :void) (emit 'return)) ((eq return-type :int) (emit 'ireturn)) ((eq return-type :boolean) (emit 'ireturn)) ((jvm-class-name-p return-type) (emit 'areturn)) (t (error "Unsupported return type: ~A" return-type)))))))))) method-implementation-fields)) (defun java::runtime-class-add-fields (class-file fields) (dolist (field-spec fields) (destructuring-bind (name type &key (modifiers '(:public)) annotations (getter nil getter-p) (setter nil setter-p) (property (and (not getter-p) (not setter-p)))) field-spec (let* ((type (if (keywordp type) type (make-jvm-class-name type))) (field (make-field name type :flags modifiers))) (when (member :static modifiers) (setf property nil getter nil setter nil)) (when annotations (field-add-attribute field (make-runtime-visible-annotations-attribute :list (mapcar #'parse-annotation annotations)))) (class-add-field class-file field) (when (or getter property) (unless (stringp getter) (setf getter (java::make-accessor-name "get" (if (stringp property) property name)))) (let ((jmethod (make-jvm-method getter type nil :flags '(:public)))) (class-add-method class-file jmethod) (with-code-to-method (class-file jmethod) (aload 0) (emit-getfield (class-file-class class-file) name type) (cond ((jvm-class-name-p type) (emit 'areturn)) ((eq type :int) (emit 'ireturn)) (t (error "Unsupported getter return type: ~A" type)))))) (when (or setter property) (unless (stringp setter) (setf setter (java::make-accessor-name "set" (if (stringp property) property name)))) (let ((jmethod (make-jvm-method setter :void (list type) :flags '(:public)))) (class-add-method class-file jmethod) (with-code-to-method (class-file jmethod) (aload 0) (cond ((jvm-class-name-p type) (aload 1)) ((eq type :int) (emit 'iload 1)) (t (error "Unsupported setter parameter type: ~A" type))) (emit-putfield (class-file-class class-file) name type) (emit 'return)))))))) (defmacro java:define-java-class () :todo) (defun parse-annotation (annotation) (when (annotation-p annotation) (return-from parse-annotation annotation)) (destructuring-bind (class &rest elements) (if (listp annotation) annotation (list annotation)) (let (actual-elements) (dolist (elem elements) (push (parse-annotation-element elem) actual-elements)) (make-annotation :type class :elements (nreverse actual-elements))))) (defun parse-annotation-element (elem) (cond ((annotation-element-p elem) elem) ((atom elem) (make-primitive-or-string-annotation-element :name nil :value elem)) ((keywordp (car elem)) (parse-annotation-element `("value" ,@elem))) (t (destructuring-bind (name &key value enum annotation) elem (cond (enum (make-enum-value-annotation-element :name name :type enum :value value)) (annotation (make-annotation-value-annotation-element :name name :value (parse-annotation annotation))) ((listp value) (make-array-annotation-element :name name :values (mapcar #'parse-annotation-element value))) (t (make-primitive-or-string-annotation-element :name name :value value))))))) ;;TODO: ;; - Returning nil as null is broken ;; - Function calls with 8+ args ;; - super method invocation. Idea: generate companion methods super_... to use with plain jcall. Add a flag per method to optionally disable this when not needed. ;; - Constructors ;; - optional accessors (CLOS methods) for properties? #+example (java:jnew-runtime-class "Foo" :interfaces (list "java.lang.Comparable") :fields (list '("someField" "java.lang.String") '("anotherField" "java.lang.Object" :getter t)) :methods (list (list "foo" :void '("java.lang.Object") (lambda (this that) (print (list this that))) :annotations (list "java.lang.Deprecated" '("java.lang.annotation.Retention" (:enum "java.lang.annotation.RetentionPolicy" :value "RUNTIME")) '("javax.xml.bind.annotation.XmlAttribute" ("required" :value t)) '("com.manydesigns.portofino.system.model.users.annotations.RequiresPermissions" ("level" :enum "com.manydesigns.portofino.model.pages.AccessLevel" :value "EDIT") ("permissions" :value ("foo" "bar"))))) (list "bar" :int '("java.lang.Object") (lambda (this that) (print (list this that)) 23)))) (provide "RUNTIME-CLASS") abcl-src-1.9.0/src/org/armedbear/lisp/scripting/AbclScriptEngine.java0100644 0000000 0000000 00000025641 14202767264 024250 0ustar000000000 0000000 /* * AbclScriptEngine.java * * Copyright (C) 2008 Alessio Stalla * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.armedbear.lisp.scripting; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringWriter; import java.util.Map; import javax.script.*; import org.armedbear.lisp.*; public class AbclScriptEngine extends AbstractScriptEngine implements Invocable, Compilable { private Interpreter interpreter; /** * The function used to evaluate a string of code. */ private Function evalScript; /** * The function used to evaluate a Lisp function. */ private Function evalFunction; /** * The function used to compile Lisp code. */ private Function compileScript; /** * The function used to evaluate a compiled script. */ Function evalCompiledScript; protected AbclScriptEngine() { interpreter = Interpreter.getInstance(); if(interpreter == null) { interpreter = Interpreter.createInstance(); } loadFromClasspath("/org/armedbear/lisp/scripting/lisp/packages.lisp"); loadFromClasspath("/org/armedbear/lisp/scripting/lisp/abcl-script.lisp"); loadFromClasspath("/org/armedbear/lisp/scripting/lisp/config.lisp"); if(getClass().getResource("/abcl-script-config.lisp") != null) { //TODO: find a way to log this if wanted //System.out.println("ABCL: loading configuration from " + getClass().getResource("/abcl-script-config.lisp")); loadFromClasspath("/abcl-script-config.lisp"); } ((Function) interpreter.eval("#'abcl-script:configure-abcl")).execute(new JavaObject(this)); //System.out.println("ABCL: configured"); evalScript = (Function) this.findSymbol("EVAL-SCRIPT", "ABCL-SCRIPT").getSymbolFunction(); compileScript = (Function) this.findSymbol("COMPILE-SCRIPT", "ABCL-SCRIPT").getSymbolFunction(); evalCompiledScript = (Function) this.findSymbol("EVAL-COMPILED-SCRIPT", "ABCL-SCRIPT").getSymbolFunction(); evalFunction = (Function) this.findSymbol("EVAL-FUNCTION", "ABCL-SCRIPT").getSymbolFunction(); } public Interpreter getInterpreter() { return interpreter; } public void setStandardInput(InputStream stream, LispThread thread) { thread.setSpecialVariable(Symbol.STANDARD_INPUT, new Stream(Symbol.SYSTEM_STREAM, stream, Symbol.CHARACTER, true)); } public void setStandardInput(InputStream stream) { setStandardInput(stream, LispThread.currentThread()); } public void setInterpreter(Interpreter interpreter) { this.interpreter = interpreter; } public static String escape(String s) { StringBuffer b = new StringBuffer(); int len = s.length(); char c; for (int i = 0; i < len; ++i) { c = s.charAt(i); if (c == '\\' || c == '"') { b.append('\\'); } b.append(c); } return b.toString(); } public LispObject loadFromClasspath(String classpathResource) { InputStream istream = getClass().getResourceAsStream(classpathResource); Stream stream = new Stream(Symbol.SYSTEM_STREAM, istream, Symbol.CHARACTER); return load(stream); } public LispObject load(Stream stream) { Symbol keyword_verbose = Lisp.internKeyword("VERBOSE"); Symbol keyword_print = Lisp.internKeyword("PRINT"); /* * load (filespec &key (verbose *load-verbose*) (print *load-print*) * (if-does-not-exist t) (external-format :default) */ return Symbol.LOAD.getSymbolFunction().execute (new LispObject[] { stream, keyword_verbose, Lisp.NIL, keyword_print, Lisp.NIL, Keyword.IF_DOES_NOT_EXIST, Lisp.T, Keyword.EXTERNAL_FORMAT, Keyword.DEFAULT }); } public LispObject load(String filespec) { return load(filespec, true); } public LispObject load(String filespec, boolean compileIfNecessary) { if (isCompiled(filespec) || !compileIfNecessary) { return interpreter.eval("(load \"" + escape(filespec) + "\")"); } else { return compileAndLoad(filespec); } } public static boolean isCompiled(String filespec) { final String compiledExt = "." + Lisp._COMPILE_FILE_TYPE_.symbolValue().getStringValue(); if (filespec.endsWith(compiledExt)) { return true; } File source; File compiled; if (filespec.endsWith(".lisp")) { source = new File(filespec); compiled = new File(filespec.substring(0, filespec.length() - 5) + compiledExt); } else { source = new File(filespec + ".lisp"); compiled = new File(filespec + compiledExt); } if (!source.exists()) { throw new IllegalArgumentException("The source file " + filespec + " cannot be found"); } return compiled.exists() && compiled.lastModified() >= source.lastModified(); } public LispObject compileFile(String filespec) { return interpreter.eval("(compile-file \"" + escape(filespec) + "\")"); } public LispObject compileAndLoad(String filespec) { return interpreter.eval("(load (compile-file \"" + escape(filespec) + "\"))"); } public static boolean functionp(LispObject obj) { return obj instanceof Function; } public JavaObject jsetq(String symbol, Object value) { Symbol s = findSymbol(symbol); JavaObject jo; if (value instanceof JavaObject) { jo = (JavaObject) value; } else { jo = new JavaObject(value); } s.setSymbolValue(jo); return jo; } public Symbol findSymbol(String name, String pkg) { Cons values = (Cons) (interpreter.eval("(cl:multiple-value-list (find-symbol (symbol-name '#:" + escape(name) + ")" + (pkg == null ? "" : " :" + escape(pkg)) + "))")); if(values.cadr() == Lisp.NIL) { return null; } else { return (Symbol) values.car(); } } public Symbol findSymbol(String name) { //Known bug: doesn't handle escaped ':' e.g. |a:b| int i = name.indexOf(':'); if(i < 0) { return findSymbol(name, null); } else { if((i < name.length() - 1) && (name.charAt(i + 1) == ':')) { return findSymbol(name.substring(i + 2), name.substring(0, i)); } else { return findSymbol(name.substring(i + 1), name.substring(0, i)); } } } public Function findFunction(String name) { return (Function) interpreter.eval("#'" + name); } @Override public Bindings createBindings() { return new SimpleBindings(); } private static LispObject makeBindings(Bindings bindings) { if (bindings == null || bindings.size() == 0) { return Lisp.NIL; } LispObject[] argList = new LispObject[bindings.size()]; int i = 0; for (Map.Entry entry : bindings.entrySet()) { argList[i++] = Symbol.CONS.execute(new SimpleString(entry.getKey()), JavaObject.getInstance(entry.getValue(), true)); } return Symbol.LIST.getSymbolFunction().execute(argList); } Object eval(Function evaluator, LispObject code, ScriptContext ctx) throws ScriptException { LispObject retVal = null; Stream outStream = new Stream(Symbol.SYSTEM_STREAM, ctx.getWriter()); Stream inStream = new Stream(Symbol.SYSTEM_STREAM, ctx.getReader()); retVal = evaluator.execute(makeBindings(ctx.getBindings(ScriptContext.GLOBAL_SCOPE)), makeBindings(ctx.getBindings(ScriptContext.ENGINE_SCOPE)), inStream, outStream, code, new JavaObject(ctx)); return retVal.javaInstance(); } @Override public Object eval(String code, ScriptContext ctx) throws ScriptException { return eval(evalScript, new SimpleString(code), ctx); } private static String toString(Reader reader) throws IOException { StringWriter w = new StringWriter(); int i; i = reader.read(); while (i != -1) { w.write(i); i = reader.read(); } return w.toString(); } @Override public Object eval(Reader code, ScriptContext ctx) throws ScriptException { try { return eval(toString(code), ctx); } catch (IOException e) { return new ScriptException(e); } } @Override public ScriptEngineFactory getFactory() { return new AbclScriptEngineFactory(); } public T getInterface(Class clasz) { try { return getInterface(eval("(cl:find-package '#:ABCL-SCRIPT-USER)"), clasz); } catch (ScriptException e) { throw new Error(e); } } @SuppressWarnings("unchecked") public T getInterface(Object thiz, Class clasz) { Symbol s = findSymbol("jmake-proxy", "JAVA"); JavaObject iface = new JavaObject(clasz); return (T) ((JavaObject) s.execute(iface, (LispObject) thiz)).javaInstance(); } public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException { Symbol s; if(name.indexOf(':') >= 0) { s = findSymbol(name); } else { s = findSymbol(name, "ABCL-SCRIPT-USER"); } if(s != null) { LispObject f = s.getSymbolFunction(); if(f != null && f instanceof Function) { LispObject functionAndArgs = Lisp.NIL.push(f); for(int i = 0; i < args.length; ++i) { functionAndArgs = functionAndArgs.push(JavaObject.getInstance(args[i], true)); } functionAndArgs = functionAndArgs.reverse(); return eval(evalFunction, functionAndArgs, getContext()); } else { throw new NoSuchMethodException(name); } } else { throw new NoSuchMethodException(name); } } public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException { throw new UnsupportedOperationException("Common Lisp does not have methods in the Java sense. Use invokeFunction instead."); } public class AbclCompiledScript extends CompiledScript { private LispObject function; public AbclCompiledScript(LispObject function) { this.function = function; } @Override public Object eval(ScriptContext context) throws ScriptException { return AbclScriptEngine.this.eval(evalCompiledScript, function, context); } @Override public ScriptEngine getEngine() { return AbclScriptEngine.this; } } @Override public CompiledScript compile(String script) throws ScriptException { try { Function f = (Function) compileScript.execute(new SimpleString(script)); return new AbclCompiledScript(f); } catch(ClassCastException e) { throw new ScriptException(e); } } @Override public CompiledScript compile(Reader script) throws ScriptException { try { return compile(toString(script)); } catch (IOException e) { throw new ScriptException(e); } } } abcl-src-1.9.0/src/org/armedbear/lisp/scripting/AbclScriptEngineFactory.java0100644 0000000 0000000 00000006166 14202767264 025601 0ustar000000000 0000000 /* * AbclScriptEngineFactory.java * * Copyright (C) 2008 Alessio Stalla * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.armedbear.lisp.scripting; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; public class AbclScriptEngineFactory implements ScriptEngineFactory { private static AbclScriptEngine THE_ONLY_ONE_ENGINE = null; public String getEngineName() { return "ABCL Script"; } public String getEngineVersion() { return "0.1"; } public List getExtensions() { List extensions = new ArrayList(1); extensions.add("lisp"); return Collections.unmodifiableList(extensions); } public String getLanguageName() { return "ANSI Common Lisp"; } public String getLanguageVersion() { return "ANSI X3.226:1994"; } public static String escape(String raw) { StringBuilder sb = new StringBuilder(); int len = raw.length(); char c; for(int i = 0; i < len; ++i) { c = raw.charAt(i); if(c != '"') { sb.append(c); } else { sb.append("\\\""); } } return sb.toString(); } public String getMethodCallSyntax(String obj, String method, String... args) { StringBuilder sb = new StringBuilder(); sb.append("(jcall \""); sb.append(method); sb.append("\" "); sb.append(obj); for(String arg : args) { sb.append(" "); sb.append(arg); } sb.append(")"); return sb.toString(); } public List getMimeTypes() { return Collections.unmodifiableList(new ArrayList()); } public List getNames() { List names = new ArrayList(1); names.add("ABCL"); names.add("cl"); names.add("Lisp"); names.add("Common Lisp"); return Collections.unmodifiableList(names); } public String getOutputStatement(String str) { return "(cl:print \"" + str + "\")"; } public Object getParameter(String key) { // TODO Auto-generated method stub return null; } public String getProgram(String... statements) { StringBuilder sb = new StringBuilder(); sb.append("(cl:progn"); for(String stmt : statements) { sb.append("\n\t"); sb.append(stmt); } sb.append(")"); return sb.toString(); } public synchronized ScriptEngine getScriptEngine() { if (THE_ONLY_ONE_ENGINE == null) { THE_ONLY_ONE_ENGINE = new AbclScriptEngine(); } return THE_ONLY_ONE_ENGINE; } } abcl-src-1.9.0/src/org/armedbear/lisp/scripting/lisp/abcl-script.lisp0100644 0000000 0000000 00000013750 14202767264 024272 0ustar000000000 0000000 ;;; abcl-script.lisp ;;; ;;; Copyright (C) 2008 Alessio Stalla ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :abcl-script) (defconstant +global-scope+ (jfield "javax.script.ScriptContext" "GLOBAL_SCOPE")) (defconstant +engine-scope+ (jfield "javax.script.ScriptContext" "ENGINE_SCOPE")) (defconstant +put-binding+ (jmethod "javax.script.Bindings" "put" "java.lang.String" "java.lang.Object")) (defconstant +get-bindings+ (jmethod "javax.script.ScriptContext" "getBindings" "int")) (defun generate-bindings (bindings) (let ((*package* (find-package :abcl-script-user))) (mapcar (lambda (binding) (list (read-from-string (car binding)) (cdr binding))) bindings))) (defun generate-special-declarations (bindings) (let ((*package* (find-package :abcl-script-user))) `(declare (special ,@(mapcar (lambda (binding) (read-from-string (car binding))) bindings))))) (defun generate-java-bindings (bindings-list actual-bindings java-bindings) (loop :for binding :in actual-bindings :for jbinding :in bindings-list :collect `(jcall +put-binding+ ,java-bindings ,(car jbinding) ,(car binding)))) (defmacro eval-in-script-context ((global-bindings engine-bindings stdin stdout script-context) body) "Sets up a context in which to evaluate a piece of code coming from Java through the JSR-223 methods." (let ((actual-global-bindings (gensym)) (actual-engine-bindings (gensym))) `(let ((*package* (find-package :abcl-script-user)) (*standard-input* ,stdin) (*standard-output* ,stdout) (,actual-global-bindings (generate-bindings ,global-bindings)) (,actual-engine-bindings (generate-bindings ,engine-bindings))) (eval `(let (,@,actual-global-bindings) (let (,@,actual-engine-bindings) ,(generate-special-declarations ,global-bindings) ,(generate-special-declarations ,engine-bindings) (prog1 (progn ,@,body) (finish-output *standard-output*) ,@(generate-java-bindings ,global-bindings ,actual-global-bindings (jcall +get-bindings+ ,script-context +global-scope+)) ,@(generate-java-bindings ,engine-bindings ,actual-engine-bindings (jcall +get-bindings+ ,script-context +engine-scope+))))))))) (defun eval-function (global-bindings engine-bindings stdin stdout function-and-args script-context) (eval-in-script-context (global-bindings engine-bindings stdin stdout script-context) `((funcall ,@(mapcar (lambda (arg) `(quote ,arg)) function-and-args))))) (defun eval-script (global-bindings engine-bindings stdin stdout code-string script-context) (eval-in-script-context (global-bindings engine-bindings stdin stdout script-context) `((with-input-from-string (str ,code-string) (sys::load-returning-last-result str))))) (defun eval-compiled-script (global-bindings engine-bindings stdin stdout function script-context) (eval-in-script-context (global-bindings engine-bindings stdin stdout script-context) `((funcall ,function)))) (defun compile-script (code-string) (let* ((tmp-file (jstatic (jmethod "java.io.File" "createTempFile" "java.lang.String" "java.lang.String") nil "abcl-src-file-" ".lisp")) (tmp-file-path (jcall (jmethod "java.io.File" "getAbsolutePath") tmp-file))) (jcall (jmethod "java.io.File" "deleteOnExit") tmp-file) ;to be really-really-really sure... (unwind-protect (progn (with-open-file (stream tmp-file-path :direction :output) (princ "(in-package :abcl-script-user)" stream) (princ code-string stream) (finish-output stream)) (let ((compiled-file (compile-file tmp-file-path))) (jcall (jmethod "java.io.File" "deleteOnExit") (jnew (jconstructor "java.io.File" "java.lang.String") (namestring compiled-file))) (lambda () (let ((*package* (find-package :abcl-script-user))) (sys::load-returning-last-result compiled-file))))) (delete-file tmp-file-path)))) ;;Java interface implementation - TODO (defvar *interface-implementation-map* (make-hash-table :test #'equal)) (defun find-java-interface-implementation (interface) (gethash interface *interface-implementation-map*)) (defun register-java-interface-implementation (interface implementation &optional lisp-this) (setf (gethash interface *interface-implementation-map*) (jmake-proxy interface implementation lisp-this))) (defun remove-java-interface-implementation (interface) (remhash interface *interface-implementation-map*)) ;Let's load it so asdf package is already defined when loading config.lisp (require 'asdf) abcl-src-1.9.0/src/org/armedbear/lisp/scripting/lisp/config.lisp0100644 0000000 0000000 00000004347 14202767264 023336 0ustar000000000 0000000 ;;; config.lisp ;;; ;;; Copyright (C) 2008 Alessio Stalla ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package :abcl-script) (defparameter *launch-swank-at-startup* nil) (defparameter *swank-dir* nil) (defparameter *swank-port* 4005) (defparameter *use-throwing-debugger* t) (defun configure-abcl (abcl-script-engine) (when *use-throwing-debugger* (setf *debugger-hook* #'sys::%debugger-hook-function)) (when *launch-swank-at-startup* (unless *swank-dir* (error "Swank directory not specified, please set *swank-dir*")) (pushnew *swank-dir* asdf:*central-registry* :test #'equal) (asdf:oos 'asdf:load-op :swank) (threads:make-thread (lambda () (funcall (find-symbol (symbol-name '#:create-server) :swank) :port *swank-port*)) :name "ABCL script - Swank thread"))) abcl-src-1.9.0/src/org/armedbear/lisp/scripting/lisp/packages.lisp0100644 0000000 0000000 00000004073 14202767264 023643 0ustar000000000 0000000 ;;; packages.lisp ;;; ;;; Copyright (C) 2008 Alessio Stalla ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (defpackage :abcl-script (:use :cl :java) (:export #:compile-script #:*compile-using-temp-files* #:configure-abcl #:eval-compiled-script #:eval-function #:eval-script #:define-java-interface-implementation #:find-java-interface-implementation #:*launch-swank-at-startup* #:register-java-interface-implementation #:remove-java-interface-implementation #:+standard-debugger-hook+ #:*swank-dir* #:*swank-port* #:*use-throwing-debugger*)) (defpackage :abcl-script-user (:use :cl :ext :java :abcl-script)) abcl-src-1.9.0/src/org/armedbear/lisp/search.lisp0100644 0000000 0000000 00000011464 14223403213 020343 0ustar000000000 0000000 ;;; search.lisp ;;; ;;; Copyright (C) 2003-2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (require "EXTENSIBLE-SEQUENCES-BASE") (export '(simple-search)) ;; From CMUCL. (eval-when (:compile-toplevel :execute) (defmacro compare-elements (elt1 elt2) `(if test-not (if (funcall test-not (apply-key key ,elt1) (apply-key key ,elt2)) (return nil) t) (if (not (funcall test (apply-key key ,elt1) (apply-key key ,elt2))) (return nil) t))) (defmacro search-compare-list-list (main sub) `(do ((main ,main (cdr main)) (jndex start1 (1+ jndex)) (sub (nthcdr start1 ,sub) (cdr sub))) ((or (null main) (null sub) (= end1 jndex)) t) (compare-elements (car sub) (car main)))) (defmacro search-compare-list-vector (main sub) `(do ((main ,main (cdr main)) (index start1 (1+ index))) ((or (null main) (= index end1)) t) (compare-elements (aref ,sub index) (car main)))) (defmacro search-compare-vector-list (main sub index) `(do ((sub (nthcdr start1 ,sub) (cdr sub)) (jndex start1 (1+ jndex)) (index ,index (1+ index))) ((or (= end1 jndex) (null sub)) t) (compare-elements (car sub) (aref ,main index)))) (defmacro search-compare-vector-vector (main sub index) `(do ((index ,index (1+ index)) (sub-index start1 (1+ sub-index))) ((= sub-index end1) t) (compare-elements (aref ,sub sub-index) (aref ,main index)))) (defmacro search-compare (main-type main sub index) (if (eq main-type 'list) `(if (listp ,sub) (search-compare-list-list ,main ,sub) (search-compare-list-vector ,main ,sub)) `(if (listp ,sub) (search-compare-vector-list ,main ,sub ,index) (search-compare-vector-vector ,main ,sub ,index)))) (defmacro list-search (main sub) `(do ((main (nthcdr start2 ,main) (cdr main)) (index2 start2 (1+ index2)) (terminus (- end2 (- end1 start1))) (last-match ())) ((> index2 terminus) last-match) (if (search-compare list main ,sub index2) (if from-end (setq last-match index2) (return index2))))) (defmacro vector-search (main sub) `(do ((index2 start2 (1+ index2)) (terminus (- end2 (- end1 start1))) (last-match ())) ((> index2 terminus) last-match) (if (search-compare vector ,main ,sub index2) (if from-end (setq last-match index2) (return index2))))) ) ; eval-when (defun search (sequence1 sequence2 &rest args &key from-end (test #'eql) test-not (start1 0) end1 (start2 0) end2 key) (let ((end1 (or end1 (length sequence1))) (end2 (or end2 (length sequence2)))) (when key (setq key (coerce-to-function key))) (sequence::seq-dispatch sequence2 (list-search sequence2 sequence1) (vector-search sequence2 sequence1) (apply #'sequence:search sequence1 sequence2 args)))) (defun simple-search (sequence1 sequence2) (cond ((and (stringp sequence1) (stringp sequence2)) (simple-string-search sequence1 sequence2)) ((vectorp sequence2) (simple-vector-search sequence1 sequence2)) (t (search sequence1 sequence2 :from-end nil)))) abcl-src-1.9.0/src/org/armedbear/lisp/sequences.lisp0100644 0000000 0000000 00000005476 14223403213 021077 0ustar000000000 0000000 ;;; sequences.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;(require "EXTENSIBLE-SEQUENCES-BASE") (in-package #:system) (defmacro type-specifier-atom (type) `(if (atom ,type) ,type (car ,type))) (defun make-sequence-of-type (type length) (case (type-specifier-atom type) (list (make-list length)) ((bit-vector simple-bit-vector) (make-array length :element-type 'bit)) ((simple-base-string simple-string string) (make-string length)) ((simple-vector vector) (if (cadr type) (make-array length :element-type (cadr type)) (make-array length))) (nil-vector (make-array length :element-type nil)) (simple-array (if (cadr type) (make-array length :element-type (cadr type)) (make-array length))) (t (error "MAKE-SEQUENCE-OF-TYPE: unsupported case ~S" type)))) (defmacro make-sequence-like (sequence length) "Return a sequence of the same type as SEQUENCE and the given LENGTH." ;;Can't use gensyms: stack overflow in boot.lisp `(let ((msl-seq-tmp-var ,sequence) (msl-len-tmp-var ,length)) (sequence::seq-dispatch msl-seq-tmp-var (make-sequence-of-type (type-of msl-seq-tmp-var) msl-len-tmp-var) (make-sequence-of-type (type-of msl-seq-tmp-var) msl-len-tmp-var) (sequence::make-sequence-like msl-seq-tmp-var msl-len-tmp-var)))) abcl-src-1.9.0/src/org/armedbear/lisp/server_socket_close.java0100644 0000000 0000000 00000004344 14223403213 023112 0ustar000000000 0000000 /* * server_socket_close.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.ServerSocket; // ### %server-socket-close public final class server_socket_close extends Primitive { private server_socket_close() { super("%server-socket-close", PACKAGE_SYS, false, "socket"); } @Override public LispObject execute(LispObject first) { try { ServerSocket serverSocket = (ServerSocket) JavaObject.getObject(first); serverSocket.close(); return T; } catch (Exception e) { return error(new LispError(e.getMessage())); } } private static final Primitive SERVER_SOCKET_CLOSE = new server_socket_close(); } abcl-src-1.9.0/src/org/armedbear/lisp/setf.lisp0100644 0000000 0000000 00000021564 14202767264 020061 0ustar000000000 0000000 ;;; setf.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun get-setf-method-inverse (form inverse setf-function) (let ((new-var (gensym)) (vars nil) (vals nil)) (dolist (x (cdr form)) (push (gensym) vars) (push x vals)) (setq vals (nreverse vals)) (values vars vals (list new-var) (if setf-function `(,@inverse ,new-var ,@vars) (if (functionp (car inverse)) `(funcall ,@inverse ,@vars ,new-var) `(,@inverse ,@vars ,new-var))) `(,(car form) ,@vars)))) ;;; If a macro, expand one level and try again. If not, go for the ;;; SETF function. (defun expand-or-get-setf-inverse (form environment) (multiple-value-bind (expansion expanded) (macroexpand-1 form environment) (if expanded (get-setf-expansion expansion environment) (get-setf-method-inverse form `(funcall #'(setf ,(car form))) t)))) (defun get-setf-expansion (form &optional environment) (let (temp) (cond ((symbolp form) (multiple-value-bind (expansion expanded) (macroexpand-1 form environment) (if expanded (get-setf-expansion expansion environment) (let ((new-var (gensym))) (values nil nil (list new-var) `(setq ,form ,new-var) form))))) ((setq temp (get (car form) 'setf-inverse)) (get-setf-method-inverse form `(,temp) nil)) ((setq temp (get (car form) 'setf-expander)) (funcall temp form environment)) (t (expand-or-get-setf-inverse form environment))))) (defmacro setf (&rest args &environment environment) (let ((numargs (length args))) (cond ((= numargs 2) (let ((place (first args)) (value-form (second args))) (if (atom place) `(setq ,place ,value-form) (progn (multiple-value-bind (dummies vals store-vars setter getter) (get-setf-expansion place environment) (let ((inverse (get (car place) 'setf-inverse))) (if (and inverse (eq inverse (car setter))) (if (functionp inverse) `(funcall ,inverse ,@(cdr place) ,value-form) `(,inverse ,@(cdr place) ,value-form)) (if (or (null store-vars) (cdr store-vars)) `(let* (,@(mapcar #'list dummies vals)) (multiple-value-bind ,store-vars ,value-form ,setter)) `(let* (,@(mapcar #'list dummies vals) ,(list (car store-vars) value-form)) ,setter))))))))) ((oddp numargs) (error "Odd number of arguments to SETF.")) (t (do ((a args (cddr a)) (l nil)) ((null a) `(progn ,@(nreverse l))) (setq l (cons (list 'setf (car a) (cadr a)) l))))))) ;;; Redefined in define-modify-macro.lisp. (defmacro incf (place &optional (delta 1)) `(setf ,place (+ ,place ,delta))) ;;; Redefined in define-modify-macro.lisp. (defmacro decf (place &optional (delta 1)) `(setf ,place (- ,place ,delta))) ;; (defsetf subseq (sequence start &optional (end nil)) (v) ;; `(progn (replace ,sequence ,v :start1 ,start :end1 ,end) ;; ,v)) (defun %set-subseq (sequence start &rest rest) (let ((end nil) v) (ecase (length rest) (1 (setq v (car rest))) (2 (setq end (car rest) v (cadr rest)))) (progn (replace sequence v :start1 start :end1 end) v))) (defun %define-setf-macro (name expander inverse doc) (declare (ignore doc)) ; FIXME (when inverse (put name 'setf-inverse inverse)) (when expander (put name 'setf-expander expander)) name) (defmacro defsetf (access-function update-function) `(eval-when (:load-toplevel :compile-toplevel :execute) (put ',access-function 'setf-inverse ',update-function))) (defun %set-caar (x v) (set-car (car x) v)) (defun %set-cadr (x v) (set-car (cdr x) v)) (defun %set-cdar (x v) (set-cdr (car x) v)) (defun %set-cddr (x v) (set-cdr (cdr x) v)) (defun %set-caaar (x v) (set-car (caar x) v)) (defun %set-cadar (x v) (set-car (cdar x) v)) (defun %set-cdaar (x v) (set-cdr (caar x) v)) (defun %set-cddar (x v) (set-cdr (cdar x) v)) (defun %set-caadr (x v) (set-car (cadr x) v)) (defun %set-caddr (x v) (set-car (cddr x) v)) (defun %set-cdadr (x v) (set-cdr (cadr x) v)) (defun %set-cdddr (x v) (set-cdr (cddr x) v)) (defun %set-caaaar (x v) (set-car (caaar x) v)) (defun %set-cadaar (x v) (set-car (cdaar x) v)) (defun %set-cdaaar (x v) (set-cdr (caaar x) v)) (defun %set-cddaar (x v) (set-cdr (cdaar x) v)) (defun %set-caadar (x v) (set-car (cadar x) v)) (defun %set-caddar (x v) (set-car (cddar x) v)) (defun %set-cdadar (x v) (set-cdr (cadar x) v)) (defun %set-cdddar (x v) (set-cdr (cddar x) v)) (defun %set-caaadr (x v) (set-car (caadr x) v)) (defun %set-cadadr (x v) (set-car (cdadr x) v)) (defun %set-cdaadr (x v) (set-cdr (caadr x) v)) (defun %set-cddadr (x v) (set-cdr (cdadr x) v)) (defun %set-caaddr (x v) (set-car (caddr x) v)) (defun %set-cadddr (x v) (set-car (cdddr x) v)) (defun %set-cdaddr (x v) (set-cdr (caddr x) v)) (defun %set-cddddr (x v) (set-cdr (cdddr x) v)) (defsetf car set-car) (defsetf cdr set-cdr) (defsetf caar %set-caar) (defsetf cadr %set-cadr) (defsetf cdar %set-cdar) (defsetf cddr %set-cddr) (defsetf caaar %set-caaar) (defsetf cadar %set-cadar) (defsetf cdaar %set-cdaar) (defsetf cddar %set-cddar) (defsetf caadr %set-caadr) (defsetf caddr %set-caddr) (defsetf cdadr %set-cdadr) (defsetf cdddr %set-cdddr) (defsetf caaaar %set-caaaar) (defsetf cadaar %set-cadaar) (defsetf cdaaar %set-cdaaar) (defsetf cddaar %set-cddaar) (defsetf caadar %set-caadar) (defsetf caddar %set-caddar) (defsetf cdadar %set-cdadar) (defsetf cdddar %set-cdddar) (defsetf caaadr %set-caaadr) (defsetf cadadr %set-cadadr) (defsetf cdaadr %set-cdaadr) (defsetf cddadr %set-cddadr) (defsetf caaddr %set-caaddr) (defsetf cadddr %set-cadddr) (defsetf cdaddr %set-cdaddr) (defsetf cddddr %set-cddddr) (defsetf first set-car) (defsetf second %set-cadr) (defsetf third %set-caddr) (defsetf fourth %set-cadddr) (defun %set-fifth (x v) (set-car (cddddr x) v)) (defsetf fifth %set-fifth) (defun %set-sixth (x v) (set-car (cdr (cddddr x)) v)) (defsetf sixth %set-sixth) (defun %set-seventh (x v) (set-car (cddr (cddddr x)) v)) (defsetf seventh %set-seventh) (defun %set-eighth (x v) (set-car (cdddr (cddddr x)) v)) (defsetf eighth %set-eighth) (defun %set-ninth (x v) (set-car (cddddr (cddddr x)) v)) (defsetf ninth %set-ninth) (defun %set-tenth (x v) (set-car (cdr (cddddr (cddddr x))) v)) (defsetf tenth %set-tenth) (defsetf rest set-cdr) ;;Redefined in extensible-sequences-base.lisp (defsetf elt %set-elt) (defsetf nth %set-nth) (defsetf svref svset) (defsetf fill-pointer %set-fill-pointer) (defsetf subseq %set-subseq) (defsetf symbol-value set) (defsetf symbol-function %set-symbol-function) (defsetf symbol-plist %set-symbol-plist) (defsetf get put) (defsetf gethash puthash) (defsetf char set-char) (defsetf schar set-schar) (defsetf logical-pathname-translations %set-logical-pathname-translations) (defsetf readtable-case %set-readtable-case) (defsetf function-info %set-function-info) (defsetf stream-external-format %set-stream-external-format) (defsetf structure-ref structure-set) abcl-src-1.9.0/src/org/armedbear/lisp/sets.lisp0100644 0000000 0000000 00000017430 14223403213 020053 0ustar000000000 0000000 ;;; sets.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) ;;; From CMUCL. (defmacro with-set-keys (funcall) `(cond (notp ,(append funcall '(:key key :test-not test-not))) (t ,(append funcall '(:key key :test test))))) (defun union (list1 list2 &key key (test #'eql testp) (test-not nil notp)) (require-type list2 'list) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (when key (setq key (coerce-to-function key))) (let ((res list2)) (dolist (elt list1) (unless (with-set-keys (member (funcall-key key elt) list2)) (push elt res))) res)) (defmacro steve-splice (source destination) `(let ((temp ,source)) (setf ,source (cdr ,source) (cdr temp) ,destination ,destination temp))) (defun nunion (list1 list2 &key key (test #'eql testp) (test-not nil notp)) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (when key (setq key (coerce-to-function key))) (let ((res list2) (list1 list1)) (do () ((endp list1)) (if (not (with-set-keys (member (funcall-key key (car list1)) list2))) (steve-splice list1 res) (setf list1 (cdr list1)))) res)) (defun intersection (list1 list2 &key key (test #'eql testp) (test-not nil notp)) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (when key (setq key (coerce-to-function key))) (let ((res nil)) (dolist (elt list1) (if (with-set-keys (member (funcall-key key elt) list2)) (push elt res))) res)) (defun nintersection (list1 list2 &key key (test #'eql testp) (test-not nil notp)) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (when key (setq key (coerce-to-function key))) (let ((res nil) (list1 list1)) (do () ((endp list1)) (if (with-set-keys (member (funcall-key key (car list1)) list2)) (steve-splice list1 res) (setq list1 (cdr list1)))) res)) (defun set-difference (list1 list2 &key key (test #'eql testp) (test-not nil notp)) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (when key (setq key (coerce-to-function key))) (if (null list2) list1 (let ((res nil)) (dolist (elt list1) (if (not (with-set-keys (member (funcall-key key elt) list2))) (push elt res))) res))) (defun nset-difference (list1 list2 &key key (test #'eql testp) (test-not nil notp)) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (when key (setq key (coerce-to-function key))) (let ((res nil) (list1 list1)) (do () ((endp list1)) (if (not (with-set-keys (member (funcall-key key (car list1)) list2))) (steve-splice list1 res) (setq list1 (cdr list1)))) res)) (defun set-exclusive-or (list1 list2 &key key (test #'eql testp) (test-not nil notp)) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (when key (setq key (coerce-to-function key))) (let ((result nil) (key (when key (coerce key 'function))) (test (coerce test 'function)) (test-not (if test-not (coerce test-not 'function) #'eql))) (dolist (elt list1) (unless (with-set-keys (member (funcall-key key elt) list2)) (setq result (cons elt result)))) (let ((test (if testp (lambda (x y) (funcall test y x)) test)) (test-not (if notp (lambda (x y) (funcall test-not y x)) test-not))) (dolist (elt list2) (unless (with-set-keys (member (funcall-key key elt) list1)) (setq result (cons elt result))))) result)) ;;; Adapted from SBCL. (defun nset-exclusive-or (list1 list2 &key key (test #'eql testp) (test-not #'eql notp)) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (let ((key (and key (coerce-to-function key))) (test (if testp (coerce-to-function test) test)) (test-not (if notp (coerce-to-function test-not) test-not))) ;; The outer loop examines LIST1 while the inner loop examines ;; LIST2. If an element is found in LIST2 "equal" to the element ;; in LIST1, both are spliced out. When the end of LIST1 is ;; reached, what is left of LIST2 is tacked onto what is left of ;; LIST1. The splicing operation ensures that the correct ;; operation is performed depending on whether splice is at the ;; top of the list or not. (do ((list1 list1) (list2 list2) (x list1 (cdr x)) (splicex ()) (deleted-y ()) ;; elements of LIST2, which are "equal" to some processed ;; earlier elements of LIST1 ) ((endp x) (if (null splicex) (setq list1 list2) (rplacd splicex list2)) list1) (let ((key-val-x (apply-key key (car x))) (found-duplicate nil)) ;; Move all elements from LIST2, which are "equal" to (CAR X), ;; to DELETED-Y. (do* ((y list2 next-y) (next-y (cdr y) (cdr y)) (splicey ())) ((endp y)) (cond ((let ((key-val-y (apply-key key (car y)))) (if notp (not (funcall test-not key-val-x key-val-y)) (funcall test key-val-x key-val-y))) (if (null splicey) (setq list2 (cdr y)) (rplacd splicey (cdr y))) (setq deleted-y (rplacd y deleted-y)) (setq found-duplicate t)) (t (setq splicey y)))) (unless found-duplicate (setq found-duplicate (with-set-keys (member key-val-x deleted-y)))) (if found-duplicate (if (null splicex) (setq list1 (cdr x)) (rplacd splicex (cdr x))) (setq splicex x)))))) ;;; Adapted from SBCL. (defun subsetp (list1 list2 &key key (test #'eql testp) (test-not nil notp)) (require-type list2 'list) (when (and testp notp) (error "Both :TEST and :TEST-NOT were supplied.")) (let ((key (and key (coerce-to-function key)))) (dolist (elt list1) (unless (with-set-keys (member (funcall-key key elt) list2)) (return-from subsetp nil))) t)) abcl-src-1.9.0/src/org/armedbear/lisp/shiftf.lisp0100644 0000000 0000000 00000006704 14202767264 020402 0ustar000000000 0000000 ;;; shiftf.lisp ;;; ;;; Copyright (C) 2003-2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From CMUCL. (in-package "SYSTEM") (require '#:collect) (defmacro shiftf (&rest args &environment env) "One or more SETF-style place expressions, followed by a single value expression. Evaluates all of the expressions in turn, then assigns the value of each expression to the place on its left, returning the value of the leftmost." (when args (collect ((let*-bindings) (mv-bindings) (setters) (getters)) ;; The last arg isn't necessarily a place, so we have to handle ;; that separately. (dolist (arg (butlast args)) (multiple-value-bind (temps subforms store-vars setter getter) (get-setf-expansion arg env) (loop for temp in temps for subform in subforms do (let*-bindings `(,temp ,subform))) (mv-bindings store-vars) (setters setter) (getters getter))) ;; Handle the last arg specially here. Just put something to ;; force the setter so the setter for the previous var gets set, ;; and the getter is just the last arg itself. (setters nil) (getters (car (last args))) (labels ((thunk (mv-bindings getters) (if mv-bindings `((multiple-value-bind ,(car mv-bindings) ,(car getters) ,@(thunk (cdr mv-bindings) (cdr getters)))) `(,@(butlast (setters)))))) `(let* ,(let*-bindings) (multiple-value-bind ,(car (mv-bindings)) ,(car (getters)) ,@(thunk (mv-bindings) (cdr (getters))) (values ,@(car (mv-bindings))))))))) abcl-src-1.9.0/src/org/armedbear/lisp/signal.lisp0100644 0000000 0000000 00000015130 14202767264 020365 0ustar000000000 0000000 ;;; signal.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package "SYSTEM") (export 'coerce-to-condition) (defvar *maximum-error-depth* 10) (defvar *current-error-depth* 0) (defvar *handler-clusters* nil) (defvar *break-on-signals* nil) (defun signal (datum &rest arguments) (let ((condition (coerce-to-condition datum arguments 'simple-condition 'signal)) (*handler-clusters* *handler-clusters*)) (let* ((old-bos *break-on-signals*) (*break-on-signals* nil)) (when (typep condition old-bos) (let ((*saved-backtrace* (sys:backtrace))) (break "~A~%BREAK called because of *BREAK-ON-SIGNALS* (now rebound to NIL)." condition)))) (loop (unless *handler-clusters* (return)) (let ((cluster (pop *handler-clusters*))) (dolist (handler cluster) (when (typep condition (car handler)) (funcall (cdr handler) condition))))) nil)) (defun error (datum &rest arguments) (let ((condition (coerce-to-condition datum arguments 'simple-error 'error))) (signal condition) (let ((*current-error-depth* (1+ *current-error-depth*))) (cond ((> *current-error-depth* *maximum-error-depth*) (%format *debug-io* "~%Maximum error depth exceeded (~D nested errors) with '~A'.~%" *current-error-depth* condition) (if (fboundp 'internal-debug) (internal-debug) (quit :status 89))) ;; it's a prime and a fibonacci! (t (invoke-debugger condition)))))) ;; COERCE-TO-CONDITION is redefined in clos.lisp. (defun coerce-to-condition (datum arguments default-type fun-name) (cond ((typep datum 'condition) (when arguments (error 'simple-type-error :datum arguments :expected-type 'null :format-control "You may not supply additional arguments when giving ~S to ~S." :format-arguments (list datum fun-name))) datum) ((symbolp datum) (%make-condition datum arguments)) ((or (stringp datum) (functionp datum)) (%make-condition default-type (list :format-control datum :format-arguments arguments))) (t (error 'simple-type-error :datum datum :expected-type '(or symbol string) :format-control "Bad argument to ~S: ~S." :format-arguments (list fun-name datum))))) (defmacro handler-bind (bindings &body forms) (dolist (binding bindings) (unless (and (consp binding) (= (length binding) 2)) (error "ill-formed handler binding ~S" binding))) `(let ((*handler-clusters* (cons (list ,@(mapcar (lambda (x) `(cons ',(car x) ,(cadr x))) bindings)) *handler-clusters*))) (java:jrun-exception-protected (lambda () (progn ,@forms))))) (defmacro handler-case (form &rest cases) (let ((no-error-clause (assoc ':no-error cases))) (if no-error-clause (let ((normal-return (make-symbol "normal-return")) (error-return (make-symbol "error-return"))) `(block ,error-return (multiple-value-call (lambda ,@(cdr no-error-clause)) (block ,normal-return (return-from ,error-return (handler-case (return-from ,normal-return ,form) ,@(remove no-error-clause cases))))))) (let ((tag (gensym)) (var (gensym)) (annotated-cases (mapcar (lambda (case) (cons (gensym) case)) cases))) `(block ,tag (let ((,var nil)) (declare (ignorable ,var)) (tagbody (handler-bind ,(mapcar (lambda (annotated-case) (list (cadr annotated-case) `(lambda (temp) ,(if (caddr annotated-case) `(setq ,var temp) '(declare (ignore temp))) (go ,(car annotated-case))))) annotated-cases) (return-from ,tag ,form)) ,@(mapcan (lambda (annotated-case) (list (car annotated-case) (let ((body (cdddr annotated-case))) `(return-from ,tag ,(cond ((caddr annotated-case) `(let ((,(caaddr annotated-case) ,var)) ,@body)) (t `(locally ,@body))))))) annotated-cases)))))))) abcl-src-1.9.0/src/org/armedbear/lisp/simple_list_remove_duplicates.java0100644 0000000 0000000 00000005054 14202767264 025204 0ustar000000000 0000000 /* * simple_list_remove_duplicates.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### simple-list-remove-duplicates public final class simple_list_remove_duplicates extends Primitive { private simple_list_remove_duplicates() { super("simple-list-remove-duplicates", PACKAGE_SYS, false, "list"); } @Override public LispObject execute(LispObject list) { LispObject result = NIL; while (list != NIL) { LispObject item = list.car(); boolean duplicate = false; LispObject tail = list.cdr(); while (tail != NIL) { if (item.eql(tail.car())) { duplicate = true; break; } tail = tail.cdr(); } if (!duplicate) result = new Cons(item, result); list = list.cdr(); } return result.nreverse(); } private static final Primitive SIMPLE_LIST_REMOVE_DUPLICATES = new simple_list_remove_duplicates(); } abcl-src-1.9.0/src/org/armedbear/lisp/socket.lisp0100644 0000000 0000000 00000011022 14202767264 020374 0ustar000000000 0000000 ;;; socket.lisp ;;; ;;; Copyright (C) 2004-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "EXTENSIONS") (export '(make-socket make-server-socket server-socket-close socket-accept socket-close get-socket-stream socket-peer-port socket-local-port socket-local-address socket-peer-address read-timeout write-timeout)) (defun get-socket-stream (socket &key (element-type 'character) (external-format :default)) ":ELEMENT-TYPE must be CHARACTER or (UNSIGNED-BYTE 8); the default is CHARACTER. EXTERNAL-FORMAT must be of the same format as specified for OPEN." (cond ((eq element-type 'character)) ((reduce #'equal (mapcar #'sys::normalize-type (list element-type '(unsigned-byte 8))))) (t (error 'simple-type-error :format-control ":ELEMENT-TYPE must be CHARACTER or (UNSIGNED-BYTE 8)."))) (sys::%socket-stream socket element-type external-format)) (defun make-socket (host port) "Create a TCP socket for client communication to HOST on PORT." (sys::%make-socket host port)) (defun make-server-socket (port) "Create a TCP server socket listening for clients on PORT." (sys::%make-server-socket port)) (defun socket-accept (socket) "Block until able to return a new socket for handling a incoming request to the specified server SOCKET." (sys::%socket-accept socket)) (defun socket-close (socket) "Close the client SOCKET." (sys::%socket-close socket)) (defun server-socket-close (socket) "Close the server SOCKET." (sys::%server-socket-close socket)) (declaim (inline %socket-address %socket-port)) (defun %socket-address (socket address-name) "Return the underlying ADDRESS-NAME for SOCKET." (java:jcall "getHostAddress" (java:jcall-raw address-name socket))) (defun %socket-port (socket port-name) "Return the PORT-NAME of SOCKET." (java:jcall port-name socket)) (defun socket-local-address (socket) "Returns the local address of the SOCKET as a dotted quad string." (%socket-address socket "getLocalAddress")) (defun socket-peer-address (socket) "Returns the peer address of the SOCKET as a dotted quad string." (%socket-address socket "getInetAddress")) (defun socket-local-port (socket) "Returns the local port number of the SOCKET." (%socket-port socket "getLocalPort")) (defun socket-peer-port (socket) "Returns the peer port number of the given SOCKET." (%socket-port socket "getPort")) (defun read-timeout (socket seconds) "Time in SECONDS to set local implementation of 'SO_RCVTIMEO' on SOCKET." (java:jcall (java:jmethod "java.net.Socket" "setSoTimeout" "int") socket (* seconds 1000))) ;; underlying API in ms. (defun write-timeout (socket seconds) "No-op setting of write timeout to SECONDS on SOCKET." (declare (ignore socket seconds)) ;; TODO timeouts for writes could possibly be implemented by ;; spawning a guardian to asynchronously check on the threads ;; perfoming the socket write. (warn "Ignoring request for unimplemented socket write timeout.")) (provide '#:socket) abcl-src-1.9.0/src/org/armedbear/lisp/socket_accept.java0100644 0000000 0000000 00000004406 14223403213 021655 0ustar000000000 0000000 /* * socket_accept.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.ServerSocket; import java.net.Socket; // ### %socket-accept public final class socket_accept extends Primitive { private socket_accept() { super("%socket-accept", PACKAGE_SYS, false, "socket"); } @Override public LispObject execute(LispObject first) { ServerSocket serverSocket = (ServerSocket) ((JavaObject)first).getObject(); try { Socket socket = serverSocket.accept(); return new JavaObject(socket); } catch (Exception e) { return error(new LispError(e.getMessage())); } } private static final Primitive SOCKET_ACCEPT = new socket_accept(); } abcl-src-1.9.0/src/org/armedbear/lisp/socket_close.java0100644 0000000 0000000 00000004221 14223403213 021516 0ustar000000000 0000000 /* * socket_close.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.Socket; // ### %socket-close public final class socket_close extends Primitive { private socket_close() { super("%socket-close", PACKAGE_SYS, false, "socket"); } @Override public LispObject execute(LispObject first) { Socket socket = (Socket) JavaObject.getObject(first); try { socket.close(); return T; } catch (Exception e) { return error(new LispError(e.getMessage())); } } private static final Primitive SOCKET_CLOSE = new socket_close(); } abcl-src-1.9.0/src/org/armedbear/lisp/socket_stream.java0100644 0000000 0000000 00000005026 14223403213 021710 0ustar000000000 0000000 /* * socket_stream.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.net.Socket; // ### %socket-stream public final class socket_stream extends Primitive { private socket_stream() { super("%socket-stream", PACKAGE_SYS, false, "socket element-type external-format"); } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { Socket socket = (Socket) ((JavaObject)first).getObject(); LispObject elementType = second; // Checked by caller. try { Stream in = new Stream(Symbol.SYSTEM_STREAM, socket.getInputStream(), elementType, third); Stream out = new Stream(Symbol.SYSTEM_STREAM, socket.getOutputStream(), elementType, third); return new SocketStream(socket, in, out); } catch (Exception e) { return error(new LispError(e.getMessage())); } } private static final Primitive SOCKET_STREAM = new socket_stream(); } abcl-src-1.9.0/src/org/armedbear/lisp/software_type.java0100644 0000000 0000000 00000003573 14202767264 021765 0ustar000000000 0000000 /* * software_type.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### software-type public final class software_type extends Primitive { private software_type() { super("software-type"); } @Override public LispObject execute() { return new SimpleString(System.getProperty("os.name")); } private static final Primitive SOFTWARE_TYPE = new software_type(); } abcl-src-1.9.0/src/org/armedbear/lisp/software_version.java0100644 0000000 0000000 00000003623 14202767264 022465 0ustar000000000 0000000 /* * software_version.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### software-version public final class software_version extends Primitive { private software_version() { super("software-version"); } @Override public LispObject execute() { return new SimpleString(System.getProperty("os.version")); } private static final Primitive SOFTWARE_VERSION = new software_version(); } abcl-src-1.9.0/src/org/armedbear/lisp/sort.lisp0100644 0000000 0000000 00000051636 14202767264 020112 0ustar000000000 0000000 ;;; sort.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (require "EXTENSIBLE-SEQUENCES-BASE") ;;; ;;; STABLE SORT ;;; ;;; ;;; MERGE SORT for vectors (and sequences in general) ;;; ;;; - top-down stable merge sort ;;; - it is defined with 2 macros to allow a single algorithm ;;; and multiple sequence types: merge-vectors-body and merge-sort-body ;;; - merge-vectors-body merges two given sequences ;;; - merge-sort-body contains the top-down algorithm ;;; - the body macro is called by the merge-sort-vectors functions, ;;; which typecases the type of sequence and expands the apropriate body ;;; - more types of sequences/vectors can be added ;;; - the macros generate the merge sort body with or without funcall to key ;;; - the merge-vectors algorithm is inspired from the CCL base code ;;; ;;; http://abcl.org/trac/ticket/196 ;;; TODO Restore the optimization for SIMPLE-VECTOR types by ;;; conditionally using aref/svref instead of always using AREF (defmacro merge-vectors-body (type ref a start-a end-a b start-b end-b aux start-aux predicate &optional key) (let ((i-a (gensym)) (i-b (gensym)) (i-aux (gensym)) (v-a (gensym)) (v-b (gensym)) (k-a (gensym)) (k-b (gensym)) (merge-block (gensym))) `(locally (declare (type fixnum ,start-a ,end-a ,start-b ,end-b ,start-aux) (type ,type ,a ,b) (type simple-vector ,aux) (type function ,predicate ,@(if key `(,key))) (optimize (speed 3) (safety 0))) (block ,merge-block (let ((,i-a ,start-a) (,i-b ,start-b) (,i-aux ,start-aux) ,v-a ,v-b ,k-a ,k-b) (declare (type fixnum ,i-a ,i-b ,i-aux)) (cond ((= ,start-a ,end-a) (when (= ,start-b ,end-b) (return-from ,merge-block)) (setf ,i-a ,start-b ,end-a ,end-b ,a ,b ,v-a (,ref ,a ,i-a))) ((= ,start-b ,end-b) (setf ,i-a ,start-a ,v-a (,ref ,a ,i-a))) (t (setf ,v-a (,ref ,a ,i-a) ,v-b (,ref ,b ,i-b) ,@(if key `(,k-a (funcall ,key ,v-a)) `(,k-a ,v-a)) ,@(if key `(,k-b (funcall ,key ,v-b)) `(,k-b ,v-b))) (loop (if (funcall ,predicate ,k-b ,k-a) (progn ,(if (subtypep type 'simple-vector) `(setf (svref ,aux ,i-aux) ,v-b ,i-aux (+ ,i-aux 1) ,i-b (+ ,i-b 1)) `(setf (aref ,aux ,i-aux) ,v-b ,i-aux (+ ,i-aux 1) ,i-b (+ ,i-b 1))) (when (= ,i-b ,end-b) (return)) (setf ,v-b (,ref ,b ,i-b) ,@(if key `(,k-b (funcall ,key ,v-b)) `(,k-b ,v-b)))) (progn ,(if (subtypep type 'simple-vector) `(setf (svref ,aux ,i-aux) ,v-a ,i-aux (+ ,i-aux 1) ,i-a (+ ,i-a 1)) `(setf (aref ,aux ,i-aux) ,v-a ,i-aux (+ ,i-aux 1) ,i-a (+ ,i-a 1))) (when (= ,i-a ,end-a) (setf ,a ,b ,i-a ,i-b ,end-a ,end-b ,v-a ,v-b) (return)) (setf ,v-a (,ref ,a ,i-a) ,@(if key `(,k-a (funcall ,key ,v-a)) `(,k-a ,v-a)))))))) (loop ,(if (subtypep type 'simple-vector) `(setf (svref ,aux ,i-aux) ,v-a ,i-a (+ ,i-a 1)) `(setf (aref ,aux ,i-aux) ,v-a ,i-a (+ ,i-a 1))) (when (= ,i-a ,end-a) (return)) (setf ,v-a (,ref ,a ,i-a) ,i-aux (+ ,i-aux 1)))))))) (defmacro merge-sort-body (type ref mpredicate mkey msequence mstart mend) (let ((merge-sort-call (gensym)) (maux (gensym)) (aux (gensym)) (sequence (gensym)) (start (gensym)) (end (gensym)) (predicate (gensym)) (key (gensym)) (mid (gensym)) (direction (gensym))) `(locally (declare (optimize (speed 3) (safety 0))) (labels ((,merge-sort-call (,sequence ,start ,end ,predicate ,key ,aux ,direction) (declare (type function ,predicate ,@(if mkey `(,key))) (type fixnum ,start ,end) (type ,type ,sequence)) (let ((,mid (+ ,start (ash (- ,end ,start) -1)))) (declare (type fixnum ,mid)) (if (<= (- ,mid 1) ,start) (unless ,direction (setf (,ref ,aux ,start) (,ref ,sequence ,start))) (,merge-sort-call ,sequence ,start ,mid ,predicate ,key ,aux (not ,direction))) (if (>= (+ ,mid 1) ,end) (unless ,direction (setf (,ref ,aux ,mid) (,ref ,sequence ,mid))) (,merge-sort-call ,sequence ,mid ,end ,predicate ,key ,aux (not ,direction))) (unless ,direction (psetq ,sequence ,aux ,aux ,sequence)) ,(if mkey `(merge-vectors-body ,type ,ref ,sequence ,start ,mid ,sequence ,mid ,end ,aux ,start ,predicate ,key) `(merge-vectors-body ,type ,ref ,sequence ,start ,mid ,sequence ,mid ,end ,aux ,start ,predicate))))) (let ((,maux (make-array ,mend))) (declare (type ,maux ,type)) (,merge-sort-call ,msequence ,mstart ,mend ,mpredicate ,mkey ,maux nil)))))) (defun merge-sort-vectors (sequence predicate key) (let ((end (length sequence))) (when (> end 1) (typecase sequence (simple-vector (if key (merge-sort-body simple-vector svref predicate key sequence 0 end) (merge-sort-body simple-vector svref predicate nil sequence 0 end))) (vector (if key (merge-sort-body vector aref predicate key sequence 0 end) (merge-sort-body vector aref predicate nil sequence 0 end))))) sequence)) ;;; ;;; MERGE SORT for lists ;;; ;; Adapted from SBCL. (declaim (ftype (function (list) cons) last-cons-of)) (defun last-cons-of (list) (loop (let ((rest (rest list))) (if rest (setf list rest) (return list))))) ;; Adapted from OpenMCL. (defun merge-lists (list1 list2 pred key) (declare (optimize (speed 3) (safety 0))) (if (null key) (merge-lists-no-key list1 list2 pred) (cond ((null list1) (values list2 (last-cons-of list2))) ((null list2) (values list1 (last-cons-of list1))) (t (let* ((result (cons nil nil)) (p result) ; p points to last cell of result (key1 (funcall key (car list1))) (key2 (funcall key (car list2)))) (declare (type list p)) (loop (cond ((funcall pred key2 key1) (rplacd p list2) ; append the lesser list to last cell of (setf p (cdr p)) ; result. Note: test must bo done for (pop list2) ; list2 < list1 so merge will be (unless list2 ; stable for list1 (rplacd p list1) (return (values (cdr result) (last-cons-of p)))) (setf key2 (funcall key (car list2)))) (t (rplacd p list1) (setf p (cdr p)) (pop list1) (unless list1 (rplacd p list2) (return (values (cdr result) (last-cons-of p)))) (setf key1 (funcall key (car list1))))))))))) (defun merge-lists-no-key (list1 list2 pred) (declare (optimize (speed 3) (safety 0))) (cond ((null list1) (values list2 (last-cons-of list2))) ((null list2) (values list1 (last-cons-of list1))) (t (let* ((result (cons nil nil)) (p result) ; p points to last cell of result (key1 (car list1)) (key2 (car list2))) (declare (type list p)) (loop (cond ((funcall pred key2 key1) (rplacd p list2) ; append the lesser list to last cell of (setf p (cdr p)) ; result. Note: test must bo done for (pop list2) ; list2 < list1 so merge will be (unless list2 ; stable for list1 (rplacd p list1) (return (values (cdr result) (last-cons-of p)))) (setf key2 (car list2))) (t (rplacd p list1) (setf p (cdr p)) (pop list1) (unless list1 (rplacd p list2) (return (values (cdr result) (last-cons-of p)))) (setf key1 (car list1))))))))) ;;; SORT-LIST uses a bottom up merge sort. First a pass is made over ;;; the list grabbing one element at a time and merging it with the next one ;;; form pairs of sorted elements. Then n is doubled, and elements are taken ;;; in runs of two, merging one run with the next to form quadruples of sorted ;;; elements. This continues until n is large enough that the inner loop only ;;; runs for one iteration; that is, there are only two runs that can be merged, ;;; the first run starting at the beginning of the list, and the second being ;;; the remaining elements. (defun sort-list (list pred key) (when (or (eq key #'identity) (eq key 'identity)) (setf key nil)) (let ((head (cons nil list)) ; head holds on to everything (n 1) ; bottom-up size of lists to be merged unsorted ; unsorted is the remaining list to be ; broken into n size lists and merged list-1 ; list-1 is one length n list to be merged last ; last points to the last visited cell ) (declare (type fixnum n)) (loop ;; start collecting runs of n at the first element (setf unsorted (cdr head)) ;; tack on the first merge of two n-runs to the head holder (setf last head) (let ((n-1 (1- n))) (declare (type fixnum n-1)) (loop (setf list-1 unsorted) (let ((temp (nthcdr n-1 list-1)) list-2) (cond (temp ;; there are enough elements for a second run (setf list-2 (cdr temp)) (setf (cdr temp) nil) (setf temp (nthcdr n-1 list-2)) (cond (temp (setf unsorted (cdr temp)) (setf (cdr temp) nil)) ;; the second run goes off the end of the list (t (setf unsorted nil))) (multiple-value-bind (merged-head merged-last) (merge-lists list-1 list-2 pred key) (setf (cdr last) merged-head) (setf last merged-last)) (if (null unsorted) (return))) ;; if there is only one run, then tack it on to the end (t (setf (cdr last) list-1) (return))))) (setf n (+ n n)) ;; If the inner loop only executed once, then there were only enough ;; elements for two runs given n, so all the elements have been merged ;; into one list. This may waste one outer iteration to realize. (if (eq list-1 (cdr head)) (return list-1)))))) ;;; ;;; MERGE ;;; ;;; From ECL. Should already be user-extensible as it does no type dispatch ;;; and uses only user-extensible functions. (defun merge (result-type sequence1 sequence2 predicate &key key &aux (l1 (length sequence1)) (l2 (length sequence2))) (unless key (setq key #'identity)) (do ((newseq (make-sequence result-type (+ l1 l2))) (j 0 (1+ j)) (i1 0) (i2 0)) ((and (= i1 l1) (= i2 l2)) newseq) (cond ((and (< i1 l1) (< i2 l2)) (cond ((funcall predicate (funcall key (elt sequence1 i1)) (funcall key (elt sequence2 i2))) (setf (elt newseq j) (elt sequence1 i1)) (incf i1)) ((funcall predicate (funcall key (elt sequence2 i2)) (funcall key (elt sequence1 i1))) (setf (elt newseq j) (elt sequence2 i2)) (incf i2)) (t (setf (elt newseq j) (elt sequence1 i1)) (incf i1)))) ((< i1 l1) (setf (elt newseq j) (elt sequence1 i1)) (incf i1)) (t (setf (elt newseq j) (elt sequence2 i2)) (incf i2))))) ;;; ;;; SORT ;;; ;;; ;;; QUICKSORT ;;; ;;; - algorithm is in the quicksort-body macro, so that it allows ;;; the use of different types (e.g., simple-vector, vector) ;;; - the pivot is picked by selecting middle point ;;; - sorts the smaller partition first ;;; - the macro generates the quicksort body with or without funcall to key ;;; (defmacro quicksort-body (type ref mpredicate mkey sequence mstart mend) (let ((quicksort-call (gensym)) (predicate (gensym)) (key (gensym)) (vector (gensym)) (start (gensym)) (end (gensym)) (i (gensym)) (j (gensym)) (p (gensym)) (d (gensym)) (kd (gensym))) `(locally (declare (speed 3) (safety 0)) (labels ((,quicksort-call (,vector ,start ,end ,predicate ,key) (declare (type function ,predicate ,@(if mkey `(,key))) (type fixnum ,start ,end) (type ,type ,sequence)) (if (< ,start ,end) (let* ((,i ,start) (,j (1+ ,end)) (,p (the fixnum (+ ,start (ash (- ,end ,start) -1)))) (,d (,ref ,vector ,p)) ,@(if mkey `((,kd (funcall ,key ,d))) `((,kd ,d)))) (rotatef (,ref ,vector ,p) (,ref ,vector ,start)) (block outer-loop (loop (loop (unless (> (decf ,j) ,i) (return-from outer-loop)) (when (funcall ,predicate ,@(if mkey `((funcall ,key (,ref ,vector ,j))) `((,ref ,vector ,j))) ,kd) (return))) (loop (unless (< (incf ,i) ,j) (return-from outer-loop)) (unless (funcall ,predicate ,@(if mkey `((funcall ,key (,ref ,vector ,i))) `((,ref ,vector ,i))) ,kd) (return))) (rotatef (,ref ,vector ,i) (,ref ,vector ,j)))) (setf (,ref ,vector ,start) (,ref ,vector ,j) (,ref ,vector ,j) ,d) (if (< (- ,j ,start) (- ,end ,j)) (progn (,quicksort-call ,vector ,start (1- ,j) ,predicate ,key) (,quicksort-call ,vector (1+ ,j) ,end ,predicate ,key)) (progn (,quicksort-call ,vector (1+ ,j) ,end ,predicate ,key) (,quicksort-call ,vector ,start (1- ,j) ,predicate ,key))))))) (,quicksort-call ,sequence ,mstart ,mend ,mpredicate ,mkey))))) (defun quicksort (sequence predicate key) (handler-case (let ((end (1- (length sequence)))) (typecase sequence (simple-vector (if key (quicksort-body simple-vector svref predicate key sequence 0 end) (quicksort-body simple-vector svref predicate nil sequence 0 end))) (vector (if key (quicksort-body vector aref predicate key sequence 0 end) (quicksort-body vector aref predicate nil sequence 0 end)))) sequence) (t (e) (warn "~&New quicksort implementation failed with~&'~A'.~&Trying stable implementation...~&" e) (quick-sort sequence 0 (length sequence) predicate key)))) ;;; DEPRECATED -- to be removed in abcl-1.4 ;;; From ECL. ;;; Alternative implementation for quick-sort SORT (defun quick-sort (seq start end pred key) (unless key (setq key #'identity)) (if (<= end (1+ start)) seq (let* ((j start) (k end) (d (elt seq start)) (kd (funcall key d))) (block outer-loop (loop (loop (decf k) (unless (< j k) (return-from outer-loop)) (when (funcall pred (funcall key (elt seq k)) kd) (return))) (loop (incf j) (unless (< j k) (return-from outer-loop)) (unless (funcall pred (funcall key (elt seq j)) kd) (return))) (let ((temp (elt seq j))) (setf (elt seq j) (elt seq k) (elt seq k) temp)))) (setf (elt seq start) (elt seq j) (elt seq j) d) (quick-sort seq start j pred key) (quick-sort seq (1+ j) end pred key)))) ;;; ;;; main SORT and STABLE-SORT function calls ;;; ;;; - sort: quicksort and merge sort (only for lists) ;;; - stable-sort: merge sort (all types) ;;; (defun sort (sequence predicate &rest args &key key) (sequence::seq-dispatch sequence (sort-list sequence predicate key) (quicksort sequence predicate key) (apply #'sequence:sort sequence predicate args))) (defun stable-sort (sequence predicate &rest args &key key) (sequence::seq-dispatch sequence (sort-list sequence predicate key) (merge-sort-vectors sequence predicate key) (apply #'sequence:stable-sort sequence predicate args))) abcl-src-1.9.0/src/org/armedbear/lisp/source-transform.lisp0100644 0000000 0000000 00000007622 14223403213 022410 0ustar000000000 0000000 ;;; source-transform.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (export '(source-transform define-source-transform expand-source-transform)) (defun source-transform (name) (get-function-info-value name :source-transform)) (defun set-source-transform (name transform) (set-function-info-value name :source-transform transform)) (defsetf source-transform set-source-transform) (defmacro define-source-transform (name lambda-list &rest body) (let* ((form (gensym)) (env (gensym)) (block-name (if (symbolp name) name (cadr name))) (body (parse-defmacro lambda-list form body name 'defmacro :environment env ;; when we encounter an error ;; parsing the arguments in the call ;; (not in the difinition!), return ;; the arguments unmodified -- ie skip the ;; transform (see also compiler-macro.lisp) :error-fun `(lambda (&rest ignored) (declare (ignore ignored)) (return-from ,block-name ,form)))) (expander `(lambda (,form) (block ,block-name ,body)))) `(progn (record-source-information-for-type ',name '(:source-transform ,name)) (eval-when (:compile-toplevel :load-toplevel :execute) (setf (source-transform ',name) ,expander) ',name)))) (defun expand-source-transform-1 (form) (let ((expander nil) (newdef nil)) (cond ((atom form) (values form nil)) ((and (consp (%car form)) (eq (caar form) 'SETF) (setf expander (source-transform (%car form)))) (values (setf newdef (funcall expander form)) (not (eq newdef form)))) ((and (symbolp (%car form)) (setf expander (source-transform (%car form)))) (values (setf newdef (funcall expander form)) (not (eq newdef form)))) (t (values form nil))))) (defun expand-source-transform (form) (let ((expanded-p nil)) (loop (multiple-value-bind (expansion exp-p) (expand-source-transform-1 form) (if exp-p (setf form expansion expanded-p t) (return)))) (values form expanded-p))) abcl-src-1.9.0/src/org/armedbear/lisp/step.lisp0100644 0000000 0000000 00000003151 14202767264 020063 0ustar000000000 0000000 ;;; step.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From SBCL. (in-package "SYSTEM") (defmacro step (form) `(let () ,form)) abcl-src-1.9.0/src/org/armedbear/lisp/stream_element_type.java0100644 0000000 0000000 00000003736 14202767264 023140 0ustar000000000 0000000 /* * stream_element_type.java * * Copyright (C) 2004-2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### stream-element-type public final class stream_element_type extends Primitive { private stream_element_type() { super("stream-element-type", "stream"); } @Override public LispObject execute(LispObject arg) { return checkStream(arg).getElementType(); } private static final Primitive STREAM_ELEMENT_TYPE = new stream_element_type(); } abcl-src-1.9.0/src/org/armedbear/lisp/strings.lisp0100644 0000000 0000000 00000015566 14202767264 020616 0ustar000000000 0000000 ;;; strings.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun string-upcase (string &key (start 0) end) (%string-upcase string start end)) (defun string-downcase (string &key (start 0) end) (%string-downcase string start end)) (defun string-capitalize (string &key (start 0) end) (%string-capitalize string start end)) (defun nstring-upcase (string &key (start 0) end) (%nstring-upcase string start end)) (defun nstring-downcase (string &key (start 0) end) (%nstring-downcase string start end)) (defun nstring-capitalize (string &key (start 0) end) (%nstring-capitalize string start end)) (defun string= (string1 string2 &key (start1 0) end1 (start2 0) end2) (%string= string1 string2 start1 end1 start2 end2)) (defun string/= (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string/= string1 string2 start1 end1 start2 end2))) (defun string-equal (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string-equal string1 string2 start1 end1 start2 end2))) (defun string-not-equal (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string-not-equal string1 string2 start1 end1 start2 end2))) (defun string< (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string< string1 string2 start1 end1 start2 end2))) (defun string> (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string> string1 string2 start1 end1 start2 end2))) (defun string<= (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string<= string1 string2 start1 end1 start2 end2))) (defun string>= (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string>= string1 string2 start1 end1 start2 end2))) (defun string-lessp (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string-lessp string1 string2 start1 end1 start2 end2))) (defun string-greaterp (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string-greaterp string1 string2 start1 end1 start2 end2))) (defun string-not-lessp (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string-not-lessp string1 string2 start1 end1 start2 end2))) (defun string-not-greaterp (string1 string2 &key (start1 0) end1 (start2 0) end2) (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2)))) (%string-not-greaterp string1 string2 start1 end1 start2 end2))) ;;; STRING-LEFT-TRIM, STRING-RIGHT-TRIM, STRING-TRIM (from OpenMCL) (defun string-left-trim (char-bag string &aux end) "Given a set of characters (a list or string) and a string, returns a copy of the string with the characters in the set removed from the left end." (setq string (string string)) (setq end (length string)) (do ((index 0 (+ index 1))) ((or (= index end) (not (find (aref string index) char-bag))) (subseq string index end)))) (defun string-right-trim (char-bag string &aux end) "Given a set of characters (a list or string) and a string, returns a copy of the string with the characters in the set removed from the right end." (setq string (string string)) (setq end (length string)) (do ((index (- end 1) (- index 1))) ((or (< index 0) (not (find (aref string index) char-bag))) (subseq string 0 (+ index 1))))) (defun string-trim (char-bag string &aux end) "Given a set of characters (a list or string) and a string, returns a copy of the string with the characters in the set removed from both ends." (setq string (string string)) (setq end (length string)) (let (left-end right-end) (do ((index 0 (+ index 1))) ((or (= index end) (not (find (aref string index) char-bag))) (setq left-end index))) (do ((index (- end 1) (- index 1))) ((or (< index left-end) (not (find (aref string index) char-bag))) (setq right-end index))) (subseq string left-end (+ right-end 1)))) abcl-src-1.9.0/src/org/armedbear/lisp/sublis.lisp0100644 0000000 0000000 00000006472 14223403213 020402 0ustar000000000 0000000 ;;; sublis.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "COMMON-LISP") ;;; From CMUCL. (defun sublis (alist tree &key key (test #'eql) (test-not nil notp)) (labels ((s (subtree) (let* ((key-val (sys::apply-key key subtree)) (assoc (if notp (assoc key-val alist :test-not test-not) (assoc key-val alist :test test)))) (cond (assoc (cdr assoc)) ((atom subtree) subtree) (t (let ((car (s (car subtree))) (cdr (s (cdr subtree)))) (if (and (eq car (car subtree)) (eq cdr (cdr subtree))) subtree (cons car cdr)))))))) (s tree))) (defmacro nsublis-macro () (let ((key-tmp (gensym))) `(let ((,key-tmp (sys::apply-key key subtree))) (if notp (assoc ,key-tmp alist :test-not test-not) (assoc ,key-tmp alist :test test))))) (defun nsublis (alist tree &key key (test #'eql) (test-not nil notp)) (let (temp) (labels ((s (subtree) (cond ((setq temp (nsublis-macro)) (cdr temp)) ((atom subtree) subtree) (t (do* ((last nil subtree) (subtree subtree (cdr subtree))) ((atom subtree) (if (setq temp (nsublis-macro)) (setf (cdr last) (cdr temp)))) (if (setq temp (nsublis-macro)) (return (setf (cdr last) (cdr temp))) (setf (car subtree) (s (car subtree))))) subtree)))) (s tree)))) abcl-src-1.9.0/src/org/armedbear/lisp/subst.lisp0100644 0000000 0000000 00000012656 14223403213 020242 0ustar000000000 0000000 ;;; subst.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") ;;; From CMUCL. (defmacro satisfies-the-test (item elt) (let ((key-tmp (gensym))) `(let ((,key-tmp (apply-key key ,elt))) (cond (testp (funcall test ,item ,key-tmp)) (notp (not (funcall test-not ,item ,key-tmp))) (t (funcall test ,item ,key-tmp)))))) (defun %subst (new old tree key test testp test-not notp) (cond ((satisfies-the-test old tree) new) ((atom tree) tree) (t (let ((car (%subst new old (car tree) key test testp test-not notp)) (cdr (%subst new old (cdr tree) key test testp test-not notp))) (if (and (eq car (car tree)) (eq cdr (cdr tree))) tree (cons car cdr)))))) (defun subst (new old tree &key key (test #'eql testp) (test-not nil notp)) (%subst new old tree key test testp test-not notp)) (defun %subst-if (new test tree key) (cond ((funcall test (apply-key key tree)) new) ((atom tree) tree) (t (let ((car (%subst-if new test (car tree) key)) (cdr (%subst-if new test (cdr tree) key))) (if (and (eq car (car tree)) (eq cdr (cdr tree))) tree (cons car cdr)))))) (defun subst-if (new test tree &key key) (%subst-if new test tree key)) (defun %subst-if-not (new test tree key) (cond ((not (funcall test (apply-key key tree))) new) ((atom tree) tree) (t (let ((car (%subst-if-not new test (car tree) key)) (cdr (%subst-if-not new test (cdr tree) key))) (if (and (eq car (car tree)) (eq cdr (cdr tree))) tree (cons car cdr)))))) (defun subst-if-not (new test tree &key key) (%subst-if-not new test tree key)) (defun nsubst (new old tree &key key (test #'eql testp) (test-not nil notp)) (labels ((s (subtree) (cond ((satisfies-the-test old subtree) new) ((atom subtree) subtree) (t (do* ((last nil subtree) (subtree subtree (cdr subtree))) ((atom subtree) (if (satisfies-the-test old subtree) (setf (cdr last) new))) (if (satisfies-the-test old subtree) (return (setf (cdr last) new)) (setf (car subtree) (s (car subtree))))) subtree)))) (s tree))) (defun nsubst-if (new test tree &key key) (labels ((s (subtree) (cond ((funcall test (apply-key key subtree)) new) ((atom subtree) subtree) (t (do* ((last nil subtree) (subtree subtree (cdr subtree))) ((atom subtree) (if (funcall test (apply-key key subtree)) (setf (cdr last) new))) (if (funcall test (apply-key key subtree)) (return (setf (cdr last) new)) (setf (car subtree) (s (car subtree))))) subtree)))) (s tree))) (defun nsubst-if-not (new test tree &key key) (labels ((s (subtree) (cond ((not (funcall test (apply-key key subtree))) new) ((atom subtree) subtree) (t (do* ((last nil subtree) (subtree subtree (cdr subtree))) ((atom subtree) (if (not (funcall test (apply-key key subtree))) (setf (cdr last) new))) (if (not (funcall test (apply-key key subtree))) (return (setf (cdr last) new)) (setf (car subtree) (s (car subtree))))) subtree)))) (s tree))) abcl-src-1.9.0/src/org/armedbear/lisp/substitute.lisp0100644 0000000 0000000 00000014552 14223403213 021312 0ustar000000000 0000000 ;;; substitute.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (require "EXTENSIBLE-SEQUENCES-BASE") (in-package "COMMON-LISP") (export '(substitute substitute-if substitute-if-not)) ;;; From CMUCL. (defmacro real-count (count) `(cond ((null ,count) most-positive-fixnum) ((sys::fixnump ,count) (if (minusp ,count) 0 ,count)) ((integerp ,count) (if (minusp ,count) 0 most-positive-fixnum)) (t ,count))) (defun list-substitute* (pred new list start end count key test test-not old) (let* ((result (list nil)) elt (splice result) (list list)) ; Get a local list for a stepper. (do ((index 0 (1+ index))) ((= index start)) (setq splice (cdr (rplacd splice (list (car list))))) (setq list (cdr list))) (do ((index start (1+ index))) ((or (= index end) (null list) (= count 0))) (setq elt (car list)) (setq splice (cdr (rplacd splice (list (cond ((case pred (normal (if test-not (not (funcall test-not old (sys::apply-key key elt))) (funcall test old (sys::apply-key key elt)))) (if (funcall test (sys::apply-key key elt))) (if-not (not (funcall test (sys::apply-key key elt))))) (setq count (1- count)) new) (t elt)))))) (setq list (cdr list))) (do () ((null list)) (setq splice (cdr (rplacd splice (list (car list))))) (setq list (cdr list))) (cdr result))) ;;; Replace old with new in sequence moving from left to right by incrementer ;;; on each pass through the loop. Called by all three substitute functions. (defun vector-substitute* (pred new sequence incrementer left right length start end count key test test-not old) (let ((result (sys::make-sequence-like sequence length)) (index left)) (do () ((= index start)) (setf (aref result index) (aref sequence index)) (setq index (+ index incrementer))) (do ((elt)) ((or (= index end) (= count 0))) (setq elt (aref sequence index)) (setf (aref result index) (cond ((case pred (normal (if test-not (not (funcall test-not old (sys::apply-key key elt))) (funcall test old (sys::apply-key key elt)))) (if (funcall test (sys::apply-key key elt))) (if-not (not (funcall test (sys::apply-key key elt))))) (setq count (1- count)) new) (t elt))) (setq index (+ index incrementer))) (do () ((= index right)) (setf (aref result index) (aref sequence index)) (setq index (+ index incrementer))) result)) (defmacro subst-dispatch (pred) `(sequence::seq-dispatch sequence (if from-end (nreverse (list-substitute* ,pred new (reverse sequence) (- length end) (- length start) count key test test-not old)) (list-substitute* ,pred new sequence start end count key test test-not old)) (if from-end (vector-substitute* ,pred new sequence -1 (1- length) -1 length (1- end) (1- start) count key test test-not old) (vector-substitute* ,pred new sequence 1 0 length length start end count key test test-not old)) ,(ecase (cadr pred) ;;pred is (quote ) (normal `(apply #'sequence:substitute new old sequence args)) (if `(apply #'sequence:substitute-if new test sequence args)) (if-not `(apply #'sequence:substitute-if-not new test sequence args))))) (defun substitute (new old sequence &rest args &key from-end (test #'eql) test-not (start 0) count end key) (let* ((length (length sequence)) (end (or end length)) (count (real-count count))) (subst-dispatch 'normal))) (defun substitute-if (new test sequence &rest args &key from-end (start 0) end count key) (let* ((length (length sequence)) (end (or end length)) (count (real-count count)) test-not old) (subst-dispatch 'if))) (defun substitute-if-not (new test sequence &rest args &key from-end (start 0) end count key) (let* ((length (length sequence)) (end (or end length)) (count (real-count count)) test-not old) (subst-dispatch 'if-not))) abcl-src-1.9.0/src/org/armedbear/lisp/subtypep.lisp0100644 0000000 0000000 00000101034 14223403213 020742 0ustar000000000 0000000 ;;; subtypep.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defparameter *known-types* (make-hash-table :test 'eq)) (defun initialize-known-types () (let ((ht (make-hash-table :test 'eq))) (dolist (i '((ARITHMETIC-ERROR ERROR) (ARRAY) (BASE-STRING STRING) (BIGNUM INTEGER) (BIT FIXNUM) (BIT-VECTOR VECTOR) (BOOLEAN SYMBOL) (BUILT-IN-CLASS CLASS) (CELL-ERROR ERROR) (CHARACTER) (CLASS STANDARD-OBJECT) (COMPILED-FUNCTION FUNCTION) (COMPLEX NUMBER) (CONDITION) (CONS LIST) (CONTROL-ERROR ERROR) (DIVISION-BY-ZERO ARITHMETIC-ERROR) (DOUBLE-FLOAT FLOAT) (END-OF-FILE STREAM-ERROR) (ERROR SERIOUS-CONDITION) (EXTENDED-CHAR CHARACTER NIL) (FILE-ERROR ERROR) (FIXNUM INTEGER) (FLOAT REAL) (FLOATING-POINT-INEXACT ARITHMETIC-ERROR) (FLOATING-POINT-INVALID-OPERATION ARITHMETIC-ERROR) (FLOATING-POINT-OVERFLOW ARITHMETIC-ERROR) (FLOATING-POINT-UNDERFLOW ARITHMETIC-ERROR) (FUNCTION) (GENERIC-FUNCTION FUNCTION) (HASH-TABLE) (INTEGER RATIONAL) (KEYWORD SYMBOL) (LIST SEQUENCE) (LONG-FLOAT FLOAT) (NIL-VECTOR SIMPLE-STRING) (NULL BOOLEAN LIST) (NUMBER) (PACKAGE) (PACKAGE-ERROR ERROR) (PARSE-ERROR ERROR) (PATHNAME) (PRINT-NOT-READABLE ERROR) (PROGRAM-ERROR ERROR) (RANDOM-STATE) (RATIO RATIONAL) (RATIONAL REAL) (READER-ERROR PARSE-ERROR STREAM-ERROR) (READTABLE) (REAL NUMBER) (RESTART) (SERIOUS-CONDITION CONDITION) (SHORT-FLOAT FLOAT) (SIMPLE-ARRAY ARRAY) (SIMPLE-BASE-STRING SIMPLE-STRING BASE-STRING) (SIMPLE-BIT-VECTOR BIT-VECTOR SIMPLE-ARRAY) (SIMPLE-CONDITION CONDITION) (SIMPLE-ERROR SIMPLE-CONDITION ERROR) (SIMPLE-STRING BASE-STRING STRING SIMPLE-ARRAY) (SIMPLE-TYPE-ERROR SIMPLE-CONDITION TYPE-ERROR) (SIMPLE-VECTOR VECTOR SIMPLE-ARRAY) (SIMPLE-WARNING SIMPLE-CONDITION WARNING) (SINGLE-FLOAT FLOAT) (STANDARD-CHAR CHARACTER) (STANDARD-CLASS CLASS) (STANDARD-GENERIC-FUNCTION GENERIC-FUNCTION) (STANDARD-OBJECT) (STORAGE-CONDITION SERIOUS-CONDITION) (STREAM) (STREAM-ERROR ERROR) (STRING VECTOR) (STRUCTURE-CLASS CLASS STANDARD-OBJECT) (STYLE-WARNING WARNING) (SYMBOL) (TWO-WAY-STREAM STREAM) (TYPE-ERROR ERROR) (UNBOUND-SLOT CELL-ERROR) (UNBOUND-VARIABLE CELL-ERROR) (UNDEFINED-FUNCTION CELL-ERROR) (VECTOR ARRAY SEQUENCE) (WARNING CONDITION))) (setf (gethash (%car i) ht) (%cdr i))) (setf *known-types* ht))) (initialize-known-types) (defun known-type-p (type) (multiple-value-bind (value present-p) (gethash type *known-types*) present-p)) (defun sub-interval-p (i1 i2) (let (low1 high1 low2 high2) (if (null i1) (setq low1 '* high1 '*) (if (null (cdr i1)) (setq low1 (car i1) high1 '*) (setq low1 (car i1) high1 (cadr i1)))) (if (null i2) (setq low2 '* high2 '*) (if (null (cdr i2)) (setq low2 (car i2) high2 '*) (setq low2 (car i2) high2 (cadr i2)))) (when (and (consp low1) (integerp (%car low1))) (setq low1 (1+ (car low1)))) (when (and (consp low2) (integerp (%car low2))) (setq low2 (1+ (car low2)))) (when (and (consp high1) (integerp (%car high1))) (setq high1 (1- (car high1)))) (when (and (consp high2) (integerp (%car high2))) (setq high2 (1- (car high2)))) (cond ((eq low1 '*) (unless (eq low2 '*) (return-from sub-interval-p nil))) ((eq low2 '*)) ((consp low1) (if (consp low2) (when (< (%car low1) (%car low2)) (return-from sub-interval-p nil)) (when (< (%car low1) low2) (return-from sub-interval-p nil)))) ((if (consp low2) (when (<= low1 (%car low2)) (return-from sub-interval-p nil)) (when (< low1 low2) (return-from sub-interval-p nil))))) (cond ((eq high1 '*) (unless (eq high2 '*) (return-from sub-interval-p nil))) ((eq high2 '*)) ((consp high1) (if (consp high2) (when (> (%car high1) (%car high2)) (return-from sub-interval-p nil)) (when (> (%car high1) high2) (return-from sub-interval-p nil)))) ((if (consp high2) (when (>= high1 (%car high2)) (return-from sub-interval-p nil)) (when (> high1 high2) (return-from sub-interval-p nil))))) (return-from sub-interval-p t))) (defun dimension-subtypep (dim1 dim2) (cond ((eq dim2 '*) t) ((equal dim1 dim2) t) ((integerp dim2) (and (listp dim1) (= (length dim1) dim2))) ((eql dim1 0) (null dim2)) ((integerp dim1) (and (consp dim2) (= (length dim2) dim1) (equal dim2 (make-list dim1 :initial-element '*)))) ((and (consp dim1) (consp dim2) (= (length dim1) (length dim2))) (do* ((list1 dim1 (cdr list1)) (list2 dim2 (cdr list2)) (e1 (car list1) (car list1)) (e2 (car list2) (car list2))) ((null list1) t) (unless (or (eq e2 '*) (eql e1 e2)) (return nil)))) (t nil))) (defun simple-subtypep (type1 type2) (if (eq type1 type2) t (multiple-value-bind (type1-supertypes type1-known-p) (gethash type1 *known-types*) (if type1-known-p (if (memq type2 type1-supertypes) t (dolist (supertype type1-supertypes) (when (simple-subtypep supertype type2) (return t)))) nil)))) ;; (defstruct ctype ;; ((:constructor make-ctype (super type))) ;; super ;; type) (defun make-ctype (super type) (cons super type)) (defun ctype-super (ctype) (car ctype)) (defun ctype-type (ctype) (cdr ctype)) (defun ctype (type) (cond ((classp type) nil) (t (let ((tp (if (atom type) type (car type)))) (case tp ((ARRAY VECTOR STRING SIMPLE-ARRAY SIMPLE-STRING BASE-STRING SIMPLE-BASE-STRING BIT-VECTOR SIMPLE-BIT-VECTOR NIL-VECTOR) (make-ctype 'ARRAY type)) ((REAL INTEGER BIT FIXNUM SIGNED-BYTE UNSIGNED-BYTE BIGNUM RATIO FLOAT SINGLE-FLOAT DOUBLE-FLOAT SHORT-FLOAT LONG-FLOAT) (make-ctype 'REAL type)) (COMPLEX (make-ctype 'COMPLEX (if (atom type) '* (cadr type)))) (FUNCTION (make-ctype 'FUNCTION type))))))) (defun csubtypep-array (ct1 ct2) (let ((type1 (normalize-type (ctype-type ct1))) (type2 (normalize-type (ctype-type ct2)))) (when (eq type1 type2) (return-from csubtypep-array (values t t))) (let (t1 t2 i1 i2) (if (atom type1) (setf t1 type1 i1 nil) (setf t1 (car type1) i1 (cdr type1))) (if (atom type2) (setf t2 type2 i2 nil) (setf t2 (car type2) i2 (cdr type2))) (cond ((and (classp t1) (eq (%class-name t1) 'array) (eq t2 'array)) (values (equal i2 '(* *)) t)) ((and (memq t1 '(array simple-array)) (eq t2 'array)) (let ((e1 (car i1)) (e2 (car i2)) (d1 (cadr i1)) (d2 (cadr i2))) (cond ((and (eq e2 '*) (eq d2 '*)) (values t t)) ((or (eq e2 '*) (equal e1 e2) (equal (upgraded-array-element-type e1) (upgraded-array-element-type e2))) (values (dimension-subtypep d1 d2) t)) (t (values nil t))))) ((and (memq t1 '(simple-base-string base-string simple-string string nil-vector)) (memq t2 '(simple-base-string base-string simple-string string nil-vector))) (if (and (simple-subtypep t1 t2) (or (eql (car i1) (car i2)) (eq (car i2) '*))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))) ((and (memq t1 '(array simple-array)) (eq t2 'string)) (let ((element-type (car i1)) (dim (cadr i1)) (size (car i2))) (unless (%subtypep element-type 'character) (return-from csubtypep-array (values nil t))) (when (integerp size) (if (and (consp dim) (= (length dim) 1) (eql (%car dim) size)) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))))) ((and (eq t1 'simple-array) (eq t2 'simple-string)) (let ((element-type (car i1)) (dim (cadr i1)) (size (car i2))) (unless (%subtypep element-type 'character) (return-from csubtypep-array (values nil t))) (when (integerp size) (if (and (consp dim) (= (length dim) 1) (eql (%car dim) size)) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))))) ((and (memq t1 '(string simple-string nil-vector)) (eq t2 'array)) (let ((element-type (car i2)) (dim (cadr i2)) (size (car i1))) (unless (eq element-type '*) (return-from csubtypep-array (values nil t))) (when (integerp size) (if (or (eq dim '*) (eql dim 1) (and (consp dim) (= (length dim) 1) (or (eq (%car dim) '*) (eql (%car dim) size)))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eq dim '*) (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))))) ((and (memq t1 '(bit-vector simple-bit-vector)) (eq t2 'array)) (let ((element-type (car i2)) (dim (cadr i2)) (size (car i1))) (unless (or (memq element-type '(bit *)) (equal element-type '(integer 0 1))) (return-from csubtypep-array (values nil t))) (when (integerp size) (if (or (eq dim '*) (eql dim 1) (and (consp dim) (= (length dim) 1) (or (eq (%car dim) '*) (eql (%car dim) size)))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eq dim '*) (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))))) ((eq t2 'simple-array) (case t1 (simple-array (let ((e1 (car i1)) (e2 (car i2)) (d1 (cadr i1)) (d2 (cadr i2))) (cond ((and (eq e2 '*) (eq d2 '*)) (values t t)) ((or (eq e2 '*) (equal e1 e2) (equal (upgraded-array-element-type e1) (upgraded-array-element-type e2))) (values (dimension-subtypep d1 d2) t)) (t (values nil t))))) ((simple-string simple-bit-vector nil-vector) (let ((element-type (car i2)) (dim (cadr i2)) (size (car i1))) (unless (eq element-type '*) (return-from csubtypep-array (values nil t))) (when (integerp size) (if (or (eq dim '*) (and (consp dim) (= (length dim) 1) (eql (%car dim) size))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eq dim '*) (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from csubtypep-array (values t t)) (return-from csubtypep-array (values nil t)))))) (t (values nil t)))) ((eq t2 'bit-vector) (let ((size1 (car i1)) (size2 (car i2))) (case t1 ((bit-vector simple-bit-vector) (values (if (or (eq size2 '*) (eql size1 size2)) t nil) t)) (t (values nil t))))) ((eq t2 'simple-bit-vector) (let ((size1 (car i1)) (size2 (car i2))) (if (and (eq t1 'simple-bit-vector) (or (eq size2 '*) (eql size1 size2))) (values t t) (values nil t)))) ((classp t2) (let ((class-name (%class-name t2))) (cond ((eq class-name t1) (values t t)) ((and (eq class-name 'array) (memq t1 '(array simple-array vector simple-vector string simple-string simple-base-string bit-vector simple-bit-vector))) (values t t)) ((eq class-name 'vector) (cond ((memq t1 '(string simple-string)) (values t t)) ((eq t1 'array) (let ((dim (cadr i1))) (if (or (eql dim 1) (and (consp dim) (= (length dim) 1))) (values t t) (values nil t)))) (t (values nil t)))) ((and (eq class-name 'simple-vector) (eq t1 'simple-array)) (let ((dim (cadr i1))) (if (or (eql dim 1) (and (consp dim) (= (length dim) 1))) (values t t) (values nil t)))) ((and (eq class-name 'bit-vector) (eq t1 'simple-bit-vector)) (values t t)) ((and (eq class-name 'string) (memq t1 '(string simple-string))) (values t t)) (t (values nil nil))))) (t (values nil nil)))))) (defun csubtypep-function (ct1 ct2) (let ((type1 (ctype-type ct1)) (type2 (ctype-type ct2))) (cond ((and (listp type1) (atom type2)) (values t t)) (t (values nil nil))))) (defun csubtypep-complex (ct1 ct2) (let ((type1 (cdr ct1)) (type2 (cdr ct2))) (cond ((or (null type2) (eq type2 '*)) (values t t)) ((eq type1 '*) (values nil t)) (t (subtypep type1 type2))))) (defun csubtypep (ctype1 ctype2) (cond ((null (and ctype1 ctype2)) (values nil nil)) ((neq (ctype-super ctype1) (ctype-super ctype2)) (values nil t)) ((eq (ctype-super ctype1) 'array) (csubtypep-array ctype1 ctype2)) ((eq (ctype-super ctype1) 'function) (csubtypep-function ctype1 ctype2)) ((eq (ctype-super ctype1) 'complex) (csubtypep-complex ctype1 ctype2)) (t (values nil nil)))) (defun properly-named-class-p (thing environment) (and (classp thing) (class-name thing) (eq thing (find-class (class-name thing) nil environment)))) (defun %subtypep (type1 type2 &optional environment) (when (or (eq type1 type2) (null type1) (eq type2 t) (and (classp type2) (eq type2 (find-class t)))) (return-from %subtypep (values t t))) (when (properly-named-class-p type1 environment) (setf type1 (class-name type1))) (when (properly-named-class-p type2 environment) (setf type2 (class-name type2))) (let ((ct1 (ctype type1)) (ct2 (ctype type2))) (multiple-value-bind (subtype-p valid-p) (csubtypep ct1 ct2) (when valid-p (return-from %subtypep (values subtype-p valid-p))))) (when (and (atom type1) (atom type2)) (let* ((classp-1 (classp type1)) (classp-2 (classp type2)) class1 class2) (when (and (setf class1 (if classp-1 type1 (and (symbolp type1) (find-class type1 nil)))) (setf class2 (if classp-2 type2 (and (symbolp type2) (find-class type2 nil))))) (return-from %subtypep (values (subclassp class1 class2) t))) (when (or classp-1 classp-2) (let ((t1 (if classp-1 (class-name type1) type1)) (t2 (if classp-2 (class-name type2) type2))) (return-from %subtypep (values (simple-subtypep t1 t2) t)))))) (setf type1 (normalize-type type1) type2 (normalize-type type2)) (when (eq type1 type2) (return-from %subtypep (values t t))) (let (t1 t2 i1 i2) (if (atom type1) (setf t1 type1 i1 nil) (setf t1 (%car type1) i1 (%cdr type1))) (if (atom type2) (setf t2 type2 i2 nil) (setf t2 (%car type2) i2 (%cdr type2))) (cond ((null t1) (return-from %subtypep (values t t))) ((eq t1 'atom) (return-from %subtypep (values (eq t2 t) t))) ((eq t2 'atom) (return-from %subtypep (cond ((memq t1 '(cons list sequence)) (values nil t)) (t (values t t))))) ((eq t1 'member) (dolist (e i1) (unless (typep e type2) (return-from %subtypep (values nil t)))) (return-from %subtypep (values t t))) ((eq t1 'eql) (case t2 (EQL (return-from %subtypep (values (eql (car i1) (car i2)) t))) (SATISFIES (return-from %subtypep (values (funcall (car i2) (car i1)) t))) (t (return-from %subtypep (values (typep (car i1) type2) t))))) ((eq t1 'or) (dolist (tt i1) (multiple-value-bind (tv flag) (%subtypep tt type2) (unless tv (return-from %subtypep (values tv flag))))) (return-from %subtypep (values t t))) ((eq t1 'and) (dolist (tt i1) (let ((tv (%subtypep tt type2))) (when tv (return-from %subtypep (values t t))))) (return-from %subtypep (values nil nil))) ((eq t1 'cons) (case t2 ((LIST SEQUENCE) (return-from %subtypep (values t t))) (CONS (when (and (%subtypep (car i1) (car i2)) (%subtypep (cadr i1) (cadr i2))) (return-from %subtypep (values t t))))) (return-from %subtypep (values nil (known-type-p t2)))) ((eq t2 'or) (dolist (tt i2) (let ((tv (%subtypep type1 tt))) (when tv (return-from %subtypep (values t t))))) (return-from %subtypep (values nil nil))) ((eq t2 'and) (dolist (tt i2) (multiple-value-bind (tv flag) (%subtypep type1 tt) (unless tv (return-from %subtypep (values tv flag))))) (return-from %subtypep (values t t))) ((null (or i1 i2)) (return-from %subtypep (values (simple-subtypep t1 t2) t))) ((eq t2 'SEQUENCE) (cond ((memq t1 '(null cons list)) (values t t)) ((memq t1 '(simple-base-string base-string simple-string string nil-vector)) (values t t)) ((memq t1 '(bit-vector simple-bit-vector)) (values t t)) ((memq t1 '(array simple-array)) (cond ((and (cdr i1) (consp (cadr i1)) (null (cdadr i1))) (values t t)) ((and (cdr i1) (eql (cadr i1) 1)) (values t t)) (t (values nil t)))) (t (values nil (known-type-p t1))))) ((eq t1 'integer) (cond ((memq t2 '(integer rational real number)) (values (sub-interval-p i1 i2) t)) ((or (eq t2 'bignum) (and (classp t2) (eq (class-name t2) 'bignum))) (values (or (sub-interval-p i1 (list '* (list most-negative-fixnum))) (sub-interval-p i1 (list (list most-positive-fixnum) '*))) t)) (t (values nil (known-type-p t2))))) ((eq t1 'rational) (if (memq t2 '(rational real number)) (values (sub-interval-p i1 i2) t) (values nil (known-type-p t2)))) ((eq t1 'float) (if (memq t2 '(float real number)) (values (sub-interval-p i1 i2) t) (values nil (known-type-p t2)))) ((memq t1 '(single-float short-float)) (if (memq t2 '(single-float short-float float real number)) (values (sub-interval-p i1 i2) t) (values nil (known-type-p t2)))) ((memq t1 '(double-float long-float)) (if (memq t2 '(double-float long-float float real number)) (values (sub-interval-p i1 i2) t) (values nil (known-type-p t2)))) ((eq t1 'real) (if (memq t2 '(real number)) (values (sub-interval-p i1 i2) t) (values nil (known-type-p t2)))) ((eq t1 'complex) (cond ((eq t2 'number) (values t t)) ((eq t2 'complex) (cond ((equal i2 '(*)) (values t t)) ((equal i1 '(*)) (values nil t)) (t (values (subtypep (car i1) (car i2)) t)))))) ((and (classp t1) (eq (class-name t1) 'array) (eq t2 'array)) (values (equal i2 '(* *)) t)) ((and (memq t1 '(array simple-array)) (eq t2 'array)) (let ((e1 (car i1)) (e2 (car i2)) (d1 (cadr i1)) (d2 (cadr i2))) (cond ((and (eq e2 '*) (eq d2 '*)) (values t t)) ((or (eq e2 '*) (equal e1 e2) (equal (upgraded-array-element-type e1) (upgraded-array-element-type e2))) (values (dimension-subtypep d1 d2) t)) (t (values nil t))))) ((and (memq t1 '(array simple-array)) (eq t2 'string)) (let ((element-type (car i1)) (dim (cadr i1)) (size (car i2))) (unless (%subtypep element-type 'character) (return-from %subtypep (values nil t))) (when (integerp size) (if (and (consp dim) (= (length dim) 1) (eql (%car dim) size)) (return-from %subtypep (values t t)) (return-from %subtypep (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from %subtypep (values t t)) (return-from %subtypep (values nil t)))))) ((and (eq t1 'simple-array) (eq t2 'simple-string)) (let ((element-type (car i1)) (dim (cadr i1)) (size (car i2))) (unless (%subtypep element-type 'character) (return-from %subtypep (values nil t))) (when (integerp size) (if (and (consp dim) (= (length dim) 1) (eql (%car dim) size)) (return-from %subtypep (values t t)) (return-from %subtypep (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from %subtypep (values t t)) (return-from %subtypep (values nil t)))))) ((and (memq t1 '(string simple-string)) (eq t2 'array)) (let ((element-type (car i2)) (dim (cadr i2)) (size (car i1))) (unless (eq element-type '*) (return-from %subtypep (values nil t))) (when (integerp size) (if (or (eq dim '*) (and (consp dim) (= (length dim) 1) (eql (%car dim) size))) (return-from %subtypep (values t t)) (return-from %subtypep (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eq dim '*) (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from %subtypep (values t t)) (return-from %subtypep (values nil t)))))) ((eq t2 'simple-array) (case t1 (simple-array (let ((e1 (car i1)) (e2 (car i2)) (d1 (cadr i1)) (d2 (cadr i2))) (cond ((and (eq e2 '*) (eq d2 '*)) (values t t)) ((or (eq e2 '*) (equal e1 e2) (equal (upgraded-array-element-type e1) (upgraded-array-element-type e2))) (values (dimension-subtypep d1 d2) t)) (t (values nil t))))) ((simple-string simple-bit-vector) (let ((element-type (car i2)) (dim (cadr i2)) (size (car i1))) (unless (eq element-type '*) (return-from %subtypep (values nil t))) (when (integerp size) (if (or (eq dim '*) (and (consp dim) (= (length dim) 1) (eql (%car dim) size))) (return-from %subtypep (values t t)) (return-from %subtypep (values nil t)))) (when (or (null size) (eql size '*)) (if (or (eq dim '*) (eql dim 1) (and (consp dim) (= (length dim) 1))) (return-from %subtypep (values t t)) (return-from %subtypep (values nil t)))))) (t (values nil t)))) ((eq t2 'bit-vector) (let ((size1 (car i1)) (size2 (car i2))) (case t1 ((bit-vector simple-bit-vector) (values (if (or (eq size2 '*) (eql size1 size2)) t nil) t)) (t (values nil t))))) ((classp t2) (let ((class-name (class-name t2))) (cond ((eq class-name t1) (values t t)) ((and (eq class-name 'array) (memq t1 '(array simple-array vector simple-vector string simple-string simple-base-string bit-vector simple-bit-vector))) (values t t)) ((eq class-name 'vector) (cond ((memq t1 '(string simple-string)) (values t t)) ((memq t1 '(array simple-array)) (let ((dim (cadr i1))) (if (or (eql dim 1) (and (consp dim) (= (length dim) 1))) (values t t) (values nil t)))) (t (values nil t)))) ((and (eq class-name 'simple-vector) (eq t1 'simple-array)) (let ((dim (cadr i1))) (if (or (eql dim 1) (and (consp dim) (= (length dim) 1))) (values t t) (values nil t)))) ((and (eq class-name 'bit-vector) (eq t1 'simple-bit-vector)) (values t t)) ((and (eq class-name 'string) (memq t1 '(string simple-string))) (values t t)) (t (values nil nil))))) (t (values nil nil))))) (defun subtypep (type1 type2 &optional environment) (%subtypep type1 type2 environment)) abcl-src-1.9.0/src/org/armedbear/lisp/tailp.lisp0100644 0000000 0000000 00000003301 14223403213 020176 0ustar000000000 0000000 ;;; tailp.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "COMMON-LISP") (defun tailp (object list) (do ((list list (cdr list))) ((atom list) (eql list object)) (if (eql object list) (return t)))) abcl-src-1.9.0/src/org/armedbear/lisp/threads.lisp0100644 0000000 0000000 00000011647 14202767264 020553 0ustar000000000 0000000 ;;; threads.lisp ;;; ;;; Copyright (C) 2009-2010 Erik Huelsmann ;;; ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:threads) (export '(make-mailbox mailbox-send mailbox-empty-p mailbox-read mailbox-peek make-thread-lock with-thread-lock current-thread yield make-mutex get-mutex release-mutex with-mutex)) ;; ;; MAKE-THREAD helper to establish restarts ;; (defun thread-function-wrapper (fun) (restart-case (funcall fun) (abort () :report "Abort thread."))) ;; ;; Mailbox implementation ;; ;; this export statement is also in autoloads.lisp (export '(make-mailbox mailbox-send mailbox-empty-p mailbox-read mailbox-peek)) (defstruct mailbox "A first-in-first out queue of messages" queue) (defun mailbox-send (mailbox item) "Sends an item into the mailbox, notifying 1 waiter to wake up for retrieval of that object." (threads:synchronized-on mailbox (push item (mailbox-queue mailbox)) (threads:object-notify mailbox))) (defun mailbox-empty-p (mailbox) "Returns non-NIL if the mailbox can be read from, NIL otherwise." ;; Because we're just checking the value of an object reference, ;; (which are atomically gotten and set) we don't need to lock ;; the mailbox before operating on it. (null (mailbox-queue mailbox))) (defun mailbox-read (mailbox) "Blocks on the mailbox until an item is available for reading. When an item is available, it is returned." (threads:synchronized-on mailbox (loop (unless (mailbox-empty-p mailbox) (return)) (object-wait mailbox)) (pop (mailbox-queue mailbox)))) (defun mailbox-peek (mailbox) "Returns two values. The second returns non-NIL when the mailbox is empty. The first is the next item to be read from the mailbox. Note that due to multi-threading, the first value returned upon peek, may be different from the one returned upon next read in the calling thread." (threads:synchronized-on mailbox (values (car (mailbox-queue mailbox)) (null (mailbox-queue mailbox))))) ;; ;; Mutex implementation ;; ;; this export statement is also in autoloads.lisp (export '(make-mutex get-mutex release-mutex)) (defstruct mutex "An object used as a mutex lock" in-use) (defun get-mutex (mutex) "Acquires the lock associated with the MUTEX" (synchronized-on mutex (loop while (mutex-in-use mutex) do (object-wait mutex)) (setf (mutex-in-use mutex) T))) (defun release-mutex (mutex) "Releases a lock associated with MUTEX" (synchronized-on mutex (setf (mutex-in-use mutex) NIL) (object-notify mutex))) (defmacro with-mutex ((mutex) &body body) "Acquires a lock on MUTEX, executes BODY, and then releases the lock" (let ((m (gensym))) `(let ((,m ,mutex)) (when (get-mutex ,m) (unwind-protect (progn ,@body) (release-mutex ,m)))))) ;; ;; Lock implementation ;; (defun make-thread-lock () "Returns an object to be used with the WITH-THREAD-LOCK macro." (gensym)) (defmacro with-thread-lock ((lock) &body body) "Acquires the LOCK, executes BODY and releases the LOCK" (let ((glock (gensym))) `(let ((,glock ,lock)) (synchronized-on ,glock ,@body)))) (defun yield () "A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint. See java.lang.Thread.yield()." (java:jcall "yield" (JAVA:jstatic "currentThread" "java.lang.Thread"))) abcl-src-1.9.0/src/org/armedbear/lisp/time.lisp0100644 0000000 0000000 00000013602 14223403213 020030 0ustar000000000 0000000 ;;; time.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package #:system) (defconstant seconds-in-week (* 60 60 24 7)) (defconstant weeks-offset 2145) (defconstant seconds-offset 432000) (defconstant minutes-per-day (* 24 60)) (defconstant quarter-days-per-year (1+ (* 365 4))) (defconstant quarter-days-per-century 146097) (defconstant november-17-1858 678882) (defconstant weekday-november-17-1858 2) ;;; decode-universal-time universal-time &optional time-zone ;;; => second minute hour date month year day daylight-p zone ;;; If time-zone is not supplied, it defaults to the current time zone adjusted ;;; for daylight saving time. If time-zone is supplied, daylight saving time ;;; information is ignored. The daylight saving time flag is nil if time-zone ;;; is supplied. (defun decode-universal-time (universal-time &optional time-zone) (let (seconds-west daylight) (if time-zone (setf seconds-west (* time-zone 3600) daylight nil) (multiple-value-bind (time-zone daylight-p) (ext:get-time-zone universal-time) (setf seconds-west (* time-zone 3600) daylight daylight-p))) (multiple-value-bind (weeks secs) (truncate (+ (- universal-time seconds-west) seconds-offset) seconds-in-week) (let ((weeks (+ weeks weeks-offset))) (multiple-value-bind (t1 second) (truncate secs 60) (let ((tday (truncate t1 minutes-per-day))) (multiple-value-bind (hour minute) (truncate (- t1 (* tday minutes-per-day)) 60) (let* ((t2 (1- (* (+ (* weeks 7) tday november-17-1858) 4))) (tcent (truncate t2 quarter-days-per-century))) (setq t2 (mod t2 quarter-days-per-century)) (setq t2 (+ (- t2 (mod t2 4)) 3)) (let* ((year (+ (* tcent 100) (truncate t2 quarter-days-per-year))) (days-since-mar0 (1+ (truncate (mod t2 quarter-days-per-year) 4))) (day (mod (+ tday weekday-november-17-1858) 7)) (t3 (+ (* days-since-mar0 5) 456))) (cond ((>= t3 1989) (setq t3 (- t3 1836)) (setq year (1+ year)))) (multiple-value-bind (month t3) (truncate t3 153) (let ((date (1+ (truncate t3 5)))) (values second minute hour date month year day daylight (if daylight (1+ (/ seconds-west 3600)) (/ seconds-west 3600)))))))))))))) (defun get-decoded-time () (decode-universal-time (get-universal-time))) (defun pick-obvious-year (year) (declare (type (mod 100) year)) (let* ((current-year (nth-value 5 (get-decoded-time))) (guess (+ year (* (truncate (- current-year 50) 100) 100)))) (declare (type (integer 1900 9999) current-year guess)) (if (> (- current-year guess) 50) (+ guess 100) guess))) (defun leap-years-before (year) (let ((years (- year 1901))) (+ (- (truncate years 4) (truncate years 100)) (truncate (+ years 300) 400)))) (defvar *days-before-month* #.(let ((reversed-result nil) (sum 0)) (push nil reversed-result) (dolist (days-in-month '(31 28 31 30 31 30 31 31 30 31 30 31)) (push sum reversed-result) (incf sum days-in-month)) (coerce (nreverse reversed-result) 'simple-vector))) (defun encode-universal-time (second minute hour date month year &optional time-zone) (let* ((year (if (< year 100) (pick-obvious-year year) year)) (days (+ (1- date) (aref *days-before-month* month) (if (> month 2) (leap-years-before (1+ year)) (leap-years-before year)) (* (- year 1900) 365))) (hours (+ hour (* days 24)))) (cond (time-zone (+ second (* (+ minute (* (+ hours time-zone) 60)) 60))) (t (let* ((tz-guess (ext:get-time-zone (* hours 3600))) (guess (+ second (* 60 (+ minute (* 60 (+ hours tz-guess)))))) (tz (get-time-zone guess))) (+ guess (* 3600 (- tz tz-guess)))))))) abcl-src-1.9.0/src/org/armedbear/lisp/top-level.lisp0100644 0000000 0000000 00000035372 14223403213 021011 0ustar000000000 0000000 ;;; top-level.lisp ;;; ;;; Copyright (C) 2003-2006 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SB-ACLREPL (originally written by Kevin Rosenberg). (in-package #:top-level) (require 'inspect) (defvar *null-cmd* (gensym)) (defvar *handled-cmd* (gensym)) (defvar *command-char* #\:) (defvar *cmd-number* 1 "Number of the next command") (defun prompt-package-name () (let ((result (package-name *package*))) (dolist (nickname (package-nicknames *package*)) (when (< (length nickname) (length result)) (setf result nickname))) result)) (defun repl-prompt-fun (stream) (fresh-line stream) (when (> *debug-level* 0) (sys::%format stream "[~D~A] " *debug-level* (if sys::*inspect-break* "i" ""))) (sys::%format stream "~A(~D): " (prompt-package-name) *cmd-number*)) (defparameter *repl-prompt-fun* #'repl-prompt-fun) (defun peek-char-non-whitespace (stream) (loop (let ((c (read-char stream nil))) (when (null c) ; control d (quit)) (unless (eql c #\space) (unread-char c stream) (return c))))) (defun apropos-command (args) (when args (apropos args))) (defun continue-command (args) (when args (let ((n (read-from-string args))) (let ((restarts (compute-restarts))) (when (< -1 n (length restarts)) (invoke-restart-interactively (nth n restarts))))))) (defun describe-command (args) (let ((obj (eval (read-from-string args)))) (describe obj))) (defun error-command (ignored) (declare (ignore ignored)) (when *debug-condition* (let* ((s (sys::%format nil "~A" *debug-condition*)) (len (length s))) (when (plusp len) (setf (schar s 0) (char-upcase (schar s 0))) (unless (eql (schar s (1- len)) #\.) (setf s (concatenate 'string s ".")))) (sys::%format *debug-io* "~A~%" s)) (show-restarts (compute-restarts) *debug-io*))) (defun print-frame (frame stream &key prefix) (when prefix (write-string prefix stream)) (etypecase frame (sys::lisp-stack-frame (let ((frame (sys:frame-to-list frame))) (pprint-logical-block (stream nil :prefix "(" :suffix ")") (ignore-errors (prin1 (car frame) stream) (let ((args (cdr frame))) (if (listp args) (format stream "~{ ~_~S~}" args) (format stream " ~S" args))))))) (sys::java-stack-frame (write-string (sys:frame-to-string frame) stream)))) (defun backtrace-command (args) (let ((count (or (and args (ignore-errors (parse-integer args))) 8)) (n 0)) (with-standard-io-syntax (let ((*print-pretty* t) (*print-readably* nil) (*print-structure* nil) (*print-array* nil)) (dolist (frame *saved-backtrace*) (fresh-line *debug-io*) (print-frame frame *debug-io* :prefix (format nil "~3D: " n)) (incf n) (when (>= n count) (fresh-line *debug-io*) (return)))))) (fresh-line *debug-io*) (values)) (defun frame-command (args) (let* ((n (or (and args (ignore-errors (parse-integer args))) 0)) (frame (nth n *saved-backtrace*))) (when frame (with-standard-io-syntax (let ((*print-pretty* t) (*print-readably* nil) (*print-structure* nil)) (fresh-line *debug-io*) (print-frame frame *debug-io*))) (setf *** ** ** * * frame))) (values)) (defun inspect-command (args) (let ((obj (eval (read-from-string args)))) (inspect obj))) (defun istep-command (args) (sys::istep args)) (defun macroexpand-command (args) (let ((s (with-output-to-string (stream) (pprint (macroexpand (read-from-string args)) stream)))) (write-string (string-left-trim '(#\return #\linefeed) s))) (values)) (defvar *old-package* nil) (defun package-command (args) (cond ((null args) (sys::%format *standard-output* "The ~A package is current.~%" (package-name *package*))) ((and *old-package* (string= args "-") (null (find-package "-"))) (rotatef *old-package* *package*)) (t (when (and (plusp (length args)) (eql (char args 0) #\:)) (setf args (subseq args 1))) (setf args (nstring-upcase args)) (let ((pkg (find-package args))) (if pkg (setf *old-package* *package* *package* pkg) (sys::%format *standard-output* "Unknown package ~A.~%" args)))))) (defun reset-command (ignored) (declare (ignore ignored)) (invoke-restart 'top-level)) (defun exit-command (ignored) (declare (ignore ignored)) (exit)) (defvar *old-pwd* nil) (defun cd-command (args) (cond ((null args) (setf args (if (featurep :windows) "C:\\" (namestring (user-homedir-pathname))))) ((string= args "-") (if *old-pwd* (setf args (namestring *old-pwd*)) (progn (sys::%format t "No previous directory.") (return-from cd-command)))) ((and (> (length args) 1) (string= (subseq args 0 2) "~/") (setf args (concatenate 'string (namestring (user-homedir-pathname)) (subseq args 2)))))) (let ((dir (probe-directory args))) (if dir (progn (unless (equal dir *default-pathname-defaults*) (setf *old-pwd* *default-pathname-defaults* *default-pathname-defaults* dir)) (sys::%format t "~A" (namestring *default-pathname-defaults*))) (sys::%format t "Error: no such directory (~S).~%" args)))) (defun ls-command (args) (let ((args (if (stringp args) args "")) (ls-program (if (featurep :windows) "dir" "ls"))) (run-shell-command (concatenate 'string ls-program " " args) :directory *default-pathname-defaults*)) (values)) (defun tokenize (string) (do* ((res nil) (string (string-left-trim " " string) (string-left-trim " " (subseq string end))) (end (position #\space string) (position #\space string))) ((zerop (length string)) (nreverse res)) (unless end (setf end (length string))) (push (subseq string 0 end) res))) (defvar *last-files-loaded* nil) (defun ld-command (args) (let ((files (if args (tokenize args) *last-files-loaded*))) (setf *last-files-loaded* files) (dolist (file files) (load file)))) (defun cf-command (args) (let ((files (tokenize args))) (dolist (file files) (compile-file file)))) (defvar *last-files-cloaded* nil) (defun cload-command (args) (let ((files (if args (tokenize args) *last-files-cloaded*))) (setf *last-files-cloaded* files) (dolist (file files) (load (compile-file file))))) (defun rq-command (args) (let ((modules (tokenize (string-upcase args)))) (dolist (module modules) (require module)))) (defun pwd-command (ignored) (declare (ignore ignored)) (sys::%format t "~A~%" (namestring *default-pathname-defaults*))) (defun trace-command (args) (if (null args) (sys::%format t "~A~%" (sys::list-traced-functions)) (dolist (f (tokenize args)) (sys::trace-1 (read-from-string f))))) (defun untrace-command (args) (if (null args) (sys::untrace-all) (dolist (f (tokenize args)) (sys::untrace-1 (read-from-string f))))) (defconstant spaces (make-string 32 :initial-element #\space)) (defun pad (string width) (if (< (length string) width) (concatenate 'string string (subseq spaces 0 (- width (length string)))) string)) (defparameter *command-table* '(("apropos" "ap" apropos-command "apropos") ("bt" nil backtrace-command "backtrace n stack frames (default 8)") ("cd" nil cd-command "change default directory") ("cf" nil cf-command "compile file(s)") ("cload" "cl" cload-command "compile and load file(s)") ("continue" "cont" continue-command "invoke restart n") ("describe" "de" describe-command "describe an object") ("error" "err" error-command "print the current error message") ("exit" "ex" exit-command "exit lisp") ("frame" "fr" frame-command "set the value of cl:* to be frame n (default 0)") ("help" "he" help-command "print this help") ("inspect" "in" inspect-command "inspect an object") ("istep" "i" istep-command "navigate within inspection of an object") ("ld" nil ld-command "load a file") ("ls" nil ls-command "list directory") ("macroexpand" "ma" macroexpand-command "macroexpand an expression") ("package" "pa" package-command "change *PACKAGE*") ("pwd" "pw" pwd-command "print current directory") ("reset" "res" reset-command "return to top level") ("rq" nil rq-command "require a module") ("trace" "tr" trace-command "trace function(s)") ("untrace" "untr" untrace-command "untrace function(s)"))) (defun %help-command (prefix) (let ((prefix-len (length prefix))) (when (and (> prefix-len 0) (eql (schar prefix 0) *command-char*)) (setf prefix (subseq prefix 1)) (decf prefix-len)) (sys::%format t "~% COMMAND ABBR DESCRIPTION~%") (dolist (entry *command-table*) (when (or (null prefix) (and (<= prefix-len (length (entry-name entry))) (string-equal prefix (subseq (entry-name entry) 0 prefix-len)))) (sys::%format t " ~A~A~A~%" (pad (entry-name entry) 12) (pad (entry-abbreviation entry) 5) (entry-help entry)))) (sys::%format t "~%Commands must be prefixed by the command character, which is '~A'~A.~%~%" *command-char* (if (eql *command-char* #\:) " by default" "")))) (defun help-command (&optional ignored) (declare (ignore ignored)) (%help-command nil)) (defun entry-name (entry) (first entry)) (defun entry-abbreviation (entry) (second entry)) (defun entry-command (entry) (third entry)) (defun entry-help (entry) (fourth entry)) (defun find-command (string) (let ((len (length string))) (when (and (> len 0) (eql (schar string 0) *command-char*)) (setf string (subseq string 1) len (1- len))) (dolist (entry *command-table*) (when (or (string-equal string (entry-abbreviation entry)) (string-equal string (entry-name entry))) (return (entry-command entry)))))) (defun process-cmd (form) (when (eq form *null-cmd*) (return-from process-cmd t)) (when (and (stringp form) (> (length form) 1) (eql (char form 0) *command-char*)) (let* ((pos (or (position #\space form) (position #\return form))) (command-string (subseq form 0 pos)) (args (if pos (subseq form (1+ pos)) nil))) (let ((command (find-command command-string))) (cond ((null command) (sys::%format t "Unknown top-level command \"~A\".~%" command-string) (sys::%format t "Type \"~Ahelp\" for a list of available commands." *command-char*)) (t (when args (setf args (string-trim (list #\space #\return) args)) (when (zerop (length args)) (setf args nil))) (funcall command args))))) t)) (defun read-cmd (stream) (let ((c (peek-char-non-whitespace stream))) (cond ((eql c *command-char*) (let* ((input (read-line stream)) (name (symbol-name (read-from-string input)))) (if (find-command name) (progn (process-cmd input) *handled-cmd*) (read-from-string (concatenate 'string ":" name))))) ((eql c #\newline) (read-line stream) *null-cmd*) (t (read stream nil *null-cmd*))))) (defun repl-read-form-fun (in out) (loop (funcall *repl-prompt-fun* out) (finish-output out) (let ((form (read-cmd in))) (setf (charpos out) 0) (unless (eq form *null-cmd*) (incf *cmd-number*)) (cond ((or (eq form *null-cmd*) (eq form *handled-cmd*))) ((and (> *debug-level* 0) (fixnump form)) (let ((n form) (restarts (compute-restarts))) (if (< -1 n (length restarts)) (invoke-restart-interactively (nth n restarts)) (return form)))) (t (return form)))))) (defparameter *repl-read-form-fun* #'repl-read-form-fun) (defun repl (&optional (in *standard-input*) (out *standard-output*)) (loop (let* ((form (funcall *repl-read-form-fun* in out)) (results (multiple-value-list (sys:interactive-eval form)))) (dolist (result results) (fresh-line out) (prin1 result out))))) (defun top-level-loop () (fresh-line) (unless sys:*noinform* (sys::%format t "Type \"~Ahelp\" for a list of available commands.~%" *command-char*)) (loop (setf *inspected-object* nil *inspected-object-stack* nil *inspect-break* nil) (with-simple-restart (top-level "Return to top level.") (if (featurep :j) (handler-case (repl) (stream-error (c) (declare (ignore c)) (return-from top-level-loop))) (repl))))) abcl-src-1.9.0/src/org/armedbear/lisp/trace.lisp0100644 0000000 0000000 00000012770 14223403213 020175 0ustar000000000 0000000 ;;; trace.lisp ;;; ;;; Copyright (C) 2003-2007 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (export 'untraced-function) ;; For FIND-GENERIC-FUNCTION in clos.lisp. (require "FORMAT") (defvar *trace-info-hashtable* (make-hash-table :test #'equal)) (defstruct trace-info name untraced-function breakp) (defvar *trace-depth* 0 "Current depth of stack push for use of TRACE facility.") (defun list-traced-functions () (copy-list *traced-names*)) (defmacro trace (&rest args) (if args (expand-trace args) `(list-traced-functions))) (defun expand-trace (args) (let ((results ()) (breakp nil)) (let ((index (position :break args))) (when index (setf breakp (nth (1+ index) args)) (setf args (append (subseq args 0 index) (subseq args (+ index 2)))))) (dolist (arg args) (push `(trace-1 ',arg (make-trace-info :name ',arg :breakp ,breakp)) results)) `(list ,@(nreverse results)))) (defun trace-1 (name info) (unless (fboundp name) (error "~S is not the name of a function." name)) (if (member name *traced-names* :test #'equal) (format t "~S is already being traced." name) (let* ((untraced-function (fdefinition name)) (traced-function (traced-function name info untraced-function))) (setf (trace-info-untraced-function info) untraced-function) (let ((*warn-on-redefinition* nil)) (setf (fdefinition name) traced-function)) (setf (gethash name *trace-info-hashtable*) info) (push name *traced-names*))) name) (defun traced-function (name info untraced-function) (let ((breakp (trace-info-breakp info)) (*trace-depth* *trace-depth*)) (lambda (&rest args) (with-standard-io-syntax (let ((*print-readably* nil) (*print-structure* nil)) (format *trace-output* (indent "~D: ~S~%") *trace-depth* (cons name args)))) (when breakp (break)) (incf *trace-depth*) (let ((results (multiple-value-list (unwind-protect (apply untraced-function args) (decf *trace-depth*))))) (with-standard-io-syntax (let ((*print-readably* nil) (*print-structure* nil)) (format *trace-output* (indent "~D: ~A returned") *trace-depth* name) (if results (dolist (result results) (format *trace-output* " ~S" result)) (format *trace-output* " no values")) (terpri *trace-output*))) (values-list results))))) (defun untraced-function (name) (let ((info (gethash name *trace-info-hashtable*))) (and info (trace-info-untraced-function info)))) (defun trace-redefined-update (name untraced-function) (when (and *traced-names* (find name *traced-names* :test #'equal)) (let* ((info (gethash name *trace-info-hashtable*)) (traced-function (traced-function name info untraced-function))) (setf (trace-info-untraced-function info) untraced-function) (let ((*traced-names* '())) (setf (fdefinition name) traced-function))))) (defun indent (string) (concatenate 'string (make-string (* (1+ *trace-depth*) 2) :initial-element #\space) string)) (defmacro untrace (&rest args) (cond ((null args) `(untrace-all)) (t `(progn ,@(mapcar (lambda (arg) `(untrace-1 ',arg)) args) t)))) (defun untrace-all () (dolist (arg *traced-names*) (untrace-1 arg)) t) (defun untrace-1 (name) (cond ((member name *traced-names* :test #'equal) (let* ((trace-info (gethash name *trace-info-hashtable*)) (untraced-function (trace-info-untraced-function trace-info)) (*warn-on-redefinition* nil)) (remhash name *trace-info-hashtable*) (setf *traced-names* (remove name *traced-names*)) (setf (fdefinition name) untraced-function))) (t (format t "~S is not being traced.~%" name))) nil) abcl-src-1.9.0/src/org/armedbear/lisp/tree-equal.lisp0100644 0000000 0000000 00000004516 14223403213 021142 0ustar000000000 0000000 ;;; tree-equal.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") ;;; From SBCL. (defun tree-equal-test-not (x y test-not) (cond ((consp x) (and (consp y) (tree-equal-test-not (car x) (car y) test-not) (tree-equal-test-not (cdr x) (cdr y) test-not))) ((consp y) nil) ((not (funcall test-not x y)) t) (t ()))) (defun tree-equal-test (x y test) (cond ((consp x) (and (consp y) (tree-equal-test (car x) (car y) test) (tree-equal-test (cdr x) (cdr y) test))) ((consp y) nil) ((funcall test x y) t) (t ()))) (defun tree-equal (x y &key (test #'eql testp) (test-not nil notp)) (when (and testp notp) (error "test and test-not both supplied")) (if test-not (tree-equal-test-not x y test-not) (tree-equal-test x y test))) abcl-src-1.9.0/src/org/armedbear/lisp/truncate.java0100644 0000000 0000000 00000004012 14202767264 020704 0ustar000000000 0000000 /* * truncate.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; // ### truncate number &optional divisor public final class truncate extends Primitive { private truncate() { super("truncate", "number &optional divisor"); } @Override public LispObject execute(LispObject arg) { return arg.truncate(Fixnum.ONE); } @Override public LispObject execute(LispObject first, LispObject second) { return first.truncate(second); } private static final Primitive TRUNCATE = new truncate(); } abcl-src-1.9.0/src/org/armedbear/lisp/typep.lisp0100644 0000000 0000000 00000016315 14223403213 020237 0ustar000000000 0000000 ;;; typep.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun simple-array-p (object) (and (arrayp object) (not (array-has-fill-pointer-p object)) (multiple-value-bind (displaced-to offset) (array-displacement object) (and (null displaced-to) (zerop offset))))) (defun in-interval-p (x interval) (if (endp interval) t (let ((low (%car interval)) (high (if (endp (%cdr interval)) '* (%cadr interval)))) (cond ((eq low '*)) ((consp low) (when (<= x (%car low)) (return-from in-interval-p nil))) ((when (< x low) (return-from in-interval-p nil)))) (cond ((eq high '*)) ((consp high) (when (>= x (%car high)) (return-from in-interval-p nil))) ((when (> x high) (return-from in-interval-p nil)))) t))) (defun match-dimensions (dim pat) (if (null dim) (null pat) (and (or (eq (car pat) '*) (eql (car dim) (car pat))) (match-dimensions (cdr dim) (cdr pat))))) (defun %typep (object type) (when (atom type) (when (eq type 'values) (error 'simple-error :format-control "The symbol ~S is not valid as a type specifier." :format-arguments (list type))) (unless (and (symbolp type) (get type 'deftype-definition)) (return-from %typep (simple-typep object type)))) (setf type (normalize-type type)) (when (atom type) (return-from %typep (simple-typep object type))) (let ((tp (%car type)) (i (%cdr type))) (case tp (INTEGER (and (integerp object) (in-interval-p object i))) (RATIONAL (and (rationalp object) (in-interval-p object i))) ((FLOAT SINGLE-FLOAT DOUBLE-FLOAT SHORT-FLOAT LONG-FLOAT) (and (floatp object) (in-interval-p object i))) (REAL (and (realp object) (in-interval-p object i))) (COMPLEX (and (complexp object) (or (null i) (and (typep (realpart object) i) (typep (imagpart object) i))))) (CONS (and (consp object) (or (null (car i)) (eq (car i) '*) (%typep (%car object) (car i))) (or (null (cadr i)) (eq (cadr i) '*) (%typep (%cdr object) (cadr i))))) (SIMPLE-BIT-VECTOR (and (simple-bit-vector-p object) (or (endp i) (eq (%car i) '*) (eql (%car i) (array-dimension object 0))))) (BIT-VECTOR (and (bit-vector-p object) (or (endp i) (eq (%car i) '*) (eql (%car i) (array-dimension object 0))))) (SIMPLE-STRING (and (simple-string-p object) (or (endp i) (eq (%car i) '*) (eql (%car i) (array-dimension object 0))))) (STRING (and (stringp object) (or (endp i) (eq (%car i) '*) (eql (%car i) (array-dimension object 0))))) (SIMPLE-VECTOR (and (simple-vector-p object) (or (endp i) (eq (%car i) '*) (eql (%car i) (array-dimension object 0))))) (VECTOR (and (vectorp object) (or (endp i) (eq (%car i) '*) (and (eq (%car i) t) (not (stringp object)) (not (bit-vector-p object))) (and (stringp object) (%subtypep (%car i) 'character)) (equal (array-element-type object) (%car i))) (or (endp (cdr i)) (eq (%cadr i) '*) (eql (%cadr i) (array-dimension object 0))))) (SIMPLE-ARRAY (and (simple-array-p object) (or (endp i) (eq (%car i) '*) (equal (array-element-type object) (upgraded-array-element-type (%car i)))) (or (endp (cdr i)) (eq (%cadr i) '*) (if (listp (%cadr i)) (match-dimensions (array-dimensions object) (%cadr i)) (eql (array-rank object) (%cadr i)))))) (ARRAY (and (arrayp object) (or (endp i) (eq (%car i) '*) (equal (array-element-type object) (upgraded-array-element-type (%car i)))) (or (endp (cdr i)) (eq (%cadr i) '*) (if (listp (%cadr i)) (match-dimensions (array-dimensions object) (%cadr i)) (eql (array-rank object) (%cadr i)))))) (AND (dolist (type i) (unless (%typep object type) (return-from %typep nil))) t) (OR (dolist (type i) (when (%typep object type) (return-from %typep t))) nil) (NOT (not (%typep object (car i)))) (MEMBER (member object i)) (EQL (eql object (car i))) (SATISFIES (unless (symbolp (car i)) (error 'simple-type-error :datum (car i) :expected-type 'symbol :format-control "The SATISFIES predicate name is not a symbol: ~S" :format-arguments (list (car i)))) (funcall (car i) object)) (NIL-VECTOR (and (simple-typep object 'nil-vector) (or (endp i) (eql (%car i) (length object))))) (MOD (and (integerp object) (or (zerop object) (and (plusp object) (< object (second type)))))) ((FUNCTION VALUES) (error 'simple-error :format-control "~S types are not a legal argument to TYPEP: ~S" :format-arguments (list tp type))) (t nil)))) (defun typep (object type &optional environment) (declare (ignore environment)) (%typep object type)) abcl-src-1.9.0/src/org/armedbear/lisp/unbound_slot_instance.java0100644 0000000 0000000 00000004113 14202767264 023460 0ustar000000000 0000000 /* * unbound_slot_instance.java * * Copyright (C) 2004 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; // ### unbound-slot-instance public final class unbound_slot_instance extends Primitive { private unbound_slot_instance() { super("unbound-slot-instance"); } @Override public LispObject execute(LispObject arg) { if (arg instanceof UnboundSlot) return ((UnboundSlot)arg).getInstance(); return type_error(arg, Symbol.UNBOUND_SLOT); } private static final unbound_slot_instance CELL_ERROR_NAME = new unbound_slot_instance(); } abcl-src-1.9.0/src/org/armedbear/lisp/unzip.java0100644 0000000 0000000 00000011777 14202767264 020244 0ustar000000000 0000000 /* * unzip.java * * Copyright (C) 2010 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.InputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @DocString(name="unzip", args="pathname &optional directory => unzipped_pathnames", doc="Unpack zip archive at PATHNAME returning a list of extracted pathnames.\nIf the optional DIRECTORY is specified, root the abstraction in that directory, otherwise use the current value of *DEFAULT-PATHNAME-DEFAULTS*.") public final class unzip extends Primitive { public unzip() { super("unzip", PACKAGE_SYS, true, "pathname &optional directory => unzipped_pathnames"); } @Override public LispObject execute(LispObject first) { Pathname zipFile = coerceToPathname(first); Pathname directory = coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()); return unzipToDirectory(zipFile, directory); } @Override public LispObject execute(LispObject first, LispObject second) { Pathname zipFile = coerceToPathname(first); Pathname directory = coerceToPathname(second); directory.setName(NIL); directory.setType(NIL); return unzipToDirectory(zipFile, directory); } private LispObject unzipToDirectory(Pathname zipPath, Pathname dirPath) { if (!zipPath.isAbsolute()) { zipPath = Pathname.mergePathnames(zipPath, coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue())); } LispObject o = Symbol.PROBE_FILE.execute(zipPath); if (!(o instanceof Pathname)) { return error(new FileError("No file found: " + zipPath, zipPath)); } String zip = ((Pathname)o).getNamestring(); if (zip == null) { return error(new FileError("Pathname has no namestring: " + zip, zipPath)); } String dir = dirPath.getNamestring(); if (dir == null) { return error(new FileError("Could not parse diretory: " + dirPath, dirPath)); } LispObject result = NIL; try { ZipFile zipfile = new ZipFile(zip); byte[] buffer = new byte[4096]; for (Enumeration entries = zipfile.entries();entries.hasMoreElements();) { ZipEntry entry = entries.nextElement(); String name = entry.getName(); String filename = dir + name; File file = new File(filename); if (entry.isDirectory()) { file.mkdirs(); continue; } FileOutputStream out = new FileOutputStream(file); InputStream in = zipfile.getInputStream(entry); int n; while ((n = in.read(buffer)) > 0) { out.write(buffer, 0, n); } out.close(); in.close(); result = result.push(Pathname.create(filename)); } } catch (IOException e) { return error(new FileError("Failed to unzip " + "'" + zipPath + "'" + " into " + "'" + dirPath + "'" + ": " + e, zipPath)); } return result; } private static final Primitive unzip = new unzip(); } abcl-src-1.9.0/src/org/armedbear/lisp/upgraded-complex-part-type.lisp0100644 0000000 0000000 00000003530 14202767264 024274 0ustar000000000 0000000 ;;; upgraded-complex-part-type.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (defun upgraded-complex-part-type (typespec &optional environment) (declare (ignore environment)) (if (subtypep typespec 'REAL) typespec (error 'simple-error :format-control "The type ~S is not a subtype of ~S." :format-arguments (list typespec 'REAL)))) abcl-src-1.9.0/src/org/armedbear/lisp/util/DecodingReader.java0100644 0000000 0000000 00000023176 14202767264 022707 0ustar000000000 0000000 /* * DecodingStreamReader.java * * Copyright (C) 2010 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp.util; import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; import java.io.PushbackReader; import java.io.Reader; import java.io.StringReader; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; import org.armedbear.lisp.Debug; /** Class to support mid-stream change of character encoding * to support setExternalFormat operation in Stream.java * * Note: extends PushbackReader, but only for its interface; * all methods are overridden. */ public class DecodingReader extends PushbackReader { // dummy reader which we need to call the Pushback constructor // because a null value won't work private static Reader staticReader = new StringReader(""); // contains the currently buffered bytes read from the stream private ByteBuffer bbuf; // stream to read from, wrapped in a PushbackInputStream private PushbackInputStream stream; // Decoder, used for decoding characters on the input stream private CharsetDecoder cd; // Encoder, used to put characters back on the input stream when unreading private CharsetEncoder ce; public DecodingReader(InputStream stream, int size, Charset cs) { super(staticReader); // pass a dummy stream value into the constructor // we need to be able to unread the byte buffer this.stream = new PushbackInputStream(stream, size); this.cd = cs.newDecoder(); this.cd.onUnmappableCharacter(CodingErrorAction.REPLACE); this.cd.onMalformedInput(CodingErrorAction.REPLACE); this.ce = cs.newEncoder(); bbuf = ByteBuffer.allocate(size); ((java.nio.Buffer)bbuf).flip(); // mark the buffer as 'needs refill' } /** Change the Charset used to decode bytes from the input stream * into characters. */ public final void setCharset(Charset cs) { this.cd = cs.newDecoder(); this.cd.onUnmappableCharacter(CodingErrorAction.REPLACE); this.cd.onMalformedInput(CodingErrorAction.REPLACE); this.ce = cs.newEncoder(); } /** Get the Charset used to decode bytes from the input stream. */ public final Charset getCharset() { return this.cd.charset(); } @Override public final void close() throws IOException { stream.close(); } @Override public final void mark(int readAheadLimit) throws IOException { throw new IOException("mark/reset not supported."); } @Override public final boolean markSupported() { return false; } @Override public final boolean ready() throws IOException { return stream.available() != 0 || bbuf.remaining() != 0; } @Override public final void reset() throws IOException { throw new IOException("reset/mark not supported."); } /** Skips 'n' characters, or as many as can be read off the stream * before its end. * * Returns the number of characters actually skipped */ @Override public final long skip(long n) throws IOException { char[] cbuf = new char[(int)Math.min(4096, n)]; long m = n; while (m > 0) { int r = read(cbuf, 0, (int)Math.min(cbuf.length, m)); if (r < 0) return (n - m); m += Math.min(cbuf.length, m); } return n; } /** Unread a single code point. * * Decomposes the code point into UTF-16 surrogate pairs * and unreads them using the char[] unreader function. * */ @Override public final void unread(int c) throws IOException { char[] ch = Character.toChars(c); unread(ch, 0, ch.length); } /** Unread the character array into the reader. * * Decodes the characters in the array into bytes, * allowing the encoding to be changed before reading from * the stream again, using a different charset. */ @Override public final void unread(char[] cbuf, int off, int len) throws IOException { ByteBuffer tb = // temp buffer ce.encode(CharBuffer.wrap(cbuf, off, len)); if (tb.limit() > ((java.nio.Buffer)bbuf).position()) { // unread bbuf into the pushback input stream // in order to free up space for the content of 'tb' for (int i = ((java.nio.Buffer)bbuf).limit(); i-- > ((java.nio.Buffer)bbuf).position(); ) stream.unread(bbuf.get(i)); ((java.nio.Buffer)bbuf).clear(); ce.encode(CharBuffer.wrap(cbuf, off, len), bbuf, true); ((java.nio.Buffer)bbuf).flip(); } else { // Don't unread bbuf, since tb will fit in front of the // existing data int j = ((java.nio.Buffer)bbuf).position() - 1; for (int i = ((java.nio.Buffer)tb).limit(); i-- > 0; j--) // two-counter loop bbuf.put(j, tb.get(i)); ((java.nio.Buffer)bbuf).position(j+1); } } @Override public final void unread(char[] cbuf) throws IOException { unread(cbuf, 0, cbuf.length); } // fill bbuf, either when empty or when forced private boolean ensureBbuf(boolean force) throws IOException { if (bbuf.remaining() == 0 || force) { bbuf.compact(); int size = stream.available(); if (size > bbuf.remaining() || size == 0) // by reading more than the available bytes when // none available, block only if we need to on // interactive streams size = bbuf.remaining(); byte[] by = new byte[size]; int c = stream.read(by); if (c < 0) { ((java.nio.Buffer)bbuf).flip(); // prepare bbuf for reading return false; } bbuf.put(by, 0, c); ((java.nio.Buffer)bbuf).flip(); } return true; } @Override public final int read() throws IOException { // read the first UTF-16 character char[] ch = new char[1]; int i = read(ch, 0, 1); if (i < 0) return i; // if this is not a high surrogate, // it must be a character which doesn't need one if (! Character.isHighSurrogate(ch[0])) return ch[0]; // save the high surrogate and read the low surrogate char high = ch[0]; i = read(ch, 0, 1); if (i < 0) return i; // combine the two and return the resulting code point return Character.toCodePoint(high, ch[0]); } @Override public final int read(char[] cbuf, int off, int len) throws IOException { CharBuffer cb = CharBuffer.wrap(cbuf, off, len); return read(cb); } @Override public final int read(CharBuffer cb) throws IOException { int len = cb.remaining(); boolean notEof = true; boolean forceRead = false; while (cb.remaining() > 0 && notEof) { int oldRemaining = cb.remaining(); notEof = ensureBbuf(forceRead); CoderResult r = cd.decode(bbuf, cb, ! notEof); if (oldRemaining == cb.remaining() && CoderResult.OVERFLOW == r) { // if this happens, the decoding failed // but the bufs didn't advance. Advance // them manually and do manual replacing, // otherwise we loop endlessly. This occurs // at least when parsing latin1 files with // lowercase o-umlauts in them. // Note that this is at the moment copy-paste // with RandomAccessCharacterFile.read() cb.put('?'); bbuf.get(); } forceRead = (CoderResult.UNDERFLOW == r); } if (cb.remaining() == len) return -1; else return len - cb.remaining(); } @Override public final int read(char[] cbuf) throws IOException { return read(cbuf, 0, cbuf.length); } } abcl-src-1.9.0/src/org/armedbear/lisp/util/Finalizer.java0100644 0000000 0000000 00000014316 14202767264 021767 0ustar000000000 0000000 /* * Finalizer.java * * Copyright (C) 2011 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp.util; import java.lang.ref.ReferenceQueue; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.WeakHashMap; /** Framework to monitor arbitrary objects to see if they have been * garbage collected, running one or more runnables when they have. */ public class Finalizer { /** Internal weak reference class which keeps a list of Runnables * with finalizing actions to be executed. */ private static class FinalizingWeakReference extends java.lang.ref.WeakReference { /** Queue of Runnables to be executed after the object is GC-ed. */ private LinkedList finalizers = new LinkedList(); FinalizingWeakReference(Object o, ReferenceQueue q, Runnable finalizer) { super(o, q); finalizers.add(finalizer); } /** Adds a finalizer. * * Finalizers will be run in reverse-registration order. * * @param finalizer The finalizer to be added. */ void addFinalizer(Runnable finalizer) { finalizers.add(finalizer); } /** Removes all registered finalizers. */ void cancelFinalizers() { finalizers.clear(); } /** Runs all finalizers registered. */ void run() { Iterator iterator = finalizers.iterator(); while (iterator.hasNext()) { iterator.next().run(); } } } /** Queue for FinalizingWeakReference objects which need * to have their references run because the associated * object has been garbage collected */ private static ReferenceQueue queue = null; /** A map from objects to their associated FinalizingWeakReferences * which is used by the routine which cancels finalization. */ private static Map references = null; /** A map which maps the finalizing references onto themselves. This map * makes sure that hard (as opposed to weak) references stay around to * prevent garbage collection of the FinalizingWeakReferences before the * referred objects are. */ private static Map anchor = null; /** Checks that the internal administration variables and thread have been * correctly set up. This solution allows the GC monitoring thread to be * started as late as its first use. */ synchronized private static void checkQueue() { if (queue == null) { queue = new ReferenceQueue(); references = Collections.synchronizedMap(new WeakHashMap()); anchor = Collections.synchronizedMap(new HashMap()); Thread handler = new Thread(new Runnable() { public void run() { while (true) { try { FinalizingWeakReference ref = (FinalizingWeakReference) queue.remove(); anchor.remove(ref); ref.run(); } catch (InterruptedException i) { } } } }, "ABCL finalizer"); handler.setPriority(Thread.MAX_PRIORITY); handler.setDaemon(true); handler.start(); } } /** Schedules a Runnable to be run after garbage collection of the object. * * Note that the Runnable can't contain references to the object to be * collected: it will disable garbage collection of the object. * * @param o The object to monitor for garbage collection * @param r The routine to be executed after GC-ing the object */ public static void addFinalizer(Object o, Runnable r) { if (queue == null) { checkQueue(); } FinalizingWeakReference ref = references.get(o); if (ref != null) { ref.addFinalizer(r); } else { ref = new FinalizingWeakReference(o, queue, r); references.put(o, ref); anchor.put(ref, ref); } } /** Cancels any references scheduled to be run after garbage * collection of the argument 'o'. * * @param o Object to cancel references for */ public static void clearFinalizers(Object o) { FinalizingWeakReference ref = references.get(o); if (ref != null) { ref.cancelFinalizers(); anchor.remove(ref); } } } abcl-src-1.9.0/src/org/armedbear/lisp/util/HttpHead.java0100644 0000000 0000000 00000013543 14202767264 021546 0ustar000000000 0000000 /* * HttpHead.java * * Copyright (C) 2010 Mark Evenson * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp.util; import org.armedbear.lisp.Debug; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.Proxy; import java.net.Socket; import java.net.URL; /** * Use HTTP/1.1 HEAD to retrieve the specified header field. */ public class HttpHead { static public String get(String urlString, String key) throws IOException { URL url = null; try { url = new URL(urlString); } catch (MalformedURLException e) { log("Failed to form url from " + "'" + urlString + "'" + ": " + e); } return get(url, key); } static public String get(URL url, String key) throws IOException { Socket socket = null; String result = null; try { String protocol = url.getProtocol(); if (!protocol.equals("http")) { log("The protocol " + "'" + protocol + "'" + " is not http."); return result; } String host = url.getHost(); int port = url.getPort(); if (port == -1) { port = 80; } socket = new Socket(host, port); PrintWriter out = null; BufferedReader in = null; try { socket.setSoTimeout(5000); // ms out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { log("Failed to establish socket io: " + e); return result; } String CRLF = "\r\n"; String head = "HEAD " + url.getPath() + " HTTP/1.1"; out.print(head + CRLF); out.print("Host: " + url.getAuthority() + CRLF); out.print("Connection: close" + CRLF); out.print(CRLF); out.flush(); String line = null; try { line = in.readLine(); } catch (IOException e) { log("Failed to read HTTP response: " + e); } if (line == null) { throw new IOException("Could not access URL to parse headers."); } String status[] = line.split("\\s"); if (status[1].equals("200")) { result = findHeader(in, key); } else if (status[1].startsWith("3")) { // Follow redirects ad nauseum String location = findHeader(in, "Location"); if (location != null) { return get(location, key); } } else { log("Unexpected response: " + line); } } finally { try { socket.close(); } catch (IOException e) { } } return result; } static private String findHeader(BufferedReader in, String key) { String result = null; String line; try { while ((line = in.readLine()) != null) { int i = line.indexOf(":"); if (i == -1) { continue; // XXX parse multi-line HTTP headers } String k = line.substring(0, i); String v = line.substring(i + 1).trim(); if (k.equals(key)) { result = v; break; } } } catch (IOException e) { log("Failed to read headers: " + e); } return result; } static private void log(String message) { Debug.warn(message); } public static void main(String argv[]) { if (argv.length != 1) { System.out.println("Usage: URL"); return; } String modified = null; try { modified = get(argv[0], "Last-Modified"); } catch (IOException ex) { System.err.println("Unable to get Last-Modified header: "); ex.printStackTrace(System.err); } if (modified != null) { System.out.println("Last-Modified: " + modified); } else { System.out.println("No result returned."); } } } abcl-src-1.9.0/src/org/armedbear/lisp/util/RACFMalformedInputException.java0100644 0000000 0000000 00000004750 14202767264 025306 0ustar000000000 0000000 /* * RACFMalformedInputException.java * * Copyright (C) 2009 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp.util; import java.nio.charset.MalformedInputException; /** Class - derived from MalformedInputException - * which holds information required to allow higher level * systems to invoke a lisp restart function to set replacement characters. */ public class RACFMalformedInputException extends MalformedInputException { final int position; final char character; final String charsetName; public RACFMalformedInputException(int position, char character, String charsetName) { super(1); // 1 == fake length this.position = position; this.character = character; this.charsetName = charsetName; } @Override public String getMessage() { return "Input value 0x" + Integer.toHexString(character) + " is malformed while recoding with charset " + charsetName; } public int getPosition() { return position; } } abcl-src-1.9.0/src/org/armedbear/lisp/util/RACFUnmappableCharacterException.java0100644 0000000 0000000 00000005000 14202767264 026246 0ustar000000000 0000000 /* * RACFUnmappableCharacterException.java * * Copyright (C) 2009 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp.util; import java.nio.charset.UnmappableCharacterException; /** Class - derived from UnmappableCharacterException - * which holds information required to allow higher level * systems to invoke a lisp restart function to set replacement characters. */ public class RACFUnmappableCharacterException extends UnmappableCharacterException { final int position; final char character; final String charsetName; public RACFUnmappableCharacterException(int position, char character, String charsetName) { super(1); // 1 == fake length this.position = position; this.character = character; this.charsetName = charsetName; } @Override public String getMessage() { return "Character \\U" + Integer.toHexString(character) + " can't be recoded using charset " + charsetName; } public int getPosition() { return position; } } abcl-src-1.9.0/src/org/armedbear/lisp/util/RandomAccessCharacterFile.java0100644 0000000 0000000 00000051275 14202767264 025030 0ustar000000000 0000000 /* * RandomAccessCharacterFile.java * * Copyright (C) 2008 Hideo at Yokohama * Copyright (C) 2008-2009 Erik Huelsmann * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, . * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp.util; import java.io.IOException; import java.io.PushbackInputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.io.PushbackReader; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderMalfunctionError; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; import java.nio.charset.UnsupportedCharsetException; import org.armedbear.lisp.Debug; import static org.armedbear.lisp.Lisp.error; import org.armedbear.lisp.SimpleError; import org.armedbear.lisp.SimpleString; public class RandomAccessCharacterFile { private class RandomAccessInputStream extends PushbackInputStream { public RandomAccessInputStream() { super(null); } private byte[] read_buf = new byte[1]; @Override public final int read() throws IOException { int len = read(read_buf); if (len == 1) { // byte is signed, char is unsigned, int is signed. // buf can hold 0xff, we want it as 0xff in int, not -1. return 0xff & (int) read_buf[0]; } else { return -1; } // ### BUG: 'int read()' is to return a *codepoint*, // not the half of a surrogate pair! } @Override public final int read(byte[] b, int off, int len) throws IOException { return RandomAccessCharacterFile.this.read(b, off, len); } @Override public final void unread(int b) throws IOException { RandomAccessCharacterFile.this.unreadByte((byte)b); } @Override public final void unread(byte[] b, int off, int len) throws IOException { for (int i = 0; i < len; i++) this.unread(b[off+i]); } @Override public final void unread(byte[] b) throws IOException { this.unread(b, 0, b.length); } @Override public final int available() throws IOException { return (int)(RandomAccessCharacterFile.this.length() - RandomAccessCharacterFile.this.position()); } @Override public final synchronized void mark(int readlimit) { } @Override public final boolean markSupported() { return false; } @Override public final synchronized void reset() throws IOException { throw new IOException("Operation not supported"); } @Override public final long skip(long n) throws IOException { RandomAccessCharacterFile.this.position(RandomAccessCharacterFile.this.position()+n); return n; } @Override public final int read(byte[] b) throws IOException { return this.read(b, 0, b.length); } @Override public final void close() throws IOException { RandomAccessCharacterFile.this.close(); } } private class RandomAccessOutputStream extends OutputStream { RandomAccessOutputStream() { } private byte[] buf = new byte[1]; public final void write(int b) throws IOException { buf[0] = (byte)b; RandomAccessCharacterFile.this.write(buf, 0, 1); } @Override public final void write(byte[] b) throws IOException { RandomAccessCharacterFile.this.write(b, 0, b.length); } @Override public final void write(byte[] b, int off, int len) throws IOException { RandomAccessCharacterFile.this.write(b, off, len); } @Override public final void flush() throws IOException { RandomAccessCharacterFile.this.flush(); } @Override public final void close() throws IOException { RandomAccessCharacterFile.this.close(); } } // dummy reader which we need to call the Pushback constructor // because a null value won't work static Reader staticReader = new StringReader(""); private class RandomAccessReader extends PushbackReader { RandomAccessReader() { // because we override all methods of Pushbackreader, // staticReader will never be referenced super(staticReader); } @Override public final void close() throws IOException { RandomAccessCharacterFile.this.close(); } private char[] read_buf = new char[1]; @Override public final int read() throws IOException { int n = this.read(read_buf); if (n == 1) return read_buf[0]; else return -1; // ### BUG: 'int read()' is to return a codepoint! // not the half of a surrogate pair! } @Override public final void unread(int c) throws IOException { RandomAccessCharacterFile.this.unreadChar((char)c); } @Override public final void unread(char[] cbuf, int off, int len) throws IOException { for (int i = 0; i < len; i++) this.unread(cbuf[off+i]); } @Override public final void unread(char[] cbuf) throws IOException { this.unread(cbuf, 0, cbuf.length); } @Override public final int read(CharBuffer target) throws IOException { //FIXME: to be implemented throw new IOException("Not implemented"); } @Override public final int read(char[] cbuf) throws IOException { return RandomAccessCharacterFile.this.read(cbuf, 0, cbuf.length); } @Override public final int read(char[] cb, int off, int len) throws IOException { return RandomAccessCharacterFile.this.read(cb, off, len); } @Override public final boolean ready() throws IOException { return true; } } private class RandomAccessWriter extends Writer { RandomAccessWriter() { } public final void close() throws IOException { RandomAccessCharacterFile.this.close(); } public final void flush() throws IOException { RandomAccessCharacterFile.this.flush(); } @Override public final void write(char[] cb, int off, int len) throws IOException { RandomAccessCharacterFile.this.write(cb, off, len); } } final static int BUFSIZ = 4*1024; // setting this to a small value like 8 is helpful for testing. private RandomAccessWriter writer; private RandomAccessReader reader; private RandomAccessInputStream inputStream; private RandomAccessOutputStream outputStream; private FileChannel fcn; private Charset cset; private CharsetEncoder cenc; private CharsetDecoder cdec; /** * bbuf is treated as a cache of the file content. * If it points to somewhere in the middle of the file, it holds the copy of the file content, * even when you are writing a large chunk of data. If you write in the middle of a file, * bbuf first gets filled with contents of the data, and only after that any new data is * written on bbuf. * The exception is when you are appending data at the end of the file. */ private ByteBuffer bbuf; private boolean bbufIsDirty; /* whether bbuf holds data that must be written. */ private boolean bbufIsReadable; /* whether bbuf.remaining() contains readable content. */ private long bbufpos; /* where the beginning of bbuf is pointing in the file now. */ public RandomAccessCharacterFile(RandomAccessFile raf, String encoding) throws IOException { fcn = raf.getChannel(); setEncoding(encoding); bbuf = ByteBuffer.allocate(BUFSIZ); // there is no readable data available in the buffers. ((java.nio.Buffer)bbuf).flip(); // there is no write pending data in the buffers. bbufIsDirty = false; bbufIsReadable = true; bbufpos = fcn.position(); reader = new RandomAccessReader(); writer = new RandomAccessWriter(); inputStream = new RandomAccessInputStream(); outputStream = new RandomAccessOutputStream(); } public void setEncoding(String encoding) { if (encoding == null) { cset = Charset.defaultCharset(); } else { try { cset = Charset.forName(encoding); } catch (UnsupportedCharsetException e) { error(new SimpleError("Undefined encoding: " + encoding)); } } cdec = cset.newDecoder(); cdec.onMalformedInput(CodingErrorAction.REPLACE); cdec.onUnmappableCharacter(CodingErrorAction.REPLACE); cenc = cset.newEncoder(); } public Writer getWriter() { return writer; } public PushbackReader getReader() { return reader; } public PushbackInputStream getInputStream() { return inputStream; } public OutputStream getOutputStream() { return outputStream; } public final void close() throws IOException { internalFlush(true); fcn.close(); } public final void flush() throws IOException { internalFlush(false); } private final boolean ensureReadBbuf(boolean force) throws IOException { boolean bufReady = true; if ((bbuf.remaining() == 0) || force || ! bbufIsReadable) { // need to read from the file. if (bbufIsDirty) { flushBbuf(false); ((java.nio.Buffer)bbuf).clear(); bbufIsReadable = false; } else { int bbufEnd = bbufIsReadable ? ((java.nio.Buffer)bbuf).limit() : ((java.nio.Buffer)bbuf).position(); fcn.position(bbufpos + bbufEnd); bbufpos += ((java.nio.Buffer)bbuf).position(); if (bbufIsReadable) { bbuf.compact(); bbufIsReadable = false; } else //must discard the junk bytes after ((java.nio.Buffer)bbuf).position() ((java.nio.Buffer)bbuf).clear(); } bufReady = (fcn.read(bbuf) != -1); ((java.nio.Buffer)bbuf).flip(); bbufIsReadable = true; } return bufReady; } final int read(char[] cb, int off, int len) throws IOException { CharBuffer cbuf = CharBuffer.wrap(cb, off, len); cdec.reset(); boolean decodeWasUnderflow = false; boolean atEof = false; while ((cbuf.remaining() > 0) && ! atEof) { int oldRemaining = cbuf.remaining(); atEof = ! ensureReadBbuf(decodeWasUnderflow); CoderResult r; try { r = cdec.decode(bbuf, cbuf, atEof ); } catch (IllegalStateException e) { throw new IOException("CharsetDecoder failed", e); } catch (CoderMalfunctionError e) { throw new IOException("CharsetDecoder malfunction", e); } if (oldRemaining == cbuf.remaining() && CoderResult.OVERFLOW == r) { // if this happens, the decoding failed // but the bufs didn't advance. Advance // them manually and do manual replacing, // otherwise we loop endlessly. This occurs // at least when parsing latin1 files with // lowercase o-umlauts in them // Note that this is at the moment copy-paste // with DecodingReader.read() cbuf.put('?'); bbuf.get(); } decodeWasUnderflow = (CoderResult.UNDERFLOW == r); } if (cbuf.remaining() == len) { return -1; } else { return len - cbuf.remaining(); } } final void write(char[] cb, int off, int len) throws IOException { CharBuffer cbuf = CharBuffer.wrap(cb, off, len); encodeAndWrite(cbuf, false, false); } private final void internalFlush(boolean endOfFile) throws IOException { if (endOfFile) { CharBuffer cbuf = CharBuffer.allocate(0); encodeAndWrite(cbuf, true, endOfFile); } else { flushBbuf(false); } } private final void encodeAndWrite(CharBuffer cbuf, boolean flush, boolean endOfFile) throws IOException { while (cbuf.remaining() > 0) { CoderResult r = cenc.encode(cbuf, bbuf, endOfFile); bbufIsDirty = true; if (CoderResult.OVERFLOW == r || bbuf.remaining() == 0) { flushBbuf(false); ((java.nio.Buffer)bbuf).clear(); bbufIsReadable = false; } if (r.isUnmappable()) { throw new RACFUnmappableCharacterException(((java.nio.Buffer)cbuf).position(), cbuf.charAt(((java.nio.Buffer)cbuf).position()), cset.name()); } if (r.isMalformed()) { // We don't really expect Malformed, but not handling it // will cause an infinite loop if we don't... throw new RACFMalformedInputException(((java.nio.Buffer)cbuf).position(), cbuf.charAt(((java.nio.Buffer)cbuf).position()), cset.name()); } // UNDERFLOW is the normal condition where cbuf runs out // before bbuf is filled. } if (((java.nio.Buffer)bbuf).position() > 0 && bbufIsDirty && flush) { flushBbuf(false); } } public final void position(long newPosition) throws IOException { flushBbuf(true); long bbufend = bbufpos // in case bbuf is readable, its contents is valid + (bbufIsReadable ? ((java.nio.Buffer)bbuf).limit() : ((java.nio.Buffer)bbuf).position()); // beyond position() if (newPosition >= bbufpos && newPosition < bbufend) { // near seek. within existing data of bbuf. if (!bbufIsReadable) { //rewinding. keep tail buffered. ((java.nio.Buffer)bbuf).limit(((java.nio.Buffer)bbuf).position()); bbufIsReadable = true; } ((java.nio.Buffer)bbuf).position((int)(newPosition - bbufpos)); } else { fcn.position(newPosition); // far seek; discard the buffer (it's already cleared) ((java.nio.Buffer)bbuf).clear(); ((java.nio.Buffer)bbuf).flip(); // "there is no useful data on this buffer yet." bbufIsReadable = true; bbufpos = newPosition; } } public final long position() throws IOException { return bbufpos + ((java.nio.Buffer)bbuf).position(); // the logical position within the file. } public final long length() throws IOException { flushBbuf(true); return fcn.size(); } final void flushBbuf(boolean commitOnly) throws IOException { if (commitOnly && !bbufIsDirty) return; //otherwise, we do at least need to increase bbufpos fcn.position(bbufpos); // if the buffer is dirty, the modifications have to be // before position(): before re-positioning, this.position() // calls this function. if (commitOnly) { ByteBuffer dup = bbuf.duplicate(); ((java.nio.Buffer)dup).flip(); fcn.write(dup); //ideally, should restore fcn.position(). but don't for performance. // fcn.position(fcn.position()-dup.position()); bbufIsDirty = false; //this fixed stas's bug, but not mine. return; } if (bbufIsDirty) { ((java.nio.Buffer)bbuf).flip(); fcn.write(bbuf); } bbufpos += ((java.nio.Buffer)bbuf).position(); ((java.nio.Buffer)bbuf).clear(); ((java.nio.Buffer)bbuf).flip(); // there's no useable data in this buffer bbufIsDirty = false; bbufIsReadable = true; } public final int read(byte[] b, int off, int len) throws IOException { int pos = off; boolean atEof = false; while (pos - off < len && ! atEof) { atEof = ! ensureReadBbuf(false); int want = Math.min(off + len - pos, bbuf.remaining()); bbuf.get(b, pos, want); pos += want; } return pos - off; } // a method corresponding to the good ol' ungetc in C. // This function may fail when using (combined) character codes that use // escape sequences to switch between sub-codes. // ASCII, ISO-8859 series, any 8bit code are OK, all unicode variations are OK, // but applications of the ISO-2022 encoding framework can have trouble. // Example of such code is ISO-2022-JP which is used in Japanese e-mail. private CharBuffer singleCharBuf; private ByteBuffer shortByteBuf; public final void unreadChar(char c) throws IOException { // algorithm : // 1. encode c into bytes, to find out how many bytes it corresponds to // 2. move the position backwards that many bytes. // ** we stop here. Don't bother to write the bytes to the buffer, // assuming that it is the same as the original data. // If we allow to write back different characters, the buffer must get 'dirty' // but that would require read/write permissions on files you use unreadChar, // even if you are just reading for some tokenizer. // // So we don't do the following. // 3. write the bytes. // 4. move the position back again. if (singleCharBuf == null) { singleCharBuf = CharBuffer.allocate(1); shortByteBuf = ByteBuffer.allocate((int)cenc.maxBytesPerChar()); } ((java.nio.Buffer)singleCharBuf).clear(); singleCharBuf.append(c); ((java.nio.Buffer)singleCharBuf).flip(); ((java.nio.Buffer)shortByteBuf).clear(); cenc.encode(singleCharBuf, shortByteBuf, false); int n = ((java.nio.Buffer)shortByteBuf).position(); long pos = position() - n; position(pos); } public final void unreadByte(byte b) throws IOException { long pos = position() - 1; position(pos); } final void write(byte[] b, int off, int len) throws IOException { int pos = off; while (pos < off + len) { if (bbuf.remaining() == 0) { flushBbuf(false); ((java.nio.Buffer)bbuf).clear(); bbufIsReadable = false; } int thisBatchLen = Math.min(off + len - pos, bbuf.remaining()); bbuf.put(b, pos, thisBatchLen); pos += thisBatchLen; bbufIsDirty = true; } } } abcl-src-1.9.0/src/org/armedbear/lisp/with-accessors.lisp0100644 0000000 0000000 00000003712 14202767264 022051 0ustar000000000 0000000 ;;; with-accessors.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From SBCL. (defmacro with-accessors (slots instance &body body) (let ((in (gensym))) `(let ((,in ,instance)) (symbol-macrolet ,(mapcar (lambda (slot-entry) (let ((variable-name (car slot-entry)) (accessor-name (cadr slot-entry))) `(,variable-name (,accessor-name ,in)))) slots) ,@body)))) abcl-src-1.9.0/src/org/armedbear/lisp/with-hash-table-iterator.lisp0100644 0000000 0000000 00000004136 14202767264 023724 0ustar000000000 0000000 ;;; with-hash-table-iterator.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun hash-table-iterator-function (hash-table) (let ((entries (hash-table-entries hash-table))) #'(lambda () (let ((entry (car entries))) (setq entries (cdr entries)) (if entry (values t (car entry) (cdr entry)) nil))))) (defmacro with-hash-table-iterator ((name hash-table) &body body) (let ((iter (gensym))) `(let ((,iter (hash-table-iterator-function ,hash-table))) (macrolet ((,name () '(funcall ,iter))) ,@body)))) abcl-src-1.9.0/src/org/armedbear/lisp/with-input-from-string.lisp0100644 0000000 0000000 00000005143 14202767264 023470 0ustar000000000 0000000 ;;; with-input-from-string.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from CMUCL. (in-package "SYSTEM") (defmacro with-input-from-string ((var string &key index start end) &body body) (multiple-value-bind (forms decls) (parse-body body) `(let ((,var ,(cond ((null end) `(make-string-input-stream ,string ,(or start 0))) ((symbolp end) `(if ,end (make-string-input-stream ,string ,(or start 0) ,end) (make-string-input-stream ,string ,(or start 0)))) (t `(make-string-input-stream ,string ,(or start 0) ,end))))) ,@decls (unwind-protect (multiple-value-prog1 (progn ,@forms) ,@(when index `((setf ,index (string-input-stream-current ,var))))) (close ,var))))) abcl-src-1.9.0/src/org/armedbear/lisp/with-open-file.lisp0100644 0000000 0000000 00000004013 14202767264 021735 0ustar000000000 0000000 ;;; with-open-file.lisp ;;; ;;; Copyright (C) 2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defmacro with-open-file (&rest args) (let ((var (caar args)) (open-args (cdar args)) (body (cdr args)) (abortp (gensym))) (multiple-value-bind (forms decls) (parse-body body) `(let ((,var (open ,@open-args)) (,abortp t)) ,@decls (unwind-protect (multiple-value-prog1 (progn ,@forms) (setq ,abortp nil)) (when ,var (close ,var :abort ,abortp))))))) abcl-src-1.9.0/src/org/armedbear/lisp/with-output-to-string.lisp0100644 0000000 0000000 00000004717 14223403213 023336 0ustar000000000 0000000 ;;; with-output-to-string.lisp ;;; ;;; Copyright (C) 2003-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) ;;; From SBCL. (defmacro with-output-to-string ((var &optional string &key (element-type ''character)) &body body) "If STRING is specified, it must be a string with a fill pointer; the output is incrementally appended to the string (as if by use of VECTOR-PUSH-EXTEND)." (multiple-value-bind (forms decls) (parse-body body) (if string (let ((ignored (gensym))) `(let ((,var (make-fill-pointer-output-stream ,string)) (,ignored ,element-type)) (declare (ignore ,ignored)) ,@decls (unwind-protect (progn ,@forms) (close ,var)))) `(let ((,var (make-string-output-stream :element-type ,element-type))) ,@decls (unwind-protect (progn ,@forms) (close ,var)) (get-output-stream-string ,var))))) abcl-src-1.9.0/src/org/armedbear/lisp/with-package-iterator.lisp0100644 0000000 0000000 00000006237 14202767264 023313 0ustar000000000 0000000 ;;; with-package-iterator.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package "SYSTEM") (defun package-iterator-function (package-list symbol-types) (unless (consp package-list) (setq package-list (list package-list))) (let ((results ())) (dolist (pkg package-list) (unless (packagep pkg) (setq pkg (find-package pkg)) (unless pkg (error 'package-error "not a package"))) (when (memq :internal symbol-types) (dolist (sym (package-internal-symbols pkg)) (push (list sym :internal pkg) results))) (when (memq :external symbol-types) (dolist (sym (package-external-symbols pkg)) (push (list sym :external pkg) results))) (when (memq :inherited symbol-types) (dolist (sym (package-inherited-symbols pkg)) (push (list sym :inherited pkg) results)))) #'(lambda () (let ((item (car results))) (setq results (cdr results)) (if item (values t (first item) (second item) (third item)) nil))))) (defmacro with-package-iterator ((name package-list &rest symbol-types) &body body) (unless symbol-types (error 'program-error "WITH-PACKAGE-ITERATOR: no symbol types specified")) (dolist (symbol-type symbol-types) (unless (memq symbol-type '(:internal :external :inherited)) (error 'program-error "WITH-PACKAGE-ITERATOR: invalid symbol type: %S" symbol-type))) (let ((iter (gensym))) `(let ((,iter (package-iterator-function ,package-list ',(remove-duplicates symbol-types)))) (macrolet ((,name () '(funcall ,iter))) ,@body)))) abcl-src-1.9.0/src/org/armedbear/lisp/with-slots.lisp0100644 0000000 0000000 00000004262 14202767264 021231 0ustar000000000 0000000 ;;; with-slots.lisp ;;; ;;; Copyright (C) 2003 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; From SBCL. (defmacro with-slots (slots instance &body body) (let ((in (gensym))) `(let ((,in ,instance)) (symbol-macrolet ,(mapcar (lambda (slot-entry) (let ((var-name (if (symbolp slot-entry) slot-entry (car slot-entry))) (slot-name (if (symbolp slot-entry) slot-entry (cadr slot-entry)))) `(,var-name (slot-value ,in ',slot-name)))) slots) ,@body)))) abcl-src-1.9.0/src/org/armedbear/lisp/with-standard-io-syntax.lisp0100644 0000000 0000000 00000004662 14202767264 023622 0ustar000000000 0000000 ;;; with-standard-io-syntax.lisp ;;; ;;; Copyright (C) 2003-2004 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. ;;; Adapted from SBCL. (in-package "SYSTEM") (defun %with-standard-io-syntax (function) (let ((*package* (find-package "CL-USER")) (*print-array* t) (*print-base* 10) (*print-case* :upcase) (*print-circle* nil) (*print-escape* t) (*print-gensym* t) (*print-length* nil) (*print-level* nil) (*print-lines* nil) (*print-miser-width* nil) (*print-pprint-dispatch* (copy-pprint-dispatch nil)) (*print-pretty* nil) (*print-radix* nil) (*print-readably* t) (*print-right-margin* nil) (*read-base* 10) (*read-default-float-format* 'single-float) (*read-eval* t) (*read-suppress* nil) (*readtable* (copy-readtable nil))) (funcall function))) (defmacro with-standard-io-syntax (&body body) `(%with-standard-io-syntax #'(lambda () ,@body))) abcl-src-1.9.0/src/org/armedbear/lisp/write-sequence.lisp0100644 0000000 0000000 00000006005 14202767264 022051 0ustar000000000 0000000 ;;; write-sequence.lisp ;;; ;;; Copyright (C) 2004-2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;; As a special exception, the copyright holders of this library give you ;;; permission to link this library with independent modules to produce an ;;; executable, regardless of the license terms of these independent ;;; modules, and to copy and distribute the resulting executable under ;;; terms of your choice, provided that you also meet, for each linked ;;; independent module, the terms and conditions of the license of that ;;; module. An independent module is a module which is not derived from ;;; or based on this library. If you modify this library, you may extend ;;; this exception to your version of the library, but you are not ;;; obligated to do so. If you do not wish to do so, delete this ;;; exception statement from your version. (in-package #:system) (defun write-sequence (sequence stream &key (start 0) end) (declare (type stream stream)) (declare (type index start)) (unless (>= start 0) (error 'simple-type-error :datum start :expected-type '(integer 0))) (if end (unless (and (integerp end) (>= end 0)) (error 'simple-type-error :datum end :expected-type '(integer 0))) (setf end (length sequence))) (let ((end (the fixnum end)) (stream-element-type (expand-deftype (stream-element-type stream)))) (cond ((eq stream-element-type 'character) (if (stringp sequence) (%write-string sequence stream start end) (do* ((i start (1+ i))) ((>= i end) sequence) (declare (type index i)) (write-char (elt sequence i) stream)))) ((equal stream-element-type '(unsigned-byte 8)) (if (and (vectorp sequence) (equal (array-element-type sequence) '(unsigned-byte 8))) (write-vector-unsigned-byte-8 sequence stream start end) (do* ((i start (1+ i))) ((>= i end) sequence) (declare (type index i)) (write-8-bits (elt sequence i) stream)))) (t (do* ((i start (1+ i))) ((>= i end) sequence) (declare (type index i)) (write-byte (elt sequence i) stream))))) sequence) abcl-src-1.9.0/src/org/armedbear/lisp/zip.java0100644 0000000 0000000 00000024544 14202767264 017675 0ustar000000000 0000000 /* * zip.java * * Copyright (C) 2005 Peter Graves * $Id$ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package org.armedbear.lisp; import static org.armedbear.lisp.Lisp.*; import java.io.File; import java.io.FileNotFoundException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @DocString(name="zip", args="pathname pathnames &optional topdir", doc="Creates a zip archive at PATHNAME whose entries enumerated via the list of PATHNAMES.\n" + "If the optional TOPDIR argument is specified, the archive will " + "preserve the hierarchy of PATHNAMES relative to TOPDIR. Without " + "TOPDIR, there will be no sub-directories in the archive, i.e. it will " + "be flat.") public final class zip extends Primitive { private zip() { super("zip", PACKAGE_SYS, true); } @Override public LispObject execute(LispObject first, LispObject second) { Pathname zipfilePathname = coerceToPathname(first); if (second instanceof org.armedbear.lisp.protocol.Hashtable) { return execute(zipfilePathname, (org.armedbear.lisp.protocol.Hashtable)second); } byte[] buffer = new byte[4096]; try { String zipfileNamestring = zipfilePathname.getNamestring(); if (zipfileNamestring == null) return error(new SimpleError("Pathname has no namestring: " + zipfilePathname.princToString())); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfileNamestring)); LispObject list = second; while (list != NIL) { Pathname pathname = coerceToPathname(list.car()); String namestring = pathname.getNamestring(); if (namestring == null) { // Clean up before signalling error. out.close(); File zipfile = new File(zipfileNamestring); zipfile.delete(); return error(new SimpleError("Pathname has no namestring: " + pathname.princToString())); } File file = new File(namestring); makeEntry(out, file); list = list.cdr(); } out.close(); } catch (IOException e) { return error(new LispError(e.getMessage())); } return zipfilePathname; } @Override public LispObject execute(LispObject first, LispObject second, LispObject third) { Pathname zipfilePathname = coerceToPathname(first); try { String zipfileNamestring = zipfilePathname.getNamestring(); if (zipfileNamestring == null) return error(new SimpleError("Pathname has no namestring: " + zipfilePathname.princToString())); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfileNamestring)); Pathname root = (Pathname) Symbol.PROBE_FILE.execute(third); String rootPath = root.getDirectoryNamestring(); int rootPathLength = rootPath.length(); Set directories = new HashSet(); LispObject list = second; while (list != NIL) { Pathname pathname = (Pathname) Symbol.PROBE_FILE.execute(list.car()); String namestring = pathname.getNamestring(); if (namestring == null) { // Clean up before signalling error. out.close(); File zipfile = new File(zipfileNamestring); zipfile.delete(); return error(new SimpleError("Pathname has no namestring: " + pathname.princToString())); } String directory = ""; String dir = pathname.getDirectoryNamestring(); if (dir.length() > rootPathLength) { String d = dir.substring(rootPathLength); int i = 0; int j; while ((j = d.indexOf(Pathname.directoryDelimiter, i)) != -1) { i = j + 1; directory = d.substring(0, j) + Pathname.directoryDelimiter; if (!directories.contains(directory)) { directories.add(directory); ZipEntry entry = new ZipEntry(directory); out.putNextEntry(entry); out.closeEntry(); } } } File file = new File(namestring); if (file.isDirectory()) { list = list.cdr(); continue; } makeEntry(out, file, directory + file.getName()); list = list.cdr(); } out.close(); } catch (IOException e) { return error(new LispError(e.getMessage())); } return zipfilePathname; } static class Directories extends HashSet { private Directories() { super(); } ZipOutputStream out; public Directories(ZipOutputStream out) { this.out = out; } public void ensure(String path) throws IOException { int i = 0; int j; while ((j = path.indexOf(Pathname.directoryDelimiter, i)) != -1) { i = j + 1; final String directory = path.substring(0, j) + Pathname.directoryDelimiter; if (!contains(directory)) { add(directory); ZipEntry entry = new ZipEntry(directory); out.putNextEntry(entry); out.closeEntry(); } } } } public LispObject execute(final Pathname zipfilePathname, final org.armedbear.lisp.protocol.Hashtable table) { LispObject entriesObject = (LispObject)table.getEntries(); if (!(entriesObject instanceof Cons)) { return NIL; } Cons entries = (Cons)entriesObject; String zipfileNamestring = zipfilePathname.getNamestring(); if (zipfileNamestring == null) return error(new SimpleError("Pathname has no namestring: " + zipfilePathname.princToString())); ZipOutputStream out = null; try { out = new ZipOutputStream(new FileOutputStream(zipfileNamestring)); } catch (FileNotFoundException e) { return error(new FileError("Failed to create file for writing zip archive", zipfilePathname)); } Directories directories = new Directories(out); for (LispObject head = entries; head != NIL; head = head.cdr()) { final LispObject key = head.car().car(); final LispObject value = head.car().cdr(); final Pathname source = Lisp.coerceToPathname(key); final Pathname destination = Lisp.coerceToPathname(value); final File file = source.getFile(); try { String jarEntry = destination.getNamestring(); if (jarEntry.startsWith("/")) { jarEntry = jarEntry.substring(1); } directories.ensure(jarEntry); makeEntry(out, file, jarEntry); } catch (FileNotFoundException e) { return error(new FileError("Failed to read file for incoporation in zip archive.", source)); } catch (IOException e) { return error(new FileError("Failed to add file to zip archive.", source)); } } try { out.close(); } catch (IOException ex) { return error(new FileError("Failed to close zip archive.", zipfilePathname)); } return zipfilePathname; } private static final Primitive zip = new zip(); private void makeEntry(ZipOutputStream zip, File file) throws FileNotFoundException, IOException { makeEntry(zip, file, file.getName()); } private void makeEntry(ZipOutputStream zip, File file, String name) throws FileNotFoundException, IOException { byte[] buffer = new byte[4096]; long lastModified = file.lastModified(); FileInputStream in = new FileInputStream(file); ZipEntry entry = new ZipEntry(name); if (lastModified > 0) { entry.setTime(lastModified); } zip.putNextEntry(entry); int n; while ((n = in.read(buffer)) > 0) zip.write(buffer, 0, n); zip.closeEntry(); in.close(); } } abcl-src-1.9.0/test/lisp/abcl/abcl-test.lisp0100644 0000000 0000000 00000000212 14202767264 017341 0ustar000000000 0000000 (require 'asdf) (handler-case (asdf:test-system :abcl/test/lisp :force t) (t (e) (warn "Exiting after catching ~A" e))) (ext:exit) abcl-src-1.9.0/test/lisp/abcl/bugs.lisp0100644 0000000 0000000 00000013333 14202767264 016433 0ustar000000000 0000000 (in-package :abcl.test.lisp) ;;; When these bugs get fixed, they should be moved elsewhere in the ;;; testsuite so they remain fixed. (deftest bugs.logical-pathname.1 #| Date: Mon, 18 Jan 2010 10:51:07 -0500 Message-ID: <29af5e2d1001180751l7cf79a3ay929cef1deb9ed063@mail.gmail.com> Subject: Re: [armedbear-devel] translate-logical-pathname and :wild-inferiors regression From: Alan Ruttenberg |# (progn (setf (logical-pathname-translations "ido") '(("IDO:IDO-CORE;**;*.*" "/Users/alanr/repos/infectious-disease-ontology/trunk/src/ontology/ido-core/**/*.*") ("IDO:IMMUNOLOGY;**;*.*" "/Users/alanr/repos/infectious-disease-ontology/trunk/src/ontology/immunology/**/*.*") ("IDO:TOOLS;**;*.*" "/Users/alanr/repos/infectious-disease-ontology/trunk/src/tools/**/*.*") ("IDO:LIB;**;*.*" "/Users/alanr/repos/infectious-disease-ontology/trunk/lib/**/*.*"))) (translate-pathname "IDO:IMMUNOLOGY;" "IDO:IMMUNOLOGY;**;*.*" "/Users/alanr/repos/infectious-disease-ontology/trunk/src/ontology/**/*.*")) #P"/users/alanr/repos/infectious-disease-ontology/trunk/src/ontology/") (deftest bugs.logical-pathname.2 #| Message-Id: From: Thomas Russ To: armedbear-devel@common-lisp.net Subject: [armedbear-devel] Bug in translate-logical-pathname. |# (progn (setf (logical-pathname-translations "L") '(("L:NATIVE;**;*.*" "/usr/lisp/abcl/native/**/*.*"))) (translate-logical-pathname "L:NATIVE;TEST;FOO.FASL")) #p"/usr/lisp/abcl/native/test/foo.fasl") (deftest bugs.pathname.1 (namestring (make-pathname :directory '(:relative) :name "file" :type :unspecific :host nil :device nil)) "./file") (deftest bugs.pathname.2 (TRANSLATE-PATHNAME #P"/Users/evenson/work/bordeaux-threads/src/bordeaux-threads.abcl" #P"/**/**/*.*" #P"/Users/evenson/.cache/common-lisp/armedbear-0.20.0-dev-darwin-unknown/**/*.*") #P"/Users/evenson/.cache/common-lisp/armedbear-0.20.0-dev-darwin-unknown/bordeaux-threads.abcl") (deftest bugs.pathname.3 (namestring (MAKE-PATHNAME :HOST NIL :DEVICE NIL :DIRECTORY '(:RELATIVE :WILD-INFERIORS) :DEFAULTS "/**/")) "**/") #+abcl (deftest bugs.java.1 (let* ((a (java:jnew-array "byte" 1)) (b (let ((array-list (java:jnew (java:jconstructor "java.util.ArrayList")))) (java:jcall (java:jmethod "java.util.AbstractList" "add" "java.lang.Object") array-list a) (java:jcall (java:jmethod "java.util.AbstractList" "get" "int") array-list 0)))) (type-of (sys::%make-byte-array-input-stream b))) stream) (deftest bugs.readtable-case.1 (let (original-case result) (setf original-case (readtable-case *readtable*) (readtable-case *readtable*) :invert result (list (string (read-from-string "lower")) (string (read-from-string "UPPER")) (string (read-from-string "#:lower")) (string (read-from-string "#:UPPER"))) (readtable-case *readtable*) original-case) (values-list result)) "LOWER" "upper" "LOWER" "upper") ;;; http://abcl.org/trac/ticket/165 (deftest bugs.pprint.1 (let ((result (make-array '(0) :element-type 'base-char :fill-pointer t))) (with-output-to-string (s result) (pprint-logical-block (s nil :per-line-prefix "---") (format s "~(~A~)" '(1 2 3 4)))) result) "---(1 2 3 4)") (deftest bugs.defgeneric.1 (let ((symbol (gensym)) (docstring "Ipso est genericus") result) (eval `(defgeneric ,symbol nil (:documentation ,docstring))) (setf result (documentation symbol 'function)) (fmakunbound symbol) (string= result docstring)) t) ;;; http://abcl.org/trac/ticket/199 (deftest bugs.clos.aux.1 ((lambda (a &aux (b (+ a 1))) b) 2) 3) ;;; http://abcl.org/trac/ticket/243 (deftest bugs.pathname.make-pathname.1 (signals-error (make-pathname :device (list "foo")) 'error) t) ;; Dunno about this one. Maybe we should signal an error when ;; constructed a pathname that we *know* can never refer to any resource. (push 'bugs.pathname.make-pathname.1 *expected-failures*) (deftest bugs.pathname.make-pathname.2 (probe-file (make-pathname :device (list "foo"))) nil) ;; http://abcl.org/trac/ticket/293 (deftest bugs.loop.1 (loop :with x :of-type (float 0) = 0.0 :for y :upto 1 :collecting (cons x y)) ((0.0 . 0) (0.0 . 1))) ;; http://abcl.org/trac/ticket/444 ;; https://trac.clozure.com/ccl/ticket/1085 (deftest bugs.loop.2 (loop for x = #'(lambda ()) for y = 10 then 20 return y) 10) ;; http://abcl.org/trac/ticket/294 (deftest bugs.reader.1 (let ((*readtable* *readtable*)) (set-macro-character #\? (lambda (stream char) (code-char (read stream nil nil t)))) '(a .?0)) (A . #\Null)) ;;; http://abcl.org/trac/ticket/311 (deftest bugs.export.1 (let ((a (symbol-name (gensym "PACKAGE-"))) (b (symbol-name (gensym "PACKAGE-"))) result) (make-package a) (intern "FOO" a) (export (find-symbol "FOO" a) a) (make-package b :use (list a)) (export (find-symbol "FOO" b) b) (unexport (find-symbol "FOO" a) a) (setf result (unexport (find-symbol "FOO" b) b)) (delete-package a) (delete-package b) result) t) abcl-src-1.9.0/test/lisp/abcl/class-file.lisp0100644 0000000 0000000 00000036636 14202767264 017530 0ustar000000000 0000000 ;;; compiler-tests.lisp ;;; ;;; Copyright (C) 2010 Erik Huelsmann ;;; ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #+abcl (require '#:jvm) (in-package #:abcl.test.lisp) (deftest fieldtype.1a (string= (jvm::internal-field-type :int) "I") T) (deftest fieldtype.1b (string= (jvm::internal-field-type :long) "J") T) (deftest fieldtype.1c (string= (jvm::internal-field-type :float) "F") T) (deftest fieldtype.1d (string= (jvm::internal-field-type :double) "D") T) (deftest fieldtype.1e (string= (jvm::internal-field-type :boolean) "Z") T) (deftest fieldtype.1f (string= (jvm::internal-field-type :char) "C") T) (deftest fieldtype.1g (string= (jvm::internal-field-type :byte) "B") T) (deftest fieldtype.1h (string= (jvm::internal-field-type :short) "S") T) (deftest fieldtype.1i (string= (jvm::internal-field-type :void) "V") T) (deftest fieldtype.1j (string= (jvm::internal-field-type nil) "V") T) (deftest fieldtype.2 (string= (jvm::internal-field-type jvm::+lisp-object+) "org/armedbear/lisp/LispObject") T) (deftest fieldref.1a (string= (jvm::internal-field-ref :int) "I") T) (deftest fieldref.1b (string= (jvm::internal-field-ref :long) "J") T) (deftest fieldref.1c (string= (jvm::internal-field-ref :float) "F") T) (deftest fieldref.1d (string= (jvm::internal-field-ref :double) "D") T) (deftest fieldref.1e (string= (jvm::internal-field-ref :boolean) "Z") T) (deftest fieldref.1f (string= (jvm::internal-field-ref :char) "C") T) (deftest fieldref.1g (string= (jvm::internal-field-ref :byte) "B") T) (deftest fieldref.1h (string= (jvm::internal-field-ref :short) "S") T) (deftest fieldref.1i (string= (jvm::internal-field-ref :void) "V") T) (deftest fieldref.1j (string= (jvm::internal-field-ref nil) "V") T) (deftest fieldref.2 (string= (jvm::internal-field-ref jvm::+lisp-object+) "Lorg/armedbear/lisp/LispObject;") T) (deftest descriptor.1 (and (string= (jvm::descriptor :void :int :long :boolean) "(IJZ)V") (string= (jvm::descriptor nil :int :long :boolean) "(IJZ)V")) T) (deftest descriptor.2 (string= (jvm::descriptor jvm::+lisp-object+ jvm::+lisp-object+) "(Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject;") T) (deftest map-flags.1 (eql (jvm::map-flags '(:public)) #x0001) T) (deftest pool.1 (let* ((pool (jvm::make-pool))) (jvm::pool-add-class pool jvm::+lisp-readtable+) (jvm::pool-add-field-ref pool jvm::+lisp-readtable+ "ABC" :int) (jvm::pool-add-field-ref pool jvm::+lisp-readtable+ "ABD" jvm::+lisp-readtable+) (jvm::pool-add-method-ref pool jvm::+lisp-readtable+ "MBC" :int) (jvm::pool-add-method-ref pool jvm::+lisp-readtable+ "MBD" jvm::+lisp-readtable+) (jvm::pool-add-interface-method-ref pool jvm::+lisp-readtable+ "MBD" :int) (jvm::pool-add-interface-method-ref pool jvm::+lisp-readtable+ "MBD" jvm::+lisp-readtable+) (jvm::pool-add-string pool "string") (jvm::pool-add-int pool 1) (jvm::pool-add-float pool 1.0f0) (jvm::pool-add-long pool 1) (jvm::pool-add-double pool 1.0d0) (jvm::pool-add-name/type pool "name1" :int) (jvm::pool-add-name/type pool "name2" jvm::+lisp-object+) (jvm::pool-add-utf8 pool "utf8") T) T) (deftest make-class-file.1 (let* ((class (jvm::make-jvm-class-name "org/armedbear/lisp/mcf_1")) (file (jvm::make-class-file class jvm::+lisp-object+ '(:public)))) (jvm::class-add-field file (jvm::make-field "ABC" :int)) (jvm::class-add-field file (jvm::make-field "ABD" jvm::+lisp-object+)) (jvm::class-add-method file (jvm::make-jvm-method "MBC" nil :int)) (jvm::class-add-method file (jvm::make-jvm-method "MBD" nil jvm::+lisp-object+)) (jvm::class-add-method file (jvm::make-jvm-method :constructor :void nil)) (jvm::class-add-method file (jvm::make-jvm-method :static-initializer :void nil)) T) T) (deftest finalize-class-file.1 (let* ((class (jvm::make-jvm-class-name "org/armedbear/lisp/fcf_1")) (file (jvm::make-class-file class jvm::+lisp-object+ '(:public)))) (jvm::class-add-field file (jvm::make-field "ABC" :int)) (jvm::class-add-field file (jvm::make-field "ABD" jvm::+lisp-object+)) (jvm::class-add-method file (jvm::make-jvm-method "MBC" nil '(:int))) (jvm::class-add-method file (jvm::make-jvm-method "MBD" nil (list jvm::+lisp-object+))) (jvm::finalize-class-file file) file T) T) (deftest generate-method.1 (let* ((class (jvm::make-jvm-class-name "org/armedbear/lisp/gm_1")) (file (jvm::make-class-file class jvm::+lisp-object+ '(:public))) (method (jvm::make-jvm-method :static-initializer :void nil :flags '(:static)))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit 'return)) (jvm::finalize-class-file file) (with-open-stream (stream (sys::%make-byte-array-output-stream)) (jvm::write-class-file file stream) (sys::load-compiled-function (sys::%get-output-stream-bytes stream))) T) T) (deftest generate-method.2 (let* ((class (jvm::make-jvm-class-name "org/armedbear/lisp/gm_2")) (file (jvm::make-class-file class jvm::+lisp-object+ '(:public))) (method (jvm::make-jvm-method "doNothing" :void nil))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (let ((label1 (gensym)) (label2 (gensym)) (label3 (gensym))) (jvm::label label1) (jvm::emit 'jvm::iconst_1) (jvm::label label2) (jvm::emit 'return) (jvm::label label3) (jvm::code-add-exception-handler (jvm::method-attribute method "Code") label1 label2 label3 nil)) (jvm::emit 'return)) (jvm::finalize-class-file file) (with-open-stream (stream (sys::%make-byte-array-output-stream)) (jvm::write-class-file file stream) (sys::load-compiled-function (sys::%get-output-stream-bytes stream))) T) T) ;; generation of an ABCL-like function class (deftest generate-method.3 (let* ((class (jvm::make-jvm-class-name "org.armedbear.lisp.gm_3")) (file (jvm::make-class-file class jvm::+lisp-primitive+ '(:public))) ) (let ((method (jvm::make-jvm-method :constructor :void nil))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit 'aload 0) (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-symbol+) (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-symbol+) (jvm::emit-invokespecial-init jvm::+lisp-primitive+ (list jvm::+lisp-object+ jvm::+lisp-object+)) (jvm::emit 'return))) (let ((method (jvm::make-jvm-method "execute" jvm::+lisp-object+ nil))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-symbol+) (jvm::emit 'jvm::areturn))) (jvm::finalize-class-file file) (with-open-stream (stream (sys::%make-byte-array-output-stream)) (jvm::write-class-file file stream) (funcall (sys::load-compiled-function (sys::%get-output-stream-bytes stream))))) NIL) ;; generation of an ABCL-like function class with static init function and ;; static field (deftest generate-method.4 (let* ((class (jvm::make-jvm-class-name "org.armedbear.lisp.gm_4")) (file (jvm::make-class-file class jvm::+lisp-primitive+ '(:public))) ) (jvm::class-add-field file (jvm::make-field "N1" jvm::+lisp-object+ :flags '(:static :private))) (let ((method (jvm::make-jvm-method :static-initializer :void nil :flags '(:static)))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-symbol+) (jvm::emit-putstatic class "N1" jvm::+lisp-object+) (jvm::emit 'return))) (let ((method (jvm::make-jvm-method :constructor :void nil))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit 'aload 0) (jvm::emit-getstatic class "N1" jvm::+lisp-object+) (jvm::emit-getstatic class "N1" jvm::+lisp-object+) (jvm::emit-invokespecial-init jvm::+lisp-primitive+ (list jvm::+lisp-object+ jvm::+lisp-object+)) (jvm::emit 'return))) (let ((method (jvm::make-jvm-method "execute" jvm::+lisp-object+ nil))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit-getstatic class "N1" jvm::+lisp-object+) (jvm::emit 'jvm::areturn))) (jvm::finalize-class-file file) (with-open-stream (stream (sys::%make-byte-array-output-stream)) (jvm::write-class-file file stream) (funcall (sys::load-compiled-function (sys::%get-output-stream-bytes stream))))) NIL) ;; generation of ABCL-like function class with multiple 'execute' methods (deftest generate-method.5 (let* ((class (jvm::make-jvm-class-name "org.armedbear.lisp.gm_5")) (file (jvm::make-class-file class jvm::+lisp-primitive+ '(:public))) ) (let ((method (jvm::make-jvm-method :constructor :void nil))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit 'aload 0) (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-symbol+) (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-symbol+) (jvm::emit-invokespecial-init jvm::+lisp-primitive+ (list jvm::+lisp-object+ jvm::+lisp-object+)) (jvm::emit 'return))) (let ((method (jvm::make-jvm-method "execute" jvm::+lisp-object+ nil))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-symbol+) (jvm::emit 'jvm::areturn))) (let ((method (jvm::make-jvm-method "execute" jvm::+lisp-object+ (list jvm::+lisp-object+)))) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::emit-getstatic jvm::+lisp+ "T" jvm::+lisp-symbol+) (jvm::emit 'jvm::areturn))) (jvm::finalize-class-file file) (with-open-stream (stream (sys::%make-byte-array-output-stream)) (jvm::write-class-file file stream) (let* ((bytes (sys::%get-output-stream-bytes stream)) (fn (sys::load-compiled-function bytes))) (values (funcall fn) (funcall fn NIL))))) NIL T) ;;Nested with-code-to-method (deftest with-code-to-method.1 (let* ((class (jvm::make-jvm-class-name "org/armedbear/lisp/gm_6")) (file (jvm::make-class-file class jvm::+lisp-object+ '(:public))) (method (jvm::make-jvm-method :static-initializer :void nil :flags '(:static))) (registers nil)) (jvm::class-add-method file method) (jvm::with-code-to-method (file method) (jvm::allocate-register :int) (push jvm::*register* registers) (jvm::with-code-to-method (file method) (jvm::allocate-register :int) (push jvm::*register* registers) (jvm::with-code-to-method (file method) (jvm::allocate-register :int) (push jvm::*register* registers)) (jvm::allocate-register :int) (push jvm::*register* registers)) (jvm::allocate-register :int) (push jvm::*register* registers) (jvm::emit 'return)) (jvm::finalize-class-file file) (nreverse registers)) (1 2 3 4 5)) (deftest with-code-to-method.2 (let* ((class (jvm::make-jvm-class-name "org/armedbear/lisp/gm_7")) (file (jvm::make-class-file class jvm::+lisp-object+ '(:public))) (method1 (jvm::make-jvm-method :static-initializer :void nil :flags '(:static))) (method2 (jvm::make-jvm-method "method2" :void nil)) (registers nil)) (jvm::class-add-method file method1) (jvm::class-add-method file method2) (jvm::with-code-to-method (file method1) (jvm::allocate-register :int) (push jvm::*register* registers) (jvm::with-code-to-method (file method2) (jvm::allocate-register :int) (push jvm::*register* registers) (jvm::with-code-to-method (file method1) (jvm::allocate-register :int) (push jvm::*register* registers)) (jvm::allocate-register :int) (push jvm::*register* registers)) (jvm::allocate-register :int) (push jvm::*register* registers) (jvm::emit 'return)) (jvm::finalize-class-file file) (nreverse registers)) (1 1 2 2 3)) ;; ;; generation of an ABCL-like function, with mixed output to constructor, ;; ;; static initializer and function method(s) ;; (deftest generate-method.6 ;; (let* ((class (jvm::make-jvm-class-name "org.armedbear.lisp.gm_6")) ;; (file (jvm::make-class-file class jvm::+lisp-primitive+ '(:public))) ;; ) ;; (let ((method (jvm::make-method :constructor :void nil))) ;; (jvm::class-add-method file method) ;; (jvm::with-code-to-method (file method) ;; (jvm::emit 'aload 0) ;; (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-object+) ;; (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-object+) ;; (jvm::emit-invokespecial-init jvm::+lisp-primitive+ ;; (list jvm::+lisp-object+ ;; jvm::+lisp-object+)) ;; (jvm::emit 'return))) ;; (let ((method (jvm::make-method "execute" jvm::+lisp-object+ nil))) ;; (jvm::class-add-method file method) ;; (jvm::with-code-to-method (file method) ;; (jvm::emit-getstatic jvm::+lisp+ "NIL" jvm::+lisp-object+) ;; (jvm::emit 'jvm::areturn))) ;; (jvm::finalize-class-file file) ;; (with-open-stream (stream (sys::%make-byte-array-output-stream)) ;; (jvm::write-class-file file stream) ;; (ignore-errors (sys::load-compiled-function nil)) ;; (funcall (sys::load-compiled-function (sys::%get-output-stream-bytes stream)))) ;; T ;; ) ;; T) abcl-src-1.9.0/test/lisp/abcl/clos-tests.lisp0100644 0000000 0000000 00000037500 14202767264 017575 0ustar000000000 0000000 ;;; clos-tests.lisp ;;; ;;; Copyright (C) 2010 Erik Huelsmann ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;; These tests are in clos tests, because e.g. D-M-C isn't mop, but *is* clos (in-package #:abcl.test.lisp) ;; tests for D-M-C, long form, some taken from SBCL ;; D-M-C should return the name of the new method combination, nothing else. (deftest dmc-return.1 (define-method-combination dmc-test-return-foo) dmc-test-return-foo) (deftest dmc-return.2 (define-method-combination dmc-test-return-bar :operator and) dmc-test-return-bar) (deftest dmc-return.3 (define-method-combination dmc-test-return (&optional (order :most-specific-first)) ((around (:around)) (primary (dmc-test-return) :order order :required t)) (let ((form (if (rest primary) `(and ,@(mapcar #'(lambda (method) `(call-method ,method)) primary)) `(call-method ,(first primary))))) (if around `(call-method ,(first around) (,@(rest around) (make-method ,form))) form))) dmc-test-return) ;; A method combination which originally failed; ;; for different reasons in SBCL than in ABCL (hence leaving out ;; the original comment) (define-method-combination dmc-test-mc.1 (&optional (order :most-specific-first)) ((around (:around)) (primary (dmc-test-mc) :order order :required t)) (let ((form (if (rest primary) `(and ,@(mapcar #'(lambda (method) `(call-method ,method)) primary)) `(call-method ,(first primary))))) (if around `(call-method ,(first around) (,@(rest around) (make-method ,form))) form))) (defgeneric dmc-test-mc.1 (&key k) (:method-combination dmc-test-mc.1)) (defmethod dmc-test-mc.1 dmc-test-mc (&key k) k) (deftest dmc-test-mc.1 (dmc-test-mc.1 :k 1) 1) ;; Completely DIY -- also taken from SBCL: (define-method-combination dmc-test-mc.2 () ((all-methods *)) (do ((methods all-methods (rest methods)) (primary nil) (around nil)) ((null methods) (let ((primary (nreverse primary)) (around (nreverse around))) (if primary (let ((form (if (rest primary) `(call-method ,(first primary) ,(rest primary)) `(call-method ,(first primary))))) (if around `(call-method ,(first around) (,@(rest around) (make-method ,form))) form)) `(make-method (error "No primary methods"))))) (let* ((method (first methods)) (qualifier (first (method-qualifiers method)))) (cond ((equal :around qualifier) (push method around)) ((null qualifier) (push method primary)))))) (defgeneric dmc-test-mc.2a (val) (:method-combination dmc-test-mc.2)) (defmethod dmc-test-mc.2a ((val number)) (+ val (if (next-method-p) (call-next-method) 0))) (deftest dmc-test-mc.2a (= (dmc-test-mc.2a 13) 13) T) (defgeneric dmc-test-mc.2b (val) (:method-combination dmc-test-mc.2)) (defmethod dmc-test-mc.2b ((val number)) (+ val (if (next-method-p) (call-next-method) 0))) (defmethod dmc-test-mc.2b :around ((val number)) (+ val (if (next-method-p) (call-next-method) 0))) (deftest dmc-test-mc.2b (= 26 (dmc-test-mc.2b 13)) T) ;;; Taken from SBCL: error when method sorting is ambiguous ;;; with multiple method groups (define-method-combination dmc-test-mc.3a () ((around (:around)) (primary * :required t)) (let ((form (if (rest primary) `(call-method ,(first primary) ,(rest primary)) `(call-method ,(first primary))))) (if around `(call-method ,(first around) (,@(rest around) (make-method ,form))) form))) (defgeneric dmc-test-mc.3a (val) (:method-combination dmc-test-mc.3a)) (defmethod dmc-test-mc.3a ((val number)) (+ val (if (next-method-p) (call-next-method) 0))) (defmethod dmc-test-mc.3a :around ((val number)) (+ val (if (next-method-p) (call-next-method) 0))) (defmethod dmc-test-mc.3a :somethingelse ((val number)) (+ val (if (next-method-p) (call-next-method) 0))) (deftest dmc-test-mc.3a (multiple-value-bind (value error) (ignore-errors (wam-test-mc.3a 13)) (declare (ignore value)) (typep error 'error)) T) ;;; Taken from SBCL: error when method sorting is ambiguous ;;; with a single (non *) method group (define-method-combination dmc-test-mc.3b () ((methods listp :required t)) (if (rest methods) `(call-method ,(first methods) ,(rest methods)) `(call-method ,(first methods)))) (defgeneric dmc-test-mc.3b (val) (:method-combination dmc-test-mc.3b)) (defmethod dmc-test-mc.3b :foo ((val number)) (+ val (if (next-method-p) (call-next-method) 0))) (defmethod dmc-test-mc.3b :bar ((val number)) (+ val (if (next-method-p) (call-next-method) 0))) (deftest dmc-test-mc.3b (multiple-value-bind (value error) (ignore-errors (dmc-test-mc.3b 13)) (declare (ignore value)) (typep error 'error)) T) ;; Taken from SBCL: test that GF invocation arguments ;; are correctly bound using the (:arguments ...) form (defparameter *dmc-test-4* nil) (defun object-lock (obj) (push "object-lock" *dmc-test-4*) obj) (defun unlock (obj) (push "unlock" *dmc-test-4*) obj) (defun lock (obj) (push "lock" *dmc-test-4*) obj) (define-method-combination dmc-test-mc.4 () ((methods *)) (:arguments object) `(unwind-protect (progn (lock (object-lock ,object)) ,@(mapcar #'(lambda (method) `(call-method ,method)) methods)) (unlock (object-lock ,object)))) (defgeneric dmc-test.4 (x) (:method-combination dmc-test-mc.4)) (defmethod dmc-test.4 ((x symbol)) (push "primary" *dmc-test-4*)) (defmethod dmc-test.4 ((x number)) (error "foo")) (deftest dmc-test.4a (progn (setq *dmc-test-4* nil) (values (equal (dmc-test.4 t) '("primary" "lock" "object-lock")) (equal *dmc-test-4* '("unlock" "object-lock" "primary" "lock" "object-lock")))) T T) (deftest dmc-test.4b (progn (setq *dmc-test-4* nil) (ignore-errors (dmc-test.4 1)) (equal *dmc-test-4* '("unlock" "object-lock" "lock" "object-lock"))) T) ;; From SBCL: method combination (long form) with arguments #-ccl ;; "The value (ABCL.TEST.LISP::EXTRA :EXTRA) is not of the expected type SYMBOL." (define-method-combination dmc-test.5 () ((method-list *)) (:arguments arg1 arg2 &aux (extra :extra)) `(progn ,@(mapcar (lambda (method) `(call-method ,method)) method-list))) #-ccl ;; "The value (ABCL.TEST.LISP::EXTRA :EXTRA) is not of the expected type SYMBOL." (defgeneric dmc-test-mc.5 (p1 p2 s) (:method-combination dmc-test.5) (:method ((p1 number) (p2 t) s) (vector-push-extend (list 'number p1 p2) s)) (:method ((p1 string) (p2 t) s) (vector-push-extend (list 'string p1 p2) s)) (:method ((p1 t) (p2 t) s) (vector-push-extend (list t p1 p2) s))) (deftest dmc-test.5a (let ((v (make-array 0 :adjustable t :fill-pointer t))) (values (dmc-test-mc.5 1 2 v) (equal (aref v 0) '(number 1 2)) (equal (aref v 1) '(t 1 2)))) 1 T T) (define-method-combination dmc-test.6 () ((normal ()) (ignored (:ignore :unused))) `(list 'result ,@(mapcar #'(lambda (method) `(call-method ,method)) normal))) (defgeneric dmc-test-mc.6 (x) (:method-combination dmc-test.6) (:method :ignore ((x number)) (/ 0))) (deftest dmc-test-mc.6a (multiple-value-bind (value error) (ignore-errors (dmc-test-mc.6 7)) (values (null value) (typep error 'error))) T T) (define-method-combination dmc-test.7 () ((methods *)) (:arguments x &rest others) `(progn ,@(mapcar (lambda (method) `(call-method ,method)) methods) (list ,x (length ,others)))) (defgeneric dmc-test-mc.7 (x &rest others) (:method-combination dmc-test.7)) (defmethod dmc-test-mc.7 (x &rest others) (declare (ignore others)) nil) (deftest dmc-test-mc.7a (equal (apply #'dmc-test-mc.7 :foo (list 1 2 3 4 5 6 7 8)) '(:foo 8)) T) ;; Tests for D-M-C with :arguments option ;; created due to http://abcl.org/trac/ticket/201 (define-method-combination dmc-test-args-with-whole.1 () ((methods ())) (:arguments &whole whole) `(progn (format nil "using ~a" ,whole) ,@(mapcar (lambda (method) `(call-method ,method)) methods))) (defgeneric dmc-test-args-with-whole.1 (x) (:method-combination dmc-test-args-with-whole.1) (:method (x) x)) ;; This test fails throws an error under #201 (deftest dmc-test-args-with-whole.1 (dmc-test-args-with-whole.1 T) T) (define-method-combination dmc-test-args-with-whole.2 () ((methods ())) (:arguments &whole whole &rest rest) `(progn (format nil "using ~a ~a" ,whole ,rest) ,@(mapcar (lambda (method) `(call-method ,method)) methods))) (defgeneric dmc-test-args-with-whole.2 (x) (:method-combination dmc-test-args-with-whole.2) (:method (x) x)) (deftest dmc-test-args-with-whole.2 (dmc-test-args-with-whole.2 T) T) (define-method-combination dmc-test-args-with-whole.3a () ((methods ())) (:arguments &whole whole &optional opt) `(progn (format nil "using ~a ~a" ,whole ,opt) ,@(mapcar (lambda (method) `(call-method ,method)) methods))) (defgeneric dmc-test-args-with-whole.3a (x) (:method-combination dmc-test-args-with-whole.3a) (:method (x) x)) (deftest dmc-test-args-with-whole.3a (dmc-test-args-with-whole.3a T) T) (define-method-combination dmc-test-args-with-whole.3b () ((methods ())) (:arguments &whole whole &optional opt &key k) `(progn (format nil "using ~a ~a ~a" ,whole ,opt ,k) ,@(mapcar (lambda (method) `(call-method ,method)) methods))) (defgeneric dmc-test-args-with-whole.3b (x) (:method-combination dmc-test-args-with-whole.3b) (:method (x) x)) (deftest dmc-test-args-with-whole.3b (dmc-test-args-with-whole.3b T) T) (define-method-combination dmc-test-args-with-whole.3c () ((methods ())) (:arguments &whole whole &optional opt &rest r) `(progn (format nil "using ~a ~a ~a" ,whole ,opt ,r) ,@(mapcar (lambda (method) `(call-method ,method)) methods))) (defgeneric dmc-test-args-with-whole.3c (x) (:method-combination dmc-test-args-with-whole.3c) (:method (x) x)) (deftest dmc-test-args-with-whole.3c (dmc-test-args-with-whole.3c T) T) (define-method-combination dmc-test-args-with-whole.3d () ((methods ())) (:arguments &whole whole &optional opt &rest r &key k) `(progn (format nil "using ~a ~a ~a ~a" ,whole ,opt ,r ,k) ,@(mapcar (lambda (method) `(call-method ,method)) methods))) (defgeneric dmc-test-args-with-whole.3d (x) (:method-combination dmc-test-args-with-whole.3d) (:method (x) x)) (deftest dmc-test-args-with-whole.3d (dmc-test-args-with-whole.3d T) T) (define-method-combination dmc-test-args-with-whole.4 () ((methods ())) (:arguments &whole whole &key k) `(progn (format nil "using ~a ~a" ,whole ,k) ,@(mapcar (lambda (method) `(call-method ,method)) methods))) (defgeneric dmc-test-args-with-whole.4 (x) (:method-combination dmc-test-args-with-whole.4) (:method (x) x)) (deftest dmc-test-args-with-whole.4 (dmc-test-args-with-whole.4 T) T) (define-method-combination dmc-test-args-with-whole.5 () ((methods ())) (:arguments &whole whole &aux a) `(progn (format nil "using ~a ~a" ,whole ,a) ,@(mapcar (lambda (method) `(call-method ,method)) methods))) (defgeneric dmc-test-args-with-whole.5 (x) (:method-combination dmc-test-args-with-whole.5) (:method (x) x)) (deftest dmc-test-args-with-whole.5 (dmc-test-args-with-whole.5 T) T) (define-method-combination dmc-test-args-with-optional.1 () ((methods ())) (:arguments &optional a) `(progn ,@(mapcar (lambda (method) `(call-method ,method)) methods) ,a)) (defgeneric dmc-test-args-with-optional.1 (x &optional b) (:method-combination dmc-test-args-with-optional.1) (:method (x &optional b) (progn x b))) (deftest dmc-test-args-with-optional.1a (dmc-test-args-with-optional.1 T) nil) (deftest dmc-test-args-with-optional.1b (dmc-test-args-with-optional.1 T T) T) #-ccl ;; "The value (ABCL.TEST.LISP::A :DEFAULT) is not of the expected type SYMBOL." (define-method-combination dmc-test-args-with-optional.2 () ((methods *)) (:arguments &optional (a :default)) (print `(progn ,@(mapcar (lambda (method) `(call-method ,method)) methods) ,a))) #-ccl ;; "The value (ABCL.TEST.LISP::A :DEFAULT) is not of the expected type SYMBOL." (defgeneric dmc-test-args-with-optional.2 (x &optional b) (:method-combination dmc-test-args-with-optional.2) (:method (x &optional b) (progn x b))) (deftest dmc-test-args-with-optional.2a :documentation "TODO" (dmc-test-args-with-optional.2 T) :default) (deftest dmc-test-args-with-optional.2b :documentation "Describe what the test does here." (dmc-test-args-with-optional.2 T T) T) #-ccl ;; The value (ABCL.TEST.LISP::A :DEFAULT) is not of the expected type SYMBOL. (define-method-combination dmc-test-args-with-optional.3 () ((methods *)) (:arguments &optional (a :default)) (print `(progn ,@(mapcar (lambda (method) `(call-method ,method)) methods) ,a))) #-ccl ;; The value (ABCL.TEST.LISP::A :DEFAULT) is not of the expected type SYMBOL. (defgeneric dmc-test-args-with-optional.3 (x) (:method-combination dmc-test-args-with-optional.3) (:method (x) (progn x))) #-ccl ;; The value (ABCL.TEST.LISP::A :DEFAULT) is not of the expected type SYMBOL. (deftest dmc-test-args-with-optional.3 :documentation "TODO" (dmc-test-args-with-optional.3 T) nil) #-ccl ;; The value (ABCL.TEST.LISP::A :DEFAULT ABCL.TEST.LISP::SUP-P) is not of the expected type SYMBOL. (define-method-combination dmc-test-args-with-optional.4 () ((methods ())) (:arguments &optional (a :default sup-p)) `(progn ,@(mapcar (lambda (method) `(call-method ,method)) methods) (values ,a ,sup-p))) #-ccl (defgeneric dmc-test-args-with-optional.4a (x &optional b) (:method-combination dmc-test-args-with-optional.4) (:method (x &optional b) (progn x b))) #-ccl (deftest dmc-test-args-with-optional.4a (dmc-test-args-with-optional.4a T) :default nil) #-ccl (deftest dmc-test-args-with-optional.4b (dmc-test-args-with-optional.4a T T) T T) #-ccl (defgeneric dmc-test-args-with-optional.4c (x) (:method-combination dmc-test-args-with-optional.4) (:method (x) (progn x))) #-ccl (deftest dmc-test-args-with-optional.4c :documentation "TODO" (dmc-test-args-with-optional.4c T) nil nil) abcl-src-1.9.0/test/lisp/abcl/closure-serialization.lisp0100644 0000000 0000000 00000002522 14202767264 022020 0ustar000000000 0000000 ;;; compiler-tests.lisp ;;; ;;; Copyright (C) 2010 Erik Huelsmann ;;; ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (in-package #:abcl.test.lisp) (require '#:java) (defun f (x) (flet ((g (y) (cons x y))) (let* ((b (java:jnew "java.io.ByteArrayOutputStream")) (o (java:jnew "java.io.ObjectOutputStream" b))) (java:jcall "writeObject" o #'g) (java:jcall "flush" o) (java:jcall "toByteArray" b)))) (deftest serialization-of-closure (let* ((b (java:jnew "java.io.ByteArrayInputStream" (f 3))) (i (java:jnew "java.io.ObjectInputStream" b))) (fmakunbound 'f) (funcall (java:jcall "readObject" i) T)) '(3 . T)) abcl-src-1.9.0/test/lisp/abcl/compiler-tests.lisp0100644 0000000 0000000 00000033305 14202767264 020446 0ustar000000000 0000000 ;;; compiler-tests.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #+abcl (require '#:jvm) (in-package #:abcl.test.lisp) (eval-when (:compile-toplevel :load-toplevel :execute) (defvar most-positive-java-long 9223372036854775807) (defvar most-negative-java-long -9223372036854775808)) #+abcl (assert (eql most-positive-java-long ext:most-positive-java-long)) #+abcl (assert (eql most-negative-java-long ext:most-negative-java-long)) (defmacro define-compiler-test (name lambda-form &key args results) `(deftest ,name (progn (fmakunbound ',name) (defun ,name ,(cadr lambda-form) ,@(cddr lambda-form)) (values (funcall ',name ,@args) (multiple-value-list (compile ',name)) (compiled-function-p #',name) (funcall ',name ,@args))) ,results (,name nil nil) t ,results)) #+abcl (deftest unused.1 (let ((output (with-output-to-string (*error-output*) (compile nil '(lambda () (let ((x 42)) 17)))))) (integerp (search "The variable X is defined but never used." output))) t) (deftest unused.2 (progn (fmakunbound 'unused.2) (defun unused.2 () (let ((x 42)) 17)) (values #-lispworks (multiple-value-list (compile 'unused.2)) #+lispworks (let ((list (multiple-value-list (compile 'unused.2)))) (list (first list) (not (null (second list))) (third list))) (unused.2))) #+allegro (unused.2 t nil) #+clisp (unused.2 1 nil) #+(or cmu sbcl abcl) (unused.2 nil nil) #+lispworks (unused.2 t nil) 17) (deftest plus.1 (progn (fmakunbound 'plus.1) (defun plus.1 (x y) (+ x y)) (compile 'plus.1) (plus.1 most-positive-fixnum most-positive-fixnum)) #.(+ most-positive-fixnum most-positive-fixnum)) (deftest plus.2 (progn (fmakunbound 'plus.2) (defun plus.2 (x y) (declare (optimize speed)) (declare (type fixnum x y)) (+ x y)) (compile 'plus.2) (plus.2 most-positive-fixnum most-positive-fixnum)) #.(+ most-positive-fixnum most-positive-fixnum)) (deftest plus.3 (progn (fmakunbound 'plus.3) (defun plus.3 (x y) (declare (optimize speed (safety 0))) (declare (type fixnum x y)) (+ x y)) (compile 'plus.3) (plus.3 most-positive-fixnum most-positive-fixnum)) #.(+ most-positive-fixnum most-positive-fixnum)) #+allegro (pushnew 'plus.3 *expected-failures*) #+abcl (define-compiler-test plus.4 (lambda (x y) (declare (type (integer #.most-negative-java-long #.most-positive-java-long) x y)) (+ x y)) :args (#.most-positive-java-long #.most-positive-java-long) :results #.(+ most-positive-java-long most-positive-java-long)) (define-compiler-test minus.1 (lambda (x) (declare (type fixnum x)) (- x)) :args (#.most-negative-fixnum) :results #.(- most-negative-fixnum)) #-clisp (define-compiler-test minus.2 (lambda (x) (declare (type (integer #.most-negative-java-long #.most-positive-java-long) x)) (- x)) :args (#.most-negative-java-long) :results #.(- most-negative-java-long)) #-clisp (define-compiler-test minus.3 (lambda (x y) (declare (type (integer #.most-negative-java-long #.most-positive-java-long) x y)) (- x y)) :args (#.most-negative-java-long #.most-positive-java-long) :results #.(- most-negative-java-long most-positive-java-long)) #-clisp (define-compiler-test logxor-minus.1 (lambda (x) (declare (type (integer 0 255) x)) (logxor (- x) #.most-positive-java-long)) :args (17) :results -9223372036854775792) #-clisp (deftest times.1 (progn (fmakunbound 'times.1) (defun times.1 (x y) (* x y)) (compile 'times.1) (times.1 most-positive-fixnum most-positive-fixnum)) #.(* most-positive-fixnum most-positive-fixnum)) (deftest times.2 (progn (fmakunbound 'times.2) (defun times.2 (x y) (declare (optimize speed)) (declare (type fixnum x y)) (* x y)) (compile 'times.2) (times.2 most-positive-fixnum most-positive-fixnum)) #.(* most-positive-fixnum most-positive-fixnum)) (deftest times.3 (progn (fmakunbound 'times.3) (defun times.3 (x y) (declare (optimize speed (safety 0))) (declare (type fixnum x y)) (* x y)) (compile 'times.3) (times.3 most-positive-fixnum most-positive-fixnum)) #.(* most-positive-fixnum most-positive-fixnum)) (deftest dotimes.1 (progn (fmakunbound 'dotimes.1) (defun dotimes.1 () (declare (optimize speed (safety 0))) (let ((result 0)) (dotimes (i 10) (incf result)) result)) (compile 'dotimes.1) (dotimes.1)) 10) (deftest dotimes.2 (progn (fmakunbound 'dotimes.2) (defun dotimes.2 () (declare (optimize speed (safety 0))) (let ((result 0)) (declare (type fixnum result)) (dotimes (i 10) (incf result)) result)) (compile 'dotimes.2) (dotimes.2)) 10) #+abcl (deftest derive-type-logxor.1 (let ((type (jvm:derive-compiler-type `(logxor (the (unsigned-byte 8) x) (the (unsigned-byte 8) y))))) (and (sys:integer-type-p type) (values (sys:integer-type-low type) (sys:integer-type-high type)))) 0 255) #+abcl (deftest derive-type-logxor.2 (let ((type (jvm:derive-compiler-type `(logxor 441516657 (the (integer 0 8589934588) x))))) (and (sys:integer-type-p type) (values (sys:integer-type-low type) (sys:integer-type-high type)))) 0 8589934588) #+abcl (deftest derive-type-logxor.3 (let ((type (jvm:derive-compiler-type `(logxor 441516657 (the (integer 0 8589934588) x) (ash (the (integer 0 8589934588) x) -5))))) (and (sys:integer-type-p type) (values (sys:integer-type-low type) (sys:integer-type-high type)))) 0 8589934588) (deftest ash.1 (progn (fmakunbound 'ash.1) (defun ash.1 (n shift) (declare (type (integer 0 8589934588) n)) (declare (type (integer -31 -1) shift)) (ash n shift)) (compile 'ash.1) (values (ash.1 8589934588 -1) (ash.1 8589934588 -2) (ash.1 8589934588 -3) (ash.1 8589934588 -4) (ash.1 8589934588 -5) (ash.1 8589934588 -6) (ash.1 8589934588 -31))) 4294967294 2147483647 1073741823 536870911 268435455 134217727 3) #-clisp (deftest bignum-constant.1 (progn (fmakunbound 'bignum-constant.1) (defun bignum-constant.1 () #.most-positive-java-long) (values (funcall 'bignum-constant.1) (multiple-value-list (compile 'bignum-constant.1)) (compiled-function-p #'bignum-constant.1) (funcall 'bignum-constant.1))) #.most-positive-java-long (bignum-constant.1 nil nil) t #.most-positive-java-long) #-clisp (deftest bignum-constant.2 (progn (fmakunbound 'bignum-constant.2) (defun bignum-constant.2 () #.(1+ most-positive-java-long)) (values (funcall 'bignum-constant.2) (multiple-value-list (compile 'bignum-constant.2)) (compiled-function-p #'bignum-constant.2) (funcall 'bignum-constant.2))) #.(1+ most-positive-java-long) (bignum-constant.2 nil nil) t #.(1+ most-positive-java-long)) #-clisp (deftest bignum-constant.3 (progn (fmakunbound 'bignum-constant.3) (defun bignum-constant.3 () #.most-negative-java-long) (values (funcall 'bignum-constant.3) (multiple-value-list (compile 'bignum-constant.3)) (compiled-function-p #'bignum-constant.3) (funcall 'bignum-constant.3))) #.most-negative-java-long (bignum-constant.3 nil nil) t #.most-negative-java-long) #-clisp (deftest bignum-constant.4 (progn (fmakunbound 'bignum-constant.4) (defun bignum-constant.4 () #.(1- most-negative-java-long)) (values (funcall 'bignum-constant.4) (multiple-value-list (compile 'bignum-constant.4)) (compiled-function-p #'bignum-constant.4) (funcall 'bignum-constant.4))) #.(1- most-negative-java-long) (bignum-constant.4 nil nil) t #.(1- most-negative-java-long)) (deftest shiftf.1 (progn (fmakunbound 'shiftf.1) (defun shiftf.1 (x) (declare (type (integer -5213 238468) x)) (+ x (shiftf x 168771))) (values (funcall 'shiftf.1 96411) (multiple-value-list (compile 'shiftf.1)) (compiled-function-p #'shiftf.1) (funcall 'shiftf.1 96411))) 192822 (shiftf.1 nil nil) t 192822) (deftest logand-values.1 (ignore-errors (funcall (compile nil '(lambda () (logand 18 (values 42 7)))))) 2) (deftest logand-lognot.1 (progn (fmakunbound 'logand-lognot.1) (defun logand-lognot.1 (x) (declare (type (unsigned-byte 32) x)) (logand #.(1- (expt 2 32)) (lognot x))) (values (funcall 'logand-lognot.1 123456789) (multiple-value-list (compile 'logand-lognot.1)) (compiled-function-p #'logand-lognot.1) (funcall 'logand-lognot.1 123456789))) 4171510506 (logand-lognot.1 nil nil) t 4171510506) (deftest logior-logand-setf.1 (progn (fmakunbound 'foo) (defun foo (x y) (declare (type (integer 2005076 2881158415) x)) (declare (type (integer -28121355 17748872) y)) (logior (logand (setf y -3475589) x)) y) (values (funcall 'foo 12345678 42) (multiple-value-list (compile 'foo)) (compiled-function-p #'foo) (funcall 'foo 12345678 42))) -3475589 (foo nil nil) t -3475589) (deftest logxor.1 (progn (fmakunbound 'foo) (defun foo () (logxor -4153366606 (- 0))) (values (funcall 'foo) (multiple-value-list (compile 'foo)) (compiled-function-p #'foo) (funcall 'foo))) -4153366606 (foo nil nil) t -4153366606) (define-compiler-test min.1 (lambda (x y) (declare (type fixnum x y)) (min x y)) :args (3 4) :results 3) (define-compiler-test min.2 (lambda (x y) (declare (type fixnum x y)) (min x y)) :args (#.most-positive-fixnum #.most-negative-fixnum) :results #.most-negative-fixnum) #-clisp (define-compiler-test min.3 (lambda (x y) (declare (type (integer #.most-negative-java-long #.most-positive-java-long) x y)) (min x y)) :args (3 4) :results 3) #-clisp (define-compiler-test min.4 (lambda (x y) (declare (type (integer #.most-negative-java-long #.most-positive-java-long) x y)) (min x y)) :args (#.most-positive-java-long #.most-negative-java-long) :results #.most-negative-java-long) (define-compiler-test max.1 (lambda (x y) (declare (type fixnum x y)) (max x y)) :args (3 4) :results 4) #-clisp (define-compiler-test max.2 (lambda (x y) (declare (type fixnum x y)) (max x y)) :args (#.most-positive-fixnum #.most-negative-fixnum) :results #.most-positive-fixnum) #-clisp (define-compiler-test max.3 (lambda (x y) (declare (type (integer #.most-negative-java-long #.most-positive-java-long) x y)) (max x y)) :args (3 4) :results 4) #-clisp (define-compiler-test max.4 (lambda (x y) (declare (type (integer #.most-negative-java-long #.most-positive-java-long) x y)) (max x y)) :args (#.most-positive-java-long #.most-negative-java-long) :results #.most-positive-java-long) ;;; ticket #147 #+abcl (deftest compiler.1 (let ((tmpfile (ext::make-temp-file)) (original-print-case *print-case*) (forms `((in-package :cl-user) (eval-when (:compile-toplevel :load-toplevel :execute) (setf *print-case* ':downcase)) (defstruct rec a b)))) (with-open-file (s tmpfile :direction :output) (dolist (form forms) (write form :stream s))) (let ((result (compile-file tmpfile))) (delete-file tmpfile) (setf *print-case* original-print-case) (not (null result)))) t) ;;; ticket #156 #+abcl (deftest compiler.2 (let ((tmpfile (ext::make-temp-file)) (line "(defconstant a #.(make-array '(8 256) :element-type '(unsigned-byte 32) :initial-element 0))")) (with-open-file (s tmpfile :direction :output) (format s "~A" line)) (let ((result (compile-file tmpfile))) #+nil (delete-file tmpfile) (not (null result)))) t) ;;; ticket #189 (deftest compiler.3 (eql (funcall (compile nil (lambda (a) (declare (type unsigned-byte a)) (max 28105919 a 1016934843))) 10545160975) 10545160975) t) ;;; ticket #241 (deftest compiler.4a (multiple-value-bind (rv error) (ignore-errors (compile nil '(lambda (&rest args &optional x)))) (typep error 'program-error)) t) (deftest compiler.4b (multiple-value-bind (rv error) (ignore-errors (compile nil '(lambda (&key args &optional x)))) (typep error 'program-error)) t) abcl-src-1.9.0/test/lisp/abcl/condition-tests.lisp0100644 0000000 0000000 00000024043 14202767264 020621 0ustar000000000 0000000 ;;; condition-tests.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (in-package #:abcl.test.lisp) (defun filter (string) "If STRING is unreadable, return \"#<>\"; otherwise return STRING unchanged." (let ((len (length string))) (when (> len 3) (when (string= (subseq string 0 2) "#<") (when (char= (char string (1- len)) #\>) (setf string "#<>"))))) string) (deftest condition.1 (filter (write-to-string (make-condition 'condition) :escape t)) "#<>") (deftest condition.2 (filter (write-to-string (make-condition 'condition) :escape nil)) #+(or abcl allegro) "#<>" #+clisp "Condition of type CONDITION." #+(or cmu sbcl) "Condition CONDITION was signalled.") #+(or abcl allegro) (deftest condition.3 (write-to-string (make-condition 'condition :format-control "The bear is armed.") :escape nil) "The bear is armed.") (deftest print-not-readable-object.1 (signals-error (slot-boundp (make-condition 'print-not-readable) #+abcl 'system::object #+allegro 'excl::object #+clisp 'system::$object #+cmu 'lisp::object #+sbcl 'sb-kernel::object) 'error) nil) (deftest print-not-readable-object.2 (slot-boundp (make-condition 'print-not-readable) #+abcl 'system::object #+allegro 'excl::object #+clisp 'system::$object #+cmu 'lisp::object #+sbcl 'sb-kernel::object) nil) (deftest type-error.1 (type-error-datum (make-instance 'type-error :datum 42)) 42) (deftest type-error.2 (type-error-expected-type (make-instance 'type-error :expected-type 'symbol)) symbol) (deftest type-error.3 (let ((c (make-condition 'type-error :datum 42 :expected-type 'symbol))) (filter (write-to-string c :escape nil))) #+allegro "#<>" #+clisp "Condition of type TYPE-ERROR." #+cmu "Type-error in NIL: 42 is not of type SYMBOL" #+(or abcl sbcl) "The value 42 is not of type SYMBOL.") (deftest type-error.4 (let ((c (make-condition 'type-error :datum 42 :expected-type 'symbol))) (filter (format nil "~A" c))) #+allegro "#<>" #+clisp "Condition of type TYPE-ERROR." #+cmu "Type-error in NIL: 42 is not of type SYMBOL" #+(or abcl sbcl) "The value 42 is not of type SYMBOL.") (deftest simple-type-error.1 (slot-boundp (make-condition 'simple-type-error) #+abcl 'system::datum #+allegro 'excl::datum #+clisp 'system::$datum #+cmu 'conditions::datum #+sbcl 'sb-kernel::datum) nil) (deftest simple-type-error.2 (slot-boundp (make-condition 'simple-type-error) #+abcl 'system::expected-type #+allegro 'excl::expected-type #+clisp 'system::$expected-type #+cmu 'conditions::expected-type #+sbcl 'sb-kernel::expected-type) nil) (deftest simple-type-error.3 (slot-boundp (make-condition 'simple-type-error) #+abcl 'system::format-control #+allegro 'excl::format-control #+clisp 'system::$format-control #+cmu 'conditions::format-control #+sbcl 'sb-kernel:format-control) #-clisp nil #+clisp t) #+clisp (deftest simple-type-error.3a (simple-condition-format-control (make-condition 'simple-type-error)) nil) (deftest simple-type-error.4 (slot-boundp (make-condition 'simple-type-error) #+abcl 'system::format-arguments #+allegro 'excl::format-arguments #+clisp 'system::$format-arguments #+cmu 'conditions::format-arguments #+sbcl 'sb-kernel::format-arguments) t) (deftest simple-type-error.5 (slot-value (make-condition 'simple-type-error) #+abcl 'system::format-arguments #+allegro 'excl::format-arguments #+clisp 'system::$format-arguments #+cmu 'conditions::format-arguments #+sbcl 'sb-kernel::format-arguments) nil) (deftest simple-type-error.6 (slot-boundp (make-instance 'simple-type-error) #+abcl 'system::datum #+allegro 'excl::datum #+clisp 'system::$datum #+cmu 'conditions::datum #+sbcl 'sb-kernel::datum) nil) (deftest simple-type-error.7 (slot-boundp (make-instance 'simple-type-error) #+abcl 'system::expected-type #+allegro 'excl::expected-type #+clisp 'system::$expected-type #+cmu 'conditions::expected-type #+sbcl 'sb-kernel::expected-type) nil) (deftest simple-type-error.8 (slot-boundp (make-instance 'simple-type-error) #+abcl 'system::format-control #+allegro 'excl::format-control #+clisp 'system::$format-control #+cmu 'conditions::format-control #+sbcl 'sb-kernel:format-control) #-clisp nil #+clisp t) #+clisp (deftest simple-type-error.8a (simple-condition-format-control (make-instance 'simple-type-error)) nil) (deftest simple-type-error.9 (slot-boundp (make-instance 'simple-type-error) #+abcl 'system::format-arguments #+allegro 'excl::format-arguments #+clisp 'system::$format-arguments #+cmu 'conditions::format-arguments #+sbcl 'sb-kernel::format-arguments) t) (deftest simple-type-error.10 (slot-value (make-instance 'simple-type-error) #+abcl 'system::format-arguments #+allegro 'excl::format-arguments #+clisp 'system::$format-arguments #+cmu 'conditions::format-arguments #+sbcl 'sb-kernel::format-arguments) nil) (deftest define-condition.1 (progn (setf (find-class 'test-error) nil) (define-condition test-error (type-error) ()) (type-error-datum (make-condition 'test-error :datum 42 :expected-type 'symbol))) 42) (deftest define-condition.2 (progn (setf (find-class 'test-error) nil) (define-condition test-error (type-error) ()) (type-error-expected-type (make-condition 'test-error :datum 42 :expected-type 'symbol))) symbol) #+(or abcl allegro) (deftest define-condition.3 (progn (setf (find-class 'test-error) nil) (define-condition test-error (type-error) ()) (slot-boundp (make-condition 'test-error) #+abcl 'system::format-control #+allegro 'excl::format-control)) nil) #+(or abcl allegro) (deftest define-condition.4 (progn (setf (find-class 'test-error) nil) (define-condition test-error (type-error) ()) (simple-condition-format-arguments (make-condition 'test-error))) nil) (deftest define-condition.5 (progn (setf (find-class 'test-error) nil) (define-condition test-error (type-error) ()) (let ((c (make-condition 'test-error :datum 42 :expected-type 'symbol))) (filter (format nil "~A" c)))) #+allegro "#<>" #+clisp "Condition of type TEST-ERROR." #+cmu "Type-error in NIL: 42 is not of type SYMBOL" #+(or abcl sbcl) "The value 42 is not of type SYMBOL.") #+(or abcl clisp cmu sbcl) (deftest define-condition.6 (progn (setf (find-class 'test-error) nil) (define-condition test-error (type-error) ()) (let ((c (make-condition 'test-error :datum 42 :expected-type 'symbol))) (filter (write-to-string c :escape nil)))) #+allegro "#<>" #+clisp "Condition of type TEST-ERROR." #+cmu "Type-error in NIL: 42 is not of type SYMBOL" #+(or abcl sbcl) "The value 42 is not of type SYMBOL.") #+(or abcl allegro) (deftest define-condition.7 (progn (setf (find-class 'test-error) nil) (define-condition test-error (type-error) ()) (let ((c (make-condition 'test-error :datum 42 :expected-type 'symbol :format-control "The bear is armed."))) (write-to-string c :escape nil))) "The bear is armed.") #+(or abcl allegro) (deftest define-condition.8 (progn (setf (find-class 'test-error) nil) (define-condition test-error (type-error) ()) (let ((c (make-condition 'test-error :datum 42 :expected-type 'symbol :format-control "~A is ~A." :format-arguments (list "The bear" "armed")))) (write-to-string c :escape nil))) "The bear is armed.") #+(or abcl allegro) (deftest define-condition.9 (progn (setf (find-class 'test-error) nil) (define-condition test-error (condition) ()) (let ((c (make-condition 'test-error :format-control "The bear is armed."))) (write-to-string c :escape nil))) "The bear is armed.") #+(or abcl allegro) (deftest define-condition.10 (progn (setf (find-class 'test-error) nil) (define-condition test-error (condition) ()) (let ((c (make-condition 'test-error :format-control "~A is ~A." :format-arguments (list "The bear" "armed")))) (write-to-string c :escape nil))) "The bear is armed.") abcl-src-1.9.0/test/lisp/abcl/file-system-tests.lisp0100644 0000000 0000000 00000045575 14202767264 021111 0ustar000000000 0000000 ;;; file-system-tests.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #+sbcl (require '#:sb-posix) (in-package #:abcl.test.lisp) (defparameter *this-file* (merge-pathnames (make-pathname :type "lisp") (if (find :asdf2 *features*) (merge-pathnames (make-pathname :name (pathname-name *load-truename*)) (asdf:system-relative-pathname :abcl "test/lisp/abcl/")) *load-truename*))) (defparameter *this-directory* (if (find :asdf2 *features*) (asdf:system-relative-pathname :abcl "test/lisp/abcl/") (make-pathname :host (pathname-host *load-truename*) :device (pathname-device *load-truename*) :directory (pathname-directory *load-truename*)))) (defun pathnames-equal-p (pathname1 pathname2) #-(or allegro clisp cmu lispworks) (equal pathname1 pathname2) #+(or allegro clisp cmu) (and (pathnamep pathname1) (pathnamep pathname2) (equal (pathname-host pathname1) (pathname-host pathname2)) (equal (pathname-device pathname1) (pathname-device pathname2)) (equal (pathname-directory pathname1) (pathname-directory pathname2)) (equal (pathname-name pathname1) (pathname-name pathname2)) (equal (pathname-type pathname1) (pathname-type pathname2)) (or (equal (pathname-version pathname1) (pathname-version pathname2)) (and (member (pathname-version pathname1) '(:newest nil)) (member (pathname-version pathname2) '(:newest nil)) t))) #+lispworks (string= (namestring pathname1) (namestring pathname2))) #+abcl (defun run-shell-command (command &key directory (output *standard-output*)) (ext:run-shell-command command :directory directory :output output)) #+allegro (defun run-shell-command (command &key directory (output *standard-output*)) (excl:run-shell-command command :directory directory :input nil :output output)) #+clisp (defun run-shell-command (command &key directory (output *standard-output*)) (declare (ignore output)) ;; FIXME (let (status old-directory) (when directory (setf old-directory (ext:cd)) (ext:cd directory)) (unwind-protect (setf status (ext:run-shell-command command)) (when old-directory (ext:cd old-directory))) (cond ((numberp status) status) ((eq status t) 0) (t -1)))) #+cmu (defun run-shell-command (command &key directory (output *standard-output*)) (when directory (setf command (concatenate 'string "\\cd \"" (namestring (pathname directory)) "\" && " command))) (ext:process-exit-code (ext:run-program "/bin/sh" (list "-c" command) :input nil :output output))) #+sbcl (defun run-shell-command (command &key directory (output *standard-output*)) (when directory (setf command (concatenate 'string "\\cd \"" (namestring (pathname directory)) "\" && " command))) (sb-ext:process-exit-code (sb-ext:run-program "/bin/sh" (list "-c" command) :input nil :output output))) #+lispworks (defun run-shell-command (command &key directory (output *standard-output*)) (when directory #+unix (setf command (concatenate 'string "\\cd \"" (namestring (pathname directory)) "\" && " command))) (system:call-system-showing-output command :shell-type "/bin/sh" :output-stream output)) (defun copy-file (from to) (let* ((from-namestring (namestring (pathname from))) (to-namestring (namestring (pathname to))) (command (concatenate 'string "cp " from-namestring " " to-namestring))) (zerop (run-shell-command command)))) (defun make-symbolic-link (from to) (let* ((from-namestring (namestring (pathname from))) (to-namestring (namestring (pathname to))) (command (concatenate 'string "ln -s " from-namestring " " to-namestring))) (zerop (run-shell-command command)))) (defun probe-directory (pathname) #+abcl (ext:probe-directory pathname) #+allegro (excl:probe-directory pathname) #+clisp (ignore-errors (ext:probe-directory pathname)) #+cmu (probe-file pathname) ; FIXME #+sbcl (probe-file pathname) ; FIXME #+lispworks (probe-file pathname) ) (defun file-directory-p (pathname) #+abcl (ext:file-directory-p pathname) #+allegro (excl:file-directory-p pathname) #-(or abcl allegro) (let* ((namestring (namestring pathname)) (len (length namestring)) (last-char (and (> len 0) (char namestring (1- len))))) (eql last-char #+windows #\\ #-windows #\/))) (defun make-directory (pathname) #+allegro (excl:make-directory pathname) #-allegro (and (ensure-directories-exist pathname) t)) (defun delete-directory (pathname) #+abcl (delete-file pathname) #+allegro (excl:delete-directory pathname) #+clisp (ext:delete-dir (namestring pathname)) #+cmu (unix:unix-rmdir (namestring pathname)) #+sbcl (zerop (sb-posix:rmdir (namestring pathname))) #+lispworks (lw:delete-directory pathname) ) ;; This approach is race-prone, but it should be adequate for our limited ;; purposes here. (defun make-temporary-filename (directory) (unless (probe-directory directory) (error "The directory ~S does not exist." directory)) (dotimes (i 10) (let ((pathname (merge-pathnames (make-pathname :name (symbol-name (gensym)) :type nil) directory))) (unless (probe-file pathname) (return-from make-temporary-filename pathname)))) (error "Unable to create a temporary filename in ~S" directory)) (defun touch (filespec) (with-open-file (stream filespec :direction :output :if-exists :error))) (defun make-temporary-directory (parent-directory) (let* ((tmp (make-temporary-filename parent-directory)) (directory-namestring (concatenate 'string (namestring tmp) "/")) (directory-pathname (pathname directory-namestring))) (make-directory directory-pathname) directory-pathname)) (defun delete-directory-and-files (pathspec &key (quiet t) (dry-run nil)) (let* ((namestring (namestring pathspec)) (len (length namestring)) (last-char (and (> len 0) (char namestring (1- len))))) (unless (eql last-char #+windows #\\ #-windows #\/) (setf namestring (concatenate 'string namestring #+windows "\\" #-windows "/"))) (let ((pathname (pathname namestring))) (unless (probe-directory pathname) (error "Directory does not exist: ~S" pathname)) (unless quiet (format t "~&processing directory ~S~%" pathname)) (let ((list (directory (make-pathname :name :wild :type #-clisp :wild #+clisp nil :defaults pathname)))) (dolist (x list) (cond ((file-directory-p x) (delete-directory-and-files x :quiet quiet)) (t (unless quiet (format t "~&deleting file ~S~%" x)) (unless dry-run (delete-file x))))) (unless quiet (format t "~&deleting directory ~S~%" pathname)) (unless dry-run (delete-directory pathname)))))) #-(or allegro clisp lispworks windows) (deftest run-shell-command.1 (let* ((raw-string (with-output-to-string (s) (run-shell-command "pwd" :directory *this-directory* :output s))) (string (string-right-trim '(#\newline #\return) raw-string)) (length (length string))) (when (> length 0) (unless (eql (char string (1- length)) #\/) (setf string (concatenate 'string string (string #\/))))) (string= string (directory-namestring *this-directory*))) t) #-(or allegro clisp lispworks windows) (deftest run-shell-command.2 (let* ((directory (probe-file (merge-pathnames "../" *this-directory*))) (raw-string (with-output-to-string (s) (run-shell-command "pwd" :directory directory :output s))) (string (string-right-trim '(#\newline #\return) raw-string)) (length (length string))) (when (> length 0) (unless (eql (char string (1- length)) #\/) (setf string (concatenate 'string string (string #\/))))) (string= string (directory-namestring directory))) t) (deftest probe-file.1 (pathnames-equal-p (probe-file *this-file*) *this-file*) t) (deftest probe-file.2 (let ((pathname #p".")) #-clisp (pathnames-equal-p (probe-file pathname) (truename pathname)) #+clisp ;; "." names a directory, not a file. (signals-error (probe-file pathname) 'file-error)) t) #+(and clisp windows) (pushnew 'probe-file.2 *expected-failures*) (deftest probe-file.3 (let ((pathname #p"./")) #-clisp (pathnames-equal-p (probe-file pathname) *this-directory*) #+clisp ;; "no file name given" (signals-error (probe-file pathname) 'file-error)) t) (deftest probe-file.4 (let ((pathname #p"..")) #-clisp (pathnames-equal-p (probe-file pathname) (truename pathname)) #+clisp ;; ".." names a directory, not a file. (signals-error (probe-file pathname) 'file-error)) t) #+(and clisp windows) (pushnew 'probe-file.4 *expected-failures*) (deftest probe-file.5 (or ;; It might not exist. That's OK. (null (probe-directory #p"/home/")) (pathnames-equal-p (probe-file #p"/home") (probe-file #p"/home/"))) t) #+(or allegro cmu clisp) (pushnew 'probe-file.5 *expected-failures*) (deftest truename.1 (pathnames-equal-p (truename *this-file*) *this-file*) t) (deftest truename.2 (pathnames-equal-p (truename #p"./") *this-directory*) t) (deftest directory.1 (let ((list (directory *this-file*))) (and (= (length list) 1) (pathnames-equal-p (car list) *this-file*))) t) ;; Verify that DIRECTORY returns nil if the directory is empty. (deftest directory.2 (let ((directory-pathname (make-temporary-directory *this-directory*))) (unwind-protect (directory (make-pathname :name :wild :defaults directory-pathname)) (delete-directory-and-files directory-pathname))) nil) ;; A directory with a one file named "foo". (deftest directory.3 (let ((directory-pathname (make-temporary-directory *this-directory*))) (unwind-protect (let ((file-pathname (make-pathname :name "foo" :defaults directory-pathname))) (touch file-pathname) (let ((directory (directory (make-pathname :name :wild :defaults directory-pathname)))) (and (listp directory) (= (length directory) 1) (pathnames-equal-p (car directory) file-pathname)))) (delete-directory-and-files directory-pathname))) t) ;; Same as DIRECTORY.3, but use :type :wild for the wildcard. (deftest directory.4 (let ((directory-pathname (make-temporary-directory *this-directory*))) (unwind-protect (let ((file-pathname (make-pathname :name "foo" :defaults directory-pathname))) (touch file-pathname) (let ((directory (directory (make-pathname :name :wild :type :wild :defaults directory-pathname)))) (and (listp directory) (= (length directory) 1) (pathnames-equal-p (truename (car directory)) (truename file-pathname))))) (delete-directory-and-files directory-pathname))) t) #+clisp ;; A pathname with type nil does not match a wildcard with type :WILD. (pushnew 'directory.4 *expected-failures*) #-windows (deftest symlink.1 (let* ((tmp1 (make-temporary-filename *this-directory*)) (tmp2 (make-temporary-filename *this-directory*))) (unwind-protect (values (unwind-protect (and ;; Copy this file to tmp1. (copy-file *this-file* tmp1) (pathnames-equal-p (probe-file tmp1) tmp1) ;; Create tmp2 as a symlink to tmp1. (make-symbolic-link tmp1 tmp2) ;; Verify that the symlink exists and points to the copy. (pathnames-equal-p (probe-file tmp2) tmp1) (pathnames-equal-p (truename tmp2) tmp1)) ;; Delete the symlink. (when (probe-file tmp2) (delete-file tmp2))) ;; Copy should still exist after symlink is deleted. (pathnames-equal-p (probe-file tmp1) tmp1)) (when (probe-file tmp1) (delete-file tmp1)))) t t) #+allegro ;; Allegro's PROBE-FILE doesn't follow the symlink. (pushnew 'symlink.1 *expected-failures*) #-windows (deftest symlink.2 (let* ((copy (make-temporary-filename *this-directory*)) (link (make-temporary-filename *this-directory*)) directory) (unwind-protect (and ;; Copy this file to copy. (copy-file *this-file* copy) ;; Verify that copy exists. (pathnames-equal-p (probe-file copy) copy) ;; Create link as a symlink to copy. (make-symbolic-link copy link) ;; Verify that the symlink appears in the directory listing. (setf directory (directory link)) (= (length directory) 1) ;; The directory listing should contain the truename of the symlink. (pathnames-equal-p (car directory) (truename link))) (progn ;; Clean up. (when (probe-file link) (delete-file link)) (when (probe-file copy) (delete-file copy))))) t) #+allegro (pushnew 'symlink.2 *expected-failures*) ;; user-homedir-pathname &optional host => pathname ;; "USER-HOMEDIR-PATHNAME returns a pathname without any name, type, or version ;; component (those components are all nil) for the user's home directory on ;; HOST. If it is impossible to determine the user's home directory on HOST, ;; then nil is returned. USER-HOMEDIR-PATHNAME never returns nil if HOST is not ;; supplied." (deftest user-homedir-pathname.1 (let ((pathname (user-homedir-pathname))) (values (pathnamep pathname) (pathname-name pathname) (pathname-type pathname) (pathname-version pathname))) t nil nil nil) #+allegro ;; Allegro's version component is :UNSPECIFIC. (pushnew 'user-homedir-pathname.1 *expected-failures*) (deftest file-system.directory-namestring.1 (let ((pathname (user-homedir-pathname))) (equal (namestring pathname) (directory-namestring pathname))) #-windows t #+windows ;; The drive prefix ("C:\\") is not part of the directory namestring. nil) #+clisp (pushnew 'file-system.directory-namestring.1 *expected-failures*) (deftest file.system.directory-namestring.2 (let ((pathname (user-homedir-pathname))) (equal (directory-namestring pathname) (namestring (make-pathname :directory (pathname-directory pathname))))) t) #+clisp (pushnew 'file-system.directory-namestring.2 *expected-failures*) (deftest ensure-directories-exist.1 (let* ((tmp (make-temporary-filename *this-directory*)) (directory-namestring (concatenate 'string (namestring tmp) "/")) (file-namestring (concatenate 'string directory-namestring "foo.bar"))) (multiple-value-bind (path created) (ensure-directories-exist file-namestring) (values ;; 1. "The primary value is the given pathspec..." #+(or allegro clisp) (eq path file-namestring) #-(or allegro clisp) (pathnames-equal-p (pathname path) (pathname file-namestring)) ;; 2. Verify that the directory was created. created ;; 3. Verify that the directory exists. #+clisp ;; CLISP's PROBE-DIRECTORY just returns T. (ext:probe-directory directory-namestring) ;; ABCL fills in DEVICE as :UNSPECIFIC when resolving ;; filesystem paths on non-M$DOG #+abcl (not (null (truename directory-namestring))) #-(or clisp abcl) (pathnames-equal-p (probe-file directory-namestring) (pathname directory-namestring)) ;; 4. Delete the directory. (when (probe-directory directory-namestring) (delete-directory directory-namestring)) ;; 5. Verify that the directory is no longer there. (probe-directory directory-namestring)) )) t t t t nil) ;; What happens if you call ENSURE-DIRECTORIES-EXIST with a pathname that has ;; no name, type, or version component? ;; Case 1: the directory in question already exists. (deftest ensure-directories-exist.2 (let ((pathname (make-pathname :host (pathname-host *this-directory*) :device (pathname-device *this-directory*) :directory (pathname-directory *this-directory*) :name nil :type nil :version nil))) (multiple-value-bind (path created) (ensure-directories-exist pathname) (values #+(or allegro clisp) (eq path pathname) #-(or allegro clisp) (pathnames-equal-p (pathname path) (pathname pathname)) created))) t nil) ;; Case 2: the directory in question does not exist. (deftest ensure-directories-exist.3 (let* ((tmp (make-temporary-filename *this-directory*)) (directory-namestring (concatenate 'string (namestring tmp) "/")) (pathname (pathname directory-namestring))) (multiple-value-bind (path created) (ensure-directories-exist pathname) (values #+(or allegro clisp) (eq path pathname) #-(or allegro clisp) (pathnames-equal-p (pathname path) (pathname pathname)) created (not (null (probe-directory directory-namestring))) (when (probe-directory directory-namestring) (delete-directory directory-namestring)) ))) t t t t) abcl-src-1.9.0/test/lisp/abcl/jar-pathname.lisp0100644 0000000 0000000 00000036117 14202767264 020047 0ustar000000000 0000000 (in-package #:abcl/test/lisp) (defparameter *tmp-directory* nil) (defparameter *tmp-directory-whitespace* nil) (defparameter *tmp-jar-path* nil) (defparameter *tmp-jar-path-whitespace* nil) (defvar *foo.lisp* `((defun foo () (labels ((output () (format t "FOO here."))) (output))))) (defvar *bar.lisp* `((defvar *pathname* *load-pathname*) (defvar *truename* *load-truename*) (defun bar () (labels ((output () (format t "Some BAR~%*load-pathname* ~S~%*load-truename* ~S~%" *pathname* *truename*))) (output))) (defvar *bar* t) (defun baz () (format t "Some BAZ")))) (defvar *eek.lisp* `((defun eek () (format t "Another EEK.")) (defun ook () (let ((*load-verbose* t)) (load (merge-pathnames #p"bar" *load-truename*)))) (defun aak () (format t "*LOAD-TRUENAME* is '~A'" *load-truename*)))) (defun write-forms (forms path) (with-open-file (s path :direction :output :if-exists :supersede) (with-standard-io-syntax (dolist (form forms) (print form s))))) (defun create-jar () (let* ((temp-file (java:jcall "getAbsolutePath" (java:jstatic "createTempFile" "java.io.File" "jar" "tmp"))) (temp-dir (make-pathname :directory (append (pathname-directory (pathname temp-file)) '("jar-pathname-tests"))))) (jar-file-init temp-dir))) (defun jar-file-init (temp-dir) "Create the jar archives used for testing. Returns the two values of the pathnames of the created archives." (ensure-directories-exist temp-dir) (setf *tmp-directory* (truename temp-dir) *tmp-directory-whitespace* (merge-pathnames "a/directory with/s p a/" *tmp-directory*)) (format t "~&Using ~A to create files for testing jar-pathnames.~%" *tmp-directory*) (ensure-directories-exist *tmp-directory*) (let* ((*default-pathname-defaults* *tmp-directory*) (asdf::*verbose-out* *standard-output*)) (write-forms *foo.lisp* "foo.lisp") (compile-file "foo.lisp") (write-forms *foo.lisp* "foo bar.lisp") (compile-file "foo bar.lisp") (write-forms *bar.lisp* "bar.lisp") (compile-file "bar.lisp") (write-forms *eek.lisp* "eek.lisp") (compile-file "eek.lisp") (let* ((tmpdir (merge-pathnames "tmp/" *tmp-directory*)) (subdirs (mapcar (lambda (p) (merge-pathnames p tmpdir)) '("a/b/" "d/e+f/" "path/with a couple/spaces/in it/"))) (sub1 (first subdirs)) (sub2 (second subdirs)) (sub3 (third subdirs))) (when (probe-directory tmpdir) (delete-directory-and-files tmpdir)) (mapcar (lambda (p) (ensure-directories-exist p)) subdirs) (sys:unzip (merge-pathnames "foo.abcl") tmpdir) (sys:unzip (merge-pathnames "foo.abcl") sub1) (sys:unzip (merge-pathnames "foo.abcl") sub3) (sys:unzip (merge-pathnames "foo bar.abcl") sub3) (cl-fad-copy-file (merge-pathnames "bar.abcl") (merge-pathnames "bar.abcl" tmpdir)) (cl-fad-copy-file (merge-pathnames "bar.abcl") (merge-pathnames "bar.abcl" sub1)) (cl-fad-copy-file (merge-pathnames "foo bar.abcl") (merge-pathnames "foo bar.abcl" sub1)) (cl-fad-copy-file (merge-pathnames "bar.abcl") (merge-pathnames "bar.abcl" sub2)) (cl-fad-copy-file (merge-pathnames "bar.abcl") (merge-pathnames "bar.abcl" sub3)) (cl-fad-copy-file (merge-pathnames "foo bar.abcl") (merge-pathnames "foo bar.abcl" sub3)) (cl-fad-copy-file (merge-pathnames "eek.lisp") (merge-pathnames "eek.lisp" tmpdir)) (cl-fad-copy-file (merge-pathnames "eek.lisp") (merge-pathnames "eek.lisp" sub1)) (setf *tmp-jar-path* (sys:zip (merge-pathnames "baz.jar") (loop :for p :in (list tmpdir sub1 sub2 sub3) :appending (directory (merge-pathnames "*" p))) tmpdir)) (ensure-directories-exist *tmp-directory-whitespace*) (setf *tmp-jar-path-whitespace* (merge-pathnames "baz.jar" *tmp-directory-whitespace*)) (cl-fad-copy-file *tmp-jar-path* *tmp-jar-path-whitespace* :overwrite t))) (values *tmp-jar-path* *tmp-jar-path-whitespace*)) (defun clean-jar-tests () (when (probe-file *tmp-directory*) (delete-directory-and-files *tmp-directory*))) (defmacro with-jar-file-init (&rest body) `(progn (unless (and *tmp-jar-path* (probe-file *tmp-jar-path*)) (create-jar)) (let ((*default-pathname-defaults* *tmp-directory*)) ;; why do we need this? ,@body))) (defun load-from-jar (jar entry) (load (merge-jar-entry jar entry))) (defun merge-jar-entry (jar entry) (let ((jar-pathname (if (ext:pathname-jar-p jar) jar (make-pathname :device (list jar))))) (merge-pathnames entry jar-pathname))) (deftest jar-pathname.load.2 (with-jar-file-init (load-from-jar *tmp-jar-path* "bar")) t) (deftest jar-pathname.load.3 (with-jar-file-init (load-from-jar *tmp-jar-path* "bar.abcl")) t) (deftest jar-pathname.load.4 (with-jar-file-init (load-from-jar *tmp-jar-path* "eek")) t) (deftest jar-pathname.load.5 (with-jar-file-init (load-from-jar *tmp-jar-path* "eek.lisp")) t) (deftest jar-pathname.load.6 (signals-error (load-from-jar *tmp-jar-path* "this doesn't exist") 'file-error) t) (deftest jar-pathname.load.7 (with-jar-file-init (load-from-jar *tmp-jar-path* "a/b/bar")) t) (deftest jar-pathname.load.8 (with-jar-file-init (load-from-jar *tmp-jar-path* "a/b/bar.abcl")) t) (deftest jar-pathname.load.9 (with-jar-file-init (load-from-jar *tmp-jar-path* "a/b/eek")) t) (deftest jar-pathname.load.10 (with-jar-file-init (load-from-jar *tmp-jar-path* "a/b/eek.lisp")) t) (deftest jar-pathname.load.11 (with-jar-file-init (load-from-jar *tmp-jar-path* "d/e+f/bar.abcl")) t) #+(or) ;; URI encodings in namestring are not currently interpolated (deftest jar-pathname.load.12 (with-jar-file-init (load-from-jar *tmp-jar-path* "a/b/foo%20bar.abcl")) t) (deftest jar-pathname.load.13 (with-jar-file-init (load-from-jar *tmp-jar-path* "a/b/foo bar.abcl")) t) #+(or) ;; URI encodings in namestring are not currently interpolated (deftest jar-pathname.load.14 (with-jar-file-init (load-from-jar *tmp-jar-path-whitespace* "a/b/bar.abcl")) t) #+(or) ;; URI encodings in namestring are not currently interpolated (deftest jar-pathname.load.15 (load-from-jar *tmp-jar-path-whitespace* "a/b/foo bar.abcl") t) #+(or) ;; URI encodings in namestring are not currently interpolated (deftest jar-pathname.load.16 (load-from-jar *tmp-jar-path-whitespace* "a/b/foo%20bar.abcl") t) (defparameter *url-jar-pathname-base* #p"jar:https://abcl.org/releases/1.7.1/abcl-contrib.jar!/") (deftest jar-pathname.url.https.1 (equalp *url-jar-pathname-base* (probe-file *url-jar-pathname-base*)) t) (deftest jar-pathname.url.https.2 (namestring (merge-pathnames "**" "jar:https://abcl.org/releases/1.7.1/abcl-contrib.jar!/")) "jar:https://abcl.org/releases/1.7.1/abcl-contrib.jar!/**") (deftest jar-pathname.url.https.3 (not (null (probe-file #p"jar:https://abcl.org/releases/1.7.1/abcl-contrib.jar!/README.markdown"))) t) (deftest jar-pathname.url.https.4 (< 1 (length (directory #p"jar:https://abcl.org/releases/1.7.1/abcl-contrib.jar!/**/"))) t) (deftest jar-pathname.probe-file.1 (with-jar-file-init (let ((p (merge-jar-entry *tmp-jar-path* "eek.lisp"))) (not (null (probe-file p))))) t) (deftest jar-pathname.probe-file.2 (with-jar-file-init (let ((p (merge-jar-entry *tmp-jar-path* "a/b/bar.abcl"))) (not (null (probe-file p))))) t) (deftest jar-pathname.probe-file.3 (with-jar-file-init (let ((p (make-pathname :device (list (pathname *tmp-jar-path*) #p"a/b/bar.abcl") :directory '(:absolute) :name "bar_1" :type "cls"))) (not (null (probe-file p))))) t) (deftest jar-pathname.probe-file.4 (with-jar-file-init (let ((p (merge-jar-entry *tmp-jar-path* "a/b/bar.abcl"))) (not (null (probe-file p))))) t) (deftest jar-pathname.probe-file.5 (with-jar-file-init (let ((p (merge-jar-entry *tmp-jar-path* "a/b/" ))) (not (null (probe-file p))))) t) (deftest jar-pathname.probe-file.6 (with-jar-file-init (let ((p (merge-jar-entry *tmp-jar-path* "d/e+f/bar.abcl"))) (not (null (probe-file p))))) t) (deftest jar-pathname.probe-file.7 (with-jar-file-init (not (null (probe-file (merge-jar-entry *tmp-jar-path* "__loader__._"))))) t) #+(or) ;; abcl-1.8.0 behavior is not to merge absolute pathname with JAR-PATHNAME defaults (deftest jar-pathname.merge-pathnames.1 (merge-pathnames "/bar.abcl" #p"jar:file:/baz.jar!/foo") #p"jar:file:/baz.jar!/bar.abcl") (deftest jar-pathname.merge-pathnames.2 (namestring (merge-pathnames "bar.abcl" #p"jar:file:///baz.jar!/foo/baz")) "jar:file:///baz.jar!/foo/bar.abcl") (deftest jar-pathname.merge-pathnames.3 (namestring (merge-pathnames "jar:file:///baz.jar!/foo" "bar")) "jar:file:///baz.jar!/foo") (deftest jar-pathname.merge-pathnames.4 (namestring (merge-pathnames "jar:file:///baz.jar!/foo" "/a/b/c")) "jar:file:///baz.jar!/foo") ;;; Under win32, we get the device in the merged path #+windows (push 'jar-pathname.merge-pathnames.5 *expected-failures*) (deftest jar-pathname.merge-pathnames.5 (namestring (merge-pathnames "jar:file:///a/b/c/foo.jar!/bar/baz.lisp")) "jar:file:///a/b/c/foo.jar!/bar/baz.lisp") (deftest jar-pathname.truename.1 (signals-error (truename "jar:file:baz.jar!/foo") 'file-error) t) (deftest jar-pathname.1 (let* ((p #p"jar:file:/foo/baz.jar!/") (d (first (pathname-device p)))) (values (pathname-directory d) (pathname-name d) (pathname-type d))) (:absolute "foo") "baz" "jar") (deftest jar-pathname.2 (let* ((p #p"jar:file:baz.jar!/foo.abcl") (d (first (pathname-device p)))) (values (pathname-name d) (pathname-type d) (pathname-directory p) (pathname-name p) (pathname-type p))) "baz" "jar" (:absolute) "foo" "abcl") (deftest jar-pathname.3 (let* ((p #p"jar:jar:file:baz.jar!/foo.abcl!/") (d0 (first (pathname-device p))) (d1 (second (pathname-device p)))) (values (pathname-name d0) (pathname-type d0) (pathname-name d1) (pathname-type d1))) "baz" "jar" "foo" "abcl") (deftest jar-pathname.4 (let* ((p #p"jar:jar:file:a/baz.jar!/b/c/foo.abcl!/this/that/foo-20.cls") (d0 (first (pathname-device p))) (d1 (second (pathname-device p)))) (values (pathname-directory d0) (pathname-name d0) (pathname-type d0) (pathname-directory d1) (pathname-name d1) (pathname-type d1) (pathname-directory p) (pathname-name p) (pathname-type p))) (:relative "a") "baz" "jar" (:relative "b" "c") "foo" "abcl" (:absolute "this" "that") "foo-20" "cls") (deftest jar-pathname.5 (let* ((p #p"jar:jar:file:a/foo/baz.jar!/b/c/foo.abcl!/armed/bear/bar-1.cls") (d0 (first (pathname-device p))) (d1 (second (pathname-device p)))) (values (pathname-directory d0) (pathname-name d0) (pathname-type d0) (pathname-directory d1) (pathname-name d1) (pathname-type d1) (pathname-directory p) (pathname-name p) (pathname-type p))) (:relative "a" "foo" ) "baz" "jar" (:relative "b" "c") "foo" "abcl" (:absolute "armed" "bear") "bar-1" "cls") (deftest jar-pathname.6 (let* ((p #p"jar:http://example.org/abcl.jar!/org/armedbear/lisp/Version.class") (d (first (pathname-device p)))) (values (ext:pathname-url-p d) (namestring d) (pathname-directory p) (pathname-name p) (pathname-type p))) t "http://example.org/abcl.jar" (:absolute "org" "armedbear" "lisp") "Version" "class") (deftest jar-pathname.7 (let* ((p #p"jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls") (d (pathname-device p)) (d0 (first d)) (d1 (second d))) (values (ext:pathname-url-p d0) (namestring d0) (pathname-name d1) (pathname-type d1) (pathname-name p) (pathname-type p))) t "http://example.org/abcl.jar" "foo" "abcl" "foo-1" "cls") (deftest jar-pathname.8 (let* ((p #p"jar:file:/a/b/foo.jar!/") (d (first (pathname-device p)))) (values (pathname-directory d) (pathname-name d) (pathname-type d))) (:ABSOLUTE "a" "b") "foo" "jar") (deftest jar-pathname.9 (let* ((p #p"jar:file:a/b/foo.jar!/c/d/foo.lisp") (d (first (pathname-device p)))) (values (pathname-directory d) (pathname-name d) (pathname-type d) (pathname-directory p) (pathname-name p) (pathname-type p))) (:relative "a" "b") "foo" "jar" (:absolute "c" "d") "foo" "lisp") ;;; 'jar:file:' forms currently (abcl-1.8.0) can't be URI encoded, meaning whitespace is not allowed (deftest jar-pathname.10 (signals-error (let ((s "jar:file:/foo/bar/a space/that!/this")) (equal s (namestring (pathname s)))) 'error) t) #+(or) ;; URI escaping not returned (deftest jar-pathname.11 (let ((s (string-downcase "jar:file:///foo/bar/a%20space%3f/that!/this"))) (string= s (string-downcase (namestring (pathname s))))) t) ;;; We allow jar-pathname to be contructed without a device to allow ;;; MERGE-PATHNAMES to work, even though #p"file:" is illegal. #+(or) (deftest jar-pathname.12 (string= (namestring (first (pathname-device #p"jar:file:!/foo.bar"))) "") t) (deftest jar-pathname.match-p.1 (pathname-match-p "jar:file:/a/b/some.jar!/a/system/def.asd" "jar:file:/**/*.jar!/**/*.asd") t) (deftest jar-pathname.match-p.2 (pathname-match-p "/a/system/def.asd" "jar:file:/**/*.jar!/**/*.asd") nil) (deftest jar-pathname.match-p.3 (pathname-match-p "jar:file:/a/b/some.jar!/a/system/def.asd" "/**/*.asd") nil) (deftest jar-pathname.translate.1 (translate-pathname "jar:file:/a/b/c.jar!/d/e/f.lisp" "jar:file:/**/*.jar!/**/*.*" "/foo/**/*.*") #p"/foo/d/e/f.lisp") ;;; ticket #181 ;;; TODO Make reasons for failure more clear (deftest jar-pathname.truename.1 (let* ((abcl (slot-value (asdf:find-system 'abcl) 'asdf::absolute-pathname)) (jar-entry (pathname (format nil "jar:file:~A/dist/abcl-contrib.jar!/jss/jss.asd" (namestring abcl)))) (jar-entry-dir (make-pathname :defaults jar-entry :name nil :type nil)) (defaults *default-pathname-defaults*)) (let ((*default-pathname-defaults* jar-entry-dir)) (not (probe-file (merge-pathnames jar-entry))))) nil) abcl-src-1.9.0/test/lisp/abcl/java-tests.lisp0100644 0000000 0000000 00000030737 14202767264 017563 0ustar000000000 0000000 ;;; java-tests.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (in-package #:abcl.test.lisp) #+abcl (use-package '#:java) #+allegro (require :jlinker) #+allegro (use-package '#:javatools.jlinker) #+allegro (use-package '#:javatools.jlinker '#:cl-user) ;; For convenience only. #+(and allegro mswindows) (use-package '#:javatools.jlinker '#:cg-user) ;; For convenience only. #+allegro (load (merge-pathnames "jl-config.cl" *load-truename*)) #+allegro (or (jlinker-query) (jlinker-init)) #+abcl (defmacro with-registered-exception (exception condition &body body) `(unwind-protect (progn (register-java-exception ,exception ,condition) ,@body) (unregister-java-exception ,exception))) #+abcl (deftest java-object.1 (class-name (find-class 'java-object nil)) java-object) (deftest jclass.1 (jcall (jmethod "java.lang.Object" "toString") (jclass "java.lang.String")) "class java.lang.String") (deftest jclass.2 (equal (jcall (jmethod "java.lang.Object" "getClass") "foo") (jclass "java.lang.String")) #+abcl t #+allegro nil) (deftest jclass.3 (equal (jclass '|java.lang.String|) (jclass "java.lang.String")) t) (deftest jclass.4 (let ((class1 (jcall (jmethod "java.lang.Object" "getClass") "foo")) (class2 (jclass "java.lang.String"))) (jcall (jmethod "java.lang.Object" "equals" "java.lang.Object") class1 class2)) t) (deftest jclass.5 (jcall (jmethod "java.lang.Object" "toString") (jclass "int")) "int") (deftest jclass.6 (equal (jclass '|int|) (jclass "int")) t) ;; No such class. (deftest jclass.error.1 (signals-error (jclass "foo") 'error) t) ;; Silly argument. (deftest jclass.error.2 (signals-error (jclass 42) 'error) t) (deftest jclass-of.1 (jclass-of "foo") "java.lang.String" "java.lang.String") (deftest jclass-of.2 (jclass-of "foo" "java.lang.String") t "java.lang.String") (deftest jclass-of.3 (jclass-of "foo" "bar") nil "java.lang.String") (deftest jclass-of.4 (jclass-of 42) nil nil) (deftest jclass-of.5 (jclass-of 'foo) nil nil) (deftest jclass-name.1 (jclass-name "java.lang.String") "java.lang.String") (deftest jclass-name.2 (signals-error (jclass-name "foo") 'error) t) (deftest jclass-name.3 (signals-error (jclass-name 42) 'error) t) (deftest jclass-name.4 (jclass-name (jclass "java.lang.String")) "java.lang.String") (deftest jclass-name.5 (jclass-name (jclass "java.lang.String") "java.lang.String") t "java.lang.String") (deftest jclass-name.6 (jclass-name (jclass "java.lang.String") "java.lang.Object") nil "java.lang.String") (deftest jclass-name.7 (jclass-name (jclass "java.lang.String") "foo") nil "java.lang.String") (deftest jclass-name.8 (jclass-name (jclass "int")) "int") (deftest jconstructor.1 (jclass-of (jconstructor "java.lang.String" "java.lang.String")) "java.lang.reflect.Constructor" "java.lang.reflect.Constructor") (deftest jnew.1 (let ((constructor (jconstructor "java.lang.String" "java.lang.String"))) (jclass-of (jnew constructor "foo"))) "java.lang.String" "java.lang.String") (deftest jnew.2 (jclass-of (jnew (jconstructor "java.awt.Point"))) "java.awt.Point" "java.awt.Point") #-abcl (deftest jnew.3 (jclass-of (jnew "java.awt.Point") "java.awt.Point") t "java.awt.Point") (deftest jnew.error.1 (signals-error (jnew (jconstructor "java.lang.String" "java.lang.String") (make-immediate-object nil :ref)) #+abcl 'java-exception #+allegro 'jlinker-error) t) (deftest jcall.1 (let ((method (jmethod "java.lang.String" "length"))) (jcall method "test")) 4) (deftest jcall.2 (jcall "length" "test") 4) (deftest jcall.3 (let ((method (jmethod "java.lang.String" "regionMatches" 4))) (jcall method "test" 0 "this is a test" 10 4)) t) (deftest jcall.4 (let ((method (jmethod "java.lang.String" "regionMatches" 5))) (jcall method "test" (make-immediate-object nil :boolean) 0 "this is a test" 10 4)) t) (deftest jcall.5 (jcall "join" (jstatic "currentThread" "java.lang.Thread") 1 1) nil) (deftest jcall.6 (jcall "offsetByCodePoints" "foobar" 0 #\Nul) 0) (deftest jcall.7 (signals-error (jcall "offsetByCodePoints" "foobar" 0 nil) #+abcl 'java-exception #+allegro 'jlinker-error)) (deftest jfield.1 (type-of (jfield "java.lang.Integer" "TYPE")) #+abcl java-object #+allegro tran-struct) (deftest jmethod.1 (jcall (jmethod "java.lang.Object" "toString") (jmethod "java.lang.String" "substring" 1)) "public java.lang.String java.lang.String.substring(int)") (deftest jmethod.2 (jcall (jmethod "java.lang.Object" "toString") (jmethod "java.lang.String" "substring" 2)) "public java.lang.String java.lang.String.substring(int,int)") (deftest jmethod.3 (signals-error (jmethod "java.lang.String" "substring" 3) 'error) t) #+abcl (deftest jmethod-return-type.1 (jclass-name (jmethod-return-type (jmethod "java.lang.String" "length"))) "int") #+abcl (deftest jmethod-return-type.2 (jclass-name (jmethod-return-type (jmethod "java.lang.String" "substring" 1))) "java.lang.String") #+abcl (deftest jmethod-return-type.error.1 (signals-error (jmethod-return-type (jclass "java.lang.String")) 'error) t) #+abcl (deftest jmethod-return-type.error.2 (signals-error (jmethod-return-type 42) 'error) t) #+abcl (deftest define-condition.1 (progn (define-condition throwable (java-exception) ()) (let ((c (make-condition 'throwable))) (signals-error (simple-condition-format-control c) 'unbound-slot))) t) #+abcl (deftest define-condition.2 (progn (define-condition throwable (java-exception) ()) (let ((c (make-condition 'throwable))) (simple-condition-format-arguments c))) nil) #+abcl (deftest define-condition.3 (progn (define-condition throwable (java-exception) ()) (let ((c (make-condition 'throwable :format-control "The bear is armed."))) (simple-condition-format-control c))) "The bear is armed.") #+abcl (deftest define-condition.4 (progn (define-condition throwable (java-exception) ()) (let ((c (make-condition 'throwable :format-control "The bear is armed."))) (simple-condition-format-arguments c))) nil) #+abcl (deftest java-exception-cause.1 (progn (define-condition throwable (java-exception) ()) (signals-error (java-exception-cause (make-condition 'throwable)) 'unbound-slot)) t) #+abcl (deftest java-exception-cause.2 (progn (define-condition throwable (java-exception) ()) (java-exception-cause (make-condition 'throwable :cause 42))) 42) #+abcl (deftest unregister-java-exception.1 (progn (define-condition throwable (java-exception) ()) (register-java-exception "java.lang.Throwable" 'throwable) (unregister-java-exception "java.lang.Throwable")) t) #+abcl (deftest unregister-java-exception.2 (unregister-java-exception "java.lang.Throwable") nil) #+abcl (deftest register-java-exception.1 (progn (define-condition throwable (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (signals-error (jnew (jconstructor "java.lang.String" "java.lang.String") (make-immediate-object nil :ref)) 'throwable))) t) #+abcl (deftest register-java-exception.1a (progn (define-condition throwable (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (handler-case (jnew (jconstructor "java.lang.String" "java.lang.String") (make-immediate-object nil :ref)) (condition (c) (values (type-of c) (princ-to-string c)))))) throwable "java.lang.NullPointerException") #+abcl (deftest register-java-exception.2 (progn (define-condition throwable (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (signals-error (jnew (jconstructor "java.lang.String" "java.lang.String") 42) 'throwable))) t) #+abcl ;; Behavior is non-deterministic. (deftest register-java-exception.2a (progn (define-condition throwable (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (handler-case (jnew (jconstructor "java.lang.String" "java.lang.String") 42) (condition (c) (let* ((s (princ-to-string c))) ;; The actual string returned by Throwable.getMessage() ;; is either "argument type mismatch" or something ;; like "java.lang.ClassCastException@9d0366". (or (string= s "argument type mismatch") (and (> (length s) (length "java.lang.ClassCastException")) (string= (subseq s 0 (length "java.lang.ClassCastException")) "java.lang.ClassCastException")))))))) t) #+abcl (deftest register-java-exception.3 (progn (define-condition throwable (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (signals-error (jstatic (jmethod "java.lang.String" "valueOf" "int") "java.lang.String" "12") 'throwable))) t) #+abcl ;; Behavior is non-deterministic. (deftest register-java-exception.3a (progn (define-condition throwable (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (handler-case (jstatic (jmethod "java.lang.String" "valueOf" "int") "java.lang.String" "12") (condition (c) (let ((s (princ-to-string c))) (or (string= s "argument type mismatch") (string= s "java.lang.IllegalArgumentException"))))))) t) #+abcl (deftest register-java-exception.4 (progn (define-condition throwable (java-exception) ()) (define-condition illegal-argument-exception (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (with-registered-exception "java.lang.IllegalArgumentException" 'illegal-argument-exception (signals-error (jstatic (jmethod "java.lang.String" "valueOf" "int") "java.lang.String" "12") 'throwable)))) nil) #+abcl (deftest register-java-exception.5 (progn (define-condition throwable (java-exception) ()) (define-condition illegal-argument-exception (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (with-registered-exception "java.lang.IllegalArgumentException" 'illegal-argument-exception (signals-error (jstatic (jmethod "java.lang.String" "valueOf" "int") "java.lang.String" "12") 'illegal-argument-exception)))) t) #+abcl (deftest register-java-exception.6 (progn (define-condition foo () ()) (register-java-exception "java.lang.Throwable" 'foo)) nil) #+abcl (deftest register-java-exception.7 (progn (define-condition throwable (java-exception) ()) (register-java-exception "java.lang.Throwable" 'throwable)) t) #+abcl (deftest register-java-exception.8 (progn (define-condition throwable (java-exception) ()) (with-registered-exception "java.lang.Throwable" 'throwable (define-condition throwable () ()) (signals-error (jstatic (jmethod "java.lang.String" "valueOf" "int") "java.lang.String" "12") 'java-exception))) t) #+abcl (deftest register-java-exception.9 (progn (define-condition throwable (java-exception) ()) (define-condition illegal-argument-exception (throwable) ()) (with-registered-exception "java.lang.IllegalArgumentException" 'illegal-argument-exception (signals-error (jstatic (jmethod "java.lang.String" "valueOf" "int") "java.lang.String" "12") 'illegal-argument-exception))) t) ;;#+allegro ;;(jlinker-end) abcl-src-1.9.0/test/lisp/abcl/java.lisp0100644 0000000 0000000 00000001441 14202767264 016411 0ustar000000000 0000000 (in-package #:abcl.test.lisp) (deftest java.truth.1 (let ((java.lang.boolean.compare-to (java:jmethod "java.lang.Boolean" "compareTo" "java.lang.Boolean")) (java.lang.boolean.equals (java:jmethod "java.lang.Boolean" "equals" "java.lang.Object"))) (values (java:jcall java.lang.Boolean.compare-to java:+true+ t) (java:jcall java.lang.Boolean.compare-to java:+false+ nil) (java:jcall java.lang.Boolean.equals java:+true+ t) (java:jcall java.lang.Boolean.equals java:+false+ nil) (java:jcall java.lang.Boolean.compare-to java:+false+ t) (java:jcall java.lang.Boolean.compare-to java:+false+ t) (java:jcall java.lang.Boolean.equals java:+true+ nil) (java:jcall java.lang.Boolean.equals java:+false+ t))) 0 0 t t -1 -1 nil nil) abcl-src-1.9.0/test/lisp/abcl/jl-config.cl0100644 0000000 0000000 00000000463 14202767264 016772 0ustar000000000 0000000 ;; $Id: jl-config.cl,v 1.2 2005-10-25 14:52:53 piso Exp $ (in-package :cl-user) (setf javatools.jlinker:*jlinker-java-home* #+linux "/home/peter/blackdown/j2sdk1.4.2" #+mswindows "C:\\Program Files\\Java\\jdk1.5.0_05") (setf javatools.jlinker:*jlinker-run-java* 'javatools.jlinker::run-java) abcl-src-1.9.0/test/lisp/abcl/latin1-tests.lisp0100644 0000000 0000000 00000001670 14202767264 020024 0ustar000000000 0000000 ;;; latin1-tests.lisp ;;; ;;; Copyright (C) 2010 Ville Voutilainen ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (in-package #:abcl.test.lisp) (deftest normal-utf8.1 (load "utf8-umlauts.txt") t) (deftest latin1.1 (load "latin1-umlauts.txt") t) abcl-src-1.9.0/test/lisp/abcl/latin1-umlauts.txt0100644 0000000 0000000 00000000225 14202767264 020217 0ustar000000000 0000000 ;; some umlauts: ������������������������ (defun not-so-hard () (format t "just a debug print~%")) abcl-src-1.9.0/test/lisp/abcl/math-tests.lisp0100644 0000000 0000000 00000026260 14202767264 017567 0ustar000000000 0000000 ;;; math-tests.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; Some of these tests are based on tests in the CLISP test suite. (in-package #:abcl.test.lisp) #+(or abcl cmu sbcl) (defmacro set-floating-point-modes (&rest args) `(funcall #+abcl 'ext:set-floating-point-modes #+cmu 'ext:set-floating-point-modes #+sbcl 'sb-int:set-floating-point-modes ,@args)) #+(or abcl cmu sbcl) (defmacro get-floating-point-modes () #+abcl `(ext:get-floating-point-modes) #+cmu `(ext:get-floating-point-modes) #+sbcl `(sb-int:get-floating-point-modes)) #+(or abcl cmu sbcl) (defmacro restore-default-floating-point-modes () #+abcl `(ext:set-floating-point-modes :traps '(:overflow :underflow)) #+(or cmu sbcl) `(set-floating-point-modes :traps '(:overflow :invalid :divide-by-zero))) #+(or abcl cmu sbcl) (eval-when (:compile-toplevel :load-toplevel :execute) (restore-default-floating-point-modes)) ;; (ext:set-floating-point-modes :traps '(:overflow :underflow))) ;; (deftest most-negative-fixnum.1 (= (/ most-negative-fixnum -1) (- most-negative-fixnum)) t) (deftest most-negative-fixnum.2 (= (abs most-negative-fixnum) (- most-negative-fixnum)) t) #+(or abcl cmu sbcl) (deftest floating-point-modes.1 (unwind-protect (progn (set-floating-point-modes :traps nil) (getf (get-floating-point-modes) :traps)) (restore-default-floating-point-modes)) nil) #+(or abcl cmu sbcl) (deftest floating-point-modes.2 (unwind-protect (progn (set-floating-point-modes :traps '(:overflow)) (getf (get-floating-point-modes) :traps)) (restore-default-floating-point-modes)) (:overflow)) #+(or abcl cmu sbcl) (deftest floating-point-modes.3 (unwind-protect (progn (set-floating-point-modes :traps '(:underflow)) (getf (get-floating-point-modes) :traps)) (restore-default-floating-point-modes)) (:underflow)) #+(or abcl cmu sbcl) (deftest floating-point-modes.4 (unwind-protect (progn (set-floating-point-modes :traps '(:overflow :underflow)) (set-exclusive-or (getf (get-floating-point-modes) :traps) '(:overflow :underflow))) (restore-default-floating-point-modes)) nil) (deftest single-float-epsilon.1 single-float-epsilon #+lispworks 1.1102230246251568f-16 #-lispworks 5.960465f-8) (deftest single-float-negative-epsilon.1 single-float-negative-epsilon #+lispworks 5.551115123125784f-17 #-lispworks 2.9802326f-8) (deftest most-positive-single-float.1 most-positive-single-float #-lispworks 3.4028235e+38 #+lispworks 1.7976931348623157E308) (deftest most-positive-single-float.2 (log most-positive-single-float) #-lispworks 88.72284 #+lispworks 709.782712893384) (deftest least-positive-single-float.1 least-positive-single-float #-(or clisp lispworks) 1.4012985e-45 #+clisp 1.1754944E-38 #+lispworks 4.9406564584124646E-324) (deftest least-positive-single-float.2 (log least-positive-single-float) #-(or clisp lispworks) -103.27893 #+clisp -87.33655 #+lispworks -744.4400719213812) ;; SQRT (deftest sqrt.1 (sqrt 0) #+clisp 0 #-clisp 0.0) (deftest sqrt.2 (sqrt 1) #+clisp 1 #-clisp 1.0) (deftest sqrt.3 (sqrt 9) #+clisp 3 #-clisp 3.0) (deftest sqrt.4 (sqrt -9) #+clisp #c(0 3) #-clisp #c(0.0 3.0)) (deftest sqrt.5 (sqrt #c(-7 24)) #-(or clisp lispworks) #c(3.0 4.0) #+clisp #c(3 4) #+lispworks #c(3.0 3.999999999999999)) (deftest sqrt.6 (sqrt 1d0) 1.0d0) (deftest sqrt.7 (sqrt -1) #+(or clisp) #c(0 1) #+(or abcl allegro cmu lispworks sbcl) #c(0.0 1.0)) (deftest sqrt.8 (sqrt -1d0) #c(0 1.0d0)) (deftest sqrt.9 (sqrt #c(0.0 0.0)) #c(0.0 0.0)) (deftest sqrt.10 (sqrt #c(4.0 0.0)) #c(2.0 0.0)) (deftest sqrt.11 (sqrt #c(-4.0 0.0)) #c(0.0 2.0)) (deftest sqrt.12 (sqrt #c(-4.4855622e-7 0.0)) #-lispworks #c(0.0 6.697434e-4) #+lispworks #c(0.0 6.697433986236818e-4)) #+(or abcl cmu lispworks sbcl) (deftest sqrt.13 (float-sign (sqrt -0.0)) -1.0) #+(or abcl cmu lispworks sbcl) (deftest sqrt.14 (float-sign (sqrt -0.0d0)) -1.0d0) ;; EXP (deftest exp.1 (exp #c(0 0)) #+(or abcl allegro cmu lispworks sbcl) 1.0 #+clisp 1) (deftest exp.2 (exp #c(0 1)) #-lispworks #c(0.5403023 0.84147096) #+lispworks #c(0.5403023058681398 0.8414709848078965)) (deftest exp.3 (exp #c(1 1)) #+(or abcl cmu sbcl) #c(1.4686939 2.2873552) #+(or allegro clisp) #c(1.468694 2.2873552) #+lispworks #c(1.4686939399158851 2.2873552871788423)) (deftest exp.4 (exp #c(1 1d0)) #c(1.4686939399158851d0 2.2873552871788423d0)) (deftest exp.5 (exp #c(1d0 1d0)) #c(1.4686939399158851d0 2.2873552871788423d0)) (deftest exp.6 (exp #c(0 1d0)) #c(0.5403023058681398d0 0.8414709848078965d0)) (deftest exp.7 (exp 1) #-lispworks 2.7182817 #+lispworks 2.718281828459045) (deftest exp.8 (exp 1f0) #-lispworks 2.7182817 #+lispworks 2.718281828459045) (deftest exp.9 (exp 1d0) 2.718281828459045d0) ;; EXPT (deftest expt.1 (expt -5.0f0 2) 25.0) (deftest expt.2 (expt -5.0f0 1.9f0) #c(20.241808 -6.576964)) (deftest expt.3 (expt -5.0f0 2.0f0) #+(or abcl cmu sbcl) 25f0 #+allegro #c(25.0 -6.1230318e-15) #+clisp #c(25f0 0f0) #+lispworks #c(24.999999999999993 -6.123031769111885e-15)) (deftest expt.4 (expt -5.0f0 2.1f0) #c(27.928223 9.074421)) (deftest expt.5 (expt -5.0d0 1.9d0) #+(or abcl allegro) #c(20.24180952239008d0 -6.576962601219341d0) #+clisp #c(20.241809522390078d0 -6.576962601219342d0) #+(or cmu sbcl) #c(20.241809522390078d0 -6.57696260121934d0)) (deftest expt.6 (expt -5.0d0 2.0d0) #+(or abcl cmu sbcl) 25d0 #+allegro #c(24.999999999999996d0 -6.1230317691118855d-15) #+clisp #c(25d0 0d0)) (deftest expt.7 (expt -5.0d0 2.1d0) #+allegro #c(27.92822499968966d0 9.074430383223417d0) #+clisp #c(27.928224999689668d0 9.074430383223435d0) #-(or allegro clisp) #c(27.92822499968967d0 9.07443038322342d0)) (deftest expt.8 (expt -5 2) 25) (deftest expt.9 (eql (expt 5f0 3f0) (* 5.0 5.0 5.0)) t) (deftest expt.10 (expt 5f0 3f0) 125f0) (deftest expt.11 (expt 5d0 3d0) 125d0) (deftest expt.12 (expt 5 3) 125) (deftest expt.13 (expt #c(10 11) 1) #c(10 11)) (deftest expt.14 (expt 0 1/2) #+(or abcl allegro clisp lispworks) 0 #+(or cmu sbcl) 0.0) (deftest expt.15 (expt 1 1/2) #+(or clisp abcl) 1 #-(or clisp abcl) 1.0) (deftest expt.16 (expt 9 1/2) #+clisp 3 #-clisp 3.0) (deftest expt.17 (expt -9 1/2) #+clisp #c(0 3) #+(or allegro sbcl cmu) #c(1.8369095e-16 3.0) #+abcl #c(1.8369701e-16 3.0)) (deftest expt.18 (expt -8 1/3) #c(1.0 1.7320508)) (deftest expt.19 (expt #c(-7 24) 1/2) #+clisp #c(3 4) #-clisp #c(3.0 4.0)) (deftest expt.20 (expt 729 1/6) #+clisp 3 #-clisp 3.0) (deftest expt.21 (expt -3 -1) -1/3) (deftest expt.22 (expt #c(3 4) -1) #c(3/25 -4/25)) (deftest expt.23 (expt 14 #c(1.0 1.0)) #-(or clisp allegro) #c(-12.269101 6.743085) #+(or clisp allegro) #c(-12.269099 6.7430854)) (deftest expt.24 (expt 0.0 4) 0.0) (deftest expt.25 (expt #c(0 0.0) 4) #c(0.0 0.0)) (deftest expt.26 (expt #c(0 0.0) 4.0) #c(0.0 0.0)) (deftest log.1 (typep (log 17d0 10) 'double-float) t) (deftest log.2 (typep (log 17 10d0) 'double-float) t) (deftest log.3 (log 17 10) #+(and abcl java-1.4) 1.2304488 #+(and abcl (not java-1.4)) 1.230449 #+(or allegro clisp cmu sbcl) 1.230449 #+lispworks #.(log 17d0 10d0)) (deftest log.4 (log 17.0 10.0) #+(and abcl java-1.4) 1.2304488 #+(and abcl (not java-1.4)) 1.230449 #+(or cmu sbcl) 1.2304488 #+(or allegro clisp) 1.230449 #+lispworks #.(log 17d0 10d0)) (deftest log.5 (log 17d0 10) #+(and abcl java-1.4) 1.2304489042913307d0 #+(and abcl (not java-1.4)) #.(log 17d0 10d0) #+(or allegro clisp lispworks) #.(log 17d0 10d0) #-(or abcl allegro clisp lispworks) 1.2304489042913307d0) (deftest log.6 (log 17 10d0) #+(and abcl java-1.4) 1.2304489149763256d0 #+(and abcl (not java-1.4)) #.(log 17d0 10d0) #+(or allegro clisp lispworks) #.(log 17d0 10d0) #-(or abcl allegro clisp lispworks) 1.2304489149763256d0) (deftest log.7 (log 17d0 10d0) 1.2304489213782739d0) (deftest pi.1 pi #+clisp 3.1415926535897932385l0 #-clisp 3.141592653589793d0) (deftest tan.1 (tan 1) #+lispworks 1.5574077246549023 #-lispworks 1.5574077) (deftest tan.2 (tan (- (/ pi 2) 0.0001)) #+(or abcl allegro cmu sbcl) 10000.0002192818d0 #+clisp 10000.000219287924741l0 #+lispworks 9999.999966661644) (deftest tan.3 (tan (/ pi 2)) #+abcl 1.633123935319537d16 #+(or allegro cmu lispworks sbcl) 1.6331778728383844d16 #+clisp -3.9867976290042641156l19) (deftest tan.4 (tan (+ (/ pi 2) 0.0001)) #+(or abcl allegro cmu sbcl) -10000.000219294045d0 #+clisp -10000.000219287919724l0 #+lispworks -9999.999966673891d0) (deftest atanh.1 (atanh 2) #C(0.54930615 -1.5707964)) (deftest atanh.2 (atanh -2) #C(-0.54930615 1.5707964)) (deftest truncate.1 (truncate least-positive-single-float) 0 #.least-positive-single-float) (deftest truncate.2 (truncate least-positive-double-float) 0 #.least-positive-double-float) (deftest truncate.3 (signals-error (truncate least-positive-single-float 2) 'floating-point-underflow) t) (deftest truncate.4 (signals-error (truncate least-positive-double-float 2) 'floating-point-underflow) t) (deftest math.read-from-string.1 #+(or cmu sbcl) (unwind-protect (signals-error (read-from-string "1.0f-1000") 'reader-error) (progn (ignore-errors (set-floating-point-modes :traps '(:underflow))) (restore-default-floating-point-modes))) #-(or cmu sbcl) (signals-error (read-from-string "1.0f-1000") 'reader-error) t) ;;; Test for http://abcl.org/trac/ticket/142 (define-compiler-test math.logand.1 (lambda (switchp) (logand (if switchp nil 2) 1)) :args (nil) :results 0) (define-compiler-test math.max.1 (lambda (a b) (declare (type (integer * 6488318769) b)) (max 1 (the (integer * 5711538578) a) b 2 1351352470)) :args (5711538444 6488318765) :results 6488318765) abcl-src-1.9.0/test/lisp/abcl/metaclass.lisp0100644 0000000 0000000 00000006564 14202767264 017457 0ustar000000000 0000000 ;;; metaclass.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id: misc-tests.lisp 12402 2010-01-26 11:15:48Z mevenson $ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (in-package #:abcl.test.lisp) (defclass testclass1 () () (:metaclass standard-class)) (defclass testclass2 () () (:metaclass standard-class) (:documentation "test")) (defclass metaclass1 (standard-class) () (:metaclass standard-class)) (defclass metaclass2 (standard-class) () (:metaclass standard-class) (:documentation "test")) (defclass testclass3 () () (:metaclass metaclass1) (:documentation "test")) (deftest testclass1.instantiate (not (null (make-instance 'testclass1))) T) (deftest testclass2.instantiate (not (null (make-instance 'testclass2))) T) (deftest testclass3.instantiate (not (null (make-instance 'testclass3))) T) (deftest testclass1.class-of (eq (class-of (make-instance 'testclass1)) (find-class 'testclass1)) T) (deftest testclass1.metaclass-of (eq (class-of (class-of (make-instance 'testclass1))) (find-class 'standard-class)) T) (deftest testclass3.metaclass-of (eq (class-of (class-of (make-instance 'testclass3))) (find-class 'metaclass1)) T) (deftest standard-class.typep.class (typep (class-of (find-class 'standard-class)) 'class) T) (deftest standard-class.typep.standard-class (typep (class-of (class-of (find-class 'standard-class))) 'standard-class) T) (deftest metaclass1.typep.class (typep (find-class 'metaclass1) 'class) T) (deftest metaclass1.typep.standard-class (typep (find-class 'metaclass1) 'standard-class) T) (deftest testclass3.class-of.typep (typep (class-of (make-instance 'testclass3)) 'metaclass1) T) (deftest testclass3.metaclass-of.typep (typep (class-of (class-of (make-instance 'testclass3))) 'standard-class) T) (defclass testclass4 () ((a :initarg :a :initform 3) (b :initarg :b :initform 4)) (:metaclass metaclass1) (:documentation "test")) (deftest testclass4.init-noargs (slot-value (make-instance 'testclass4) 'a) 3) (deftest testclass4.initargs (slot-value (make-instance 'testclass4 :a 2) 'a) 2) (defclass testclass5 () ((a :initarg :a) (b :initarg :b :initform 1)) (:metaclass metaclass1) (:default-initargs :a 5)) (deftest testclass5.init-noargs (slot-value (make-instance 'testclass5) 'a) 5) (deftest testclass5.initargs (slot-value (make-instance 'testclass5 :a 3) 'a) 3) (defclass testclass6 () ((a :initarg :a :allocation :class)) (:metaclass metaclass1) (:documentation "test")) (deftest testclass6.1 (let ((instance1 (make-instance 'testclass6 :a 3)) (instance2 (make-instance 'testclass6 :a 4))) (slot-value instance1 'a)) 4) abcl-src-1.9.0/test/lisp/abcl/misc-tests.lisp0100644 0000000 0000000 00000010566 14202767264 017573 0ustar000000000 0000000 ;;; misc-tests.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (in-package #:abcl.test.lisp) (deftest misc.dotimes.1 (progn (fmakunbound 'misc.dotimes.1) (defun misc.dotimes.1 () (let ((sum 0)) (dotimes (i 10) (setq i 42) (incf sum i)) sum)) (misc.dotimes.1)) 420) (deftest dotimes.1.compiled (progn (fmakunbound 'dotimes.1.compiled) (defun dotimes.1.compiled () (let ((sum 0)) (dotimes (i 10) (setq i 42) (incf sum i)) sum)) (compile 'dotimes.1.compiled) (dotimes.1.compiled)) 420) (deftest misc.dotimes.2 (progn (fmakunbound 'misc.dotimes.2) (defun misc.dotimes.2 (count) (let ((sum 0)) (dotimes (i count) (setq i 42) (incf sum i)) sum)) (misc.dotimes.2 10)) 420) (deftest dotimes.2.compiled (progn (fmakunbound 'dotimes.2.compiled) (defun dotimes.2.compiled (count) (let ((sum 0)) (dotimes (i count) (setq i 42) (incf sum i)) sum)) (compile 'dotimes.2.compiled) (dotimes.2.compiled 10)) 420) (deftest funcall.1 (funcall (compile nil (lambda (a b c d e f) (list a b c d e f))) 1 2 3 4 5 6) (1 2 3 4 5 6)) (deftest funcall.2 (funcall (compile nil (lambda (a b c d e f g) (list a b c d e f g ))) 1 2 3 4 5 6 7) (1 2 3 4 5 6 7)) (deftest funcall.3 (funcall (compile nil (lambda (a b c d e f g h) (list a b c d e f g h))) 1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8)) (deftest funcall.4 (funcall (compile nil (lambda (a b c d e f g h i) (list a b c d e f g h i))) 1 2 3 4 5 6 7 8 9) (1 2 3 4 5 6 7 8 9)) (deftest funcall.5 (funcall (compile nil (lambda (a b c d e f g h i j) (list a b c d e f g h i j))) 1 2 3 4 5 6 7 8 9 10) (1 2 3 4 5 6 7 8 9 10)) (deftest copy-list.1 (eq (copy-list nil) nil) t) (deftest read-from-string.1 (read-from-string "(1 2 #-abcl #k(3 4))") (1 2) 20) (deftest read-from-string.2 (read-from-string "(1 2 #+nil #k(3 4))") (1 2) 19) ;; executed of the compiled expression below ;; resulted in an error on pre-0.23 versions (defstruct mystruct slot) (deftest ticket.107 (funcall (compile nil '(lambda () (let ((struct (make-mystruct)) x) (setf (values (mystruct-slot struct) x) (values 42 2)))))) 42 2) (deftest string-output-stream.seekable (string= "Goodbye, World! Something." (let ((stream (make-string-output-stream))) (write-string "Hello, World! Something." stream) (file-position stream :start) (write-string "Goodbye, World!" stream) (get-output-stream-string stream))) T) (deftest destructuring-bind.1 (signals-error (destructuring-bind (a b &rest c) '(1) (list a b)) 'program-error) T) (deftest destructuring-bind.2 (signals-error (destructuring-bind (a . b) '() (list a b)) 'program-error) T) (deftest destructuring-bind.3 (destructuring-bind (a . b) '(1) (list a b)) (1 NIL)) ;; this used to fail during byte code verification (deftest nth.inlined.1 (prog1 T (compile NIL (lambda (list) (nth (lambda ()) list)))) T) ;; these used to fail during byte code verification (deftest throw.representation.1 (prog1 T (compile NIL (lambda () (eql (the fixnum (throw 'foo 42)) 2)))) T) (deftest throw.representation.2 (prog1 T (compile NIL (lambda () (char-code (the character (throw 'foo 42)))))) T) (deftest throw.representation.3 (prog1 T (compile NIL (lambda () (if (the boolean (throw 'foo 42)) 1 2)))) T) (deftest package-error-package.1 (package-error-package (nth-value 1 (ignore-errors (intern "FOO" :bar)))) :bar) abcl-src-1.9.0/test/lisp/abcl/mop-tests-setup.lisp0100644 0000000 0000000 00000006452 14202767264 020570 0ustar000000000 0000000 ;;; mop-tests-setup.lisp ;;; ;;; Copyright (C) 2010 Matthias Hölzl ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; Definitions used by mop-tests.lisp. Split into a separate file to ;;; avoid problems with the functions not being available during test ;;; runs. (in-package #:abcl.test.lisp) (defun find-classes (&rest args) (mapcar #'find-class args)) (defgeneric mop-test.foo (x y) (:method (x y) (list :object x :object y)) (:method ((x fixnum) y) (list :fixnum x :object y)) (:method ((x fixnum) (y fixnum)) (list :fixnum x :fixnum y))) (defun find-foo (&rest specializers) (find-method #'mop-test.foo nil (mapcar #'find-class specializers))) (defgeneric mop-test.bar (x y) (:method (x y) (list :object x :object y)) (:method ((x fixnum) y) (list :fixnum x :object y)) (:method ((x fixnum) (y fixnum)) (list :fixnum x :fixnum y)) (:method ((x fixnum) (y string)) (list :fixnum x :fixnum y)) (:method ((x fixnum) (y (eql 123))) (list :fixnum x :123 y))) (defun find-bar (&rest specializers) (find-method #'mop-test.bar nil (mapcar #'find-class specializers))) (defgeneric mop-test.baz (x y) (:method (x y) (list :object x :object y)) (:method ((x fixnum) y) (list :fixnum x :object y)) (:method ((x fixnum) (y fixnum)) (list :fixnum x :fixnum y)) (:method ((x (eql 234)) (y fixnum)) (list :234 x :fixnum y))) (defun find-baz (&rest specializers) (find-method #'mop-test.baz nil (mapcar #'find-class specializers))) (defgeneric mop-test.quux (x y) (:method (x y) (list :object x :object y)) (:method ((x fixnum) y) (list :fixnum x :object y)) (:method ((x fixnum) (y fixnum)) (list :fixnum x :fixnum y)) (:method ((x (eql :foo)) (y fixnum)) (list :foo x :fixnum y))) (defun find-quux (&rest specializers) (find-method #'mop-test.quux nil (mapcar #'find-class specializers))) (defclass foo-meta-class (standard-class) ()) (defclass foo-direct-slot-definition (mop:standard-direct-slot-definition) ()) (defclass foo-effective-slot-definition (mop:standard-effective-slot-definition) ()) (defmethod mop:direct-slot-definition-class ((class foo-meta-class) &rest initargs) (find-class 'foo-direct-slot-definition)) (defmethod mop:effective-slot-definition ((class foo-meta-class) &rest initargs) (find-class 'foo-effective-slot-definition)) (defmethod mop:compute-effective-slot-definition ((class foo-meta-class) name direct-slots) (car direct-slots)) (defclass bar-class () ((x :initform T)) (:metaclass foo-meta-class)) (defmethod mop:slot-boundp-using-class ((class foo-meta-class) object slot) (error "foo")) abcl-src-1.9.0/test/lisp/abcl/mop-tests.lisp0100644 0000000 0000000 00000023206 14202767264 017426 0ustar000000000 0000000 ;;; mop-tests.lisp ;;; ;;; Copyright (C) 2010 Matthias Hölzl ;;; Copyright (C) 2010 Erik Huelsmann ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; CLOS related tests go clos-tssts.lisp (in-package #:abcl.test.lisp) (deftest compute-applicable-methods.foo.1 (equalp (mop:compute-applicable-methods #'mop-test.foo '(111 222)) (mop:compute-applicable-methods-using-classes #'mop-test.foo (find-classes 'fixnum 'fixnum))) t) (deftest compute-applicable-methods.foo.2 (equalp (mop:compute-applicable-methods #'mop-test.foo '(x y)) (mop:compute-applicable-methods-using-classes #'mop-test.foo (find-classes 'symbol 'symbol))) t) (deftest compute-applicable-methods.foo.3 (equalp (mop:compute-applicable-methods #'mop-test.foo '(111 y)) (mop:compute-applicable-methods-using-classes #'mop-test.foo (find-classes 'fixnum 'symbol))) t) (deftest compute-applicable-methods.foo.4 (equalp (mop:compute-applicable-methods #'mop-test.foo '(x 111)) (mop:compute-applicable-methods-using-classes #'mop-test.foo (find-classes 'symbol 'fixnum))) t) (deftest compute-applicable-methods.foo.5 (equalp (mop:compute-applicable-methods #'mop-test.foo '(111 "asdf")) (mop:compute-applicable-methods-using-classes #'mop-test.foo (find-classes 'fixnum 'simple-base-string))) t) (deftest compute-applicable-methods.foo.6 (equalp (mop:compute-applicable-methods #'mop-test.foo '(111 222)) (list (find-foo 'fixnum 'fixnum) (find-foo 'fixnum t) (find-foo t t))) t) (deftest compute-applicable-methods.foo.7 (equalp (mop:compute-applicable-methods #'mop-test.foo '(111 x)) (list (find-foo 'fixnum t) (find-foo t t))) t) (deftest compute-applicable-methods.foo.8 (equalp (mop:compute-applicable-methods #'mop-test.foo '(x 222)) (list (find-foo t t))) t) (deftest compute-applicable-methods.bar.1 (equalp (mop:compute-applicable-methods #'mop-test.bar '(111 222)) (mop:compute-applicable-methods-using-classes #'mop-test.bar (find-classes 'fixnum 'fixnum))) ;;; Bar with two fixnums might select EQL specializer for second ;;; argument. nil) (deftest compute-applicable-methods.bar.1a (equalp (mop:compute-applicable-methods #'mop-test.bar '(111 222)) (list (find-bar 'fixnum 'fixnum) (find-bar 'fixnum t) (find-bar t t))) t) (deftest compute-applicable-methods.bar.1b (equalp (mop:compute-applicable-methods #'mop-test.bar '(111 123)) (list (find-method #'mop-test.bar nil (list (find-class 'fixnum) '(eql 123))) (find-bar 'fixnum 'fixnum) (find-bar 'fixnum t) (find-bar t t))) t) (deftest compute-applicable-methods.bar.1c (mop:compute-applicable-methods-using-classes #'mop-test.bar (find-classes 'fixnum 'fixnum)) nil nil) (deftest compute-applicable-methods.bar.2 (equalp (mop:compute-applicable-methods #'mop-test.bar '(x y)) (mop:compute-applicable-methods-using-classes #'mop-test.bar (find-classes 'symbol 'symbol))) t) (deftest compute-applicable-methods.bar.2a (equalp (mop:compute-applicable-methods #'mop-test.bar '(x y)) (list (find-bar t t))) t) (deftest compute-applicable-methods.bar.3 (equalp (mop:compute-applicable-methods #'mop-test.bar '(111 y)) (mop:compute-applicable-methods-using-classes #'mop-test.bar (find-classes 'fixnum 'symbol))) t) (deftest compute-applicable-methods.bar.3a (equalp (mop:compute-applicable-methods #'mop-test.bar '(111 y)) (list (find-bar 'fixnum t) (find-bar t t))) t) (deftest compute-applicable-methods.bar.4 (equalp (mop:compute-applicable-methods #'mop-test.bar '(x 111)) (mop:compute-applicable-methods-using-classes #'mop-test.bar (find-classes 'symbol 'fixnum))) t) (deftest compute-applicable-methods.bar.4a (equalp (mop:compute-applicable-methods #'mop-test.bar '(x 111)) (list (find-bar t t))) t) (deftest compute-applicable-methods.bar.5 (equalp (mop:compute-applicable-methods #'mop-test.bar '(111 "asdf")) (mop:compute-applicable-methods-using-classes #'mop-test.bar (find-classes 'fixnum 'simple-base-string))) t) (deftest compute-applicable-methods.bar.5a (equalp (mop:compute-applicable-methods #'mop-test.bar '(111 "asdf")) (list (find-bar 'fixnum 'string) (find-bar 'fixnum t) (find-bar t t))) t) (deftest compute-applicable-methods.baz.1 (equalp (mop:compute-applicable-methods #'mop-test.baz '(111 222)) (mop:compute-applicable-methods-using-classes #'mop-test.baz (find-classes 'fixnum 'fixnum))) ;; Two fixnum arguments might select EQL specializer for first ;; argument. nil) (deftest compute-applicable-methods.baz.1a (equalp (mop:compute-applicable-methods #'mop-test.baz '(111 222)) (list (find-baz 'fixnum 'fixnum) (find-baz 'fixnum t) (find-baz t t))) t) (deftest compute-applicable-methods.baz.1b (equalp (mop:compute-applicable-methods #'mop-test.baz '(234 222)) (list (find-method #'mop-test.baz nil (list '(eql 234) (find-class 'fixnum))) (find-baz 'fixnum 'fixnum) (find-baz 'fixnum t) (find-baz t t))) t) (deftest compute-applicable-methods.baz.1c (mop:compute-applicable-methods-using-classes #'mop-test.baz (find-classes 'fixnum 'fixnum)) nil nil) (deftest compute-applicable-methods.baz.2 (equalp (mop:compute-applicable-methods #'mop-test.baz '(x y)) (mop:compute-applicable-methods-using-classes #'mop-test.baz (find-classes 'symbol 'symbol))) t) (deftest compute-applicable-methods.baz.3 (equalp (mop:compute-applicable-methods #'mop-test.baz '(111 y)) (mop:compute-applicable-methods-using-classes #'mop-test.baz (find-classes 'fixnum 'symbol))) t) (deftest compute-applicable-methods.baz.4 (equalp (mop:compute-applicable-methods #'mop-test.baz '(x 111)) (mop:compute-applicable-methods-using-classes #'mop-test.baz (find-classes 'symbol 'fixnum))) t) (deftest compute-applicable-methods.baz.5 (equalp (mop:compute-applicable-methods #'mop-test.baz '(111 "asdf")) (mop:compute-applicable-methods-using-classes #'mop-test.baz (find-classes 'fixnum 'simple-base-string))) t) (deftest compute-applicable-methods.quux.1 (equalp (mop:compute-applicable-methods #'mop-test.quux '(111 222)) (mop:compute-applicable-methods-using-classes #'mop-test.quux (find-classes 'fixnum 'fixnum))) t) (deftest compute-applicable-methods.quux.1a (equalp (mop:compute-applicable-methods #'mop-test.quux '(111 222)) (list (find-quux 'fixnum 'fixnum) (find-quux 'fixnum t) (find-quux t t))) t) (deftest compute-applicable-methods.quux.2 (equalp (mop:compute-applicable-methods #'mop-test.quux '(x y)) (mop:compute-applicable-methods-using-classes #'mop-test.quux (find-classes 'symbol 'symbol))) t) (deftest compute-applicable-methods.quux.2a (equalp (mop:compute-applicable-methods #'mop-test.quux '(x y)) (list (find-quux t t))) t) (deftest compute-applicable-methods.quux.3 (equalp (mop:compute-applicable-methods #'mop-test.quux '(111 y)) (mop:compute-applicable-methods-using-classes #'mop-test.quux (find-classes 'fixnum 'symbol))) t) (deftest compute-applicable-methods.quux.3a (equalp (mop:compute-applicable-methods #'mop-test.quux '(111 y)) (list (find-quux 'fixnum t) (find-quux t t))) t) (deftest compute-applicable-methods.quux.4 (equalp (mop:compute-applicable-methods #'mop-test.quux '(x 111)) (mop:compute-applicable-methods-using-classes #'mop-test.quux (find-classes 'symbol 'fixnum))) ;; Symbol/fixnum might trigger EQL spezializer nil) (deftest compute-applicable-methods.quux.4a (equalp (mop:compute-applicable-methods #'mop-test.quux '(x 111)) (list (find-quux t t))) t) (deftest compute-applicable-methods.quux.4b (equalp (mop:compute-applicable-methods #'mop-test.quux '(:foo 111)) (list (find-method #'mop-test.quux nil (list '(eql :foo) (find-class 'fixnum))) (find-quux t t))) t) (deftest compute-applicable-methods.quux.4c (mop:compute-applicable-methods-using-classes #'mop-test.quux (find-classes 'symbol 'fixnum)) nil nil) (deftest compute-applicable-methods.quux.5 (equalp (mop:compute-applicable-methods #'mop-test.quux '(111 "asdf")) (mop:compute-applicable-methods-using-classes #'mop-test.quux (find-classes 'fixnum 'simple-base-string))) t) ;; creating the instance should already call our meta class methods (deftest shared-initialize.1 (block NIL (handler-case (make-instance 'bar-class) (error (error) (return (equal (princ-to-string error) "foo"))))) t) ;; ensure-generic-function shouldn't kill existing definition (deftest ensure-generic-function.1 (progn (ensure-generic-function 'mop-test.foo) (not (null (mop:generic-function-argument-precedence-order #'mop-test.foo)))) t) abcl-src-1.9.0/test/lisp/abcl/package-local-nicknames-tests.lisp0100644 0000000 0000000 00000015537 14202767264 023274 0ustar000000000 0000000 ;;; package-local-nicknames-tests.lisp ;;; ;;; Copyright (C) 2013 Nikodemus Siivola, Rudolf Schlatte ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; Most of these tests are adapted from the SBCL test suite. ;;;; FIXME: re-running these tests in the same process fails the second time due to interactions ;;; with the problems with DEFPACKAGE "only being run once" (in-package #:abcl.test.lisp) (defmacro with-tmp-packages (bindings &body body) `(let ,(mapcar #'car bindings) (unwind-protect (progn (setf ,@(apply #'append bindings)) ,@body) ,@(mapcar (lambda (p) `(when ,p (delete-package ,p))) (mapcar #'car bindings))))) (defpackage :package-local-nicknames-test-1 (:local-nicknames (:l :cl) (:e :ext))) (defpackage :package-local-nicknames-test-2 (:export "CONS")) (deftest pln-introspect (let ((alist (ext:package-local-nicknames :package-local-nicknames-test-1))) (values (equal (cons "L" (find-package "CL")) (assoc "L" alist :test 'string=)) (equal (cons "E" (find-package "EXT")) (assoc "E" alist :test 'string=)) (eql 2 (length alist)))) t t t) (deftest pln-usage (let ((*package* (find-package :package-local-nicknames-test-1))) (let ((cons0 (read-from-string "L:CONS")) (exit0 (read-from-string "E:EXIT")) (cons1 (find-symbol "CONS" :l)) (exit1 (find-symbol "EXIT" :e)) (cl (find-package :l)) (ext (find-package :e))) (values (eq 'cons cons0) (eq 'cons cons1) (equal "L:CONS" (prin1-to-string cons0)) (eq 'ext:exit exit0) (eq 'ext:exit exit1) (equal "E:EXIT" (prin1-to-string exit0)) (eq cl (find-package :common-lisp)) (eq ext (find-package :ext))))) T T T T T T T T) (deftest pln-add-nickname-twice (handler-case (ext:add-package-local-nickname :l :package-local-nicknames-test-2 :package-local-nicknames-test-1) (error () :oopsie)) :oopsie) (deftest pln-add-same-nickname (progn (ext:add-package-local-nickname :l :cl :package-local-nicknames-test-1) :okay) :okay) (deftest pln-remove-local-nickname (progn (assert (ext:remove-package-local-nickname :l :package-local-nicknames-test-1)) (assert (not (ext:remove-package-local-nickname :l :package-local-nicknames-test-1))) (let ((*package* (find-package :package-local-nicknames-test-1))) (let ((exit0 (read-from-string "E:EXIT")) (exit1 (find-symbol "EXIT" :e)) (e (find-package :e))) (assert (eq 'ext:exit exit0)) (assert (eq 'ext:exit exit1)) (assert (equal "E:EXIT" (prin1-to-string exit0))) (assert (eq e (find-package :ext))) (assert (not (find-package :l))))) (assert (eq (find-package :package-local-nicknames-test-1) (ext:add-package-local-nickname :l :package-local-nicknames-test-2 :package-local-nicknames-test-1))) (let ((*package* (find-package :package-local-nicknames-test-1))) (let ((cons0 (read-from-string "L:CONS")) (exit0 (read-from-string "E:EXIT")) (cons1 (find-symbol "CONS" :l)) (exit1 (find-symbol "EXIT" :e)) (cl (find-package :l)) (e (find-package :e))) (assert (eq cons0 cons1)) (assert (not (eq 'cons cons0))) (assert (eq (find-symbol "CONS" :package-local-nicknames-test-2) cons0)) (assert (equal "L:CONS" (prin1-to-string cons0))) (assert (eq 'ext:exit exit0)) (assert (eq 'ext:exit exit1)) (assert (equal "E:EXIT" (prin1-to-string exit0))) (assert (eq cl (find-package :package-local-nicknames-test-2))) (assert (eq e (find-package :ext))))) :success) :success) (deftest pln-delete-locally-nicknaming-package (with-tmp-packages ((p1 (make-package "LOCALLY-NICKNAMES-OTHERS")) (p2 (make-package "LOCALLY-NICKNAMED-BY-OTHERS"))) (ext:add-package-local-nickname :foo p2 p1) (assert (equal (list p1) (ext:package-locally-nicknamed-by-list p2))) (delete-package p1) (assert (null (ext:package-locally-nicknamed-by-list p2))) :success) :success) (deftest pln-delete-locally-nicknamed-package (with-tmp-packages ((p1 (make-package "LOCALLY-NICKNAMES-OTHERS")) (p2 (make-package "LOCALLY-NICKNAMED-BY-OTHERS"))) (ext:add-package-local-nickname :foo p2 p1) (assert (ext:package-local-nicknames p1)) (delete-package p2) (assert (null (ext:package-local-nicknames p1))) :success) :success) (deftest pln-own-name-as-local-nickname (with-tmp-packages ((p1 (make-package "OWN-NAME-AS-NICKNAME1")) (p2 (make-package "OWN-NAME-AS-NICKNAME2"))) (assert (eq :oops (handler-case (ext:add-package-local-nickname :own-name-as-nickname1 p2 p1) (error () :oops)))) (handler-bind ((error #'continue)) (ext:add-package-local-nickname :own-name-as-nickname1 p2 p1)) (assert (eq (intern "FOO" p2) (let ((*package* p1)) (intern "FOO" :own-name-as-nickname1)))) :success) :success) (deftest pln-own-nickname-as-local-nickname (with-tmp-packages ((p1 (make-package "OWN-NICKNAME-AS-NICKNAME1" :nicknames '("OWN-NICKNAME"))) (p2 (make-package "OWN-NICKNAME-AS-NICKNAME2"))) (assert (eq :oops (handler-case (ext:add-package-local-nickname :own-nickname p2 p1) (error () :oops)))) (handler-bind ((error #'continue)) (ext:add-package-local-nickname :own-nickname p2 p1)) (assert (eq (intern "FOO" p2) (let ((*package* p1)) (intern "FOO" :own-nickname)))) :success) :success) abcl-src-1.9.0/test/lisp/abcl/package.lisp0100644 0000000 0000000 00000003357 14202767264 017073 0ustar000000000 0000000 (defpackage #:abcl/test/lisp (:use #:cl #:abcl-rt) (:nicknames #:abcl-test-lisp #:abcl-test #:abcl.test.lisp) (:export #:run #:do-test #:do-tests #:do-tests-matching ;; previously in file-system-tests.lisp #:pathnames-equal-p #:run-shell-command #:copy-file #:make-symbolic-link #:touch #:make-temporary-directory #:delete-directory-and-files ;;; Deprecated #:do-matching #:run-matching)) (in-package #:abcl.test.lisp) (defparameter *abcl-test-directory* (if (find :asdf2 *features*) (asdf:system-relative-pathname :abcl "test/lisp/abcl/") (make-pathname :host (pathname-host *load-truename*) :device (pathname-device *load-truename*) :directory (pathname-directory *load-truename*)))) (defun run () "Run the Lisp test suite for ABCL." (let ((*default-pathname-defaults* *abcl-test-directory*)) (do-tests))) ;;; XXX move this into test-utilities.lisp? (defvar *last-run-matching* "url-pathname") (defun do-tests-matching (&optional (match *last-run-matching*)) "Run all tests in suite whose symbol contains MATCH in a case-insensitive manner." (setf *last-run-matching* match) (let* ((matching (string-upcase match)) (count 0)) (mapcar (lambda (entry) (if (search matching (symbol-name (abcl-rt::name entry))) (setf (abcl-rt::pend entry) t count (1+ count)) (setf (abcl-rt::pend entry) nil))) (rest abcl-rt::*entries*)) (format t "Performing ~A tests matching '~A'.~%" count matching) (abcl-rt::do-entries t))) ;;; Deprecated (setf (symbol-function 'run-matching) #'do-tests-matching) (setf (symbol-function 'do-matching) #'do-tests-matching) abcl-src-1.9.0/test/lisp/abcl/pathname-tests.lisp0100644 0000000 0000000 00000152426 14202767264 020437 0ustar000000000 0000000 ;;; pathname-tests.lisp ;;; ;;; Copyright (C) 2005 Peter Graves ;;; $Id$ ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (in-package #:abcl.test.lisp) (defun check-physical-pathname (pathname expected-directory expected-name expected-type) (let* ((directory (pathname-directory pathname)) (name (pathname-name pathname)) (type (pathname-type pathname)) (ok t)) (unless (and (pathnamep pathname) (not (typep pathname 'logical-pathname))) (setf ok nil)) (unless (and (equal directory expected-directory) (equal name expected-name) (equal type expected-type)) (setf ok nil)) ok)) (defun check-windows-pathname (pathname expected-host expected-device expected-directory expected-name expected-type) (let* ((host (pathname-host pathname)) (device (pathname-device pathname)) (directory (pathname-directory pathname)) (name (pathname-name pathname)) (type (pathname-type pathname)) (ok t)) (unless (and (pathnamep pathname) (not (typep pathname 'logical-pathname))) (setf ok nil)) (unless (and (equal host expected-host) (equal device expected-device) (equal directory expected-directory) (equal name expected-name) (equal type expected-type)) (setf ok nil)) ok)) (defun check-logical-pathname (pathname expected-host expected-directory expected-name expected-type expected-version) (let* ((host (pathname-host pathname)) (directory (pathname-directory pathname)) (name (pathname-name pathname)) (type (pathname-type pathname)) (version (pathname-version pathname)) ;; Allegro's logical pathnames don't canonicalize their string ;; components to upper case. (test #-allegro 'equal #+allegro 'equalp) (ok t)) (unless (typep pathname 'logical-pathname) (setf ok nil)) ;; "The device component of a logical pathname is always :UNSPECIFIC..." 19.3.2.1 #-allegro ;; Except on Allegro, where it's NIL. (unless (eq (pathname-device pathname) :unspecific) (setf ok nil)) (unless (and (funcall test (if (stringp host) host (host-namestring pathname)) expected-host) (funcall test directory expected-directory) (funcall test name expected-name) (funcall test type expected-type) (eql version expected-version)) (setf ok nil)) ok)) (defun check-merge-pathnames (pathname default-pathname expected-result) (let* ((result (merge-pathnames pathname default-pathname)) (test #-allegro 'equal #+allegro (if (typep result 'logical-pathname) 'equalp 'equal))) (and (funcall test (pathname-host result) (pathname-host expected-result)) (funcall test (pathname-directory result) (pathname-directory expected-result)) (funcall test (pathname-name result) (pathname-name expected-result)) (funcall test (pathname-type result) (pathname-type expected-result))))) (defun check-translate-pathname (args expected) (declare (optimize safety)) (declare (type list args)) (declare (type string expected)) (let ((result (namestring (apply 'translate-pathname args)))) (equal result ;;#-windows expected ;;#+windows (substitute #\\ #\/ expected) ))) (defmacro check-readable (pathname) `(equal ,pathname (read-from-string (write-to-string ,pathname :readably t)))) (defun check-readable-or-signals-error (pathname) (handler-case (equal pathname (read-from-string (write-to-string pathname :readably t))) (print-not-readable () t))) (defmacro check-namestring (pathname namestring) `(string= (namestring ,pathname) ;;#+windows (substitute #\\ #\/ ,namestring) ;;#-windows ,namestring)) ;; Define a logical host. (eval-when (:compile-toplevel :load-toplevel :execute) (setf (logical-pathname-translations "effluvia") '(("**;*.*.*" "/usr/local/**/*.*")))) (deftest equal.1 (equal (make-pathname :name "foo" :type "bar") (make-pathname :name "foo" :type "bar")) t) (deftest equal.2 (equal (make-pathname :name "foo" :type "bar" :version nil) (make-pathname :name "foo" :type "bar" :version :newest)) #+(or clisp lispworks) nil #-(or clisp lispworks) t) (deftest sxhash.1 (let* ((p (make-pathname :name "foo" :type "bar" :version nil)) (s (sxhash p))) (values (typep s 'fixnum) (>= s 0))) t t) ;; "(equal x y) implies (= (sxhash x) (sxhash y))" (deftest sxhash.2 (let ((p1 (make-pathname :name "foo" :type "bar" :version nil)) (p2 (make-pathname :name "foo" :type "bar" :version :newest))) (if (equal p1 p2) (= (sxhash p1) (sxhash p2)) t)) t) ;; It's suboptimal if all pathnames return the same SXHASH, but that happens ;; with SBCL. (deftest sxhash.3 (= (sxhash #p"/usr/local/bin/sbcl") (sxhash #p"") (sxhash #p"foo.bar")) #+sbcl t #-sbcl nil) ;; "Parsing a null string always succeeds, producing a pathname with all ;; components (except the host) equal to nil." (deftest physical.1 (check-physical-pathname #p"" nil nil nil) t) (deftest physical.2 (check-physical-pathname #p"/" '(:absolute) nil nil) t) (deftest physical.3 (check-physical-pathname #p"/foo" '(:absolute) "foo" nil) t) (deftest physical.4 #-lispworks (check-physical-pathname #p"/foo." '(:absolute) "foo" "") #+lispworks (check-physical-pathname #p"/foo." '(:absolute) "foo." nil) t) (deftest physical.5 (check-physical-pathname #p"/foo.bar" '(:absolute) "foo" "bar") t) (deftest physical.6 #-lispworks (check-physical-pathname #p"/foo.bar." '(:absolute) "foo.bar" "") #+lispworks (check-physical-pathname #p"/foo.bar." '(:absolute) "foo.bar." nil) t) (deftest physical.7 (check-physical-pathname #p"/foo.bar.baz" '(:absolute) "foo.bar" "baz") t) (deftest physical.8 (check-physical-pathname #p"/foo/bar" '(:absolute "foo") "bar" nil) t) (deftest physical.9 (check-physical-pathname #p"/foo..bar" '(:absolute) "foo." "bar") t) (deftest physical.10 (check-physical-pathname #p"foo.bar" nil "foo" "bar") t) (deftest physical.11 (check-physical-pathname #p"foo.bar.baz" nil "foo.bar" "baz") t) (deftest physical.12 (check-physical-pathname #p"foo/" '(:relative "foo") nil nil) t) (deftest physical.13 (check-physical-pathname #p"foo/bar" '(:relative "foo") "bar" nil) t) (deftest physical.14 (check-physical-pathname #p"foo/bar/baz" '(:relative "foo" "bar") "baz" nil) t) (deftest physical.15 (check-physical-pathname #p"foo/bar/" '(:relative "foo" "bar") nil nil) t) #+allegro (deftest physical.16 ;; This reduction is wrong. (check-physical-pathname #p"foo/bar/.." '(:relative "foo") nil nil) t) #+allegro (deftest physical.17 (check-physical-pathname #p"/foo/../" '(:absolute) nil nil) t) (deftest physical.18 #-lispworks (check-physical-pathname #p".lisprc" nil ".lisprc" nil) #+lispworks (check-physical-pathname #p".lisprc" nil "" "lisprc") t) (deftest physical.19 (check-physical-pathname #p"x.lisprc" nil "x" "lisprc") t) (deftest physical.20 #-allegro (check-physical-pathname (make-pathname :name ".") nil "." nil) #+allegro (check-physical-pathname (make-pathname :name ".") '(:relative) nil nil) t) (deftest physical.21 #-cmu (check-readable (make-pathname :name ".")) #+cmu (check-readable-or-signals-error (make-pathname :name ".")) t) #+(or cmu lispworks (and allegro windows)) (pushnew 'physical.21 *expected-failures*) ;; #p"." (deftest physical.22 #+(or allegro abcl cmu) (check-physical-pathname #p"." '(:relative) nil nil) #-(or allegro abcl cmu) ;; No trailing separator character means it's a file. (check-physical-pathname #p"." nil "." nil) t) #+lispworks (pushnew 'physical.22 *expected-failures*) (deftest namestring.1 (check-namestring #p"." #+(or abcl allegro cmu) "./" #-(or abcl allegro cmu) ".") t) #+lispworks (pushnew 'namestring.1 *expected-failures*) (deftest physical.23 (equal #p"." #p"") nil) #+lispworks (pushnew 'physical.23 *expected-failures*) ;; #p"./" ;; Trailing separator character means it's a directory. (deftest physical.24 (let ((pathname #-windows #p"./" #+windows #p".\\")) #-(or sbcl) (check-physical-pathname pathname '(:relative) nil nil) #+(or sbcl) ;; Is this more exact? (check-physical-pathname pathname '(:relative ".") nil nil)) t) #+(or lispworks (and allegro windows)) (pushnew 'physical.24 *expected-failures*) (deftest namestring.2 (check-namestring #-windows #p"./" #+windows #p".\\" "./") t) #+lispworks (pushnew 'namestring.2 *expected-failures*) (deftest directory-namestring.1 (equal (directory-namestring #p"./") "./") t) #+lispworks (pushnew 'directory-namestring.1 *expected-failures*) (deftest physical.25 (equal #-windows #p"./" #+windows #p".\\" #p"") nil) #+(or lispworks (and allegro windows)) (pushnew 'physical.25 *expected-failures*) (deftest physical.26 #-allegro (check-physical-pathname (make-pathname :name "..") nil ".." nil) #+allegro (check-physical-pathname (make-pathname :name "..") '(:relative :back) nil nil) t) #-(or sbcl) (deftest physical.27 #-cmu (check-readable (make-pathname :name "..")) #+cmu (check-readable-or-signals-error (make-pathname :name "..")) t) #+(or clisp cmu lispworks) (pushnew 'physical.27 *expected-failures*) ;; #p".." (deftest physical.28 #+(or allegro (and lispworks windows)) (check-physical-pathname #p".." '(:relative :back) nil nil) #+(or abcl cmu (and lispworks unix)) (check-physical-pathname #p".." '(:relative :up) nil nil) ;; Other implementations think it's a file. #+(or) ;; If it's a file, to a human its name would be "..". No implementation gets ;; this right. (check-physical-pathname #p".." nil ".." nil) #+(or sbcl clisp) ;; These implementations parse ".." as the name "." followed by another dot and ;; the type string "", which no human would do. (check-physical-pathname #p".." nil "." "") t) #+cmu (pushnew 'physical.28 *expected-failures*) (deftest namestring.3 (check-namestring #p".." #+(or abcl allegro cmu lispworks) "../" #-(or abcl allegro cmu lispworks) "..") t) ;; #p"../" (deftest physical.29 (let ((pathname #-windows #p"../" #+windows #p"..\\")) #+(or allegro (and lispworks windows)) (check-physical-pathname pathname '(:relative :back) nil nil) #+(or abcl sbcl cmu clisp (and lispworks unix)) (check-physical-pathname pathname '(:relative :up) nil nil)) t) (deftest namestring.4 (check-namestring #-windows #p"../" #+windows #p"..\\" "../") t) (deftest directory-namestring.2 (equal (directory-namestring #-windows #p"../" #+windows #p"..\\") "../") t) #-sbcl (deftest physical.30 #-(or allegro cmu) (string= (namestring (make-pathname :name "..")) "..") #+allegro (string= (namestring (make-pathname :name "..")) #-windows "../" #+windows "..\\") #+cmu (signals-error (make-pathname :name "..") 'warning) t) (deftest physical.31 (string= (namestring (make-pathname :directory '(:relative :up))) "../") t) #+windows (deftest windows.1 (equal #p"/foo/bar/baz" #p"\\foo\\bar\\baz") t) #+windows (deftest windows.2 (let ((pathname #p"foo.bar")) (check-windows-pathname pathname nil nil nil "foo" "bar")) t) #+windows (deftest windows.3 (let ((pathname #p"\\foo.bar")) (check-windows-pathname pathname nil nil '(:absolute) "foo" "bar")) t) #+windows (deftest windows.4 (let ((pathname #p"c:\\foo.bar")) #+(or abcl allegro) (check-windows-pathname pathname nil "c" '(:absolute) "foo" "bar") #+clisp (check-windows-pathname pathname nil "C" '(:absolute) "foo" "bar") #+lispworks (check-windows-pathname pathname "c" nil '(:absolute) "foo" "bar")) t) #+windows (deftest windows.5 (equal #p"c:\\foo.bar" #p"C:\\FOO.BAR") t) #+windows (deftest pathname.windows.6 (equal (pathname-device #p"z:/foo/bar") "z") t) #+windows (deftest pathname.windows.7 (equal (pathname-device #p"file:z:/foo/bar") "z") t) #+windows (deftest pathname.windows.8 (equal (pathname-device #p"zoo:/foo/bar") nil) t) (deftest wild.1 (check-physical-pathname #p"foo.*" nil "foo" :wild) t) (deftest wild.2 (check-physical-pathname #p"*.*" nil :wild :wild) t) (deftest wild.3 #-(or cmu sbcl) (check-physical-pathname #p"abc*" nil "abc*" nil) #+(or cmu sbcl) (wild-pathname-p #p"abc*") t) (deftest wild.4 #-(or cmu sbcl) (check-physical-pathname #p"abc?" nil "abc?" nil) #+(or cmu sbcl) (wild-pathname-p #p"abc?") t) (deftest wild.5 #-(or cmu sbcl) (check-physical-pathname #p"abc[d-h]" nil "abc[d-h]" nil) #+(or cmu sbcl) (wild-pathname-p #p"abc[d-h]") t) ;; Lots of dots. #+(or allegro abcl cmu) (deftest lots-of-dots.1 (check-physical-pathname #p"..." nil "..." nil) t) #+cmu (pushnew 'lots-of-dots.1 *expected-failures*) #+(or allegro abcl cmu) (deftest lots-of-dots.2 (check-physical-pathname #p"......" nil "......" nil) t) #+cmu (pushnew 'lots-of-dots.2 *expected-failures*) ;; Silly names. #-(or allegro sbcl) (deftest silly.1 #+(or abcl clisp) (signals-error (make-pathname :name "abc/def") 'error) #-(or abcl clisp) (check-readable (make-pathname :name "abc/def")) t) #+(or cmu lispworks) (pushnew 'silly.1 *expected-failures*) (deftest silly.2 (signals-error (make-pathname :name "abc/def") #-cmu 'error #+cmu 'warning) t) (deftest silly.3 (check-readable-or-signals-error (make-pathname :name ".foo")) t) (deftest silly.4 (check-readable-or-signals-error (make-pathname :type ".foo")) t) (deftest silly.5 (check-readable-or-signals-error (make-pathname :name "abc.def")) t) (deftest silly.6 (check-readable-or-signals-error (make-pathname :type "abc.def")) t) ;; LOGICAL-PATHNAME-TRANSLATIONS #-allegro (deftest logical-pathname-translations.1 #+(or sbcl cmu lispworks) (equal (logical-pathname-translations "effluvia") '(("**;*.*.*" "/usr/local/**/*.*"))) #+clisp (equal (logical-pathname-translations "effluvia") '((#p"EFFLUVIA:**;*.*.*" "/usr/local/**/*.*"))) #+abcl (equal (logical-pathname-translations "effluvia") '((#p"EFFLUVIA:**;*.*.*" #p"/usr/local/**/*.*"))) t) ;; "The null string, "", is not a valid value for any component of a logical ;; pathname." 19.3.2.2 (deftest logical-pathname.1 #-clisp (signals-error (logical-pathname ":") 'error) #+clisp (check-logical-pathname (logical-pathname ":") "" '(:absolute) nil nil nil) t) ;; Parse error. (deftest logical-pathname.2 (signals-error (logical-pathname "effluvia::foo.bar") #-(or allegro clisp) 'parse-error #+(or allegro clisp) 'type-error) t) ;; If the prefix isn't a defined logical host, it's not a logical pathname. #-(or ccl cmu (and clisp windows)) ;; CMUCL parses this as (:ABSOLUTE #) "bar.baz" "42". ;; CLISP signals a parse error reading #p"foo:bar.baz.42". (deftest logical.1 (let ((pathname #p"foo:bar.baz.42")) #+allegro ;; Except in Allegro. (check-logical-pathname pathname "foo" nil "bar" "baz" nil) #-allegro (check-physical-pathname pathname nil "foo:bar.baz" "42")) t) #+lispworks (pushnew 'logical.1 *expected-failures*) #+sbcl (deftest logical.2 ;; Even though "effluvia" is defined as a logical host, "bop" is not a valid ;; logical pathname version, so this can't be a logical pathname. (check-physical-pathname #p"effluvia:bar.baz.bop" nil "effluvia:bar.baz" "bop") t) (deftest logical.3 #-allegro (check-logical-pathname (make-pathname :defaults "effluvia:foo.lisp") "EFFLUVIA" '(:absolute) "FOO" "LISP" nil) #+allegro (check-logical-pathname (make-pathname :defaults "effluvia:foo.lisp") "effluvia" nil "foo" "lisp" nil) t) #-allegro (deftest logical.4 (check-logical-pathname #p"effluvia:bar.baz.42" "EFFLUVIA" '(:absolute) "BAR" "BAZ" 42) t) #-allegro (deftest logical.5 (string= (write-to-string #p"effluvia:bar.baz.42" :escape t) "#P\"EFFLUVIA:BAR.BAZ.42\"") t) #+allegro ;; Allegro returns NIL for the device and directory and drops the version ;; entirely (even from the namestring). (deftest logical.6 (check-logical-pathname #p"effluvia:bar.baz.42" "effluvia" nil "bar" "baz" nil) t) #+allegro (deftest logical.7 (string= (write-to-string #p"effluvia:bar.baz" :escape t) #+allegro-v6.2 "#p\"effluvia:bar.baz\"" #+allegro-v7.0 "#P\"effluvia:bar.baz\"") t) (deftest logical.8 (typep (parse-namestring "**;*.*.*" "effluvia") 'logical-pathname) t) (deftest logical.9 (check-namestring (parse-namestring "**;*.*.*" "effluvia") #-(or allegro lispworks) "EFFLUVIA:**;*.*.*" #+allegro ;; Allegro preserves case and drops the version component. "effluvia:**;*.*" #+lispworks "effluvia:**;*.*.*") t) #-allegro ;; The version can be a bignum. (deftest logical.10 (check-logical-pathname #p"effluvia:bar.baz.2147483648" "EFFLUVIA" '(:absolute) "BAR" "BAZ" 2147483648) t) #-allegro (deftest logical.11 (check-namestring #p"effluvia:bar.baz.2147483648" "EFFLUVIA:BAR.BAZ.2147483648") t) #+sbcl ;; SBCL has a bug when the version is a bignum. (pushnew 'logical.11 *expected-failures*) (deftest logical.12 (check-namestring #p"effluvia:foo.bar.newest" #-allegro "EFFLUVIA:FOO.BAR.NEWEST" #+allegro "effluvia:foo.bar") t) (deftest logical.13 #-allegro (check-logical-pathname #p"effluvia:foo.*" "EFFLUVIA" '(:absolute) "FOO" :wild nil) #+allegro (check-logical-pathname #p"effluvia:foo.*" "effluvia" nil "foo" :wild nil) t) (deftest logical.14 #-allegro (check-logical-pathname #p"effluvia:*.lisp" "EFFLUVIA" '(:absolute) :wild "LISP" nil) #+allegro (check-logical-pathname #p"effluvia:*.lisp" "effluvia" nil :wild "lisp" nil) t) (deftest logical.15 #-allegro (check-logical-pathname #p"effluvia:bar.baz.newest" "EFFLUVIA" '(:absolute) "BAR" "BAZ" :newest) #+allegro (check-logical-pathname #p"effluvia:bar.baz.newest" "effluvia" nil "bar" "baz" nil) t) (deftest logical.16 #-allegro (check-logical-pathname #p"EFFLUVIA:BAR.BAZ.NEWEST" "EFFLUVIA" '(:absolute) "BAR" "BAZ" :newest) #+allegro (check-logical-pathname #p"EFFLUVIA:BAR.BAZ.NEWEST" "EFFLUVIA" nil "BAR" "BAZ" nil) t) ;; The directory component. (deftest logical.17 (check-logical-pathname #p"effluvia:foo;bar.baz" "EFFLUVIA" '(:absolute "FOO") "BAR" "BAZ" nil) t) (deftest logical.18 (check-namestring #p"effluvia:foo;bar.baz" #-allegro "EFFLUVIA:FOO;BAR.BAZ" #+allegro "effluvia:foo;bar.baz") t) (deftest logical.19 #-allegro (check-logical-pathname #p"effluvia:;bar.baz" "EFFLUVIA" '(:relative) "BAR" "BAZ" nil) #+allegro ;; Allegro drops the directory component and removes the semicolon from the ;; namestring. (check-logical-pathname #p"effluvia:;bar.baz" "EFFLUVIA" nil "BAR" "BAZ" nil) t) (deftest logical.20 (check-namestring #p"effluvia:;bar.baz" #+allegro "effluvia:bar.baz" #-allegro "EFFLUVIA:;BAR.BAZ") t) ;; "If a relative-directory-marker precedes the directories, the directory ;; component parsed is as relative; otherwise, the directory component is ;; parsed as absolute." (deftest logical.21 (equal (pathname-directory #p"effluvia:foo.baz") #-allegro '(:absolute) #+allegro nil) t) (deftest logical.22 (typep #p"effluvia:" 'logical-pathname) t) (deftest logical.23 (equal (pathname-directory #p"effluvia:") #-allegro '(:absolute) #+allegro nil) t) ;; PARSE-NAMESTRING (deftest parse-namestring.1 #-allegro (check-logical-pathname (parse-namestring "effluvia:foo.bar") "EFFLUVIA" '(:absolute) "FOO" "BAR" nil) #+allegro (check-logical-pathname (parse-namestring "effluvia:foo.bar") "effluvia" nil "foo" "bar" nil) t) (deftest parse-namestring.2 (let ((pathname (parse-namestring "foo.bar" "effluvia"))) #-(or allegro lispworks) (check-logical-pathname pathname "EFFLUVIA" '(:absolute) "FOO" "BAR" nil) #+allegro (check-logical-pathname pathname "effluvia" nil "foo" "bar" nil) #+lispworks (check-logical-pathname pathname "effluvia" '(:absolute) "FOO" "BAR" nil)) t) (deftest parse-namestring.3 (let ((pathname (parse-namestring "foo;bar;baz.fas.3" "effluvia"))) #-(or allegro lispworks) (check-logical-pathname pathname "EFFLUVIA" '(:absolute "FOO" "BAR") "BAZ" "FAS" 3) #+allegro (check-logical-pathname pathname "effluvia" '(:absolute "foo" "bar") "baz" "fas" nil) #+lispworks (check-logical-pathname pathname "effluvia" '(:absolute "FOO" "BAR") "BAZ" "FAS" 3) ) t) (deftest parse-namestring.4 #-(or abcl clisp cmu lispworks (and allegro windows)) (check-physical-pathname (parse-namestring "effluvia:foo.bar" "") nil "effluvia:foo" "bar") #+abcl ;; Invalid logical host name: "" (signals-error (parse-namestring "effluvia:foo.bar" "") 'error) #+(or clisp lispworks) ;; Host mismatch. (signals-error (parse-namestring "effluvia:foo.bar" "") 'error) #+cmu (signals-error (parse-namestring "effluvia:foo.bar" "") 'error) #+(and allegro windows) ;; "effluvia" is the device (check-physical-pathname (parse-namestring "effluvia:foo.bar" "") nil "foo" "bar") t) ;; "If host is nil and thing is a syntactically valid logical pathname ;; namestring containing an explicit host, then it is parsed as a logical ;; pathname namestring." (deftest parse-namestring.5 #-allegro (check-logical-pathname (parse-namestring "effluvia:foo.bar" nil) "EFFLUVIA" '(:absolute) "FOO" "BAR" nil) #+allegro (check-logical-pathname (parse-namestring "effluvia:foo.bar" nil) "effluvia" nil "foo" "bar" nil) t) ;; "If host is nil, default-pathname is a logical pathname, and thing is a ;; syntactically valid logical pathname namestring without an explicit host, ;; then it is parsed as a logical pathname namestring on the host that is the ;; host component of default-pathname." (deftest parse-namestring.6 #-allegro (check-logical-pathname (parse-namestring "foo" nil #p"effluvia:bar") "EFFLUVIA" '(:absolute) "FOO" nil nil) #+allegro (check-logical-pathname (parse-namestring "foo" nil #p"effluvia:bar") "effluvia" nil "foo" nil nil) t) (deftest parse-namestring.7 (let* ((*default-pathname-defaults* (logical-pathname "EFFLUVIA:")) (pathname (parse-namestring "foo.bar"))) #-allegro (check-logical-pathname pathname "EFFLUVIA" '(:absolute) "FOO" "BAR" nil) #+allegro (check-logical-pathname pathname "effluvia" nil "foo" "bar" nil)) t) (deftest parse-namestring.8 (let* ((*default-pathname-defaults* #p"effluvia:bar") (pathname (parse-namestring "foo" nil))) #-allegro (check-logical-pathname pathname "EFFLUVIA" '(:absolute) "FOO" nil nil) #+allegro (check-logical-pathname pathname "effluvia" nil "foo" nil nil)) t) ;; WILD-PATHNAME-P (deftest wild-pathname-p.1 (wild-pathname-p #p"effluvia:;*.baz") #+(or cmu sbcl) (:wild :wild-inferiors) #-(or cmu sbcl) t) ;; PATHNAME-MATCH-P (deftest pathname-match-p.1 (pathname-match-p "/foo/bar/baz" "/*/*/baz") t) (deftest pathname-match-p.2 (pathname-match-p "/foo/bar/baz" "/**/baz") t) (deftest pathname-match-p.3 (pathname-match-p "/foo/bar/quux/baz" "/**/baz") t) (deftest pathname-match-p.4 (pathname-match-p "foo.bar" "/**/*.*") t) (deftest pathname-match-p.5 (pathname-match-p "/usr/local/bin/foo.bar" "/**/foo.bar") t) (deftest pathname-match-p.6 (pathname-match-p "/usr/local/bin/foo.bar" "**/foo.bar") nil) (deftest pathname-match-p.7 (pathname-match-p "/foo/bar.txt" "/**/*.*") t) (deftest pathname-match-p.8 (pathname-match-p "/foo/bar.txt" "**/*.*") nil) (deftest pathname-match-p.9 (pathname-match-p #p"effluvia:foo.bar" #p"effluvia:**;*.*.*") t) (deftest pathname-match-p.10 (pathname-match-p "foo" "foo.*") t) ;; TRANSLATE-PATHNAME (deftest translate-pathname.1 #-clisp (equal (translate-pathname "foo" "*" "bar") #p"bar") #+clisp (signals-error (translate-pathname "foo" "*" "bar") 'error) t) (deftest translate-pathname.2 (equal (translate-pathname "foo" "*" "*") #p"foo") t) (deftest translate-pathname.3 #-abcl (string= (pathname-name (translate-pathname "foobar" "*" "foo*")) #-allegro-v7.0 "foofoobar" #+allegro-v7.0 "foo*") #+abcl ;; ABCL doesn't implement this translation. Verify that it signals an error. (signals-error (translate-pathname "foobar" "*" "foo*") 'error) t) (deftest translate-pathname.4 #-abcl (equal (translate-pathname "foobar" "foo*" "*baz") #-allegro-v7.0 #p"barbaz" #+allegro-v7.0 #p"*baz") #+abcl ;; ABCL doesn't implement this translation. Verify that it signals an error. (signals-error (translate-pathname "foobar" "foo*" "*baz") 'error) t) (deftest translate-pathname.5 (equal (translate-pathname "foobar" "foo*" "") #+(or allegro clisp) #p"bar" #+(or cmu sbcl lispworks abcl) #p"foobar") t) (deftest translate-pathname.6 (equal (translate-pathname "foo/bar" "*/bar" "*/baz") #p"foo/baz") t) (deftest translate-pathname.7 (equal (translate-pathname "bar/foo" "bar/*" "baz/*") #p"baz/foo") t) (deftest translate-pathname.8 (equal (translate-pathname "foo/bar" "*/bar" "*/baz") #p"foo/baz") t) (deftest translate-pathname.9 (string= (namestring (translate-pathname "test.txt" "*.txt" "*.text")) "test.text") t) (deftest translate-pathname.10 (equal (translate-pathname "foo" "foo.*" "bar") #p"bar") t) (deftest translate-pathname.11 (equal (translate-pathname "foo" "foo.*" "bar.*") #p"bar") t) (deftest translate-pathname.12 (string= (namestring (translate-pathname "foo.bar" "*.*" "/usr/local/*.*")) "/usr/local/foo.bar") t) (deftest translate-pathname.13 (equal (translate-pathname "foo.bar" "*.*" "/usr/local/*.*") #p"/usr/local/foo.bar") t) (deftest translate-pathname.14 (check-translate-pathname '("/foo/" "/*/" "/usr/local/*/") "/usr/local/foo/") t) (deftest translate-pathname.15 (check-translate-pathname '("/foo/baz/bar.txt" "/**/*.*" "/usr/local/**/*.*") "/usr/local/foo/baz/bar.txt") t) (deftest translate-pathname.16 (equal (translate-pathname "/foo/" "/*/" "/usr/local/*/bar/") #p"/usr/local/foo/bar/") t) (deftest translate-pathname.17 (equal (translate-pathname "/foo/bar.txt" "/*/*.*" "/usr/local/*/*.*") #P"/usr/local/foo/bar.txt") t) ;; "TRANSLATE-PATHNAME translates SOURCE (that matches FROM-WILDCARD)..." (deftest pathname-match-p.11 (pathname-match-p "/foo/bar.txt" "**/*.*") nil) ;; Since (pathname-match-p "/foo/bar.txt" "**/*.*" ) => NIL... (deftest translate-pathname.18 #+(or clisp allegro abcl cmu lispworks) ;; This seems to be the correct behavior. (signals-error (translate-pathname "/foo/bar.txt" "**/*.*" "/usr/local/**/*.*") 'error) #+sbcl ;; This appears to be a bug, since SOURCE doesn't match FROM-WILDCARD. (equal (translate-pathname "/foo/bar.txt" "**/*.*" "/usr/local/**/*.*") #p"/usr/local/foo/bar.txt") t) (deftest pathname-match-p.12 (pathname-match-p "/foo/bar.txt" "/**/*.*") t) (deftest translate-pathname.19 (equal (translate-pathname "/foo/bar.txt" "/**/*.*" "/usr/local/**/*.*") #p"/usr/local/foo/bar.txt") t) #-clisp (deftest translate-pathname.20 (equal (translate-pathname "foo.bar" "/**/*.*" "/usr/local/") #p"/usr/local/foo.bar") t) ;; TRANSLATE-LOGICAL-PATHNAME ;; "PATHNAME is first coerced to a pathname. If the coerced pathname is a ;; physical pathname, it is returned." (deftest translate-logical-pathname.1 (equal (translate-logical-pathname #p"/") #p"/") t) #+(or abcl clisp) (deftest translate-logical-pathname.2 (equal (translate-logical-pathname "effluvia:foo.bar") #p"/usr/local/foo.bar") t) #+(or sbcl cmu) (deftest translate-logical-pathname.3 ;; Device mismatch. (and (eq (pathname-device (translate-logical-pathname "effluvia:foo.bar")) :unspecific) (eq (pathname-device #p"/usr/local/foo/bar") nil)) t) (deftest translate-logical-pathname.4 (check-namestring (translate-logical-pathname "effluvia:foo.bar") "/usr/local/foo.bar") t) (deftest translate-logical-pathname.5 (check-namestring (translate-logical-pathname "effluvia:foo;bar.txt") "/usr/local/foo/bar.txt") t) (deftest translate-logical-pathname.6 #-allegro (check-logical-pathname #p"effluvia:Foo.Bar" "EFFLUVIA" '(:absolute) "FOO" "BAR" nil) #+allegro ;; Allegro preserves case. (check-logical-pathname #p"effluvia:Foo.Bar" "effluvia" nil "Foo" "Bar" nil) t) ;; "TRANSLATE-PATHNAME [and thus also TRANSLATE-LOGICAL-PATHNAME] maps ;; customary case in SOURCE into customary case in the output pathname." (deftest translate-logical-pathname.7 #-allegro (check-physical-pathname (translate-logical-pathname #p"effluvia:Foo.Bar") '(:absolute "usr" "local") "foo" "bar") #+allegro ;; Allegro preserves case. (check-physical-pathname (translate-logical-pathname #p"effluvia:Foo.Bar") '(:absolute "usr" "local") "Foo" "Bar") t) (deftest merge-pathnames.1 #-allegro (check-logical-pathname (merge-pathnames "effluvia:foo.bar") "EFFLUVIA" '(:absolute) "FOO" "BAR" :newest) #+allegro ;; Allegro's MERGE-PATHNAMES apparently calls TRANSLATE-LOGICAL-PATHNAME. (check-physical-pathname (merge-pathnames "effluvia:foo.bar") '(:absolute "usr" "local") "foo" "bar") t) (deftest merge-pathnames.2 (equal (merge-pathnames (logical-pathname "effluvia:;foo;bar;") (logical-pathname "effluvia:baz;quux.lisp.3")) #-allegro (make-pathname :host "EFFLUVIA" :device :unspecific :directory '(:absolute "BAZ" "FOO" "BAR") :name "QUUX" :type "LISP" :version 3) #+allegro (make-pathname :host "effluvia" :device nil :directory '(:absolute "baz" "foo" "bar") :name "quux" :type "lisp" :version nil) ) t) (deftest compile-file-pathname.1 (equal (compile-file-pathname "effluvia:foo.lisp") #+abcl ;; Is this a bug? (Should version be :NEWEST?) #p"EFFLUVIA:FOO.ABCL" #+allegro #p"effluvia:foo.fasl" #+(or cmu sbcl) #p"EFFLUVIA:FOO.FASL.NEWEST" #+clisp ;; Is this a bug? ;; #p"EFFLUVIA:FOO.fas.NEWEST" (make-pathname :host "EFFLUVIA" :directory '(:absolute) :name "FOO" :type "fas" :version :newest) #+(and lispworks unix) #p"EFFLUVIA:FOO.UFSL.NEWEST" #+(and lispworks windows) #p"EFFLUVIA:FOO.FSL.NEWEST") t) (deftest file-namestring.1 (equal (file-namestring #p"") #+(or abcl allegro cmu) nil #+(or clisp lispworks sbcl) "") t) (deftest file-namestring.2 (equal (file-namestring #p"foo") "foo") t) (deftest file-namestring.3 (let ((pathname (make-pathname :type "foo"))) #+abcl (equal (file-namestring pathname) nil) #+allegro (equal (file-namestring pathname) "NIL.foo") ;; bug #+(or clisp lispworks) (equal (file-namestring pathname) ".foo") #+(or cmu sbcl) (signals-error (file-namestring pathname) 'error)) t) ;; A variant of FILE-NAMESTRING.3 that detects Allegro's bug as a bug. (deftest file-namestring.4 (let ((pathname (make-pathname :type "foo"))) #-(or cmu sbcl) (not (equal (file-namestring pathname) "NIL.foo")) #+(or cmu sbcl) (signals-error (file-namestring pathname) 'error)) t) #+allegro (pushnew 'file-namestring.4 *expected-failures*) (deftest enough-namestring.1 (equal (enough-namestring #p"/foo" #p"/") "foo") t) #+sbcl (pushnew 'enough-namestring.1 *expected-failures*) (deftest enough-namestring.2 #-windows (equal (enough-namestring #p"foo/bar" #p"foo") "foo/bar") #+windows (equal (enough-namestring #p"foo\\bar" #p"foo") "foo/bar") t) (deftest enough-namestring.3 (equal (enough-namestring #p"foo/bar" #p"foo/") "bar") t) #+sbcl (pushnew 'enough-namestring.3 *expected-failures*) ;; The following tests are adapted from SBCL's pathnames.impure.lisp. (setf (logical-pathname-translations "demo0") '(("**;*.*.*" "/tmp/"))) (deftest sbcl.1 (pathname-match-p "demo0:file.lisp" (logical-pathname "demo0:tmp;**;*.*.*")) nil) #-clisp (deftest sbcl.2 (check-namestring (translate-logical-pathname "demo0:file.lisp") "/tmp/file.lisp") t) (setf (logical-pathname-translations "demo1") '(("**;*.*.*" "/tmp/**/*.*") (";**;*.*.*" "/tmp/rel/**/*.*"))) ;; Remove "**" from the resulting pathname when the source directory is NIL. (deftest sbcl.3 (equal (namestring (translate-logical-pathname "demo1:foo.lisp")) #-windows "/tmp/**/foo.lisp" #+windows "\\tmp\\**\\foo.lisp") nil) (deftest sbcl.4 (check-namestring (translate-logical-pathname "demo1:foo.lisp") "/tmp/foo.lisp") t) ;;; Check for absolute/relative path confusion. #-allegro (deftest sbcl.5 (pathname-match-p "demo1:;foo.lisp" "demo1:**;*.*.*") nil) #+(or sbcl cmu) ;; BUG Pathnames should match if the following translation is to work. (deftest sbcl.6 (pathname-match-p "demo1:;foo.lisp" "demo1:;**;*.*.*") t) #+clisp (deftest sbcl.7 (pathname-match-p "demo1:;foo.lisp" ";**;*.*.*") t) (deftest sbcl.8 (check-namestring (translate-logical-pathname "demo1:;foo.lisp") #+abcl "/tmp/rel/foo.lisp" #+allegro "/tmp/foo.lisp" #-(or allegro abcl) "/tmp/rel/foo.lisp") t) (setf (logical-pathname-translations "demo2") '(("test;**;*.*" "/tmp/demo2/test"))) (deftest sbcl.9 (equal (enough-namestring "demo2:test;foo.lisp") #+sbcl "DEMO2:;TEST;FOO.LISP" #+(or abcl cmu lispworks) "DEMO2:TEST;FOO.LISP" #+allegro-v7.0 "demo2:test;foo.lisp" #+allegro-v6.2 "/test/foo.lisp" ;; BUG #+(and clisp unix) "TEST;FOO.LISP" #+(and clisp windows) "DEMO2:TEST;FOO.LISP") t) #-(or allegro clisp cmu) (deftest sbcl.10 (signals-error (make-pathname :host "EFFLUVIA" :directory "!bla" :name "bar") 'error) t) #-(or allegro cmu) (deftest sbcl.11 (signals-error (make-pathname :host "EFFLUVIA" :directory "bla" :name "!bar") 'error) t) #-(or allegro cmu) (deftest sbcl.12 (signals-error (make-pathname :host "EFFLUVIA" :directory "bla" :name "bar" :type "&baz") 'error) t) (deftest sbcl.13 (equal (namestring (parse-namestring "" "EFFLUVIA")) "EFFLUVIA:") t) (deftest sbcl.14 #-cmu (equal (namestring (parse-namestring "" :unspecific)) "") #+cmu ;; It seems reasonable to signal an error here, since the HOST argument to ;; PARSE-NAMESTRING is specified to be "a valid pathname host, a logical host, ;; or NIL". (signals-error (parse-namestring "" :unspecific) 'type-error) t) (deftest sbcl.15 (equal (namestring (parse-namestring "" (pathname-host (translate-logical-pathname "EFFLUVIA:")))) "") t) ;; PARSE-NAMESTRING host mismatch: "If HOST is supplied and not NIL, and THING ;; contains a manifest host name, an error of type ERROR is signaled if the ;; hosts do not match." (deftest sbcl.16 (signals-error (parse-namestring "effluvia:foo.bar" "demo2") 'error) t) (setf (logical-pathname-translations "bazooka") '(("todemo;*.*.*" "demo0:*.*.*"))) (deftest sbcl.17 #+allegro ;; BUG (check-namestring (translate-logical-pathname "bazooka:todemo;x.y") "/tmp/todemo/x.y") #+clisp ;; BUG (signals-error (translate-logical-pathname "bazooka:todemo;x.y") 'error) #-(or allegro clisp) (check-namestring (translate-logical-pathname "bazooka:todemo;x.y") "/tmp/x.y") t) (deftest sbcl.18 #+clisp ;; BUG (signals-error (translate-logical-pathname "demo0:x.y") 'error) #-clisp (equal (namestring (translate-logical-pathname "demo0:x.y")) ;;#-windows "/tmp/x.y" ;;#+windows "\\tmp\\x.y" ) t) #-(or allegro clisp) (deftest sbcl.19 (equal (namestring (translate-logical-pathname "bazooka:todemo;x.y")) (namestring (translate-logical-pathname "demo0:x.y"))) t) ;; "If HOST is incorrectly supplied, an error of type TYPE-ERROR is signaled." (deftest sbcl.20 (signals-error (logical-pathname-translations "unregistered-host") #+(or clisp lispworks) 'error ;; BUG #+cmu 'file-error ;; BUG #-(or clisp lispworks cmu) 'type-error) t) (deftest sbcl.21 (string-equal (host-namestring (parse-namestring "OTHER-HOST:ILLEGAL/LPN")) "OTHER-HOST") nil) #+(or lispworks (and clisp windows)) (pushnew 'sbcl.21 *expected-failures*) (deftest sbcl.22 (string= (pathname-name (parse-namestring "OTHER-HOST:ILLEGAL/LPN")) "LPN") t) #+(and clisp windows) (pushnew 'sbcl.22 *expected-failures*) (setf (logical-pathname-translations "test0") '(("**;*.*.*" "/library/foo/**/"))) (deftest sbcl.23 (check-namestring (translate-logical-pathname "test0:foo;bar;baz;mum.quux") "/library/foo/foo/bar/baz/mum.quux") t) (setf (logical-pathname-translations "prog") '(("CODE;*.*.*" "/lib/prog/"))) #-allegro (deftest sbcl.24 (check-namestring (translate-logical-pathname "prog:code;documentation.lisp") "/lib/prog/documentation.lisp") t) (setf (logical-pathname-translations "prog1") '(("CODE;DOCUMENTATION.*.*" "/lib/prog/docum.*") ("CODE;*.*.*" "/lib/prog/"))) #-allegro (deftest sbcl.25 (check-namestring (translate-logical-pathname "prog1:code;documentation.lisp") "/lib/prog/docum.lisp") t) ;; "ANSI section 19.3.1.1.5 specifies that translation to a filesystem which ;; doesn't have versions should ignore the version slot. CMU CL didn't ignore ;; this as it should, but we [i.e. SBCL] do." ;; "Some file systems do not have versions. Logical pathname translation to ;; such a file system ignores the version." 19.3.1.1.5 #-cmu ;; CMUCL supports emacs-style versions. (deftest sbcl.26 (check-namestring (translate-logical-pathname "test0:foo;bar;baz;mum.quux.3") "/library/foo/foo/bar/baz/mum.quux") t) #+lispworks (pushnew 'sbcl.26 *expected-failures*) (eval-when (:compile-toplevel :load-toplevel :execute) (setf (logical-pathname-translations "scratch") '(("**;*.*.*" "/usr/local/doc/**/*")))) ;; Trivial merge. (deftest sbcl.27 (check-merge-pathnames #p"foo" #p"/usr/local/doc/" #p"/usr/local/doc/foo") t) ;; If pathname does not specify a host, device, directory, name, or type, each ;; such component is copied from default-pathname. ;; 1) no name, no type (deftest sbcl.28 (check-merge-pathnames #p"/supplied-dir/" #p"/dir/name.type" #p"/supplied-dir/name.type") t) ;; 2) no directory, no type (deftest sbcl.29 (check-merge-pathnames #p"supplied-name" #p"/dir/name.type" #p"/dir/supplied-name.type") t) ;; 3) no name, no dir (must use make-pathname as ".foo" is parsed ;; as a name) (deftest sbcl.30 (check-merge-pathnames (make-pathname :type "supplied-type") #p"/dir/name.type" #p"/dir/name.supplied-type") t) ;; If (pathname-directory pathname) is a list whose car is ;; :relative, and (pathname-directory default-pathname) is a ;; list, then the merged directory is [...] (deftest sbcl.31 (check-merge-pathnames #p"qqq/www" #p"/aaa/bbb/ccc/ddd/eee" #p"/aaa/bbb/ccc/ddd/qqq/www") t) ;; except that if the resulting list contains a string or ;; :wild immediately followed by :back, both of them are ;; removed. (deftest sbcl.32 (check-merge-pathnames ;; "../" in a namestring is parsed as :up not :back, so MAKE-PATHNAME. (make-pathname :directory '(:relative :back "blah")) #p"/aaa/bbb/ccc/ddd/eee" #P"/aaa/bbb/ccc/blah/eee") t) ;; If (pathname-directory default-pathname) is not a list or ;; (pathname-directory pathname) is not a list whose car is ;; :relative, the merged directory is (or (pathname-directory ;; pathname) (pathname-directory default-pathname)) (deftest sbcl.33 (check-merge-pathnames #p"/absolute/path/name" #p"/dir/default-name.type" #P"/absolute/path/name.type") t) (deftest sbcl.34 (check-merge-pathnames #p"scratch:;name2" #p"scratch:foo;" #p"SCRATCH:FOO;NAME2") t) (deftest sbcl.35 (check-merge-pathnames #p"scratch:;foo" #p"/usr/local/doc/" #-(or allegro clisp lispworks) #P"SCRATCH:USR;LOCAL;DOC;FOO" #+(and allegro unix) #p"/usr/local/doc/foo" #+(and allegro windows) #p"scratch:usr;local;doc;foo" #+clisp #p"SCRATCH:;FOO" #+lispworks #p"SCRATCH:FOO") t) (deftest sbcl.36 (check-merge-pathnames #p"scratch:supplied-dir;" #p"/dir/name.type" #-clisp #p"SCRATCH:SUPPLIED-DIR;NAME.TYPE" #+clisp ;; #p"SCRATCH:SUPPLIED-DIR;name.type.NEWEST" (make-pathname :host "SCRATCH" :directory '(:absolute "SUPPLIED-DIR") :name "name" :type "type")) t) (deftest sbcl.37 (check-merge-pathnames #p"scratch:;supplied-name" #p"/dir/name.type" #-(or allegro clisp lispworks) #p"SCRATCH:DIR;SUPPLIED-NAME.TYPE" #+(and allegro unix) #p"/usr/local/doc/supplied-name.type" #+(and allegro windows) #P"scratch:dir;supplied-name.type" #+clisp ;; #P"SCRATCH:;SUPPLIED-NAME.type.NEWEST" (make-pathname :host "SCRATCH" :directory '(:relative) :name "SUPPLIED-NAME" :type "type") #+lispworks ;; #P"SCRATCH:SUPPLIED-NAME.TYPE.NEWEST" (make-pathname :host "SCRATCH" :directory '(:absolute) :name "SUPPLIED-NAME" :type "TYPE")) t) (deftest sbcl.38 (check-merge-pathnames (make-pathname :host "scratch" :type "supplied-type") #p"/dir/name.type" #-(or allegro clisp lispworks) #p"SCRATCH:DIR;NAME.SUPPLIED-TYPE" #+(and allegro unix) #p"/usr/local/doc/name.supplied-type" #+(and allegro windows) #P"scratch:dir;name.supplied-type" #+clisp ;; #P"SCRATCH:dir;name.supplied-type.NEWEST" (make-pathname :host "SCRATCH" :directory '(:absolute "dir") :name "name" :type "supplied-type") #+lispworks ;; #P"SCRATCH:NAME.SUPPLIED-TYPE.NEWEST" (make-pathname :host "SCRATCH" :directory '(:absolute) :name "NAME" :type "SUPPLIED-TYPE")) t) (deftest sbcl.39 (let ((pathname (make-pathname :host "scratch" :directory '(:relative "foo") :name "bar")) (default-pathname #p"/aaa/bbb/ccc/ddd/eee")) #-allegro (check-merge-pathnames pathname default-pathname #-(or clisp lispworks) #p"SCRATCH:AAA;BBB;CCC;DDD;FOO;BAR" #+clisp ;; #P"SCRATCH:;foo;bar" (make-pathname :host "SCRATCH" :directory '(:relative "foo") :name "bar") #+lispworks #p"SCRATCH:FOO;BAR") #+(and allegro unix) (signals-error (merge-pathnames pathname default-pathname) 'error) #+(and allegro windows) (check-merge-pathnames pathname default-pathname #P"scratch:aaa;bbb;ccc;ddd;foo;bar")) t) #-lispworks (deftest sbcl.40 (let ((pathname (make-pathname :host "scratch" :directory '(:relative :back "foo") :name "bar")) (default-pathname #p"/aaa/bbb/ccc/ddd/eee")) #-allegro (check-merge-pathnames pathname default-pathname #-clisp #p"SCRATCH:AAA;BBB;CCC;FOO;BAR" #+clisp ;; #P"SCRATCH:;..;foo;bar.NEWEST" (make-pathname :host "SCRATCH" :directory '(:relative :back "foo") :name "bar")) #+(and allegro unix) (signals-error (merge-pathnames pathname default-pathname) 'error) #+(and allegro windows) (check-merge-pathnames pathname default-pathname #P"scratch:aaa;bbb;ccc;foo;bar")) t) #+lispworks ;; "Illegal logical pathname directory component: :BACK." (deftest sbcl.40 (signals-error (make-pathname :host "scratch" :directory '(:relative :back "foo") :name "bar") 'error) t) (deftest sbcl.41 (check-merge-pathnames #p"scratch:absolute;path;name" #p"/dir/default-name.type" #-clisp #p"SCRATCH:ABSOLUTE;PATH;NAME.TYPE" #+clisp ;; #P"SCRATCH:ABSOLUTE;PATH;NAME.type.NEWEST" (make-pathname :host "SCRATCH" :directory '(:absolute "ABSOLUTE" "PATH") :name "NAME" :type "type")) t) (deftest sbcl.42 (check-namestring (parse-namestring "/foo" (host-namestring #p"/bar")) "/foo") t) #+lispworks (pushnew 'sbcl.42 *expected-failures*) (deftest sbcl.43 (string= (namestring (parse-namestring "FOO" (host-namestring #p"SCRATCH:BAR"))) "SCRATCH:FOO") t) #-(or allegro clisp cmu lispworks) (deftest sbcl.44 ;; "The null string, "", is not a valid value for any component of a logical ;; pathname." 19.3.2.2 (signals-error (setf (logical-pathname-translations "") (list '("**;*.*.*" "/**/*.*"))) 'error) t) #-clisp (deftest sbcl.45 (check-namestring (translate-logical-pathname "/") "/") t) (deftest sbcl.46 (signals-error (pathname (make-string-input-stream "FOO")) #-(or allegro-v6.2 cmu) 'type-error #+allegro-v6.2 'stream-error #+cmu 'error) t) (deftest sbcl.47 (signals-error (merge-pathnames (make-string-output-stream)) #-allegro-v6.2 'type-error #+allegro-v6.2 'stream-error) t) (deftest sbcl.48 (check-readable-or-signals-error (make-pathname :name "foo" :type "txt" :version :newest)) t) #+lispworks (pushnew 'sbcl.48 *expected-failures*) #-allegro (deftest sbcl.49 (check-readable-or-signals-error (make-pathname :name "foo" :type "txt" :version 1)) t) #+lispworks (pushnew 'sbcl.49 *expected-failures*) (deftest sbcl.50 #-clisp (check-readable-or-signals-error (make-pathname :name "foo" :type ".txt")) #+clisp (signals-error (make-pathname :name "foo" :type ".txt") 'error) t) #+(or allegro cmu lispworks) (pushnew 'sbcl.50 *expected-failures*) (deftest sbcl.51 (check-readable-or-signals-error (make-pathname :name "foo." :type "txt")) t) (deftest sbcl.52 (check-readable-or-signals-error (parse-namestring "SCRATCH:FOO.TXT.1")) t) (deftest sbcl.53 (check-readable-or-signals-error (parse-namestring "SCRATCH:FOO.TXT.NEWEST")) t) (deftest sbcl.54 (check-readable-or-signals-error (parse-namestring "SCRATCH:FOO.TXT")) t) (deftest sbcl.55 (equal (parse-namestring "foo" nil "/") (parse-namestring "foo" nil #p"/")) t) #-allegro (deftest sbcl.56 (let ((test "parse-namestring-test.tmp")) (unwind-protect (with-open-file (f test :direction :output) ;; FIXME: This test is a bit flaky, since we only check that ;; no error is signalled. The dilemma here is "what is the ;; correct result when defaults is a _file_, not a ;; directory". Currently (0.8.10.73) we get #P"foo" here (as ;; opposed to eg. #P"/path/to/current/foo"), which is ;; possibly mildly surprising but probably conformant. (equal (parse-namestring "foo" nil f) #p"foo")) (when (probe-file test) (delete-file test)))) t) ;;; ENOUGH-NAMESTRING should probably not fail when the namestring in ;;; question has a :RELATIVE pathname. (deftest sbcl.57 (equal (enough-namestring #p"foo" #p"./") "foo") t) ;;; bug reported by Artem V. Andreev: :WILD not handled in unparsing ;;; directory lists. (deftest sbcl.58 (check-namestring #p"/tmp/*/" "/tmp/*/") t) #-allegro (deftest sbcl.59 (string= (with-standard-io-syntax (write-to-string #p"/foo")) ;;#-windows "#P\"/foo\"" ;;#+(and windows (not lispworks)) "#P\"\\\\foo\"" ;;#+(and windows lispworks) "#P\"/foo\"") t) #-allegro (deftest sbcl.60 (string= (with-standard-io-syntax (write-to-string #p"/foo" :readably nil)) ;;#-windows "#P\"/foo\"" ;;#+(and windows (not lispworks)) "#P\"\\\\foo\"" ;;#+(and windows lispworks) "#P\"/foo\"" ) t) #-allegro (deftest sbcl.61 (string= (with-standard-io-syntax (write-to-string #p"/foo" :escape nil)) ;;#-windows "#P\"/foo\"" ;;#+(and windows (not lispworks)) "#P\"\\\\foo\"" ;;#+(and windows lispworks) "#P\"/foo\"" ) t) (deftest sbcl.62 (string= (with-standard-io-syntax (write-to-string #p"/foo" :readably nil :escape nil)) ;;#-windows "/foo" ;;#+windows "\\foo" ) t) (deftest make-pathname.1 (handler-case (make-pathname :directory #p"/tmp/") (type-error () t)) t) (deftest pathname.load.1 (let ((dir (merge-pathnames "dir+with+plus/" *abcl-test-directory*))) (with-temp-directory (dir) (let ((file (merge-pathnames "foo.lisp" dir))) (with-open-file (s file :direction :output) (write *foo.lisp* :stream s)) (load file)))) t) (deftest pathname.load.2 (let ((dir (merge-pathnames "dir with space/" *abcl-test-directory*))) (with-temp-directory (dir) (let ((file (merge-pathnames "foo.lisp" dir))) (with-open-file (s file :direction :output) (write *foo.lisp* :stream s)) (load file)))) t) (deftest pathname.make-pathname.1 (make-pathname :directory nil :defaults "/home/fare/") #p"") (deftest pathname.make-pathname.2 (let ((p (make-pathname :defaults (make-pathname :name :wild :type :wild :version :wild :directory :wild)))) (values (pathname-name p) (pathname-type p) (pathname-version p) (pathname-directory p))) :wild :wild :wild (:absolute :wild)) (deftest pathname.make-pathname.3 (signals-error (make-pathname :directory '(:absolute ("a" "b"))) 'file-error) t) (deftest pathname.make-pathname.4 (directory-namestring (make-pathname :directory :unspecific)) "") abcl-src-1.9.0/test/lisp/abcl/rt-package.lisp0100644 0000000 0000000 00000002636 14202767264 017515 0ustar000000000 0000000 ;-*- Mode: Lisp -*- ;;;; Author: Paul Dietz ;;;; Created: Tue Dec 17 21:10:53 2002 ;;;; Contains: Package definition for RT ;; (eval-when (:execute :compile-toplevel :load-toplevel) #| (defpackage :regression-test (:use :cl) (:nicknames :rtest #-lispworks :rt) (:export #:*do-tests-when-defined* #:*compile-tests* #:*test* #:continue-testing #:deftest #:do-test #:do-tests #:get-test #:pending-tests #:rem-all-tests #:rem-test #:defnote #:my-aref #:*catch-errors* #:disable-note )) |# (let* ((name (symbol-name :abcl-regression-test)) (pkg (find-package name))) (unless pkg (setq pkg (make-package name :nicknames (mapcar #'symbol-name '(:abcl-rtest #-lispworks :abcl-rt)) :use '(#-wcl :cl #+wcl :lisp) ))) (let ((*package* pkg)) (export (mapcar #'intern (mapcar #'symbol-name '(#:*compile-tests* #:*test* #:continue-testing #:deftest #:do-test #:do-tests #:do-extended-tests #:get-test #:pending-tests #:rem-all-tests #:rem-test #:defnote #:my-aref #:*catch-errors* #:*passed-tests* #:*failed-tests* #:disable-note #:*expected-failures*)))))) ;; ) ;; (in-package :regression-test) abcl-src-1.9.0/test/lisp/abcl/rt.lisp0100644 0000000 0000000 00000035774 14202767264 016135 0ustar000000000 0000000 ;-*-syntax:COMMON-LISP;Package:(RT :use "COMMON-LISP" :colon-mode :external)-*- #|----------------------------------------------------------------------------| | Copyright 1990 by the Massachusetts Institute of Technology, Cambridge MA. | | | | Permission to use, copy, modify, and distribute this software and its | | documentation for any purpose and without fee is hereby granted, provided | | that this copyright and permission notice appear in all copies and | | supporting documentation, and that the name of M.I.T. not be used in | | advertising or publicity pertaining to distribution of the software | | without specific, written prior permission. M.I.T. makes no | | representations about the suitability of this software for any purpose. | | It is provided "as is" without express or implied warranty. | | | | M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | | M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | | SOFTWARE. | |----------------------------------------------------------------------------|# ;This was the December 19, 1990 version of the regression tester, but ;has since been modified. (in-package :abcl-regression-test) (declaim (ftype (function (t) t) get-entry expanded-eval do-entries)) (declaim (type list *entries*)) (declaim (ftype (function (t &rest t) t) report-error)) (declaim (ftype (function (t &optional t) t) do-entry)) (defvar *test* nil "Current test name") (defvar *do-tests-when-defined* nil) (defvar *entries* '(nil) "Test database. Has a leading dummy cell that does not contain an entry.") (defvar *entries-tail* *entries* "Tail of the *entries* list") (defvar *entries-table* (make-hash-table :test #'equal) "Map the names of entries to the cons cell in *entries* that precedes the one whose car is the entry.") (defvar *in-test* nil "Used by TEST") (defvar *debug* nil "For debugging") (defvar *catch-errors* t "When true, causes errors in a test to be caught.") (defvar *print-circle-on-failure* nil "Failure reports are printed with *PRINT-CIRCLE* bound to this value.") (defvar *compile-tests* nil "When true, compile the tests before running them.") (defvar *expanded-eval* nil "When true, convert the tests into a form that is less likely to have compiler optimizations.") (defvar *optimization-settings* '((safety 3))) (defvar *failed-tests* nil "After DO-TESTS, becomes the list of names of tests that have failed") (defvar *passed-tests* nil "After DO-TESTS, becomes the list of names of tests that have passed") (defvar *expected-failures* nil "A list of test names that are expected to fail.") (defvar *notes* (make-hash-table :test 'equal) "A mapping from names of notes to note objects.") (defstruct (entry (:conc-name nil)) pend name props form vals) ;;; Note objects are used to attach information to tests. ;;; A typical use is to mark tests that depend on a particular ;;; part of a set of requirements, or a particular interpretation ;;; of the requirements. (defstruct note name contents disabled ;; When true, tests with this note are considered inactive ) ;; (defmacro vals (entry) `(cdddr ,entry)) (defmacro defn (entry) (let ((var (gensym))) `(let ((,var ,entry)) (list* (name ,var) (form ,var) (vals ,var))))) (defun entry-notes (entry) (let* ((props (props entry)) (notes (getf props :notes))) (if (listp notes) notes (list notes)))) (defun has-disabled-note (entry) (let ((notes (entry-notes entry))) (loop for n in notes for note = (if (note-p n) n (gethash n *notes*)) thereis (and note (note-disabled note))))) (defun has-note (entry note) (unless (note-p note) (let ((new-note (gethash note *notes*))) (setf note new-note))) (and note (not (not (member note (entry-notes entry)))))) (defun pending-tests () (loop for entry in (cdr *entries*) when (and (pend entry) (not (has-disabled-note entry))) collect (name entry))) (defun rem-all-tests () (setq *entries* (list nil)) (setq *entries-tail* *entries*) (clrhash *entries-table*) nil) (defun rem-test (&optional (name *test*)) (let ((pred (gethash name *entries-table*))) (when pred (if (null (cddr pred)) (setq *entries-tail* pred) (setf (gethash (name (caddr pred)) *entries-table*) pred)) (setf (cdr pred) (cddr pred)) (remhash name *entries-table*) name))) (defun get-test (&optional (name *test*)) (defn (get-entry name))) (defun get-entry (name) (let ((entry ;; (find name (the list (cdr *entries*)) ;; :key #'name :test #'equal) (cadr (gethash name *entries-table*)) )) (when (null entry) (report-error t "~%No test with name ~:@(~S~)." name)) entry)) (defmacro deftest (name &rest body) (let* ((p body) (properties (loop while (keywordp (first p)) unless (cadr p) do (error "Poorly formed deftest: ~A~%" (list* 'deftest name body)) append (list (pop p) (pop p)))) (form (pop p)) (vals p)) `(add-entry (make-entry :pend t :name ',name :props ',properties :form ',form :vals ',vals)))) (defun add-entry (entry) (setq entry (copy-entry entry)) (let* ((pred (gethash (name entry) *entries-table*))) (cond (pred (setf (cadr pred) entry) (report-error nil "Redefining test ~:@(~S~)" (name entry))) (t (setf (gethash (name entry) *entries-table*) *entries-tail*) (setf (cdr *entries-tail*) (cons entry nil)) (setf *entries-tail* (cdr *entries-tail*)) ))) (when *do-tests-when-defined* (do-entry entry)) (setq *test* (name entry))) (defun report-error (error? &rest args) (cond (*debug* (apply #'format t args) (if error? (throw '*debug* nil))) (error? (apply #'error args)) (t (apply #'warn args))) nil) (defun do-test (&optional (name *test*) &rest key-args) (flet ((%parse-key-args (&key ((:catch-errors *catch-errors*) *catch-errors*) ((:compile *compile-tests*) *compile-tests*)) (do-entry (get-entry name)))) (apply #'%parse-key-args key-args))) (defun my-aref (a &rest args) (apply #'aref a args)) (defun my-row-major-aref (a index) (row-major-aref a index)) (defun equalp-with-case (x y) "Like EQUALP, but doesn't do case conversion of characters. Currently doesn't work on arrays of dimension > 2." (cond ((eq x y) t) ((consp x) (and (consp y) (equalp-with-case (car x) (car y)) (equalp-with-case (cdr x) (cdr y)))) ((and (typep x 'array) (= (array-rank x) 0)) (equalp-with-case (my-aref x) (my-aref y))) ((typep x 'vector) (and (typep y 'vector) (let ((x-len (length x)) (y-len (length y))) (and (eql x-len y-len) (loop for i from 0 below x-len for e1 = (my-aref x i) for e2 = (my-aref y i) always (equalp-with-case e1 e2)))))) ((and (typep x 'array) (typep y 'array) (not (equal (array-dimensions x) (array-dimensions y)))) nil) ((typep x 'array) (and (typep y 'array) (let ((size (array-total-size x))) (loop for i from 0 below size always (equalp-with-case (my-row-major-aref x i) (my-row-major-aref y i)))))) ((typep x 'pathname) (equal x y)) (t (eql x y)))) (defun do-entry (entry &optional (s *standard-output*)) (catch '*in-test* (setq *test* (name entry)) (setf (pend entry) t) (let* ((*in-test* t) ;; (*break-on-warnings* t) (aborted nil) r) ;; (declare (special *break-on-warnings*)) (block aborted (setf r (flet ((%do () (handler-bind #-sbcl nil #+sbcl ((sb-ext:code-deletion-note #'(lambda (c) (if (has-note entry :do-not-muffle) nil (muffle-warning c))))) (cond (*compile-tests* (multiple-value-list (funcall (compile nil `(lambda () (declare (optimize ,@*optimization-settings*)) ,(form entry)))))) (*expanded-eval* (multiple-value-list (expanded-eval (form entry)))) (t (multiple-value-list (eval (form entry)))))))) (if *catch-errors* (handler-bind (#-ecl (style-warning #'(lambda (c) (if (has-note entry :do-not-muffle-warnings) c (muffle-warning c)))) (error #'(lambda (c) (setf aborted t) (setf r (list c)) (return-from aborted nil)))) (%do)) (%do))))) (setf (pend entry) (or aborted (not (equalp-with-case r (vals entry))))) (when (pend entry) (let ((*print-circle* *print-circle-on-failure*)) #+xcl (progn (fresh-line) (format t "Test ~S failed~%" *test*) (format t "Form: ~S~%" (form entry)) (format t "Expected value: ~S~%" (if (= (length (vals entry)) 1) (car (vals entry)) (vals entry)))) #-xcl (format s "~&Test ~:@(~S~) failed~ ~%Form: ~S~ ~%Expected value~P: ~ ~{~S~^~%~17t~}~%" *test* (form entry) (length (vals entry)) (vals entry)) (handler-case #+xcl (let ((r (if (= (length r) 1) (car r) r))) (format t "Actual value: ~S" r) (when (typep r 'condition) (format t " [\"~A\"]" r)) (terpri)) #-xcl (let ((st (format nil "Actual value~P: ~ ~{~S~^~%~15t~}.~%" (length r) r))) (format s "~A" st)) (error () (format s "Actual value: #~%"))) (finish-output s))))) (when (not (pend entry)) *test*)) (defun expanded-eval (form) "Split off top level of a form and eval separately. This reduces the chance that compiler optimizations will fold away runtime computation." (if (not (consp form)) (eval form) (let ((op (car form))) (cond ((eq op 'let) (let* ((bindings (loop for b in (cadr form) collect (if (consp b) b (list b nil)))) (vars (mapcar #'car bindings)) (binding-forms (mapcar #'cadr bindings))) (apply (the function (eval `(lambda ,vars ,@(cddr form)))) (mapcar #'eval binding-forms)))) ((and (eq op 'let*) (cadr form)) (let* ((bindings (loop for b in (cadr form) collect (if (consp b) b (list b nil)))) (vars (mapcar #'car bindings)) (binding-forms (mapcar #'cadr bindings))) (funcall (the function (eval `(lambda (,(car vars) &aux ,@(cdr bindings)) ,@(cddr form)))) (eval (car binding-forms))))) ((eq op 'progn) (loop for e on (cdr form) do (if (null (cdr e)) (return (eval (car e))) (eval (car e))))) ((and (symbolp op) (fboundp op) (not (macro-function op)) (not (special-operator-p op))) (apply (symbol-function op) (mapcar #'eval (cdr form)))) (t (eval form)))))) (defun continue-testing () (if *in-test* (throw '*in-test* nil) (do-entries *standard-output*))) (defun do-tests (&key (out *standard-output*) ((:catch-errors *catch-errors*) *catch-errors*) ((:compile *compile-tests*) *compile-tests*)) (setq *failed-tests* nil *passed-tests* nil) (dolist (entry (cdr *entries*)) (setf (pend entry) t)) (if (streamp out) (do-entries out) (with-open-file (stream out :direction :output) (do-entries stream)))) (defun do-entries (s) (format s "~&Doing ~A pending test~:P ~ of ~A tests total.~%" (count t (the list (cdr *entries*)) :key #'pend) (length (cdr *entries*))) (finish-output s) (dolist (entry (cdr *entries*)) (when (and (pend entry) (not (has-disabled-note entry))) (let ((success? (do-entry entry s))) (if success? (push (name entry) *passed-tests*) (push (name entry) *failed-tests*)) #+xcl (progn (fresh-line s) (when success? (format s "Test ~S~%" (name entry)))) #-xcl (format s "~@[~<~%~:; ~:@(~S~)~>~]" success?)) (finish-output s) )) (let ((pending (pending-tests)) (expected-table (make-hash-table :test #'equal))) (dolist (ex *expected-failures*) (setf (gethash ex expected-table) t)) (let ((new-failures (loop for pend in pending unless (gethash pend expected-table) collect pend))) (if (null pending) #+xcl (progn (fresh-line s) (format s "No tests failed.")) #-xcl (format s "~&No tests failed.") (progn #+xcl (progn (fresh-line s) (format s "~D out of ~D total tests failed" (length pending) (length (cdr *entries*)))) #-xcl (format s "~&~A out of ~A ~ total tests failed: ~ ~:@(~{~<~% ~1:;~S~>~ ~^, ~}~)." (length pending) (length (cdr *entries*)) pending) (if (null new-failures) (format s "~&No unexpected failures.") (when *expected-failures* (format s "~&~A unexpected failures: ~ ~:@(~{~<~% ~1:;~S~>~ ~^, ~}~)." (length new-failures) new-failures))) )) (finish-output s) (null pending)))) ;;; Note handling functions and macros (defmacro defnote (name contents &optional disabled) `(eval-when (:load-toplevel :execute) (let ((note (make-note :name ',name :contents ',contents :disabled ',disabled))) (setf (gethash (note-name note) *notes*) note) note))) (defun disable-note (n) (let ((note (if (note-p n) n (setf n (gethash n *notes*))))) (unless note (error "~A is not a note or note name." n)) (setf (note-disabled note) t) note)) (defun enable-note (n) (let ((note (if (note-p n) n (setf n (gethash n *notes*))))) (unless note (error "~A is not a note or note name." n)) (setf (note-disabled note) nil) note)) ;;; Extended random regression (defun do-extended-tests (&key (tests *passed-tests*) (count nil) ((:catch-errors *catch-errors*) *catch-errors*) ((:compile *compile-tests*) *compile-tests*)) "Execute randomly chosen tests from TESTS until one fails or until COUNT is an integer and that many tests have been executed." (let ((test-vector (coerce tests 'simple-vector))) (let ((n (length test-vector))) (when (= n 0) (error "Must provide at least one test.")) (loop for i from 0 for name = (svref test-vector (random n)) until (eql i count) do (print name) unless (do-test name) return (values name (1+ i)))))) abcl-src-1.9.0/test/lisp/abcl/runtime-class.lisp0100644 0000000 0000000 00000004462 14232261063 020251 0ustar000000000 0000000 (in-package :abcl.test.lisp) ;; method with no arguments (deftest runtime-class.1 (java:jclass-name (java:jnew-runtime-class "Actor" :fields '(("name" "java.lang.String" :getter NIL)) :methods '(("getName" "java.lang.String" NIL (lambda (this) (java:jfield "name" this)))))) "Actor") ;; method with primitive type (deftest runtime-class.2 (java:jclass-name (java:jnew-runtime-class "Actor" :fields '(("name" "java.lang.String" :getter NIL)) :methods '(("getName" "java.lang.String" (:int) (lambda (this x) (declare (ignore x)) (java:jfield "name" this)))))) "Actor") ;; inheritance of type (deftest runtime-class.3 (let ((class-loader (java::make-memory-class-loader))) (java:jnew-runtime-class "foo.Actor" :fields '(("name" "java.lang.String")) :class-loader class-loader) (java:jclass-name (java:jnew-runtime-class "foo.StageActor" :superclass "foo.Actor" :fields '(("givenName" "java.lang.String")) :class-loader class-loader))) "foo.StageActor") ;; constructor (deftest runtime-class.4 (java:jcall "getName" (java:jnew (java:jnew-runtime-class "Actor" :constructors '((("java.lang.String") (lambda (this name) (setf (java:jfield "name" this) name)))) :methods '(("getName" "java.lang.String" NIL (lambda (this) (java:jfield "name" this)))) :fields '(("name" "java.lang.String" :getter NIL))) "Someone")) "Someone") ;; print-object (deftest runtime-class.print-object (subseq (with-output-to-string (stream) (print-object (java:jnew (java:jnew-runtime-class "FooList" :superclass "java.util.AbstractList" :methods '(("get" "java.lang.Object" (:int) (lambda (this index) "Foo")) ("size" :int () (lambda (this) 15))))) stream)) 0 20) "# entries new-entries)) (format t "~&Previously ~A entries, now ~A." entries new-entries)) (setf entries new-entries)))) nil) (deftest weak-hash-table.2 (let* ((ht (make-hash-table :weakness :value)) (entries 0)) (dotimes (i 100000) (setf (gethash (random-object) ht) (random 100000)) (let ((new-entries (sys::hash-table-count ht))) (when (and new-entries (> entries new-entries)) (format t "~&Previously ~A entries, now ~A." entries new-entries)) (setf entries new-entries)))) nil) (deftest weak-hash-table.3 (let* ((ht (make-hash-table :weakness :key-and-value)) (entries 0)) (dotimes (i 100000) (setf (gethash (random-object) ht) (random 100000)) (let ((new-entries (sys::hash-table-count ht))) (when (and new-entries (> entries new-entries)) (format t "~&Previously ~A entries, now ~A." entries new-entries)) (setf entries new-entries)))) nil) (deftest weak-hash-table.4 (let* ((ht (make-hash-table :weakness :key-or-value)) (entries 0)) (dotimes (i 100000) (setf (gethash (random-object) ht) (random 100000)) (let ((new-entries (sys::hash-table-count ht))) (when (and new-entries (> entries new-entries)) (format t "~&Previously ~A entries, now ~A." entries new-entries)) (setf entries new-entries)))) nil) abcl-src-1.9.0/test/lisp/abcl/wild-pathnames.lisp0100644 0000000 0000000 00000003767 14202767264 020422 0ustar000000000 0000000 (in-package :abcl.test.lisp) ;;; Various tests for PATHNAMES :WILD and :WILD-INFERIORS (defvar *test-files* '("foo.ext" "a/b/c/foo.ext" "a/d/e/foo.ext" "b/foo.ext" "a/foo.ext")) (defvar *temp-directory-root* (ext:make-temp-directory)) (defun create-wild-test-hierarchy () (ensure-directories-exist *temp-directory-root*) (dolist (file *test-files*) (let ((file (merge-pathnames file *temp-directory-root*))) (ensure-directories-exist (directory-namestring file)) (unless (probe-file file) (touch file))))) (defun remove-wild-test-hierarchy () (ignore-errors (delete-directory-and-files *temp-directory-root*))) (defmacro with-test-directories (&rest body) `(prog2 (create-wild-test-hierarchy) ,@body (remove-wild-test-hierarchy))) (defun set-equal (a b) (and (= (length a) (length b)) (subsetp a b :test #'equal) (subsetp b a :test #'equal))) (deftest wild-pathnames.1 (with-test-directories (let ((results (directory (merge-pathnames "**/*.ext" *temp-directory-root*))) (expected (loop :for file :in *test-files* :collecting (merge-pathnames file *temp-directory-root*)))) (values (eq (length results) (length expected)) ;; link --> file is not resolved by change in DIRECTORY to :RESOLVE-SYMLINKS nil results expected (set-equal (mapcar #'truename results) (mapcar #'truename expected))))) t) (deftest wild-pathnames.2 (check-namestring (namestring (first (with-test-directories (directory (make-pathname :directory (pathname-directory *temp-directory-root*) :name :wild :type "ext" :version :newest))))) (namestring (merge-pathnames *temp-directory-root* "foo.ext"))) t) abcl-src-1.9.0/test/lisp/abcl/zip.lisp0100644 0000000 0000000 00000001375 14202767264 016300 0ustar000000000 0000000 (in-package #:abcl.test.lisp) (deftest zip.1 (let ((mapping (make-hash-table :test 'equal))) (loop :for (key value) :in `(("/etc/hosts" "/etc/hosts") ("/etc/group" "groups") ("/etc/resolv.conf" "/opt/etc/resolv.conf")) :doing (setf (gethash key mapping) value)) (values (system:zip #p"/var/tmp/foo.jar" mapping) (not (probe-file "jar:file:/var/tmp/foo.jar!/etc/hosts")) (not (probe-file "jar:file:/var/tmp/foo.jar!/groups")) (not (probe-file "jar:file:/var/tmp/foo.jar!/opt/etc/resolv.conf")))) #p"/var/tmp/foo.jar" nil nil nil) (eval-when (:load-toplevel) (if (not (find :unix *features*)) (pushnew 'zip.1 *expected-failures*))) abcl-src-1.9.0/test/lisp/ansi/abcl-ansi.lisp0100644 0000000 0000000 00000006571 14202767264 017363 0ustar000000000 0000000 (in-package :abcl.test.ansi) (defparameter *ansi-tests-master-source-location* "") (defparameter *ansi-tests-directory* (asdf:system-relative-pathname :abcl/test/ansi/compiled "../ansi-test/")) (defun run (&key (compile-tests nil)) "Run the ANSI-TESTS suite, to be found in *ANSI-TESTS-DIRECTORY*. Possibly running the compiled version of the tests if COMPILE-TESTS is non-NIL." (verify-ansi-tests) (mapcar (lambda (result) (when (second result) (format t "~&Removed '~A'.~%" (first result)))) (clean-tests)) (let* ((ansi-tests-directory *ansi-tests-directory*) (boot-file (if compile-tests "compileit.lsp" "doit.lsp")) (message (format nil "Invocation of '~A' in ~A" boot-file ansi-tests-directory))) (progv '(*default-pathname-defaults*) `(,(merge-pathnames *ansi-tests-directory* *default-pathname-defaults*)) (format t "---> ~A begins.~%" message) (format t "Invoking ABCL hosted on ~A ~A.~%" (software-type) (software-version)) (time (load boot-file)) (format t "<--- ~A ends.~%" message)))) (defun verify-ansi-tests () (unless (probe-file *ansi-tests-directory*) (error 'file-error "Failed to find the GCL ANSI tests in '~A'. Please locally obtain ~A, and place it in a sibling directory to the ABCL source named '../ansi-tests/'" *ansi-tests-directory* *ansi-tests-master-source-location*))) (defvar *ansi-tests-loaded-p* nil) (defun load-tests () "Load the ANSI tests but do not execute them." (verify-ansi-tests) (let ((*default-pathname-defaults* *ansi-tests-directory*) (package *package*)) (setf *package* (find-package :cl-user)) (load "gclload1.lsp") (load "gclload2.lsp") (setf *package* package)) (setf *ansi-tests-loaded-p* t)) (defun clean-tests () "Do what 'make clean' would do from the GCL ANSI tests," ;; so we don't have to hunt for 'make' in the PATH on win32. (verify-ansi-tests) (mapcar (lambda (p) (when (probe-file p) (list p (delete-file p)))) (append (directory (format nil "~A/**/*.cls" *ansi-tests-directory*)) (directory (format nil "~A/**/*.abcl" *ansi-tests-directory*)) (directory (format nil "~A/scratch/*" *ansi-tests-directory*)) (mapcar (lambda(x) (format nil "~A/~A" *ansi-tests-directory* x)) '("scratch/" "scratch.txt" "foo.txt" "foo.lsp" "foo.dat" "tmp.txt" "tmp.dat" "tmp2.dat" "temp.dat" "out.class" "file-that-was-renamed.txt" "compile-file-test-lp.lsp" "compile-file-test-lp.out" "ldtest.lsp"))))) ;;; XXX move this into test-utilities.lisp? (defvar *last-run-matching* "bit-vector") (defun do-tests-matching (&optional (match *last-run-matching*)) "Run all tests in suite whose symbol contains MATCH in a case-insensitive manner." (setf *last-run-matching* match) (let* ((matching (string-upcase match)) (count 0) (*default-pathname-defaults* *ansi-tests-directory*)) (mapcar (lambda (entry) (if (search matching (symbol-name (rt::name entry))) (setf (rt::pend entry) t count (1+ count)) (setf (rt::pend entry) nil))) (rest rt::*entries*)) (format t "Performing ~A tests matching '~A'.~%" count matching) (rt::do-entries t))) abcl-src-1.9.0/test/lisp/ansi/ansi-test-failures0100644 0000000 0000000 00000143477 14242627550 020307 0ustar000000000 0000000 ;;;; -*- Mode: LISP; Syntax: COMMON-LISP -*- (doit r12506 :id dada :uname "x64-darwin-10.2.0" :jvm "apple-jdk-1.6.0_17" (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23)) (compileit r12506 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) ; prevent duplicate subclasses ; introduces PRINT.BACKQUOTE.RANDOM.14 ;r12391 781 (doit r12391 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23)) (compileit r12391 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.BACKQUOTE.RANDOM.14 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) ; change output-ugly-object ;r12390 780 ;doit nil (compileit r12390 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) ; changelogs for newest release ;r12383 779 ;doit nil (compileit r12383 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) ;abcl-src-0.18.0 (doit 0.18.0 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23)) (compileit 0.18.0 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) (doit 0.18.1 :id alqaeda :jvm "1.6.0_17-b04" :uname "ia32-winxp-5.1" (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23)) (compileit 0.18.1 :id alqaeda (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) (doit 0.18.1 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.BACKQUOTE.RANDOM.14 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23)) (compileit 0.18.1 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 MAKE-BROADCAST-STREAM.8 PRINT.BACKQUOTE.RANDOM.14 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) (doit r12506 :id jupiter :uname "i386-pc-solaris2.11" :jvm "jdk-1.6.0_13" (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23)) (compileit r12506 :id jupiter (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) (compileit 0.19.0 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 TRACE.8)) (doit 0.19.0 :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32)) (doit 0.19.x :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32)) (compileit 0.19.x :id dada (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 TRACE.8)) (doit 0.19.x :id jupiter (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32)) (compileit 0.19.x :id jupiter (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 TRACE.8)) (doit r12552 :id xp1 :uname "ia32-winnt-5.1" :jvm "sun-jdk-1.6.0_18" (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3)) (compileit r12552 :id xp1 (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 TRACE.8)) (doit 0.19.x :id xp1 (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 PRINT.BACKQUOTE.RANDOM.14 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3)) (compileit 0.19.x :id xp1 (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 TRACE.8)) (doit 0.18.1 :id xp1 (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 WITH-STANDARD-IO-SYNTAX.23)) (compileit 0.18.1 :id xp1 (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 ENSURE-DIRECTORIES-EXIST.8 MAKE-BROADCAST-STREAM.8 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 WITH-STANDARD-IO-SYNTAX.23 TRACE.8)) (doit 0.25.0 :id saturn :uname "i386-pc-solaris2.11.oi_148" :jvm "jdk-1.6.0_25" (DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-PATHNAME.9 ENSURE-DIRECTORIES-EXIST.8 PRINT.SYMBOL.RANDOM.2 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 COMPILE-FILE.16)) (compileit 0.25.0 :id saturn :uname "i386-pc-solaris2.11.oi_148" :jvm "jdk-1.6.0_25" (MULTIPLE-VALUE-PROG1.10 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-PATHNAME.9 ENSURE-DIRECTORIES-EXIST.8 PRINT.SYMBOL.RANDOM.2 PRINT.SYMBOL.RANDOM.4 PRINT.STRING.RANDOM.1 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 COMPILE-FILE.16 TRACE.8)) (doit 0.26.1 :id saturn (DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 PRINT.STRING.RANDOM.1 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17)) (compileit 0.26.1 :id saturn (MULTIPLE-VALUE-PROG1.10 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 PRINT.SYMBOL.RANDOM.3 PRINT.SYMBOL.RANDOM.4 PRINT.STRING.RANDOM.1 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) (doit 0.27.0-dev-13415 :id saturn (DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17)) (compileit 0.27.0-dev-13415 :id saturn (MULTIPLE-VALUE-PROG1.10 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) (doit 0.27.0-dev-r13420 :id saturn-java7 (DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 PRINT.SYMBOL.RANDOM.2 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17)) (compileit 0.27.0-dev-r13420 :id saturn-java7 (MULTIPLE-VALUE-PROG1.10 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 PRINT.SYMBOL.RANDOM.2 PRINT.SYMBOL.RANDOM.3 PRINT.STRING.RANDOM.1 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) (doit 1.0.1 :id saturn-java6 :uname "i386-pc-solaris2.11.oi_151a7" :jvm "jdk-1.6.0_37" (DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 READ-SYMBOL.22)) (compileit 1.0.1 :id saturn-java6 (DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 READ-SYMBOL.22 TRACE.8)) (doit r14249 :id saturn-java6 (PSETF.37 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.BACKQUOTE.RANDOM.14 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 COMPILE-FILE.2 COMPILE-FILE.2A)) (compileit r14249 :id saturn-java6 (PSETF.37 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 COMPILE-FILE.2 COMPILE-FILE.2A TRACE.8)) ;;13 out of 21707 total tests failed: (doit abcl-1.1.0-rc-0 :id saturn-java6 (PSETF.37 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17)) ;;15 out of 21707 total tests failed: (compileit abcl-1.1.0-rc-0 :id saturn-java6 (PSETF.37 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.BACKQUOTE.RANDOM.14 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;;13 out of 21707 total tests failed: (compileit abcl-1.1.1 :id saturn-java6 (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;; 12 out of 21707 total tests failed: (doit abcl-1.1.1 :id saturn-java6 (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17)) ;; 14 out of 21707 total tests failed: (compileit abcl-1.2.1-rc-0 :id saturn-java6 (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 LOAD.18 TRACE.8)) ;; 13 out of 21707 total tests failed: (doit abcl-1.2.1-rc-0 :id saturn-java6 (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 LOAD.18)) ;;14 out of 21707 total tests failed: (compileit abcl-1.2.1-rc-2 :id saturn-java7 (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;;12 out of 21707 total tests failed: (compileit abcl-1.2.1-rc-2 :id saturn-java7 :uname "i386-pc-solaris2.11" :jvm "jdk-1.7.0_25" (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;;630.139 seconds real time ;;3868350 cons cells ;;18 out of 21707 total tests failed: (compileit abcl-1.3.0-dev :id quoth ;; :lisp-implementation-version ("1.3.0-dev" ;; "Java_HotSpot(TM)_64-Bit_Server_VM-Oracle_Corporation-1.7.0_45-b18" ;; "x86_64-Mac_OS_X-10.9") (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;;20 out of 21707 total tests failed: (doit abcl-1.3.0-dev :id quoth ;; 1087.598 seconds real time 6642141 cons cells 1102.029 seconds real time 6642326 cons cells (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.SYMBOL.RANDOM.3 PRINT.SYMBOL.RANDOM.4 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;;13 out of 21707 total tests failed: (compileit abcl-1.3.0-dev :id quoth ;; 1123.95 seconds real time 6390199 cons cells 1163.923 seconds real time 6390343 cons cells (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;;;;12 out of 21707 total tests failed: ;;;828.563 seconds real time 16771547 cons cells 858.546 seconds real time 16771826 cons cells (doit abcl-1.3.0-dev :id quoth (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17)) ;;13 out of 21707 total tests failed: (compileit abcl-1.3.1-rc-0 :id illin (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8) ) ;;453.45 seconds real time 6389761 cons cells ;;462.761 seconds real time ;;6389826 cons cells ;; 19 out of 21707 total tests failed: (compileit abcl-r14750 :id illin (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;;20 out of 21707 total tests failed (doit abcl-r14750 :id illin (CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 MAP.48 TYPE-OF.1 TYPE-OF.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.SYMBOL.RANDOM.4 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 TRACE.8)) ;;; Results which follow this line use "different" ANSI tests from ;;; above, so are no longer strictly comparable. Future versions of ;;; this database should include ansi-test revisions ;;; Tests below this line use the last version of the ansi tests ;;; before directory reorganization, as versions of abcl prior to ;;; changeset svn-r14783 fail as they are unable to invoke ;;; FILE-WRITE-DATE on a logical pathname. #| The hg revision corresponds to a repository that is the results of using the hg-git Mercurial bridge. hg: 2150:22f411f1c69fef712c5e6ebfacd1dea00b62bada git: 8412195bfb681da255b79806b97990cf0d3c1ed3 2015-08-19 19:09 +0200 Daniel Kochmański ctypecase: fix invalid tests (constant assignment) |# ;; 35 out of 21727 total tests failed (compileit abcl-1.3.3-dev-r14797 :id illin-jdk1.8.0_60 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 DEFPACKAGE.2B MAP.48 TYPE-OF.1 TYPE-OF.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 TRACE.8)) ;; 37 out of 21727 total tests failed (compileit abcl-1.4.0-dev-r14793 :id illin-jdk1.8.0_60 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 DEFPACKAGE.2B MAP.48 TYPE-OF.1 TYPE-OF.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 FORMAT.C.2A FORMATTER.C.2A FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 TRACE.8)) ;; 46 out of 21738 total tests failed: #| URL: svn+ssh://mevenson@abcl.org/project/armedbear/svn/trunk/abcl Repository Root: svn+ssh://mevenson@abcl.org/project/armedbear/svn Repository UUID: 1c010e3e-69d0-11dd-93a8-456734b0d56f Revision: 14868 Node Kind: directory Last Changed Author: mevenson Last Changed Rev: 14868 Last Changed Date: 2016-09-04 12:54:18 +0000 (Sun, 04 Sep 2016) |# (compileit abcl-1.4.0-dev-14868 :id quoth-jdk1.8.0_102 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 DEFPACKAGE.2B MAP.48 TYPE-OF.1 TYPE-OF.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 PEEK-CHAR.18 PEEK-CHAR.19 FILE-POSITION.10 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.5 TRACE.8 DECODE-UNIVERSAL-TIME.3 DECODE-UNIVERSAL-TIME.4 DECODE-UNIVERSAL-TIME.5 ENCODE-UNIVERSAL-TIME.1 ENCODE-UNIVERSAL-TIME.3)) ;;47 unexpected failures (compileit abcl-1.4.0-dev-14885 :id quoth-jdk1.8.0_102 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 SXHASH.8 DEFPACKAGE.2B MAP.48 TYPE-OF.1 TYPE-OF.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 PEEK-CHAR.18 PEEK-CHAR.19 FILE-POSITION.10 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PRINT-STRUCTURE.1 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.5 TRACE.8 DECODE-UNIVERSAL-TIME.3 DECODE-UNIVERSAL-TIME.4 DECODE-UNIVERSAL-TIME.5 ENCODE-UNIVERSAL-TIME.1 ENCODE-UNIVERSAL-TIME.3)) ;; 50 failures (compileit abcl-1.5.0-dev-svn-r14953 :id quoth-jdk1.8.0_112 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 PEEK-CHAR.18 PEEK-CHAR.19 FILE-POSITION.10 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.9 DISASSEMBLE.10 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.3 DECODE-UNIVERSAL-TIME.4 ENCODE-UNIVERSAL-TIME.1 ENCODE-UNIVERSAL-TIME.3)) (compileit abcl-1.5.0-dev-20170330a :id quoth-jdk1.8.0_121 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 PEEK-CHAR.18 PEEK-CHAR.19 FILE-POSITION.10 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.3 DECODE-UNIVERSAL-TIME.4 DECODE-UNIVERSAL-TIME.5 ENCODE-UNIVERSAL-TIME.1 ENCODE-UNIVERSAL-TIME.3)) ;; 46 failures (compileit abcl-1.5.0-dev-20170417a :id quoth-jdk1.8.0_121 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 PEEK-CHAR.18 PEEK-CHAR.19 FILE-POSITION.10 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PRINT-STRUCTURE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.5)) ;;; 293.016 seconds real time ;;; 4021046 cons cells ;;; ; Loaded /usr/home/evenson/work/ansi-test/compileit.lsp (305.351 seconds) ;;; 305.372 seconds real time ;;; 4021137 cons cells ;;46 out of 21748 total tests failed: (compileit abcl-1.5.0-dev-20170703a :id quoth-jdk-1.8.0_131-b11 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B MAP.48 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 PEEK-CHAR.18 PEEK-CHAR.19 FILE-POSITION.10 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PRINT-STRUCTURE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.5)) ;;403.568 seconds real time ;;6651799 cons cells ; Loaded /usr/home/evenson/work/ansi-test/compileit.lsp (416.414 seconds) ;;416.415 seconds real time ;;6651863 cons cells ;; 51 out of 21776 total tests failed: (compileit abcl-1.6.0-dev-20180128a :id oxi-jdk-1.8.0_152 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 PEEK-CHAR.18 PEEK-CHAR.19 FILE-POSITION.10 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 MAKE-CONCATENATED-STREAM.30 PRINT.RANDOM-STATE.1 PRINT-STRUCTURE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.5)) ;; 800.151 seconds real time ;; 6635189 cons cells ;; 811.741 seconds real time ;; 55 failures (compileit abcl-1.6.0-dev-20190111a :uname "amd64-FreeBSD-12.0-RELEASE-p10" :jvm "OpenJDK_64-Bit_Server_VM-Oracle_Corporation-11.0.5+10-1" :id oxi-java11 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 PRINT.RANDOM-STATE.1 PRINT-STRUCTURE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.6 FORMAT.E.20 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.5)) ;; 55 out of 21836 total tests failed: (compileit abcl-1.6.0-dev-20190111a :uname "amd64-FreeBSD-12.0-RELEASE-p10" :vm "OpenJDK_64-Bit_Server_VM-Oracle_Corporation-1.8.0_232-b09" :id oxi-java8 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 PRINT.RANDOM-STATE.1 PRINT-STRUCTURE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.6 FORMAT.E.20 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.5)) (compileit abcl-1.6.0-dev-20191105a :id oxi-java8 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 LOGICAL-PATHNAME.3 DIRECTORY.8 ENSURE-DIRECTORIES-EXIST.8 RENAME-FILE.5 DELETE-FILE.3 DELETE-FILE.4 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 OPEN.64 OPEN.OUTPUT.3 OPEN.IO.3 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 PRINT.RANDOM-STATE.1 PRINT-STRUCTURE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.6 FORMAT.E.20 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 COMPILE-FILE.17 COMPILE-FILE.18 LOAD.19 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.5)) ;; ;; 46 out of 21852 total tests failed (compileit abcl-1.6.2-dev-20200516a :id travis-linux-openjdk8 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 PRINT.BACKQUOTE.RANDOM.14 PRINT.RANDOM-STATE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.6 FORMAT.E.20 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8)) (compileit abcl-1.7.2-dev-20201001a (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 LOOP.8.10 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 PRINT.RANDOM-STATE.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.6 FORMAT.E.20 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.5)) (compileit abcl-1.7.2-dev-20201013a :id oxi (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 LOOP.8.10 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 PATHNAMES-PRINT-AND-READ-PROPERLY MERGE-PATHNAMES.7A ENSURE-DIRECTORIES-EXIST.8 READ-BYTE.ERROR.5 WRITE-BYTE.ERROR.4 CLEAR-INPUT.ERROR.5 FINISH-OUTPUT.ERROR.3 FORCE-OUTPUT.ERROR.3 CLEAR-OUTPUT.ERROR.3 PRINT.RANDOM-STATE.1 PRINT.PATHNAME.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.6 FORMAT.E.20 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 LOAD.18 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8 DECODE-UNIVERSAL-TIME.5)) ;; 61 out of 21854 total tests failed: (compileit abcl-1.8.0-rc-20201025a (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 LOOP.8.10 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 PATHNAMES-PRINT-AND-READ-PROPERLY LOGICAL-PATHNAME.3 DIRECTORY.8 TRUENAME.5 RENAME-FILE.5 DELETE-FILE.3 DELETE-FILE.4 OPEN.64 OPEN.OUTPUT.3 OPEN.IO.3 PRINT.RANDOM-STATE.1 PRINT.PATHNAME.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.6 FORMAT.E.20 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 COMPILE-FILE.17 COMPILE-FILE.18 LOAD.18 LOAD.19 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8)) ;;49 out of 21854 total tests failed: (compileit abcl-1.8.0-rc-10 (SHIFTF.7 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 LOOP.8.10 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 PATHNAMES-PRINT-AND-READ-PROPERLY LOGICAL-PATHNAME.3 PRINT.RANDOM-STATE.1 PRINT.PATHNAME.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.6 FORMAT.E.20 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8)) ;; 62 out of 21870 total tests failed ;;test (ubuntu-latest, openjdk17) (compileit abcl-1.9.0-rc-2 :uname "x64-ubuntu-latest" :jvm "adoptium-openjdk-Java 17 Eclipse Adoptium" :id "openjdk17/github.com/ubuntu-latest" (SHIFTF.7 LABELS.37 LABELS.38 LABELS.39 LOOP.1.40 LOOP.1.41 LOOP.1.42 LOOP.1.43 LOOP.8.10 MAKE-LOAD-FORM.ORDER.3 MAKE-LOAD-FORM.ORDER.4 MAKE-LOAD-FORM.ORDER.5 MAKE-LOAD-FORM.ORDER.6 MAKE-LOAD-FORM.ORDER.7 MAKE-LOAD-FORM.ORDER.8 MAKE-LOAD-FORM.ORDER.9 MAKE-LOAD-FORM.ORDER.10 MAKE-LOAD-FORM.ORDER.11 MAKE-LOAD-FORM.ORDER.12 MAKE-LOAD-FORM.ORDER.13 MAKE-LOAD-FORM.ORDER.14 DEFGENERIC.ERROR.1 DEFGENERIC.ERROR.2 DEFGENERIC.ERROR.3 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 MAKE-CONDITION.3 MAKE-CONDITION.4 DEFPACKAGE.2B EXPT.29 MAP.48 DEFSTRUCT.ERROR.3 DEFSTRUCT.ERROR.4 TYPE-OF.1 TYPE-OF.4 PATHNAMES-PRINT-AND-READ-PROPERLY LOGICAL-PATHNAME.3 PARSE-NAMESTRING.5 PRINT.PATHNAME.1 PPRINT-FILL.2 PPRINT-LINEAR.2 PPRINT-TABULAR.2 PPRINT-LOGICAL-BLOCK.17 FORMAT.F.5 FORMAT.F.8 FORMAT.F.45 FORMATTER.F.45 FORMAT.F.46 FORMATTER.F.46 FORMAT.F.46B FORMATTER.F.46B FORMAT.F.47 FORMATTER.F.47 FORMAT.E.1 FORMAT.E.2 FORMAT.E.3 FORMAT.E.26 SYNTAX.SHARP-COLON.ERROR.1 APROPOS.ERROR.2 APROPOS-LIST.ERROR.2 DISASSEMBLE.ERROR.3 TRACE.8)) abcl-src-1.9.0/test/lisp/ansi/packages.lisp0100644 0000000 0000000 00000001241 14202767264 017275 0ustar000000000 0000000 (defpackage #:abcl.test.ansi (:use :cl :cl-user) (:nicknames #:ansi-tests #:abcl-ansi-tests #:gcl-ansi #:abcl/test/ansi) (:export #:run #:difference #:verify-ansi-tests #:do-tests-matching #:load-tests #:clean-tests #:full-report #:report #:parse) ;; This should be REGRESSION-TEST included with the ANSI-TESTS, but ;; it is possible that the user may have included a slightly ;; different version from say Quicklisp. (:import-from #:rt #:pend #:name #:*entries* #:do-test #:do-tests #:do-entries)) abcl-src-1.9.0/test/lisp/ansi/parse-ansi-errors.lisp0100644 0000000 0000000 00000020643 14202767264 021102 0ustar000000000 0000000 ;;;; $Id$ ;;;; ;;;; Parse ANSI test results from a s-expr database, allowing queries ;;;; to show differences. ;;;; ;;;; 'cuz I get lost after comparing about five items in a list ;;;; #| To use 1. Create a "database" of test results consisting of s-exps. A default database is in 'failures'. The s-exprs have the form: (compileit|doit :id [: ] ()) where compileit|doit The symbol 'compileit' or 'doit' depending on whether the compiled or interpreted tests were run. version A symbol identifying the version of source of the tests (i.e. r12506 or 0.18.0) :id is a symbol identifying the environment for the tests :key Additional key-value pairs The list of symbols failing the tests. An example on an entry: (doit r12506 :id jupiter :uname "i386-pc-solaris2.11" :jvm "jdk-1.6.0_13" (REINITIALIZE-INSTANCE.ERROR.1 DEFGENERIC.ERROR.20 DEFGENERIC.ERROR.21 DEFGENERIC.30 CALL-NEXT-METHOD.ERROR.1 CALL-NEXT-METHOD.ERROR.2 DEFMETHOD.ERROR.14 DEFMETHOD.ERROR.15 INVOKE-DEBUGGER.1 MAKE-CONDITION.3 MAKE-CONDITION.4 DELETE-PACKAGE.5 DELETE-PACKAGE.6 MAP.48 TYPE-OF.1 TYPE-OF.4 CHAR-UPCASE.2 CHAR-DOWNCASE.2 FRESH-LINE.5 PRINT.RANDOM-STATE.1 PPRINT-FILL.14 PPRINT-FILL.15 PPRINT-LINEAR.14 PPRINT-TABULAR.13 PPRINT-LOGICAL-BLOCK.17 PPRINT-POP.7 PPRINT-POP.8 FORMAT.LOGICAL-BLOCK.CIRCLE.1 FORMAT.LOGICAL-BLOCK.CIRCLE.2 FORMAT.LOGICAL-BLOCK.CIRCLE.3 FORMAT.JUSTIFY.30 FORMAT.JUSTIFY.32 WITH-STANDARD-IO-SYNTAX.23)) 2. Run (PARSE []) on the file of your database. Without an argument, the default database is read. 3. Then differences between versions can be queried via REPORT CL-USER> (REPORT 'compileit '0.18.0 'r13590) |# (in-package :abcl.test.ansi) (defvar *doit* (make-hash-table)) (defvar *compileit* (make-hash-table)) (defvar *id* (make-hash-table)) (defun reset () (clrhash *doit*) (clrhash *compileit*) (clrhash *id*)) (defun get-hash-table (test) (let ((name (symbol-name test))) (when (string-equal name "doit") (return-from get-hash-table *doit*)) (when (string-equal name "compileit") (return-from get-hash-table *compileit*)))) (defvar *default-database-file* (asdf:system-relative-pathname :abcl "test/lisp/ansi/ansi-test-failures")) (defun parse (&optional (file *default-database-file*)) "Parse the ansi test database present at *DEFAULT-DATABASE-FILE*. Optionally the file to parse may be specified by the FILE argument." (format t "Parsing test report database from ~A~%" *default-database-file*) (with-open-file (s file :direction :input) (do ((form (read s) (read s nil nil))) ((null form)) (destructuring-bind (test version &rest rest) form (let ((args) (failures) (id)) (dolist (arg rest) (if (typep arg 'cons) (setf failures arg) (push arg args))) (setf args (nreverse args)) (unless (getf args :id) (push 'noid args) (push :id args)) (setf id (getf args :id)) (unless (gethash version (get-hash-table test)) (setf (gethash version (get-hash-table test)) (make-hash-table))) (if (> (length args) 2) (setf (gethash id *id*) args) (if (null (gethash id *id*)) (setf (gethash id *id*) args))) (setf (gethash id (gethash version (get-hash-table test))) failures)))))) (defun versions (test) (loop :for key :being :the :hash-keys :of (get-hash-table test) :collecting key)) (defun report-versions (&optional (test 'compileit)) (format t "~A has the following versions:~%~A~%" test (versions test)) (values)) (defun get-failures (test version) (gethash version (get-hash-table test))) (defun difference (failures-1 failures-2) "Report the set-difference between the lists of FAILURES-1 and FAILURES-2" (list (list (length failures-1) (set-difference failures-1 failures-2)) (list (length failures-2) (set-difference failures-2 failures-1)))) (defun generate-report (test version-1 version-2) (flet ((list-results (hash-table) (loop :for key :being :the :hash-key :of hash-table :using (:hash-value value) :collecting (list key value)))) (let ((entries-1 (list-results (get-failures test version-1))) (entries-2 (list-results (get-failures test version-2)))) (loop :for (id-1 failure-1) :in entries-1 :appending (loop :for (id-2 failure-2) :in entries-2 :collecting (list (cons id-1 id-2) (difference failure-1 failure-2))))))) (defun deprecated/report (test version-1 version-2) (report version-1 version-2 :test test)) (defun report (version-1 version-2 &key (test 'compileit)) "Report on the difference of test failures for TEST between VERSION-1 and VERSION-2. TEST is symbol with a value of 'DOIT specifying the interpreted version of the tests, or 'COMPILEIT specifiying the compiled verision of the tests. VERSION-1 and VERSION-2 are symbols of two versions contained in the test database." (let ((reports (generate-report test version-1 version-2))) (dolist (report reports) (destructuring-bind ((id1 . id2) ((total-failures1 diff-1->2) (total-failures2 diff-2->1))) report (when diff-1->2 (format t "~A[~A] --> ~A[~A] additional failures:~%~A~%" version-1 id1 version-2 id2 diff-1->2)) (when diff-2->1 (format t "~A[~A] --> ~A[~A] additional failures:~%~A~%" version-2 id2 version-1 id1 diff-2->1)))))) (defun full-report (version-1 version-2) (let ((interpreted-reports (generate-report 'doit version-1 version-2)) (compiled-reports (generate-report 'compileit version-1 version-2))) (dolist (interpreted interpreted-reports) (destructuring-bind ((id1 . id2) ((total-failures1 diff-1->2) (total-failures2 diff-2->1))) interpreted (format t "~2&Interpreted~%") (format t "~&~20<~A-~A~>~20<~A-~A~>" id1 version-1 id2 version-2) (format t "~&~20<~A failures~>~20<~A failures~>" total-failures1 total-failures2) (format t "~&~A-~A:~& ~A" id1 version-1 diff-1->2) (format t "~&~A-~A:~& ~A" id2 version-2 diff-2->1))) (dolist (compiled compiled-reports) (destructuring-bind ((id1 . id2) ((total-failures1 diff-1->2) (total-failures2 diff-2->1))) compiled (format t "~2&Compiled~%") (format t "~&~20<~A-~A~>~20<~A-~A~>" id1 version-1 id2 version-2) (format t "~&~20<~A failures~>~20<~A failures~>" total-failures1 total-failures2) (format t "~&~A-~A:~& ~A" id1 version-1 diff-1->2) (format t "~&~A-~A:~& ~A" id2 version-2 diff-2->1))))) (defun report-compiled (version-1 version-2) (let ((compiled-reports (generate-report 'compileit version-1 version-2))) (dolist (interpreted interpreted-reports) (destructuring-bind ((id1 . id2) ((total-failures1 diff-1->2) (total-failures2 diff-2->1))) interpreted (format t "~2&Interpreted~%") (format t "~&~20<~A-~A~>~20<~A-~A~>" id1 version-1 id2 version-2) (format t "~&~20<~A failures~>~20<~A failures~>" total-failures1 total-failures2) (format t "~&~A-~A:~& ~A" id1 version-1 diff-1->2) (format t "~&~A-~A:~& ~A" id2 version-2 diff-2->1))) (dolist (compiled compiled-reports) (destructuring-bind ((id1 . id2) ((total-failures1 diff-1->2) (total-failures2 diff-2->1))) compiled (format t "~2&Compiled~%") (format t "~&~20<~A-~A~>~20<~A-~A~>" id1 version-1 id2 version-2) (format t "~&~20<~A failures~>~20<~A failures~>" total-failures1 total-failures2) (format t "~&~A-~A:~& ~A" id1 version-1 diff-1->2) (format t "~&~A-~A:~& ~A" id2 version-2 diff-2->1))))) abcl-src-1.9.0/test/lisp/ansi/slime-ansi.el0100644 0000000 0000000 00000000577 14202767264 017224 0ustar000000000 0000000 (defun copy-previous-ansi-failures () "From the SLIME REPL buffer, copy the previous ANSI error report to kill ring." (interactive) (save-excursion (unless (search-backward "<--- Invocation of ") (error "Failed to find end of test invocation")) (previous-line 4) (let ((end (point))) (backward-sexp) (copy-region-as-kill (point) end)))) abcl-src-1.9.0/test/lisp/cl-bench/wrapper.lisp0100644 0000000 0000000 00000005463 14202767264 017732 0ustar000000000 0000000 (defpackage :abcl.test.cl-bench (:use :cl :asdf) (:nicknames "CL-BENCH") (:export #:run)) (in-package :abcl.test.cl-bench) (defparameter *cl-bench-master-source-location* "") ;;; Deprecated. Use ASDF to locate CL-BENCH source (defparameter *cl-bench-directory* (asdf:system-relative-pathname :abcl "../cl-bench/")) ;;; cl-bench defines BENCH-GC and WITH-SPAWNED-THREAD in ;;; '*cl-bench-directory*/sysdep/setup-ablisp.lisp'. (defun cl-bench::bench-gc () (ext:gc)) (defmacro cl-bench::with-spawned-thread (&body body) `(progn ,@body)) (defun add-to-asdf (directory &key (asdf-conf-file "cl-bench.conf")) (let* ((source-registry.conf.d (merge-pathnames ".config/common-lisp/source-registry.conf.d/" (user-homedir-pathname))) (asdf-conf (merge-pathnames asdf-conf-file source-registry.conf.d))) (unless (probe-file source-registry.conf.d) (ensure-directories-exist source-registry.conf.d)) (when (probe-file asdf-conf) (format *standard-output* "Overwriting existing ~a" asdf-conf)) (with-open-file (o asdf-conf :direction :output :if-exists :supersede) (write `(:directory ,directory) :stream o)) (format *standard-output* "Configured ASDF via ~%~t~a~% to search~%~t'~a'~%" asdf-conf directory))) (defun run () (unless (ignore-errors (asdf:find-system :cl-bench)) (if (probe-file *cl-bench-directory*) (when (probe-file (merge-pathnames "cl-bench.asd" *cl-bench-directory*)) (add-to-asdf *cl-bench-directory*) (asdf/source-registry:initialize-source-registry) (unless (ignore-errors (asdf:find-system :cl-bench)) (error "Failed to configure ASDF to find CL-BENCH in ~a" *cl-bench-directory*))) (error "Please download and install a newer version of CL-BENCH containing an ASDF definition in ~a from ~a" *cl-bench-directory* *cl-bench-master-source-location*))) (ql:quickload :cl-bench) (uiop:symbol-call :cl-bench :bench-run)) ;;; Deprecated running CL-BENCH without ASDF definition. (defun old-run () (unless (probe-file *cl-bench-directory*) (error "Failed to find the cl-bench test suite in '~A'.~% Please manually download and extract the cl-bench tool suite~% from ~A to run the tests." *cl-bench-directory* *cl-bench-master-source-location*)) (let ((*default-pathname-defaults* *cl-bench-directory*)) (if (find :unix *features*) (run-shell-command (format nil "cd ~A; make clean optimize-files" *cl-bench-directory*)) (run-shell-command "cd ~A && make clean optimize-files" *cl-bench-directory*)) (load "generate.lisp") (load "do-compilation-script.lisp") (load "do-execute-script.lisp"))) abcl-src-1.9.0/test/src/org/abcl/util/StreamTaskTest.java0100644 0000000 0000000 00000002250 14202767264 021743 0ustar000000000 0000000 /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.abcl.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author evenson */ public class StreamTaskTest { public StreamTaskTest() { } @BeforeClass public static void setUpClass() { } @AfterClass public static void tearDownClass() { } @Before public void setUp() { } @After public void tearDown() { } /** * Test of run method, of class StreamTask. */ @Test public void testRun() { System.out.println("run"); byte inputBytes[] = {65, 66, 66, 90} ; ByteArrayInputStream input = new ByteArrayInputStream(inputBytes); ByteArrayOutputStream output = new ByteArrayOutputStream(); StreamTask instance = new StreamTask(input, output); instance.run(); assertArrayEquals(inputBytes, output.toByteArray()); } } abcl-src-1.9.0/test/src/org/armedbear/lisp/JarPathnameTest.java0100644 0000000 0000000 00000010324 14202767264 023073 0ustar000000000 0000000 package org.armedbear.lisp; import java.util.List; import java.text.MessageFormat; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class JarPathnameTest { @Test public void enumerate1() { String s = "jar:jar:file:/a/foo.jar!/b/baz.abcl!/path/c.lisp"; List r = JarPathname.enumerate(s); assertTrue("3 results", r.size() == 3); String parts[] = { "file:/a/foo.jar", "b/baz.abcl!/", "/path/c.lisp" }; for (int i = 0; i < parts.length; i++) { assertTrue(parts[i], r.get(i).equals(parts[i])); } } @Test public void enumerate2() { String s = "jar:jar:file:/a/foo.jar!/b/baz.abcl!/"; List r = JarPathname.enumerate(s); assertTrue("2 results", r.size() == 2); String parts[] = { "file:/a/foo.jar", "b/baz.abcl!/" }; for (int i = 0; i < parts.length; i++) { assertTrue(parts[i], r.get(i).equals(parts[i])); } } @Test public void enumerate3() { String s = "jar:jar:https://example.com/a/foo.jar!/b/baz.abcl!/path/c.lisp"; List r = JarPathname.enumerate(s); assertTrue("3 results", r.size() == 3); String parts[] = { "https://example.com/a/foo.jar", "b/baz.abcl!/", "/path/c.lisp" }; for (int i = 0; i < parts.length; i++) { assertTrue(parts[i], r.get(i).equals(parts[i])); } } @Test public void enumerate4() { String s = "jar:jar:jar:file:/a/foo.jar!/b/baz.abcl!/log4j.jar!/MF/manifest.mf"; List r = JarPathname.enumerate(s); assertTrue("4 results", r.size() == 4); String parts[] = { "file:/a/foo.jar", "b/baz.abcl!/", "log4j.jar!/", "/MF/manifest.mf" }; for (int i = 0; i < parts.length; i++) { assertTrue(parts[i], r.get(i).equals(parts[i])); } } @Test public void roundTrips() { String namestrings[] = { "jar:file:///foo.jar!/", "jar:jar:file:///foo.jar!/baz.abcl!/", "jar:jar:file:///foo.jar!/baz.abcl!/__loader__._", "jar:jar:jar:file:///a/b/foo.jar!/c/baz.zip!/log4j.jar!/MF/manifest.mf", "jar:https://abcl.org/releases/1.7.1/abcl-contrib.jar!/" }; for (String namestring : namestrings) { Pathname result = (Pathname) Pathname.create(namestring); String resultingNamestring = result.getNamestring(); String message = MessageFormat.format("Namestring \"{0}\" failed to roundtrip", namestring); assertTrue(message, namestring.equals(resultingNamestring)); } } @Test public void invalidNamestrings() { String namestrings[] = { "jar:file:foo.jar!/", "jar:file:foo.jar!/baz.abcl!/", "jar:jar:file:foo.jar!/baz.abcl!/__loader__._", "jar:file:foo.jar!/baz.abcl!/__loader__._", "jar:jar:file:foo.jar!/baz.abcl!/", "jar:jar:jar:file:a/b/foo.jar!/c/baz.zip!/log4j.jar!/MF/manifest.mf" }; // JUnit 4.12 (which is what is available in Netbeans 12) doesn't // have an assertion about throwing an error. for (String namestring : namestrings) { try { Pathname.create(namestring); } catch (Throwable t) { String message = MessageFormat.format("Namestring \"{0}\" is invalid throwing: {1}", namestring, t.getCause()); assertTrue(message, true); } } } @Test public void makePathname() { String urlString = "https://abcl.org/releases/1.7.1/abcl-contrib.jar"; URLPathname urlPathname = URLPathname.create(urlString); LispObject args[] = {Keyword.DEVICE, Lisp.list(urlPathname)}; LispObject result = Symbol.MAKE_PATHNAME.execute(args); assertTrue("MAKE-PATHNAME created instance of a JAR-PATHNAME", result instanceof JarPathname); String expectedNamestring = MessageFormat.format("jar:{0}!/", urlString); String resultingNamestring = ((JarPathname)result).getNamestring(); assertTrue(MessageFormat.format("Namestring '{0}' is '{1}'", expectedNamestring, resultingNamestring), expectedNamestring.equals(resultingNamestring)); } } abcl-src-1.9.0/test/src/org/armedbear/lisp/PathnameTest.java0100644 0000000 0000000 00000011040 14202767264 022432 0ustar000000000 0000000 package org.armedbear.lisp; import java.net.MalformedURLException; import org.junit.Test; import static org.junit.Assert.*; import org.junit.runner.JUnitCore; import java.net.URL; import java.io.File; import java.io.FileWriter; import java.io.InputStream; import java.io.InputStreamReader; import java.io.IOException; public class PathnameTest { public static void main(final String args[]) { JUnitCore.main("org.armedbear.lisp.PathnameTest"); } @Test public void constructorURL() { URL url = null; try { url = new URL("file:///Users/evenson/work/abcl/build/classes/org/armedbear/lisp/boot.lisp"); } catch (MalformedURLException e) { System.out.println(e.getMessage()); } Pathname pathname = (Pathname)URLPathname.create(url); assertNotNull(pathname); assertNotNull(pathname.getNamestring()); assertNotNull(pathname.getName()); assertNotNull(pathname.getType()); assertNotNull(pathname.getDirectory()); } @Test public void getInputStream() throws IOException { File file = File.createTempFile("foo", ".lisp"); FileWriter output = new FileWriter(file); String contents = "(defun foo () 42)"; output.append(contents); output.close(); Pathname pathname = Pathname.makePathname(file); InputStream input = pathname.getInputStream(); InputStreamReader reader = new InputStreamReader(input); char[] buffer = new char[1024]; StringBuilder result = new StringBuilder(); int i; while((i = reader.read(buffer, 0, buffer.length)) != -1) { result.append(buffer, 0, i); } assertEquals(contents, result.toString()); input.close(); file.delete(); } @Test public void copyConstructor() { Pathname orig = (Pathname)Pathname.create("/a/b/c/d/e/foo.lisp"); Pathname copy = (Pathname)Pathname.create(orig.getNamestring()); assertTrue(orig.getNamestring().equals(copy.getNamestring())); } @Test public void mergePathnames1() { Pathname p = (Pathname)Pathname.create("a/b/c/d/foo.lisp"); Pathname d = (Pathname)Pathname.create("/foo/bar/there"); Pathname r = (Pathname)Pathname.mergePathnames(p, d); String s = r.getNamestring(); assertTrue(s.equals("/foo/bar/a/b/c/d/foo.lisp")); } @Test public void mergePathnames2() { Pathname p = (Pathname)Pathname.create("/a/b/c/d/foo.lisp"); Pathname d = (Pathname)Pathname.create("/foo/bar/there"); Pathname r = (Pathname)Pathname.mergePathnames(p, d); assertTrue(r.getNamestring().equals("/a/b/c/d/foo.lisp")); } @Test public void mergePathnames3() { LispObject args = Lisp.NIL; args = args.push(Keyword.TYPE); args = args.push(new SimpleString("abcl-tmp")); args = args.nreverse(); Pathname p = (Pathname)Pathname.makePathname(args); Pathname d = (Pathname)Pathname.create("/foo/bar.abcl"); Pathname r = (Pathname)Pathname.mergePathnames(p, d); assertTrue(r.getNamestring().equals("/foo/bar.abcl-tmp")); } // Currently we disallow construction of relative pathname JARs // @Test // public void mergePathnames4() { // Pathname p = (Pathname)Pathname.create("jar:file:foo.jar!/bar.abcl"); // Pathname d = (Pathname)Pathname.create("/a/b/c/"); // Pathname r = (Pathname)Pathname.mergePathnames(p, d); // String s = r.getNamestring(); // assertTrue(s.equals("jar:file:///a/b/c/foo.jar!/bar.abcl")); // } @Test public void constructorFileDirectory() { Pathname p = (Pathname)Pathname.create("file:///tmp/"); assertTrue(p.getNamestring().endsWith("/")); } @Test public void constructorFileWindowsDevice() { Pathname p = (Pathname)Pathname.create("file:c://tmp/"); LispObject device = p.getDevice(); if (Utilities.isPlatformWindows) { assert(device != Lisp.NIL); } } // Necessary for ASDF output translations to work @Test public void wildInferiorsJars() { String namestring = "jar:file:///**/*.jar!/**/*.*"; Pathname p = (Pathname)Pathname.create(namestring); String parsedNamestring = p.getNamestring(); assertTrue(parsedNamestring.equals(namestring)); } @Test public void equality() { Pathname p1 = (Pathname)Pathname.create("file:///tmp/"); Pathname p2 = (Pathname)Pathname.create("file:///tmp/"); boolean result = p1.equals(p2); assertTrue("Java equals() for Pathname", result); JarPathname p3 = (JarPathname)Pathname.create("jar:file:///abcl.jar!/tmp/"); JarPathname p4 = (JarPathname)Pathname.create("jar:file:///abcl.jar!/tmp/"); result = p3.equals(p4); assertTrue("Java equals() for PathnameJar", result); } } abcl-src-1.9.0/test/src/org/armedbear/lisp/SeekableStringWriterTest.java0100644 0000000 0000000 00000001543 14202767264 025003 0ustar000000000 0000000 package org.armedbear.lisp; import static org.junit.Assert.*; import org.junit.Test; public class SeekableStringWriterTest { @Test public void writeAndSeek() { SeekableStringWriter writer = new SeekableStringWriter(); String buf = "sdf"; writer.append('a').append(buf).append(buf, 1, 2); assertEquals("asdfd", writer.toString()); writer.seek(0); writer.append("meow"); assertEquals("meowd", writer.toString()); } @Test public void writeAndClear() { SeekableStringWriter writer = new SeekableStringWriter(); String buf1 = "empus"; String buf2 = " fugit"; writer.append('t').append(buf1).append(buf2, 1, 7); assertEquals("tempus fugit", writer.toString()); String result = writer.toStringAndClear(); assertEquals("tempus fugit", result); assertEquals("", writer.toString()); } } abcl-src-1.9.0/test/src/org/armedbear/lisp/StreamTest.java0100644 0000000 0000000 00000001642 14202767264 022137 0ustar000000000 0000000 package org.armedbear.lisp; import static org.junit.Assert.*; import java.io.File; import java.io.FileWriter; import org.junit.Test; import java.io.IOException; public class StreamTest { @Test public void readLispObject() { File file = null; try { file = File.createTempFile("foo", "lisp"); FileWriter output = new FileWriter(file); String contents = "(defun foo () 42)"; output.append(contents); output.close(); } catch (IOException e) { System.out.println("Failed to create temp file" + e); return; } Pathname pathname = Pathname.makePathname(file); Stream in = new Stream(Symbol.SYSTEM_STREAM, pathname.getInputStream(), Symbol.CHARACTER); LispObject o = in.read(false, Lisp.EOF, false, LispThread.currentThread(), Stream.currentReadtable); assertFalse(o.equals(Lisp.NIL)); in._close(); file.delete(); } } abcl-src-1.9.0/test/src/org/armedbear/lisp/URLPathnameTest.java0100644 0000000 0000000 00000001467 14202767264 023031 0ustar000000000 0000000 package org.armedbear.lisp; import java.util.List; import java.text.MessageFormat; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class URLPathnameTest { @Test public void roundTrips() { String namestrings[] = { "https://www.youtube.com/user/BlackHatOfficialYT", "file:///a%20path%20/with/whitespace.lisp" }; for (String namestring : namestrings) { URLPathname result = URLPathname.create(namestring); String resultingNamestring = result.getNamestring(); String message = MessageFormat.format("Namestring \"{0}\" failed to roundtrip", namestring); assertTrue(message, namestring.equals(resultingNamestring)); } } } abcl-src-1.9.0/test/src/org/armedbear/lisp/ZipTest.java0100644 0000000 0000000 00000007240 14202767264 021446 0ustar000000000 0000000 package org.armedbear.lisp; import java.io.FileNotFoundException; import static org.junit.Assert.*; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.junit.Before; public class ZipTest { // FIXME These need to be created as part of executing the tests String zipFile = "/Users/evenson/work/abcl/dist/abcl-contrib.jar"; // created via // (require :abcl-contrib) // (asdf:load-system :asdf-jar) // (asdf-jar:package :cl-ppcre) String nestedJarFile = "/var/tmp/cl-ppcre-all-2.1.1.jar"; JarPathname zip; JarPathname nestedJar; @Before public void setup() { zip = (JarPathname) JarPathname.createFromFile(zipFile); nestedJar = (JarPathname) JarPathname.createFromFile(nestedJarFile); } @Test public void getArchive() { ZipCache.Archive archive1 = ZipCache.getArchive(zip); assertTrue("Get ZipArchive from pathname", archive1 instanceof ZipCache.ArchiveFile && ((ZipCache.ArchiveFile)archive1).file != null); JarPathname zip2 = (JarPathname) JarPathname.createFromFile(zipFile); ZipCache.Archive archive2 = ZipCache.getArchive(zip2); assertTrue("Get cached ZipArchive from pathname", archive2 instanceof ZipCache.ArchiveFile && ((ZipCache.ArchiveFile)archive2).file != null); assertTrue("Cached ZipArchive refers to same entry", archive2.equals(archive1)); } @Test public void getEntry() { String entryPath = "abcl-asdf/abcl-asdf-tests.asd"; JarPathname entryPathname = (JarPathname) JarPathname.createEntryFromFile(zipFile, entryPath); ZipEntry entry = ZipCache.getZipEntry(entryPathname); assertTrue("Getting entry from jar", entry.getName().equals(entryPath)); JarPathname entryPathname2 = (JarPathname) JarPathname.createEntryFromFile(zipFile, entryPath); ZipEntry entry2 = ZipCache.getZipEntry(entryPathname2); assertTrue("Cached ZipEntry returns same object", entry.equals(entry2)); } @Test public void getNestedJar() { String nestedNamestring = "jar:jar:file:/var/tmp/cl-ppcre-all-2.1.1.jar!/cl-ppcre/packages.abcl!/"; JarPathname nested = (JarPathname)JarPathname.create(nestedNamestring); ZipCache.Archive archive = ZipCache.getArchive(nested); assertTrue("Able to retrieve nested jar archive", !archive.equals(null)); } // @Test public void getNestedJarEntry() { String nestedNamestring = "jar:jar:file:/var/tmp/cl-ppcre-all-2.1.1.jar!/cl-ppcre/packages.abcl!/__loader__._"; } // @Test // public void getZipEntry() throws FileNotFoundException, IOException { // FileInputStream inputFile = new FileInputStream(zipFile); // ZipInputStream input = new ZipInputStream(inputFile); // ZipEntry entry = ZipCache.getEntry(input, "a/b/bar.abcl"); // assertNotNull(entry); // input.close(); // inputFile.close(); // } // @Test // public void getZipInputStreamZipEntry() throws FileNotFoundException, IOException { // JarFile jar = new JarFile(zipFile); // Pathname pathname = (Pathname)Pathname.create("a/b/bar.abcl"); // InputStream entryInputStream = ZipCache.getInputStream(jar, pathname); // assertNotNull(entryInputStream); // ZipInputStream zip = new ZipInputStream(entryInputStream); // assertNotNull(zip); // ZipEntry entry = ZipCache.getEntry(zip, "bar._"); // assertNotNull(entry); // } } abcl-src-1.9.0/test/src/org/armedbear/lisp/serialization/SerializationTest.java0100644 0000000 0000000 00000005315 14202767264 026377 0ustar000000000 0000000 package org.armedbear.lisp.serialization; import org.armedbear.lisp.*; import java.io.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.lang.reflect.Field; import org.junit.Test; import static org.armedbear.lisp.Lisp.NIL; import static org.armedbear.lisp.Lisp.list; import static org.junit.Assert.*; public class SerializationTest { @Test public void testSerializationOfBuiltInFunction() throws Exception { Field declaredField = Primitives.class.getDeclaredField("CONS"); declaredField.setAccessible(true); Object consFunction = declaredField.get(null); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(consFunction); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); Object readObject = ois.readObject(); assertEquals(readObject, consFunction); } @Test public void testSerializationOfLocalFunction() throws Exception { LispObject lambda_expression = new Cons(Symbol.LAMBDA, new Cons(NIL, NIL)); LispObject lambda_name = list(Symbol.FLET, new Symbol("test")); Closure closure = new Closure(lambda_name, lambda_expression, new Environment()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(closure); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); Object readObject = ois.readObject(); assertTrue(readObject instanceof Closure); assertEquals(NIL, ((Closure) readObject).execute()); } @Test public void testSerializationOfLocalClosure() throws Exception { Symbol symbol = new Symbol("test"); LispObject lambda_expression = new Cons(Symbol.LAMBDA, new Cons(NIL, new Cons(symbol))); LispObject lambda_name = list(Symbol.FLET, new Symbol("test")); Environment env = new Environment(); env.bind(symbol, new SimpleString("OK")); Closure closure = new Closure(lambda_name, lambda_expression, env); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(closure); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); Object readObject = ois.readObject(); assertTrue(readObject instanceof Closure); assertEquals("OK", ((Closure) readObject).execute().toString()); } } abcl-src-1.9.0/test/src/org/armedbear/lisp/util/HttpHeadTest.java0100644 0000000 0000000 00000002506 14202767264 023362 0ustar000000000 0000000 package org.armedbear.lisp.util; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class HttpHeadTest { public HttpHeadTest() { } @BeforeClass public static void setUpClass() { } @AfterClass public static void tearDownClass() { } @Before public void setUp() { } @After public void tearDown() { } @Test public void testGet() { URL url = null; try { url = new URL("http://abcl.org/fasl/42/baz-20140105a-fasl-42.jar"); } catch (MalformedURLException ex) { Logger.getLogger(HttpHeadTest.class.getName()).log(Level.SEVERE, null, ex); } String key = "Last-Modified"; String result = null; try { result = HttpHead.get(url, key); } catch (IOException ex) { Logger.getLogger(HttpHeadTest.class.getName()).log(Level.SEVERE, null, ex); } assertNotNull(result); System.out.println("Last-Modified result was "+ result); } @Test public void testMain() { System.out.println("main"); String[] argv = {"http://google.com/"}; HttpHead.main(argv); } }