Newsgroups: alt.lang.design,comp.lang.c++,comp.lang.lisp
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!news.mathworks.com!uunet!in1.uu.net!pipex!uknet!festival!edcogsci!jeff
From: jeff@aiai.ed.ac.uk (Jeff Dalton)
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was  Re: Reference Counting))
Message-ID: <D43LnL.Au3@cogsci.ed.ac.uk>
Sender: usenet@cogsci.ed.ac.uk (C News Software)
Nntp-Posting-Host: bute-alter.aiai.ed.ac.uk
Organization: AIAI, University of Edinburgh, Scotland
References: <D3J8FB.11v@rheged.dircon.co.uk> <D3n2wK.4r7@cogsci.ed.ac.uk> <D409vC.7r3@rheged.dircon.co.uk>
Date: Thu, 16 Feb 1995 14:59:44 GMT
Lines: 233
Xref: glinda.oz.cs.cmu.edu comp.lang.c++:113235 comp.lang.lisp:16832

In article <D409vC.7r3@rheged.dircon.co.uk> simon@rheged.dircon.co.uk (Simon Brooke) writes:
>In article <D3n2wK.4r7@cogsci.ed.ac.uk>,
>Jeff Dalton <jeff@aiai.ed.ac.uk> wrote:
>>In article <D3J8FB.11v@rheged.dircon.co.uk> simon@rheged.dircon.co.uk
>>(Simon Brooke) writes:
>
>>>Common LISP, as a standard language, does have and does have to have
>>>an interpreter. 
>>
>>No, that's just not true.
>>
>>>How individual implementations implement that
>>>interpreter is up to the authors; if they choose to implement the
>>>interpreter by making a call to the compiler and then executing the
>>>result, that's up to them, but it doesn't make the process any the
>>>less one of interpreting language.
>>
>>Compilers interpret langauge.  Very true.  And that makes them
>>interpreters in a sense (all things that interpret are interpreters).
>>But the word "interpreter" has a technical meaning as well in which
>>the word refers to a way of implementing a programming language.
>>Compilers are not interpreters in that sense and Common Lisp
>>implementations do not have to have interpreters in that sense.
>>
>>In short, your argument commits the fallacy of equivocation
>>(on the word "interpreter").
>
>OK, Jeff, I'll take up this fight, although I know you'll beat me on
>both rhetorical or technical skill. LisP newbies please ignore my
>arguments, they're pretty much bound to be wrong.
>
>Your claim is that there is something in computer science called an
>'interpreter', special technical meaning for a particular sort of
>tool, and that a LisP which implements EVAL by precompiling does not
>have one, but a LisP that implements EVAL by applying the s-expression
>which is the value of the function cell of the car of the s-expression
>just read does have one.

Well, sort of.

As I'm sure you know, there is a distinction between interpreters
and compilers as ways to implement programming languages.  GCC is
a compiler, for instance, as is the "byte compiler" for GNU Emacs
Lisp.  However, the byte codes produced by the Emacs Lisp compiler
are interpreted.

I'm not sure what you have in mind by contrasting "precompiling"
with "applying the s-expression".  Lisp interpreters don't just
apply s-exprs, and when they do, apply has to interpret the s-expr.
Just think of, say, the eval/apply definitions in the Lisp 1.5
book or in Abelson and Sussman's SICP.

There are, of course, interpreters that aren't "pure" interpreters.
They may do some analysis (more than just converting to tokens) in
order to get something that's more efficiently interpreted, for
instance.  So there are probably some cases where it's not clear
whether we have an interpreter or a compiler.  But there are other
cases where it is clear, as in your Pascal and Basic descriptions
below.  And in the Lisp world, there's an interpreter / compiler
distinction that aligns fairly well with the interpreter / compiler
distinction found elsewhere.

There may also be compilers that are part way towards being
interpreters.  But incremental compilers (which is all a
Common Lisp needs if it wants to get by without an interpreter)
are not interpreters.  They're incremental compilers.

>And my answer to you is 'no, that's just not true', to quote a learned
>sage. Let us divide non-LisP like languages into two broad categories
>for the time being.
>
>There are languages such as (classic implementations of) Pascal, in
>which the source text is scanned and compiled from a file on disk,
>never being loaded in it's entirety into main memory. It is compiled
>into the machine code of some processor, possibly virtual (as in P
>Code), and the compiled code is later run. It is clear what is meant
>by compiled in this case, and the language is clearly compiled.
>
>There are languages such as (primitive implementations of) BASIC, in
>which the source text is loaded into a continuous vector of memory
>(more or less tokenised), and then a process scans the vector of text
>interpreting each command as it is encountered. It is clear what is
>meant by interpreted in this case, and the language is clearly
>interpreted.

Here you're describing particular implementations, and of course
many other kinds of implementations are possible.  For instance,
Dartmouth Basic has always been implemented (at Dartmouth, anyway)
as a compiler.  True Basic, I believe, compiled to byte codes and
then interpreted the byte codes.  Some Basic interpreters interpret
tokens rather than the sequence-of-characters source text.

So it's implementations rather than languages that are divided
into the two broad categories.

>I have, in my collection, largely as a curiosity, a C language library
>package called C Lisp, written by a chap called Frederick Drasch. This
>works exactly like a primitive BASIC interpreter. It loads LisP source
>text into a continuous vector of memory, and scans along it
>interpreting it token by token as it goes. The weird thing is, it
>works!
>
>It is, however, a total aberration, -- It's LisP, Jeff, but not as we
>know it <cue stirring music>. Almost any other LisP compiles source
>code into an internal form as it is read -- i.e. into s-expressions,
>linked lists of pointers, with symbols cached in hash arrays or other
>curiosities. The source text of the LisP program does not exist
>anywhere in memory. For example, although probably the two most common
>characters in any LisP program are LPAR and RPAR respectively, a
>memory dump of a running LisP program is unlikely to reveal more than
>one instance of either.

It's a bit much to call what READ does compiling.  It's at most
a parser, and it's actually fairly close to just being a scanner.
(If you think of what's usually part of parsing, much of the parsing
for Lisp is actually performed by the macros.)

Anyway, almost all Lisp interpreters and compilers use READ as a
first pass.  That does not stop them from _being_ interpreters and
compilers.

>In an 'interpreted' LisP, the s-expressions are then explored by a
>depth first tree walking algorithm. That's nothing like what an
>'interpreter', in the sense of a BASIC interpreter, does. It's very
>much like what a P Code virtual processor does; except that the
>instruction set of the Lisp virtual processor is user-extensible.

The Pascal-to-P-code compiler is rather like compilers that compile
to byte codes.  They're compilers, and the byte codes are then
interpreted (or perhaps translated into actual machine code for
some machine).

This is a different approach from that of an interpreter that first
converts the sourse to tokens; and Lisp interpreters don't do much
more than that.

In any case, what you're saying here is rather odd.  You seem to
be arguing that ordinary, every day, interpret-the-S-exprs Lisp
interpreters are really compilers.  But what you need to show is
that various things I call compilers are really interpreters.

Note that it's not enough to show that various possible Lisp
implementation techniques are intermediate between some supposedly
more or less pure forms of interpreters and compilers.  What you
have to show is that it's not possible to implement Common Lisp
without an interpreter.  That is, you have to show not that some
possible implementations are sort of like interprters but that
all are.

>So, talking outside the LisP community, interpreted LisP looks very
>much like compiled P Code. 

No it doesn't.  It looks, at most, like a parse tree.  And it's not
really even that, because much of the parsing is still to be done.
Now, if the Lisp implementation converted the original source to
S-exprs in some simple canonical form (as some Schemes have more
or less done), then you'd have something more like a compiler.
It would be like a compiler that went as far as one of the 
intermediate instruction-like forms that compiler sometimes
use (e.g. "triples") and then stopped.

>  Now suppose we compile the LisP, and
>suppose we compile it using abstract machine technology. You may argue
>that this is just like P Code, but in fact it's not, because where P
>Code would include an absolute jump instruction, the LisP abstract
>machine will compile to an indirected jump via the value of a symbol.

So when you make the comparison, you're allowed to say "looks very
much like"; but when I do it, I have to say "just like".  No wonder
you think your comparisons are true and that mine are false.

>Say again: the abstract machine interpreter will scan linearly along
>the vector of abstract machine instructions (like tokenised BASIC)
>until it comes to a jump indirected via a symbol. This is very like a
>command in a BASIC program to CHAIN another program, 

No, it's not very like it.  To be much like it, the Lisp jump
would have to cause the implementation to process a separate
source file, not just go indirect through a table.

>         and the
>'compiled' LisP now looks much more like interpreted BASIC than it
>does like compiled PASCAL (although of course the P Code virtual
>processor and the BASIC interpreter look very much like one another).

You seem to be arguing that using a transfer vector brings you
closer to interpreted Basic than to compiled Pascal.  But I
hesitate to suggest that you actually believe that.

>My conclusion, then: there is no clear understanding in computer
>science of what the difference between a compiler and an interpreter
>is, or if there is, it does not fit a LisP interpreter. 

I think there is a fairly clear understanding.  Some things are
clearly interpreters and some things are clearly compilers.
Other approaches are somewhere in between and have elements of
both.

Lisp interpreters are not very different from many non-Lisp
interpreters, and Lisp compilers are not very different from
non-Lisp compilers.  I don't think this is at all controversial.
Has anyone ever gone to the Lisp 1.5 book or to SICP or to other
places that discuss Lisp interpreters and compilers and said
"there's really no such distinction".  On the contrary: people
who read these books understand rather well what is meant and
why the things described as interpreters are interpreters and
those described as compilers are compilers.

>A LisP interpreter is more different from a BASIC interpreter than it
>is from a LisP compiler. 

If it is, then the differences that make it so aren't differences
that distinguish interpreters from compilers.  There are a number
of ways in which a Lisp interpreter is closer to a Lisp compiler
than to a Basic interpreter.  For one, they both implement Lisp
while the Basic interpreter implements Basic.

> To argue that something which interprets
>s-expressions is not an interpreter because it does not work in the
>way that things called by computer science 'interpreters' work is
>simply to say that all LisPs (with the exception of the good Mr
>Drasch's C Lisp) are compiled. Do you want to say that? Or shall we
>invent a new word?

What is your argument that a Lisp compiler, say the Franz Lisp
compiler (Liszt) is really an interpreter?  Only that it can be
said to interpret s-exprs in some sense of "interpret".  But it
interprets them in the way compilers interpret things: by translating
them into object code.  The Franz interpreter, on the other hand,
interprets s-exprs in the way interpreters do: it performs the
required actions itself.

-- jeff
