From: Jeff Dalton
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was Re: Reference Counting))
Date: 
Message-ID: <D2x55L.8Ht@cogsci.ed.ac.uk>
In article <·················@cfdevx1.lehman.com> ···@lehman.com (Rick Busdiecker) writes:
>In article <··········@news.panix.com> Viktor Yurkovsky <········@panix.com> writes:
>
>   I wrote:
>   >  Syntax of the language matters very little.
>   >  ===========================================
>   > 
>   ······@netcom.com (Henry Baker) wrote:
>   > Agreed, unless the language is Lisp.  In that case, you can use the full
>   > power of macros to write most of the code for you in Lisp.  In this case,
>   > the simple syntax matters a lot.
>
>   The interesting point here is that many people have a misconception about
>   what an interpreter is really for.
>
>The point that Henry was making wrt macros and syntax is unrelated to
>interpreters.
>
>I think that there is a common misconceptions that Lisp is an
>``interpreted language''.  In fact, there is nothing to prevent anyone
>from building either a Lisp or a C++ in any of these configurations:
> 1. Compiler and interpreter.
> 2. Compiler with no interpreter
> 3. Interpreter with no compiler
>
>The fact that most Lisp implementations are of type 1 and most C/C++
>implementations are of type 2 does not reflect anything fundamental
>about the languages themselves, but rather about the decisions made by
>people who chose to build implementations of the languages.

Since Lisp interpreters are usually fairly easy to write, that
may be one reason why Lisps tend to include interpreters (even
if they have a compiler as well) while Cs and C++s don't.
However, Common Lisp interpreters tend to me more complex than
those of simpler Lisps, which may have had an effect on
implementation techniques (e.g. so the interpreter and compiler
can share more code).

In any case, I think your point is a very important one, and not only
when it comes to macros.  Many of the things people think of as properties
of langauges are actually due in large part to implementation traditions
instead.  C programmers often (usually?) know the kind of code they'll get
from various constructs, and they know this even though the language
definition allows things to work very differently.

-- jd

From: Wolfgang Goerigk
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was Re: Reference Counting))
Date: 
Message-ID: <3gftki$26f@karlo.informatik.uni-kiel.de>
In <··········@cogsci.ed.ac.uk> ····@aiai.ed.ac.uk (Jeff Dalton) writes:

   > In article <·················@cfdevx1.lehman.com> ···@lehman.com (Rick Busdiecker) writes:
   > >In article <··········@news.panix.com> Viktor Yurkovsky <········@panix.com> writes:
   > >
   > >   I wrote:
   > >   >  Syntax of the language matters very little.
   > >   >  ===========================================
   > >   > 
   > >   ······@netcom.com (Henry Baker) wrote:
   > >   > Agreed, unless the language is Lisp.  In that case, you can use the full
   > >   > power of macros to write most of the code for you in Lisp.  In this case,
   > >   > the simple syntax matters a lot.
   > >
   > >   The interesting point here is that many people have a misconception about
   > >   what an interpreter is really for.
   > >
   > >The point that Henry was making wrt macros and syntax is unrelated to
   > >interpreters.
   > >
   > >I think that there is a common misconceptions that Lisp is an
   > >``interpreted language''.  In fact, there is nothing to prevent anyone
   > >from building either a Lisp or a C++ in any of these configurations:
   > > 1. Compiler and interpreter.
   > > 2. Compiler with no interpreter
   > > 3. Interpreter with no compiler
   > >
   > >The fact that most Lisp implementations are of type 1 and most C/C++
   > >implementations are of type 2 does not reflect anything fundamental
   > >about the languages themselves, but rather about the decisions made by
   > >people who chose to build implementations of the languages.

   > Since Lisp interpreters are usually fairly easy to write, that
   > may be one reason why Lisps tend to include interpreters (even
   > if they have a compiler as well) while Cs and C++s don't.
   > However, Common Lisp interpreters tend to me more complex than
   > those of simpler Lisps, which may have had an effect on
   > implementation techniques (e.g. so the interpreter and compiler
   > can share more code).

   > In any case, I think your point is a very important one, and not only
   > when it comes to macros.  Many of the things people think of as properties
   > of langauges are actually due in large part to implementation traditions
   > instead.  C programmers often (usually?) know the kind of code they'll get
   > from various constructs, and they know this even though the language
   > definition allows things to work very differently.

   > -- jd

Of course, the reflective nature (e.g. EVAL) of at least Common Lisp
is due to implementation tradition. However, it is part of the
language definition and of course is a fundamental language property
distinguishing Lisp from other languages. The ongoing discussion tends
to hide the difference between interpretation used to implement a
language and the __reflective__ nature of functions like EVAL beeing
part of the programs itself.

EVAL is not just an interpreter in the above sense, although it is
fairly easy to write one using EVAL, e.g. 

     (print (eval (read)))

with some prompting stuff. As an exercise we could try to eliminate
EVAL using some other reflective features of Lisp. LOAD has been
mentioned already but there are more, and of course, COMPILE is one,
too.

However, it is not possible to write an EVAL function like that of
Common Lisp to be part of the user program in C or C++, interpreting
or even changing its own code, because those languages are not
reflective. As a matter of fact, this is not only due to
implementation tradition using compilers.

  -- Wolfgang

-- 
 Dr. Wolfgang Goerigk             ( ··@informatik.uni-kiel.d400.de )
 University of Kiel (CAU)                    phone: ++49-431-5604-24
 D-24105 Kiel, Germany                       fax  :  ++49-431-566143
From: Simon Brooke
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was  Re: Reference Counting))
Date: 
Message-ID: <D3J8FB.11v@rheged.dircon.co.uk>
In article <·········@cogsci.ed.ac.uk>, Jeff Dalton <····@aiai.ed.ac.uk> wrote:
>
>*Lisp* does not have to include eval.  Neither EuLisp not Scheme
>have an eval, for instance.  (Eval is not part of those language
>definitions.)  But even in Lisps that do include eval (such as
>Common Lisp), it's not necessary to have an interpreter.  Everything
>can be done by a compiler.  My point above was that *languages* in
>the Lisp family do not have to be interpreted, even though it's
>common for *implementations* to be or to include interpreters.

Jeff, you've laboured this point, and in labouring it have convinced
me that you are wrong (normally, I tend to believe what you say :-}).

Common LISP, as a standard language, does have and does have to have
an interpreter. 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.

And, indeed, as your correspondent has pointed out, one feature that
all LisP variants share is that it is trivial to build, in LisP, an
interpreter for S expressions (it's not trivial to build one with
exactly the same semantics as the compiler, but that's a different
argument). So if eval isn't there, you can quickly build enough of it
to suit most purposes.

If you perversely hacked enough out of LisP (any LisP) to make it
*hard* to write an interpreter for S expressions, it would be pretty
much useless for any other purpose, too.

By contrast, although it's fairly easy to write interpreters for
simple languages in AlgoL family languages, it isn't easy, for example
to write in C an interpreter for C source code.

-- 
------- ·····@rheged.dircon.co.uk (Simon Brooke)
    .::;===r==\   
   /  /___||___\____         
  //==\-  ||-  |  /__\(      MS Windows IS an operating environment.
 //____\__||___|_//  \|:     C++ IS an object oriented programming language. 
   \__/ ~~~~~~~~~ \__/       Citroen 2cv6 IS a four door family saloon.
From: Scott McLoughlin
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was
Date: 
Message-ID: <DF95Zc2w165w@sytex.com>
·····@rheged.dircon.co.uk (Simon Brooke) writes:

> If you perversely hacked enough out of LisP (any LisP) to make it
> *hard* to write an interpreter for S expressions, it would be pretty
> much useless for any other purpose, too.
> 

Howdy,
        Really? Would compiling away the symbolic names
of global bindings in, say a straight Lisp->ASM compiler,
be considered a "perverse hack". 
        It might still be easy to build an interpreter,
but it would not be an interpreter that could, in the
general case, obtain the values of compiled global
bindings, and thus less useful than the typical EVAL.
        Just a question.

=============================================
Scott McLoughlin
Conscious Computing
=============================================
From: Jeff Dalton
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was  Re: Reference Counting))
Date: 
Message-ID: <D3n2wK.4r7@cogsci.ed.ac.uk>
In article <··········@rheged.dircon.co.uk> ·····@rheged.dircon.co.uk (Simon Brooke) writes:
>In article <·········@cogsci.ed.ac.uk>, Jeff Dalton <····@aiai.ed.ac.uk> wrote:
>>
>>*Lisp* does not have to include eval.  Neither EuLisp not Scheme
>>have an eval, for instance.  (Eval is not part of those language
>>definitions.)  But even in Lisps that do include eval (such as
>>Common Lisp), it's not necessary to have an interpreter.  Everything
>>can be done by a compiler.  My point above was that *languages* in
>>the Lisp family do not have to be interpreted, even though it's
>>common for *implementations* to be or to include interpreters.
>
>Jeff, you've laboured this point, and in labouring it have convinced
>me that you are wrong (normally, I tend to believe what you say :-}).
>
>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").

>And, indeed, as your correspondent has pointed out, one feature that
>all LisP variants share is that it is trivial to build, in LisP, an
>interpreter for S expressions (it's not trivial to build one with
>exactly the same semantics as the compiler, but that's a different
>argument). So if eval isn't there, you can quickly build enough of it
>to suit most purposes.

I don't know that it's *trivial* to write an interpreter for Common
Lisp.  But Common Lisp gives you a fair amout of help.  For instance:

  * Symbol-value and symbol-function let you treat symbols as the
    names of global/special variables and global functions respectively.
    Without something like that, your interpreter couldn't access
    the variables that are used by ordinary code and it couldn't
    call the built-in functions without a big case statement (or
    equivalent).

  * Macroexpand-1 lets you expand macros.  Without something like
    that you'd have to write your own implementation of all the
    built-in macros.  And even with macroexpand-1, it's difficult
    to write a portable CL interpreter.  I'm not even sure it's
    possible.  (Look at the code-walker in PCL to see some of
    the problems.  Note too that that code-walker is not exactly
    *trivial*.)

Now, some Lisps (such as EuLisp) do not define equivalents of
symbol-value or macroexpand-1.

>If you perversely hacked enough out of LisP (any LisP) to make it
>*hard* to write an interpreter for S expressions, it would be pretty
>much useless for any other purpose, too.

That's just false.  Of course, it will be possible to write *an*
interpreter for some language written as S-exprs.  If you took out
so much that *that* was hard, you might be right.  But it can be
difficult to write an interpreter for the Lisp you're using
(e.g. EuLisp) without any such dire consequences.

>By contrast, although it's fairly easy to write interpreters for
>simple languages in AlgoL family languages, it isn't easy, for example
>to write in C an interpreter for C source code.

That's true.  But the reasons it's easier for Lisp don't have all
that much to do with the sorts of eval-is-bad-for-your-compiled-code
arguments we've seen here.  Some of the most important reasons why
it's easier to write an interpreter for Lisp-family languages are 

  * Read provides the lexical-analyzer/scanner and a bit more.
  * The rest of the parsing task (e.g. to extract the variable
    names in a "let") is usually pretty trivial (though some
    things, such as handler-case and defstruct are harder).
  * Many constructs are defined by macros so that there's less
    that must be directly implemented.

-- jeff
From: Simon Brooke
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was  Re: Reference Counting))
Date: 
Message-ID: <D409vC.7r3@rheged.dircon.co.uk>
In article <··········@cogsci.ed.ac.uk>,
Jeff Dalton <····@aiai.ed.ac.uk> wrote:
>In article <··········@rheged.dircon.co.uk> ·····@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.

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.

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.

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.

So, talking outside the LisP community, interpreted LisP looks very
much like compiled P Code. 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.

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, 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).

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. A LisP
interpreter is more different from a BASIC interpreter than it is from
a LisP compiler. 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?

(discussion deleted)

>>...although it's fairly easy to write interpreters for
>>simple languages in AlgoL family languages, it isn't easy, for example
>>to write in C an interpreter for C source code.
>
>That's true.  But the reasons it's easier for Lisp don't have all
>that much to do with the sorts of eval-is-bad-for-your-compiled-code
>arguments we've seen here.  Some of the most important reasons why
>it's easier to write an interpreter for Lisp-family languages are 
>
>  * Read provides the lexical-analyzer/scanner and a bit more.
>  * The rest of the parsing task (e.g. to extract the variable
>    names in a "let") is usually pretty trivial (though some
>    things, such as handler-case and defstruct are harder).

Errhrrm. What I think you're saying is something I've long believed:
it's easy to interpret LisP because LisP has almost no syntax in any
conventional sense. That's why I deprecate this horrid modern Common
LISP stuff with keywords in lambda lists. Yech! Nasty!

:-} :-} :-} :-} :-} :-}:-} :-} :-} {-: {-: {-: {-: {-; {-; {-: {-: {-:
:-}                                                                {-:
:-}     guys, that's a deliberate windup, guys, I'm not trying     {-:
:-}     to refight old battles -- honest, guys... no, please...    )-:
:-}                                                                {-:
:-} :-} :-} :-} :-} :-}:-} :-} :-} {-: {-: {-: {-: {-; {-; {-: {-: {-:

Cheers, 

Simon

-- 
------- ·····@rheged.dircon.co.uk (Simon Brooke)

	The trouble with Simon is that he only opens his mouth to change feet.
					;; of me, by a 'friend'
From: Jeff Dalton
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was  Re: Reference Counting))
Date: 
Message-ID: <D43LnL.Au3@cogsci.ed.ac.uk>
In article <··········@rheged.dircon.co.uk> ·····@rheged.dircon.co.uk (Simon Brooke) writes:
>In article <··········@cogsci.ed.ac.uk>,
>Jeff Dalton <····@aiai.ed.ac.uk> wrote:
>>In article <··········@rheged.dircon.co.uk> ·····@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
From: Shriram Krishnamurthi
Subject: Re: Interpreters (Re: Comparing productivity: LisP against C++ (was Re: Reference Counting))
Date: 
Message-ID: <3i2ki8$jck@larry.rice.edu>
It seems like part of the confusion here is simply about what
interpreters and compilers look like.  Traditionally, people have been
programmed to think that a compiler is something that interacts thus:

% <compile> <filename>
...
% <run program>

whereas an interpreter does this:

> <expression>
<answer>
>

Of course, this simply isn't true.  At the "shell" level, the
"compiler" model looks a lot like the "interpreter" model.  The two
differences are that there is an "inside" and an "outside", and that
the compiler and compiled code are being called explicitly.  A program
that automated both these steps would then do the former, but look
like the latter.

This is what many Lisp and Scheme systems do.  (They actually confuse
us further by interpreting "simple" expressions and compiling more
complex ones, but that's beside the point.)

Anyway, these distinctions are somewhat artificial, and becoming
increasingly so.  One question is how low a level the source must be
translated to for the system to become a compiler; another is what you
call a system that does, say, partial evaluation on the way to
performing the compile.

'shriram