[comp.lang.lisp] "fine commercial lisps" vs KCL vs other ways

gjc@paradigm.com (11/02/90)

You know what would improve the state of the art of lisp implementations
a bit? If somebody wrote a LISP front-end to GCC. 

Really, it should be easier than the C++ stuff that was done with GCC.
Just handle the syntactic and lexical scoping issues (GCC already handles
most of the control construct issues that come up), and *dont* *worry*
about garbage collection.  Pass lisp arguments just like arguments
to C procedures. 

A definite must: Implement numeric declaration optimizations, fixnums
and floats, for expression evaluation, argument passing and return values.

Another must: Translate the names of arguments and local variable symbols
as little as possible, make sure compiled code can be debugged effectively
using GDB.

As far as the GC goes, don't sweat it. I have some minor (in terms of
understandability) extensions to the techniques used in SIOD that handle
the C object vs. C object ambiguity extremely well in practice and while
supporting the more modern lisp data structures.

The result: A production-quality lisp that lives up to the standards of
PDP-10 maclisp and more. A portable lisp with an understandable and
nearly universally supported compiler.

Maybe RMS will spend some of that MacArther money he won on a lisp
front end for GCC.

Or maybe somebody good enough will decide to stop screwing around
with stuff like KCL and go for the brass ring.

-gjc

barmar@think.com (Barry Margolin) (11/04/90)

In article <1353@paradigm.com> gjc@paradigm.com writes:
>You know what would improve the state of the art of lisp implementations
>a bit? If somebody wrote a LISP front-end to GCC. 

Well, it's not GCC-specific, but it seems like Chestnut's Lisp to C
translator does most of what you say.  It also does GC (and provides ways
to control it) and generic arithmetic when declarations aren't provided.

About the only problem is that they charge about $100,000 for it.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

gumby@Cygnus.COM (David Vinayak Wallace) (11/05/90)

   Date: 2 Nov 90 14:02:11 GMT
   From: gjc@paradigm.com

   You know what would improve the state of the art of lisp implementations
   a bit? If somebody wrote a LISP front-end to GCC. 

Jim Miller and I discussed this at the last Lisp conference, using GCC
as the back end for GAMBIT.  You're right in that it wouldn't be that
hard, though there is a little more work than you implied.

Looking over my notes: PVM (GAMBIT's representation) or s-codes are a
little higher-level than rtl in that rtl doesn't understand things
like closure variables (e.g. for CL it could compile flet only if you
didn't use upward funargs) and a little low-level (ie rtl can
represent loops, so that it can do various optimisations; PVM
represents loops with branch instructions).

To do a decent lisp with GCC would require the following
modifications:  The addition of an apply operator, since the calling
conventions differ, and a modification to procedure code generation so
that functions could have lisp entry points and optimised (post-arg-
checking) entry points for calling by C code and perhaps for
compiler-generated calls when the arity and type are known at compile
time.  The calling sequence would have to be fixed too, of course.

The real problem is GC.  You really want to tell the compiler about
register conventions it should share with the GC.  Unfortunately most
processors now have register usage conventions which are followed by C
compilers and which don't allow you to be able to depend on this.
Also, several new machines have register windows which make it
expensive for the GC to scan the machine state (register windows also
make it extremely unpleasant to use any sort of closure as a funarg).
GCC naturally uses register windows heavily on the machines which
implement them.

We're modifying GCC to allow certain kinds of conservative GC without
scanning the machine registers or stack, but this isn't cheap either.

If you removed the requirement that the compiler trivially intercall
with existing programs then this would become a lot easier.

Using GDB on generated code would be easy in any case, but you'd lose
all the benefits of having lisp in your debugging environment!
Perhaps the thing to do would be to link parts of GDB into your
runtime.

The reason the FSF isn't doing anything like this appear to be a two
(but I don't speak for them): rms' priorities lie in different areas,
and you can't really just write a compiler: you have to write a whole
lisp implementation.  Brian Fox wants to work on one; has anyone some
money for him?

bothner@sevenlayer.cs.wisc.edu (Per Bothner) (11/13/90)

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