I have finally run out of excuses to delay publishing Kea Common Lisp, the compiler for Parrot I've been hacking on for years now. Attached please find a draft of the release announcement and the README.text file it mentions; these should be enough to download it and try it out. For those who are curious enough to do so, I would be grateful for any reports of success or failure (especially failure!) before I annouce Kea-CL to the Lisp community.
Thanks in advance -- and many thanks to the Parrot community in general for making dynamic language implementation (almost) easy! -- Bob Rogers http://rgrjr.dyndns.org/
Subject: [ANNOUNCE] Kea Common Lisp: A Lisp compiler for Parrot Kea Common Lisp is an implementation of ANSI Common Lisp that is based on CMU Common Lisp (see http://www.cons.org/cmucl/) and is targeted to the Parrot bytecode virtual machine (see http://www.parrotcode.org/). Parrot is a VM designed specifically for running dynamic languages in general, and Perl 6 in particular. The chief goal of the Kea Common Lisp project is to provide easy interoperability between Lisp and the other dynamic languages hosted on Parrot. The runtime is incomplete, being at the level of a simple desk calculator with an eccentric syntax, but the cross-compiler already supports most of the core semantic repertoire. The cross-compiler is almost capable of compiling itself; when that happens, EVAL will become suddenly much more powerful, and Kea will be able to grow rapidly. Kea Common Lisp is free sofware, and is licenced under the same terms as Parrot (approximately). See the README.text file (contents appended below) for license details, and for download instructions.
Kea Common Lisp version 0.4.15 Copyright (C) 2005, 2006, 2007, Bob Rogers <[EMAIL PROTECTED]>. All Rights Reserved. Kea Common Lisp is an implementation of ANSI Common Lisp that is based on CMU Common Lisp (see http://www.cons.org/cmucl/) and is targeted to the Parrot bytecode virtual machine (see http://www.parrotcode.org/). LICENSE INFORMATION ------------------- This code is distributed under the same license as Perl 5; you can redistribute it and/or modify it under the terms of either: a) the GNU General Public License as found in the directory "LICENSES", or any later version; or b) the "Artistic License" as be found in the directory "LICENSES", or any later version. So far, this is identical to the Parrot license. However, some source files are derived directly from CMU Common Lisp sources that are in the public domain; these files have headers that clearly mark them as such, and, taken individually, each of these files is still in the public domain. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the Artistic License for more details. PREREQUISITES ------------- Kea Common Lisp works with the current development version of Parrot. See http://www.parrotcode.org/ to find out how to get the current development sources using Subversion. Alternatively, download the Parrot release from CPAN that has the same version number. Parrot, in turn, requires Perl 5.8.x (for some "x" greater than 1), and an ANSI C compiler; both are also used by Kea-CL. Kea Common Lisp has only been tested on Linux/x86, but should in principal run on any platform supported by Parrot. However, makefile tweaks will be necessary to build dynclasses/character.pmc on some non-Linux systems. (Patches welcome.) BUILDING -------- The release tarball is available at: http://rgrjr.dyndns.org/lisp/kea-cl/kea-cl-0.4.15.tgz Building Kea Common Lisp from the tarball is straightforward: 1. Untar and cd into the build directory (kea-cl-0.x.x). 2. Edit the PARROT-HOME macro at the top of the makefile to reflect the location of the Parrot build directory. 3. "make" 4. "make test" There is no "make install" as Kea Common Lisp (like Parrot) can only be run from its build directory. Note that "make" just compiles prepackaged *.imc and *.pir files to *.pbc (i.e. from Parrot assembler to Parrot bytecode). This is because there is not enough runtime support yet for the compiler to run natively on Parrot, so compiling *.lisp files to *.imc requires cross-compilation from a full-blown Common Lisp implementation. For details, see the "REBUILDING FROM SCRATCH" section below. RUNNING ------- After compiling, do parrot kea.pbc to run the Lisp interpreter. The prompt is a "* ". To exit, type an EOF. See below for a summary of implemented functions. Note that there is no DEFUN or even LET; the interpreter is really just a simple desk calculator with an eccentric syntax. REBUILDING FROM SCRATCH ----------------------- Kea Common Lisp consists of five categories of source files (ignoring test scaffolding): 1. Hand-written Parrot Intermediate Representation (PIR) sources; 2. dynclasses/character.pmc, a PMC class definition, which is preprocessed into C and then compiled to a shared object file; 3. A cross-compiler, written in Common Lisp, which compiles a subset of Common Lisp to PIR; 4. Lisp sources compiled by the cross-compiler (listed in the COMPILED-LISP-FILES macro in the makefile); and 5. A few other *.lisp files that are not actually used yet. Categories 1 and 2 are compiled by/with Parrot, and require only a working copy of Parrot and the C compiler you used to compile Parrot. Recompiling the *.lisp files in categories 3 and 4 requires CMU Common Lisp (CMUCL), which only works on flavors of Unix. This release of Kea CL was tested with 19d, but any recent CMUCL version should work just fine. (It used to work with Steel Bank Common Lisp (SBCL) version 0.8.18, but the lexical variable support in r158 broke it, since the lexvar stuff uses more CMUCL internals, and I haven't been able to fix it since.) To recompile the *.lisp files, assuming the Parrot config is still correct, do the following: 1. Adjust the macros in "Lisp config" section of the makefile. They are set up correctly for the default CMUCL install (at least on an x86 machine). 2. "make realclean" (or "make imc-clean"). 3. "make" 4. "make test" 5. "make test-compiler" Typing "make clean" removes all PMC-derived and *.pbc files, restoring the state to that of the distribution tarball; this is sufficient to rebuild after updating Parrot. Typing "make imc-clean" also removes ALL *.imc files that were compiled from *.lisp; in that case, a subsequent "make" will recompile the necessary *.lisp sources. Finally, "make realclean" also gets rid of the cross-compiler binaries. REBUILDING FROM SUBVERSION -------------------------- The Kea-CL Subversion repository (see http://subversion.tigris.org/) is at https://rgrjr.dyndns.org/svn/kea-cl/, and does not require login credentials for read access. To check it out, do svn checkout https://rgrjr.dyndns.org/svn/kea-cl/trunk/ kea-cl cd kea-cl Unlike the release tarball, a fresh working copy does not have the *.imc files produced by the cross-compiler, so you will need to follow the instructions in the "REBUILDING FROM SCRATCH" section above. WHAT'S CURRENTLY IMPLEMENTED ---------------------------- For details on the state of the implementation, see the kea-cl.pod document. See also the TODO.text file for a task list of missing functionality. Here's a summary of the Lisp functions implemented in Kea Common Lisp version 0.4.15. For the most part, full ANSI semantics are supported for these functions, the chief exceptions being the arithmetic functions, FORMAT, multidimensional arrays, readtables, and error handling. (For reference, this represents a bit over a quarter of the symbols defined by the language.) For documentation of individual Lisp functions, please see the Common Lisp HyperSpec at (e.g.) http://www.lispworks.com/documentation/HyperSpec/Front/ . * (&rest args) + (&rest args) - (number &rest more-numbers) / (number &rest more-numbers) /= (number &rest more-numbers) 1+ (number) 1- (number) < (number &rest more-numbers) <= (number &rest more-numbers) = (number &rest more-numbers) > (number &rest more-numbers) >= (number &rest more-numbers) abs (number) adjoin (item list &key key (test #'eql) (test-not nil notp)) alpha-char-p (char) alphanumericp (char) append (&rest lists) apply (function arg &rest args) aref (array &rest subscripts) ash (integer count) assoc (item alist &key key test test-not) atom (object) both-case-p (char) boundp (variable) butlast (list &optional (n 1)) caaaar (list) caaadr (list) caaar (list) caadar (list) caaddr (list) caadr (list) caar (list) cadaar (list) cadadr (list) cadar (list) caddar (list) cadddr (list) caddr (list) cadr (list) car (list) cdaaar (list) cdaadr (list) cdaar (list) cdadar (list) cdaddr (list) cdadr (list) cdar (list) cddaar (list) cddadr (list) cddar (list) cdddar (list) cddddr (list) cdddr (list) cddr (list) cdr (list) ceiling (number &optional (divisor 1)) cerror (continue-string datum &rest arguments) char (string index) char-code (char) char-downcase (char) char-equal (character &rest more-characters) char-int (char) char-name (char) char-upcase (char) char= (character &rest more-characters) character (object) characterp (object) close (stream &key abort) code-char (code) complexp (object) concatenate (output-type-spec &rest sequences) cons (se1 se2) consp (object) copy-alist (alist) copy-list (list) copy-seq (sequence) copy-symbol (symbol &optional (copy-props nil)) copy-tree (object) count (item sequence &key from-end (test #'eql) (test-not nil) (start 0) end key) count-if (test sequence &key from-end (start 0) end key) count-if-not (test sequence &key from-end (start 0) end key) digit-char (weight &optional (radix 10)) digit-char-p (char &optional (radix 10)) eighth (list) elt (sequence index) endp (object) eq (obj1 obj2) eql (obj1 obj2) equal (x y) equalp (x y) error (datum &rest arguments) eval (original-exp) evenp (number) export (symbols &optional (package *package*)) expt (base power) fboundp (name) fceiling (number &optional (divisor 1)) fdefinition (function-name) ffloor (number &optional (divisor 1)) fifth (list) find (item sequence &key from-end (test #'eql) test-not (start 0) end key) find-if (test sequence &key from-end (start 0) end key) find-if-not (test sequence &key from-end (start 0) end key) find-package (name) find-symbol (name &optional package) first (list) floatp (object) floor (number &optional (divisor 1)) fmakunbound (name) format (destination control-string &rest format-arguments) fourth (list) funcall (function &rest arguments) function (object) functionp (object) gensym (&optional (thing g)) gentemp (&optional (prefix t) (package *package*)) get (symbol indicator &optional (default nil)) get-dispatch-macro-character (disp-char sub-char &optional (rt *readtable*)) get-macro-character (char &optional (rt *readtable*)) get-output-stream-string (stream) getf (place indicator &optional (default nil)) gethash (key hash-table &optional default) graphic-char-p (char) hash-table-count (hash-table) hash-table-p (object) hash-table-rehash-size (structure) hash-table-rehash-threshold (object) hash-table-test (structure) identity (thing) input-stream-p (stream) integerp (object) interactive-stream-p (stream) intern (name &optional package) intersection (list1 list2 &key key (test #'eql) (test-not nil)) keywordp (object) last (list &optional (n 1)) length (sequence) list (&rest args) list* (arg &rest others) list-length (list) listp (object) load (filename) lower-case-p (char) make-array (dimensions &key (element-type t) (initial-element nil) (initial-contents nil) adjustable fill-pointer displaced-to displaced-index-offset) make-dispatch-macro-character (char &optional (non-terminating-p nil) (rt *readtable*)) make-hash-table (&key (test 'eql) (size 65) (rehash-size 1.5) (rehash-threshold 1.0) (weak-p nil)) make-list (size &key initial-element) make-package (name &key (use *default-package-use-list*) nicknames (internal-symbols 10) (external-symbols 10)) make-sequence (type length &key (initial-element nil iep)) make-string (count &key element-type initial-element) make-string-output-stream (&key (element-type 'character)) make-symbol (string) makunbound (variable) mapc (function list &rest more-lists) mapcan (function list &rest more-lists) mapcar (function list &rest more-lists) mapcon (function list &rest more-lists) maphash (map-function hash-table) mapl (function list &rest more-lists) maplist (function list &rest more-lists) max (number &rest more-numbers) member (item list &key key (test #'eql) (test-not nil)) member-if (test list &key key) member-if-not (test list &key key) min (number &rest more-numbers) minusp (number) mod (number divisor) name-char (name) nconc (&rest lists) nintersection (list1 list2 &key key (test #'eql) (test-not nil)) ninth (list) nreconc (x y) nreverse (sequence) nset-difference (list1 list2 &key key (test #'eql) (test-not nil)) nset-exclusive-or (list1 list2 &key key (test #'eql) (test-not #'eql)) nth (n list) nthcdr (n list) null (object) numberp (object) nunion (list1 list2 &key key (test #'eql) (test-not nil)) oddp (number) open-stream-p (stream) output-stream-p (stream) package-name (x) package-nicknames (x) package-shadowing-symbols (x) package-use-list (x) package-used-by-list (x) packagep (object) plusp (number) position (item sequence &key from-end (test #'eql) test-not (start 0) end key) position-if (test sequence &key from-end (start 0) key end) position-if-not (test sequence &key from-end (start 0) key end) prin1 (object &optional stream) prin1-to-string (object) princ (object &optional stream) princ-to-string (object) print (object &optional stream) print-object (mc stream) progn (&rest stuff) rassoc (item alist &key key test test-not) rationalp (object) read (&optional (stream *standard-input*) (eof-errorp t) (eof-value nil) (recursivep nil)) read-char (&optional (stream *standard-input*) (eof-errorp t) eof-value recursive-p) read-delimited-list (endchar &optional (input-stream *standard-input*) recursive-p) read-preserving-whitespace (&optional (stream *standard-input*) (eof-errorp t) (eof-value nil) (recursivep nil)) readtable-case (structure) readtablep (object) realp (object) reduce (function sequence &key key from-end (start 0) end (initial-value nil ivp)) rem (number divisor) remhash (key hash-table) remove (item sequence &key from-end (test #'eql) test-not (start 0) end count key) remove-if (predicate sequence &key from-end (start 0) end count key) remove-if-not (predicate sequence &key from-end (start 0) end count key) remprop (symbol indicator) rename-package (package name &optional (nicknames nil)) replace (target-sequence source-sequence &key (start1 0) end1 (start2 0) end2) rest (list) revappend (x y) reverse (sequence) round (number &optional (divisor 1)) row-major-aref (array index) rplaca (x y) rplacd (x y) schar (string index) second (list) set (variable new-value) set-difference (list1 list2 &key key (test #'eql) (test-not nil)) set-dispatch-macro-character (disp-char sub-char function &optional (rt *readtable*)) set-exclusive-or (list1 list2 &key key (test #'eql) (test-not nil)) set-macro-character (char function &optional (non-terminatingp nil) (rt *readtable*)) setq (&rest stuff) seventh (list) sixth (list) special-operator-p (symbol) standard-char-p (char) stream-element-type (stream) streamp (stream) string (x) string-downcase (string &key (start 0) end) string-equal (string1 string2 &key (start1 0) end1 (start2 0) end2) string-upcase (string &key (start 0) end) string= (string1 string2 &key (start1 0) end1 (start2 0) end2) stringp (object) subseq (sequence start &optional end) subsetp (list1 list2 &key key (test #'eql) (test-not nil)) sxhash (s-expr) symbol-function (variable) symbol-name (variable) symbol-package (variable) symbol-plist (variable) symbol-value (variable) symbolp (object) tailp (object list) tenth (list) terpri (&optional (stream *standard-output*)) third (list) truncate (number &optional (divisor 1)) type-of (object) union (list1 list2 &key key (test #'eql) (test-not nil)) unread-char (character &optional (stream *standard-input*)) upper-case-p (char) use-package (packages-to-use &optional (package *package*)) values (&rest values) values-list (list) vector (&rest objects) vectorp (object) warn (datum &rest arguments) write-char (character &optional (stream *standard-output*)) write-string (string &optional (stream *standard-output*) &key (start 0) end) zerop (number) Other operations supported by the compiler but not by the runtime system: and (&rest forms) macroexpands into if block (block-name &rest body-forms) cond (&rest clauses) macroexpands into if decf defmacro defstruct do macroexpands into let/block/tagbody do* macroexpands into let*/block/tagbody dolist macroexpands into let/block/tagbody dotimes macroexpands into let/block/tagbody eval-when (situations &rest forms) flet (function-bindings &rest body-forms) go (tag) if (test eval-if-true eval-if-false) labels (function-bindings &rest body-forms) let (bindings &rest body-forms) let* (bindings &rest body-forms) multiple-value-bind (varlist value-form &body body) multiple-value-call (&rest stuff) multiple-value-list macroexpands into multiple-value-call multiple-value-prog1 (&rest stuff) multiple-value-setq (varlist value-form) not (thing) nth-value (&rest args) or (&rest forms) macroexpands into if prog macroexpands into let/block/tagbody prog* macroexpands into let*/block/tagbody prog1 macroexpands into let prog2 macroexpands into let return (values) return-from (tag values) svref (simple-vector index) tagbody (&rest stuff) the (&rest stuff) throw (&rest stuff) typep (object type &optional environment) unless macroexpands into if unwind-protect (&rest stuff) when macroexpands into if These are mostly special forms and macros that require ad-hoc evaluation and/or extra lexical analysis. They could be implemented as part of the hand-written evaluator, but that would involve some duplication of code; better to wait until the compiler lexical analyzer can be ported, and use that (if not the full compiler).