[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Maclisp interpreter/compiler nearly identical w/ (declare (special t)) on??

    Date: Fri, 14 Sep 84 09:40:12 pdt
    From: fateman%ucbdali at Berkeley (Richard Fateman)

    ... If we look at Maclisp with (declare (special t)), is it not the
    case that (nearly) identical semantics are used for the interpreter
    and compiler, given CORRECT programs? ...

I'm afraid I take offense at this. Maclisp interpreted semantics are *very*
different than compiled semantics. Common Lisp is not completely there, but
puts its heart in the right place by at least acknowledging the problem.
Also, it has corrected at least some of the Maclisp problems. Here are a
few Maclisp interpreter/compiler differences that come to mind at the
moment to jar your memory; I'm sure this is not an exhaustive list:

* If you make a "correct" number declaration for X and Y, you may 
  risk that (PLUS X Y) which would run correctly interpreted will 
  be open coded as if (+ X Y) had been written. In PLUS case interpreted,
  however, overflow becomes a bignum while in the + case interpreted, 
  the result is undefined (wraparound or some such thing occurs undetected).

  I didn't see any obvious place in the CL manual where it says if 
  this is fixed.

* There are a bunch of control variables such as CAR, CDR, and EVAL 
  which are (necessarily) ignored by compiled code. They radically 
  affect the semantics of interpreted code by allowing the user to 
  extend the notion of what was "defined" without providing a mechanism 
  for informing the compiler of such extensions.

  There are no such variables in CL.

* The status of macros in the car of a form was not uniformly treated in
  interpreted and compiled form. In the form ((FOO BAR) ...), if FOO was a
  macro, the interpreter would cause the result of expanding (FOO BAR) to be
  evaluated before being applied, while the compiler would compile an apply
  to the result of expanding (FOO BAR) directly rather than compiling a call
  to the result of evaluating the expansion. Early Maclisp actually attempted
  to define this as reasonable behavior; I think it was eventually flushed
  and compiler warnings were issued in some cases saying to use FUNCALL.

  I could not determine where or whether the CL manual takes a stand on this
  issue.  It would be nice if it simply declared that forms other than
  ((LAMBDA ...) ...) whose cars are lists are explicitly undefined.

* Compiled macros, if redefined, have no effect on running programs.

  This is still true in CL. If interpreted CL definitions were ENCLOSE'd 
  (a la Scheme) at definition time, this could be fixed.

* Constant quoted expressions which were EQUAL will have been made EQ by the
  FASLOAD process. This fact has been heavily depended upon by Macsyma on 
  the pdp10 to avoid wasting huge amounts of space needlessly, and must be
  understood by all programs to avoid accidentally side-effecting constants
  which ought by right have no relation to each other.

  I guess this one is under active discussion.

* Function definitions for interpreted and compiled code differ.
  (FUNCALL (GET 'X 'EXPR)) runs the same interpreted and compiled, but
  (DEFPROP X (LAMBDA () 3) EXPR) runs differently compiled than interpreted.

  There is definitely an advance in CL by having simply a function cell and
  eliminating this nonsense about having 18 different places to store 
  functions. There's some question in my mind about whether macros belong 
  in the function cell, but this is at least treated uniformly from 
  interpreter to compiler.

* EVAL-WHEN does different things in an EVAL context than a COMPILE context.

  I can't imagine wanting to fix this given the current state of the world,
  although if, as I mentioned above, CL had an analog to Scheme ENCLOSE which
  was used at appropriate times in both interpreter and compiler, I could
  imagine changing the set of keys that EVAL-WHEN used (to not be EVAL and
  COMPILE, but instead something more abstract) so that they were uniformly
  treated in interpreted and compiled code.

* EVALFRAME works completely differently in compiled and interpreted contexts
  since call the compiler may optimize out intermediate call frames. Hence
  (LET ((THIS-FRAME (EVALFRAME ...))) ...) works fine compiled but must be 
  treated very carefully interpreted.

  This issue isn't addressed by CL, hence is sort of fixed.

* Number EQness of small numbers may not be preserved in compiled code, but
  is guaranteed in many cases in interpreted code. Technically, it was never
  guaranteed that this was so, but in practice, I (and probably others) wrote
  code that relied on the fact and achieved useful ends.

  The introduction of EQL in CL makes a positive stride in the right direction.
  I don't know if I consider this problem completely resolved.