Path: utzoo!attcan!uunet!nih-csl!lhc!mimsy!midway!uwvax!sevenlayer.cs.wisc.edu!bothner From: bothner@sevenlayer.cs.wisc.edu (Per Bothner) Newsgroups: comp.lang.lisp Subject: Re: "fine commercial lisps" vs KCL vs other ways Message-ID: <11702@spool.cs.wisc.edu> Date: 12 Nov 90 21:09:11 GMT References: <1990Oct26.123828.7308@cs.nott.ac.uk> <20220001@hpfcdj.HP.COM> <1353@paradigm.com> Sender: news@spool.cs.wisc.edu Reply-To: bothner@sevenlayer.cs.wisc.edu (Per Bothner) Organization: University of Wisconsin--Madison Lines: 109 I've done some thinking about how to design a multi-language integrated language environment, including Lisp support. I've been working on a very high-level language, which supports first-class functions, run-time types, abstract sequence objects, and various other features. In other words, a language closer to the Lisp family than C++. In spite of that, most of the run-time system is written in C++, using a nihlib-like Object hierarchy. I also compile my language into C++ (though the compiler suffers from heavy bit-rot, since I'm waiting for some features to be added to g++). Some notes: My compilation model is based on persistent objects, or saving a workspace: A source "module" is loaded (parsed and evaluated), and then the resulting "workspace" is "dumped." I write it out as a C++ source file: The objects local to the workspace are emitted as static C++ data declarations. The methods/functions are compiled into source code. (I haven't worked on the compiler for a while. I understand g++-2.0 will emit run-time type descriptors. When available, I will remodel my "Class" class to use these descriptors. This will allow me to simplify the compiler, the run-time system, and the emitted C++ code.) All objects are pointers. There are no tag bits on the pointers. This allows compatibility with the C++ object model, which gives uniformity, and easier interaction with other tools. I pre-allocate "small fixints" (about the range -100..+1000) for speed and space, and these are guaranteed to be "eq". I use the DEC PRL package for infinite precision integer arithmetic. However, I don't use their signed-magnitude implementation of signed integers; instead I implemented a two's-complement package. This allows fixnums to be a sub-class of bignums, which is quite convenient: I can write a single implementation for (say) gcd, or I can choose to write two (one bignum, one fixnum) for speed. It also makes it easy to implementent the common lisp semantics for logical operators, shifts, etc. Symbols: Symbols are conventional. So far I just implement "keyword" symbols: No packages, "set", or property lisps, but adding these shuld be straight-forward. Since symbols must be interned, this causes a problem with separate compilation: I emit C++ data declarations for the various types of object; however each symbol with the same print-name must be globally unique. I solve this problem by emitting a symbol as an "extern" reference, and then using the linker to actually allocate the symbols. (Currently, I use a utility program prior to linking, but I would like to merge this code into ld.c at some point.) Functions: Functions are first-class, and closures are generated automatically. Functions can take variable number of parameters, defaults, and keyword parameters. I support full logic programming (logic variables, unification, backtracking, as well as constraints); however, the implementation is undergoing change. I'm experimenting with supporting shell-like features: A command is a function that takes one string input (stdin), some keywords (argv), and emits a string as output (stdout). This makes a nice model for a functional shell. A disk file is a string variable. An open input file is a character iterator. I've made some effort to make the syntax convenient and pleasant for interactive use. Garbage collecton. I have punted on garbage collection for now. In the long run, I'm hoping to use the implementation under development for Modula-3 by Eliot Moss and others, especially if it can be adopted for C++ (or a dialect thereof). Lisp: I have been thinking about putting a Lisp front-end on my system (and making the needed changes to the run-times). I've been toying with various Lisp dialects. One possibilty is to take gnu emacs, and re-write the definitions of Lisp_Object in terms of a C++ object hierarchy based on my existing system. I don't know yet how pervasive the changes would have to be, but since GNU code (including emacs) makes heavy use of accessor macros, I hope it would not be too bad. And the benefit would be an extensible, object-oriented emacs, in addition to providing a lot of useful library routines for my own language. Availability: Well, not really yet. There is very little documentation, the code is not robust (poor error recovery), I constantly re-write lange portions of it, there is lots of obsolete or no-longer-working code, and the compilers emit many warnings (mostly about const/non-const mismatches). The code has only been tested recently on a 68020 system running 4.3 bsd (Sony News), though in the past it ran on VAX ultrix. I believe it should port easily to any machine with gcc and g++. Berkeley a.out format would be a plus. There are some machine dependencies (including assembley code); the major ones are to support backtracking (which is not essential and will probably be replaced anyway). If there is interest, I could make a version available, to (brave) people who will to return improvements to me. By the way, I call my language "Q", for no good reason. Those who are interested could look at my dissertation: Efficiently Combining Logical Constraints with Functions, Stanford, 1988. It gives a flavor of an early version of Q, but the syntax has changed quite a bit, and I've had some second thoughts. -- --Per Bothner bothner@cs.wisc.edu Computer Sciences Dept, U. of Wisconsin-Madison